standard_interface_tests.py 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. """
  2. Standard tests for behaviour common across the whole of cloudbridge.
  3. This includes:
  4. 1. Checking that every resource has an id property
  5. 2. Checking for object equality and repr
  6. 3. Checking standard behaviour for list, iter, find, get, delete
  7. """
  8. import uuid
  9. from cloudbridge.cloud.interfaces.exceptions \
  10. import InvalidNameException
  11. from cloudbridge.cloud.interfaces.resources import ResultList
  12. def check_repr(test, obj):
  13. test.assertTrue(
  14. obj.id in repr(obj),
  15. "repr(obj) for %s contain the object id so that the object"
  16. " can be reconstructed, but does not. eval(repr(obj)) == obj"
  17. % (type(obj).__name__,))
  18. def check_json(test, obj):
  19. val = obj.to_json()
  20. test.assertEqual(val.get('id'), obj.id)
  21. test.assertEqual(val.get('name'), obj.name)
  22. def check_obj_properties(test, obj):
  23. test.assertEqual(obj, obj, "Object should be equal to itself")
  24. test.assertFalse(obj != obj, "Object inequality should be false")
  25. check_obj_name(test, obj)
  26. def check_list(test, service, obj):
  27. list_objs = service.list()
  28. test.assertIsInstance(list_objs, ResultList)
  29. all_records = list_objs
  30. while list_objs.is_truncated:
  31. list_objs = service.list(marker=list_objs.marker)
  32. all_records += list_objs
  33. match_objs = [o for o in all_records if o.id == obj.id]
  34. test.assertTrue(
  35. len(match_objs) == 1,
  36. "List objects for %s does not return the expected object id %s. Got %s"
  37. % (type(obj).__name__, obj.id, match_objs))
  38. return match_objs
  39. def check_iter(test, service, obj):
  40. # check iteration
  41. iter_objs = list(service)
  42. iter_ids = [o.id for o in service]
  43. test.assertEqual(len(set(iter_ids)), len(iter_ids),
  44. "Iteration should not return duplicates")
  45. match_objs = [o for o in iter_objs if o.id == obj.id]
  46. test.assertTrue(
  47. len(match_objs) == 1,
  48. "Iter objects for %s does not return the expected object id %s. Got %s"
  49. % (type(obj).__name__, obj.id, match_objs))
  50. return match_objs
  51. def check_find(test, service, obj):
  52. # check find
  53. find_objs = service.find(name=obj.name)
  54. test.assertTrue(
  55. len(find_objs) == 1,
  56. "Find objects for %s does not return the expected object: %s. Got %s"
  57. % (type(obj).__name__, obj.name, find_objs))
  58. return find_objs
  59. def check_find_non_existent(test, service):
  60. # check find
  61. find_objs = service.find(name="random_imagined_obj_name")
  62. test.assertTrue(
  63. len(find_objs) == 0,
  64. "Find non-existent object for %s returned unexpected objects: %s"
  65. % (type(service).__name__, find_objs))
  66. def check_get(test, service, obj):
  67. get_obj = service.get(obj.id)
  68. test.assertEqual(get_obj, obj)
  69. test.assertIsInstance(get_obj, type(obj))
  70. return get_obj
  71. def check_get_non_existent(test, service):
  72. # check get
  73. get_objs = service.get(str(uuid.uuid4()))
  74. test.assertIsNone(
  75. get_objs,
  76. "Get non-existent object for %s returned unexpected objects: %s"
  77. % (type(service).__name__, get_objs))
  78. def check_delete(test, service, obj, perform_delete=False):
  79. if perform_delete:
  80. obj.delete()
  81. objs = service.list()
  82. found_objs = [o for o in objs if o.id == obj.id]
  83. test.assertTrue(
  84. len(found_objs) == 0,
  85. "Object %s in service %s should have been deleted but still exists."
  86. % (found_objs, type(service).__name__))
  87. def check_obj_name(test, obj):
  88. """
  89. Cloudbridge identifiers must be 1-63 characters long, and comply with
  90. RFC1035. In addition, identifiers should contain only lowercase letters,
  91. numeric characters, underscores, and dashes. International
  92. characters are allowed.
  93. """
  94. # if name has a setter, make sure invalid values cannot be set
  95. name_property = getattr(type(obj), 'name', None)
  96. if isinstance(name_property, property) and name_property.fset:
  97. # setting letters, numbers and international characters should succeed
  98. # TODO: Unicode characters trip up Moto. Add following: \u0D85\u0200
  99. VALID_NAME = u"hello_world-123"
  100. original_name = obj.name
  101. obj.name = VALID_NAME
  102. # setting spaces should raise an exception
  103. with test.assertRaises(InvalidNameException):
  104. obj.name = "hello world"
  105. # setting upper case characters should raise an exception
  106. with test.assertRaises(InvalidNameException):
  107. obj.name = "hello World"
  108. # setting special characters should raise an exception
  109. with test.assertRaises(InvalidNameException):
  110. obj.name = "hello.world:how_goes_it"
  111. # setting a length > 63 should result in an exception
  112. with test.assertRaises(InvalidNameException,
  113. msg="Name of length > 64 should be disallowed"):
  114. obj.name = "a" * 64
  115. # refreshing should yield the last successfully set name
  116. obj.refresh()
  117. test.assertEqual(obj.name, VALID_NAME)
  118. obj.name = original_name
  119. pass
  120. def check_standard_behaviour(test, service, obj):
  121. """
  122. Checks standard behaviour in a given cloudbridge resource
  123. of a given service.
  124. """
  125. check_repr(test, obj)
  126. check_json(test, obj)
  127. check_obj_properties(test, obj)
  128. objs_list = check_list(test, service, obj)
  129. objs_iter = check_iter(test, service, obj)
  130. objs_find = check_find(test, service, obj)
  131. check_find_non_existent(test, service)
  132. obj_get = check_get(test, service, obj)
  133. check_get_non_existent(test, service)
  134. test.assertTrue(
  135. obj == objs_list[0] == objs_iter[0] == objs_find[0] == obj_get,
  136. "Objects returned by list: {0}, iter: {1}, find: {2} and get: {3} "
  137. " are not as expected: {4}" .format(objs_list[0].id, objs_iter[0].id,
  138. objs_find[0].id, obj_get.id,
  139. obj.id))
  140. test.assertTrue(
  141. obj.id == objs_list[0].id == objs_iter[0].id ==
  142. objs_find[0].id == obj_get.id,
  143. "Object Ids returned by list: {0}, iter: {1}, find: {2} and get: {3} "
  144. " are not as expected: {4}" .format(objs_list[0].id, objs_iter[0].id,
  145. objs_find[0].id, obj_get.id,
  146. obj.id))
  147. test.assertTrue(
  148. obj.name == objs_list[0].name == objs_iter[0].name ==
  149. objs_find[0].name == obj_get.name,
  150. "Names returned by list: {0}, iter: {1}, find: {2} and get: {3} "
  151. " are not as expected: {4}" .format(objs_list[0].id, objs_iter[0].id,
  152. objs_find[0].id, obj_get.id,
  153. obj.id))