code:
<?php

/*
 * Tests for the attribute exchange extension module
 */

require_once "Auth/OpenID/AX.php";
require_once "Auth/OpenID/Message.php";
require_once "Auth/OpenID/Consumer.php";
require_once "Auth/OpenID/Server.php";

class BogusAXMessage extends Auth_OpenID_AX_Message {
    var $mode = 'bogus';

    function getExtensionArgs()
    {
        return $this->_newArgs();
    }
}

class AXMessageTest extends PHPUnit_Framework_TestCase {
    function setUp()
    {
        $this->bax = new BogusAXMessage();
    }

    function test_checkMode()
    {
        $result = $this->bax->_checkMode(array());
        $this->assertTrue(Auth_OpenID_AX::isError($result));

        $result = $this->bax->_checkMode(array('mode' => 'fetch_request'));
        $this->assertTrue(Auth_OpenID_AX::isError($result));

        // does not raise an exception when the mode is right
        $result = $this->bax->_checkMode(array('mode' => $this->bax->mode));
        $this->assertTrue($result === true);
    }

    /*
     * _newArgs generates something that has the correct mode
     */
    function test_checkMode_newArgs()
    {
        $result = $this->bax->_checkMode($this->bax->_newArgs());
        $this->assertTrue($result === true);
    }
}

class AttrInfoTest extends PHPUnit_Framework_TestCase {
    function test_construct()
    {
        $type_uri = 'a uri';
        $ainfo = Auth_OpenID_AX_AttrInfo::make($type_uri);

        $this->assertEquals($type_uri, $ainfo->type_uri);
        $this->assertEquals(1, $ainfo->count);
        $this->assertFalse($ainfo->required);
        $this->assertTrue($ainfo->alias === null);
    }
}

class ToTypeURIsTest extends PHPUnit_Framework_TestCase {
    function setUp()
    {
        $this->aliases = new Auth_OpenID_NamespaceMap();
    }

    function test_empty()
    {
        foreach (array(null, '') as $empty) {
            $uris = Auth_OpenID_AX_toTypeURIs($this->aliases, $empty);
            $this->assertEquals(array(), $uris);
        }
    }

    function test_undefined()
    {
        $result = Auth_OpenID_AX_toTypeURIs($this->aliases,
                                            'http://janrain.com/');
        $this->assertTrue(Auth_OpenID_AX::isError($result));
    }

    function test_one()
    {
        $uri = 'http://janrain.com/';
        $alias = 'openid_hackers';
        $this->aliases->addAlias($uri, $alias);
        $uris = Auth_OpenID_AX_toTypeURIs($this->aliases, $alias);
        $this->assertEquals(array($uri), $uris);
    }

    function test_two()
    {
        $uri1 = 'http://janrain.com/';
        $alias1 = 'openid_hackers';
        $this->aliases->addAlias($uri1, $alias1);

        $uri2 = 'http://jyte.com/';
        $alias2 = 'openid_hack';
        $this->aliases->addAlias($uri2, $alias2);

        $uris = Auth_OpenID_AX_toTypeURIs($this->aliases,
                                          implode(',', array($alias1, $alias2)));
        $this->assertEquals(array($uri1, $uri2), $uris);
    }
}

class ParseAXValuesTest extends PHPUnit_Framework_TestCase {
    function failUnlessAXKeyError($ax_args)
    {
        $msg = new Auth_OpenID_AX_KeyValueMessage();
        $result = $msg->parseExtensionArgs($ax_args);
        $this->assertTrue(Auth_OpenID_AX::isError($result));
        $this->assertTrue($result->message);
    }

    function failUnlessAXValues($ax_args, $expected_args)
    {
        $msg = new Auth_OpenID_AX_KeyValueMessage();
        $msg->parseExtensionArgs($ax_args);
        $this->assertEquals($expected_args, $msg->data);
    }

    function test_emptyIsValid()
    {
        $this->failUnlessAXValues(array(), array());
    }

    function test_invalidAlias()
    {
        $types = array(
                       'Auth_OpenID_AX_KeyValueMessage',
                       'Auth_OpenID_AX_FetchRequest'
                       );

        $inputs = array(
                        array('type.a.b' =>  'urn:foo',
                              'count.a.b' => '1'),
                        array('type.a,b' => 'urn:foo',
                              'count.a,b' => '1'),
                        );

        foreach ($types as $typ) {
            foreach ($inputs as $input) {
                $msg = new $typ();
                $result = $msg->parseExtensionArgs($input);
                $this->assertTrue(Auth_OpenID_AX::isError($result));
            }
        }
    }

    function test_missingValueForAliasExplodes()
    {
        $this->failUnlessAXKeyError(array('type.foo' => 'urn:foo'));
    }

    function test_countPresentButNotValue()
    {
        $this->failUnlessAXKeyError(array('type.foo' => 'urn:foo',
                                          'count.foo' => '1'));
    }

    function test_invalidCountValue()
    {
        $msg = new Auth_OpenID_AX_FetchRequest();

        $result = $msg->parseExtensionArgs(
                    array('type.foo' => 'urn:foo',
                          'count.foo' => 'bogus'));

        $this->assertTrue(Auth_OpenID_AX::isError($result));
    }

    function test_requestUnlimitedValues()
    {
        $msg = new Auth_OpenID_AX_FetchRequest();

        $result = $msg->parseExtensionArgs(
               array('mode' => 'fetch_request',
                     'required' => 'foo',
                     'type.foo' => 'urn:foo',
                     'count.foo' => Auth_OpenID_AX_UNLIMITED_VALUES));

        $attrs = $msg->iterAttrs();
        $foo = $attrs[0];

        $this->assertTrue($foo->count == Auth_OpenID_AX_UNLIMITED_VALUES);
        $this->assertTrue($foo->wantsUnlimitedValues());
    }

    function test_longAlias()
    {
        // Spec minimum length is 32 characters.  This is a silly test
        // for this library, but it's here for completeness.
        $alias = str_repeat('x', Auth_OpenID_AX_MINIMUM_SUPPORTED_ALIAS_LENGTH);

        $msg = new Auth_OpenID_AX_KeyValueMessage();
        $result = $msg->parseExtensionArgs(
                                 array('type.' . $alias => 'urn:foo',
                                       'count.' . $alias => '1',
                                       'value.'.$alias.'.1' => 'first')
                                 );
        $this->assertFalse(Auth_OpenID_AX::isError($result));
    }

    function test_countPresentAndIsZero()
    {
        $this->failUnlessAXValues(
                                  array('type.foo' => 'urn:foo',
                                        'count.foo' => '0',
                                        ), array('urn:foo' => array()));
    }

    function test_singletonEmpty()
    {
        $this->failUnlessAXValues(
                                  array('type.foo' => 'urn:foo',
                                        'value.foo' => '',
                                        ), array('urn:foo' => array()));
    }

    function test_doubleAlias()
    {
        $this->failUnlessAXKeyError(
                                    array('type.foo' => 'urn:foo',
                                          'value.foo' => '',
                                          'type.bar' => 'urn:foo',
                                          'value.bar' => '',
                                          ));
    }

    function test_doubleSingleton()
    {
        $this->failUnlessAXValues(
                                  array('type.foo' => 'urn:foo',
                                        'value.foo' => '',
                                        'type.bar' => 'urn:bar',
                                        'value.bar' => '',
                                        ), array('urn:foo' => array(), 'urn:bar' => array()));
    }

    function test_singletonValue()
    {
        $this->failUnlessAXValues(
                                  array('type.foo' => 'urn:foo',
                                        'value.foo' => 'Westfall',
                                        ), array('urn:foo' => array('Westfall')));
    }
}

class FetchRequestTest extends PHPUnit_Framework_TestCase {
    function setUp()
    {
        $this->msg = new Auth_OpenID_AX_FetchRequest();
        $this->type_a = 'http://janrain.example.com/a';
        $this->alias_a = 'a';
    }

    function test_mode()
    {
        $this->assertEquals($this->msg->mode, 'fetch_request');
    }

    function test_construct()
    {
        $this->assertEquals(array(), $this->msg->requested_attributes);
        $this->assertEquals(null, $this->msg->update_url);

        $msg = new Auth_OpenID_AX_FetchRequest('hailstorm');
        $this->assertEquals(array(), $msg->requested_attributes);
        $this->assertEquals('hailstorm', $msg->update_url);
    }

    function test_add()
    {
        $uri = 'mud://puddle';

        // Not yet added:
        $this->assertFalse(in_array($uri, $this->msg->iterTypes()));

        $attr = Auth_OpenID_AX_AttrInfo::make($uri);
        $this->msg->add($attr);

        // Present after adding
        $this->assertTrue(in_array($uri, $this->msg->iterTypes()));
    }

    function test_addTwice()
    {
        $uri = 'lightning://storm';

        $attr = Auth_OpenID_AX_AttrInfo::make($uri);
        $this->msg->add($attr);
        $this->assertTrue(Auth_OpenID_AX::isError($this->msg->add($attr)));
    }

    function test_getExtensionArgs_empty()
    {
        $expected_args = array(
                               'mode' =>'fetch_request',
                               );
        $this->assertEquals($expected_args, $this->msg->getExtensionArgs());
    }

    function test_getExtensionArgs_noAlias()
    {
        $attr = Auth_OpenID_AX_AttrInfo::make('type://of.transportation');

        $this->msg->add($attr);
        $ax_args = $this->msg->getExtensionArgs();
        $found = false;
        $alias = null;

        foreach ($ax_args as $k => $v) {
            if (($v == $attr->type_uri) && (strpos($k, 'type.') === 0)) {
                $alias = substr($k, 5);
                $found = true;
                break;
            }
        }

        if (!$found) {
            $this->fail("Didn't find the type definition");
            return;
        }

        $this->failUnlessExtensionArgs(array(
            'type.' . $alias => $attr->type_uri,
            'if_available' => $alias));
    }

    function test_getExtensionArgs_alias_if_available()
    {
        $attr = Auth_OpenID_AX_AttrInfo::make(
                                              'type://of.transportation', 1, false,
                                              'transport');

        $this->msg->add($attr);
        $this->failUnlessExtensionArgs(array(
            'type.' .  $attr->alias => $attr->type_uri,
            'if_available' => $attr->alias));
    }

    function test_getExtensionArgs_alias_req()
    {
        $attr = Auth_OpenID_AX_AttrInfo::make(
            'type://of.transportation',
            1, true, 'transport');

        $this->msg->add($attr);
        $this->failUnlessExtensionArgs(array(
            'type.' . $attr->alias => $attr->type_uri,
            'required' => $attr->alias));
    }

    /*
     * Make sure that getExtensionArgs has the expected result
     *
     * This method will fill in the mode.
     */
    function failUnlessExtensionArgs($expected_args)
    {
        $expected_args['mode'] = $this->msg->mode;
        $this->assertEquals($expected_args, $this->msg->getExtensionArgs());
    }

    function test_isIterable()
    {
        $this->assertEquals(array(), $this->msg->iterAttrs());
        $this->assertEquals(array(), $this->msg->iterTypes());
    }

    function test_getRequiredAttrs_empty()
    {
        $this->assertEquals(array(), $this->msg->getRequiredAttrs());
    }

    function test_parseExtensionArgs_extraType()
    {
        $extension_args = array(
                                'mode' => 'fetch_request',
                                'type.' . $this->alias_a => $this->type_a);

        $this->assertTrue(Auth_OpenID_AX::isError(
               $this->msg->parseExtensionArgs($extension_args)));
    }

    function test_parseExtensionArgs()
    {
        $extension_args = array(
            'mode' => 'fetch_request',
            'type.' . $this->alias_a => $this->type_a,
            'if_available' => $this->alias_a);

        $this->msg->parseExtensionArgs($extension_args);
        $this->assertEquals(array($this->type_a), $this->msg->iterTypes());
        $attr_info = Auth_OpenID::arrayGet($this->msg->requested_attributes,
                                           $this->type_a);
        $this->assertTrue($attr_info);
        $this->assertFalse($attr_info->required);
        $this->assertEquals($this->type_a, $attr_info->type_uri);
        $this->assertEquals($this->alias_a, $attr_info->alias);
        $this->assertEquals(array($attr_info),
                            $this->msg->iterAttrs());
    }

    function test_extensionArgs_idempotent()
    {
        $extension_args = array(
            'mode' => 'fetch_request',
            'type.' . $this->alias_a => $this->type_a,
            'if_available' => $this->alias_a);

        $this->msg->parseExtensionArgs($extension_args);
        $this->assertEquals($extension_args, $this->msg->getExtensionArgs());

        $attr = $this->msg->requested_attributes[$this->type_a];
        $this->assertFalse($attr->required);
    }

    function test_extensionArgs_idempotent_count_required()
    {
        $extension_args = array(
                                'mode' => 'fetch_request',
                                'type.' . $this->alias_a => $this->type_a,
                                'count.' . $this->alias_a => '2',
                                'required' => $this->alias_a);

        $this->msg->parseExtensionArgs($extension_args);
        $this->assertEquals($extension_args, $this->msg->getExtensionArgs());

        $attr = $this->msg->requested_attributes[$this->type_a];
        $this->assertTrue($attr->required);
    }

    function test_extensionArgs_count1()
    {
        $extension_args = array(
            'mode' => 'fetch_request',
            'type.' . $this->alias_a => $this->type_a,
            'count.' . $this->alias_a => '1',
            'if_available' => $this->alias_a);

        $extension_args_norm = array(
            'mode' => 'fetch_request',
            'type.' . $this->alias_a => $this->type_a,
            'if_available' => $this->alias_a);

        $this->msg->parseExtensionArgs($extension_args);
        $this->assertEquals($extension_args_norm, $this->msg->getExtensionArgs());
    }

    function test_openidNoRealm()
    {
        $openid_req_msg = Auth_OpenID_Message::fromOpenIDArgs(array(
            'mode' => 'checkid_setup',
            'ns' => Auth_OpenID_OPENID2_NS,
            'ns.ax' => Auth_OpenID_AX_NS_URI,
            'ax.update_url' => 'http://different.site/path',
            'ax.mode' => 'fetch_request',
            ));
		$openid_req = new Auth_OpenID_Request();
		$openid_req->message =& $openid_req_msg;
        $result = Auth_OpenID_AX_FetchRequest::fromOpenIDRequest(
                                                     $openid_req);
        $this->assertTrue(Auth_OpenID_AX::isError($result));
    }

    function test_openidUpdateURLVerificationError()
    {
        $openid_req_msg = Auth_OpenID_Message::fromOpenIDArgs(array(
            'mode' => 'checkid_setup',
            'ns' => Auth_OpenID_OPENID2_NS,
            'realm' => 'http://example.com/realm',
            'ns.ax' => Auth_OpenID_AX_NS_URI,
            'ax.update_url' => 'http://different.site/path',
            'ax.mode' => 'fetch_request',
            ));
		$openid_req = new Auth_OpenID_Request();
		$openid_req->message =& $openid_req_msg;
        $result = Auth_OpenID_AX_FetchRequest::fromOpenIDRequest($openid_req);
        $this->assertTrue(Auth_OpenID_AX::isError($result));
    }

    function test_openidUpdateURLVerificationSuccess()
    {
        $openid_req_msg = Auth_OpenID_Message::fromOpenIDArgs(array(
            'mode' => 'checkid_setup',
            'ns' => Auth_OpenID_OPENID2_NS,
            'realm' => 'http://example.com/realm',
            'ns.ax' => Auth_OpenID_AX_NS_URI,
            'ax.update_url' => 'http://example.com/realm/update_path',
            'ax.mode' => 'fetch_request',
            ));
		$openid_req = new Auth_OpenID_Request();
		$openid_req->message =& $openid_req_msg;
        $fr = Auth_OpenID_AX_FetchRequest::fromOpenIDRequest($openid_req);
        $this->assertFalse(Auth_OpenID_AX::isError($fr));
    }

    function test_openidUpdateURLVerificationSuccessReturnTo()
    {
        $openid_req_msg = Auth_OpenID_Message::fromOpenIDArgs(array(
            'mode' => 'checkid_setup',
            'ns' => Auth_OpenID_OPENID2_NS,
            'return_to' => 'http://example.com/realm',
            'ns.ax' => Auth_OpenID_AX_NS_URI,
            'ax.update_url' => 'http://example.com/realm/update_path',
            'ax.mode' => 'fetch_request',
            ));
		$openid_req = new Auth_OpenID_Request();
		$openid_req->message =& $openid_req_msg;
        $fr = Auth_OpenID_AX_FetchRequest::fromOpenIDRequest($openid_req);
        $this->assertFalse(Auth_OpenID_AX::isError($fr));
    }
}

class FauxEndpoint {
    function FauxEndpoint() {
        $this->claimed_id = 'http://some.url/';
    }
}

class FetchResponseTest extends PHPUnit_Framework_TestCase {
    function setUp()
    {
        $this->msg = new Auth_OpenID_AX_FetchResponse();
        $this->value_a = 'monkeys';
        $this->type_a = 'http://phone.home/';
        $this->alias_a = 'robocop';
        $this->request_update_url = 'http://update.bogus/';
    }

    function test_construct()
    {
        $this->assertTrue($this->msg->update_url === null);
        $this->assertEquals(array(), $this->msg->data);
    }

    function test_getExtensionArgs_empty()
    {
        $expected_args = array(
            'mode' => 'fetch_response',
                               );
        $req = null;
        $this->assertEquals($expected_args, $this->msg->getExtensionArgs($req));
    }

    function test_getExtensionArgs_empty_request()
    {
        $expected_args = array(
            'mode' => 'fetch_response',
                               );
        $req = new Auth_OpenID_AX_FetchRequest();
        $this->assertEquals($expected_args, $this->msg->getExtensionArgs($req));
    }

    function test_getExtensionArgs_empty_request_some()
    {
        $uri = 'http://not.found/';
        $alias = 'ext0';

        $expected_args = array(
            'mode' => 'fetch_response',
            'type.' . $alias => $uri,
            'count.' . $alias => '0'
                               );
        $req = new Auth_OpenID_AX_FetchRequest();
        $req->add(Auth_OpenID_AX_AttrInfo::make('http://not.found/'));
        $this->assertEquals($expected_args, $this->msg->getExtensionArgs($req));
    }

    function test_updateUrlInResponse()
    {
        $uri = 'http://not.found/';
        $alias = 'ext0';

        $expected_args = array(
            'mode' => 'fetch_response',
            'update_url' => $this->request_update_url,
            'type.' . $alias => $uri,
            'count.' . $alias => '0'
                               );
        $req = new Auth_OpenID_AX_FetchRequest($this->request_update_url);
        $req->add(Auth_OpenID_AX_AttrInfo::make($uri));
        $this->assertEquals($expected_args, $this->msg->getExtensionArgs($req));
    }

    function test_getExtensionArgs_some_request()
    {
        $expected_args = array(
            'mode' => 'fetch_response',
            'type.' . $this->alias_a => $this->type_a,
            'value.' . $this->alias_a . '.1' => $this->value_a,
            'count.' . $this->alias_a => '1'
                               );

        $req = new Auth_OpenID_AX_FetchRequest();
        $req->add(Auth_OpenID_AX_AttrInfo::make($this->type_a, 1, false, $this->alias_a));
        $this->msg->addValue($this->type_a, $this->value_a);

        $result = $this->msg->getExtensionArgs($req);
        $this->assertEquals($expected_args, $result);
    }

    function test_getExtensionArgs_some_not_request()
    {
        $req = new Auth_OpenID_AX_FetchRequest();
        $this->msg->addValue($this->type_a, $this->value_a);
        $this->assertTrue(Auth_OpenID_AX::isError($this->msg->getExtensionArgs($req)));
    }

    function test_getSingle_success()
    {
        $req = new Auth_OpenID_AX_FetchRequest();
        $this->msg->addValue($this->type_a, $this->value_a);
        $this->assertEquals($this->value_a, $this->msg->getSingle($this->type_a));
    }

    function test_getSingle_none()
    {
        $this->assertEquals(null, $this->msg->getSingle($this->type_a));
    }

    function test_getSingle_extra()
    {
        $data = array('x', 'y');
        $this->msg->setValues($this->type_a, $data);
        $this->assertTrue(Auth_OpenID_AX::isError($this->msg->getSingle($this->type_a)));
    }

    function test_get()
    {
      $this->assertTrue(Auth_OpenID_AX::isError($this->msg->get($this->type_a)));
    }

    function test_fromSuccessResponseWithoutExtension()
    {
        $args = array(
                      'mode' => 'id_res',
                      'ns' => Auth_OpenID_OPENID2_NS
                     );
        $sf = array();
        foreach (array_keys($args) as $k) {
            array_push($sf, $k);
        }
        $msg = Auth_OpenID_Message::fromOpenIDArgs($args);
        $e = new FauxEndpoint();
        $resp = new Auth_OpenID_SuccessResponse($e, $msg, $sf);
        $ax_resp = Auth_OpenID_AX_FetchResponse::fromSuccessResponse($resp);
        $this->assertTrue($ax_resp === null);
    }

    function test_fromSuccessResponseWithoutData()
    {
        $args = array(
                      'mode' => 'id_res',
                      'ns' => Auth_OpenID_OPENID2_NS,
                      'ns.ax' => Auth_OpenID_AX_NS_URI,
                      'ax.mode' => 'fetch_response',
                     );
        $sf = array();
        foreach (array_keys($args) as $k) {
            array_push($sf, $k);
        }
        $msg = Auth_OpenID_Message::fromOpenIDArgs($args);
        $e = new FauxEndpoint();
        $resp = new Auth_OpenID_SuccessResponse($e, $msg, $sf);
        $ax_resp = Auth_OpenID_AX_FetchResponse::fromSuccessResponse($resp);
        $this->assertTrue($ax_resp === null);
    }

    function test_fromSuccessResponse()
    {
        $name = "ziggy";
        $value = "stardust";
        $uri = "http://david.bowie.name/";
        $args = array(
                      'mode' => 'id_res',
                      'ns' => Auth_OpenID_OPENID2_NS,
                      'ns.ax' => Auth_OpenID_AX_NS_URI,
                      'ax.mode' => 'fetch_response',
                      'ax.update_url' => 'http://example.com/realm/update_path',
                      'ax.type.'.$name => $uri,
                      'ax.count.'.$name => '1',
                      'ax.value.'.$name.'.1' => $value,
                     );
        $sf = array();
        foreach (array_keys($args) as $k) {
            array_push($sf, $k);
        }
        $msg = Auth_OpenID_Message::fromOpenIDArgs($args);
        $e = new FauxEndpoint();
        $resp = new Auth_OpenID_SuccessResponse($e, $msg, $sf);
        $ax_resp = Auth_OpenID_AX_FetchResponse::fromSuccessResponse($resp, false);
        $this->assertFalse($ax_resp === null);
        $this->assertTrue(is_a($ax_resp, 'Auth_OpenID_AX_FetchResponse'));
        $values = $ax_resp->get($uri);
        $this->assertEquals(array($value), $values);
    }
}

class StoreRequestTest extends PHPUnit_Framework_TestCase {
    function setUp()
    {
        $this->msg = new Auth_OpenID_AX_StoreRequest();
        $this->type_a = 'http://three.count/';
        $this->alias_a = 'juggling';
    }

    function test_construct()
    {
        $this->assertEquals(array(), $this->msg->data);
    }

    function test_getExtensionArgs_empty()
    {
        $args = $this->msg->getExtensionArgs();
        $expected_args = array(
            'mode' => 'store_request',
                               );
        $this->assertEquals($expected_args, $args);
    }

    function test_getExtensionArgs_nonempty()
    {
        $data = array('foo', 'bar');
        $this->msg->setValues($this->type_a, $data);
        $aliases = new Auth_OpenID_NamespaceMap();
        $aliases->addAlias($this->type_a, $this->alias_a);
        $args = $this->msg->getExtensionArgs($aliases);
        $expected_args = array(
            'mode' => 'store_request',
            'type.' . $this->alias_a => $this->type_a,
            'count.' . $this->alias_a => '2',
            sprintf('value.%s.1', $this->alias_a) => 'foo',
            sprintf('value.%s.2', $this->alias_a) => 'bar',
                               );
        $this->assertEquals($expected_args, $args);
    }
}

class StoreResponseTest extends PHPUnit_Framework_TestCase {
    function test_success()
    {
        $msg = new Auth_OpenID_AX_StoreResponse();
        $this->assertTrue($msg->succeeded());
        $this->assertFalse($msg->error_message);
        $this->assertEquals(array('mode' => 'store_response_success'),
                            $msg->getExtensionArgs());
    }

    function test_fail_nomsg()
    {
        $msg = new Auth_OpenID_AX_StoreResponse(false);
        $this->assertFalse($msg->succeeded());
        $this->assertFalse($msg->error_message);
        $this->assertEquals(array('mode' => 'store_response_failure'),
                            $msg->getExtensionArgs());
    }

    function test_fail_msg()
    {
        $reason = 'no reason, really';
        $msg = new Auth_OpenID_AX_StoreResponse(false, $reason);
        $this->assertFalse($msg->succeeded());
        $this->assertEquals($reason, $msg->error_message);
        $this->assertEquals(array('mode' => 'store_response_failure',
                                  'error' => $reason), $msg->getExtensionArgs());
    }
}

class Tests_Auth_OpenID_AX extends PHPUnit_Framework_TestSuite {
    function getName()
    {
        return "Tests_Auth_OpenID_AX";
    }

    function Tests_Auth_OpenID_AX()
    {
        $this->addTestSuite('StoreResponseTest');
        $this->addTestSuite('StoreRequestTest');
        $this->addTestSuite('FetchResponseTest');
        $this->addTestSuite('FetchRequestTest');
        $this->addTestSuite('ParseAXValuesTest');
        $this->addTestSuite('ToTypeURIsTest');
        $this->addTestSuite('AttrInfoTest');
        $this->addTestSuite('AXMessageTest');
    }
}


code:
<?php

/**
 * Tests for the Association implementation.
 *
 * PHP versions 4 and 5
 *
 * LICENSE: See the COPYING file included in this distribution.
 *
 * @package OpenID
 * @author JanRain, Inc. <openid@janrain.com>
 * @copyright 2005-2008 Janrain, Inc.
 * @license http://www.apache.org/licenses/LICENSE-2.0 Apache
 */

require_once 'Auth/OpenID/Association.php';

class Tests_Auth_OpenID_Association extends PHPUnit_Framework_TestCase {
    function test_me()
    {
        $issued = time();
        $lifetime = 600;
        $assoc = new Auth_OpenID_Association('handle', 'secret', $issued,
                                            $lifetime, 'HMAC-SHA1');
        $s = $assoc->serialize();
        $assoc2 = Auth_OpenID_Association::deserialize(
            'Auth_OpenID_Association', $s);

        if ($assoc2 === null) {
            $this->fail('deserialize returned null');
        } else {
            $this->assertTrue($assoc2->equal($assoc));
        }
    }
    function test_me256()
    {
        if(!Auth_OpenID_HMACSHA256_SUPPORTED) return;
        $issued = time();
        $lifetime = 600;
        $assoc = new Auth_OpenID_Association('handle', 'secret', $issued,
                                            $lifetime, 'HMAC-SHA256');
        $s = $assoc->serialize();
        $assoc2 = Auth_OpenID_Association::deserialize(
            'Auth_OpenID_Association', $s);

        if ($assoc2 === null) {
            $this->fail('deserialize returned null');
        } else {
            $this->assertTrue($assoc2->equal($assoc));
        }
    }
}

repo_name: ksuudilla/gnu

license: mit


code:
<?php

require_once "Tests/Auth/OpenID/TestUtil.php";
require_once "Tests/Auth/OpenID/MemStore.php";

require_once "Auth/OpenID/Message.php";
require_once "Auth/OpenID/Server.php";
require_once "Auth/OpenID/Consumer.php";
require_once "Auth/OpenID/Association.php";

// Some values we can use for convenience (see mkAssocResponse)
global $association_response_values;
$association_response_values = array(
    'expires_in' => '1000',
    'assoc_handle' => 'a handle',
    'assoc_type' => 'a type',
    'session_type' => 'a session type',
    'ns' => Auth_OpenID_OPENID2_NS
    );

/**
 * Build an association response message that contains the specified
 * subset of keys. The values come from association_response_values.
 *
 * This is useful for testing for missing keys and other times that we
 * don't care what the values are.
 */
function mkAssocResponse($keys)
{
    global $association_response_values;

    $args = array();

    foreach ($keys as $key) {
        $args[$key] = $association_response_values[$key];
    }

    return Auth_OpenID_Message::fromOpenIDArgs($args);
}

class Tests_Auth_OpenID_AssociationResponse extends PHPUnit_Framework_TestCase {
    function setUp()
    {
        $this->store = new Tests_Auth_OpenID_MemStore();
        $this->consumer = new Auth_OpenID_GenericConsumer($this->store);
        $this->endpoint = new Auth_OpenID_ServiceEndpoint();
    }

    function failUnlessProtocolError($thing)
    {
        $this->assertTrue(Auth_OpenID::isFailure($thing));
    }

    function _run($keys)
    {
        $msg = mkAssocResponse($keys);
        $dumb = null;
        $this->assertTrue(Auth_OpenID::isFailure($this->consumer->_extractAssociation($msg, $dumb)));
    }
}

/**
 * Test for returning an error upon missing fields in association
 * responses for OpenID 2
 */
class TestExtractAssociationMissingFieldsOpenID2 extends Tests_Auth_OpenID_AssociationResponse {

    function test_noFields_openid2()
    {
        $this->_run(array('ns'));
    }

    function test_missingExpires_openid2()
    {
        $this->_run(array('assoc_handle', 'assoc_type', 'session_type', 'ns'));
    }

    function test_missingHandle_openid2()
    {
        $this->_run(array('expires_in', 'assoc_type', 'session_type', 'ns'));
    }

    function test_missingAssocType_openid2()
    {
        $this->_run(array('expires_in', 'assoc_handle', 'session_type', 'ns'));
    }

    function test_missingSessionType_openid2()
    {
        $this->_run(array('expires_in', 'assoc_handle', 'assoc_type', 'ns'));
    }
}

/**
 * Test for returning an error upon missing fields in association
 * responses for OpenID 2
 */
class TestExtractAssociationMissingFieldsOpenID1 extends Tests_Auth_OpenID_AssociationResponse {
    function test_noFields_openid1()
    {
        $this->_run(array());
    }

    function test_missingExpires_openid1()
    {
        $this->_run(array('assoc_handle', 'assoc_type'));
    }

    function test_missingHandle_openid1()
    {
        $this->_run(array('expires_in', 'assoc_type'));
    }

    function test_missingAssocType_openid1()
    {
        $this->_run(array('expires_in', 'assoc_handle'));
    }
}

class DummyAssocationSession {
    function DummyAssocationSession($session_type, $allowed_assoc_types=array())
    {
        $this->session_type = $session_type;
        $this->allowed_assoc_types = $allowed_assoc_types;
    }
}

class ExtractAssociationSessionTypeMismatch extends Tests_Auth_OpenID_AssociationResponse {
    function _run($requested_session_type, $response_session_type, $openid1=false)
    {
        global $association_response_values;

        $assoc_session = new DummyAssocationSession($requested_session_type);
        $keys = array_keys($association_response_values);
        if ($openid1) {
            if (in_array('ns', $keys)) {
                unset($keys[array_search('ns', $keys)]);
            }
        }

        $msg = mkAssocResponse($keys);
        $msg->setArg(Auth_OpenID_OPENID_NS, 'session_type',
                     $response_session_type);
        $this->assertTrue(
           $this->consumer->_extractAssociation($msg, $assoc_session) === null);
    }

    function test_typeMismatchNoEncBlank_openid2()
    {
        $this->_run('no-encryption', '');
    }

    function test_typeMismatchDHSHA1NoEnc_openid2()
    {
        $this->_run('DH-SHA1', 'no-encryption');
    }

    function test_typeMismatchDHSHA256NoEnc_openid2()
    {
        $this->_run('DH-SHA256', 'no-encryption');
    }

    function test_typeMismatchNoEncDHSHA1_openid2()
    {
        $this->_run('no-encryption', 'DH-SHA1');
    }

    function test_typeMismatchDHSHA1NoEnc_openid1()
    {
        $this->_run('DH-SHA1', 'DH-SHA256', true);
    }

    function test_typeMismatchDHSHA256NoEnc_openid1()
    {
        $this->_run('DH-SHA256', 'DH-SHA1', true);
    }

    function test_typeMismatchNoEncDHSHA1_openid1()
    {
        $this->_run('no-encryption', 'DH-SHA1', true);
    }
}

class TestOpenID1AssociationResponseSessionType extends Tests_Auth_OpenID_AssociationResponse {
    function _run($expected_session_type, $session_type_value)
    {
        // Create a Message with just 'session_type' in it, since
        // that's all this function will use. 'session_type' may be
        // absent if it's set to None.
        $args = array();
        if ($session_type_value !== null) {
            $args['session_type'] = $session_type_value;
        }
        $message = Auth_OpenID_Message::fromOpenIDArgs($args);
        $this->assertTrue($message->isOpenID1());

        $actual_session_type = $this->consumer->_getOpenID1SessionType($message);
        $error_message = sprintf('Returned sesion type parameter %s was expected ' .
                                 'to yield session type %s, but yielded %s',
                                 $session_type_value, $expected_session_type,
                                 $actual_session_type);
        $this->assertEquals(
                            $expected_session_type,
                            $actual_session_type,
                            $error_message);
    }

    function test_none()
    {
        $this->_run('no-encryption', null);
    }

    function test_empty()
    {
        $this->_run('no-encryption', '');
    }

    function test_explicitNoEncryption()
    {
        $this->_run('no-encryption', 'no-encryption');
    }

    function test_dhSHA1()
    {
        $this->_run('DH-SHA1', 'DH-SHA1');
    }

    // DH-SHA256 is not a valid session type for OpenID1, but this
    // function does not test that. This is mostly just to make sure
    // that it will pass-through stuff that is not explicitly handled,
    // so it will get handled the same way as it is handled for OpenID
    // 2
    function test_dhSHA256()
    {
        $this->_run('DH-SHA256', 'DH-SHA256');
    }
}

class DummyAssociationSession {
    var $secret = "shh! don't tell!";
    var $extract_secret_called = false;
    var $session_type = null;
    var $allowed_assoc_types = null;

    function extractSecret($message)
    {
        $this->extract_secret_called = true;
        return $this->secret;
    }
}

class TestInvalidFields extends Tests_Auth_OpenID_AssociationResponse {
    function setUp()
    {
        parent::setUp();
        $this->session_type = 'testing-session';

        // This must something that works for Association.fromExpiresIn
        $this->assoc_type = 'HMAC-SHA1';

        $this->assoc_handle = 'testing-assoc-handle';

        // These arguments should all be valid
        $this->assoc_response = Auth_OpenID_Message::fromOpenIDArgs(array(
            'expires_in' => '1000',
            'assoc_handle' => $this->assoc_handle,
            'assoc_type' => $this->assoc_type,
            'session_type' => $this->session_type,
            'ns' => Auth_OpenID_OPENID2_NS,
            ));

        $this->assoc_session = new DummyAssociationSession();

        // Make the session for the response's session type
        $this->assoc_session->session_type = $this->session_type;
        $this->assoc_session->allowed_assoc_types = array($this->assoc_type);
    }

    function test_worksWithGoodFields()
    {
        // Handle a full successful association response
        $assoc = $this->consumer->_extractAssociation(
                   $this->assoc_response, $this->assoc_session);
        $this->assertTrue($this->assoc_session->extract_secret_called);
        $this->assertEquals($this->assoc_session->secret, $assoc->secret);
        $this->assertEquals(1000, $assoc->lifetime);
        $this->assertEquals($this->assoc_handle, $assoc->handle);
        $this->assertEquals($this->assoc_type, $assoc->assoc_type);
    }

    function test_badAssocType()
    {
        // Make sure that the assoc type in the response is not valid
        // for the given session.
        $this->assoc_session->allowed_assoc_types = array();
        $this->assertTrue(
             $this->consumer->_extractAssociation($this->assoc_response,
                                                  $this->assoc_session) === null);
    }

    function test_badExpiresIn()
    {
        // Invalid value for expires_in should cause failure
        $this->assoc_response->setArg(Auth_OpenID_OPENID_NS, 'expires_in', 'forever');
        $assoc = $this->consumer->_extractAssociation($this->assoc_response,
                                                      $this->assoc_session);
        $this->assertTrue(Auth_OpenID::isFailure($assoc));
    }
}

class TestExtractAssociationDiffieHellman extends Tests_Auth_OpenID_AssociationResponse {
    var $secret = 'xxxxxxxxxxxxxxxxxxxx';

    function _setUpDH()
    {
        list($sess, $message) = $this->consumer->_createAssociateRequest(
                                  $this->endpoint, 'HMAC-SHA1', 'DH-SHA1');

        // XXX: this is testing _createAssociateRequest
        $this->assertEquals($this->endpoint->compatibilityMode(),
                            $message->isOpenID1());

        $server_sess = Auth_OpenID_DiffieHellmanSHA1ServerSession::fromMessage($message);
        $server_resp = $server_sess->answer($this->secret);
        $server_resp['assoc_type'] = 'HMAC-SHA1';
        $server_resp['assoc_handle'] = 'handle';
        $server_resp['expires_in'] = '1000';
        $server_resp['session_type'] = 'DH-SHA1';
        return array($sess, Auth_OpenID_Message::fromOpenIDArgs($server_resp));
    }

    function test_success()
    {
        list($sess, $server_resp) = $this->_setUpDH();
        $ret = $this->consumer->_extractAssociation($server_resp, $sess);
        $this->assertTrue($ret !== null);
        $this->assertEquals($ret->assoc_type, 'HMAC-SHA1');
        $this->assertEquals($ret->secret, $this->secret);
        $this->assertEquals($ret->handle, 'handle');
        $this->assertEquals($ret->lifetime, 1000);
    }

    function test_openid2success()
    {
        // Use openid 2 type in endpoint so _setUpDH checks
        // compatibility mode state properly
        $this->endpoint->type_uris = array(Auth_OpenID_TYPE_2_0,
                                           Auth_OpenID_TYPE_1_1);
        $this->test_success();
    }

    /**
     * Can't run this test because the base64 decoder is broken.
     */
    /*
    function test_badDHValues()
    {
        list($sess, $server_resp) = $this->_setUpDH();
        $server_resp->setArg(Auth_OpenID_OPENID_NS, 'enc_mac_key', "\x00\x00\x00");
        $this->assertTrue($this->consumer->_extractAssociation($server_resp, $sess) === null);
    }
    */
}

global $Tests_Auth_OpenID_AssociationResponse_other;
$Tests_Auth_OpenID_AssociationResponse_other = array(
                                                     new TestInvalidFields(),
                                                     new TestOpenID1AssociationResponseSessionType(),
                                                     new ExtractAssociationSessionTypeMismatch(),
                                                     new TestExtractAssociationMissingFieldsOpenID1(),
                                                     new TestExtractAssociationMissingFieldsOpenID2()
                                                     );

if (!defined('Auth_OpenID_NO_MATH_SUPPORT')) {
    $Tests_Auth_OpenID_AssociationResponse_other[] = new TestExtractAssociationDiffieHellman();
}


code:
<?php

require_once 'Tests/Auth/OpenID/TestUtil.php';

require_once 'Auth/OpenID/Association.php';
require_once 'Auth/OpenID/Consumer.php';

class AuthRequest_DummyEndpoint {
    var $preferred_namespace = null;
    var $local_id = null;
    var $server_url = null;
    var $is_op_identifier = false;

    function preferredNamespace()
    {
        return $this->preferred_namespace;
    }

    function getLocalID()
    {
        return $this->local_id;
    }

    function isOPIdentifier()
    {
        return $this->is_op_identifier;
    }
}

class AuthRequest_DummyAssoc {
    var $handle = "assoc-handle";
}

/**
 * Base for AuthRequest tests for OpenID 1 and 2.
 */
class TestAuthRequestMixin extends OpenIDTestMixin {

    var $preferred_namespace = null;
    var $immediate = false;
    var $expected_mode = 'checkid_setup';

    function setUp()
    {
        $this->endpoint = new AuthRequest_DummyEndpoint();
        $this->endpoint->local_id = 'http://server.unittest/joe';
        $this->endpoint->claimed_id = 'http://joe.vanity.example/';
        $this->endpoint->server_url = 'http://server.unittest/';
        $this->endpoint->preferred_namespace = $this->preferred_namespace;
        $this->realm = 'http://example/';
        $this->return_to = 'http://example/return/';
        $this->assoc = new AuthRequest_DummyAssoc();
        $this->authreq = new Auth_OpenID_AuthRequest($this->endpoint, $this->assoc);
    }

    function failUnlessAnonymous($msg)
    {
        foreach (array('claimed_id', 'identity') as $key) {
            $this->failIfOpenIDKeyExists($msg, $key);
        }
    }

    function failUnlessHasRequiredFields($msg)
    {
        $this->assertEquals($this->preferred_namespace,
                               $this->authreq->message->getOpenIDNamespace());

        $this->assertEquals($this->preferred_namespace,
                               $msg->getOpenIDNamespace());

        $this->failUnlessOpenIDValueEquals($msg, 'mode',
                                           $this->expected_mode);

        // Implement these in subclasses because they depend on
        // protocol differences!
        $this->failUnlessHasRealm($msg);
        $this->failUnlessIdentifiersPresent($msg);
    }

    // TESTS

    function test_checkNoAssocHandle()
    {
        $this->authreq->assoc = null;
        $msg = $this->authreq->getMessage($this->realm, $this->return_to,
                                          $this->immediate);

        $this->failIfOpenIDKeyExists($msg, 'assoc_handle');
    }

    function test_checkWithAssocHandle()
    {
        $msg = $this->authreq->getMessage($this->realm, $this->return_to,
                                         $this->immediate);

        $this->failUnlessOpenIDValueEquals($msg, 'assoc_handle',
                                           $this->assoc->handle);
    }

    function test_addExtensionArg()
    {
        $this->authreq->addExtensionArg('bag:', 'color', 'brown');
        $this->authreq->addExtensionArg('bag:', 'material', 'paper');
        $this->assertTrue($this->authreq->message->namespaces->contains('bag:'));
        $this->assertEquals($this->authreq->message->getArgs('bag:'),
                            array('color' => 'brown',
                                  'material' => 'paper'));
        $msg = $this->authreq->getMessage($this->realm, $this->return_to,
                                          $this->immediate);

        // XXX: this depends on the way that Message assigns
        // namespaces. Really it doesn't care that it has alias "0",
        // but that is tested anyway
        $post_args = $msg->toPostArgs();
        $this->assertEquals('brown', $post_args['openid.ext0.color']);
        $this->assertEquals('paper', $post_args['openid.ext0.material']);
    }

    function test_standard()
    {
        $msg = $this->authreq->getMessage($this->realm, $this->return_to,
                                         $this->immediate);

        $this->failUnlessHasIdentifiers(
             $msg, $this->endpoint->local_id,
             $this->endpoint->claimed_id);
    }
}

class TestAuthRequestOpenID2 extends TestAuthRequestMixin {
    var $preferred_namespace = Auth_OpenID_OPENID2_NS;

    function failUnlessHasRealm($msg)
    {
        // check presence of proper realm key and absence of the wrong
        // one.
        $this->failUnlessOpenIDValueEquals($msg, 'realm', $this->realm);
        $this->failIfOpenIDKeyExists($msg, 'trust_root');
    }

    function failUnlessIdentifiersPresent($msg)
    {
        $identity_present = $msg->hasKey(Auth_OpenID_OPENID_NS, 'identity');
        $claimed_present = $msg->hasKey(Auth_OpenID_OPENID_NS, 'claimed_id');

        $this->assertEquals($claimed_present, $identity_present);
    }

    function failUnlessHasIdentifiers($msg, $op_specific_id, $claimed_id)
    {
        $this->failUnlessOpenIDValueEquals($msg, 'identity', $op_specific_id);
        $this->failUnlessOpenIDValueEquals($msg, 'claimed_id', $claimed_id);
    }

    // TESTS

    function test_markup_checkidImmediate()
    {
        $result = $this->authreq->formMarkup($this->realm,
                                             null, true);
        $this->assertTrue(Auth_OpenID::isFailure($result));
    }

    function test_markup_returnToArgs()
    {
        $this->authreq->return_to_args = array('extra' => 'args');
        $result = $this->authreq->formMarkup($this->realm,
                                             null, false);
        $this->assertTrue(Auth_OpenID::isFailure($result));
    }

    function test_setAnonymousWorksForOpenID2()
    {
        // OpenID AuthRequests should be able to set 'anonymous' to true.
        $this->assertTrue($this->authreq->message->isOpenID2());
        $this->assertTrue($this->authreq->setAnonymous(true));
        $this->assertTrue($this->authreq->setAnonymous(false));
    }

    function test_userAnonymousIgnoresIdentfier()
    {
        $this->authreq->setAnonymous(true);
        $msg = $this->authreq->getMessage($this->realm, $this->return_to,
                                          $this->immediate);
        $this->failUnlessHasRequiredFields($msg);
        $this->failUnlessAnonymous($msg);
    }

    function test_opAnonymousIgnoresIdentifier()
    {
        $this->endpoint->is_op_identifier = true;
        $this->authreq->setAnonymous(true);
        $msg = $this->authreq->getMessage($this->realm, $this->return_to,
                                          $this->immediate);
        $this->failUnlessHasRequiredFields($msg);
        $this->failUnlessAnonymous($msg);
    }

    function test_opIdentifierSendsIdentifierSelect()
    {
        $this->endpoint->is_op_identifier = true;
        $msg = $this->authreq->getMessage($this->realm, $this->return_to,
                                          $this->immediate);
        $this->failUnlessHasRequiredFields($msg);
        $this->failUnlessHasIdentifiers($msg,
                                        Auth_OpenID_IDENTIFIER_SELECT,
                                        Auth_OpenID_IDENTIFIER_SELECT);
    }
}

class TestAuthRequestOpenID1 extends TestAuthRequestMixin {
    var $preferred_namespace = Auth_OpenID_OPENID1_NS;

    function setUpEndpoint()
    {
        parent::setUpEndpoint();
        $this->endpoint->preferred_namespace = Auth_OpenID_OPENID1_NS;
    }

    function failUnlessHasIdentifiers($msg, $op_specific_id, $claimed_id)
    {
        // Make sure claimed_is is *absent* in request.
        $this->failUnlessOpenIDValueEquals($msg, 'identity', $op_specific_id);
        $this->failIfOpenIDKeyExists($msg, 'claimed_id');
    }

    function failUnlessIdentifiersPresent($msg)
    {
        $this->failIfOpenIDKeyExists($msg, 'claimed_id');
        $this->assertTrue($msg->hasKey(Auth_OpenID_OPENID_NS, 'identity'));
    }

    function failUnlessHasRealm($msg)
    {
        // check presence of proper realm key and absence of the wrong
        // one.
        $this->failUnlessOpenIDValueEquals($msg, 'trust_root', $this->realm);
        $this->failIfOpenIDKeyExists($msg, 'realm');
    }

    // TESTS

    function test_markup_missingReturnTo()
    {
        $result = $this->authreq->formMarkup($this->realm,
                                             null, false);
        $this->assertTrue(Auth_OpenID::isFailure($result));
    }

    function test_setAnonymousFailsForOpenID1()
    {
        // OpenID 1 requests MUST NOT be able to set anonymous to True
        $this->assertTrue($this->authreq->message->isOpenID1());
        $this->assertFalse($this->authreq->setAnonymous(true));
        $this->assertTrue($this->authreq->setAnonymous(false));
    }

    function test_identifierSelect()
    {
        // Identfier select SHOULD NOT be sent, but this pathway is in
        // here in case some special discovery stuff is done to
        // trigger it with OpenID 1. If it is triggered, it will send
        // identifier_select just like OpenID 2.
        $this->endpoint->is_op_identifier = true;
        $msg = $this->authreq->getMessage($this->realm, $this->return_to,
                                          $this->immediate);
        $this->failUnlessHasRequiredFields($msg);
        $this->assertEquals(Auth_OpenID_IDENTIFIER_SELECT,
                            $msg->getArg(Auth_OpenID_OPENID1_NS,
                                         'identity'));
    }
}

class TestAuthRequestOpenID1Immediate extends TestAuthRequestOpenID1 {
    var $immediate = true;
    var $expected_mode = 'checkid_immediate';
}

class TestAuthRequestOpenID2Immediate extends TestAuthRequestOpenID2 {
    var $immediate = true;
    var $expected_mode = 'checkid_immediate';
}

class Tests_Auth_OpenID_AuthRequest extends PHPUnit_Framework_TestSuite {

    function getName()
    {
        return "Tests_Auth_OpenID_AuthRequest";
    }

    function Tests_Auth_OpenID_AuthRequest()
    {
        $this->addTestSuite('TestAuthRequestOpenID1');
        $this->addTestSuite('TestAuthRequestOpenID1Immediate');
        $this->addTestSuite('TestAuthRequestOpenID2');
        $this->addTestSuite('TestAuthRequestOpenID2Immediate');
    }
}


code:
<?php

/**
 * Tests for the BigMath functions.
 *
 * PHP versions 4 and 5
 *
 * LICENSE: See the COPYING file included in this distribution.
 *
 * @package OpenID
 * @author JanRain, Inc. <openid@janrain.com>
 * @copyright 2005-2008 Janrain, Inc.
 * @license http://www.apache.org/licenses/LICENSE-2.0 Apache
 */

require_once 'Auth/OpenID/BigMath.php';
require_once 'Tests/Auth/OpenID/TestUtil.php';

class Tests_Auth_OpenID_BinLongConvertRnd extends PHPUnit_Framework_TestCase {
    var $lib;
    var $max;

    function Tests_Auth_OpenID_BinLongConvertRnd($lib, $max)
    {
        $this->lib =& $lib;
        $this->max = $max;
    }

    function runTest()
    {
        $n = $this->lib->init(0);
        foreach (range(0, 9) as $i) {
            $rnd = $this->lib->rand($this->max);
            $n = $this->lib->add($n, $rnd);
        }
        $s = $this->lib->longToBinary($n);
        $this->assertTrue(is_string($s));
        $n_prime = $this->lib->binaryToLong($s);
        $this->assertEquals($this->lib->cmp($n, $n_prime), 0);
    }
}

class Tests_Auth_OpenID_BinLongConvert extends PHPUnit_Framework_TestCase {
    var $lib;
    var $bin;
    var $lng;

    function Tests_Auth_OpenID_BinLongConvert($lib, $bin, $lng)
    {
        $this->lib =& $lib;
        $this->bin = $bin;
        $this->lng = $lng;
    }

    function runTest()
    {
        $n_prime = $this->lib->binaryToLong($this->bin);
        $s_prime = $this->lib->longToBinary($this->lng);
        $this->assertEquals($this->lib->cmp($this->lng, $n_prime), 0);
        $this->assertTrue($this->bin == $s_prime);
    }
}

class Tests_Auth_OpenID_Base64ToLong extends PHPUnit_Framework_TestCase {
    var $num;
    var $b64;
    var $lib;

    function Tests_Auth_OpenID_Base64ToLong($lib, $b64, $num)
    {
        $this->lib = $lib;
        $this->b64 = $b64;
        $this->num = $num;
    }

    function runTest()
    {
        $actual = $this->lib->base64ToLong($this->b64);
        $this->assertTrue($this->lib->cmp($this->num, $actual) == 0);
    }
}

class Tests_Auth_OpenID_LongToBase64 extends Tests_Auth_OpenID_Base64ToLong {
    function Tests_Auth_OpenID_LongToBase64($lib, $b64, $num)
    {
        $this->lib = $lib;
        $this->b64 = $b64;
        $this->num = $num;
    }

    function runTest()
    {
        $actual = $this->lib->longToBase64($this->num);
        $this->assertEquals($this->b64, $actual);
    }
}

class Tests_Auth_OpenID_Rand extends PHPUnit_Framework_TestCase {
    function Tests_Auth_OpenID_Rand($lib)
    {
        $this->lib =& $lib;
    }

    function runTest()
    {
        $stop = $this->lib->pow(2, 128);
        $a = $this->lib->rand($stop);
        $b = $this->lib->rand($stop);

        $this->assertFalse($this->lib->cmp($b, $a) == 0, "Same: $a $b");

        $n = $this->lib->init(Tests_Auth_OpenID_maxint());
        $n = $this->lib->add($n, 1);

        // Make sure that we can generate random numbers that are
        // larger than platform int size
        $result = $this->lib->rand($n);

        // What can we say about the result?
    }
}

/**
 * Computes the maximum integer value for this PHP installation.
 *
 * @return int $max_int_value The maximum integer value for this
 * PHP installation
 */
function Tests_Auth_OpenID_maxint()
{
    /* assumes largest integer is of form 2^n - 1 */
    $to_test = pow(2, 16);
    while (1) {
        $last = $to_test;
        $to_test = 2 * $to_test;
        if (($to_test < $last) || (!is_int($to_test))) {
            return($last + ($last - 1));
        }
    }
}

class Tests_Auth_OpenID_BigMath extends PHPUnit_Framework_TestSuite {
    function _parseBase64Data()
    {
        $lines = Tests_Auth_OpenID_readlines('n2b64');

        $data = array();
        foreach ($lines as $line) {
            $line = trim($line);
            if (!$line) {
                continue;
            }
            list($b64, $ascii) = explode(' ', $line);
            $data[$b64] = $ascii;
        }
        return $data;
    }

    function _addB64Tests()
    {
        $lib = Auth_OpenID_getMathLib();
        $count = defined('Tests_Auth_OpenID_thorough') ? -1 : 2;
        $data = $this->_parseBase64Data();
        foreach ($data as $b64 => $num_s) {
            // Only test the first few unless thorough is defined
            if (strlen($num_s) > 5) {
                if ($count == 0) {
                    break;
                } else {
                    $count -= 1;
                }
            }
            $num = $lib->init($num_s);
            $test = new Tests_Auth_OpenID_Base64ToLong($lib, $b64, $num);
            $test->setName("B64->Long $num_s");
            $this->addTest($test);

            $test = new Tests_Auth_OpenID_LongToBase64($lib, $b64, $num);
            $test->setName("Long->B64 $num_s");
            $this->addTest($test);
        }
    }

    function _addBinLongTests()
    {
        $lib =& Auth_OpenID_getMathLib();
        $max = Tests_Auth_OpenID_maxint();
        $upper = defined('Tests_Auth_OpenID_thorough') ? 499 : 3;

        foreach (range(0, $upper) as $iteration) {
            $test = new Tests_Auth_OpenID_BinLongConvertRnd($lib, $max);
            $test->setName("BinLongConvertRnd " . strval($iteration));
            $this->addTest($test);
        }

        $cases = array(
                       array("\x00", 0),
                       array("\x01", 1),
                       array("\x7F", 127),
                       array("\x00\x80", 128),
                       array("\x00\x81", 129),
                       array("\x00\xFF", 255),
                       array("\x00\x80\x00", 32768),
                       array("OpenID is cool",
                             "1611215304203901150134421257416556")
                       );

        foreach ($cases as $case) {
            list($bin, $lng_m) = $case;
            $lng = $lib->init($lng_m);
            $test = new Tests_Auth_OpenID_BinLongConvert($lib, $bin, $lng);
            $test->setName('BinLongConvert ' . bin2hex($bin));
            $this->addTest($test);
        }

    }

    function Tests_Auth_OpenID_BigMath($name)
    {
        $this->setName($name);

        if (defined('Auth_OpenID_NO_MATH_SUPPORT')) {
          return;
        }

        $this->_addB64Tests();
        $this->_addBinLongTests();
        $test = new Tests_Auth_OpenID_Rand(Auth_OpenID_getMathLib());
        $test->setName('Big number rand');
        $this->addTest($test);
    }
}