mirror of
https://github.com/Lastorder-DC/rhymix.git
synced 2026-01-18 10:49:54 +09:00
git-svn-id: http://xe-core.googlecode.com/svn/sandbox@5137 201d5d3c-b55e-5fd7-737f-ddc643e51545
574 lines
18 KiB
PHP
574 lines
18 KiB
PHP
<?php
|
|
|
|
/**
|
|
* A test script for the OpenIDStore classes.
|
|
*
|
|
* PHP versions 4 and 5
|
|
*
|
|
* LICENSE: See the COPYING file included in this distribution.
|
|
*
|
|
* @package OpenID
|
|
* @author JanRain, Inc. <openid@janrain.com>
|
|
* @copyright 2005 Janrain, Inc.
|
|
* @license http://www.gnu.org/copyleft/lesser.html LGPL
|
|
*/
|
|
|
|
/**
|
|
* 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.php';
|
|
require_once 'PHPUnit.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.
|
|
*/
|
|
$_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 = strtolower(str_replace('.', '_', $hostname));
|
|
|
|
return sprintf("%s_%d_%s_openid_test",
|
|
$hostname,
|
|
getmypid(),
|
|
strval(rand(1, time())));
|
|
}
|
|
|
|
/**
|
|
* Tests the OpenID stores.
|
|
*
|
|
* @package OpenID
|
|
*/
|
|
class Tests_Auth_OpenID_StoreTest extends PHPUnit_TestCase {
|
|
|
|
/**
|
|
* 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 a nonce value.
|
|
*/
|
|
function generateNonce()
|
|
{
|
|
return Auth_OpenID_CryptUtil::randomString(8, $this->allowed_nonce);
|
|
}
|
|
|
|
/**
|
|
* 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) || ($store->isDumb())) {
|
|
$this->assertNull($retrieved_assoc, "Retrieved association " .
|
|
"was non-null");
|
|
} else {
|
|
if ($retrieved_assoc === null) {
|
|
$this->fail("$name: Got null when expecting " .
|
|
$expected->serialize());
|
|
} else {
|
|
$this->assertEquals($expected->serialize(),
|
|
$retrieved_assoc->serialize(), $name);
|
|
}
|
|
}
|
|
}
|
|
|
|
function _checkRemove(&$store, $url, $handle, $expected, $name = null)
|
|
{
|
|
$present = $store->removeAssociation($url, $handle);
|
|
$expectedPresent = (!$store->isDumb() && $expected);
|
|
$this->assertTrue((!$expectedPresent && !$present) ||
|
|
($expectedPresent && $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)");
|
|
}
|
|
|
|
function _checkUseNonce(&$store, $nonce, $expected, $msg=null)
|
|
{
|
|
$actual = $store->useNonce($nonce);
|
|
$expected = $store->isDumb() || $expected;
|
|
$val = ($actual && $expected) || (!$actual && !$expected);
|
|
$this->assertTrue($val, "_checkUseNonce failed: $msg");
|
|
}
|
|
|
|
function _testNonce(&$store)
|
|
{
|
|
// Nonce functions
|
|
|
|
// Random nonce (not in store)
|
|
$nonce1 = $this->generateNonce();
|
|
|
|
// A nonce is not present by default
|
|
$this->_checkUseNonce($store, $nonce1, false, 1);
|
|
|
|
// Storing once causes useNonce to return true the first, and
|
|
// only the first, time it is called after the $store->
|
|
$store->storeNonce($nonce1);
|
|
$this->_checkUseNonce($store, $nonce1, true, 2);
|
|
$this->_checkUseNonce($store, $nonce1, false, 3);
|
|
$this->_checkUseNonce($store, $nonce1, false, 4);
|
|
|
|
// Storing twice has the same effect as storing once.
|
|
$store->storeNonce($nonce1);
|
|
$store->storeNonce($nonce1);
|
|
$this->_checkUseNonce($store, $nonce1, true, 5);
|
|
$this->_checkUseNonce($store, $nonce1, false, 6);
|
|
$this->_checkUseNonce($store, $nonce1, false, 7);
|
|
|
|
// Auth key functions
|
|
|
|
// There is no key to start with, so generate a new key and
|
|
// return it.
|
|
$key = $store->getAuthKey();
|
|
|
|
// The second time around should return the same as last time.
|
|
$key2 = $store->getAuthKey();
|
|
$this->assertEquals($key, $key2, "Auth keys differ");
|
|
$this->assertEquals(strlen($key), $store->AUTH_KEY_LEN,
|
|
"Key length not equals AUTH_KEY_LEN");
|
|
}
|
|
|
|
function test_memstore()
|
|
{
|
|
require_once 'Tests/Auth/OpenID/MemStore.php';
|
|
$store = new Tests_Auth_OpenID_MemStore('Bogus auth key ');
|
|
$this->_testStore(&$store);
|
|
$this->_testNonce(&$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);
|
|
$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') ||
|
|
@dl('pgsql.' . PHP_SHLIB_SUFFIX))) {
|
|
$this->pass();
|
|
return;
|
|
}
|
|
|
|
require_once 'Auth/OpenID/PostgreSQLStore.php';
|
|
require_once 'DB.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->fail("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);
|
|
$store->createTables();
|
|
$this->_testStore($store);
|
|
$this->_testNonce($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 postgres extension isn't loaded or loadable, succeed
|
|
// because we can't run the test.
|
|
if (!(extension_loaded('sqlite') ||
|
|
@dl('sqlite.' . PHP_SHLIB_SUFFIX))) {
|
|
$this->pass();
|
|
return;
|
|
}
|
|
|
|
require_once 'Auth/OpenID/SQLiteStore.php';
|
|
require_once 'DB.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 = sprintf("sqlite:///%s/file.db", $temp_dir);
|
|
$db =& DB::connect($dsn);
|
|
|
|
if (PEAR::isError($db)) {
|
|
$this->fail("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);
|
|
}
|
|
|
|
$db->disconnect();
|
|
unset($db);
|
|
unset($store);
|
|
unlink($temp_dir . '/file.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') ||
|
|
@dl('mysql.' . PHP_SHLIB_SUFFIX))) {
|
|
$this->pass();
|
|
return;
|
|
}
|
|
|
|
require_once 'Auth/OpenID/MySQLStore.php';
|
|
require_once 'DB.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->fail("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);
|
|
|
|
$db->query("DROP DATABASE $temp_db_name");
|
|
}
|
|
}
|
|
|
|
?>
|