entp-ruby-openid 2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (200) hide show
  1. data/CHANGELOG +215 -0
  2. data/INSTALL +47 -0
  3. data/LICENSE +210 -0
  4. data/NOTICE +2 -0
  5. data/README +85 -0
  6. data/UPGRADE +127 -0
  7. data/admin/runtests.rb +45 -0
  8. data/examples/README +32 -0
  9. data/examples/active_record_openid_store/README +58 -0
  10. data/examples/active_record_openid_store/XXX_add_open_id_store_to_db.rb +24 -0
  11. data/examples/active_record_openid_store/XXX_upgrade_open_id_store.rb +26 -0
  12. data/examples/active_record_openid_store/init.rb +8 -0
  13. data/examples/active_record_openid_store/lib/association.rb +10 -0
  14. data/examples/active_record_openid_store/lib/nonce.rb +3 -0
  15. data/examples/active_record_openid_store/lib/open_id_setting.rb +4 -0
  16. data/examples/active_record_openid_store/lib/openid_ar_store.rb +57 -0
  17. data/examples/active_record_openid_store/test/store_test.rb +212 -0
  18. data/examples/discover +49 -0
  19. data/examples/rails_openid/README +153 -0
  20. data/examples/rails_openid/Rakefile +10 -0
  21. data/examples/rails_openid/app/controllers/application.rb +4 -0
  22. data/examples/rails_openid/app/controllers/consumer_controller.rb +125 -0
  23. data/examples/rails_openid/app/controllers/login_controller.rb +45 -0
  24. data/examples/rails_openid/app/controllers/server_controller.rb +265 -0
  25. data/examples/rails_openid/app/helpers/application_helper.rb +3 -0
  26. data/examples/rails_openid/app/helpers/login_helper.rb +2 -0
  27. data/examples/rails_openid/app/helpers/server_helper.rb +9 -0
  28. data/examples/rails_openid/app/views/consumer/index.rhtml +81 -0
  29. data/examples/rails_openid/app/views/layouts/server.rhtml +68 -0
  30. data/examples/rails_openid/app/views/login/index.rhtml +56 -0
  31. data/examples/rails_openid/app/views/server/decide.rhtml +26 -0
  32. data/examples/rails_openid/config/boot.rb +19 -0
  33. data/examples/rails_openid/config/database.yml +74 -0
  34. data/examples/rails_openid/config/environment.rb +54 -0
  35. data/examples/rails_openid/config/environments/development.rb +19 -0
  36. data/examples/rails_openid/config/environments/production.rb +19 -0
  37. data/examples/rails_openid/config/environments/test.rb +19 -0
  38. data/examples/rails_openid/config/routes.rb +24 -0
  39. data/examples/rails_openid/doc/README_FOR_APP +2 -0
  40. data/examples/rails_openid/public/404.html +8 -0
  41. data/examples/rails_openid/public/500.html +8 -0
  42. data/examples/rails_openid/public/dispatch.cgi +12 -0
  43. data/examples/rails_openid/public/dispatch.fcgi +26 -0
  44. data/examples/rails_openid/public/dispatch.rb +12 -0
  45. data/examples/rails_openid/public/favicon.ico +0 -0
  46. data/examples/rails_openid/public/images/openid_login_bg.gif +0 -0
  47. data/examples/rails_openid/public/javascripts/controls.js +750 -0
  48. data/examples/rails_openid/public/javascripts/dragdrop.js +584 -0
  49. data/examples/rails_openid/public/javascripts/effects.js +854 -0
  50. data/examples/rails_openid/public/javascripts/prototype.js +1785 -0
  51. data/examples/rails_openid/public/robots.txt +1 -0
  52. data/examples/rails_openid/script/about +3 -0
  53. data/examples/rails_openid/script/breakpointer +3 -0
  54. data/examples/rails_openid/script/console +3 -0
  55. data/examples/rails_openid/script/destroy +3 -0
  56. data/examples/rails_openid/script/generate +3 -0
  57. data/examples/rails_openid/script/performance/benchmarker +3 -0
  58. data/examples/rails_openid/script/performance/profiler +3 -0
  59. data/examples/rails_openid/script/plugin +3 -0
  60. data/examples/rails_openid/script/process/reaper +3 -0
  61. data/examples/rails_openid/script/process/spawner +3 -0
  62. data/examples/rails_openid/script/process/spinner +3 -0
  63. data/examples/rails_openid/script/runner +3 -0
  64. data/examples/rails_openid/script/server +3 -0
  65. data/examples/rails_openid/test/functional/login_controller_test.rb +18 -0
  66. data/examples/rails_openid/test/functional/server_controller_test.rb +18 -0
  67. data/examples/rails_openid/test/test_helper.rb +28 -0
  68. data/lib/hmac/hmac.rb +112 -0
  69. data/lib/hmac/sha1.rb +11 -0
  70. data/lib/hmac/sha2.rb +25 -0
  71. data/lib/openid.rb +22 -0
  72. data/lib/openid/association.rb +249 -0
  73. data/lib/openid/consumer.rb +395 -0
  74. data/lib/openid/consumer/associationmanager.rb +344 -0
  75. data/lib/openid/consumer/checkid_request.rb +186 -0
  76. data/lib/openid/consumer/discovery.rb +497 -0
  77. data/lib/openid/consumer/discovery_manager.rb +123 -0
  78. data/lib/openid/consumer/html_parse.rb +134 -0
  79. data/lib/openid/consumer/idres.rb +523 -0
  80. data/lib/openid/consumer/responses.rb +150 -0
  81. data/lib/openid/cryptutil.rb +115 -0
  82. data/lib/openid/dh.rb +89 -0
  83. data/lib/openid/extension.rb +39 -0
  84. data/lib/openid/extensions/ax.rb +539 -0
  85. data/lib/openid/extensions/oauth.rb +91 -0
  86. data/lib/openid/extensions/pape.rb +179 -0
  87. data/lib/openid/extensions/sreg.rb +277 -0
  88. data/lib/openid/extras.rb +11 -0
  89. data/lib/openid/fetchers.rb +258 -0
  90. data/lib/openid/kvform.rb +136 -0
  91. data/lib/openid/kvpost.rb +58 -0
  92. data/lib/openid/message.rb +553 -0
  93. data/lib/openid/protocolerror.rb +12 -0
  94. data/lib/openid/server.rb +1544 -0
  95. data/lib/openid/store.rb +10 -0
  96. data/lib/openid/store/filesystem.rb +272 -0
  97. data/lib/openid/store/interface.rb +75 -0
  98. data/lib/openid/store/memcache.rb +109 -0
  99. data/lib/openid/store/memory.rb +84 -0
  100. data/lib/openid/store/nonce.rb +68 -0
  101. data/lib/openid/trustroot.rb +349 -0
  102. data/lib/openid/urinorm.rb +75 -0
  103. data/lib/openid/util.rb +119 -0
  104. data/lib/openid/version.rb +3 -0
  105. data/lib/openid/yadis.rb +15 -0
  106. data/lib/openid/yadis/accept.rb +148 -0
  107. data/lib/openid/yadis/constants.rb +21 -0
  108. data/lib/openid/yadis/discovery.rb +153 -0
  109. data/lib/openid/yadis/filters.rb +205 -0
  110. data/lib/openid/yadis/htmltokenizer.rb +305 -0
  111. data/lib/openid/yadis/parsehtml.rb +45 -0
  112. data/lib/openid/yadis/services.rb +42 -0
  113. data/lib/openid/yadis/xrds.rb +155 -0
  114. data/lib/openid/yadis/xri.rb +90 -0
  115. data/lib/openid/yadis/xrires.rb +91 -0
  116. data/test/data/test_discover/openid_utf8.html +11 -0
  117. data/test/support/test_data_mixin.rb +127 -0
  118. data/test/support/test_util.rb +53 -0
  119. data/test/support/yadis_data.rb +131 -0
  120. data/test/support/yadis_data/accept.txt +124 -0
  121. data/test/support/yadis_data/dh.txt +29 -0
  122. data/test/support/yadis_data/example-xrds.xml +14 -0
  123. data/test/support/yadis_data/linkparse.txt +587 -0
  124. data/test/support/yadis_data/n2b64 +650 -0
  125. data/test/support/yadis_data/test1-discover.txt +137 -0
  126. data/test/support/yadis_data/test1-parsehtml.txt +152 -0
  127. data/test/support/yadis_data/test_discover/malformed_meta_tag.html +19 -0
  128. data/test/support/yadis_data/test_discover/openid.html +11 -0
  129. data/test/support/yadis_data/test_discover/openid2.html +11 -0
  130. data/test/support/yadis_data/test_discover/openid2_xrds.xml +12 -0
  131. data/test/support/yadis_data/test_discover/openid2_xrds_no_local_id.xml +11 -0
  132. data/test/support/yadis_data/test_discover/openid_1_and_2.html +11 -0
  133. data/test/support/yadis_data/test_discover/openid_1_and_2_xrds.xml +16 -0
  134. data/test/support/yadis_data/test_discover/openid_1_and_2_xrds_bad_delegate.xml +17 -0
  135. data/test/support/yadis_data/test_discover/openid_and_yadis.html +12 -0
  136. data/test/support/yadis_data/test_discover/openid_no_delegate.html +10 -0
  137. data/test/support/yadis_data/test_discover/openid_utf8.html +11 -0
  138. data/test/support/yadis_data/test_discover/yadis_0entries.xml +12 -0
  139. data/test/support/yadis_data/test_discover/yadis_2_bad_local_id.xml +15 -0
  140. data/test/support/yadis_data/test_discover/yadis_2entries_delegate.xml +22 -0
  141. data/test/support/yadis_data/test_discover/yadis_2entries_idp.xml +21 -0
  142. data/test/support/yadis_data/test_discover/yadis_another_delegate.xml +14 -0
  143. data/test/support/yadis_data/test_discover/yadis_idp.xml +12 -0
  144. data/test/support/yadis_data/test_discover/yadis_idp_delegate.xml +13 -0
  145. data/test/support/yadis_data/test_discover/yadis_no_delegate.xml +11 -0
  146. data/test/support/yadis_data/test_xrds/=j3h.2007.11.14.xrds +25 -0
  147. data/test/support/yadis_data/test_xrds/README +12 -0
  148. data/test/support/yadis_data/test_xrds/delegated-20060809-r1.xrds +34 -0
  149. data/test/support/yadis_data/test_xrds/delegated-20060809-r2.xrds +34 -0
  150. data/test/support/yadis_data/test_xrds/delegated-20060809.xrds +34 -0
  151. data/test/support/yadis_data/test_xrds/no-xrd.xml +7 -0
  152. data/test/support/yadis_data/test_xrds/not-xrds.xml +2 -0
  153. data/test/support/yadis_data/test_xrds/prefixsometimes.xrds +34 -0
  154. data/test/support/yadis_data/test_xrds/ref.xrds +109 -0
  155. data/test/support/yadis_data/test_xrds/sometimesprefix.xrds +34 -0
  156. data/test/support/yadis_data/test_xrds/spoof1.xrds +25 -0
  157. data/test/support/yadis_data/test_xrds/spoof2.xrds +25 -0
  158. data/test/support/yadis_data/test_xrds/spoof3.xrds +37 -0
  159. data/test/support/yadis_data/test_xrds/status222.xrds +9 -0
  160. data/test/support/yadis_data/test_xrds/subsegments.xrds +58 -0
  161. data/test/support/yadis_data/test_xrds/valid-populated-xrds.xml +39 -0
  162. data/test/support/yadis_data/trustroot.txt +153 -0
  163. data/test/support/yadis_data/urinorm.txt +79 -0
  164. data/test/test_accept.rb +170 -0
  165. data/test/test_association.rb +268 -0
  166. data/test/test_associationmanager.rb +918 -0
  167. data/test/test_ax.rb +690 -0
  168. data/test/test_checkid_request.rb +293 -0
  169. data/test/test_consumer.rb +260 -0
  170. data/test/test_cryptutil.rb +119 -0
  171. data/test/test_dh.rb +85 -0
  172. data/test/test_discover.rb +848 -0
  173. data/test/test_discovery_manager.rb +259 -0
  174. data/test/test_extension.rb +46 -0
  175. data/test/test_extras.rb +35 -0
  176. data/test/test_fetchers.rb +554 -0
  177. data/test/test_filters.rb +269 -0
  178. data/test/test_helper.rb +4 -0
  179. data/test/test_idres.rb +961 -0
  180. data/test/test_kvform.rb +164 -0
  181. data/test/test_kvpost.rb +64 -0
  182. data/test/test_linkparse.rb +100 -0
  183. data/test/test_message.rb +1115 -0
  184. data/test/test_nonce.rb +89 -0
  185. data/test/test_oauth.rb +176 -0
  186. data/test/test_openid_yadis.rb +177 -0
  187. data/test/test_pape.rb +248 -0
  188. data/test/test_parsehtml.rb +79 -0
  189. data/test/test_responses.rb +63 -0
  190. data/test/test_server.rb +2455 -0
  191. data/test/test_sreg.rb +479 -0
  192. data/test/test_stores.rb +292 -0
  193. data/test/test_trustroot.rb +111 -0
  194. data/test/test_urinorm.rb +34 -0
  195. data/test/test_util.rb +145 -0
  196. data/test/test_xrds.rb +167 -0
  197. data/test/test_xri.rb +48 -0
  198. data/test/test_xrires.rb +67 -0
  199. data/test/test_yadis_discovery.rb +218 -0
  200. metadata +268 -0
@@ -0,0 +1,119 @@
1
+ # coding: ASCII-8BIT
2
+ require "test_helper"
3
+ require "openid/cryptutil"
4
+ require "pathname"
5
+
6
+ module OpenID
7
+ class CryptUtilTestCase < Test::Unit::TestCase
8
+ include TestDataMixin
9
+
10
+ BIG = 2 ** 256
11
+
12
+ def test_rand
13
+ # If this is not true, the rest of our test won't work
14
+ assert(BIG.is_a?(Bignum))
15
+
16
+ # It's possible that these will be small enough for fixnums, but
17
+ # extraorindarily unlikely.
18
+ a = OpenID::CryptUtil.rand(BIG)
19
+ b = OpenID::CryptUtil.rand(BIG)
20
+ assert(a.is_a?(Bignum))
21
+ assert(b.is_a?(Bignum))
22
+ assert_not_equal(a, b)
23
+ end
24
+
25
+ def test_rand_doesnt_depend_on_srand
26
+ Kernel.srand(1)
27
+ a = OpenID::CryptUtil.rand(BIG)
28
+ Kernel.srand(1)
29
+ b = OpenID::CryptUtil.rand(BIG)
30
+ assert_not_equal(a, b)
31
+ end
32
+
33
+ def test_random_binary_convert
34
+ (0..500).each do
35
+ n = (0..10).inject(0) {|sum, element| sum + OpenID::CryptUtil.rand(BIG) }
36
+ s = OpenID::CryptUtil.num_to_binary n
37
+ assert(s.is_a?(String))
38
+ n_converted_back = OpenID::CryptUtil.binary_to_num(s)
39
+ assert_equal(n, n_converted_back)
40
+ end
41
+ end
42
+
43
+ def test_enumerated_binary_convert
44
+ {
45
+ "\x00" => 0,
46
+ "\x01" => 1,
47
+ "\x7F" => 127,
48
+ "\x00\xFF" => 255,
49
+ "\x00\x80" => 128,
50
+ "\x00\x81" => 129,
51
+ "\x00\x80\x00" => 32768,
52
+ "OpenID is cool" => 1611215304203901150134421257416556,
53
+ }.each do |str, num|
54
+ num_prime = OpenID::CryptUtil.binary_to_num(str)
55
+ str_prime = OpenID::CryptUtil.num_to_binary(num)
56
+ assert_equal(num, num_prime)
57
+ assert_equal(str, str_prime)
58
+ end
59
+ end
60
+
61
+ def with_n2b64
62
+ read_data_file( 'n2b64').each do |line|
63
+ base64, base10 = line.chomp.split
64
+ yield base64, base10.to_i
65
+ end
66
+ end
67
+
68
+ def test_base64_to_num
69
+ with_n2b64 do |base64, num|
70
+ assert_equal(num, OpenID::CryptUtil.base64_to_num(base64))
71
+ end
72
+ end
73
+
74
+ def test_base64_to_num_invalid
75
+ assert_raises(ArgumentError) {
76
+ OpenID::CryptUtil.base64_to_num('!@#$')
77
+ }
78
+ end
79
+
80
+ def test_num_to_base64
81
+ with_n2b64 do |base64, num|
82
+ assert_equal(base64, OpenID::CryptUtil.num_to_base64(num))
83
+ end
84
+ end
85
+
86
+ def test_randomstring
87
+ s1 = OpenID::CryptUtil.random_string(42)
88
+ assert_equal(42, s1.length)
89
+ s2 = OpenID::CryptUtil.random_string(42)
90
+ assert_equal(42, s2.length)
91
+ assert_not_equal(s1, s2)
92
+ end
93
+
94
+ def test_randomstring_population
95
+ s1 = OpenID::CryptUtil.random_string(42, "XO")
96
+ assert_match(/[XO]{42}/, s1)
97
+ end
98
+
99
+ def test_sha1
100
+ assert_equal("\x11\xf6\xad\x8e\xc5*)\x84\xab\xaa\xfd|;Qe\x03x\\ r",
101
+ OpenID::CryptUtil.sha1('x'))
102
+ end
103
+
104
+ def test_hmac_sha1
105
+ assert_equal("\x8bo\xf7O\xa7\x18*\x90\xac ah\x16\xf7\xb8\x81JB\x9f|",
106
+ OpenID::CryptUtil.hmac_sha1('x', 'x'))
107
+ end
108
+
109
+ def test_sha256
110
+ assert_equal("-q\x16B\xb7&\xb0D\x01b|\xa9\xfb\xac2\xf5\xc8S\x0f\xb1\x90<\xc4\xdb\x02%\x87\x17\x92\x1aH\x81",
111
+ OpenID::CryptUtil.sha256('x'))
112
+ end
113
+
114
+ def test_hmac_sha256
115
+ assert_equal("\x94{\xd2w\xb2\xd3\\\xfc\x07\xfb\xc7\xe3b\xf2iuXz1\xf8:}\xffx\x8f\xda\xc1\xfaC\xc4\xb2\x87",
116
+ OpenID::CryptUtil.hmac_sha256('x', 'x'))
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,85 @@
1
+ require "test_helper"
2
+ require 'openid/dh'
3
+
4
+ module OpenID
5
+ class DiffieHellmanExposed < OpenID::DiffieHellman
6
+ def DiffieHellmanExposed.strxor_for_testing(a, b)
7
+ return DiffieHellmanExposed.strxor(a, b)
8
+ end
9
+ end
10
+
11
+ class DiffieHellmanTestCase < Test::Unit::TestCase
12
+ include OpenID::TestDataMixin
13
+
14
+ NUL = "\x00"
15
+
16
+ def test_strxor_success
17
+ [#input 1 input 2 expected
18
+ [NUL, NUL, NUL ],
19
+ ["\x01", NUL, "\x01" ],
20
+ ["a", "a", NUL ],
21
+ ["a", NUL, "a" ],
22
+ ["abc", NUL * 3, "abc" ],
23
+ ["x" * 10, NUL * 10, "x" * 10],
24
+ ["\x01", "\x02", "\x03" ],
25
+ ["\xf0", "\x0f", "\xff" ],
26
+ ["\xff", "\x0f", "\xf0" ],
27
+ ].each do |input1, input2, expected|
28
+ actual = DiffieHellmanExposed.strxor_for_testing(input1, input2)
29
+ assert_equal(expected, actual)
30
+ end
31
+ end
32
+
33
+ def test_strxor_failure
34
+ [
35
+ ['', 'a' ],
36
+ ['foo', 'ba' ],
37
+ [NUL * 3, NUL * 4],
38
+ [255, 127 ].map{|h| (0..h).map{|i|i.chr}.join('')},
39
+ ].each do |aa, bb|
40
+ assert_raises(ArgumentError) {
41
+ DiffieHellmanExposed.strxor(aa, bb)
42
+ }
43
+ end
44
+ end
45
+
46
+ def test_simple_exchange
47
+ dh1 = DiffieHellman.from_defaults()
48
+ dh2 = DiffieHellman.from_defaults()
49
+ secret1 = dh1.get_shared_secret(dh2.public)
50
+ secret2 = dh2.get_shared_secret(dh1.public)
51
+ assert_equal(secret1, secret2)
52
+ end
53
+
54
+ def test_xor_secret
55
+ dh1 = DiffieHellman.from_defaults()
56
+ dh2 = DiffieHellman.from_defaults()
57
+ secret = "Shhhhhh! don't tell!"
58
+ encrypted = dh1.xor_secret((CryptUtil.method :sha1), dh2.public, secret)
59
+ decrypted = dh2.xor_secret((CryptUtil.method :sha1), dh1.public, encrypted)
60
+ assert_equal(secret, decrypted)
61
+ end
62
+
63
+ def test_dh
64
+ dh = DiffieHellman.from_defaults()
65
+ class << dh
66
+ def set_private_test(priv)
67
+ set_private(priv)
68
+ end
69
+ end
70
+
71
+ read_data_file('dh.txt', true).each do |line|
72
+ priv, pub = line.split(' ').map {|x| x.to_i}
73
+ dh.set_private_test(priv)
74
+ assert_equal(dh.public, pub)
75
+ end
76
+ end
77
+
78
+ def test_using_defaults
79
+ dh = DiffieHellman.from_defaults()
80
+ assert(dh.using_default_values?)
81
+ dh = DiffieHellman.new(3, 2750161)
82
+ assert(!dh.using_default_values?)
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,848 @@
1
+ require 'test_helper'
2
+ require 'openid/fetchers'
3
+ require 'openid/yadis/discovery'
4
+ require 'openid/consumer/discovery'
5
+ require 'openid/yadis/xrires'
6
+ require 'openid/yadis/xri'
7
+ require 'openid/message'
8
+ require 'openid/util'
9
+
10
+ ### Tests for conditions that trigger DiscoveryFailure
11
+
12
+ module OpenID
13
+ class SimpleMockFetcher
14
+ def initialize(test, responses)
15
+ @test = test
16
+ @responses = responses.dup
17
+ end
18
+
19
+ def fetch(url, body=nil, headers=nil, limit=nil)
20
+ response = @responses.shift
21
+ @test.assert(body.nil?)
22
+ @test.assert_equal(response.final_url, url)
23
+ return response
24
+ end
25
+ end
26
+
27
+ class TestDiscoveryFailure < Test::Unit::TestCase
28
+ def initialize(*args)
29
+ super(*args)
30
+
31
+ @responses = [
32
+ [HTTPResponse._from_raw_data(nil, nil, {}, 'http://network.error/')],
33
+ [HTTPResponse._from_raw_data(404, nil, {}, 'http://not.found/')],
34
+ [HTTPResponse._from_raw_data(400, nil, {}, 'http://bad.request/')],
35
+ [HTTPResponse._from_raw_data(500, nil, {}, 'http://server.error/')],
36
+ [HTTPResponse._from_raw_data(200, nil, {'x-xrds-location' => 'http://xrds.missing/'},
37
+ 'http://header.found/'),
38
+ HTTPResponse._from_raw_data(404, nil, {}, 'http://xrds.missing/')],
39
+ ]
40
+ end
41
+
42
+ def test_discovery_failure
43
+
44
+ @responses.each { |response_set|
45
+ @url = response_set[0].final_url
46
+ OpenID.fetcher = SimpleMockFetcher.new(self, response_set)
47
+
48
+ expected_status = response_set[-1].code
49
+ begin
50
+ OpenID.discover(@url)
51
+ rescue DiscoveryFailure => why
52
+ assert_equal(why.http_response.code, expected_status)
53
+ else
54
+ flunk('Did not raise DiscoveryFailure')
55
+ end
56
+
57
+ OpenID.fetcher = nil
58
+ }
59
+ end
60
+ end
61
+
62
+ ### Tests for raising/catching exceptions from the fetcher through
63
+ ### the discover function
64
+
65
+ class ErrorRaisingFetcher
66
+ # Just raise an exception when fetch is called
67
+
68
+ def initialize(thing_to_raise)
69
+ @thing_to_raise = thing_to_raise
70
+ end
71
+
72
+ def fetch(url, body=nil, headers=nil, limit=nil)
73
+ raise @thing_to_raise
74
+ end
75
+ end
76
+
77
+ class DidFetch < Exception
78
+ # Custom exception just to make sure it's not handled differently
79
+ end
80
+
81
+ class TestFetchException < Test::Unit::TestCase
82
+ # Discovery should only raise DiscoveryFailure
83
+
84
+ def initialize(*args)
85
+ super(*args)
86
+
87
+ @cases = [
88
+ DidFetch.new(),
89
+ Exception.new(),
90
+ ArgumentError.new(),
91
+ RuntimeError.new(),
92
+ ]
93
+ end
94
+
95
+ def test_fetch_exception
96
+ @cases.each { |exc|
97
+ OpenID.fetcher = ErrorRaisingFetcher.new(exc)
98
+ assert_raises(DiscoveryFailure) {
99
+ OpenID.discover('http://doesnt.matter/')
100
+ }
101
+ OpenID.fetcher = nil
102
+ }
103
+ end
104
+ end
105
+
106
+ ### Tests for openid.consumer.discover.discover
107
+
108
+ class TestNormalization < Test::Unit::TestCase
109
+ def test_addingProtocol
110
+ f = ErrorRaisingFetcher.new(RuntimeError.new())
111
+ OpenID.fetcher = f
112
+
113
+ begin
114
+ OpenID.discover('users.stompy.janrain.com:8000/x')
115
+ rescue DiscoveryFailure => why
116
+ assert why.to_s.match("Failed to fetch")
117
+ rescue RuntimeError
118
+ end
119
+
120
+ OpenID.fetcher = nil
121
+ end
122
+ end
123
+
124
+ class DiscoveryMockFetcher
125
+ def initialize(documents)
126
+ @redirect = nil
127
+ @documents = documents
128
+ @fetchlog = []
129
+ end
130
+
131
+ def fetch(url, body=nil, headers=nil, limit=nil)
132
+ @fetchlog << [url, body, headers]
133
+ if @redirect
134
+ final_url = @redirect
135
+ else
136
+ final_url = url
137
+ end
138
+
139
+ begin
140
+ ctype, body = @documents.fetch(url)
141
+ rescue IndexError
142
+ status = 404
143
+ ctype = 'text/plain'
144
+ body = ''
145
+ else
146
+ status = 200
147
+ end
148
+
149
+ return HTTPResponse._from_raw_data(status, body, {'content-type' => ctype}, final_url)
150
+ end
151
+ end
152
+
153
+ class BaseTestDiscovery < Test::Unit::TestCase
154
+ attr_accessor :id_url, :fetcher_class
155
+
156
+ def initialize(*args)
157
+ super(*args)
158
+ @id_url = "http://someuser.unittest/"
159
+ @documents = {}
160
+ @fetcher_class = DiscoveryMockFetcher
161
+ end
162
+
163
+ def _checkService(s, server_url, claimed_id=nil,
164
+ local_id=nil, canonical_id=nil,
165
+ types=nil, used_yadis=false,
166
+ display_identifier=nil)
167
+ assert_equal(server_url, s.server_url)
168
+ if types == ['2.0 OP']
169
+ assert(!claimed_id)
170
+ assert(!local_id)
171
+ assert(!s.claimed_id)
172
+ assert(!s.local_id)
173
+ assert(!s.get_local_id())
174
+ assert(!s.compatibility_mode())
175
+ assert(s.is_op_identifier())
176
+ assert_equal(s.preferred_namespace(),
177
+ OPENID_2_0_MESSAGE_NS)
178
+ else
179
+ assert_equal(claimed_id, s.claimed_id)
180
+ assert_equal(local_id, s.get_local_id())
181
+ end
182
+
183
+ if used_yadis
184
+ assert(s.used_yadis, "Expected to use Yadis")
185
+ else
186
+ assert(!s.used_yadis,
187
+ "Expected to use old-style discovery")
188
+ end
189
+
190
+ openid_types = {
191
+ '1.1' => OPENID_1_1_TYPE,
192
+ '1.0' => OPENID_1_0_TYPE,
193
+ '2.0' => OPENID_2_0_TYPE,
194
+ '2.0 OP' => OPENID_IDP_2_0_TYPE,
195
+ }
196
+
197
+ type_uris = types.collect { |t| openid_types[t] }
198
+
199
+ assert_equal(type_uris, s.type_uris)
200
+ assert_equal(canonical_id, s.canonical_id)
201
+
202
+ if canonical_id.nil?
203
+ assert_equal(claimed_id, s.display_identifier)
204
+ else
205
+ assert_equal(display_identifier, s.display_identifier)
206
+ end
207
+ end
208
+
209
+ def setup
210
+ # @documents = @documents.dup
211
+ @fetcher = @fetcher_class.new(@documents)
212
+ OpenID.fetcher = @fetcher
213
+ end
214
+
215
+ def teardown
216
+ OpenID.fetcher = nil
217
+ end
218
+
219
+ def test_blank
220
+ # XXX to avoid > 0 test requirement
221
+ end
222
+ end
223
+
224
+ # def readDataFile(filename):
225
+ # module_directory = os.path.dirname(os.path.abspath(__file__))
226
+ # filename = os.path.join(
227
+ # module_directory, 'yadis_data', 'test_discover', filename)
228
+ # return file(filename).read()
229
+
230
+ class TestDiscovery < BaseTestDiscovery
231
+ include TestDataMixin
232
+
233
+ def _discover(content_type, data,
234
+ expected_services, expected_id=nil)
235
+ if expected_id.nil?
236
+ expected_id = @id_url
237
+ end
238
+
239
+ @documents[@id_url] = [content_type, data]
240
+ id_url, services = OpenID.discover(@id_url)
241
+
242
+ assert_equal(expected_services, services.length)
243
+ assert_equal(expected_id, id_url)
244
+ return services
245
+ end
246
+
247
+ def test_404
248
+ assert_raise(DiscoveryFailure) {
249
+ OpenID.discover(@id_url + '/404')
250
+ }
251
+ end
252
+
253
+ def test_noOpenID
254
+ services = _discover('text/plain',
255
+ "junk", 0)
256
+
257
+ services = _discover(
258
+ 'text/html',
259
+ read_data_file('test_discover/openid_no_delegate.html', false),
260
+ 1)
261
+
262
+ _checkService(
263
+ services[0],
264
+ "http://www.myopenid.com/server",
265
+ @id_url,
266
+ @id_url,
267
+ nil,
268
+ ['1.1'],
269
+ false)
270
+ end
271
+
272
+ def test_malformed_meta_tag
273
+ @id_url = "http://user.myopenid.com/"
274
+
275
+ services = _discover(
276
+ 'text/html',
277
+ read_data_file('test_discover/malformed_meta_tag.html', false),
278
+ 2)
279
+
280
+ _checkService(
281
+ services[0],
282
+ "http://www.myopenid.com/server",
283
+ @id_url,
284
+ @id_url,
285
+ nil,
286
+ ['2.0'],
287
+ false)
288
+
289
+ _checkService(
290
+ services[1],
291
+ "http://www.myopenid.com/server",
292
+ @id_url,
293
+ @id_url,
294
+ nil,
295
+ ['1.1'],
296
+ false)
297
+ end
298
+
299
+ def test_html1
300
+ services = _discover('text/html',
301
+ read_data_file('test_discover/openid.html', false),
302
+ 1)
303
+
304
+ _checkService(services[0],
305
+ "http://www.myopenid.com/server",
306
+ @id_url,
307
+ 'http://smoker.myopenid.com/',
308
+ nil,
309
+ ['1.1'],
310
+ false)
311
+ end
312
+
313
+ def test_html1Fragment
314
+ # Ensure that the Claimed Identifier does not have a fragment if
315
+ # one is supplied in the User Input.
316
+ content_type = 'text/html'
317
+ data = read_data_file('test_discover/openid.html', false)
318
+ expected_services = 1
319
+
320
+ @documents[@id_url] = [content_type, data]
321
+ expected_id = @id_url
322
+ @id_url = @id_url + '#fragment'
323
+ id_url, services = OpenID.discover(@id_url)
324
+
325
+ assert_equal(expected_services, services.length)
326
+ assert_equal(expected_id, id_url)
327
+
328
+ _checkService(services[0],
329
+ "http://www.myopenid.com/server",
330
+ expected_id,
331
+ 'http://smoker.myopenid.com/',
332
+ nil,
333
+ ['1.1'],
334
+ false)
335
+ end
336
+
337
+ def test_html2
338
+ services = _discover('text/html',
339
+ read_data_file('test_discover/openid2.html', false),
340
+ 1)
341
+
342
+ _checkService(services[0],
343
+ "http://www.myopenid.com/server",
344
+ @id_url,
345
+ 'http://smoker.myopenid.com/',
346
+ nil,
347
+ ['2.0'],
348
+ false)
349
+ end
350
+
351
+ def test_html1And2
352
+ services = _discover(
353
+ 'text/html',
354
+ read_data_file('test_discover/openid_1_and_2.html', false),
355
+ 2)
356
+
357
+ services.zip(['2.0', '1.1']).each { |s, t|
358
+ _checkService(s,
359
+ "http://www.myopenid.com/server",
360
+ @id_url,
361
+ 'http://smoker.myopenid.com/',
362
+ nil,
363
+ [t],
364
+ false)
365
+ }
366
+ end
367
+
368
+ def test_html_utf8
369
+ utf8_html = read_data_file('test_discover/openid_utf8.html', false)
370
+ utf8_html.force_encoding("UTF-8") if utf8_html.respond_to?(:force_encoding)
371
+ services = _discover('text/html', utf8_html, 1)
372
+
373
+ _checkService(services[0],
374
+ "http://www.myopenid.com/server",
375
+ @id_url,
376
+ 'http://smoker.myopenid.com/',
377
+ nil,
378
+ ['1.1'],
379
+ false)
380
+ end
381
+
382
+ def test_yadisEmpty
383
+ services = _discover('application/xrds+xml',
384
+ read_data_file('test_discover/yadis_0entries.xml', false),
385
+ 0)
386
+ end
387
+
388
+ def test_htmlEmptyYadis
389
+ # HTML document has discovery information, but points to an
390
+ # empty Yadis document. The XRDS document pointed to by
391
+ # "openid_and_yadis.html"
392
+ @documents[@id_url + 'xrds'] = ['application/xrds+xml',
393
+ read_data_file('test_discover/yadis_0entries.xml', false)]
394
+
395
+ services = _discover('text/html',
396
+ read_data_file('test_discover/openid_and_yadis.html', false),
397
+ 1)
398
+
399
+ _checkService(services[0],
400
+ "http://www.myopenid.com/server",
401
+ @id_url,
402
+ 'http://smoker.myopenid.com/',
403
+ nil,
404
+ ['1.1'],
405
+ false)
406
+ end
407
+
408
+ def test_yadis1NoDelegate
409
+ services = _discover('application/xrds+xml',
410
+ read_data_file('test_discover/yadis_no_delegate.xml', false),
411
+ 1)
412
+
413
+ _checkService(services[0],
414
+ "http://www.myopenid.com/server",
415
+ @id_url,
416
+ @id_url,
417
+ nil,
418
+ ['1.0'],
419
+ true)
420
+ end
421
+
422
+ def test_yadis2NoLocalID
423
+ services = _discover('application/xrds+xml',
424
+ read_data_file('test_discover/openid2_xrds_no_local_id.xml', false),
425
+ 1)
426
+
427
+ _checkService(services[0],
428
+ "http://www.myopenid.com/server",
429
+ @id_url,
430
+ @id_url,
431
+ nil,
432
+ ['2.0'],
433
+ true)
434
+ end
435
+
436
+ def test_yadis2
437
+ services = _discover('application/xrds+xml',
438
+ read_data_file('test_discover/openid2_xrds.xml', false),
439
+ 1)
440
+
441
+ _checkService(services[0],
442
+ "http://www.myopenid.com/server",
443
+ @id_url,
444
+ 'http://smoker.myopenid.com/',
445
+ nil,
446
+ ['2.0'],
447
+ true)
448
+ end
449
+
450
+ def test_yadis2OP
451
+ services = _discover('application/xrds+xml',
452
+ read_data_file('test_discover/yadis_idp.xml', false),
453
+ 1)
454
+
455
+ _checkService(services[0],
456
+ "http://www.myopenid.com/server",
457
+ nil, nil, nil,
458
+ ['2.0 OP'],
459
+ true)
460
+ end
461
+
462
+ def test_yadis2OPDelegate
463
+ # The delegate tag isn't meaningful for OP entries.
464
+ services = _discover('application/xrds+xml',
465
+ read_data_file('test_discover/yadis_idp_delegate.xml', false),
466
+ 1)
467
+
468
+ _checkService(services[0],
469
+ "http://www.myopenid.com/server",
470
+ nil, nil, nil,
471
+ ['2.0 OP'],
472
+ true)
473
+ end
474
+
475
+ def test_yadis2BadLocalID
476
+ assert_raise(DiscoveryFailure) {
477
+ _discover('application/xrds+xml',
478
+ read_data_file('test_discover/yadis_2_bad_local_id.xml', false),
479
+ 1)
480
+ }
481
+ end
482
+
483
+ def test_yadis1And2
484
+ services = _discover('application/xrds+xml',
485
+ read_data_file('test_discover/openid_1_and_2_xrds.xml', false),
486
+ 1)
487
+
488
+ _checkService(services[0],
489
+ "http://www.myopenid.com/server",
490
+ @id_url,
491
+ 'http://smoker.myopenid.com/',
492
+ nil,
493
+ ['2.0', '1.1'],
494
+ true)
495
+ end
496
+
497
+ def test_yadis1And2BadLocalID
498
+ assert_raise(DiscoveryFailure) {
499
+ _discover('application/xrds+xml',
500
+ read_data_file('test_discover/openid_1_and_2_xrds_bad_delegate.xml', false),
501
+ 1)
502
+ }
503
+ end
504
+ end
505
+
506
+ class MockFetcherForXRIProxy
507
+
508
+ def initialize(documents, proxy_url=Yadis::XRI::ProxyResolver::DEFAULT_PROXY)
509
+ @documents = documents
510
+ @fetchlog = []
511
+ @proxy_url = nil
512
+ end
513
+
514
+ def fetch(url, body=nil, headers=nil, limit=nil)
515
+ @fetchlog << [url, body, headers]
516
+
517
+ u = URI::parse(url)
518
+ proxy_host = u.host
519
+ xri = u.path
520
+ query = u.query
521
+
522
+ if !headers and !query
523
+ raise ArgumentError.new("No headers or query; you probably didn't " +
524
+ "mean to do that.")
525
+ end
526
+
527
+ if xri.starts_with?('/')
528
+ xri = xri[1..-1]
529
+ end
530
+
531
+ begin
532
+ ctype, body = @documents.fetch(xri)
533
+ rescue IndexError
534
+ status = 404
535
+ ctype = 'text/plain'
536
+ body = ''
537
+ else
538
+ status = 200
539
+ end
540
+
541
+ return HTTPResponse._from_raw_data(status, body,
542
+ {'content-type' => ctype}, url)
543
+ end
544
+ end
545
+
546
+ class TestXRIDiscovery < BaseTestDiscovery
547
+
548
+ include TestDataMixin
549
+ include TestUtil
550
+
551
+ def initialize(*args)
552
+ super(*args)
553
+
554
+ @fetcher_class = MockFetcherForXRIProxy
555
+
556
+ @documents = {'=smoker' => ['application/xrds+xml',
557
+ read_data_file('test_discover/yadis_2entries_delegate.xml', false)],
558
+ '=smoker*bad' => ['application/xrds+xml',
559
+ read_data_file('test_discover/yadis_another_delegate.xml', false)]}
560
+ end
561
+
562
+ def test_xri
563
+ user_xri, services = OpenID.discover_xri('=smoker')
564
+
565
+ _checkService(services[0],
566
+ "http://www.myopenid.com/server",
567
+ Yadis::XRI.make_xri("=!1000"),
568
+ 'http://smoker.myopenid.com/',
569
+ Yadis::XRI.make_xri("=!1000"),
570
+ ['1.0'],
571
+ true,
572
+ '=smoker')
573
+
574
+ _checkService(services[1],
575
+ "http://www.livejournal.com/openid/server.bml",
576
+ Yadis::XRI.make_xri("=!1000"),
577
+ 'http://frank.livejournal.com/',
578
+ Yadis::XRI.make_xri("=!1000"),
579
+ ['1.0'],
580
+ true,
581
+ '=smoker')
582
+ end
583
+
584
+ def test_xri_normalize
585
+ user_xri, services = OpenID.discover_xri('xri://=smoker')
586
+
587
+ _checkService(services[0],
588
+ "http://www.myopenid.com/server",
589
+ Yadis::XRI.make_xri("=!1000"),
590
+ 'http://smoker.myopenid.com/',
591
+ Yadis::XRI.make_xri("=!1000"),
592
+ ['1.0'],
593
+ true,
594
+ '=smoker')
595
+
596
+ _checkService(services[1],
597
+ "http://www.livejournal.com/openid/server.bml",
598
+ Yadis::XRI.make_xri("=!1000"),
599
+ 'http://frank.livejournal.com/',
600
+ Yadis::XRI.make_xri("=!1000"),
601
+ ['1.0'],
602
+ true,
603
+ '=smoker')
604
+ end
605
+
606
+ def test_xriNoCanonicalID
607
+ silence_logging {
608
+ user_xri, services = OpenID.discover_xri('=smoker*bad')
609
+ assert(services.empty?)
610
+ }
611
+ end
612
+
613
+ def test_useCanonicalID
614
+ # When there is no delegate, the CanonicalID should be used with
615
+ # XRI.
616
+ endpoint = OpenIDServiceEndpoint.new()
617
+ endpoint.claimed_id = Yadis::XRI.make_xri("=!1000")
618
+ endpoint.canonical_id = Yadis::XRI.make_xri("=!1000")
619
+ assert_equal(endpoint.get_local_id, Yadis::XRI.make_xri("=!1000"))
620
+ end
621
+ end
622
+
623
+ class TestXRIDiscoveryIDP < BaseTestDiscovery
624
+ include TestDataMixin
625
+
626
+ def initialize(*args)
627
+ super(*args)
628
+
629
+ @fetcher_class = MockFetcherForXRIProxy
630
+
631
+ @documents = {'=smoker' => ['application/xrds+xml',
632
+ read_data_file('test_discover/yadis_2entries_idp.xml', false)] }
633
+ end
634
+
635
+ def test_xri
636
+ user_xri, services = OpenID.discover_xri('=smoker')
637
+ assert(!services.empty?, "Expected services, got zero")
638
+ assert_equal(services[0].server_url,
639
+ "http://www.livejournal.com/openid/server.bml")
640
+ end
641
+ end
642
+
643
+ class TestPreferredNamespace < Test::Unit::TestCase
644
+ def initialize(*args)
645
+ super(*args)
646
+
647
+ @cases = [
648
+ [OPENID1_NS, []],
649
+ [OPENID1_NS, ['http://jyte.com/']],
650
+ [OPENID1_NS, [OPENID_1_0_TYPE]],
651
+ [OPENID1_NS, [OPENID_1_1_TYPE]],
652
+ [OPENID2_NS, [OPENID_2_0_TYPE]],
653
+ [OPENID2_NS, [OPENID_IDP_2_0_TYPE]],
654
+ [OPENID2_NS, [OPENID_2_0_TYPE,
655
+ OPENID_1_0_TYPE]],
656
+ [OPENID2_NS, [OPENID_1_0_TYPE,
657
+ OPENID_2_0_TYPE]],
658
+ ]
659
+ end
660
+
661
+ def test_preferred_namespace
662
+
663
+ @cases.each { |expected_ns, type_uris|
664
+ endpoint = OpenIDServiceEndpoint.new()
665
+ endpoint.type_uris = type_uris
666
+ actual_ns = endpoint.preferred_namespace()
667
+ assert_equal(actual_ns, expected_ns)
668
+ }
669
+ end
670
+ end
671
+
672
+ class TestIsOPIdentifier < Test::Unit::TestCase
673
+ def setup
674
+ @endpoint = OpenIDServiceEndpoint.new()
675
+ end
676
+
677
+ def test_none
678
+ assert(!@endpoint.is_op_identifier())
679
+ end
680
+
681
+ def test_openid1_0
682
+ @endpoint.type_uris = [OPENID_1_0_TYPE]
683
+ assert(!@endpoint.is_op_identifier())
684
+ end
685
+
686
+ def test_openid1_1
687
+ @endpoint.type_uris = [OPENID_1_1_TYPE]
688
+ assert(!@endpoint.is_op_identifier())
689
+ end
690
+
691
+ def test_openid2
692
+ @endpoint.type_uris = [OPENID_2_0_TYPE]
693
+ assert(!@endpoint.is_op_identifier())
694
+ end
695
+
696
+ def test_openid2OP
697
+ @endpoint.type_uris = [OPENID_IDP_2_0_TYPE]
698
+ assert(@endpoint.is_op_identifier())
699
+ end
700
+
701
+ def test_multipleMissing
702
+ @endpoint.type_uris = [OPENID_2_0_TYPE,
703
+ OPENID_1_0_TYPE]
704
+ assert(!@endpoint.is_op_identifier())
705
+ end
706
+
707
+ def test_multiplePresent
708
+ @endpoint.type_uris = [OPENID_2_0_TYPE,
709
+ OPENID_1_0_TYPE,
710
+ OPENID_IDP_2_0_TYPE]
711
+ assert(@endpoint.is_op_identifier())
712
+ end
713
+ end
714
+
715
+ class TestFromOPEndpointURL < Test::Unit::TestCase
716
+ def setup
717
+ @op_endpoint_url = 'http://example.com/op/endpoint'
718
+ @endpoint = OpenIDServiceEndpoint.from_op_endpoint_url(@op_endpoint_url)
719
+ end
720
+
721
+ def test_isOPEndpoint
722
+ assert(@endpoint.is_op_identifier())
723
+ end
724
+
725
+ def test_noIdentifiers
726
+ assert_equal(@endpoint.get_local_id, nil)
727
+ assert_equal(@endpoint.claimed_id, nil)
728
+ end
729
+
730
+ def test_compatibility
731
+ assert(!@endpoint.compatibility_mode())
732
+ end
733
+
734
+ def test_canonical_id
735
+ assert_equal(@endpoint.canonical_id, nil)
736
+ end
737
+
738
+ def test_serverURL
739
+ assert_equal(@endpoint.server_url, @op_endpoint_url)
740
+ end
741
+ end
742
+
743
+ class TestDiscoverFunction < Test::Unit::TestCase
744
+ def test_discover_function
745
+ # XXX these were all different tests in python, but they're
746
+ # combined here so I only have to use with_method_overridden
747
+ # once.
748
+ discoverXRI = Proc.new { |identifier|
749
+ return 'XRI'
750
+ }
751
+
752
+ discoverURI = Proc.new { |identifier|
753
+ return 'URI'
754
+ }
755
+
756
+ OpenID.extend(OverrideMethodMixin)
757
+
758
+ OpenID.with_method_overridden(:discover_uri, discoverURI) do
759
+ OpenID.with_method_overridden(:discover_xri, discoverXRI) do
760
+ assert_equal('URI', OpenID.discover('http://woo!'))
761
+ assert_equal('URI', OpenID.discover('not a URL or XRI'))
762
+ assert_equal('XRI', OpenID.discover('xri://=something'))
763
+ assert_equal('XRI', OpenID.discover('=something'))
764
+ end
765
+ end
766
+ end
767
+ end
768
+
769
+ class TestEndpointSupportsType < Test::Unit::TestCase
770
+ def setup
771
+ @endpoint = OpenIDServiceEndpoint.new()
772
+ end
773
+
774
+ def failUnlessSupportsOnly(*types)
775
+ ['foo',
776
+ OPENID_1_1_TYPE,
777
+ OPENID_1_0_TYPE,
778
+ OPENID_2_0_TYPE,
779
+ OPENID_IDP_2_0_TYPE].each { |t|
780
+ if types.member?(t)
781
+ assert(@endpoint.supports_type(t),
782
+ sprintf("Must support %s", t))
783
+ else
784
+ assert(!@endpoint.supports_type(t),
785
+ sprintf("Shouldn't support %s", t))
786
+ end
787
+ }
788
+ end
789
+
790
+ def test_supportsNothing
791
+ failUnlessSupportsOnly()
792
+ end
793
+
794
+ def test_openid2
795
+ @endpoint.type_uris = [OPENID_2_0_TYPE]
796
+ failUnlessSupportsOnly(OPENID_2_0_TYPE)
797
+ end
798
+
799
+ def test_openid2provider
800
+ @endpoint.type_uris = [OPENID_IDP_2_0_TYPE]
801
+ failUnlessSupportsOnly(OPENID_IDP_2_0_TYPE,
802
+ OPENID_2_0_TYPE)
803
+ end
804
+
805
+ def test_openid1_0
806
+ @endpoint.type_uris = [OPENID_1_0_TYPE]
807
+ failUnlessSupportsOnly(OPENID_1_0_TYPE)
808
+ end
809
+
810
+ def test_openid1_1
811
+ @endpoint.type_uris = [OPENID_1_1_TYPE]
812
+ failUnlessSupportsOnly(OPENID_1_1_TYPE)
813
+ end
814
+
815
+ def test_multiple
816
+ @endpoint.type_uris = [OPENID_1_1_TYPE,
817
+ OPENID_2_0_TYPE]
818
+ failUnlessSupportsOnly(OPENID_1_1_TYPE,
819
+ OPENID_2_0_TYPE)
820
+ end
821
+
822
+ def test_multipleWithProvider
823
+ @endpoint.type_uris = [OPENID_1_1_TYPE,
824
+ OPENID_2_0_TYPE,
825
+ OPENID_IDP_2_0_TYPE]
826
+ failUnlessSupportsOnly(OPENID_1_1_TYPE,
827
+ OPENID_2_0_TYPE,
828
+ OPENID_IDP_2_0_TYPE)
829
+ end
830
+ end
831
+
832
+ class TestEndpointDisplayIdentifier < Test::Unit::TestCase
833
+ def test_strip_fragment
834
+ @endpoint = OpenIDServiceEndpoint.new()
835
+ @endpoint.claimed_id = 'http://recycled.invalid/#123'
836
+ assert_equal 'http://recycled.invalid/', @endpoint.display_identifier
837
+ end
838
+ end
839
+
840
+
841
+ class TestNormalizeURL < Test::Unit::TestCase
842
+ def test_no_host
843
+ assert_raise(DiscoveryFailure) {
844
+ OpenID::normalize_url('http:///too-many.invalid/slashes')
845
+ }
846
+ end
847
+ end
848
+ end