obsolete.ChilliProject/vendor/gems/ruby-openid-2.1.4/test/test_associationmanager.rb

918 lines
30 KiB
Ruby

require "openid/consumer/associationmanager"
require "openid/association"
require "openid/dh"
require "openid/util"
require "openid/cryptutil"
require "openid/message"
require "openid/store/memory"
require "test/unit"
require "util"
require "time"
module OpenID
class DHAssocSessionTest < Test::Unit::TestCase
def test_sha1_get_request
# Initialized without an explicit DH gets defaults
sess = Consumer::DiffieHellmanSHA1Session.new
assert_equal(['dh_consumer_public'], sess.get_request.keys)
assert_nothing_raised do
Util::from_base64(sess.get_request['dh_consumer_public'])
end
end
def test_sha1_get_request_custom_dh
dh = DiffieHellman.new(1299721, 2)
sess = Consumer::DiffieHellmanSHA1Session.new(dh)
req = sess.get_request
assert_equal(['dh_consumer_public', 'dh_modulus', 'dh_gen'].sort,
req.keys.sort)
assert_equal(dh.modulus, CryptUtil.base64_to_num(req['dh_modulus']))
assert_equal(dh.generator, CryptUtil.base64_to_num(req['dh_gen']))
assert_nothing_raised do
Util::from_base64(req['dh_consumer_public'])
end
end
end
module TestDiffieHellmanResponseParametersMixin
def setup
session_cls = self.class.session_cls
# Pre-compute DH with small prime so tests run quickly.
@server_dh = DiffieHellman.new(100389557, 2)
@consumer_dh = DiffieHellman.new(100389557, 2)
# base64(btwoc(g ^ xb mod p))
@dh_server_public = CryptUtil.num_to_base64(@server_dh.public)
@secret = CryptUtil.random_string(session_cls.secret_size)
enc_mac_key_unencoded =
@server_dh.xor_secret(session_cls.hashfunc,
@consumer_dh.public,
@secret)
@enc_mac_key = Util.to_base64(enc_mac_key_unencoded)
@consumer_session = session_cls.new(@consumer_dh)
@msg = Message.new(self.class.message_namespace)
end
def test_extract_secret
@msg.set_arg(OPENID_NS, 'dh_server_public', @dh_server_public)
@msg.set_arg(OPENID_NS, 'enc_mac_key', @enc_mac_key)
extracted = @consumer_session.extract_secret(@msg)
assert_equal(extracted, @secret)
end
def test_absent_serve_public
@msg.set_arg(OPENID_NS, 'enc_mac_key', @enc_mac_key)
assert_raises(Message::KeyNotFound) {
@consumer_session.extract_secret(@msg)
}
end
def test_absent_mac_key
@msg.set_arg(OPENID_NS, 'dh_server_public', @dh_server_public)
assert_raises(Message::KeyNotFound) {
@consumer_session.extract_secret(@msg)
}
end
def test_invalid_base64_public
@msg.set_arg(OPENID_NS, 'dh_server_public', 'n o t b a s e 6 4.')
@msg.set_arg(OPENID_NS, 'enc_mac_key', @enc_mac_key)
assert_raises(ArgumentError) {
@consumer_session.extract_secret(@msg)
}
end
def test_invalid_base64_mac_key
@msg.set_arg(OPENID_NS, 'dh_server_public', @dh_server_public)
@msg.set_arg(OPENID_NS, 'enc_mac_key', 'n o t base 64')
assert_raises(ArgumentError) {
@consumer_session.extract_secret(@msg)
}
end
end
class TestConsumerOpenID1DHSHA1 < Test::Unit::TestCase
include TestDiffieHellmanResponseParametersMixin
class << self
attr_reader :session_cls, :message_namespace
end
@session_cls = Consumer::DiffieHellmanSHA1Session
@message_namespace = OPENID1_NS
end
class TestConsumerOpenID2DHSHA1 < Test::Unit::TestCase
include TestDiffieHellmanResponseParametersMixin
class << self
attr_reader :session_cls, :message_namespace
end
@session_cls = Consumer::DiffieHellmanSHA1Session
@message_namespace = OPENID2_NS
end
class TestConsumerOpenID2DHSHA256 < Test::Unit::TestCase
include TestDiffieHellmanResponseParametersMixin
class << self
attr_reader :session_cls, :message_namespace
end
@session_cls = Consumer::DiffieHellmanSHA256Session
@message_namespace = OPENID2_NS
end
class TestConsumerNoEncryptionSession < Test::Unit::TestCase
def setup
@sess = Consumer::NoEncryptionSession.new
end
def test_empty_request
assert_equal(@sess.get_request, {})
end
def test_get_secret
secret = 'shhh!' * 4
mac_key = Util.to_base64(secret)
msg = Message.from_openid_args({'mac_key' => mac_key})
assert_equal(secret, @sess.extract_secret(msg))
end
end
class TestCreateAssociationRequest < Test::Unit::TestCase
def setup
@server_url = 'http://invalid/'
@assoc_manager = Consumer::AssociationManager.new(nil, @server_url)
class << @assoc_manager
def compatibility_mode=(val)
@compatibility_mode = val
end
end
@assoc_type = 'HMAC-SHA1'
end
def test_no_encryption_sends_type
session_type = 'no-encryption'
session, args = @assoc_manager.send(:create_associate_request,
@assoc_type,
session_type)
assert(session.is_a?(Consumer::NoEncryptionSession))
expected = Message.from_openid_args(
{'ns' => OPENID2_NS,
'session_type' => session_type,
'mode' => 'associate',
'assoc_type' => @assoc_type,
})
assert_equal(expected, args)
end
def test_no_encryption_compatibility
@assoc_manager.compatibility_mode = true
session_type = 'no-encryption'
session, args = @assoc_manager.send(:create_associate_request,
@assoc_type,
session_type)
assert(session.is_a?(Consumer::NoEncryptionSession))
assert_equal(Message.from_openid_args({'mode' => 'associate',
'assoc_type' => @assoc_type,
}), args)
end
def test_dh_sha1_compatibility
@assoc_manager.compatibility_mode = true
session_type = 'DH-SHA1'
session, args = @assoc_manager.send(:create_associate_request,
@assoc_type,
session_type)
assert(session.is_a?(Consumer::DiffieHellmanSHA1Session))
# This is a random base-64 value, so just check that it's
# present.
assert_not_nil(args.get_arg(OPENID1_NS, 'dh_consumer_public'))
args.del_arg(OPENID1_NS, 'dh_consumer_public')
# OK, session_type is set here and not for no-encryption
# compatibility
expected = Message.from_openid_args({'mode' => 'associate',
'session_type' => 'DH-SHA1',
'assoc_type' => @assoc_type,
})
assert_equal(expected, args)
end
end
class TestAssociationManagerExpiresIn < Test::Unit::TestCase
def expires_in_msg(val)
msg = Message.from_openid_args({'expires_in' => val})
Consumer::AssociationManager.extract_expires_in(msg)
end
def test_parse_fail
['',
'-2',
' 1',
' ',
'0x00',
'foosball',
'1\n',
'100,000,000,000',
].each do |x|
assert_raises(ProtocolError) {expires_in_msg(x)}
end
end
def test_parse
['0',
'1',
'1000',
'9999999',
'01',
].each do |n|
assert_equal(n.to_i, expires_in_msg(n))
end
end
end
class TestAssociationManagerCreateSession < Test::Unit::TestCase
def test_invalid
assert_raises(ArgumentError) {
Consumer::AssociationManager.create_session('monkeys')
}
end
def test_sha256
sess = Consumer::AssociationManager.create_session('DH-SHA256')
assert(sess.is_a?(Consumer::DiffieHellmanSHA256Session))
end
end
module NegotiationTestMixin
include TestUtil
def mk_message(args)
args['ns'] = @openid_ns
Message.from_openid_args(args)
end
def call_negotiate(responses, negotiator=nil)
store = nil
compat = self.class::Compat
assoc_manager = Consumer::AssociationManager.new(store, @server_url,
compat, negotiator)
class << assoc_manager
attr_accessor :responses
def request_association(assoc_type, session_type)
m = @responses.shift
if m.is_a?(Message)
raise ServerError.from_message(m)
else
return m
end
end
end
assoc_manager.responses = responses
assoc_manager.negotiate_association
end
end
# Test the session type negotiation behavior of an OpenID 2
# consumer.
class TestOpenID2SessionNegotiation < Test::Unit::TestCase
include NegotiationTestMixin
Compat = false
def setup
@server_url = 'http://invalid/'
@openid_ns = OPENID2_NS
end
# Test the case where the response to an associate request is a
# server error or is otherwise undecipherable.
def test_bad_response
assert_log_matches('Server error when requesting an association') {
assert_equal(call_negotiate([mk_message({})]), nil)
}
end
# Test the case where the association type (assoc_type) returned
# in an unsupported-type response is absent.
def test_empty_assoc_type
msg = mk_message({'error' => 'Unsupported type',
'error_code' => 'unsupported-type',
'session_type' => 'new-session-type',
})
assert_log_matches('Unsupported association type',
"Server #{@server_url} responded with unsupported "\
"association session but did not supply a fallback."
) {
assert_equal(call_negotiate([msg]), nil)
}
end
# Test the case where the session type (session_type) returned
# in an unsupported-type response is absent.
def test_empty_session_type
msg = mk_message({'error' => 'Unsupported type',
'error_code' => 'unsupported-type',
'assoc_type' => 'new-assoc-type',
})
assert_log_matches('Unsupported association type',
"Server #{@server_url} responded with unsupported "\
"association session but did not supply a fallback."
) {
assert_equal(call_negotiate([msg]), nil)
}
end
# Test the case where an unsupported-type response specifies a
# preferred (assoc_type, session_type) combination that is not
# allowed by the consumer's SessionNegotiator.
def test_not_allowed
negotiator = AssociationNegotiator.new([])
negotiator.instance_eval{
@allowed_types = [['assoc_bogus', 'session_bogus']]
}
msg = mk_message({'error' => 'Unsupported type',
'error_code' => 'unsupported-type',
'assoc_type' => 'not-allowed',
'session_type' => 'not-allowed',
})
assert_log_matches('Unsupported association type',
'Server sent unsupported session/association type:') {
assert_equal(call_negotiate([msg], negotiator), nil)
}
end
# Test the case where an unsupported-type response triggers a
# retry to get an association with the new preferred type.
def test_unsupported_with_retry
msg = mk_message({'error' => 'Unsupported type',
'error_code' => 'unsupported-type',
'assoc_type' => 'HMAC-SHA1',
'session_type' => 'DH-SHA1',
})
assoc = Association.new('handle', 'secret', Time.now, 10000, 'HMAC-SHA1')
assert_log_matches('Unsupported association type') {
assert_equal(assoc, call_negotiate([msg, assoc]))
}
end
# Test the case where an unsupported-typ response triggers a
# retry, but the retry fails and nil is returned instead.
def test_unsupported_with_retry_and_fail
msg = mk_message({'error' => 'Unsupported type',
'error_code' => 'unsupported-type',
'assoc_type' => 'HMAC-SHA1',
'session_type' => 'DH-SHA1',
})
assert_log_matches('Unsupported association type',
"Server #{@server_url} refused") {
assert_equal(call_negotiate([msg, msg]), nil)
}
end
# Test the valid case, wherein an association is returned on the
# first attempt to get one.
def test_valid
assoc = Association.new('handle', 'secret', Time.now, 10000, 'HMAC-SHA1')
assert_log_matches() {
assert_equal(call_negotiate([assoc]), assoc)
}
end
end
# Tests for the OpenID 1 consumer association session behavior. See
# the docs for TestOpenID2SessionNegotiation. Notice that this
# class is not a subclass of the OpenID 2 tests. Instead, it uses
# many of the same inputs but inspects the log messages logged with
# oidutil.log. See the calls to self.failUnlessLogMatches. Some of
# these tests pass openid2-style messages to the openid 1
# association processing logic to be sure it ignores the extra data.
class TestOpenID1SessionNegotiation < Test::Unit::TestCase
include NegotiationTestMixin
Compat = true
def setup
@server_url = 'http://invalid/'
@openid_ns = OPENID1_NS
end
def test_bad_response
assert_log_matches('Server error when requesting an association') {
response = call_negotiate([mk_message({})])
assert_equal(nil, response)
}
end
def test_empty_assoc_type
msg = mk_message({'error' => 'Unsupported type',
'error_code' => 'unsupported-type',
'session_type' => 'new-session-type',
})
assert_log_matches('Server error when requesting an association') {
response = call_negotiate([msg])
assert_equal(nil, response)
}
end
def test_empty_session_type
msg = mk_message({'error' => 'Unsupported type',
'error_code' => 'unsupported-type',
'assoc_type' => 'new-assoc-type',
})
assert_log_matches('Server error when requesting an association') {
response = call_negotiate([msg])
assert_equal(nil, response)
}
end
def test_not_allowed
negotiator = AssociationNegotiator.new([])
negotiator.instance_eval{
@allowed_types = [['assoc_bogus', 'session_bogus']]
}
msg = mk_message({'error' => 'Unsupported type',
'error_code' => 'unsupported-type',
'assoc_type' => 'not-allowed',
'session_type' => 'not-allowed',
})
assert_log_matches('Server error when requesting an association') {
response = call_negotiate([msg])
assert_equal(nil, response)
}
end
def test_unsupported_with_retry
msg = mk_message({'error' => 'Unsupported type',
'error_code' => 'unsupported-type',
'assoc_type' => 'HMAC-SHA1',
'session_type' => 'DH-SHA1',
})
assoc = Association.new('handle', 'secret', Time.now, 10000, 'HMAC-SHA1')
assert_log_matches('Server error when requesting an association') {
response = call_negotiate([msg, assoc])
assert_equal(nil, response)
}
end
def test_valid
assoc = Association.new('handle', 'secret', Time.now, 10000, 'HMAC-SHA1')
assert_log_matches() {
response = call_negotiate([assoc])
assert_equal(assoc, response)
}
end
end
class TestExtractAssociation < Test::Unit::TestCase
include ProtocolErrorMixin
# An OpenID associate response (without the namespace)
DEFAULTS = {
'expires_in' => '1000',
'assoc_handle' => 'a handle',
'assoc_type' => 'a type',
'session_type' => 'a session type',
}
def setup
@assoc_manager = Consumer::AssociationManager.new(nil, nil)
end
# Make tests that ensure that an association response that is
# missing required fields will raise an Message::KeyNotFound.
#
# According to 'Association Session Response' subsection 'Common
# Response Parameters', the following fields are required for
# OpenID 2.0:
#
# * ns
# * session_type
# * assoc_handle
# * assoc_type
# * expires_in
#
# In OpenID 1, everything except 'session_type' and 'ns' are
# required.
MISSING_FIELD_SETS = ([["no_fields", []]] +
(DEFAULTS.keys.map do |f|
fields = DEFAULTS.keys
fields.delete(f)
["missing_#{f}", fields]
end)
)
[OPENID1_NS, OPENID2_NS].each do |ns|
MISSING_FIELD_SETS.each do |name, fields|
# OpenID 1 is allowed to be missing session_type
if ns != OPENID1_NS and name != 'missing_session_type'
test = lambda do
msg = Message.new(ns)
fields.each do |field|
msg.set_arg(ns, field, DEFAULTS[field])
end
assert_raises(Message::KeyNotFound) do
@assoc_manager.send(:extract_association, msg, nil)
end
end
define_method("test_#{name}", test)
end
end
end
# assert that extracting a response that contains the given
# response session type when the request was made for the given
# request session type will raise a ProtocolError indicating
# session type mismatch
def assert_session_mismatch(req_type, resp_type, ns)
# Create an association session that has "req_type" as its
# session_type and no allowed_assoc_types
assoc_session_class = Class.new do
@session_type = req_type
def self.session_type
@session_type
end
def self.allowed_assoc_types
[]
end
end
assoc_session = assoc_session_class.new
# Build an OpenID 1 or 2 association response message that has
# the specified association session type
msg = Message.new(ns)
msg.update_args(ns, DEFAULTS)
msg.set_arg(ns, 'session_type', resp_type)
# The request type and response type have been chosen to produce
# a session type mismatch.
assert_protocol_error('Session type mismatch') {
@assoc_manager.send(:extract_association, msg, assoc_session)
}
end
[['no-encryption', '', OPENID2_NS],
['DH-SHA1', 'no-encryption', OPENID2_NS],
['DH-SHA256', 'no-encryption', OPENID2_NS],
['no-encryption', 'DH-SHA1', OPENID2_NS],
['DH-SHA1', 'DH-SHA256', OPENID1_NS],
['DH-SHA256', 'DH-SHA1', OPENID1_NS],
['no-encryption', 'DH-SHA1', OPENID1_NS],
].each do |req_type, resp_type, ns|
test = lambda { assert_session_mismatch(req_type, resp_type, ns) }
name = "test_mismatch_req_#{req_type}_resp_#{resp_type}_#{ns}"
define_method(name, test)
end
def test_openid1_no_encryption_fallback
# A DH-SHA1 session
assoc_session = Consumer::DiffieHellmanSHA1Session.new
# An OpenID 1 no-encryption association response
msg = Message.from_openid_args({
'expires_in' => '1000',
'assoc_handle' => 'a handle',
'assoc_type' => 'HMAC-SHA1',
'mac_key' => 'X' * 20,
})
# Should succeed
assoc = @assoc_manager.send(:extract_association, msg, assoc_session)
assert_equal('a handle', assoc.handle)
assert_equal('HMAC-SHA1', assoc.assoc_type)
assert(assoc.expires_in.between?(999, 1000))
assert('X' * 20, assoc.secret)
end
end
class GetOpenIDSessionTypeTest < Test::Unit::TestCase
include TestUtil
SERVER_URL = 'http://invalid/'
def do_test(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 = {}
if !session_type_value.nil?
args['session_type'] = session_type_value
end
message = Message.from_openid_args(args)
assert(message.is_openid1)
assoc_manager = Consumer::AssociationManager.new(nil, SERVER_URL)
actual_session_type = assoc_manager.send(:get_openid1_session_type,
message)
error_message = ("Returned session type parameter #{session_type_value}"\
"was expected to yield session type "\
"#{expected_session_type}, but yielded "\
"#{actual_session_type}")
assert_equal(expected_session_type, actual_session_type, error_message)
end
[['nil', 'no-encryption', nil],
['empty', 'no-encryption', ''],
['dh_sha1', 'DH-SHA1', 'DH-SHA1'],
['dh_sha256', 'DH-SHA256', 'DH-SHA256'],
].each {|name, expected, input|
# Define a test method that will check what session type will be
# used if the OpenID 1 response to an associate call sets the
# 'session_type' field to `session_type_value`
test = lambda {assert_log_matches() { do_test(expected, input) } }
define_method("test_#{name}", &test)
}
# This one's different because it expects log messages
def test_explicit_no_encryption
assert_log_matches("WARNING: #{SERVER_URL} sent 'no-encryption'"){
do_test('no-encryption', 'no-encryption')
}
end
end
class ExtractAssociationTest < Test::Unit::TestCase
include ProtocolErrorMixin
SERVER_URL = 'http://invalid/'
def setup
@session_type = 'testing-session'
# This must something that works for Association::from_expires_in
@assoc_type = 'HMAC-SHA1'
@assoc_handle = 'testing-assoc-handle'
# These arguments should all be valid
@assoc_response =
Message.from_openid_args({
'expires_in' => '1000',
'assoc_handle' => @assoc_handle,
'assoc_type' => @assoc_type,
'session_type' => @session_type,
'ns' => OPENID2_NS,
})
assoc_session_cls = Class.new do
class << self
attr_accessor :allowed_assoc_types, :session_type
end
attr_reader :extract_secret_called, :secret
def initialize
@extract_secret_called = false
@secret = 'shhhhh!'
end
def extract_secret(_)
@extract_secret_called = true
@secret
end
end
@assoc_session = assoc_session_cls.new
@assoc_session.class.allowed_assoc_types = [@assoc_type]
@assoc_session.class.session_type = @session_type
@assoc_manager = Consumer::AssociationManager.new(nil, SERVER_URL)
end
def call_extract
@assoc_manager.send(:extract_association,
@assoc_response, @assoc_session)
end
# Handle a full successful association response
def test_works_with_good_fields
assoc = call_extract
assert(@assoc_session.extract_secret_called)
assert_equal(@assoc_session.secret, assoc.secret)
assert_equal(1000, assoc.lifetime)
assert_equal(@assoc_handle, assoc.handle)
assert_equal(@assoc_type, assoc.assoc_type)
end
def test_bad_assoc_type
# Make sure that the assoc type in the response is not valid
# for the given session.
@assoc_session.class.allowed_assoc_types = []
assert_protocol_error('Unsupported assoc_type for sess') {call_extract}
end
def test_bad_expires_in
# Invalid value for expires_in should cause failure
@assoc_response.set_arg(OPENID_NS, 'expires_in', 'forever')
assert_protocol_error('Invalid expires_in') {call_extract}
end
end
class TestExtractAssociationDiffieHellman < Test::Unit::TestCase
include ProtocolErrorMixin
SECRET = 'x' * 20
def setup
@assoc_manager = Consumer::AssociationManager.new(nil, nil)
end
def setup_dh
sess, message = @assoc_manager.send(:create_associate_request,
'HMAC-SHA1', 'DH-SHA1')
server_dh = DiffieHellman.new
cons_dh = sess.instance_variable_get('@dh')
enc_mac_key = server_dh.xor_secret(CryptUtil.method(:sha1),
cons_dh.public, SECRET)
server_resp = {
'dh_server_public' => CryptUtil.num_to_base64(server_dh.public),
'enc_mac_key' => Util.to_base64(enc_mac_key),
'assoc_type' => 'HMAC-SHA1',
'assoc_handle' => 'handle',
'expires_in' => '1000',
'session_type' => 'DH-SHA1',
}
if @assoc_manager.instance_variable_get(:@compatibility_mode)
server_resp['ns'] = OPENID2_NS
end
return [sess, Message.from_openid_args(server_resp)]
end
def test_success
sess, server_resp = setup_dh
ret = @assoc_manager.send(:extract_association, server_resp, sess)
assert(!ret.nil?)
assert_equal(ret.assoc_type, 'HMAC-SHA1')
assert_equal(ret.secret, SECRET)
assert_equal(ret.handle, 'handle')
assert_equal(ret.lifetime, 1000)
end
def test_openid2success
# Use openid 1 type in endpoint so _setUpDH checks
# compatibility mode state properly
@assoc_manager.instance_variable_set('@compatibility_mode', true)
test_success()
end
def test_bad_dh_values
sess, server_resp = setup_dh
server_resp.set_arg(OPENID_NS, 'enc_mac_key', '\x00\x00\x00')
assert_protocol_error('Malformed response for') {
@assoc_manager.send(:extract_association, server_resp, sess)
}
end
end
class TestAssocManagerGetAssociation < Test::Unit::TestCase
include FetcherMixin
include TestUtil
attr_reader :negotiate_association
def setup
@server_url = 'http://invalid/'
@store = Store::Memory.new
@assoc_manager = Consumer::AssociationManager.new(@store, @server_url)
@assoc_manager.extend(Const)
@assoc = Association.new('handle', 'secret', Time.now, 10000,
'HMAC-SHA1')
end
def set_negotiate_response(assoc)
@assoc_manager.const(:negotiate_association, assoc)
end
def test_not_in_store_no_response
set_negotiate_response(nil)
assert_equal(nil, @assoc_manager.get_association)
end
def test_not_in_store_negotiate_assoc
# Not stored beforehand:
stored_assoc = @store.get_association(@server_url, @assoc.handle)
assert_equal(nil, stored_assoc)
# Returned from associate call:
set_negotiate_response(@assoc)
assert_equal(@assoc, @assoc_manager.get_association)
# It should have been stored:
stored_assoc = @store.get_association(@server_url, @assoc.handle)
assert_equal(@assoc, stored_assoc)
end
def test_in_store_no_response
set_negotiate_response(nil)
@store.store_association(@server_url, @assoc)
assert_equal(@assoc, @assoc_manager.get_association)
end
def test_request_assoc_with_status_error
fetcher_class = Class.new do
define_method(:fetch) do |*args|
MockResponse.new(500, '')
end
end
with_fetcher(fetcher_class.new) do
assert_log_matches('Got HTTP status error when requesting') {
result = @assoc_manager.send(:request_association, 'HMAC-SHA1',
'no-encryption')
assert(result.nil?)
}
end
end
end
class TestAssocManagerRequestAssociation < Test::Unit::TestCase
include FetcherMixin
include TestUtil
def setup
@assoc_manager = Consumer::AssociationManager.new(nil, 'http://invalid/')
@assoc_type = 'HMAC-SHA1'
@session_type = 'no-encryption'
@message = Message.new(OPENID2_NS)
@message.update_args(OPENID_NS, {
'assoc_type' => @assoc_type,
'session_type' => @session_type,
'assoc_handle' => 'kaboodle',
'expires_in' => '1000',
'mac_key' => 'X' * 20,
})
end
def make_request
kv = @message.to_kvform
fetcher_class = Class.new do
define_method(:fetch) do |*args|
MockResponse.new(200, kv)
end
end
with_fetcher(fetcher_class.new) do
@assoc_manager.send(:request_association, @assoc_type, @session_type)
end
end
# The association we get is from valid processing of our result,
# and that no errors are raised
def test_success
assert_equal('kaboodle', make_request.handle)
end
# A missing parameter gets translated into a log message and
# causes the method to return nil
def test_missing_fields
@message.del_arg(OPENID_NS, 'assoc_type')
assert_log_matches('Missing required par') {
assert_equal(nil, make_request)
}
end
# A bad value results in a log message and causes the method to
# return nil
def test_protocol_error
@message.set_arg(OPENID_NS, 'expires_in', 'goats')
assert_log_matches('Protocol error processing') {
assert_equal(nil, make_request)
}
end
end
end