Example #1
0
 def setUp(self):
     self.fake_endpoint = "http://1.2.3.4:8000"
     self.api = FakeStorageApi("NS", endpoint=self.fake_endpoint)
     self.account = "test"
     self.container = "fake"
     self.headers = {"x-req-id": random_str(32)}
     self.policy = "THREECOPIES"
     self.uri_base = self.fake_endpoint + "/v3.0/NS"
Example #2
0
 def setUp(self):
     self.fake_endpoint = "http://1.2.3.4:8000"
     self.api = FakeStorageApi("NS", endpoint=self.fake_endpoint)
     self.account = "test"
     self.container = "fake"
     reqid = random_str(32)
     self.headers = {REQID_HEADER: reqid}
     self.common_kwargs = {'headers': self.headers, 'reqid': reqid}
     self.policy = "THREECOPIES"
     self.uri_base = self.fake_endpoint + "/v3.0/NS"
 def setUp(self):
     self.fake_endpoint = "http://1.2.3.4:8000"
     self.api = FakeStorageApi("NS", endpoint=self.fake_endpoint)
     self.account = "test_container_client"
     self.container = "fake_container"
Example #4
0
class ObjectStorageTest(unittest.TestCase):
    def setUp(self):
        self.fake_endpoint = "http://1.2.3.4:8000"
        self.api = FakeStorageApi("NS", endpoint=self.fake_endpoint)
        self.account = "test"
        self.container = "fake"
        self.headers = {"x-req-id": random_str(32)}
        self.policy = "THREECOPIES"
        self.uri_base = self.fake_endpoint + "/v3.0/NS"

    def test_handle_container_not_found(self):
        @handle_container_not_found
        def test(self, account, container):
            raise exceptions.NotFound("No container")

        container = random_str(32)
        self.assertRaises(exceptions.NoSuchContainer, test, self, self.account,
                          container)

    def test_handle_object_not_found(self):
        @handle_object_not_found
        def test(self, account, container, obj):
            raise exceptions.NotFound("No object")

        obj = random_str(32)
        self.assertRaises(exceptions.NoSuchObject, test, self, self.account,
                          self.container, obj)

    def test_container_list(self):
        resp = FakeApiResponse()
        name = random_str(32)
        marker = random_str(32)
        delimiter = random_str(32)
        end_marker = random_str(32)
        prefix = random_str(32)
        limit = random.randint(1, 1000)
        body = {"listing": [[name, 0, 0, 0]]}
        fake_endpoint = 'fake_endpoint'
        self.api.account._direct_request = Mock(return_value=(resp, body))
        self.api.account._get_account_addr = Mock(return_value=fake_endpoint)
        containers = self.api.container_list(self.account,
                                             limit=limit,
                                             marker=marker,
                                             prefix=prefix,
                                             delimiter=delimiter,
                                             end_marker=end_marker,
                                             headers=self.headers)
        params = {
            "id": self.account,
            "prefix": prefix,
            "delimiter": delimiter,
            "marker": marker,
            "end_marker": end_marker,
            "limit": limit
        }
        uri = "http://%s/v1.0/account/containers" % fake_endpoint
        self.api.account._direct_request.assert_called_once_with(
            'GET', uri, params=params, headers=self.headers)
        self.assertEqual(len(containers), 1)

    def test_object_list(self):
        api = self.api
        marker = random_str(32)
        delimiter = random_str(32)
        end_marker = random_str(32)
        prefix = random_str(32)
        limit = random.randint(1, 1000)
        name0 = random_str(32)
        name1 = random_str(32)
        resp_body = {"objects": [{"name": name0}, {"name": name1}]}
        resp = FakeApiResponse()
        resp.headers = {}
        api.container._direct_request = Mock(return_value=(resp, resp_body))
        listing = api.object_list(self.account,
                                  self.container,
                                  limit=limit,
                                  marker=marker,
                                  prefix=prefix,
                                  delimiter=delimiter,
                                  end_marker=end_marker,
                                  headers=self.headers)
        uri = "%s/container/list" % self.uri_base
        params = {
            'acct': self.account,
            'ref': self.container,
            'marker': marker,
            'max': limit,
            'delimiter': delimiter,
            'prefix': prefix,
            'end_marker': end_marker,
            'properties': False
        }
        api.container._direct_request.assert_called_once_with(
            'GET', uri, params=params, headers=self.headers)
        self.assertEqual(len(listing['objects']), 2)

    def test_container_show(self):
        api = self.api
        resp = FakeApiResponse()
        name = random_str(32)
        cont_size = random.randint(1, 1000)
        resp.headers = {container_headers["size"]: cont_size}
        api.container._direct_request = Mock(return_value=(resp, {}))
        info = api.container_show(self.account, name, headers=self.headers)
        uri = "%s/container/show" % self.uri_base
        params = {'acct': self.account, 'ref': name}
        api.container._direct_request.assert_called_once_with(
            'GET', uri, params=params, headers=self.headers)
        self.assertEqual(info, {})

    def test_container_show_not_found(self):
        api = self.api
        api.container._direct_request = Mock(
            side_effect=exceptions.NotFound("No container"))
        name = random_str(32)
        self.assertRaises(exceptions.NoSuchContainer, api.container_show,
                          self.account, name)

    def test_container_create(self):
        api = self.api
        resp = FakeApiResponse()
        resp.status = 201
        api.container._direct_request = Mock(return_value=(resp, None))

        name = random_str(32)
        result = api.container_create(self.account, name, headers=self.headers)
        self.assertEqual(result, True)

        uri = "%s/container/create" % self.uri_base
        params = {'acct': self.account, 'ref': name}
        self.headers['x-oio-action-mode'] = 'autocreate'
        data = json.dumps({'properties': {}, 'system': {}})
        api.container._direct_request.assert_called_once_with(
            'POST',
            uri,
            autocreate=True,
            params=params,
            data=data,
            headers=self.headers)

    def test_container_create_exist(self):
        api = self.api
        resp = FakeApiResponse()
        resp.status = 204
        api.container._direct_request = Mock(return_value=(resp, None))

        name = random_str(32)
        result = api.container_create(self.account, name)
        self.assertEqual(result, False)

    def test_container_delete(self):
        api = self.api

        resp = FakeApiResponse()
        resp.status_code = 204
        api.container._direct_request = Mock(return_value=(resp, None))
        api.directory.unlink = Mock(return_value=None)
        name = random_str(32)
        api.container_delete(self.account, name, headers=self.headers)

        uri = "%s/container/destroy" % self.uri_base
        params = {'acct': self.account, 'ref': name}
        api.container._direct_request.assert_called_once_with(
            'POST', uri, params=params, headers=self.headers)

    def test_container_delete_not_empty(self):
        api = self.api

        api.container._direct_request = Mock(
            side_effect=exceptions.Conflict(""))
        api.directory.unlink = Mock(return_value=None)
        name = random_str(32)

        self.assertRaises(exceptions.ContainerNotEmpty, api.container_delete,
                          self.account, name)

    def test_container_update(self):
        api = self.api

        name = random_str(32)
        key = random_str(32)
        value = random_str(32)
        meta = {key: value}
        resp = FakeApiResponse()
        api.container._direct_request = Mock(return_value=(resp, None))
        api.container_set_properties(self.account,
                                     name,
                                     meta,
                                     headers=self.headers)

        data = json.dumps({'properties': meta, 'system': {}})
        uri = "%s/container/set_properties" % self.uri_base
        params = {'acct': self.account, 'ref': name}
        api.container._direct_request.assert_called_once_with(
            'POST', uri, data=data, params=params, headers=self.headers)

    def test_object_show(self):
        api = self.api
        name = random_str(32)
        size = random.randint(1, 1000)
        content_hash = random_str(32)
        content_type = random_str(32)
        resp = FakeApiResponse()
        resp.headers = {
            object_headers["name"]: name,
            object_headers["size"]: str(size),
            object_headers["hash"]: content_hash,
            object_headers["mime_type"]: content_type
        }
        api.container._direct_request = Mock(return_value=(resp, {
            'properties': {}
        }))
        obj = api.object_show(self.account,
                              self.container,
                              name,
                              headers=self.headers)

        uri = "%s/content/get_properties" % self.uri_base
        params = {'acct': self.account, 'ref': self.container, 'path': name}
        api.container._direct_request.assert_called_once_with(
            'POST', uri, params=params, data=None, headers=self.headers)
        self.assertIsNotNone(obj)

    def test_object_create_no_data(self):
        api = self.api
        name = random_str(32)
        self.assertRaises(exceptions.MissingData,
                          api.object_create,
                          self.account,
                          self.container,
                          obj_name=name)

    def test_object_create_no_name(self):
        api = self.api
        self.assertRaises(exceptions.MissingName,
                          api.object_create,
                          self.account,
                          self.container,
                          data="x")

    def test_object_create_missing_file(self):
        api = self.api
        name = random_str(32)
        self.assertRaises(exceptions.FileNotFound, api.object_create,
                          self.account, self.container, name)

    def test_object_set_properties(self):
        api = self.api

        name = random_str(32)
        key = random_str(32)
        value = random_str(32)
        meta = {key: value}
        resp = FakeApiResponse()
        api.container._direct_request = Mock(return_value=(resp, None))
        api.object_set_properties(self.account,
                                  self.container,
                                  name,
                                  meta,
                                  headers=self.headers)

        data = {'properties': meta}
        data = json.dumps(data)
        uri = "%s/content/set_properties" % self.uri_base
        params = {'acct': self.account, 'ref': self.container, 'path': name}
        api.container._direct_request.assert_called_once_with(
            'POST', uri, data=data, params=params, headers=self.headers)

    def test_object_delete(self):
        api = self.api
        name = random_str(32)
        resp_body = [
            chunk("AAAA", "0"),
            chunk("BBBB", "1"),
            chunk("CCCC", "2")
        ]
        resp = FakeApiResponse()
        api.container._direct_request = Mock(return_value=(resp, resp_body))

        api.object_delete(self.account,
                          self.container,
                          name,
                          headers=self.headers)

        uri = "%s/content/delete" % self.uri_base
        params = {'acct': self.account, 'ref': self.container, 'path': name}
        api.container._direct_request.assert_called_once_with(
            'POST', uri, params=params, headers=self.headers)

    def test_object_delete_not_found(self):
        api = self.api
        name = random_str(32)
        api.container._direct_request = Mock(
            side_effect=exceptions.NotFound("No object"))
        self.assertRaises(exceptions.NoSuchObject, api.object_delete,
                          self.account, self.container, name)

    def test_sort_chunks(self):
        raw_chunks = [
            chunk("AAAA", "0"),
            chunk("BBBB", "0"),
            chunk("CCCC", "1"),
            chunk("DDDD", "1"),
            chunk("EEEE", "2"),
            chunk("FFFF", "2"),
        ]
        chunks = _sort_chunks(raw_chunks, False)
        sorted_chunks = {
            0: [
                extend(chunk("AAAA", "0"), {"offset": 0}),
                extend(chunk("BBBB", "0"), {"offset": 0})
            ],
            1: [
                extend(chunk("CCCC", "1"), {"offset": 32}),
                extend(chunk("DDDD", "1"), {"offset": 32})
            ],
            2: [
                extend(chunk("EEEE", "2"), {"offset": 64}),
                extend(chunk("FFFF", "2"), {"offset": 64})
            ]
        }
        self.assertEqual(chunks, sorted_chunks)
        raw_chunks = [
            chunk("AAAA", "0.0"),
            chunk("BBBB", "0.1"),
            chunk("CCCC", "0.2"),
            chunk("DDDD", "1.0"),
            chunk("EEEE", "1.1"),
            chunk("FFFF", "1.2"),
        ]
        chunks = _sort_chunks(raw_chunks, True)
        sorted_chunks = {
            0: [
                extend(chunk("AAAA", "0.0"), {
                    "num": 0,
                    "offset": 0
                }),
                extend(chunk("BBBB", "0.1"), {
                    "num": 1,
                    "offset": 0
                }),
                extend(chunk("CCCC", "0.2"), {
                    "num": 2,
                    "offset": 0
                })
            ],
            1: [
                extend(chunk("DDDD", "1.0"), {
                    "num": 0,
                    "offset": 32
                }),
                extend(chunk("EEEE", "1.1"), {
                    "num": 1,
                    "offset": 32
                }),
                extend(chunk("FFFF", "1.2"), {
                    "num": 2,
                    "offset": 32
                })
            ]
        }
        self.assertEqual(chunks, sorted_chunks)

    def test_container_refresh_conflict(self):
        self.api.account.container_reset = Mock(
            side_effect=exceptions.Conflict("No update needed"))
        self.assertRaises(exceptions.Conflict, self.api.container_refresh,
                          self.account, self.container)
class ObjectStorageTest(unittest.TestCase):
    def setUp(self):
        self.fake_endpoint = "http://1.2.3.4:8000"
        self.api = FakeStorageApi("NS", endpoint=self.fake_endpoint)
        self.account = "test"
        self.container = "fake"
        self.headers = {"x-oio-req-id": random_str(32)}
        self.policy = "THREECOPIES"
        self.uri_base = self.fake_endpoint + "/v3.0/NS"

    def test_handle_container_not_found(self):
        @handle_container_not_found
        def test(self, account, container):
            raise exceptions.NotFound("No container")

        container = random_str(32)
        self.assertRaises(
            exceptions.NoSuchContainer, test, self, self.account, container)

    def test_handle_object_not_found(self):
        @handle_object_not_found
        def test(self, account, container, obj):
            raise exceptions.NotFound("No object")

        obj = random_str(32)
        self.assertRaises(
            exceptions.NoSuchObject, test, self, self.account, self.container,
            obj)

    def test_container_list(self):
        resp = FakeApiResponse()
        name = random_str(32)
        marker = random_str(32)
        delimiter = random_str(32)
        end_marker = random_str(32)
        prefix = random_str(32)
        limit = random.randint(1, 1000)
        body = {"listing": [[name, 0, 0, 0]]}
        fake_endpoint = 'fake_endpoint'
        self.api.account._direct_request = Mock(return_value=(resp, body))
        self.api.account._get_account_addr = Mock(return_value=fake_endpoint)
        containers = self.api.container_list(
            self.account, limit=limit, marker=marker, prefix=prefix,
            delimiter=delimiter, end_marker=end_marker, headers=self.headers)
        params = {"id": self.account, "prefix": prefix, "delimiter": delimiter,
                  "marker": marker, "end_marker": end_marker, "limit": limit}
        uri = "http://%s/v1.0/account/containers" % fake_endpoint
        self.api.account._direct_request.assert_called_once_with(
            'GET', uri, params=params, headers=self.headers)
        self.assertEqual(len(containers), 1)

    def test_object_list(self):
        api = self.api
        marker = random_str(32)
        delimiter = random_str(32)
        end_marker = random_str(32)
        prefix = random_str(32)
        limit = random.randint(1, 1000)
        name0 = random_str(32)
        name1 = random_str(32)
        resp_body = {"objects": [{"name": name0}, {"name": name1}]}
        resp = FakeApiResponse()
        resp.headers = {}
        api.container._direct_request = Mock(return_value=(resp, resp_body))
        listing = api.object_list(
            self.account, self.container, limit=limit, marker=marker,
            prefix=prefix, delimiter=delimiter, end_marker=end_marker,
            headers=self.headers)
        uri = "%s/container/list" % self.uri_base
        params = {'acct': self.account, 'ref': self.container,
                  'marker': marker, 'max': limit,
                  'delimiter': delimiter, 'prefix': prefix,
                  'end_marker': end_marker,
                  'properties': False}
        api.container._direct_request.assert_called_once_with(
            'GET', uri, params=params, headers=self.headers)
        self.assertEqual(len(listing['objects']), 2)

    def test_container_show(self):
        api = self.api
        resp = FakeApiResponse()
        name = random_str(32)
        cont_size = random.randint(1, 1000)
        resp.headers = {
            container_headers["size"]: cont_size
        }
        api.container._direct_request = Mock(return_value=(resp, {}))
        info = api.container_show(self.account, name, headers=self.headers)
        uri = "%s/container/show" % self.uri_base
        params = {'acct': self.account, 'ref': name}
        api.container._direct_request.assert_called_once_with(
            'GET', uri, params=params, headers=self.headers)
        self.assertEqual(info, {})

    def test_container_show_not_found(self):
        api = self.api
        api.container._direct_request = Mock(
            side_effect=exceptions.NotFound("No container"))
        name = random_str(32)
        self.assertRaises(exceptions.NoSuchContainer, api.container_show,
                          self.account, name)

    def test_container_create(self):
        api = self.api
        resp = FakeApiResponse()
        resp.status = 201
        api.container._direct_request = Mock(return_value=(resp, None))

        name = random_str(32)
        result = api.container_create(self.account, name, headers=self.headers)
        self.assertEqual(result, True)

        uri = "%s/container/create" % self.uri_base
        params = {'acct': self.account, 'ref': name}
        self.headers['x-oio-action-mode'] = 'autocreate'
        data = json.dumps({'properties': {}, 'system': {}})
        api.container._direct_request.assert_called_once_with(
            'POST', uri, params=params, data=data,
            headers=self.headers)

    def test_container_create_exist(self):
        api = self.api
        resp = FakeApiResponse()
        resp.status = 204
        api.container._direct_request = Mock(return_value=(resp, None))

        name = random_str(32)
        result = api.container_create(self.account, name)
        self.assertEqual(result, False)

    def test_container_delete(self):
        api = self.api

        resp = FakeApiResponse()
        resp.status_code = 204
        api.container._direct_request = Mock(return_value=(resp, None))
        api.directory.unlink = Mock(return_value=None)
        name = random_str(32)
        api.container_delete(self.account, name, headers=self.headers)

        uri = "%s/container/destroy" % self.uri_base
        params = {'acct': self.account, 'ref': name}
        api.container._direct_request.assert_called_once_with(
            'POST', uri, params=params, headers=self.headers)

    def test_container_delete_not_empty(self):
        api = self.api

        api.container._direct_request = Mock(
            side_effect=exceptions.Conflict(""))
        api.directory.unlink = Mock(return_value=None)
        name = random_str(32)

        self.assertRaises(
            exceptions.ContainerNotEmpty, api.container_delete, self.account,
            name)

    def test_container_update(self):
        api = self.api

        name = random_str(32)
        key = random_str(32)
        value = random_str(32)
        meta = {key: value}
        resp = FakeApiResponse()
        api.container._direct_request = Mock(return_value=(resp, None))
        api.container_set_properties(
            self.account, name, meta, headers=self.headers)

        data = json.dumps({'properties': meta, 'system': {}})
        uri = "%s/container/set_properties" % self.uri_base
        params = {'acct': self.account, 'ref': name}
        api.container._direct_request.assert_called_once_with(
            'POST', uri, data=data, params=params, headers=self.headers)

    def test_object_show(self):
        api = self.api
        name = random_str(32)
        size = random.randint(1, 1000)
        content_hash = random_str(32)
        content_type = random_str(32)
        resp = FakeApiResponse()
        resp.headers = {object_headers["name"]: name,
                        object_headers["size"]: str(size),
                        object_headers["hash"]: content_hash,
                        object_headers["mime_type"]: content_type}
        api.container._direct_request = Mock(
            return_value=(resp, {'properties': {}}))
        obj = api.object_show(
            self.account, self.container, name, headers=self.headers)

        uri = "%s/content/get_properties" % self.uri_base
        params = {'acct': self.account, 'ref': self.container,
                  'path': name}
        api.container._direct_request.assert_called_once_with(
            'POST', uri, params=params, data=None, headers=self.headers)
        self.assertIsNotNone(obj)

    def test_object_create_no_data(self):
        api = self.api
        name = random_str(32)
        self.assertRaises(exceptions.MissingData, api.object_create,
                          self.account, self.container, obj_name=name)

    def test_object_create_no_name(self):
        api = self.api
        self.assertRaises(exceptions.MissingName, api.object_create,
                          self.account, self.container, data="x")

    def test_object_create_missing_file(self):
        api = self.api
        name = random_str(32)
        self.assertRaises(
            exceptions.FileNotFound, api.object_create, self.account,
            self.container, name)

    def test_object_create_from_file(self):
        self.api._object_create = Mock(return_value=None)
        src = NamedTemporaryFile()
        self.api.object_create_ext(
            self.account, self.container, file_or_path=src)
        self.api._object_create.assert_called_once()
        call_args = self.api._object_create.call_args
        self.assertIs(call_args[0][0], self.account)
        self.assertIs(call_args[0][1], self.container)
        self.assertEqual(call_args[0][2], basename(src.name))
        self.assertIs(call_args[0][3], src)

    def test_object_create_from_file_path(self):
        self.api._object_create = Mock(return_value=None)
        src = NamedTemporaryFile()
        self.api.object_create_ext(
            self.account, self.container, file_or_path=src.name)
        self.api._object_create.assert_called_once()
        call_args = self.api._object_create.call_args
        self.assertIs(call_args[0][0], self.account)
        self.assertIs(call_args[0][1], self.container)
        self.assertEqual(call_args[0][2], basename(src.name))
        self.assertIsInstance(call_args[0][3], file)
        self.assertEqual(call_args[0][3].name, src.name)

    def test_object_create_from_iterable(self):
        class DataGen(object):
            def __init__(self):
                self.data = "abcd"
                self.pos = 0

            def __iter__(self):
                return self

            def next(self):
                if self.pos >= len(self.data):
                    raise StopIteration()
                self.pos += 1
                return self.data[self.pos - 1]

        self.api._object_create = Mock(return_value=None)
        name = random_str(32)
        self.api.object_create_ext(
            self.account, self.container, data=DataGen(), obj_name=name)
        self.api._object_create.assert_called_once()
        call_args = self.api._object_create.call_args
        from oio.common.utils import GeneratorIO
        self.assertIs(call_args[0][0], self.account)
        self.assertIs(call_args[0][1], self.container)
        self.assertIs(call_args[0][2], name)
        self.assertIsInstance(call_args[0][3], GeneratorIO)

    def test_object_create_from_string(self):
        self.api._object_create = Mock(return_value=None)
        name = random_str(32)
        self.api.object_create_ext(
            self.account, self.container, data=name, obj_name=name)
        self.api._object_create.assert_called_once()
        call_args = self.api._object_create.call_args
        from io import BytesIO
        self.assertIs(call_args[0][0], self.account)
        self.assertIs(call_args[0][1], self.container)
        self.assertIs(call_args[0][2], name)
        self.assertIsInstance(call_args[0][3], BytesIO)

    def test_object_set_properties(self):
        api = self.api

        name = random_str(32)
        key = random_str(32)
        value = random_str(32)
        meta = {key: value}
        resp = FakeApiResponse()
        api.container._direct_request = Mock(return_value=(resp, None))
        api.object_set_properties(
            self.account, self.container, name, meta, headers=self.headers)

        data = {'properties': meta}
        data = json.dumps(data)
        uri = "%s/content/set_properties" % self.uri_base
        params = {'acct': self.account, 'ref': self.container,
                  'path': name}
        api.container._direct_request.assert_called_once_with(
            'POST', uri, data=data, params=params, headers=self.headers)

    def test_object_del_properties(self):
        resp = FakeApiResponse()
        self.api.container._direct_request = Mock(return_value=(resp, None))
        self.api.object_del_properties(self.account, self.container, 'a',
                                       ['a'], version='17',
                                       headers=self.headers)
        uri = '%s/content/del_properties' % self.uri_base
        params = {'acct': self.account, 'ref': self.container,
                  'path': 'a', 'version': '17'}
        self.api.container._direct_request.assert_called_once_with(
            'POST', uri, data=json.dumps(['a']), params=params,
            headers=self.headers)

    def test_object_delete(self):
        api = self.api
        name = random_str(32)
        resp_body = [
            chunk("AAAA", "0"), chunk("BBBB", "1"), chunk("CCCC", "2")
        ]
        resp = FakeApiResponse()
        api.container._direct_request = Mock(return_value=(resp, resp_body))

        api.object_delete(
            self.account, self.container, name, headers=self.headers)

        uri = "%s/content/delete" % self.uri_base
        params = {'acct': self.account, 'ref': self.container,
                  'path': name}
        api.container._direct_request.assert_called_once_with(
            'POST', uri, params=params, headers=self.headers)

    def test_object_delete_not_found(self):
        api = self.api
        name = random_str(32)
        api.container._direct_request = Mock(
            side_effect=exceptions.NotFound("No object"))
        self.assertRaises(
            exceptions.NoSuchObject, api.object_delete, self.account,
            self.container, name)

    def test_object_touch(self):
        self.api.container._direct_request = Mock()
        self.api.object_touch(self.account, self.container, 'obj',
                              version='31', headers=self.headers)
        uri = '%s/content/touch' % self.uri_base
        params = {'acct': self.account, 'ref': self.container,
                  'path': 'obj', 'version': '31'}
        self.api.container._direct_request.assert_called_once_with(
            'POST', uri, params=params, headers=self.headers)

    def test_sort_chunks(self):
        raw_chunks = [
            chunk("AAAA", "0"), chunk("BBBB", "0"),
            chunk("CCCC", "1"), chunk("DDDD", "1"),
            chunk("EEEE", "2"), chunk("FFFF", "2"),
        ]
        chunks = _sort_chunks(raw_chunks, False)
        sorted_chunks = {
            0: [extend(chunk("AAAA", "0"), {"offset": 0}),
                extend(chunk("BBBB", "0"), {"offset": 0})],
            1: [extend(chunk("CCCC", "1"), {"offset": 32}),
                extend(chunk("DDDD", "1"), {"offset": 32})],
            2: [extend(chunk("EEEE", "2"), {"offset": 64}),
                extend(chunk("FFFF", "2"), {"offset": 64})]
            }
        self.assertEqual(chunks, sorted_chunks)
        raw_chunks = [
            chunk("AAAA", "0.0"), chunk("BBBB", "0.1"), chunk("CCCC", "0.2"),
            chunk("DDDD", "1.0"), chunk("EEEE", "1.1"), chunk("FFFF", "1.2"),
        ]
        chunks = _sort_chunks(raw_chunks, True)
        sorted_chunks = {
            0: [extend(chunk("AAAA", "0.0"), {"num": 0, "offset": 0}),
                extend(chunk("BBBB", "0.1"), {"num": 1, "offset": 0}),
                extend(chunk("CCCC", "0.2"), {"num": 2, "offset": 0})],
            1: [extend(chunk("DDDD", "1.0"), {"num": 0, "offset": 32}),
                extend(chunk("EEEE", "1.1"), {"num": 1, "offset": 32}),
                extend(chunk("FFFF", "1.2"), {"num": 2, "offset": 32})]
        }
        self.assertEqual(chunks, sorted_chunks)

    def test_container_refresh_conflict(self):
        self.api.account.container_reset = Mock(
            side_effect=exceptions.Conflict("No update needed"))
        self.assertRaises(
            exceptions.Conflict, self.api.container_refresh, self.account,
            self.container)

    def test_object_create_patch_kwargs(self):
        """
        Check that the patch_kwargs decorator does its job on object_create.
        """
        kwargs = {x: 'test' for x in ObjectStorageApi.EXTRA_KEYWORDS}
        # Pass kwargs to class constructor
        api = ObjectStorageApi('NS', endpoint=self.fake_endpoint,
                               dummy_keyword='dummy_value',
                               **kwargs)
        self.assertNotIn('dummy_keyword', api._global_kwargs)
        for k, v in kwargs.items():
            self.assertIn(k, api._global_kwargs)
            self.assertEqual(v, api._global_kwargs[k])

        # Verify that kwargs are forwarded to method call
        api._object_create = Mock()
        api.object_create_ext(self.account, self.container,
                              data='data', obj_name='dummy')
        api._object_create.assert_called_with(
            self.account, self.container, 'dummy', ANY, ANY,
            append=ANY, headers=ANY, key_file=ANY, policy=ANY, properties=ANY,
            **kwargs)

    def test_container_flush_not_found_1(self):
        self.api.object_list = Mock(
            side_effect=exceptions.NotFound("No container"))
        self.assertRaises(
            exceptions.NoSuchContainer, self.api.container_flush,
            self.account, self.container)

    def test_container_flush_not_found_2(self):
        self.api.object_list = Mock(
            return_value={"objects": [{"name": "test"}]})
        self.api.object_delete_many = Mock(
            side_effect=exceptions.NotFound("No container"))
        self.assertRaises(
            exceptions.NoSuchContainer, self.api.container_flush,
            self.account, self.container)

    def test_container_flush_empty(self):
        self.api.object_list = Mock(return_value={"objects": []})
        self.api.container_flush(self.account, self.container)