From d9bf22a0e29c2a70049443a0ae8521a2c0492c8b Mon Sep 17 00:00:00 2001 From: Cash Costello Date: Sun, 11 Dec 2011 06:38:23 -0500 Subject: initial commit for git repository --- .../Tests/Auth/OpenID/StoreTest.php | 755 +++++++++++++++++++++ 1 file changed, 755 insertions(+) create mode 100644 models/openid-php-openid-782224d/Tests/Auth/OpenID/StoreTest.php (limited to 'models/openid-php-openid-782224d/Tests/Auth/OpenID/StoreTest.php') diff --git a/models/openid-php-openid-782224d/Tests/Auth/OpenID/StoreTest.php b/models/openid-php-openid-782224d/Tests/Auth/OpenID/StoreTest.php new file mode 100644 index 000000000..7c50e2fda --- /dev/null +++ b/models/openid-php-openid-782224d/Tests/Auth/OpenID/StoreTest.php @@ -0,0 +1,755 @@ + + * @copyright 2005-2008 Janrain, Inc. + * @license http://www.apache.org/licenses/LICENSE-2.0 Apache + */ + +/** + * Require classes and functions to run the Store tests. + */ +require_once 'Auth/OpenID/Association.php'; +require_once 'Auth/OpenID/CryptUtil.php'; +require_once 'Auth/OpenID/Nonce.php'; +require_once 'Auth/OpenID.php'; + +function _Auth_OpenID_mkdtemp() +{ + if (strpos(PHP_OS, 'WIN') === 0) { + $dir = $_ENV['TMP']; + if (!isset($dir)) { + $dir = 'C:\Windows\Temp'; + } + } else { + $dir = @$_ENV['TMPDIR']; + if (!isset($dir)) { + $dir = '/tmp'; + } + } + + return Auth_OpenID_FileStore::_mkdtemp($dir); +} + +/** + * This is the host where the SQL stores' databases should be created + * and destroyed. + */ +global $_Auth_OpenID_db_test_host; +$_Auth_OpenID_db_test_host = 'dbtest'; + +/** + * Generate a sufficently unique database name so many hosts can run + * SQL store tests on the server at the same time and not step on each + * other. + */ +function _Auth_OpenID_getTmpDbName() +{ + $hostname = php_uname('n'); + $hostname = str_replace('.', '_', $hostname); + $hostname = str_replace('-', '_', $hostname); + $hostname = strtolower($hostname); + + return sprintf("%s_%d_%s_openid_test", + $hostname, + getmypid(), + strval(rand(1, time()))); +} + +/** + * Superclass that has methods for testing OpenID stores. Subclass this to + * test your own store implementation. + * + * @package OpenID + */ +class Tests_Auth_OpenID_Store extends PHPUnit_Framework_TestCase { + + function pass() {} + + /** + * Prepares for the SQL store tests. + */ + function setUp() + { + $this->letters = Auth_OpenID_letters; + $this->digits = Auth_OpenID_digits; + $this->punct = Auth_OpenID_punct; + $this->allowed_nonce = $this->letters . $this->digits; + $this->allowed_handle = $this->letters . $this->digits . $this->punct; + } + + /** + * Generates an association with the specified parameters. + */ + function genAssoc($now, $issued = 0, $lifetime = 600) + { + $sec = Auth_OpenID_CryptUtil::randomString(20); + $hdl = Auth_OpenID_CryptUtil::randomString(128, $this->allowed_handle); + return new Auth_OpenID_Association($hdl, $sec, $now + $issued, + $lifetime, 'HMAC-SHA1'); + } + + /** + * @access private + */ + function _checkRetrieve($store, $url, $handle, $expected, $name = null) + { + $retrieved_assoc = $store->getAssociation($url, $handle); + if ($expected === null) { + $this->assertTrue($retrieved_assoc === null); + } else { + $this->assertTrue($expected->equal($retrieved_assoc), $name); + } + } + + function _checkRemove($store, $url, $handle, $expected, $name = null) + { + $present = $store->removeAssociation($url, $handle); + $this->assertTrue((!$expected && !$present) || + ($expected && $present), + $name); + } + + /** + * Make sure a given store has a minimum of API compliance. Call + * this function with an empty store. + * + * Raises AssertionError if the store does not work as expected. + * + * OpenIDStore -> NoneType + */ + function _testStore($store) + { + // Association functions + $now = time(); + + $server_url = 'http://www.myopenid.com/openid'; + + $assoc = $this->genAssoc($now); + + $this->_checkRetrieve($store, $server_url, null, null, + 'Make sure that a missing association returns no result'); + + $store->storeAssociation($server_url, $assoc); + $this->_checkRetrieve($store, $server_url, null, $assoc, + 'Check that after storage, getting returns the same result'); + + $this->_checkRetrieve($store, $server_url, null, $assoc, + 'more than once'); + + $store->storeAssociation($server_url, $assoc); + $this->_checkRetrieve($store, $server_url, null, $assoc, + 'Storing more than once has no ill effect'); + + // Removing an association that does not exist returns not present + $this->_checkRemove($store, $server_url, $assoc->handle . 'x', false, + "Remove nonexistent association (1)"); + + // Removing an association that does not exist returns not present + $this->_checkRemove($store, $server_url . 'x', $assoc->handle, false, + "Remove nonexistent association (2)"); + + // Removing an association that is present returns present + $this->_checkRemove($store, $server_url, $assoc->handle, true, + "Remove existent association"); + + // but not present on subsequent calls + $this->_checkRemove($store, $server_url, $assoc->handle, false, + "Remove nonexistent association after removal"); + + // Put assoc back in the store + $store->storeAssociation($server_url, $assoc); + + // More recent and expires after assoc + $assoc2 = $this->genAssoc($now, $issued = 1); + $store->storeAssociation($server_url, $assoc2); + + $this->_checkRetrieve($store, $server_url, null, $assoc2, + 'After storing an association with a different handle, but the +same $server_url, the handle with the later expiration is +returned.'); + + $this->_checkRetrieve($store, $server_url, $assoc->handle, $assoc, + 'We can still retrieve the older association'); + + $this->_checkRetrieve($store, $server_url, $assoc2->handle, $assoc2, + 'Plus we can retrieve the association with the later expiration +explicitly'); + + $assoc3 = $this->genAssoc($now, $issued = 2, $lifetime = 100); + $store->storeAssociation($server_url, $assoc3); + + // More recent issued time, so assoc3 is expected. + $this->_checkRetrieve($store, $server_url, null, $assoc3, "(1)"); + + $this->_checkRetrieve($store, $server_url, $assoc->handle, + $assoc, "(2)"); + + $this->_checkRetrieve($store, $server_url, $assoc2->handle, + $assoc2, "(3)"); + + $this->_checkRetrieve($store, $server_url, $assoc3->handle, + $assoc3, "(4)"); + + $this->_checkRemove($store, $server_url, $assoc2->handle, true, "(5)"); + + $this->_checkRetrieve($store, $server_url, null, $assoc3, "(6)"); + + $this->_checkRetrieve($store, $server_url, $assoc->handle, + $assoc, "(7)"); + + $this->_checkRetrieve($store, $server_url, $assoc2->handle, + null, "(8)"); + + $this->_checkRetrieve($store, $server_url, $assoc3->handle, + $assoc3, "(9)"); + + $this->_checkRemove($store, $server_url, $assoc2->handle, + false, "(10)"); + + $this->_checkRemove($store, $server_url, $assoc3->handle, + true, "(11)"); + + $this->_checkRetrieve($store, $server_url, null, $assoc, "(12)"); + + $this->_checkRetrieve($store, $server_url, $assoc->handle, + $assoc, "(13)"); + + $this->_checkRetrieve($store, $server_url, $assoc2->handle, + null, "(14)"); + + $this->_checkRetrieve($store, $server_url, $assoc3->handle, + null, "(15)"); + + $this->_checkRemove($store, $server_url, $assoc2->handle, + false, "(16)"); + + $this->_checkRemove($store, $server_url, $assoc->handle, + true, "(17)"); + + $this->_checkRemove($store, $server_url, $assoc3->handle, + false, "(18)"); + + $this->_checkRetrieve($store, $server_url, null, null, "(19)"); + + $this->_checkRetrieve($store, $server_url, $assoc->handle, + null, "(20)"); + + $this->_checkRetrieve($store, $server_url, $assoc2->handle, + null, "(21)"); + + $this->_checkRetrieve($store, $server_url,$assoc3->handle, + null, "(22)"); + + $this->_checkRemove($store, $server_url, $assoc2->handle, + false, "(23)"); + + $this->_checkRemove($store, $server_url, $assoc->handle, + false, "(24)"); + + $this->_checkRemove($store, $server_url, $assoc3->handle, + false, "(25)"); + + // Put associations into store, for two different server URLs + $assoc1 = $this->genAssoc($now); + $assoc2 = $this->genAssoc($now + 2); + $server_url1 = "http://one.example.com/one"; + $server_url2 = "http://two.localhost.localdomain/two"; + + $store->storeAssociation($server_url1, $assoc1); + $store->storeAssociation($server_url2, $assoc2); + + // Ask for each one, make sure we get it + $this->_checkRetrieve($store, $server_url1, $assoc1->handle, + $assoc1, "(26)"); + + $this->_checkRetrieve($store, $server_url2, $assoc2->handle, + $assoc2, "(27)"); + + $store->storeAssociation($server_url1, $assoc1); + $store->storeAssociation($server_url2, $assoc2); + + // Ask for each one, make sure we get it + $this->_checkRetrieve($store, $server_url1, null, + $assoc1, "(28)"); + + $this->_checkRetrieve($store, $server_url2, null, + $assoc2, "(29)"); + + // test expired associations + // assoc 1: server 1, valid + // assoc 2: server 1, expired + // assoc 3: server 2, expired + // assoc 4: server 3, valid + $assocValid1 = $this->genAssoc($now, -3600, 7200); + $assocValid2 = $this->genAssoc($now, -5); + $assocExpired1 = $this->genAssoc($now, -7200, 3600); + $assocExpired2 = $this->genAssoc($now, -7200, 3600); + + if (!$store->supportsCleanup()) { + return; + } + + $store->cleanupAssociations(); + $store->storeAssociation($server_url . '1', $assocValid1); + $store->storeAssociation($server_url . '1', $assocExpired1); + $store->storeAssociation($server_url . '2', $assocExpired2); + $store->storeAssociation($server_url . '3', $assocValid2); + + $cleaned = $store->cleanupAssociations(); + $this->assertEquals(2, $cleaned); + } + + function _checkUseNonce($store, $nonce, $expected, $server_url, $msg=null) + { + list($stamp, $salt) = Auth_OpenID_splitNonce($nonce); + $actual = $store->useNonce($server_url, $stamp, $salt); + $this->assertEquals(intval($expected), intval($actual), "_checkUseNonce failed: $server_url, $msg"); + } + + function _testNonce($store) + { + // Nonce functions + + $server_url = 'http://www.myopenid.com/openid'; + + foreach (array($server_url, '') as $url) { + // Random nonce (not in store) + $nonce1 = Auth_OpenID_mkNonce(); + + // A nonce is not by default + $this->_checkUseNonce($store, $nonce1, true, $url, "blergx"); + + // Once stored, cannot be stored again + $this->_checkUseNonce($store, $nonce1, false, $url, 2); + + // And using again has the same effect + $this->_checkUseNonce($store, $nonce1, false, $url, 3); + + // Nonces from when the universe was an hour old should + // not pass these days. + $old_nonce = Auth_OpenID_mkNonce(3600); + $this->_checkUseNonce($store, $old_nonce, false, $url, + "Old nonce ($old_nonce) passed."); + + } + } + + function _testNonceCleanup($store) { + if (!$store->supportsCleanup()) { + return; + } + + $server_url = 'http://www.myopenid.com/openid'; + + $now = time(); + + $old_nonce1 = Auth_OpenID_mkNonce($now - 20000); + $old_nonce2 = Auth_OpenID_mkNonce($now - 10000); + $recent_nonce = Auth_OpenID_mkNonce($now - 600); + + global $Auth_OpenID_SKEW; + $orig_skew = $Auth_OpenID_SKEW; + + $Auth_OpenID_SKEW = 0; + $store->cleanupNonces(); + // Set SKEW high so stores will keep our nonces. + $Auth_OpenID_SKEW = 100000; + + $params = Auth_OpenID_splitNonce($old_nonce1); + array_unshift($params, $server_url); + $this->assertTrue(call_user_func_array(array($store, 'useNonce'), $params)); + + $params = Auth_OpenID_splitNonce($old_nonce2); + array_unshift($params, $server_url); + $this->assertTrue(call_user_func_array(array($store, 'useNonce'), $params)); + + $params = Auth_OpenID_splitNonce($recent_nonce); + array_unshift($params, $server_url); + $this->assertTrue(call_user_func_array(array($store, 'useNonce'), $params)); + + $Auth_OpenID_SKEW = 3600; + $cleaned = $store->cleanupNonces(); + $this->assertEquals(2, $cleaned); // , "Cleaned %r nonces." % (cleaned,) + + $Auth_OpenID_SKEW = 100000; + // A roundabout method of checking that the old nonces were + // cleaned is to see if we're allowed to add them again. + + $params = Auth_OpenID_splitNonce($old_nonce1); + array_unshift($params, $server_url); + $this->assertTrue(call_user_func_array(array($store, 'useNonce'), $params)); + $params = Auth_OpenID_splitNonce($old_nonce2); + array_unshift($params, $server_url); + $this->assertTrue(call_user_func_array(array($store, 'useNonce'), $params)); + + // The recent nonce wasn't cleaned, so it should still fail. + $params = Auth_OpenID_splitNonce($recent_nonce); + array_unshift($params, $server_url); + $this->assertFalse(call_user_func_array(array($store, 'useNonce'), $params)); + + $Auth_OpenID_SKEW = $orig_skew; + } + +} +/** + * Class that tests all of the stores included with the OpenID library + * + * @package OpenID + */ +class Tests_Auth_OpenID_Included_StoreTest extends Tests_Auth_OpenID_Store { + function test_memstore() + { + require_once 'Tests/Auth/OpenID/MemStore.php'; + $store = new Tests_Auth_OpenID_MemStore(); + $this->_testStore($store); + $this->_testNonce($store); + $this->_testNonceCleanup($store); + } + + function test_filestore() + { + require_once 'Auth/OpenID/FileStore.php'; + + $temp_dir = _Auth_OpenID_mkdtemp(); + + if (!$temp_dir) { + trigger_error('Could not create temporary directory ' . + 'with Auth_OpenID_FileStore::_mkdtemp', + E_USER_WARNING); + return null; + } + + $store = new Auth_OpenID_FileStore($temp_dir); + $this->_testStore($store); + $this->_testNonce($store); + $this->_testNonceCleanup($store); + $store->destroy(); + } + + function test_postgresqlstore() + { + // If the postgres extension isn't loaded or loadable, succeed + // because we can't run the test. + if (!(extension_loaded('pgsql')) || + !(@include_once 'DB.php')) { + print "(not testing PostGreSQL store)"; + $this->pass(); + return; + } + + require_once 'Auth/OpenID/PostgreSQLStore.php'; + + global $_Auth_OpenID_db_test_host; + + $temp_db_name = _Auth_OpenID_getTmpDbName(); + + $connect_db_name = 'test_master'; + + $dsn = array( + 'phptype' => 'pgsql', + 'username' => 'openid_test', + 'password' => '', + 'hostspec' => $_Auth_OpenID_db_test_host, + 'database' => $connect_db_name + ); + + $allowed_failures = 5; + $result = null; + $sleep_time = 1.0; + $sql = sprintf("CREATE DATABASE %s", $temp_db_name); + + for ($failures = 0; $failures < $allowed_failures; $failures++) { + $template_db =& DB::connect($dsn); + + if (PEAR::isError($template_db)) { + $result =& $template_db; + } else { + // Try to create the test database. + $result = $template_db->query($sql); + + $template_db->disconnect(); + unset($template_db); + + if (!PEAR::isError($result)) { + break; + } + } + + $sleep_time *= ((mt_rand(1, 100) / 100.0) + 1.5); + print "Failed to create database $temp_db_name.\n". + "Waiting $sleep_time before trying again\n"; + + $int_sleep = floor($sleep_time); + $frac_sleep = $sleep_time - $int_sleep; + sleep($int_sleep); + usleep($frac_sleep * 1000000.0); + } + + if ($failures == $allowed_failures) { + $this->pass("Temporary database creation failed after $failures ". + " tries ('$temp_db_name'): " . $result->getMessage()); + return; + } + + // Disconnect from template1 and reconnect to the temporary + // testing database. + $dsn['database'] = $temp_db_name; + $db =& DB::connect($dsn); + + if (PEAR::isError($db)) { + $this->fail("Temporary database connection failed " . + " ('$temp_db_name'): " . $db->getMessage()); + return; + } + + $store = new Auth_OpenID_PostgreSQLStore($db); + + $this->assertFalse($store->tableExists($store->nonces_table_name)); + $this->assertFalse($store->tableExists($store->associations_table_name)); + + $store->createTables(); + + $this->assertTrue($store->tableExists($store->nonces_table_name)); + $this->assertTrue($store->tableExists($store->associations_table_name)); + + $this->_testStore($store); + $this->_testNonce($store); + $this->_testNonceCleanup($store); + + $db->disconnect(); + unset($db); + + // Connect to template1 again so we can drop the temporary + // database. + $dsn['database'] = $connect_db_name; + $template_db =& DB::connect($dsn); + + if (PEAR::isError($template_db)) { + $this->fail("Template database connection (to drop " . + "temporary database) failed: " . + $template_db->getMessage()); + return; + } + + $result = $template_db->query(sprintf("DROP DATABASE %s", + $temp_db_name)); + + if (PEAR::isError($result)) { + $this->fail("Dropping temporary database failed: " . + $result->getMessage()); + return; + } + + $template_db->disconnect(); + unset($template_db); + } + + function test_sqlitestore() + { + // If the sqlite extension isn't loaded or loadable, succeed + // because we can't run the test. + if (!(extension_loaded('sqlite')) || + !(@include_once 'DB.php')) { + print "(not testing SQLite store)"; + $this->pass(); + return; + } + + require_once 'Auth/OpenID/SQLiteStore.php'; + + $temp_dir = _Auth_OpenID_mkdtemp(); + + if (!$temp_dir) { + trigger_error('Could not create temporary directory ' . + 'with Auth_OpenID_FileStore::_mkdtemp', + E_USER_WARNING); + return null; + } + + $dsn = 'sqlite:///' . urlencode($temp_dir) . '/php_openid_storetest.db'; + $db =& DB::connect($dsn); + + if (PEAR::isError($db)) { + $this->pass("SQLite database connection failed: " . + $db->getMessage()); + } else { + $store = new Auth_OpenID_SQLiteStore($db); + $this->assertTrue($store->createTables(), "Table creation failed"); + $this->_testStore($store); + $this->_testNonce($store); + $this->_testNonceCleanup($store); + } + + $db->disconnect(); + unset($db); + unset($store); + unlink($temp_dir . '/php_openid_storetest.db'); + rmdir($temp_dir); + } + + function test_mysqlstore() + { + // If the mysql extension isn't loaded or loadable, succeed + // because we can't run the test. + if (!(extension_loaded('mysql')) || + !(@include_once 'DB.php')) { + print "(not testing MySQL store)"; + $this->pass(); + return; + } + + require_once 'Auth/OpenID/MySQLStore.php'; + + global $_Auth_OpenID_db_test_host; + + $dsn = array( + 'phptype' => 'mysql', + 'username' => 'openid_test', + 'password' => '', + 'hostspec' => $_Auth_OpenID_db_test_host + ); + + $db =& DB::connect($dsn); + + if (PEAR::isError($db)) { + print "MySQL database connection failed: " . + $db->getMessage(); + $this->pass(); + return; + } + + $temp_db_name = _Auth_OpenID_getTmpDbName(); + + $result = $db->query("CREATE DATABASE $temp_db_name"); + + if (PEAR::isError($result)) { + $this->pass("Error creating MySQL temporary database: " . + $result->getMessage()); + return; + } + + $db->query("USE $temp_db_name"); + + $store = new Auth_OpenID_MySQLStore($db); + $store->createTables(); + $this->_testStore($store); + $this->_testNonce($store); + $this->_testNonceCleanup($store); + + $db->query("DROP DATABASE $temp_db_name"); + } + + function test_mdb2store() + { + // The MDB2 test can use any database engine. MySQL is chosen + // arbitrarily. + if (!(extension_loaded('mysql') || + @dl('mysql.' . PHP_SHLIB_SUFFIX)) || + !(@include_once 'MDB2.php')) { + print "(not testing MDB2 store)"; + $this->pass(); + return; + } + + require_once 'Auth/OpenID/MDB2Store.php'; + + global $_Auth_OpenID_db_test_host; + + $dsn = array( + 'phptype' => 'mysql', + 'username' => 'openid_test', + 'password' => '', + 'hostspec' => $_Auth_OpenID_db_test_host + ); + + $db =& MDB2::connect($dsn); + + if (PEAR::isError($db)) { + print "MySQL database connection failed: " . + $db->getMessage(); + $this->pass(); + return; + } + + $temp_db_name = _Auth_OpenID_getTmpDbName(); + + $result = $db->query("CREATE DATABASE $temp_db_name"); + + if (PEAR::isError($result)) { + $this->pass("Error creating MySQL temporary database: " . + $result->getMessage()); + return; + } + + $db->query("USE $temp_db_name"); + + $store =& new Auth_OpenID_MDB2Store($db); + if (!$store->createTables()) { + $this->fail("Failed to create tables"); + return; + } + $this->_testStore($store); + $this->_testNonce($store); + $this->_testNonceCleanup($store); + + $db->query("DROP DATABASE $temp_db_name"); + } +} + +/** + * This is the host that the store test will use + */ +global $_Auth_OpenID_memcache_test_host; +$_Auth_OpenID_memcache_test_host = 'localhost'; + +class Tests_Auth_OpenID_MemcachedStore_Test extends Tests_Auth_OpenID_Store { + function test_memcache() + { + // If the memcache extension isn't loaded or loadable, succeed + // because we can't run the test. + if (!extension_loaded('memcache')) { + print "(skipping memcache store tests)"; + $this->pass(); + return; + } + require_once 'Auth/OpenID/MemcachedStore.php'; + + global $_Auth_OpenID_memcache_test_host; + + $memcached = new Memcache(); + if (!$memcached->connect($_Auth_OpenID_memcache_test_host)) { + print "(skipping memcache store tests - couldn't connect)"; + $this->pass(); + } else { + $store = new Auth_OpenID_MemcachedStore($memcached); + + $this->_testStore($store); + $this->_testNonce($store); + $this->_testNonceCleanup($store); + + $memcached->close(); + } + } +} + +class Tests_Auth_OpenID_StoreTest extends PHPUnit_Framework_TestSuite { + function getName() + { + return "Tests_Auth_OpenID_StoreTest"; + } + + function Tests_Auth_OpenID_StoreTest() + { + $this->addTestSuite('Tests_Auth_OpenID_Included_StoreTest'); + $this->addTestSuite('Tests_Auth_OpenID_MemcachedStore_Test'); + } +} + -- cgit v1.2.3