class TestMeta2Database(BaseTestCase): def setUp(self): super(TestMeta2Database, self).setUp() self.api = ObjectStorageApi(self.ns) self.account = "test_meta2_database" self.reference = "meta2_database_" + random_str(4) self.meta2_database = Meta2Database(self.conf) self.service_type = 'meta2' def _get_peers(self): linked_services = self.api.directory.list(self.account, self.reference) peers = list() for service in linked_services['srv']: if service['type'] == self.service_type: peers.append(service['host']) return peers def _test_move(self, base=None, fixed_dst=True): if base is None: base = cid_from_name(self.account, self.reference) current_peers = self._get_peers() all_meta2_services = self.conscience.all_services( self.service_type, True) if len(all_meta2_services) <= len(current_peers): self.skipTest("need at least %d more %s" % (len(current_peers)+1, self.service_type)) expected_peers = list(current_peers) src = random.choice(current_peers) expected_peers.remove(src) dst = None if fixed_dst: for service in all_meta2_services: if service['id'] not in current_peers: dst = service['id'] expected_peers.append(dst) moved = self.meta2_database.move(base, src, dst=dst) moved = list(moved) self.assertEqual(1, len(moved)) self.assertTrue(moved[0]['base'].startswith(base)) self.assertEqual(src, moved[0]['src']) if fixed_dst: self.assertEqual(dst, moved[0]['dst']) self.assertIsNone(moved[0]['err']) new_peers = self._get_peers() if fixed_dst: self.assertListEqual(sorted(expected_peers), sorted(new_peers)) else: for expected_service in expected_peers: self.assertIn(expected_service, new_peers) self.assertNotIn(src, new_peers) self.assertEqual(len(expected_peers)+1, len(new_peers)) if self.service_type == 'meta2': properties = self.api.container_get_properties( self.account, self.reference) peers = properties['system']['sys.peers'] new_peers_bis = peers.split(',') self.assertListEqual(sorted(new_peers), sorted(new_peers_bis)) return (src, expected_peers) def test_move(self): self.api.container_create(self.account, self.reference) self.api.object_create(self.account, self.reference, data="move meta2", obj_name="test1") self._test_move() for _ in range(0, 5): self.api.object_show(self.account, self.reference, "test1") self.api.object_create(self.account, self.reference, data="move meta2", obj_name="test2") for _ in range(0, 5): self.api.object_show(self.account, self.reference, "test2") def test_move_with_seq(self): self.api.container_create(self.account, self.reference) properties = self.api.container_get_properties( self.account, self.reference) base = properties['system']['sys.name'] self.api.object_create(self.account, self.reference, data="move meta2", obj_name="test1") self._test_move(base=base) for _ in range(0, 5): self.api.object_show(self.account, self.reference, "test1") self.api.object_create(self.account, self.reference, data="move meta2", obj_name="test2") for _ in range(0, 5): self.api.object_show(self.account, self.reference, "test2") def test_move_without_dst(self): self.api.container_create(self.account, self.reference) self.api.object_create(self.account, self.reference, data="move meta2", obj_name="test1") self._test_move(fixed_dst=False) for _ in range(0, 5): self.api.object_show(self.account, self.reference, "test1") self.api.object_create(self.account, self.reference, data="move meta2", obj_name="test2") for _ in range(0, 5): self.api.object_show(self.account, self.reference, "test2") def test_move_with_src_not_used(self): self.api.container_create(self.account, self.reference) base = cid_from_name(self.account, self.reference) current_peers = self._get_peers() src = None all_meta2_services = self.conscience.all_services('meta2', True) for service in all_meta2_services: if service['id'] not in current_peers: src = service['id'] if src is None: self.skipTest("need at least 1 more meta2") moved = self.meta2_database.move(base, src) moved = list(moved) self.assertEqual(1, len(moved)) self.assertTrue(moved[0]['base'].startswith(base)) self.assertEqual(src, moved[0]['src']) self.assertIsNone(moved[0]['dst']) self.assertIsNotNone(moved[0]['err']) def test_move_with_dst_already_used(self): self.api.container_create(self.account, self.reference) base = cid_from_name(self.account, self.reference) current_peers = self._get_peers() src = random.choice(current_peers) dst = random.choice(current_peers) moved = self.meta2_database.move(base, src, dst=dst) moved = list(moved) self.assertEqual(1, len(moved)) self.assertTrue(moved[0]['base'].startswith(base)) self.assertEqual(src, moved[0]['src']) self.assertEqual(dst, moved[0]['dst']) self.assertIsNotNone(moved[0]['err']) def test_move_with_invalid_src(self): self.api.container_create(self.account, self.reference) base = cid_from_name(self.account, self.reference) src = '127.0.0.1:666' moved = self.meta2_database.move(base, src) moved = list(moved) self.assertEqual(1, len(moved)) self.assertTrue(moved[0]['base'].startswith(base)) self.assertEqual(src, moved[0]['src']) self.assertIsNone(moved[0]['dst']) self.assertIsNotNone(moved[0]['err']) def test_move_with_invalid_dst(self): self.api.container_create(self.account, self.reference) base = cid_from_name(self.account, self.reference) current_peers = self._get_peers() src = random.choice(current_peers) dst = '127.0.0.1:666' moved = self.meta2_database.move(base, src, dst=dst) moved = list(moved) self.assertEqual(1, len(moved)) self.assertTrue(moved[0]['base'].startswith(base)) self.assertEqual(src, moved[0]['src']) self.assertEqual(dst, moved[0]['dst']) self.assertIsNotNone(moved[0]['err']) def test_move_with_1_missing_base(self): self.api.container_create(self.account, self.reference) self.api.object_create(self.account, self.reference, data="move meta2", obj_name="test1") base = cid_from_name(self.account, self.reference) current_peers = self._get_peers() if len(current_peers) <= 1: self.skipTest('need replicated bases') to_remove = random.choice(current_peers) self.admin.remove_base(self.service_type, cid=base, service_id=to_remove) self._test_move() for _ in range(0, 5): self.api.object_show(self.account, self.reference, "test1") self.api.object_create(self.account, self.reference, data="move meta2", obj_name="test2") for _ in range(0, 5): self.api.object_show(self.account, self.reference, "test2") def test_move_with_1_remaining_base(self): self.api.container_create(self.account, self.reference) self.api.object_create(self.account, self.reference, data="move meta2", obj_name="test1") base = cid_from_name(self.account, self.reference) current_peers = self._get_peers() if len(current_peers) <= 1: self.skipTest('need replicated bases') to_remove = list(current_peers) to_remove.remove(random.choice(current_peers)) self.admin.remove_base(self.service_type, cid=base, service_id=to_remove) self._test_move() for _ in range(0, 5): self.api.object_show(self.account, self.reference, "test1") self.api.object_create(self.account, self.reference, data="move meta2", obj_name="test2") for _ in range(0, 5): self.api.object_show(self.account, self.reference, "test2") def test_move_sqlx(self): self.meta2_database = Meta2Database(self.conf, service_type='sqlx') self.service_type = 'sqlx' execute('oio-sqlx -O AutoCreate %s/%s/%s ' '"create table foo (a INT, b TEXT)"' % (self.ns, self.account, self.reference)) self._test_move()
class TestContentVersioning(BaseTestCase): def setUp(self): super(TestContentVersioning, self).setUp() self.api = ObjectStorageApi(self.conf['namespace']) self.container = random_str(8) system = {'sys.m2.policy.version': '3'} self.wait_for_score(('meta2', )) self.api.container_create(self.account, self.container, system=system) def test_versioning_enabled(self): props = self.api.container_get_properties(self.account, self.container) self.assertEqual('3', props['system']['sys.m2.policy.version']) def test_list_versions(self): self.api.object_create(self.account, self.container, obj_name="versioned", data="content0") self.api.object_create(self.account, self.container, obj_name="versioned", data="content1") listing = self.api.object_list(self.account, self.container, versions=True) objects = listing['objects'] self.assertEqual(2, len(objects)) self.assertNotEqual(objects[0]['version'], objects[1]['version']) def test_container_purge(self): # many contents for i in range(0, 4): self.api.object_create(self.account, self.container, obj_name="versioned", data="content") listing = self.api.object_list(self.account, self.container, versions=True) objects = listing['objects'] self.assertEqual(4, len(objects)) oldest_version = min(objects, key=lambda x: x['version']) # use the maxvers of the container configuration self.api.container_purge(self.account, self.container) listing = self.api.object_list(self.account, self.container, versions=True) objects = listing['objects'] self.assertEqual(3, len(objects)) self.assertNotIn(oldest_version, [x['version'] for x in objects]) oldest_version = min(objects, key=lambda x: x['version']) # use the maxvers of the request self.api.container_purge(self.account, self.container, maxvers=1) listing = self.api.object_list(self.account, self.container, versions=True) objects = listing['objects'] self.assertEqual(1, len(objects)) self.assertNotIn(oldest_version, [x['version'] for x in objects]) def test_content_purge(self): # many contents for i in range(0, 4): self.api.object_create(self.account, self.container, obj_name="versioned", data="content") listing = self.api.object_list(self.account, self.container, versions=True) objects = listing['objects'] self.assertEqual(4, len(objects)) oldest_version = min(objects, key=lambda x: x['version']) # use the maxvers of the container configuration self.api.container.content_purge(self.account, self.container, "versioned") listing = self.api.object_list(self.account, self.container, versions=True) objects = listing['objects'] self.assertEqual(3, len(objects)) self.assertNotIn(oldest_version, [x['version'] for x in objects]) oldest_version = min(objects, key=lambda x: x['version']) # use the maxvers of the request self.api.container.content_purge(self.account, self.container, "versioned", maxvers=1) listing = self.api.object_list(self.account, self.container, versions=True) objects = listing['objects'] self.assertEqual(1, len(objects)) self.assertNotIn(oldest_version, [x['version'] for x in objects]) # other contents for i in range(0, 4): self.api.object_create(self.account, self.container, obj_name="versioned2", data="content" + str(i)) listing = self.api.object_list(self.account, self.container, versions=True) objects = listing['objects'] self.assertEqual(5, len(objects)) # use the maxvers of the container configuration self.api.container.content_purge(self.account, self.container, "versioned") listing = self.api.object_list(self.account, self.container, versions=True) objects = listing['objects'] self.assertEqual(5, len(objects)) def test_delete_exceeding_version(self): def check_num_objects_and_get_oldest_version(expected_objects, expected_deleted_aliases, oldest_version): listing = self.api.object_list(self.account, self.container, versions=True) objects = listing['objects'] nb_objects = 0 nb_deleted = 0 new_oldest_version = 0 for obj in objects: if obj['deleted']: nb_deleted += 1 else: nb_objects += 1 if new_oldest_version == 0 \ or new_oldest_version > obj['version']: new_oldest_version = obj['version'] self.assertEqual(expected_objects, nb_objects) self.assertEqual(expected_deleted_aliases, nb_deleted) if oldest_version is not None: self.assertLess(oldest_version, new_oldest_version) return new_oldest_version system = {'sys.m2.policy.version.delete_exceeding': '1'} self.api.container_set_properties(self.account, self.container, system=system) self.api.object_create(self.account, self.container, obj_name="versioned", data="content0") oldest_version = check_num_objects_and_get_oldest_version(1, 0, None) self.api.object_create(self.account, self.container, obj_name="versioned", data="content1") self.assertEqual(oldest_version, check_num_objects_and_get_oldest_version(2, 0, None)) self.api.object_create(self.account, self.container, obj_name="versioned", data="content2") self.assertEqual(oldest_version, check_num_objects_and_get_oldest_version(3, 0, None)) self.api.object_create(self.account, self.container, obj_name="versioned", data="content3") oldest_version = check_num_objects_and_get_oldest_version( 3, 0, oldest_version) self.api.object_delete(self.account, self.container, "versioned") self.assertEqual(oldest_version, check_num_objects_and_get_oldest_version(3, 1, None)) self.api.object_create(self.account, self.container, obj_name="versioned", data="content4") oldest_version = check_num_objects_and_get_oldest_version( 3, 1, oldest_version) self.api.object_create(self.account, self.container, obj_name="versioned", data="content5") oldest_version = check_num_objects_and_get_oldest_version( 3, 1, oldest_version) self.api.object_create(self.account, self.container, obj_name="versioned", data="content6") # FIXME(adu) The deleted alias should be deleted at the same time oldest_version = check_num_objects_and_get_oldest_version( 3, 1, oldest_version) self.api.object_create(self.account, self.container, obj_name="versioned", data="content7") oldest_version = check_num_objects_and_get_oldest_version( 3, 1, oldest_version) def test_change_flag_delete_exceeding_versions(self): def check_num_objects(expected): listing = self.api.object_list(self.account, self.container, versions=True) objects = listing['objects'] self.assertEqual(expected, len(objects)) for i in range(5): self.api.object_create(self.account, self.container, obj_name="versioned", data="content" + str(i)) check_num_objects(5) system = {'sys.m2.policy.version.delete_exceeding': '1'} self.api.container_set_properties(self.account, self.container, system=system) self.api.object_create(self.account, self.container, obj_name="versioned", data="content5") check_num_objects(3) for i in range(6, 10): self.api.object_create(self.account, self.container, obj_name="versioned", data="content" + str(i)) check_num_objects(3) system['sys.m2.policy.version.delete_exceeding'] = '0' self.api.container_set_properties(self.account, self.container, system=system) self.api.object_create(self.account, self.container, obj_name="versioned", data="content11") check_num_objects(4) def test_purge_objects_with_delete_marker(self): def check_num_objects(expected): listing = self.api.object_list(self.account, self.container, versions=True) objects = listing['objects'] self.assertEqual(expected, len(objects)) for i in range(5): self.api.object_create(self.account, self.container, obj_name="versioned", data="content" + str(i)) check_num_objects(5) self.api.object_delete(self.account, self.container, "versioned") self.assertRaises(NoSuchObject, self.api.object_locate, self.account, self.container, "versioned") check_num_objects(6) self.api.container.content_purge(self.account, self.container, "versioned") self.assertRaises(NoSuchObject, self.api.object_locate, self.account, self.container, "versioned") check_num_objects(4) system = {'sys.m2.keep_deleted_delay': '1'} self.api.container_set_properties(self.account, self.container, system=system) time.sleep(2) self.api.container.content_purge(self.account, self.container, "versioned") check_num_objects(0) def test_list_objects(self): resp = self.api.object_list(self.account, self.container) self.assertEqual(0, len(list(resp['objects']))) self.assertFalse(resp.get('truncated')) def _check_objects(expected_objects, objects): self.assertEqual(len(expected_objects), len(objects)) for i in range(len(expected_objects)): self.assertEqual(expected_objects[i]['name'], objects[i]['name']) self.assertEqual(int(expected_objects[i]['version']), int(objects[i]['version'])) self.assertEqual(true_value(expected_objects[i]['deleted']), true_value(objects[i]['deleted'])) all_versions = dict() def _create_object(obj_name, all_versions): self.api.object_create(self.account, self.container, obj_name=obj_name, data="test") versions = all_versions.get(obj_name, list()) versions.append( self.api.object_show(self.account, self.container, obj_name)) all_versions[obj_name] = versions def _delete_object(obj_name, all_versions): self.api.object_delete(self.account, self.container, obj_name) versions = all_versions.get(obj_name, list()) versions.append( self.api.object_show(self.account, self.container, obj_name)) all_versions[obj_name] = versions def _get_current_objects(all_versions): current_objects = list() obj_names = sorted(all_versions.keys()) for obj_name in obj_names: obj = all_versions[obj_name][-1] if not true_value(obj['deleted']): current_objects.append(obj) return current_objects def _get_object_versions(all_versions): object_versions = list() obj_names = sorted(all_versions.keys()) for obj_name in obj_names: versions = all_versions[obj_name] versions.reverse() object_versions += versions versions.reverse() return object_versions # 0 object expected_current_objects = _get_current_objects(all_versions) expected_object_versions = _get_object_versions(all_versions) resp = self.api.object_list(self.account, self.container, limit=3) _check_objects(expected_current_objects, list(resp['objects'])) self.assertFalse(resp.get('truncated')) resp = self.api.object_list(self.account, self.container, limit=2) _check_objects(expected_current_objects, list(resp['objects'])) self.assertFalse(resp.get('truncated')) resp = self.api.object_list(self.account, self.container, limit=1) _check_objects(expected_current_objects, list(resp['objects'])) self.assertFalse(resp.get('truncated')) resp = self.api.object_list(self.account, self.container, versions=True) _check_objects(expected_object_versions, list(resp['objects'])) self.assertFalse(resp.get('truncated')) resp = self.api.object_list(self.account, self.container, versions=True, limit=3) _check_objects(expected_object_versions, list(resp['objects'])) self.assertFalse(resp.get('truncated')) # 3 objects with 1 version for i in range(3): _create_object("versioned" + str(i), all_versions) expected_current_objects = _get_current_objects(all_versions) expected_object_versions = _get_object_versions(all_versions) resp = self.api.object_list(self.account, self.container) _check_objects(expected_current_objects, list(resp['objects'])) self.assertFalse(resp.get('truncated')) resp = self.api.object_list(self.account, self.container, limit=3) _check_objects(expected_current_objects, list(resp['objects'])) self.assertFalse(resp.get('truncated')) resp = self.api.object_list(self.account, self.container, limit=2) _check_objects(expected_current_objects[:2], list(resp['objects'])) self.assertTrue(resp.get('truncated')) self.assertEqual('versioned1', resp['next_marker']) resp = self.api.object_list(self.account, self.container, limit=1) _check_objects(expected_current_objects[:1], list(resp['objects'])) self.assertTrue(resp.get('truncated')) self.assertEqual('versioned0', resp['next_marker']) resp = self.api.object_list(self.account, self.container, versions=True) _check_objects(expected_object_versions, list(resp['objects'])) self.assertFalse(resp.get('truncated')) resp = self.api.object_list(self.account, self.container, versions=True, limit=3) _check_objects(expected_object_versions[:3], list(resp['objects'])) self.assertFalse(resp.get('truncated')) resp = self.api.object_list(self.account, self.container, marker='versioned0') _check_objects(expected_current_objects[1:], list(resp['objects'])) self.assertFalse(resp.get('truncated')) resp = self.api.object_list(self.account, self.container, marker='versioned0', limit=1) _check_objects(expected_current_objects[1:2], list(resp['objects'])) self.assertTrue(resp.get('truncated')) self.assertEqual('versioned1', resp['next_marker']) resp = self.api.object_list(self.account, self.container, marker='versioned0', versions=True) _check_objects(expected_object_versions[1:], list(resp['objects'])) self.assertFalse(resp.get('truncated')) resp = self.api.object_list(self.account, self.container, marker='versioned0', versions=True, limit=3) _check_objects(expected_object_versions[1:], list(resp['objects'])) self.assertFalse(resp.get('truncated')) # 3 objects with 2 versions for i in range(3): _create_object("versioned" + str(i), all_versions) expected_current_objects = _get_current_objects(all_versions) expected_object_versions = _get_object_versions(all_versions) resp = self.api.object_list(self.account, self.container) _check_objects(expected_current_objects, list(resp['objects'])) self.assertFalse(resp.get('truncated')) resp = self.api.object_list(self.account, self.container, limit=3) _check_objects(expected_current_objects, list(resp['objects'])) self.assertFalse(resp.get('truncated')) resp = self.api.object_list(self.account, self.container, limit=2) _check_objects(expected_current_objects[:2], list(resp['objects'])) self.assertTrue(resp.get('truncated')) self.assertEqual('versioned1', resp['next_marker']) resp = self.api.object_list(self.account, self.container, limit=1) _check_objects(expected_current_objects[:1], list(resp['objects'])) self.assertTrue(resp.get('truncated')) self.assertEqual('versioned0', resp['next_marker']) resp = self.api.object_list(self.account, self.container, versions=True) _check_objects(expected_object_versions, list(resp['objects'])) self.assertFalse(resp.get('truncated')) resp = self.api.object_list(self.account, self.container, versions=True, limit=3) _check_objects(expected_object_versions[:3], list(resp['objects'])) self.assertTrue(resp.get('truncated')) self.assertEqual('versioned1', resp['next_marker']) resp = self.api.object_list(self.account, self.container, marker='versioned0') _check_objects(expected_current_objects[1:], list(resp['objects'])) self.assertFalse(resp.get('truncated')) resp = self.api.object_list(self.account, self.container, marker='versioned0', limit=1) _check_objects(expected_current_objects[1:2], list(resp['objects'])) self.assertTrue(resp.get('truncated')) self.assertEqual('versioned1', resp['next_marker']) resp = self.api.object_list(self.account, self.container, marker='versioned0', versions=True) _check_objects(expected_object_versions[2:], list(resp['objects'])) self.assertFalse(resp.get('truncated')) resp = self.api.object_list(self.account, self.container, marker='versioned0', versions=True, limit=3) _check_objects(expected_object_versions[2:5], list(resp['objects'])) self.assertTrue(resp.get('truncated')) self.assertEqual('versioned2', resp['next_marker']) # 3 objects with 2 versions and 1 object with delete marker _delete_object("versioned1", all_versions) expected_current_objects = _get_current_objects(all_versions) expected_object_versions = _get_object_versions(all_versions) resp = self.api.object_list(self.account, self.container) _check_objects(expected_current_objects, list(resp['objects'])) self.assertFalse(resp.get('truncated')) resp = self.api.object_list(self.account, self.container, limit=3) _check_objects(expected_current_objects, list(resp['objects'])) self.assertFalse(resp.get('truncated')) resp = self.api.object_list(self.account, self.container, limit=2) _check_objects(expected_current_objects, list(resp['objects'])) self.assertFalse(resp.get('truncated')) resp = self.api.object_list(self.account, self.container, limit=1) _check_objects(expected_current_objects[:1], list(resp['objects'])) self.assertTrue(resp.get('truncated')) self.assertEqual('versioned0', resp['next_marker']) resp = self.api.object_list(self.account, self.container, versions=True) _check_objects(expected_object_versions, list(resp['objects'])) self.assertFalse(resp.get('truncated')) resp = self.api.object_list(self.account, self.container, versions=True, limit=3) _check_objects(expected_object_versions[:3], list(resp['objects'])) self.assertTrue(resp.get('truncated')) self.assertEqual('versioned1', resp['next_marker']) resp = self.api.object_list(self.account, self.container, marker='versioned0') _check_objects(expected_current_objects[1:], list(resp['objects'])) self.assertFalse(resp.get('truncated')) resp = self.api.object_list(self.account, self.container, marker='versioned0', limit=1) _check_objects(expected_current_objects[1:], list(resp['objects'])) self.assertFalse(resp.get('truncated')) resp = self.api.object_list(self.account, self.container, marker='versioned0', versions=True) _check_objects(expected_object_versions[2:], list(resp['objects'])) self.assertFalse(resp.get('truncated')) resp = self.api.object_list(self.account, self.container, marker='versioned0', versions=True, limit=3) _check_objects(expected_object_versions[2:5], list(resp['objects'])) self.assertTrue(resp.get('truncated')) self.assertEqual('versioned1', resp['next_marker']) # 3 objects with 2 versions and 2 objects with delete marker _delete_object("versioned0", all_versions) expected_current_objects = _get_current_objects(all_versions) expected_object_versions = _get_object_versions(all_versions) resp = self.api.object_list(self.account, self.container) _check_objects(expected_current_objects, list(resp['objects'])) self.assertFalse(resp.get('truncated')) resp = self.api.object_list(self.account, self.container, limit=3) _check_objects(expected_current_objects, list(resp['objects'])) self.assertFalse(resp.get('truncated')) resp = self.api.object_list(self.account, self.container, limit=2) _check_objects(expected_current_objects, list(resp['objects'])) self.assertFalse(resp.get('truncated')) resp = self.api.object_list(self.account, self.container, limit=1) _check_objects(expected_current_objects, list(resp['objects'])) self.assertFalse(resp.get('truncated')) resp = self.api.object_list(self.account, self.container, versions=True) _check_objects(expected_object_versions, list(resp['objects'])) self.assertFalse(resp.get('truncated')) resp = self.api.object_list(self.account, self.container, versions=True, limit=3) _check_objects(expected_object_versions[:3], list(resp['objects'])) self.assertTrue(resp.get('truncated')) self.assertEqual('versioned0', resp['next_marker']) resp = self.api.object_list(self.account, self.container, marker='versioned0') _check_objects(expected_current_objects, list(resp['objects'])) self.assertFalse(resp.get('truncated')) resp = self.api.object_list(self.account, self.container, marker='versioned0', limit=1) _check_objects(expected_current_objects, list(resp['objects'])) self.assertFalse(resp.get('truncated')) resp = self.api.object_list(self.account, self.container, marker='versioned0', versions=True) _check_objects(expected_object_versions[3:], list(resp['objects'])) self.assertFalse(resp.get('truncated')) resp = self.api.object_list(self.account, self.container, marker='versioned0', versions=True, limit=3) _check_objects(expected_object_versions[3:6], list(resp['objects'])) self.assertTrue(resp.get('truncated')) self.assertEqual('versioned1', resp['next_marker']) # 3 objects with 2 versions and 3 objects with delete marker _delete_object("versioned2", all_versions) expected_current_objects = _get_current_objects(all_versions) expected_object_versions = _get_object_versions(all_versions) resp = self.api.object_list(self.account, self.container) _check_objects(expected_current_objects, list(resp['objects'])) self.assertFalse(resp.get('truncated')) resp = self.api.object_list(self.account, self.container, limit=3) _check_objects(expected_current_objects, list(resp['objects'])) self.assertFalse(resp.get('truncated')) resp = self.api.object_list(self.account, self.container, limit=2) _check_objects(expected_current_objects, list(resp['objects'])) self.assertFalse(resp.get('truncated')) resp = self.api.object_list(self.account, self.container, limit=1) _check_objects(expected_current_objects, list(resp['objects'])) self.assertFalse(resp.get('truncated')) resp = self.api.object_list(self.account, self.container, versions=True) _check_objects(expected_object_versions, list(resp['objects'])) self.assertFalse(resp.get('truncated')) resp = self.api.object_list(self.account, self.container, versions=True, limit=3) _check_objects(expected_object_versions[:3], list(resp['objects'])) self.assertTrue(resp.get('truncated')) self.assertEqual('versioned0', resp['next_marker']) resp = self.api.object_list(self.account, self.container, marker='versioned0') _check_objects(expected_current_objects, list(resp['objects'])) self.assertFalse(resp.get('truncated')) resp = self.api.object_list(self.account, self.container, marker='versioned0', limit=1) _check_objects(expected_current_objects, list(resp['objects'])) self.assertFalse(resp.get('truncated')) resp = self.api.object_list(self.account, self.container, marker='versioned0', versions=True) _check_objects(expected_object_versions[3:], list(resp['objects'])) self.assertFalse(resp.get('truncated')) resp = self.api.object_list(self.account, self.container, marker='versioned0', versions=True, limit=3) _check_objects(expected_object_versions[3:6], list(resp['objects'])) self.assertTrue(resp.get('truncated')) self.assertEqual('versioned1', resp['next_marker']) # 3 objects with 2 versions and 3 objects with delete marker # (1 current version and 2 non current versions) _create_object("versioned0", all_versions) expected_current_objects = _get_current_objects(all_versions) expected_object_versions = _get_object_versions(all_versions) resp = self.api.object_list(self.account, self.container) _check_objects(expected_current_objects, list(resp['objects'])) self.assertFalse(resp.get('truncated')) resp = self.api.object_list(self.account, self.container, limit=3) _check_objects(expected_current_objects, list(resp['objects'])) self.assertFalse(resp.get('truncated')) resp = self.api.object_list(self.account, self.container, limit=2) _check_objects(expected_current_objects, list(resp['objects'])) self.assertFalse(resp.get('truncated')) resp = self.api.object_list(self.account, self.container, limit=1) _check_objects(expected_current_objects, list(resp['objects'])) self.assertFalse(resp.get('truncated')) resp = self.api.object_list(self.account, self.container, versions=True) _check_objects(expected_object_versions, list(resp['objects'])) self.assertFalse(resp.get('truncated')) resp = self.api.object_list(self.account, self.container, versions=True, limit=3) _check_objects(expected_object_versions[:3], list(resp['objects'])) self.assertTrue(resp.get('truncated')) self.assertEqual('versioned0', resp['next_marker']) resp = self.api.object_list(self.account, self.container, marker='versioned0') _check_objects(expected_current_objects[1:], list(resp['objects'])) self.assertFalse(resp.get('truncated')) resp = self.api.object_list(self.account, self.container, marker='versioned0', limit=1) _check_objects(expected_current_objects[1:], list(resp['objects'])) self.assertFalse(resp.get('truncated')) resp = self.api.object_list(self.account, self.container, marker='versioned0', versions=True) _check_objects(expected_object_versions[4:], list(resp['objects'])) self.assertFalse(resp.get('truncated')) resp = self.api.object_list(self.account, self.container, marker='versioned0', versions=True, limit=3) _check_objects(expected_object_versions[4:7], list(resp['objects'])) self.assertTrue(resp.get('truncated')) self.assertEqual('versioned1', resp['next_marker'])