From 3d221bcdd775f43e1beec0042792e42181d7276e Mon Sep 17 00:00:00 2001
From: Joseph Schorr <josephschorr@users.noreply.github.com>
Date: Thu, 10 Nov 2016 14:25:05 -0500
Subject: [PATCH] Add tests for the Swift storage layer using a fake swift
 engine

---
 test/test_swift.py | 140 +++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 134 insertions(+), 6 deletions(-)

diff --git a/test/test_swift.py b/test/test_swift.py
index 83c604cb5..3d7769671 100644
--- a/test/test_swift.py
+++ b/test/test_swift.py
@@ -1,19 +1,22 @@
+import io
 import unittest
 
+from collections import defaultdict
+
 from storage.swift import SwiftStorage
 from mock import MagicMock
 
 
-class TestSwiftStorage(SwiftStorage):
+class MockSwiftStorage(SwiftStorage):
   def __init__(self, *args, **kwargs):
-    super(TestSwiftStorage, self).__init__(*args, **kwargs)
+    super(MockSwiftStorage, self).__init__(*args, **kwargs)
     self._connection = MagicMock()
 
   def _get_connection(self):
     return self._connection
 
 
-class SwiftTests(unittest.TestCase):
+class MockSwiftTests(unittest.TestCase):
   base_args = {
     'metric_queue': None,
     'swift_container': 'container-name',
@@ -23,9 +26,8 @@ class SwiftTests(unittest.TestCase):
     'swift_password': 'password',
   }
 
-
   def test_fixed_path_concat(self):
-    swift = TestSwiftStorage(**self.base_args)
+    swift = MockSwiftStorage(**self.base_args)
     swift.exists('object/path')
     swift._get_connection().head_object.assert_called_with('container-name', 'basepath/object/path')
 
@@ -33,10 +35,136 @@ class SwiftTests(unittest.TestCase):
   def test_simple_path_concat(self):
     simple_concat_args = dict(self.base_args)
     simple_concat_args['simple_path_concat'] = True
-    swift = TestSwiftStorage(**simple_concat_args)
+    swift = MockSwiftStorage(**simple_concat_args)
     swift.exists('object/path')
     swift._get_connection().head_object.assert_called_with('container-name', 'basepathobject/path')
 
 
+class FakeSwiftStorage(SwiftStorage):
+  def __init__(self, *args, **kwargs):
+    super(FakeSwiftStorage, self).__init__(*args, **kwargs)
+    self._connection = FakeSwift()
+
+  def _get_connection(self):
+    return self._connection
+
+
+class FakeSwift(object):
+  def __init__(self):
+    self.containers = defaultdict(dict)
+
+  def head_object(self, container, path):
+    return self.containers[container].get(path)
+
+  def put_object(self, container, path, content, chunk_size=None, content_type=None, headers=None):
+    if not isinstance(content, str):
+      content = content.read()
+
+    self.containers[container][path] = {
+      'content': content,
+      'chunk_size': chunk_size,
+      'content_type': content_type,
+      'headers': headers,
+    }
+
+  def get_object(self, container, path, resp_chunk_size=None):
+    data = self.containers[container].get(path, {})
+    if 'X-Object-Manifest' in data['headers']:
+      new_contents = []
+      prefix = data['headers']['X-Object-Manifest']
+      for key, value in self.containers[container].iteritems():
+        if ('container-name/' + key).startswith(prefix):
+          new_contents.append((key, value['content']))
+
+      new_contents.sort(key=lambda value: value[0])
+
+      data = dict(data)
+      data['content'] = ''.join([nc[1] for nc in new_contents])
+      return bool(data), data.get('content')
+
+    return bool(data), data.get('content')
+
+  def delete_object(self, container, path):
+    self.containers[container].pop(path, None)
+
+
+class FakeSwiftTests(unittest.TestCase):
+  base_args = {
+    'metric_queue': None,
+    'swift_container': 'container-name',
+    'storage_path': '/basepath',
+    'auth_url': 'https://auth.com',
+    'swift_user': 'root',
+    'swift_password': 'password',
+  }
+
+  def test_simple_put_get(self):
+    swift = FakeSwiftStorage(**self.base_args)
+    self.assertFalse(swift.exists('somepath'))
+
+    swift.put_content('somepath', 'hello world!')
+    self.assertTrue(swift.exists('somepath'))
+
+    self.assertEquals('hello world!', swift.get_content('somepath'))
+
+  def test_stream_read_write(self):
+    swift = FakeSwiftStorage(**self.base_args)
+    self.assertFalse(swift.exists('somepath'))
+
+    swift.stream_write('somepath', io.BytesIO('some content here'))
+    self.assertTrue(swift.exists('somepath'))
+
+    self.assertEquals('some content here', swift.get_content('somepath'))
+    self.assertEquals('some content here', ''.join(list(swift.stream_read('somepath'))))
+
+  def test_remove(self):
+    swift = FakeSwiftStorage(**self.base_args)
+    self.assertFalse(swift.exists('somepath'))
+
+    swift.put_content('somepath', 'hello world!')
+    self.assertTrue(swift.exists('somepath'))
+
+    swift.remove('somepath')
+    self.assertFalse(swift.exists('somepath'))
+
+  def test_checksum(self):
+    swift = FakeSwiftStorage(**self.base_args)
+    swift.put_content('somepath', 'hello world!')
+    self.assertIsNotNone(swift.get_checksum('somepath'))
+
+  def test_chunked_upload(self):
+    swift = FakeSwiftStorage(**self.base_args)
+    uuid, metadata = swift.initiate_chunked_upload()
+
+    chunks = ['this', 'is', 'some', 'chunked', 'data', '']
+    offset = 0
+    for chunk in chunks:
+      bytes_written, metadata, error = swift.stream_upload_chunk(uuid, offset, len(chunk),
+                                                                 io.BytesIO(chunk), metadata)
+      self.assertIsNone(error)
+      self.assertEquals(bytes_written, len(chunk))
+      offset += len(chunk)
+
+    swift.complete_chunked_upload(uuid, 'somepath', metadata)
+    self.assertEquals(''.join(chunks), swift.get_content('somepath'))
+
+  def test_cancel_chunked_upload(self):
+    swift = FakeSwiftStorage(**self.base_args)
+    uuid, metadata = swift.initiate_chunked_upload()
+
+    chunks = ['this', 'is', 'some', 'chunked', 'data', '']
+    offset = 0
+    for chunk in chunks:
+      bytes_written, metadata, error = swift.stream_upload_chunk(uuid, offset, len(chunk),
+                                                                 io.BytesIO(chunk), metadata)
+      self.assertIsNone(error)
+      self.assertEquals(bytes_written, len(chunk))
+      offset += len(chunk)
+
+    swift.cancel_chunked_upload(uuid, metadata)
+    for segment in SwiftStorage._segment_list_from_metadata(metadata):
+      self.assertFalse(swift.exists(segment.path))
+
+
 if __name__ == '__main__':
   unittest.main()