def test_expired_claim(self): meta = {"ttl": 0, "grace": 60} claim_id, messages = self.controller.create(self.queue_name, meta, project=self.project) with testing.expect(storage.errors.DoesNotExist): self.controller.get(self.queue_name, claim_id, project=self.project) with testing.expect(storage.errors.DoesNotExist): self.controller.update(self.queue_name, claim_id, meta, project=self.project)
def test_illformed_id(self): # any ill-formed IDs should be regarded as non-existing ones. self.controller.delete(self.queue_name, "illformed", project=self.project) with testing.expect(errors.DoesNotExist): self.controller.get(self.queue_name, "illformed", project=self.project) with testing.expect(errors.DoesNotExist): self.controller.update(self.queue_name, "illformed", {"ttl": 40}, project=self.project)
def test_expired_claim(self): meta = {'ttl': 0, 'grace': 60} claim_id, messages = self.controller.create(self.queue_name, meta, project=self.project) with testing.expect(storage.errors.DoesNotExist): self.controller.get(self.queue_name, claim_id, project=self.project) with testing.expect(storage.errors.DoesNotExist): self.controller.update(self.queue_name, claim_id, meta, project=self.project)
def test_expired_claim(self): meta = {'ttl': 0, 'grace': 60} claim_id, messages = self.controller.create(self.queue_name, meta, project=self.project) with testing.expect(storage.exceptions.DoesNotExist): self.controller.get(self.queue_name, claim_id, project=self.project) with testing.expect(storage.exceptions.DoesNotExist): self.controller.update(self.queue_name, claim_id, meta, project=self.project)
def test_claim_effects(self): client_uuid = uuid.uuid4() _insert_fixtures(self.controller, self.queue_name, project=self.project, client_uuid=client_uuid, num=12) def list_messages(include_claimed=None): kwargs = {"project": self.project, "client_uuid": client_uuid, "echo": True} # Properly test default value if include_claimed is not None: kwargs["include_claimed"] = include_claimed interaction = self.controller.list(self.queue_name, **kwargs) messages = next(interaction) return [msg["id"] for msg in messages] messages_before = list_messages(True) meta = {"ttl": 70, "grace": 60} another_cid, _ = self.claim_controller.create(self.queue_name, meta, project=self.project) messages_after = list_messages(True) self.assertEqual(messages_before, messages_after) messages_excluding_claimed = list_messages() self.assertNotEqual(messages_before, messages_excluding_claimed) self.assertEqual(2, len(messages_excluding_claimed)) cid, msgs = self.claim_controller.create(self.queue_name, meta, project=self.project) [msg1, msg2] = msgs # A wrong claim does not ensure the message deletion with testing.expect(storage.errors.NotPermitted): self.controller.delete(self.queue_name, msg1["id"], project=self.project, claim=another_cid) # Make sure a message can be deleted with a claim self.controller.delete(self.queue_name, msg1["id"], project=self.project, claim=cid) with testing.expect(storage.errors.DoesNotExist): self.controller.get(self.queue_name, msg1["id"], project=self.project) # Make sure such a deletion is idempotent self.controller.delete(self.queue_name, msg1["id"], project=self.project, claim=cid) # A non-existing claim does not ensure the message deletion self.claim_controller.delete(self.queue_name, cid, project=self.project) with testing.expect(storage.errors.NotPermitted): self.controller.delete(self.queue_name, msg2["id"], project=self.project, claim=cid)
def test_illformed_id(self): # any ill-formed IDs should be regarded as non-existing ones. self.controller.delete(self.queue_name, 'illformed', project=self.project) with testing.expect(errors.DoesNotExist): self.controller.get(self.queue_name, 'illformed', project=self.project) with testing.expect(errors.DoesNotExist): self.controller.update(self.queue_name, 'illformed', {'ttl': 40}, project=self.project)
def test_message_lifecycle(self): queue_name = self.queue_name messages = [ { 'ttl': 60, 'body': { 'event': 'BackupStarted', 'backupId': 'c378813c-3f0b-11e2-ad92-7823d2b0f3ce' } }, ] # Test Message Creation created = list(self.controller.post(queue_name, messages, project=self.project, client_uuid=uuid.uuid4())) self.assertEqual(len(created), 1) # Test Message Get self.controller.get(queue_name, created[0], project=self.project) # Test Message Deletion self.controller.delete(queue_name, created[0], project=self.project) # Test does not exist with testing.expect(storage.exceptions.DoesNotExist): self.controller.get(queue_name, created[0], project=self.project)
def test_message_lifecycle(self): queue_name = self.queue_name message = { 'ttl': 60, 'body': { 'event': 'BackupStarted', 'backupId': 'c378813c-3f0b-11e2-ad92-7823d2b0f3ce' } } # Test Message Creation created = list(self.controller.post(queue_name, [message], project=self.project, client_uuid=uuid.uuid4())) self.assertEqual(len(created), 1) message_id = created[0] # Test Message Get message_out = self.controller.get(queue_name, message_id, project=self.project) self.assertEqual(set(message_out), set(('id', 'body', 'ttl', 'age'))) self.assertEqual(message_out['id'], message_id) self.assertEqual(message_out['body'], message['body']) self.assertEqual(message_out['ttl'], message['ttl']) # Test Message Deletion self.controller.delete(queue_name, message_id, project=self.project) # Test does not exist with testing.expect(storage.errors.DoesNotExist): self.controller.get(queue_name, message_id, project=self.project)
def test_message_lifecycle(self): queue_name = self.queue_name messages = [ { 'ttl': 60, 'body': { 'event': 'BackupStarted', 'backupId': 'c378813c-3f0b-11e2-ad92-7823d2b0f3ce' } }, ] # Test Message Creation created = list( self.controller.post(queue_name, messages, project=self.project, client_uuid='unused')) self.assertEqual(len(created), 1) # Test Message Get self.controller.get(queue_name, created[0], project=self.project) # Test Message Deletion self.controller.delete(queue_name, created[0], project=self.project) # Test does not exist with testing.expect(storage.exceptions.DoesNotExist): self.controller.get(queue_name, created[0], project=self.project)
def test_illformed_id(self): # any ill-formed IDs should be regarded as non-existing ones. self.controller.delete(self.queue_name, 'illformed', project=self.project) with testing.expect(exceptions.DoesNotExist): self.controller.get(self.queue_name, 'illformed', project=self.project) with testing.expect(exceptions.DoesNotExist): self.controller.update(self.queue_name, 'illformed', {'ttl': 40}, project=self.project)
def test_bad_id(self): # NOTE(cpp-cabrera): A malformed ID should result in an empty # query. Raising an exception for validating IDs makes the # implementation more verbose instead of taking advantage of # the Maybe/Optional protocol, particularly when dealing with # bulk operations. bad_message_id = "xyz" self.controller.delete(self.queue_name, bad_message_id, project=self.project) with testing.expect(errors.MessageDoesNotExist): self.controller.get(self.queue_name, bad_message_id, project=self.project)
def test_expired_message(self): messages = [{'body': 3.14, 'ttl': 0}] [msgid] = self.controller.post(self.queue_name, messages, project=self.project, client_uuid='my_uuid') with testing.expect(storage.exceptions.DoesNotExist): self.controller.get(self.queue_name, msgid, project=self.project) countof = self.queue_controller.stats(self.queue_name, project=self.project) self.assertEquals(countof['messages']['free'], 0)
def test_multi_ids(self): messages_in = [{"ttl": 120, "body": 0}, {"ttl": 240, "body": 1}] ids = self.controller.post(self.queue_name, messages_in, project=self.project, client_uuid=uuid.uuid4()) messages_out = self.controller.bulk_get(self.queue_name, ids, project=self.project) for idx, message in enumerate(messages_out): self.assertEqual(message["body"], idx) self.controller.bulk_delete(self.queue_name, ids, project=self.project) with testing.expect(StopIteration): result = self.controller.bulk_get(self.queue_name, ids, project=self.project) next(result)
def test_bad_id(self): # NOTE(cpp-cabrera): A malformed ID should result in an empty # query. Raising an exception for validating IDs makes the # implementation more verbose instead of taking advantage of # the Maybe/Optional protocol, particularly when dealing with # bulk operations. bad_message_id = 'xyz' self.controller.delete(self.queue_name, bad_message_id, project=self.project) with testing.expect(errors.MessageDoesNotExist): self.controller.get(self.queue_name, bad_message_id, project=self.project)
def test_expired_messages(self): messages = [{"body": 3.14, "ttl": 0}] client_uuid = uuid.uuid4() [msgid] = self.controller.post(self.queue_name, messages, project=self.project, client_uuid=client_uuid) [msgid] = self.controller.post(self.queue_name, messages, project=self.project, client_uuid=client_uuid) time.sleep(self.gc_interval) with testing.expect(storage.errors.DoesNotExist): self.controller.get(self.queue_name, msgid, project=self.project) stats = self.queue_controller.stats(self.queue_name, project=self.project) self.assertEqual(stats["messages"]["free"], 0)
def test_message_lifecycle(self): queue_name = self.queue_name messages = [{"ttl": 60, "body": {"event": "BackupStarted", "backupId": "c378813c-3f0b-11e2-ad92-7823d2b0f3ce"}}] # Test Message Creation created = list(self.controller.post(queue_name, messages, project=self.project, client_uuid=uuid.uuid4())) self.assertEqual(len(created), 1) # Test Message Get self.controller.get(queue_name, created[0], project=self.project) # Test Message Deletion self.controller.delete(queue_name, created[0], project=self.project) # Test does not exist with testing.expect(storage.errors.DoesNotExist): self.controller.get(queue_name, created[0], project=self.project)
def test_expired_messages(self): messages = [{'body': 3.14, 'ttl': 0}] client_uuid = uuid.uuid4() [msgid] = self.controller.post(self.queue_name, messages, project=self.project, client_uuid=client_uuid) time.sleep(self.gc_interval) with testing.expect(storage.errors.DoesNotExist): self.controller.get(self.queue_name, msgid, project=self.project) stats = self.queue_controller.stats(self.queue_name, project=self.project) self.assertEqual(stats['messages']['free'], 0)
def test_multi_ids(self): messages_in = [{'ttl': 120, 'body': 0}, {'ttl': 240, 'body': 1}] ids = self.controller.post(self.queue_name, messages_in, project=self.project, client_uuid=uuid.uuid4()) messages_out = self.controller.bulk_get(self.queue_name, ids, project=self.project) for idx, message in enumerate(messages_out): self.assertEqual(message['body'], idx) self.controller.bulk_delete(self.queue_name, ids, project=self.project) with testing.expect(StopIteration): result = self.controller.bulk_get(self.queue_name, ids, project=self.project) next(result)
def test_multi_ids(self): messages_in = [{'ttl': 120, 'body': 0}, {'ttl': 240, 'body': 1}] ids = self.controller.post(self.queue_name, messages_in, project=self.project, client_uuid='my_uuid') messages_out = self.controller.bulk_get(self.queue_name, ids, project=self.project) for idx, message in enumerate(messages_out): self.assertEquals(message['body'], idx) self.controller.bulk_delete(self.queue_name, ids, project=self.project) with testing.expect(StopIteration): result = self.controller.bulk_get(self.queue_name, ids, project=self.project) next(result)
def test_expired_messages(self): messages = [{'body': 3.14, 'ttl': 0}] client_uuid = uuid.uuid4() [msgid] = self.controller.post(self.queue_name, messages, project=self.project, client_uuid=client_uuid) [msgid] = self.controller.post(self.queue_name, messages, project=self.project, client_uuid=client_uuid) time.sleep(self.gc_interval) with testing.expect(storage.exceptions.DoesNotExist): self.controller.get(self.queue_name, msgid, project=self.project) stats = self.queue_controller.stats(self.queue_name, project=self.project) self.assertEqual(stats['messages']['free'], 0)
def test_claim_effects(self): client_uuid = uuid.uuid4() _insert_fixtures(self.controller, self.queue_name, project=self.project, client_uuid=client_uuid, num=12) def list_messages(include_claimed=None): kwargs = { 'project': self.project, 'client_uuid': client_uuid, 'echo': True, } # Properly test default value if include_claimed is not None: kwargs['include_claimed'] = include_claimed interaction = self.controller.list(self.queue_name, **kwargs) messages = next(interaction) return [msg['id'] for msg in messages] messages_before = list_messages(True) meta = {'ttl': 70, 'grace': 60} another_cid, _ = self.claim_controller.create(self.queue_name, meta, project=self.project) messages_after = list_messages(True) self.assertEqual(messages_before, messages_after) messages_excluding_claimed = list_messages() self.assertNotEqual(messages_before, messages_excluding_claimed) self.assertEqual(2, len(messages_excluding_claimed)) cid, msgs = self.claim_controller.create(self.queue_name, meta, project=self.project) [msg1, msg2] = msgs # A wrong claim does not ensure the message deletion with testing.expect(storage.errors.NotPermitted): self.controller.delete(self.queue_name, msg1['id'], project=self.project, claim=another_cid) # Make sure a message can be deleted with a claim self.controller.delete(self.queue_name, msg1['id'], project=self.project, claim=cid) with testing.expect(storage.errors.DoesNotExist): self.controller.get(self.queue_name, msg1['id'], project=self.project) # Make sure such a deletion is idempotent self.controller.delete(self.queue_name, msg1['id'], project=self.project, claim=cid) # A non-existing claim does not ensure the message deletion self.claim_controller.delete(self.queue_name, cid, project=self.project) with testing.expect(storage.errors.NotPermitted): self.controller.delete(self.queue_name, msg2['id'], project=self.project, claim=cid)
def test_queue_lifecycle(self): # Test Queue Creation created = self.controller.create('test', project=self.project) self.assertTrue(created) # Test Queue Existence self.assertTrue(self.controller.exists('test', project=self.project)) # Test Queue retrieval metadata = self.controller.get_metadata('test', project=self.project) self.assertEqual(metadata, {}) # Test Queue Update created = self.controller.set_metadata('test', project=self.project, metadata=dict(meta='test_meta')) metadata = self.controller.get_metadata('test', project=self.project) self.assertEqual(metadata['meta'], 'test_meta') # Touching an existing queue does not affect metadata created = self.controller.create('test', project=self.project) self.assertFalse(created) metadata = self.controller.get_metadata('test', project=self.project) self.assertEqual(metadata['meta'], 'test_meta') # Test Queue Statistic _insert_fixtures(self.message_controller, 'test', project=self.project, client_uuid='my_uuid', num=6) # NOTE(kgriffs): We can't get around doing this, because # we don't know how the storage drive may be calculating # message timestamps (and may not be monkey-patchable). time.sleep(1) _insert_fixtures(self.message_controller, 'test', project=self.project, client_uuid='my_uuid', num=6) stats = self.controller.stats('test', project=self.project) message_stats = stats['messages'] self.assertEqual(message_stats['free'], 12) self.assertEqual(message_stats['claimed'], 0) self.assertEqual(message_stats['total'], 12) oldest = message_stats['oldest'] newest = message_stats['newest'] self.assertNotEqual(oldest, newest) # NOTE(kgriffs): Ensure "now" is different enough # for the next comparison to work. timeutils.set_time_override() timeutils.advance_time_seconds(10) for message_stat in (oldest, newest): created_iso = message_stat['created'] created = timeutils.parse_isotime(created_iso) self.assertThat(timeutils.normalize_time(created), matchers.LessThan(timeutils.utcnow())) self.assertIn('id', message_stat) self.assertThat(oldest['created'], matchers.LessThan(newest['created'])) # Test Queue Deletion self.controller.delete('test', project=self.project) # Test Queue Existence self.assertFalse(self.controller.exists('test', project=self.project)) # Test DoesNotExist Exception with testing.expect(storage.exceptions.DoesNotExist): self.controller.get_metadata('test', project=self.project) with testing.expect(storage.exceptions.DoesNotExist): self.controller.set_metadata('test', '{}', project=self.project)
def test_queue_lifecycle(self): # Test queue creation created = self.controller.create('test', project=self.project) self.assertTrue(created) # Test queue existence self.assertTrue(self.controller.exists('test', project=self.project)) # Test queue retrieval interaction = self.controller.list(project=self.project) queue = list(next(interaction))[0] self.assertEqual(queue['name'], 'test') # Test queue metadata retrieval metadata = self.controller.get_metadata('test', project=self.project) self.assertEqual(metadata, {}) # Test queue update created = self.controller.set_metadata('test', project=self.project, metadata=dict(meta='test_meta')) metadata = self.controller.get_metadata('test', project=self.project) self.assertEqual(metadata['meta'], 'test_meta') # Touching an existing queue does not affect metadata created = self.controller.create('test', project=self.project) self.assertFalse(created) metadata = self.controller.get_metadata('test', project=self.project) self.assertEqual(metadata['meta'], 'test_meta') client_uuid = uuid.uuid4() # Test queue statistic _insert_fixtures(self.message_controller, 'test', project=self.project, client_uuid=client_uuid, num=6) # NOTE(kgriffs): We can't get around doing this, because # we don't know how the storage drive may be calculating # message timestamps (and may not be monkey-patchable). time.sleep(1.2) _insert_fixtures(self.message_controller, 'test', project=self.project, client_uuid=client_uuid, num=6) stats = self.controller.stats('test', project=self.project) message_stats = stats['messages'] self.assertEqual(message_stats['free'], 12) self.assertEqual(message_stats['claimed'], 0) self.assertEqual(message_stats['total'], 12) oldest = message_stats['oldest'] newest = message_stats['newest'] self.assertNotEqual(oldest, newest) age = oldest['age'] self.assertThat(age, matchers.GreaterThan(0)) # NOTE(kgriffs): Ensure is different enough # for the next comparison to work. soon = timeutils.utcnow() + datetime.timedelta(seconds=60) for message_stat in (oldest, newest): created_iso = message_stat['created'] created = timeutils.parse_isotime(created_iso) self.assertThat(timeutils.normalize_time(created), matchers.LessThan(soon)) self.assertIn('id', message_stat) self.assertThat(oldest['created'], matchers.LessThan(newest['created'])) # Test queue deletion self.controller.delete('test', project=self.project) # Test queue existence self.assertFalse(self.controller.exists('test', project=self.project)) # Test DoesNotExist exception with testing.expect(storage.errors.DoesNotExist): self.controller.get_metadata('test', project=self.project) with testing.expect(storage.errors.DoesNotExist): self.controller.set_metadata('test', '{}', project=self.project)
def test_race_condition_on_post(self): queue_name = self.queue_name expected_messages = [ { 'ttl': 60, 'body': { 'event': 'BackupStarted', 'backupId': 'c378813c-3f0b-11e2-ad92-7823d2b0f3ce', }, }, { 'ttl': 60, 'body': { 'event': 'BackupStarted', 'backupId': 'd378813c-3f0b-11e2-ad92-7823d2b0f3ce', }, }, { 'ttl': 60, 'body': { 'event': 'BackupStarted', 'backupId': 'e378813c-3f0b-11e2-ad92-7823d2b0f3ce', }, }, ] uuid = '97b64000-2526-11e3-b088-d85c1300734c' # NOTE(kgriffs): Patch _inc_counter so it is a noop, so that # the second time we post, we will get a collision. This simulates # what happens when we have parallel requests and the "winning" # requests hasn't gotten around to calling _inc_counter before the # "losing" request attempts to insert it's batch of messages. with mock.patch.object(mongodb.queues.QueueController, '_inc_counter', autospec=True) as method: method.return_value = 2 messages = expected_messages[:1] created = list( self.controller.post(queue_name, messages, uuid, project=self.project)) self.assertEqual(len(created), 1) # Force infinite retries if testing.RUN_SLOW_TESTS: method.return_value = None with testing.expect(errors.MessageConflict): self.controller.post(queue_name, messages, uuid, project=self.project) created = list( self.controller.post(queue_name, expected_messages[1:], uuid, project=self.project)) self.assertEqual(len(created), 2) expected_ids = [m['body']['backupId'] for m in expected_messages] interaction = self.controller.list(queue_name, client_uuid=uuid, echo=True, project=self.project) actual_messages = list(next(interaction)) self.assertEqual(len(actual_messages), len(expected_messages)) actual_ids = [m['body']['backupId'] for m in actual_messages] self.assertEqual(actual_ids, expected_ids)
def test_queue_lifecycle(self): # Test queue creation created = self.controller.create('test', project=self.project) self.assertTrue(created) # Test queue existence self.assertTrue(self.controller.exists('test', project=self.project)) # Test queue retrieval interaction = self.controller.list(project=self.project) queue = list(next(interaction))[0] self.assertEqual(queue['name'], 'test') # Test queue metadata retrieval metadata = self.controller.get_metadata('test', project=self.project) self.assertEqual(metadata, {}) # Test queue update created = self.controller.set_metadata('test', project=self.project, metadata=dict(meta='test_meta')) metadata = self.controller.get_metadata('test', project=self.project) self.assertEqual(metadata['meta'], 'test_meta') # Touching an existing queue does not affect metadata created = self.controller.create('test', project=self.project) self.assertFalse(created) metadata = self.controller.get_metadata('test', project=self.project) self.assertEqual(metadata['meta'], 'test_meta') client_uuid = uuid.uuid4() # Test queue statistic _insert_fixtures(self.message_controller, 'test', project=self.project, client_uuid=client_uuid, num=6) # NOTE(kgriffs): We can't get around doing this, because # we don't know how the storage drive may be calculating # message timestamps (and may not be monkey-patchable). time.sleep(1.2) _insert_fixtures(self.message_controller, 'test', project=self.project, client_uuid=client_uuid, num=6) stats = self.controller.stats('test', project=self.project) message_stats = stats['messages'] self.assertEqual(message_stats['free'], 12) self.assertEqual(message_stats['claimed'], 0) self.assertEqual(message_stats['total'], 12) oldest = message_stats['oldest'] newest = message_stats['newest'] self.assertNotEqual(oldest, newest) age = oldest['age'] self.assertThat(age, matchers.GreaterThan(0)) # NOTE(kgriffs): Ensure is different enough # for the next comparison to work. soon = timeutils.utcnow() + datetime.timedelta(seconds=60) for message_stat in (oldest, newest): created_iso = message_stat['created'] created = timeutils.parse_isotime(created_iso) self.assertThat(timeutils.normalize_time(created), matchers.LessThan(soon)) self.assertIn('id', message_stat) self.assertThat(oldest['created'], matchers.LessThan(newest['created'])) # Test queue deletion self.controller.delete('test', project=self.project) # Test queue existence self.assertFalse(self.controller.exists('test', project=self.project)) # Test DoesNotExist exception with testing.expect(storage.exceptions.DoesNotExist): self.controller.get_metadata('test', project=self.project) with testing.expect(storage.exceptions.DoesNotExist): self.controller.set_metadata('test', '{}', project=self.project)
def test_claim_effects(self): _insert_fixtures(self.controller, self.queue_name, project=self.project, client_uuid='my_uuid', num=12) def list_messages(include_claimed=None): kwargs = { 'project': self.project, 'client_uuid': 'my_uuid', 'echo': True, } # Properly test default value if include_claimed is not None: kwargs['include_claimed'] = include_claimed interaction = self.controller.list(self.queue_name, **kwargs) messages = next(interaction) return [msg['id'] for msg in messages] messages_before = list_messages(True) meta = {'ttl': 70, 'grace': 60} another_cid, _ = self.claim_controller.create(self.queue_name, meta, project=self.project) messages_after = list_messages(True) self.assertEqual(messages_before, messages_after) messages_excluding_claimed = list_messages() self.assertNotEqual(messages_before, messages_excluding_claimed) self.assertEqual(2, len(messages_excluding_claimed)) cid, msgs = self.claim_controller.create(self.queue_name, meta, project=self.project) [msg1, msg2] = msgs # A wrong claim does not ensure the message deletion with testing.expect(storage.exceptions.NotPermitted): self.controller.delete(self.queue_name, msg1['id'], project=self.project, claim=another_cid) # Make sure a message can be deleted with a claim self.controller.delete(self.queue_name, msg1['id'], project=self.project, claim=cid) with testing.expect(storage.exceptions.DoesNotExist): self.controller.get(self.queue_name, msg1['id'], project=self.project) # Make sure such a deletion is idempotent self.controller.delete(self.queue_name, msg1['id'], project=self.project, claim=cid) # A non-existing claim does not ensure the message deletion self.claim_controller.delete(self.queue_name, cid, project=self.project) with testing.expect(storage.exceptions.NotPermitted): self.controller.delete(self.queue_name, msg2['id'], project=self.project, claim=cid)
def test_wrong_type(self): ns = config.namespace('local') with testing.expect(config.cfg.Error): ns.from_options(opt={})
def test_race_condition_on_post(self): queue_name = 'marker_test' self.queue_controller.create(queue_name) expected_messages = [ { 'ttl': 60, 'body': { 'event': 'BackupStarted', 'backupId': 'c378813c-3f0b-11e2-ad92-7823d2b0f3ce', }, }, { 'ttl': 60, 'body': { 'event': 'BackupStarted', 'backupId': 'd378813c-3f0b-11e2-ad92-7823d2b0f3ce', }, }, { 'ttl': 60, 'body': { 'event': 'BackupStarted', 'backupId': 'e378813c-3f0b-11e2-ad92-7823d2b0f3ce', }, }, ] uuid = '97b64000-2526-11e3-b088-d85c1300734c' # NOTE(kgriffs): Patch _inc_counter so it is a noop, so that # the second time we post, we will get a collision. This simulates # what happens when we have parallel requests and the "winning" # requests hasn't gotten around to calling _inc_counter before the # "losing" request attempts to insert it's batch of messages. with mock.patch.object(mongodb.queues.QueueController, '_inc_counter', autospec=True) as method: method.return_value = 2 messages = expected_messages[:1] created = list(self.controller.post(queue_name, messages, uuid)) self.assertEqual(len(created), 1) # Force infinite retries if testing.RUN_SLOW_TESTS: method.return_value = None with testing.expect(errors.MessageConflict): self.controller.post(queue_name, messages, uuid) created = list(self.controller.post(queue_name, expected_messages[1:], uuid)) self.assertEqual(len(created), 2) expected_ids = [m['body']['backupId'] for m in expected_messages] interaction = self.controller.list(queue_name, client_uuid=uuid, echo=True) actual_messages = list(next(interaction)) self.assertEqual(len(actual_messages), len(expected_messages)) actual_ids = [m['body']['backupId'] for m in actual_messages] self.assertEqual(actual_ids, expected_ids)