StoreTest.php 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706
  1. <?php
  2. /**
  3. * A test script for the OpenIDStore classes.
  4. *
  5. * PHP versions 4 and 5
  6. *
  7. * LICENSE: See the COPYING file included in this distribution.
  8. *
  9. * @package OpenID
  10. * @author JanRain, Inc. <openid@janrain.com>
  11. * @copyright 2005-2008 Janrain, Inc.
  12. * @license http://www.apache.org/licenses/LICENSE-2.0 Apache
  13. */
  14. /**
  15. * Require classes and functions to run the Store tests.
  16. */
  17. require_once 'Auth/OpenID/Association.php';
  18. require_once 'Auth/OpenID/CryptUtil.php';
  19. require_once 'Auth/OpenID/Nonce.php';
  20. require_once 'Auth/OpenID.php';
  21. require_once 'PHPUnit.php';
  22. function _Auth_OpenID_mkdtemp()
  23. {
  24. if (strpos(PHP_OS, 'WIN') === 0) {
  25. $dir = $_ENV['TMP'];
  26. if (!isset($dir)) {
  27. $dir = 'C:\Windows\Temp';
  28. }
  29. } else {
  30. $dir = @$_ENV['TMPDIR'];
  31. if (!isset($dir)) {
  32. $dir = '/tmp';
  33. }
  34. }
  35. return Auth_OpenID_FileStore::_mkdtemp($dir);
  36. }
  37. /**
  38. * This is the host where the SQL stores' databases should be created
  39. * and destroyed.
  40. */
  41. global $_Auth_OpenID_db_test_host;
  42. $_Auth_OpenID_db_test_host = 'dbtest';
  43. /**
  44. * Generate a sufficently unique database name so many hosts can run
  45. * SQL store tests on the server at the same time and not step on each
  46. * other.
  47. */
  48. function _Auth_OpenID_getTmpDbName()
  49. {
  50. $hostname = php_uname('n');
  51. $hostname = str_replace('.', '_', $hostname);
  52. $hostname = str_replace('-', '_', $hostname);
  53. $hostname = strtolower($hostname);
  54. return sprintf("%s_%d_%s_openid_test",
  55. $hostname,
  56. getmypid(),
  57. strval(rand(1, time())));
  58. }
  59. /**
  60. * Superclass that has methods for testing OpenID stores. Subclass this to
  61. * test your own store implementation.
  62. *
  63. * @package OpenID
  64. */
  65. class Tests_Auth_OpenID_Store extends PHPUnit_TestCase {
  66. /**
  67. * Prepares for the SQL store tests.
  68. */
  69. function setUp()
  70. {
  71. $this->letters = Auth_OpenID_letters;
  72. $this->digits = Auth_OpenID_digits;
  73. $this->punct = Auth_OpenID_punct;
  74. $this->allowed_nonce = $this->letters . $this->digits;
  75. $this->allowed_handle = $this->letters . $this->digits . $this->punct;
  76. }
  77. /**
  78. * Generates an association with the specified parameters.
  79. */
  80. function genAssoc($now, $issued = 0, $lifetime = 600)
  81. {
  82. $sec = Auth_OpenID_CryptUtil::randomString(20);
  83. $hdl = Auth_OpenID_CryptUtil::randomString(128, $this->allowed_handle);
  84. return new Auth_OpenID_Association($hdl, $sec, $now + $issued,
  85. $lifetime, 'HMAC-SHA1');
  86. }
  87. /**
  88. * @access private
  89. */
  90. function _checkRetrieve(&$store, $url, $handle, $expected, $name = null)
  91. {
  92. $retrieved_assoc = $store->getAssociation($url, $handle);
  93. if ($expected === null) {
  94. $this->assertTrue($retrieved_assoc === null);
  95. } else {
  96. $this->assertTrue($expected->equal($retrieved_assoc), $name);
  97. }
  98. }
  99. function _checkRemove(&$store, $url, $handle, $expected, $name = null)
  100. {
  101. $present = $store->removeAssociation($url, $handle);
  102. $this->assertTrue((!$expected && !$present) ||
  103. ($expected && $present),
  104. $name);
  105. }
  106. /**
  107. * Make sure a given store has a minimum of API compliance. Call
  108. * this function with an empty store.
  109. *
  110. * Raises AssertionError if the store does not work as expected.
  111. *
  112. * OpenIDStore -> NoneType
  113. */
  114. function _testStore(&$store)
  115. {
  116. // Association functions
  117. $now = time();
  118. $server_url = 'http://www.myopenid.com/openid';
  119. $assoc = $this->genAssoc($now);
  120. $this->_checkRetrieve($store, $server_url, null, null,
  121. 'Make sure that a missing association returns no result');
  122. $store->storeAssociation($server_url, $assoc);
  123. $this->_checkRetrieve($store, $server_url, null, $assoc,
  124. 'Check that after storage, getting returns the same result');
  125. $this->_checkRetrieve($store, $server_url, null, $assoc,
  126. 'more than once');
  127. $store->storeAssociation($server_url, $assoc);
  128. $this->_checkRetrieve($store, $server_url, null, $assoc,
  129. 'Storing more than once has no ill effect');
  130. // Removing an association that does not exist returns not present
  131. $this->_checkRemove($store, $server_url, $assoc->handle . 'x', false,
  132. "Remove nonexistent association (1)");
  133. // Removing an association that does not exist returns not present
  134. $this->_checkRemove($store, $server_url . 'x', $assoc->handle, false,
  135. "Remove nonexistent association (2)");
  136. // Removing an association that is present returns present
  137. $this->_checkRemove($store, $server_url, $assoc->handle, true,
  138. "Remove existent association");
  139. // but not present on subsequent calls
  140. $this->_checkRemove($store, $server_url, $assoc->handle, false,
  141. "Remove nonexistent association after removal");
  142. // Put assoc back in the store
  143. $store->storeAssociation($server_url, $assoc);
  144. // More recent and expires after assoc
  145. $assoc2 = $this->genAssoc($now, $issued = 1);
  146. $store->storeAssociation($server_url, $assoc2);
  147. $this->_checkRetrieve($store, $server_url, null, $assoc2,
  148. 'After storing an association with a different handle, but the
  149. same $server_url, the handle with the later expiration is
  150. returned.');
  151. $this->_checkRetrieve($store, $server_url, $assoc->handle, $assoc,
  152. 'We can still retrieve the older association');
  153. $this->_checkRetrieve($store, $server_url, $assoc2->handle, $assoc2,
  154. 'Plus we can retrieve the association with the later expiration
  155. explicitly');
  156. $assoc3 = $this->genAssoc($now, $issued = 2, $lifetime = 100);
  157. $store->storeAssociation($server_url, $assoc3);
  158. // More recent issued time, so assoc3 is expected.
  159. $this->_checkRetrieve($store, $server_url, null, $assoc3, "(1)");
  160. $this->_checkRetrieve($store, $server_url, $assoc->handle,
  161. $assoc, "(2)");
  162. $this->_checkRetrieve($store, $server_url, $assoc2->handle,
  163. $assoc2, "(3)");
  164. $this->_checkRetrieve($store, $server_url, $assoc3->handle,
  165. $assoc3, "(4)");
  166. $this->_checkRemove($store, $server_url, $assoc2->handle, true, "(5)");
  167. $this->_checkRetrieve($store, $server_url, null, $assoc3, "(6)");
  168. $this->_checkRetrieve($store, $server_url, $assoc->handle,
  169. $assoc, "(7)");
  170. $this->_checkRetrieve($store, $server_url, $assoc2->handle,
  171. null, "(8)");
  172. $this->_checkRetrieve($store, $server_url, $assoc3->handle,
  173. $assoc3, "(9)");
  174. $this->_checkRemove($store, $server_url, $assoc2->handle,
  175. false, "(10)");
  176. $this->_checkRemove($store, $server_url, $assoc3->handle,
  177. true, "(11)");
  178. $this->_checkRetrieve($store, $server_url, null, $assoc, "(12)");
  179. $this->_checkRetrieve($store, $server_url, $assoc->handle,
  180. $assoc, "(13)");
  181. $this->_checkRetrieve($store, $server_url, $assoc2->handle,
  182. null, "(14)");
  183. $this->_checkRetrieve($store, $server_url, $assoc3->handle,
  184. null, "(15)");
  185. $this->_checkRemove($store, $server_url, $assoc2->handle,
  186. false, "(16)");
  187. $this->_checkRemove($store, $server_url, $assoc->handle,
  188. true, "(17)");
  189. $this->_checkRemove($store, $server_url, $assoc3->handle,
  190. false, "(18)");
  191. $this->_checkRetrieve($store, $server_url, null, null, "(19)");
  192. $this->_checkRetrieve($store, $server_url, $assoc->handle,
  193. null, "(20)");
  194. $this->_checkRetrieve($store, $server_url, $assoc2->handle,
  195. null, "(21)");
  196. $this->_checkRetrieve($store, $server_url,$assoc3->handle,
  197. null, "(22)");
  198. $this->_checkRemove($store, $server_url, $assoc2->handle,
  199. false, "(23)");
  200. $this->_checkRemove($store, $server_url, $assoc->handle,
  201. false, "(24)");
  202. $this->_checkRemove($store, $server_url, $assoc3->handle,
  203. false, "(25)");
  204. // Put associations into store, for two different server URLs
  205. $assoc1 = $this->genAssoc($now);
  206. $assoc2 = $this->genAssoc($now + 2);
  207. $server_url1 = "http://one.example.com/one";
  208. $server_url2 = "http://two.localhost.localdomain/two";
  209. $store->storeAssociation($server_url1, $assoc1);
  210. $store->storeAssociation($server_url2, $assoc2);
  211. // Ask for each one, make sure we get it
  212. $this->_checkRetrieve($store, $server_url1, $assoc1->handle,
  213. $assoc1, "(26)");
  214. $this->_checkRetrieve($store, $server_url2, $assoc2->handle,
  215. $assoc2, "(27)");
  216. $store->storeAssociation($server_url1, $assoc1);
  217. $store->storeAssociation($server_url2, $assoc2);
  218. // Ask for each one, make sure we get it
  219. $this->_checkRetrieve($store, $server_url1, null,
  220. $assoc1, "(28)");
  221. $this->_checkRetrieve($store, $server_url2, null,
  222. $assoc2, "(29)");
  223. // test expired associations
  224. // assoc 1: server 1, valid
  225. // assoc 2: server 1, expired
  226. // assoc 3: server 2, expired
  227. // assoc 4: server 3, valid
  228. $assocValid1 = $this->genAssoc($now, -3600, 7200);
  229. $assocValid2 = $this->genAssoc($now, -5);
  230. $assocExpired1 = $this->genAssoc($now, -7200, 3600);
  231. $assocExpired2 = $this->genAssoc($now, -7200, 3600);
  232. if (!$store->supportsCleanup()) {
  233. return;
  234. }
  235. $store->cleanupAssociations();
  236. $store->storeAssociation($server_url . '1', $assocValid1);
  237. $store->storeAssociation($server_url . '1', $assocExpired1);
  238. $store->storeAssociation($server_url . '2', $assocExpired2);
  239. $store->storeAssociation($server_url . '3', $assocValid2);
  240. $cleaned = $store->cleanupAssociations();
  241. $this->assertEquals(2, $cleaned);
  242. }
  243. function _checkUseNonce(&$store, $nonce, $expected, $server_url, $msg=null)
  244. {
  245. list($stamp, $salt) = Auth_OpenID_splitNonce($nonce);
  246. $actual = $store->useNonce($server_url, $stamp, $salt);
  247. $this->assertEquals(intval($expected), intval($actual), "_checkUseNonce failed: $server_url, $msg");
  248. }
  249. function _testNonce(&$store)
  250. {
  251. // Nonce functions
  252. $server_url = 'http://www.myopenid.com/openid';
  253. foreach (array($server_url, '') as $url) {
  254. // Random nonce (not in store)
  255. $nonce1 = Auth_OpenID_mkNonce();
  256. // A nonce is not by default
  257. $this->_checkUseNonce($store, $nonce1, true, $url, "blergx");
  258. // Once stored, cannot be stored again
  259. $this->_checkUseNonce($store, $nonce1, false, $url, 2);
  260. // And using again has the same effect
  261. $this->_checkUseNonce($store, $nonce1, false, $url, 3);
  262. // Nonces from when the universe was an hour old should
  263. // not pass these days.
  264. $old_nonce = Auth_OpenID_mkNonce(3600);
  265. $this->_checkUseNonce($store, $old_nonce, false, $url,
  266. "Old nonce ($old_nonce) passed.");
  267. }
  268. }
  269. function _testNonceCleanup(&$store) {
  270. if (!$store->supportsCleanup()) {
  271. return;
  272. }
  273. $server_url = 'http://www.myopenid.com/openid';
  274. $now = time();
  275. $old_nonce1 = Auth_OpenID_mkNonce($now - 20000);
  276. $old_nonce2 = Auth_OpenID_mkNonce($now - 10000);
  277. $recent_nonce = Auth_OpenID_mkNonce($now - 600);
  278. global $Auth_OpenID_SKEW;
  279. $orig_skew = $Auth_OpenID_SKEW;
  280. $Auth_OpenID_SKEW = 0;
  281. $store->cleanupNonces();
  282. // Set SKEW high so stores will keep our nonces.
  283. $Auth_OpenID_SKEW = 100000;
  284. $params = Auth_OpenID_splitNonce($old_nonce1);
  285. array_unshift($params, $server_url);
  286. $this->assertTrue(call_user_func_array(array(&$store, 'useNonce'), $params));
  287. $params = Auth_OpenID_splitNonce($old_nonce2);
  288. array_unshift($params, $server_url);
  289. $this->assertTrue(call_user_func_array(array(&$store, 'useNonce'), $params));
  290. $params = Auth_OpenID_splitNonce($recent_nonce);
  291. array_unshift($params, $server_url);
  292. $this->assertTrue(call_user_func_array(array(&$store, 'useNonce'), $params));
  293. $Auth_OpenID_SKEW = 3600;
  294. $cleaned = $store->cleanupNonces();
  295. $this->assertEquals(2, $cleaned); // , "Cleaned %r nonces." % (cleaned,)
  296. $Auth_OpenID_SKEW = 100000;
  297. // A roundabout method of checking that the old nonces were
  298. // cleaned is to see if we're allowed to add them again.
  299. $params = Auth_OpenID_splitNonce($old_nonce1);
  300. array_unshift($params, $server_url);
  301. $this->assertTrue(call_user_func_array(array(&$store, 'useNonce'), $params));
  302. $params = Auth_OpenID_splitNonce($old_nonce2);
  303. array_unshift($params, $server_url);
  304. $this->assertTrue(call_user_func_array(array(&$store, 'useNonce'), $params));
  305. // The recent nonce wasn't cleaned, so it should still fail.
  306. $params = Auth_OpenID_splitNonce($recent_nonce);
  307. array_unshift($params, $server_url);
  308. $this->assertFalse(call_user_func_array(array(&$store, 'useNonce'), $params));
  309. $Auth_OpenID_SKEW = $orig_skew;
  310. }
  311. }
  312. /**
  313. * Class that tests all of the stores included with the OpenID library
  314. *
  315. * @package OpenID
  316. */
  317. class Tests_Auth_OpenID_Included_StoreTest extends Tests_Auth_OpenID_Store {
  318. function test_memstore()
  319. {
  320. require_once 'Tests/Auth/OpenID/MemStore.php';
  321. $store = new Tests_Auth_OpenID_MemStore();
  322. $this->_testStore($store);
  323. $this->_testNonce($store);
  324. $this->_testNonceCleanup($store);
  325. }
  326. function test_filestore()
  327. {
  328. require_once 'Auth/OpenID/FileStore.php';
  329. $temp_dir = _Auth_OpenID_mkdtemp();
  330. if (!$temp_dir) {
  331. trigger_error('Could not create temporary directory ' .
  332. 'with Auth_OpenID_FileStore::_mkdtemp',
  333. E_USER_WARNING);
  334. return null;
  335. }
  336. $store = new Auth_OpenID_FileStore($temp_dir);
  337. $this->_testStore($store);
  338. $this->_testNonce($store);
  339. $this->_testNonceCleanup($store);
  340. $store->destroy();
  341. }
  342. function test_postgresqlstore()
  343. {
  344. // If the postgres extension isn't loaded or loadable, succeed
  345. // because we can't run the test.
  346. if (!(extension_loaded('pgsql') ||
  347. @dl('pgsql.so') ||
  348. @dl('php_pgsql.dll'))) {
  349. print "(not testing PostGreSQL store)";
  350. $this->pass();
  351. return;
  352. }
  353. require_once 'Auth/OpenID/PostgreSQLStore.php';
  354. require_once 'DB.php';
  355. global $_Auth_OpenID_db_test_host;
  356. $temp_db_name = _Auth_OpenID_getTmpDbName();
  357. $connect_db_name = 'test_master';
  358. $dsn = array(
  359. 'phptype' => 'pgsql',
  360. 'username' => 'openid_test',
  361. 'password' => '',
  362. 'hostspec' => $_Auth_OpenID_db_test_host,
  363. 'database' => $connect_db_name
  364. );
  365. $allowed_failures = 5;
  366. $result = null;
  367. $sleep_time = 1.0;
  368. $sql = sprintf("CREATE DATABASE %s", $temp_db_name);
  369. for ($failures = 0; $failures < $allowed_failures; $failures++) {
  370. $template_db =& DB::connect($dsn);
  371. if (PEAR::isError($template_db)) {
  372. $result =& $template_db;
  373. } else {
  374. // Try to create the test database.
  375. $result = $template_db->query($sql);
  376. $template_db->disconnect();
  377. unset($template_db);
  378. if (!PEAR::isError($result)) {
  379. break;
  380. }
  381. }
  382. $sleep_time *= ((mt_rand(1, 100) / 100.0) + 1.5);
  383. print "Failed to create database $temp_db_name.\n".
  384. "Waiting $sleep_time before trying again\n";
  385. $int_sleep = floor($sleep_time);
  386. $frac_sleep = $sleep_time - $int_sleep;
  387. sleep($int_sleep);
  388. usleep($frac_sleep * 1000000.0);
  389. }
  390. if ($failures == $allowed_failures) {
  391. $this->pass("Temporary database creation failed after $failures ".
  392. " tries ('$temp_db_name'): " . $result->getMessage());
  393. return;
  394. }
  395. // Disconnect from template1 and reconnect to the temporary
  396. // testing database.
  397. $dsn['database'] = $temp_db_name;
  398. $db =& DB::connect($dsn);
  399. if (PEAR::isError($db)) {
  400. $this->fail("Temporary database connection failed " .
  401. " ('$temp_db_name'): " . $db->getMessage());
  402. return;
  403. }
  404. $store =& new Auth_OpenID_PostgreSQLStore($db);
  405. $this->assertFalse($store->tableExists($store->nonces_table_name));
  406. $this->assertFalse($store->tableExists($store->associations_table_name));
  407. $store->createTables();
  408. $this->assertTrue($store->tableExists($store->nonces_table_name));
  409. $this->assertTrue($store->tableExists($store->associations_table_name));
  410. $this->_testStore($store);
  411. $this->_testNonce($store);
  412. $this->_testNonceCleanup($store);
  413. $db->disconnect();
  414. unset($db);
  415. // Connect to template1 again so we can drop the temporary
  416. // database.
  417. $dsn['database'] = $connect_db_name;
  418. $template_db =& DB::connect($dsn);
  419. if (PEAR::isError($template_db)) {
  420. $this->fail("Template database connection (to drop " .
  421. "temporary database) failed: " .
  422. $template_db->getMessage());
  423. return;
  424. }
  425. $result = $template_db->query(sprintf("DROP DATABASE %s",
  426. $temp_db_name));
  427. if (PEAR::isError($result)) {
  428. $this->fail("Dropping temporary database failed: " .
  429. $result->getMessage());
  430. return;
  431. }
  432. $template_db->disconnect();
  433. unset($template_db);
  434. }
  435. function test_sqlitestore()
  436. {
  437. // If the sqlite extension isn't loaded or loadable, succeed
  438. // because we can't run the test.
  439. if (!(extension_loaded('sqlite') ||
  440. @dl('sqlite.so') ||
  441. @dl('php_sqlite.dll'))) {
  442. print "(not testing SQLite store)";
  443. $this->pass();
  444. return;
  445. }
  446. require_once 'Auth/OpenID/SQLiteStore.php';
  447. require_once 'DB.php';
  448. $temp_dir = _Auth_OpenID_mkdtemp();
  449. if (!$temp_dir) {
  450. trigger_error('Could not create temporary directory ' .
  451. 'with Auth_OpenID_FileStore::_mkdtemp',
  452. E_USER_WARNING);
  453. return null;
  454. }
  455. $dsn = 'sqlite:///' . urlencode($temp_dir) . '/php_openid_storetest.db';
  456. $db =& DB::connect($dsn);
  457. if (PEAR::isError($db)) {
  458. $this->pass("SQLite database connection failed: " .
  459. $db->getMessage());
  460. } else {
  461. $store =& new Auth_OpenID_SQLiteStore($db);
  462. $this->assertTrue($store->createTables(), "Table creation failed");
  463. $this->_testStore($store);
  464. $this->_testNonce($store);
  465. $this->_testNonceCleanup($store);
  466. }
  467. $db->disconnect();
  468. unset($db);
  469. unset($store);
  470. unlink($temp_dir . '/php_openid_storetest.db');
  471. rmdir($temp_dir);
  472. }
  473. function test_mysqlstore()
  474. {
  475. // If the mysql extension isn't loaded or loadable, succeed
  476. // because we can't run the test.
  477. if (!(extension_loaded('mysql') ||
  478. @dl('mysql.' . PHP_SHLIB_SUFFIX))) {
  479. print "(not testing MySQL store)";
  480. $this->pass();
  481. return;
  482. }
  483. require_once 'Auth/OpenID/MySQLStore.php';
  484. require_once 'DB.php';
  485. global $_Auth_OpenID_db_test_host;
  486. $dsn = array(
  487. 'phptype' => 'mysql',
  488. 'username' => 'openid_test',
  489. 'password' => '',
  490. 'hostspec' => $_Auth_OpenID_db_test_host
  491. );
  492. $db =& DB::connect($dsn);
  493. if (PEAR::isError($db)) {
  494. print "MySQL database connection failed: " .
  495. $db->getMessage();
  496. $this->pass();
  497. return;
  498. }
  499. $temp_db_name = _Auth_OpenID_getTmpDbName();
  500. $result = $db->query("CREATE DATABASE $temp_db_name");
  501. if (PEAR::isError($result)) {
  502. $this->pass("Error creating MySQL temporary database: " .
  503. $result->getMessage());
  504. return;
  505. }
  506. $db->query("USE $temp_db_name");
  507. $store =& new Auth_OpenID_MySQLStore($db);
  508. $store->createTables();
  509. $this->_testStore($store);
  510. $this->_testNonce($store);
  511. $this->_testNonceCleanup($store);
  512. $db->query("DROP DATABASE $temp_db_name");
  513. }
  514. }
  515. /**
  516. * This is the host that the store test will use
  517. */
  518. global $_Auth_OpenID_memcache_test_host;
  519. $_Auth_OpenID_memcache_test_host = 'localhost';
  520. class Tests_Auth_OpenID_MemcachedStore_Test extends Tests_Auth_OpenID_Store {
  521. function test_memcache()
  522. {
  523. // If the memcache extension isn't loaded or loadable, succeed
  524. // because we can't run the test.
  525. if (!(extension_loaded('memcache') ||
  526. @dl('memcache.so') ||
  527. @dl('php_memcache.dll'))) {
  528. print "(skipping memcache store tests)";
  529. $this->pass();
  530. return;
  531. }
  532. require_once 'Auth/OpenID/MemcachedStore.php';
  533. global $_Auth_OpenID_memcache_test_host;
  534. $memcached = new Memcache();
  535. if (!$memcached->connect($_Auth_OpenID_memcache_test_host)) {
  536. print "(skipping memcache store tests - couldn't connect)";
  537. $this->pass();
  538. } else {
  539. $store = new Auth_OpenID_MemcachedStore($memcached);
  540. $this->_testStore($store);
  541. $this->_testNonce($store);
  542. $this->_testNonceCleanup($store);
  543. $memcached->close();
  544. }
  545. }
  546. }
  547. class Tests_Auth_OpenID_StoreTest extends PHPUnit_TestSuite {
  548. function getName()
  549. {
  550. return "Tests_Auth_OpenID_StoreTest";
  551. }
  552. function Tests_Auth_OpenID_StoreTest()
  553. {
  554. $this->addTestSuite('Tests_Auth_OpenID_Included_StoreTest');
  555. $this->addTestSuite('Tests_Auth_OpenID_MemcachedStore_Test');
  556. }
  557. }
  558. ?>