test_object_store_service.py 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. from datetime import datetime
  2. from io import BytesIO
  3. from unittest import skip
  4. import uuid
  5. import requests
  6. import tempfile
  7. from cloudbridge.cloud.interfaces.resources import BucketObject
  8. from test.helpers import ProviderTestBase
  9. import test.helpers as helpers
  10. class CloudObjectStoreServiceTestCase(ProviderTestBase):
  11. def __init__(self, methodName, provider):
  12. super(CloudObjectStoreServiceTestCase, self).__init__(
  13. methodName=methodName, provider=provider)
  14. @helpers.skipIfNoService(['object_store'])
  15. def test_crud_bucket(self):
  16. """
  17. Create a new bucket, check whether the expected values are set,
  18. and delete it.
  19. """
  20. name = "cbtestcreatebucket-{0}".format(uuid.uuid4())
  21. test_bucket = self.provider.object_store.create(name)
  22. with helpers.cleanup_action(lambda: test_bucket.delete()):
  23. self.assertTrue(
  24. test_bucket.id in repr(test_bucket),
  25. "repr(obj) should contain the object id so that the object"
  26. " can be reconstructed, but does not. eval(repr(obj)) == obj")
  27. buckets = self.provider.object_store.list()
  28. list_buckets = [c for c in buckets if c.name == name]
  29. self.assertTrue(
  30. len(list_buckets) == 1,
  31. "List buckets does not return the expected bucket %s" %
  32. name)
  33. # check iteration
  34. iter_buckets = [c for c in self.provider.object_store
  35. if c.name == name]
  36. self.assertTrue(
  37. len(iter_buckets) == 1,
  38. "Iter buckets does not return the expected bucket %s" %
  39. name)
  40. # check find
  41. find_buckets = self.provider.object_store.find(name=name)
  42. self.assertTrue(
  43. len(find_buckets) == 1,
  44. "Find buckets does not return the expected bucket %s" %
  45. name)
  46. get_bucket = self.provider.object_store.get(
  47. test_bucket.id)
  48. self.assertTrue(
  49. list_buckets[0] ==
  50. get_bucket == test_bucket,
  51. "Objects returned by list: {0} and get: {1} are not as "
  52. " expected: {2}" .format(list_buckets[0].id,
  53. get_bucket.id,
  54. test_bucket.name))
  55. buckets = self.provider.object_store.list()
  56. found_buckets = [c for c in buckets if c.name == name]
  57. self.assertTrue(
  58. len(found_buckets) == 0,
  59. "Bucket %s should have been deleted but still exists." %
  60. name)
  61. @helpers.skipIfNoService(['object_store'])
  62. def test_crud_bucket_objects(self):
  63. """
  64. Create a new bucket, upload some contents into the bucket, and
  65. check whether list properly detects the new content.
  66. Delete everything afterwards.
  67. """
  68. name = "cbtestbucketobjs-{0}".format(uuid.uuid4())
  69. test_bucket = self.provider.object_store.create(name)
  70. # ensure that the bucket is empty
  71. objects = test_bucket.list()
  72. self.assertEqual([], objects)
  73. with helpers.cleanup_action(lambda: test_bucket.delete()):
  74. obj_name_prefix = "hello"
  75. obj_name = obj_name_prefix + "_world.txt"
  76. obj = test_bucket.create_object(obj_name)
  77. self.assertTrue(
  78. obj.id in repr(obj),
  79. "repr(obj) should contain the object id so that the object"
  80. " can be reconstructed, but does not. eval(repr(obj)) == obj")
  81. with helpers.cleanup_action(lambda: obj.delete()):
  82. # TODO: This is wrong. We shouldn't have to have a separate
  83. # call to upload some content before being able to delete
  84. # the content. Maybe the create_object method should accept
  85. # the file content as a parameter.
  86. obj.upload("dummy content")
  87. objs = test_bucket.list()
  88. self.assertTrue(
  89. isinstance(objs[0].size, int),
  90. "Object size property needs to be a int, not {0}".format(
  91. type(objs[0].size)))
  92. self.assertTrue(
  93. datetime.strptime(objs[0].last_modified[:23],
  94. "%Y-%m-%dT%H:%M:%S.%f"),
  95. "Object's last_modified field format {0} not matching."
  96. .format(objs[0].last_modified))
  97. # check iteration
  98. iter_objs = list(test_bucket)
  99. self.assertListEqual(iter_objs, objs)
  100. found_objs = [o for o in objs if o.name == obj_name]
  101. self.assertTrue(
  102. len(found_objs) == 1,
  103. "List bucket objects does not return the expected"
  104. " object %s" % obj_name)
  105. get_bucket_obj = test_bucket.get(obj_name)
  106. self.assertTrue(
  107. found_objs[0] ==
  108. get_bucket_obj == obj,
  109. "Objects returned by list: {0} and get: {1} are not as "
  110. " expected: {2}" .format(found_objs[0].id,
  111. get_bucket_obj.id,
  112. obj.id))
  113. obj_too = test_bucket.get(obj_name)
  114. self.assertTrue(
  115. isinstance(obj_too, BucketObject),
  116. "Did not get object {0} of expected type.".format(obj_too))
  117. prefix_filtered_list = test_bucket.list(prefix=obj_name_prefix)
  118. self.assertTrue(
  119. len(objs) == len(prefix_filtered_list) == 1,
  120. 'The number of objects returned by list function, '
  121. 'with and without a prefix, are expected to be equal, '
  122. 'but its detected otherwise.')
  123. objs = test_bucket.list()
  124. found_objs = [o for o in objs if o.name == obj_name]
  125. self.assertTrue(
  126. len(found_objs) == 0,
  127. "Object %s should have been deleted but still exists." %
  128. obj_name)
  129. @helpers.skipIfNoService(['object_store'])
  130. def test_upload_download_bucket_content(self):
  131. name = "cbtestbucketobjs-{0}".format(uuid.uuid4())
  132. test_bucket = self.provider.object_store.create(name)
  133. with helpers.cleanup_action(lambda: test_bucket.delete()):
  134. obj_name = "hello_upload_download.txt"
  135. obj = test_bucket.create_object(obj_name)
  136. with helpers.cleanup_action(lambda: obj.delete()):
  137. content = b"Hello World. Here's some content."
  138. # TODO: Upload and download methods accept different parameter
  139. # types. Need to make this consistent - possibly provider
  140. # multiple methods like upload_from_file, from_stream etc.
  141. obj.upload(content)
  142. target_stream = BytesIO()
  143. obj.save_content(target_stream)
  144. self.assertEqual(target_stream.getvalue(), content)
  145. target_stream2 = BytesIO()
  146. for data in obj.iter_content():
  147. target_stream2.write(data)
  148. self.assertEqual(target_stream2.getvalue(), content)
  149. @skip("Skip until OpenStack implementation is provided")
  150. @helpers.skipIfNoService(['object_store'])
  151. def test_generate_url(self):
  152. name = "cbtestbucketobjs-{0}".format(uuid.uuid4())
  153. test_bucket = self.provider.object_store.create(name)
  154. with helpers.cleanup_action(lambda: test_bucket.delete()):
  155. obj_name = "hello_upload_download.txt"
  156. obj = test_bucket.create_object(obj_name)
  157. with helpers.cleanup_action(lambda: obj.delete()):
  158. content = b"Hello World. Generate a url."
  159. obj.upload(content)
  160. target_stream = BytesIO()
  161. obj.save_content(target_stream)
  162. url = obj.generate_url(100)
  163. self.assertEqual(requests.get(url).content, content)
  164. @helpers.skipIfNoService(['object_store'])
  165. def test_upload_download_bucket_content_from_file(self):
  166. name = "cbtestbucketobjs-{0}".format(uuid.uuid4())
  167. test_bucket = self.provider.object_store.create(name)
  168. with helpers.cleanup_action(lambda: test_bucket.delete()):
  169. obj_name = "hello_upload_download.txt"
  170. obj = test_bucket.create_object(obj_name)
  171. with helpers.cleanup_action(lambda: obj.delete()):
  172. content = b"Hello World. Upload from file."
  173. with tempfile.NamedTemporaryFile() as tmpFile:
  174. tmpFile.write(content)
  175. tmpFile.flush()
  176. obj.upload_from_file(tmpFile.name)
  177. target_stream = BytesIO()
  178. obj.save_content(target_stream)
  179. self.assertEqual(target_stream.getvalue(), content)