Refactored test helpers to remove TestSupport and move its functionality into OpenIdT...
[dotnetoauth.git] / src / DotNetOpenAuth.Test / OpenId / XriIdentifierTests.cs
blob87ecd4bd2a28b9d379624a02e21919cc068fb5f3
1 //-----------------------------------------------------------------------
2 // <copyright file="XriIdentifierTests.cs" company="Andrew Arnott">
3 // Copyright (c) Andrew Arnott. All rights reserved.
4 // </copyright>
5 //-----------------------------------------------------------------------
7 namespace DotNetOpenAuth.Test.OpenId {
8 using System;
9 using System.Collections.Generic;
10 using System.Linq;
11 using DotNetOpenAuth.OpenId;
12 using DotNetOpenAuth.OpenId.RelyingParty;
13 using Microsoft.VisualStudio.TestTools.UnitTesting;
15 [TestClass]
16 public class XriIdentifierTests : OpenIdTestBase {
17 private string goodXri = "=Andrew*Arnott";
18 private string badXri = "some\\wacky%^&*()non-XRI";
20 [TestInitialize]
21 public override void SetUp() {
22 base.SetUp();
25 [TestMethod, ExpectedException(typeof(ArgumentNullException))]
26 public void CtorNull() {
27 new XriIdentifier(null);
30 [TestMethod, ExpectedException(typeof(ArgumentException))]
31 public void CtorBlank() {
32 new XriIdentifier(string.Empty);
35 [TestMethod, ExpectedException(typeof(FormatException))]
36 public void CtorBadXri() {
37 new XriIdentifier(this.badXri);
40 [TestMethod]
41 public void CtorGoodXri() {
42 var xri = new XriIdentifier(this.goodXri);
43 Assert.AreEqual(this.goodXri, xri.OriginalXri);
44 Assert.AreEqual(this.goodXri, xri.CanonicalXri); // assumes 'goodXri' is canonical already
45 Assert.IsFalse(xri.IsDiscoverySecureEndToEnd);
48 [TestMethod]
49 public void CtorGoodXriSecure() {
50 var xri = new XriIdentifier(this.goodXri, true);
51 Assert.AreEqual(this.goodXri, xri.OriginalXri);
52 Assert.AreEqual(this.goodXri, xri.CanonicalXri); // assumes 'goodXri' is canonical already
53 Assert.IsTrue(xri.IsDiscoverySecureEndToEnd);
56 [TestMethod]
57 public void IsValid() {
58 Assert.IsTrue(XriIdentifier.IsValidXri(this.goodXri));
59 Assert.IsFalse(XriIdentifier.IsValidXri(this.badXri));
62 /// <summary>
63 /// Verifies 2.0 spec section 7.2#1
64 /// </summary>
65 [TestMethod]
66 public void StripXriScheme() {
67 var xri = new XriIdentifier("xri://" + this.goodXri);
68 Assert.AreEqual("xri://" + this.goodXri, xri.OriginalXri);
69 Assert.AreEqual(this.goodXri, xri.CanonicalXri);
72 [TestMethod]
73 public void TrimFragment() {
74 Identifier xri = new XriIdentifier(this.goodXri);
75 Assert.AreSame(xri, xri.TrimFragment());
78 [TestMethod]
79 public void ToStringTest() {
80 Assert.AreEqual(this.goodXri, new XriIdentifier(this.goodXri).ToString());
83 [TestMethod]
84 public void EqualsTest() {
85 Assert.AreEqual(new XriIdentifier(this.goodXri), new XriIdentifier(this.goodXri));
86 Assert.AreNotEqual(new XriIdentifier(this.goodXri), new XriIdentifier(this.goodXri + "a"));
87 Assert.AreNotEqual(null, new XriIdentifier(this.goodXri));
88 Assert.AreEqual(this.goodXri, new XriIdentifier(this.goodXri));
91 [TestMethod]
92 public void Discover() {
93 string xrds = @"<?xml version='1.0' encoding='UTF-8'?>
94 <XRD version='2.0' xmlns='xri://$xrd*($v*2.0)'>
95 <Query>*Arnott</Query>
96 <Status ceid='off' cid='verified' code='100'/>
97 <Expires>2008-07-14T02:03:24.000Z</Expires>
98 <ProviderID>xri://=</ProviderID>
99 <LocalID>!9b72.7dd1.50a9.5ccd</LocalID>
100 <CanonicalID>=!9B72.7DD1.50A9.5CCD</CanonicalID>
102 <Service priority='10'>
103 <ProviderID>xri://!!1008</ProviderID>
104 <Type select='true'>xri://+i-service*(+contact)*($v*1.0)</Type>
105 <Type match='default' select='false'/>
106 <Path select='true'>(+contact)</Path>
107 <Path match='null' select='false'/>
108 <URI append='qxri' priority='1'>http://1id.com/contact/</URI>
110 </Service>
111 <Service priority='10'>
112 <ProviderID>xri://!!1008</ProviderID>
113 <Type select='true'>xri://+i-service*(+forwarding)*($v*1.0)</Type>
114 <Type match='null' select='false'/>
115 <URI append='qxri' priority='1'>http://1id.com/</URI>
116 </Service>
118 <Service priority='10'>
119 <ProviderID>xri://!!1008</ProviderID>
120 <Type select='true'>http://openid.net/signon/1.0</Type>
121 <URI append='none' priority='10'>http://1id.com/sso</URI>
122 </Service>
123 </XRD>";
124 Dictionary<string, string> mocks = new Dictionary<string, string> {
125 { "https://xri.net/=Arnott?_xrd_r=application/xrd%2Bxml;sep=false", xrds },
126 { "https://xri.net/=!9B72.7DD1.50A9.5CCD?_xrd_r=application/xrd%2Bxml;sep=false", xrds },
128 this.MockResponder.RegisterMockXrdsResponses(mocks);
130 string expectedCanonicalId = "=!9B72.7DD1.50A9.5CCD";
131 ServiceEndpoint se = this.VerifyCanonicalId("=Arnott", expectedCanonicalId);
132 Assert.AreEqual(Protocol.V10, se.Protocol);
133 Assert.AreEqual("http://1id.com/sso", se.ProviderEndpoint.ToString());
134 Assert.AreEqual(se.ClaimedIdentifier, se.ProviderLocalIdentifier);
135 Assert.AreEqual("=Arnott", se.FriendlyIdentifierForDisplay);
138 [TestMethod]
139 public void DiscoverCommunityInameCanonicalIDs() {
140 string llliResponse = @"<?xml version='1.0' encoding='UTF-8'?>
141 <XRD version='2.0' xmlns='xri://$xrd*($v*2.0)'>
142 <Query>*llli</Query>
143 <Status ceid='off' cid='verified' code='100'/>
144 <Expires>2008-07-14T02:21:06.000Z</Expires>
145 <ProviderID>xri://@</ProviderID>
146 <LocalID>!72cd.a072.157e.a9c6</LocalID>
147 <CanonicalID>@!72CD.A072.157E.A9C6</CanonicalID>
148 <Service priority='10'>
149 <ProviderID>xri://!!1003!103</ProviderID>
150 <Type select='true'>http://openid.net/signon/1.0</Type>
151 <URI append='none' priority='1'>https://login.llli.org/server/</URI>
152 </Service>
153 <Service priority='1'>
154 <ProviderID>xri://!!1003!103</ProviderID>
155 <Type match='null' select='false'/>
156 <Type select='true'>xri://+i-service*(+forwarding)*($v*1.0)</Type>
157 <Path match='default'/>
158 <Path>(+index)</Path>
159 <URI append='qxri' priority='1'>http://linksafe-forward.ezibroker.net/forwarding/</URI>
160 </Service>
161 <Service priority='10'>
162 <ProviderID>xri://!!1003!103</ProviderID>
163 <Type select='true'>xri://$res*auth*($v*2.0)</Type>
164 <MediaType>application/xrds+xml;trust=none</MediaType>
165 <URI priority='10'>http://resolve.ezibroker.net/resolve/@llli/</URI>
166 </Service>
167 <Service priority='10'>
168 <ProviderID>xri://!!1003!103</ProviderID>
169 <Type select='true'>xri://+i-service*(+contact)*($v*1.0)</Type>
170 <Type match='null'/>
171 <Path select='true'>(+contact)</Path>
172 <Path match='null'/>
173 <URI append='authority' priority='1'>http://linksafe-contact.ezibroker.net/contact/</URI>
174 </Service>
175 </XRD>
177 string llliAreaResponse = @"<?xml version='1.0' encoding='UTF-8'?>
178 <XRD xmlns='xri://$xrd*($v*2.0)'>
179 <Query>*area</Query>
180 <Status cid='verified' code='100'>SUCCESS</Status>
181 <ServerStatus code='100'>SUCCESS</ServerStatus>
182 <Expires>2008-07-15T01:21:07.000Z</Expires>
183 <ProviderID>xri://!!1003</ProviderID>
184 <LocalID>0000.0000.3B9A.CA0C</LocalID>
185 <CanonicalID>@!72CD.A072.157E.A9C6!0000.0000.3B9A.CA0C</CanonicalID>
186 <Service>
187 <ProviderID>xri://!!1003!103</ProviderID>
188 <Type select='true'>http://openid.net/signon/1.0</Type>
189 <URI append='none' priority='1'>https://login.llli.org/server/</URI>
190 </Service>
191 <Service>
192 <ProviderID>xri://!!1003!103</ProviderID>
193 <Type select='true'>xri://+i-service*(+contact)*($v*1.0)</Type>
194 <Type match='null'/>
195 <Path select='true'>(+contact)</Path>
196 <Path match='null'/>
197 <URI append='authority' priority='1'>http://linksafe-contact.ezibroker.net/contact/</URI>
198 </Service>
199 <Service priority='1'>
200 <ProviderID>xri://!!1003!103</ProviderID>
201 <Type select='true'>xri://+i-service*(+forwarding)*($v*1.0)</Type>
202 <Type match='null' select='false'/>
203 <Path>(+index)</Path>
204 <Path match='default'/>
205 <URI append='qxri' priority='1'>http://linksafe-forward.ezibroker.net/forwarding/</URI>
206 </Service>
207 <Service>
208 <ProviderID>xri://!!1003!103</ProviderID>
209 <Type select='true'>xri://$res*auth*($v*2.0)</Type>
210 <MediaType>application/xrds+xml;trust=none</MediaType>
211 <URI>http://resolve.ezibroker.net/resolve/@llli*area/</URI>
212 </Service>
213 </XRD>";
214 string llliAreaCanadaUnattachedResponse = @"<?xml version='1.0' encoding='UTF-8'?>
215 <XRD xmlns='xri://$xrd*($v*2.0)'>
216 <Query>*canada.unattached</Query>
217 <Status cid='verified' code='100'>SUCCESS</Status>
218 <ServerStatus code='100'>SUCCESS</ServerStatus>
219 <Expires>2008-07-15T01:21:08.000Z</Expires>
220 <ProviderID>xri://!!1003</ProviderID>
221 <LocalID>0000.0000.3B9A.CA41</LocalID>
222 <CanonicalID>@!72CD.A072.157E.A9C6!0000.0000.3B9A.CA0C!0000.0000.3B9A.CA41</CanonicalID>
223 <Service>
224 <ProviderID>xri://!!1003!103</ProviderID>
225 <Type select='true'>http://openid.net/signon/1.0</Type>
226 <URI append='none' priority='1'>https://login.llli.org/server/</URI>
227 </Service>
228 <Service>
229 <ProviderID>xri://!!1003!103</ProviderID>
230 <Type select='true'>xri://+i-service*(+contact)*($v*1.0)</Type>
231 <Type match='null'/>
232 <Path select='true'>(+contact)</Path>
233 <Path match='null'/>
234 <URI append='authority' priority='1'>http://linksafe-contact.ezibroker.net/contact/</URI>
235 </Service>
236 <Service priority='1'>
237 <ProviderID>xri://!!1003!103</ProviderID>
238 <Type select='true'>xri://+i-service*(+forwarding)*($v*1.0)</Type>
239 <Type match='null' select='false'/>
240 <Path>(+index)</Path>
241 <Path match='default'/>
242 <URI append='qxri' priority='1'>http://linksafe-forward.ezibroker.net/forwarding/</URI>
243 </Service>
244 <Service>
245 <ProviderID>xri://!!1003!103</ProviderID>
246 <Type select='true'>xri://$res*auth*($v*2.0)</Type>
247 <MediaType>application/xrds+xml;trust=none</MediaType>
248 <URI>http://resolve.ezibroker.net/resolve/@llli*area*canada.unattached/</URI>
249 </Service>
250 </XRD>";
251 string llliAreaCanadaUnattachedAdaResponse = @"<?xml version='1.0' encoding='UTF-8'?>
252 <XRD xmlns='xri://$xrd*($v*2.0)'>
253 <Query>*ada</Query>
254 <Status cid='verified' code='100'>SUCCESS</Status>
255 <ServerStatus code='100'>SUCCESS</ServerStatus>
256 <Expires>2008-07-15T01:21:10.000Z</Expires>
257 <ProviderID>xri://!!1003</ProviderID>
258 <LocalID>0000.0000.3B9A.CA01</LocalID>
259 <CanonicalID>@!72CD.A072.157E.A9C6!0000.0000.3B9A.CA0C!0000.0000.3B9A.CA41!0000.0000.3B9A.CA01</CanonicalID>
260 <Service>
261 <ProviderID>xri://!!1003!103</ProviderID>
262 <Type select='true'>http://openid.net/signon/1.0</Type>
263 <URI append='none' priority='1'>https://login.llli.org/server/</URI>
264 </Service>
265 <Service>
266 <ProviderID>xri://!!1003!103</ProviderID>
267 <Type select='true'>xri://+i-service*(+contact)*($v*1.0)</Type>
268 <Type match='null'/>
269 <Path select='true'>(+contact)</Path>
270 <Path match='null'/>
271 <URI append='authority' priority='1'>http://linksafe-contact.ezibroker.net/contact/</URI>
272 </Service>
273 <Service priority='1'>
274 <ProviderID>xri://!!1003!103</ProviderID>
275 <Type select='true'>xri://+i-service*(+forwarding)*($v*1.0)</Type>
276 <Type match='null' select='false'/>
277 <Path>(+index)</Path>
278 <Path match='default'/>
279 <URI append='qxri' priority='1'>http://linksafe-forward.ezibroker.net/forwarding/</URI>
280 </Service>
281 </XRD>";
282 string webResponse = @"<?xml version='1.0' encoding='UTF-8'?>
283 <XRD version='2.0' xmlns='xri://$xrd*($v*2.0)'>
284 <Query>*Web</Query>
285 <Status ceid='off' cid='verified' code='100'/>
286 <Expires>2008-07-14T02:21:12.000Z</Expires>
287 <ProviderID>xri://=</ProviderID>
288 <LocalID>!91f2.8153.f600.ae24</LocalID>
289 <CanonicalID>=!91F2.8153.F600.AE24</CanonicalID>
290 <Service priority='10'>
291 <Type select='true'>xri://+i-service*(+locator)*($v*1.0)</Type>
292 <Path select='true'>(+locator)</Path>
293 <MediaType match='default' select='false'/>
294 <URI append='qxri'>http://locator.fullxri.com/locator/</URI>
295 </Service>
296 <Service priority='10'>
297 <ProviderID>xri://=web</ProviderID>
298 <Type select='true'>xri://$res*auth*($v*2.0)</Type>
299 <Type select='true'>xri://$res*auth*($v*2.0)</Type>
300 <MediaType select='true'>application/xrds+xml</MediaType>
301 <URI append='qxri' priority='1'>https://resolve.freexri.com/ns/=web/</URI>
302 <URI append='qxri' priority='2'>http://resolve.freexri.com/ns/=web/</URI>
303 </Service>
304 <Service priority='10'>
305 <Type select='true'>http://openid.net/signon/1.0</Type>
306 <Type select='true'>http://specs.openid.net/auth/2.0/signon</Type>
307 <Path select='true'>(+login)</Path>
308 <Path match='default' select='false'/>
309 <MediaType match='default' select='false'/>
310 <URI append='none' priority='2'>http://authn.fullxri.com/authentication/</URI>
311 <URI append='none' priority='1'>https://authn.fullxri.com/authentication/</URI>
312 </Service>
313 <Service priority='10'>
314 <Type select='true'>xri://+i-service*(+contact)*($v*1.0)</Type>
315 <Type match='null' select='false'/>
316 <Path select='true'>(+contact)</Path>
317 <Path match='null' select='false'/>
318 <MediaType match='default' select='false'/>
319 <URI append='qxri'>http://contact.fullxri.com/contact/</URI>
320 </Service>
321 <KeyInfo xmlns='http://www.w3.org/2000/09/xmldsig#'>
322 <X509Data>
323 <X509Certificate>
324 MIIExzCCA6+gAwIBAgIJAM+MlFr0Sth6MA0GCSqGSIb3DQEBBQUAMIGdMR8wHQYD
325 VQQDExZTdXBlcnZpbGxhaW46IFRoZSBSb290MQswCQYDVQQGEwJVUzERMA8GA1UE
326 CBMITmV3IFlvcmsxDzANBgNVBAcTBkdvdGhhbTEgMB4GA1UEChMXU3VwZXJ2aWxs
327 YWluIFVuaXZlcnNpdHkxJzAlBgkqhkiG9w0BCQEWGHBlbmd1aW5Ac3VwZXJ2aWxs
328 YWluLmVkdTAeFw0wNjA4MTcxOTU5NTNaFw0xMTA4MTYxOTU5NTNaMIGdMR8wHQYD
329 VQQDExZTdXBlcnZpbGxhaW46IFRoZSBSb290MQswCQYDVQQGEwJVUzERMA8GA1UE
330 CBMITmV3IFlvcmsxDzANBgNVBAcTBkdvdGhhbTEgMB4GA1UEChMXU3VwZXJ2aWxs
331 YWluIFVuaXZlcnNpdHkxJzAlBgkqhkiG9w0BCQEWGHBlbmd1aW5Ac3VwZXJ2aWxs
332 YWluLmVkdTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL6uFqas4dK6
333 A2wTZL0viRQNJrPyFnFBDSZGib/2ijhgzed/vvmZIBM9sFpwahcuR5hvyKUe37/c
334 /RSZXoNDi/eiNOx4qb0l9UB6bd8qvc4V1PnLE7L+ZYcmwrvTKm4x8qXMgEv1wca2
335 FPsreHNPdLiTUZ8v0tDTWi3Mgi7y47VTzJaTkcfmO1nL6xAtln5sLdH0PbMM3LAp
336 T1d3nwI3VdbhqqZ+6+OKEuC8gk5iH4lfrbr6C9bYS6vzIKrotHpZ3N2aIC3NMjJD
337 PMw/mfCuADfRNlHXgZW+0zyUkwGTMDea8qgsoAMWJGdeTIw8I1I3RhnbgLzdsNQl
338 b/1ZXx1uJRUCAwEAAaOCAQYwggECMB0GA1UdDgQWBBQe+xSjYTrlfraJARjMxscb
339 j36jvDCB0gYDVR0jBIHKMIHHgBQe+xSjYTrlfraJARjMxscbj36jvKGBo6SBoDCB
340 nTEfMB0GA1UEAxMWU3VwZXJ2aWxsYWluOiBUaGUgUm9vdDELMAkGA1UEBhMCVVMx
341 ETAPBgNVBAgTCE5ldyBZb3JrMQ8wDQYDVQQHEwZHb3RoYW0xIDAeBgNVBAoTF1N1
342 cGVydmlsbGFpbiBVbml2ZXJzaXR5MScwJQYJKoZIhvcNAQkBFhhwZW5ndWluQHN1
343 cGVydmlsbGFpbi5lZHWCCQDPjJRa9ErYejAMBgNVHRMEBTADAQH/MA0GCSqGSIb3
344 DQEBBQUAA4IBAQC4SPBDGYAxfbXd8N5OvG0drM7a5hjXfcCZpiILlPSRpxp79yh7
345 I5vVWxBxUfolwbei7PTBVy7CE27SUbSICeqWjcDCfjNjiZk6mLS80rm/TdLrHSyM
346 +Ujlw9MGcBGaLI+sdziDUMtTQDpeAyQTaGVbh1mx5874Hlo1VXqGYNo0RwR+iLfs
347 x48VuO6GbWVyxtktkE2ypz1KLWiyI056YynydRvuBCBHeRqGUixPlH9CrmeSCP2S
348 sfbiKnMOGXjIYbvbsTAMdW2iqg6IWa/fgxhvZoAXChM9bkhisJQc0qD0J5TJQwgr
349 uEyb50RJ7DWmXctSC0b3eymZ2lSXxAWNOsNy
350 </X509Certificate>
351 </X509Data>
352 </KeyInfo>
353 </XRD>";
354 this.MockResponder.RegisterMockXrdsResponses(new Dictionary<string, string> {
355 { "https://xri.net/@llli?_xrd_r=application/xrd%2Bxml;sep=false", llliResponse },
356 { "https://xri.net/@llli*area?_xrd_r=application/xrd%2Bxml;sep=false", llliAreaResponse },
357 { "https://xri.net/@llli*area*canada.unattached?_xrd_r=application/xrd%2Bxml;sep=false", llliAreaCanadaUnattachedResponse },
358 { "https://xri.net/@llli*area*canada.unattached*ada?_xrd_r=application/xrd%2Bxml;sep=false", llliAreaCanadaUnattachedAdaResponse },
359 { "https://xri.net/=Web?_xrd_r=application/xrd%2Bxml;sep=false", webResponse },
361 this.VerifyCanonicalId("@llli", "@!72CD.A072.157E.A9C6");
362 this.VerifyCanonicalId("@llli*area", "@!72CD.A072.157E.A9C6!0000.0000.3B9A.CA0C");
363 this.VerifyCanonicalId("@llli*area*canada.unattached", "@!72CD.A072.157E.A9C6!0000.0000.3B9A.CA0C!0000.0000.3B9A.CA41");
364 this.VerifyCanonicalId("@llli*area*canada.unattached*ada", "@!72CD.A072.157E.A9C6!0000.0000.3B9A.CA0C!0000.0000.3B9A.CA41!0000.0000.3B9A.CA01");
365 this.VerifyCanonicalId("=Web", "=!91F2.8153.F600.AE24");
368 [TestMethod]
369 public void DiscoveryCommunityInameDelegateWithoutCanonicalID() {
370 this.MockResponder.RegisterMockXrdsResponses(new Dictionary<string, string> {
371 { "https://xri.net/=Web*andrew.arnott?_xrd_r=application/xrd%2Bxml;sep=false", @"<?xml version='1.0' encoding='UTF-8'?>
372 <XRD xmlns='xri://$xrd*($v*2.0)'>
373 <Query>*andrew.arnott</Query>
374 <Status cid='absent' code='100'>Success</Status>
375 <ServerStatus code='100'>Success</ServerStatus>
376 <Expires>2008-07-14T03:30:59.722Z</Expires>
377 <ProviderID>=!91F2.8153.F600.AE24</ProviderID>
378 <Service>
379 <Type select='true'>http://openid.net/signon/1.0</Type>
380 <Path select='true'>(+login)</Path>
381 <Path match='default'/>
382 <MediaType match='default'/>
383 <URI append='none' priority='2'>http://www.myopenid.com/server</URI>
384 <openid:Delegate xmlns:openid='http://openid.net/xmlns/1.0'>http://blog.nerdbank.net</openid:Delegate>
385 </Service>
386 <Service>
387 <ProviderID>@!7F6F.F50.A4E4.1133</ProviderID>
388 <Type select='true'>xri://+i-service*(+contact)*($v*1.0)</Type>
389 <Type match='null'/>
390 <Path select='true'>(+contact)</Path>
391 <Path match='null'/>
392 <MediaType match='default'/>
393 <URI append='qxri'>http://contact.freexri.com/contact/</URI>
394 </Service>
395 <Service>
396 <ProviderID>@!7F6F.F50.A4E4.1133</ProviderID>
397 <Type select='true'>xri://+i-service*(+forwarding)*($v*1.0)</Type>
398 <Path select='true'>(+index)</Path>
399 <Path match='default'/>
400 <MediaType match='default'/>
401 <URI append='qxri'>http://forwarding.freexri.com/forwarding/</URI>
402 </Service>
403 <Service>
404 <ProviderID>@!7F6F.F50.A4E4.1133</ProviderID>
405 <Type select='true'>http://openid.net/signon/1.0</Type>
406 <Path select='true'>(+login)</Path>
407 <Path match='default'/>
408 <MediaType match='default'/>
409 <URI append='none' priority='2'>http://authn.freexri.com/authentication/</URI>
410 <URI append='none' priority='1'>https://authn.freexri.com/authentication/</URI>
411 </Service>
412 <ServedBy>OpenXRI</ServedBy>
413 </XRD>" },
414 { "https://xri.net/@id*andrewarnott?_xrd_r=application/xrd%2Bxml;sep=false", @"<?xml version='1.0' encoding='UTF-8'?>
415 <XRD xmlns='xri://$xrd*($v*2.0)'>
416 <Query>*andrewarnott</Query>
417 <Status cid='absent' code='100'>Success</Status>
418 <ServerStatus code='100'>Success</ServerStatus>
419 <Expires>2008-07-14T03:31:00.466Z</Expires>
420 <ProviderID>@!B1E8.C27B.E41C.25C3</ProviderID>
421 <Service>
422 <Type select='true'>http://openid.net/signon/1.0</Type>
423 <Path select='true'>(+login)</Path>
424 <Path match='default'/>
425 <MediaType match='default'/>
426 <URI append='none' priority='2'>http://www.myopenid.com/server</URI>
427 <openid:Delegate xmlns:openid='http://openid.net/xmlns/1.0'>http://blog.nerdbank.net</openid:Delegate>
428 </Service>
429 <Service>
430 <ProviderID>@!7F6F.F50.A4E4.1133</ProviderID>
431 <Type select='true'>xri://+i-service*(+contact)*($v*1.0)</Type>
432 <Type match='null'/>
433 <Path select='true'>(+contact)</Path>
434 <Path match='null'/>
435 <MediaType match='default'/>
436 <URI append='qxri'>http://contact.freexri.com/contact/</URI>
437 </Service>
438 <Service>
439 <ProviderID>@!7F6F.F50.A4E4.1133</ProviderID>
440 <Type select='true'>xri://+i-service*(+forwarding)*($v*1.0)</Type>
441 <Path select='true'>(+index)</Path>
442 <Path match='default'/>
443 <MediaType match='default'/>
444 <URI append='qxri'>http://forwarding.freexri.com/forwarding/</URI>
445 </Service>
446 <ServedBy>OpenXRI</ServedBy>
447 </XRD>" },
449 // Consistent with spec section 7.3.2.3, we do not permit
450 // delegation on XRI discovery when there is no CanonicalID present.
451 this.VerifyCanonicalId("=Web*andrew.arnott", null);
452 this.VerifyCanonicalId("@id*andrewarnott", null);
455 [TestMethod, Ignore] // XRI parsing and normalization is not implemented (yet).
456 public void NormalizeCase() {
457 Identifier id = "=!9B72.7dd1.50a9.5ccd";
458 Assert.AreEqual("=!9B72.7DD1.50A9.5CCD", id.ToString());
461 private ServiceEndpoint VerifyCanonicalId(Identifier iname, string expectedClaimedIdentifier) {
462 ServiceEndpoint se = iname.Discover(this.RequestHandler).FirstOrDefault();
463 if (expectedClaimedIdentifier != null) {
464 Assert.IsNotNull(se);
465 Assert.AreEqual(expectedClaimedIdentifier, se.ClaimedIdentifier.ToString(), "i-name {0} discovery resulted in unexpected CanonicalId", iname);
466 Assert.IsTrue(se.ProviderSupportedServiceTypeUris.Count > 0);
467 } else {
468 Assert.IsNull(se);
470 return se;