1  """Tests for the attribute exchange extension module 
  2  """ 
  3   
  4  import unittest 
  5  from openid.extensions import ax 
  6  from openid.message import NamespaceMap, Message, OPENID2_NS 
  7  from openid.consumer.consumer import SuccessResponse 
  8   
 13   
 17   
 21   
 23          check = self.bax._checkMode 
 24          self.failUnlessRaises(ax.NotAXMessage, check, {}) 
 25          self.failUnlessRaises(ax.AXError, check, {'mode':'fetch_request'}) 
 26   
 27           
 28          check({'mode':self.bax.mode}) 
  29   
 31          """_newArgs generates something that has the correct mode""" 
 32           
 33          self.bax._checkMode(self.bax._newArgs()) 
   34   
 35   
 38          self.failUnlessRaises(TypeError, ax.AttrInfo) 
 39          type_uri = 'a uri' 
 40          ainfo = ax.AttrInfo(type_uri) 
 41   
 42          self.failUnlessEqual(type_uri, ainfo.type_uri) 
 43          self.failUnlessEqual(1, ainfo.count) 
 44          self.failIf(ainfo.required) 
 45          self.failUnless(ainfo.alias is None) 
   46   
 47   
 51   
 53          for empty in [None, '']: 
 54              uris = ax.toTypeURIs(self.aliases, empty) 
 55              self.failUnlessEqual([], uris) 
  56   
 58          self.failUnlessRaises( 
 59              KeyError, 
 60              ax.toTypeURIs, self.aliases, 'http://janrain.com/') 
  61   
 63          uri = 'http://janrain.com/' 
 64          alias = 'openid_hackers' 
 65          self.aliases.addAlias(uri, alias) 
 66          uris = ax.toTypeURIs(self.aliases, alias) 
 67          self.failUnlessEqual([uri], uris) 
  68   
 70          uri1 = 'http://janrain.com/' 
 71          alias1 = 'openid_hackers' 
 72          self.aliases.addAlias(uri1, alias1) 
 73   
 74          uri2 = 'http://jyte.com/' 
 75          alias2 = 'openid_hack' 
 76          self.aliases.addAlias(uri2, alias2) 
 77   
 78          uris = ax.toTypeURIs(self.aliases, ','.join([alias1, alias2])) 
 79          self.failUnlessEqual([uri1, uri2], uris) 
   80   
 82      """Testing AXKeyValueMessage.parseExtensionArgs.""" 
 83   
 87   
 89          """Fail unless parseExtensionArgs(ax_args) == expected_args.""" 
 90          msg = ax.AXKeyValueMessage() 
 91          msg.parseExtensionArgs(ax_args) 
 92          self.failUnlessEqual(expected_args, msg.data) 
  93   
 96   
 99   
103   
110   
125   
137   
139          types = [ 
140              ax.AXKeyValueMessage, 
141              ax.FetchRequest 
142              ] 
143   
144          inputs = [ 
145              {'type.a.b':'urn:foo', 
146               'count.a.b':'1'}, 
147              {'type.a,b':'urn:foo', 
148               'count.a,b':'1'}, 
149              ] 
150   
151          for typ in types: 
152              for input in inputs: 
153                  msg = typ() 
154                  self.failUnlessRaises(ax.AXError, msg.parseExtensionArgs, 
155                                        input) 
 156   
158          self.failUnlessAXValues( 
159              {'type.foo':'urn:foo', 
160               'count.foo':'0', 
161               }, {'urn:foo':[]}) 
 162   
164          self.failUnlessAXValues( 
165              {'type.foo':'urn:foo', 
166               'value.foo':'', 
167               }, {'urn:foo':[]}) 
 168   
170          self.failUnlessAXKeyError( 
171              {'type.foo':'urn:foo', 
172               'value.foo':'', 
173               'type.bar':'urn:foo', 
174               'value.bar':'', 
175               }) 
 176   
178          self.failUnlessAXValues( 
179              {'type.foo':'urn:foo', 
180               'value.foo':'', 
181               'type.bar':'urn:bar', 
182               'value.bar':'', 
183               }, {'urn:foo':[], 'urn:bar':[]}) 
 184   
186          self.failUnlessAXValues( 
187              {'type.foo':'urn:foo', 
188               'value.foo':'Westfall', 
189               }, {'urn:foo':['Westfall']}) 
  190   
191   
194          self.msg = ax.FetchRequest() 
195          self.type_a = 'http://janrain.example.com/a' 
196          self.alias_a = 'a' 
 197   
198   
200          self.failUnlessEqual(self.msg.mode, 'fetch_request') 
 201   
203          self.failUnlessEqual({}, self.msg.requested_attributes) 
204          self.failUnlessEqual(None, self.msg.update_url) 
205   
206          msg = ax.FetchRequest('hailstorm') 
207          self.failUnlessEqual({}, msg.requested_attributes) 
208          self.failUnlessEqual('hailstorm', msg.update_url) 
 209   
211          uri = 'mud://puddle' 
212   
213           
214          self.failIf(uri in self.msg) 
215   
216          attr = ax.AttrInfo(uri) 
217          self.msg.add(attr) 
218   
219           
220          self.failUnless(uri in self.msg) 
 221   
223          uri = 'lightning://storm' 
224   
225          attr = ax.AttrInfo(uri) 
226          self.msg.add(attr) 
227          self.failUnlessRaises(KeyError, self.msg.add, attr) 
 228   
230          expected_args = { 
231              'mode':'fetch_request', 
232              } 
233          self.failUnlessEqual(expected_args, self.msg.getExtensionArgs()) 
 234   
236          attr = ax.AttrInfo( 
237              type_uri = 'type://of.transportation', 
238              ) 
239          self.msg.add(attr) 
240          ax_args = self.msg.getExtensionArgs() 
241          for k, v in ax_args.iteritems(): 
242              if v == attr.type_uri and k.startswith('type.'): 
243                  alias = k[5:] 
244                  break 
245          else: 
246              self.fail("Didn't find the type definition") 
247   
248          self.failUnlessExtensionArgs({ 
249              'type.' + alias:attr.type_uri, 
250              'if_available':alias, 
251              }) 
 252   
254          attr = ax.AttrInfo( 
255              type_uri = 'type://of.transportation', 
256              alias = 'transport', 
257              ) 
258          self.msg.add(attr) 
259          self.failUnlessExtensionArgs({ 
260              'type.' + attr.alias:attr.type_uri, 
261              'if_available':attr.alias, 
262              }) 
 263   
265          attr = ax.AttrInfo( 
266              type_uri = 'type://of.transportation', 
267              alias = 'transport', 
268              required = True, 
269              ) 
270          self.msg.add(attr) 
271          self.failUnlessExtensionArgs({ 
272              'type.' + attr.alias:attr.type_uri, 
273              'required':attr.alias, 
274              }) 
 275   
277          """Make sure that getExtensionArgs has the expected result 
278   
279          This method will fill in the mode. 
280          """ 
281          expected_args = dict(expected_args) 
282          expected_args['mode'] = self.msg.mode 
283          self.failUnlessEqual(expected_args, self.msg.getExtensionArgs()) 
 284   
286          self.failUnlessEqual([], list(self.msg)) 
287          self.failUnlessEqual([], list(self.msg.iterAttrs())) 
 288   
291   
293          extension_args = { 
294              'mode':'fetch_request', 
295              'type.' + self.alias_a:self.type_a, 
296              } 
297          self.failUnlessRaises(ValueError, 
298                                self.msg.parseExtensionArgs, extension_args) 
 299   
301          extension_args = { 
302              'mode':'fetch_request', 
303              'type.' + self.alias_a:self.type_a, 
304              'if_available':self.alias_a 
305              } 
306          self.msg.parseExtensionArgs(extension_args) 
307          self.failUnless(self.type_a in self.msg) 
308          self.failUnlessEqual([self.type_a], list(self.msg)) 
309          attr_info = self.msg.requested_attributes.get(self.type_a) 
310          self.failUnless(attr_info) 
311          self.failIf(attr_info.required) 
312          self.failUnlessEqual(self.type_a, attr_info.type_uri) 
313          self.failUnlessEqual(self.alias_a, attr_info.alias) 
314          self.failUnlessEqual([attr_info], list(self.msg.iterAttrs())) 
 315   
317          extension_args = { 
318              'mode':'fetch_request', 
319              'type.' + self.alias_a:self.type_a, 
320              'if_available':self.alias_a 
321              } 
322          self.msg.parseExtensionArgs(extension_args) 
323          self.failUnlessEqual(extension_args, self.msg.getExtensionArgs()) 
324          self.failIf(self.msg.requested_attributes[self.type_a].required) 
 325   
327          extension_args = { 
328              'mode':'fetch_request', 
329              'type.' + self.alias_a:self.type_a, 
330              'count.' + self.alias_a:'2', 
331              'required':self.alias_a 
332              } 
333          self.msg.parseExtensionArgs(extension_args) 
334          self.failUnlessEqual(extension_args, self.msg.getExtensionArgs()) 
335          self.failUnless(self.msg.requested_attributes[self.type_a].required) 
 336   
338          extension_args = { 
339              'mode':'fetch_request', 
340              'type.' + self.alias_a:self.type_a, 
341              'count.' + self.alias_a:'1', 
342              'if_available':self.alias_a, 
343              } 
344          extension_args_norm = { 
345              'mode':'fetch_request', 
346              'type.' + self.alias_a:self.type_a, 
347              'if_available':self.alias_a, 
348              } 
349          self.msg.parseExtensionArgs(extension_args) 
350          self.failUnlessEqual(extension_args_norm, self.msg.getExtensionArgs()) 
 351   
363   
377   
389   
401   
403          """return None for an OpenIDRequest without AX paramaters.""" 
404          openid_req_msg = Message.fromOpenIDArgs({ 
405              'mode': 'checkid_setup', 
406              'ns': OPENID2_NS, 
407              }) 
408          oreq = DummyRequest(openid_req_msg) 
409          r = ax.FetchRequest.fromOpenIDRequest(oreq) 
410          self.failUnless(r is None, "%s is not None" % (r,)) 
 411   
413          """return something for SuccessResponse with AX paramaters, 
414          even if it is the empty set.""" 
415          openid_req_msg = Message.fromOpenIDArgs({ 
416              'mode': 'checkid_setup', 
417              'realm': 'http://example.com/realm', 
418              'ns': OPENID2_NS, 
419              'ns.ax': ax.AXMessage.ns_uri, 
420              'ax.mode': 'fetch_request', 
421              }) 
422          oreq = DummyRequest(openid_req_msg) 
423          r = ax.FetchRequest.fromOpenIDRequest(oreq) 
424          self.failUnless(r is not None) 
  425   
426   
429          self.msg = ax.FetchResponse() 
430          self.value_a = 'monkeys' 
431          self.type_a = 'http://phone.home/' 
432          self.alias_a = 'robocop' 
433          self.request_update_url = 'http://update.bogus/' 
 434   
436          self.failUnless(self.msg.update_url is None) 
437          self.failUnlessEqual({}, self.msg.data) 
 438   
440          expected_args = { 
441              'mode':'fetch_response', 
442              } 
443          self.failUnlessEqual(expected_args, self.msg.getExtensionArgs()) 
 444   
446          expected_args = { 
447              'mode':'fetch_response', 
448              } 
449          req = ax.FetchRequest() 
450          msg = ax.FetchResponse(request=req) 
451          self.failUnlessEqual(expected_args, msg.getExtensionArgs()) 
 452   
454          uri = 'http://not.found/' 
455          alias = 'ext0' 
456   
457          expected_args = { 
458              'mode':'fetch_response', 
459              'type.%s' % (alias,): uri, 
460              'count.%s' % (alias,): '0' 
461              } 
462          req = ax.FetchRequest() 
463          req.add(ax.AttrInfo(uri)) 
464          msg = ax.FetchResponse(request=req) 
465          self.failUnlessEqual(expected_args, msg.getExtensionArgs()) 
 466   
468          uri = 'http://not.found/' 
469          alias = 'ext0' 
470   
471          expected_args = { 
472              'mode':'fetch_response', 
473              'update_url': self.request_update_url, 
474              'type.%s' % (alias,): uri, 
475              'count.%s' % (alias,): '0' 
476              } 
477          req = ax.FetchRequest(update_url=self.request_update_url) 
478          req.add(ax.AttrInfo(uri)) 
479          msg = ax.FetchResponse(request=req) 
480          self.failUnlessEqual(expected_args, msg.getExtensionArgs()) 
 481   
483          expected_args = { 
484              'mode':'fetch_response', 
485              'type.' + self.alias_a:self.type_a, 
486              'value.' + self.alias_a + '.1':self.value_a, 
487              'count.' + self.alias_a: '1' 
488              } 
489          req = ax.FetchRequest() 
490          req.add(ax.AttrInfo(self.type_a, alias=self.alias_a)) 
491          msg = ax.FetchResponse(request=req) 
492          msg.addValue(self.type_a, self.value_a) 
493          self.failUnlessEqual(expected_args, msg.getExtensionArgs()) 
 494   
496          req = ax.FetchRequest() 
497          msg = ax.FetchResponse(request=req) 
498          msg.addValue(self.type_a, self.value_a) 
499          self.failUnlessRaises(KeyError, msg.getExtensionArgs) 
 500   
502          req = ax.FetchRequest() 
503          self.msg.addValue(self.type_a, self.value_a) 
504          self.failUnlessEqual(self.value_a, self.msg.getSingle(self.type_a)) 
 505   
507          self.failUnlessEqual(None, self.msg.getSingle(self.type_a)) 
 508   
510          self.msg.setValues(self.type_a, ['x', 'y']) 
511          self.failUnlessRaises(ax.AXError, self.msg.getSingle, self.type_a) 
 512   
514          self.failUnlessRaises(KeyError, self.msg.get, self.type_a) 
 515   
517          """return None for SuccessResponse with no AX paramaters.""" 
518          args = { 
519              'mode': 'id_res', 
520              'ns': OPENID2_NS, 
521              } 
522          sf = ['openid.' + i for i in args.keys()] 
523          msg = Message.fromOpenIDArgs(args) 
524          class Endpoint: 
525              claimed_id = 'http://invalid.' 
 526   
527          oreq = SuccessResponse(Endpoint(), msg, signed_fields=sf) 
528          r = ax.FetchResponse.fromSuccessResponse(oreq) 
529          self.failUnless(r is None, "%s is not None" % (r,)) 
 530   
532          """return something for SuccessResponse with AX paramaters, 
533          even if it is the empty set.""" 
534          args = { 
535              'mode': 'id_res', 
536              'ns': OPENID2_NS, 
537              'ns.ax': ax.AXMessage.ns_uri, 
538              'ax.mode': 'fetch_response', 
539              } 
540          sf = ['openid.' + i for i in args.keys()] 
541          msg = Message.fromOpenIDArgs(args) 
542          class Endpoint: 
543              claimed_id = 'http://invalid.' 
 544   
545          oreq = SuccessResponse(Endpoint(), msg, signed_fields=sf) 
546          r = ax.FetchResponse.fromSuccessResponse(oreq) 
547          self.failUnless(r is not None) 
548   
550          name = 'ext0' 
551          value = 'snozzberry' 
552          uri = "http://willy.wonka.name/" 
553          args = { 
554              'mode': 'id_res', 
555              'ns': OPENID2_NS, 
556              'ns.ax': ax.AXMessage.ns_uri, 
557              'ax.update_url': 'http://example.com/realm/update_path', 
558              'ax.mode': 'fetch_response', 
559              'ax.type.'+name: uri, 
560              'ax.count.'+name: '1', 
561              'ax.value.%s.1'%name: value, 
562              } 
563          sf = ['openid.' + i for i in args.keys()] 
564          msg = Message.fromOpenIDArgs(args) 
565          class Endpoint: 
566              claimed_id = 'http://invalid.' 
 567   
568          resp = SuccessResponse(Endpoint(), msg, signed_fields=sf) 
569          ax_resp = ax.FetchResponse.fromSuccessResponse(resp) 
570          values = ax_resp.get(uri) 
571          self.failUnlessEqual([value], values) 
572   
573   
576          self.msg = ax.StoreRequest() 
577          self.type_a = 'http://three.count/' 
578          self.alias_a = 'juggling' 
 579   
581          self.failUnlessEqual({}, self.msg.data) 
 582   
584          args = self.msg.getExtensionArgs() 
585          expected_args = { 
586              'mode':'store_request', 
587              } 
588          self.failUnlessEqual(expected_args, args) 
 589   
591          aliases = NamespaceMap() 
592          aliases.addAlias(self.type_a, self.alias_a) 
593          msg = ax.StoreRequest(aliases=aliases) 
594          msg.setValues(self.type_a, ['foo', 'bar']) 
595          args = msg.getExtensionArgs() 
596          expected_args = { 
597              'mode':'store_request', 
598              'type.' + self.alias_a: self.type_a, 
599              'count.' + self.alias_a: '2', 
600              'value.%s.1' % (self.alias_a,):'foo', 
601              'value.%s.2' % (self.alias_a,):'bar', 
602              } 
603          self.failUnlessEqual(expected_args, args) 
  604   
612   
619   
621          reason = 'no reason, really' 
622          msg = ax.StoreResponse(False, reason) 
623          self.failIf(msg.succeeded()) 
624          self.failUnlessEqual(reason, msg.error_message) 
625          self.failUnlessEqual({'mode':'store_response_failure', 
626                                'error':reason}, msg.getExtensionArgs()) 
  627