def test(self): sequence_id = 'sequence1' position = 0 topic = 'topic1' data = '{}' item = SequencedItem(sequence_id=sequence_id, position=position, topic=topic, data=data) self.assertEqual(item.sequence_id, sequence_id) self.assertEqual(item.position, position) self.assertEqual(item.topic, topic) self.assertEqual(item.data, data) with self.assertRaises(AttributeError): item.sequence_id = 'sequence2'
def test(self): sequence_id = "sequence1" position = 0 topic = "topic1" state = "{}" item = SequencedItem(sequence_id=sequence_id, position=position, topic=topic, state=state) self.assertEqual(item.sequence_id, sequence_id) self.assertEqual(item.position, position) self.assertEqual(item.topic, topic) self.assertEqual(item.state, state) with self.assertRaises(AttributeError): item.sequence_id = "sequence2"
def test_with_versioned_entity_event(self): # Setup the mapper, and create an event. mapper = SequencedItemMapper(sequenced_item_class=SequencedItem, sequence_id_attr_name='originator_id', position_attr_name='originator_version') entity_id1 = uuid4() event1 = Event1(originator_id=entity_id1, originator_version=101) # Check to_sequenced_item() method results in a sequenced item. sequenced_item = mapper.to_sequenced_item(event1) self.assertIsInstance(sequenced_item, SequencedItem) self.assertEqual(sequenced_item.position, 101) self.assertEqual(sequenced_item.sequence_id, entity_id1) self.assertEqual(sequenced_item.topic, topic_from_domain_class(Event1)) self.assertTrue(sequenced_item.data) # Use the returned values to create a new sequenced item. sequenced_item_copy = SequencedItem( sequence_id=sequenced_item.sequence_id, position=sequenced_item.position, topic=sequenced_item.topic, data=sequenced_item.data, ) # Check from_sequenced_item() returns an event. domain_event = mapper.from_sequenced_item(sequenced_item_copy) self.assertIsInstance(domain_event, Event1) self.assertEqual(domain_event.originator_id, event1.originator_id) self.assertEqual(domain_event.originator_version, event1.originator_version)
def test_with_timestamped_entity_event(self): # Setup the mapper, and create an event. mapper = SequencedItemMapper( sequenced_item_class=SequencedItem, sequence_id_attr_name="originator_id", position_attr_name="timestamp", ) before = decimaltimestamp() sleep(0.000001) # Avoid test failing due to timestamp having limited precision. event2 = Event2(originator_id="entity2") sleep(0.000001) # Avoid test failing due to timestamp having limited precision. after = decimaltimestamp() # Check to_sequenced_item() method results in a sequenced item. sequenced_item = mapper.item_from_event(event2) self.assertIsInstance(sequenced_item, SequencedItem) self.assertGreater(sequenced_item.position, before) self.assertLess(sequenced_item.position, after) self.assertEqual(sequenced_item.sequence_id, "entity2") self.assertEqual(sequenced_item.topic, get_topic(Event2)) self.assertTrue(sequenced_item.state) # Use the returned values to create a new sequenced item. sequenced_item_copy = SequencedItem( sequence_id=sequenced_item.sequence_id, position=sequenced_item.position, topic=sequenced_item.topic, state=sequenced_item.state, ) # Check from_sequenced_item() returns an event. domain_event = mapper.event_from_item(sequenced_item_copy) self.assertIsInstance(domain_event, Event2) self.assertEqual(domain_event.originator_id, event2.originator_id) self.assertEqual(domain_event.timestamp, event2.timestamp)
def test(self): sequence_id = 'sequence1' position = 0 topic = 'topic1' data = '{}' item = SequencedItem( sequence_id=sequence_id, position=position, topic=topic, data=data ) self.assertEqual(item.sequence_id, sequence_id) self.assertEqual(item.position, position) self.assertEqual(item.topic, topic) self.assertEqual(item.data, data) with self.assertRaises(AttributeError): item.sequence_id = 'sequence2'
def setup_sequenced_items(self): self.sequenced_items = [] self.number_of_sequenced_items = 12 for i in six.moves.range(self.number_of_sequenced_items): sequenced_item = SequencedItem( sequence_id=self.entity_id, position=i, topic='eventsourcing.example.domain_model#Example.Created', data='{"i":%s,"entity_id":"%s","timestamp":%s}' % (i, self.entity_id, time())) self.sequenced_items.append(sequenced_item) self.entity_active_record_strategy.append(sequenced_item)
def setup_sequenced_items(self): self.sequenced_items = [] self.number_of_sequenced_items = 12 for i in range(self.number_of_sequenced_items): sequenced_item = SequencedItem( sequence_id=self.entity_id, position=i, topic='eventsourcing.example.domain_model#Example.Created', state='{"i":%s,"entity_id":"%s","timestamp":%s}' % (i, self.entity_id, decimaltimestamp()), ) self.sequenced_items.append(sequenced_item) self.entity_record_manager.record_sequenced_items(sequenced_item)
def test_with_different_types_of_event_attributes(self): # Setup the mapper, and create an event. mapper = SequencedItemMapper( sequenced_item_class=SequencedItem, sequence_id_attr_name="originator_id", position_attr_name="a", ) # Check value objects can be compared ok. self.assertEqual(ValueObject1("value1"), ValueObject1("value1")) self.assertNotEqual(ValueObject1("value1"), ValueObject1("value2")) # Create an event with dates and datetimes. event3 = Event3( originator_id="entity3", originator_version=303, a=datetime.datetime(2017, 3, 22, 9, 12, 14), b=datetime.date(2017, 3, 22), c=uuid4(), # d=Decimal(1.1), e=ValueObject1("value1"), ) # Check to_sequenced_item() method results in a sequenced item. sequenced_item = mapper.item_from_event(event3) # Use the returned values to create a new sequenced item. sequenced_item_copy = SequencedItem( sequence_id=sequenced_item.sequence_id, position=sequenced_item.position, topic=sequenced_item.topic, state=sequenced_item.state, ) # Check from_sequenced_item() returns an event. domain_event = mapper.event_from_item(sequenced_item_copy) self.assertIsInstance(domain_event, Event3) self.assertEqual(domain_event.originator_id, event3.originator_id) self.assertEqual(domain_event.a, event3.a) self.assertEqual(domain_event.b, event3.b) self.assertEqual(domain_event.c, event3.c) # self.assertEqual(domain_event.d, event3.d) self.assertEqual(domain_event.e, event3.e)
def test_with_timestamped_entity_event(self): # Setup the mapper, and create an event. mapper = SequencedItemMapper(sequenced_item_class=SequencedItem, sequence_id_attr_name='originator_id', position_attr_name='timestamp') before = time() sleep( 0.000001 ) # Avoid test failing due to timestamp having limited precision. event2 = Event2(originator_id='entity2') sleep( 0.000001 ) # Avoid test failing due to timestamp having limited precision. after = time() # Check to_sequenced_item() method results in a sequenced item. sequenced_item = mapper.to_sequenced_item(event2) self.assertIsInstance(sequenced_item, SequencedItem) self.assertGreater(sequenced_item.position, before) self.assertLess(sequenced_item.position, after) self.assertEqual(sequenced_item.sequence_id, 'entity2') self.assertEqual(sequenced_item.topic, topic_from_domain_class(Event2)) self.assertTrue(sequenced_item.data) # Use the returned values to create a new sequenced item. sequenced_item_copy = SequencedItem( sequence_id=sequenced_item.sequence_id, position=sequenced_item.position, topic=sequenced_item.topic, data=sequenced_item.data, ) # Check from_sequenced_item() returns an event. domain_event = mapper.from_sequenced_item(sequenced_item_copy) self.assertIsInstance(domain_event, Event2) self.assertEqual(domain_event.originator_id, event2.originator_id) self.assertEqual(domain_event.timestamp, event2.timestamp)
def test_with_different_types_of_event_attributes(self): # Setup the mapper, and create an event. mapper = SequencedItemMapper(sequenced_item_class=SequencedItem, sequence_id_attr_name='originator_id', position_attr_name='a') # Create an event with dates and datetimes. event3 = Event3( originator_id='entity3', originator_version=303, a=datetime.datetime(2017, 3, 22, 9, 12, 14), b=datetime.date(2017, 3, 22), c=uuid4(), # d=Decimal(1.1), e=ValueObject1('value1'), ) # Check to_sequenced_item() method results in a sequenced item. sequenced_item = mapper.to_sequenced_item(event3) # Use the returned values to create a new sequenced item. sequenced_item_copy = SequencedItem( sequence_id=sequenced_item.sequence_id, position=sequenced_item.position, topic=sequenced_item.topic, data=sequenced_item.data, ) # Check from_sequenced_item() returns an event. domain_event = mapper.from_sequenced_item(sequenced_item_copy) self.assertIsInstance(domain_event, Event3) self.assertEqual(domain_event.originator_id, event3.originator_id) self.assertEqual(domain_event.a, event3.a) self.assertEqual(domain_event.b, event3.b) self.assertEqual(domain_event.c, event3.c) # self.assertEqual(domain_event.d, event3.d) self.assertEqual(domain_event.e, event3.e)
def test(self): sequence_id1 = uuid.uuid1() sequence_id2 = uuid.uuid1() # Check record manager returns empty list when there aren't any items. self.assertEqual(self.record_manager.list_items(sequence_id1), []) # Check record manager returns no sequence IDs. self.assertEqual([], self.record_manager.list_sequence_ids()) position1, position2, position3 = self.construct_positions() self.assertLess(position1, position2) self.assertLess(position2, position3) # Append an item. state1 = json.dumps({'name': 'value1'}) item1 = SequencedItem( sequence_id=sequence_id1, position=position1, topic=self.EXAMPLE_EVENT_TOPIC1, state=state1, ) self.record_manager.record_sequenced_items(item1) # Check record manager returns one sequence ID. self.assertEqual([sequence_id1], self.record_manager.list_sequence_ids()) # Append an item to a different sequence. state2 = json.dumps({'name': 'value2'}) item2 = SequencedItem( sequence_id=sequence_id2, position=position1, topic=self.EXAMPLE_EVENT_TOPIC1, state=state2, ) self.record_manager.record_sequenced_items(item2) # Check record manager returns two sequence IDs. self.assertEqual(sorted([sequence_id1, sequence_id2]), sorted(self.record_manager.list_sequence_ids())) # Get first event. retrieved_item = self.record_manager.get_item(sequence_id1, position1) self.assertEqual(sequence_id1, retrieved_item.sequence_id) self.assertEqual(state1, retrieved_item.state) # Check index error is raised when item does not exist at position. with self.assertRaises(IndexError): self.record_manager.get_item(sequence_id1, position2) # Check record manager returns the item. retrieved_items = self.record_manager.list_items(sequence_id1) self.assertEqual(1, len(retrieved_items), str(retrieved_items)) self.assertIsInstance(retrieved_items[0], SequencedItem) self.assertEqual(retrieved_items[0].sequence_id, item1.sequence_id) self.assertEqual(retrieved_items[0].state, item1.state) self.assertEqual(retrieved_items[0].topic, item1.topic) # Check raises RecordConflictError when appending an item at same position in same sequence. state3 = json.dumps({'name': 'value3'}) item3 = SequencedItem( sequence_id=item1.sequence_id, position=position1, topic=self.EXAMPLE_EVENT_TOPIC2, state=state3, ) self.assertEqual(item1.sequence_id, item3.sequence_id) self.assertNotEqual(item1.topic, item3.topic) self.assertNotEqual(item1.state, item3.state) # - append conflicting item as single item with self.assertRaises(RecordConflictError): self.record_manager.record_sequenced_items(item3) item4 = SequencedItem( sequence_id=item1.sequence_id, position=position2, topic=self.EXAMPLE_EVENT_TOPIC2, state=state3, ) item5 = SequencedItem( sequence_id=item1.sequence_id, position=position3, topic=self.EXAMPLE_EVENT_TOPIC2, state=state3, ) # - append conflicting item in list with new items (none should be appended) with self.assertRaises(RecordConflictError): self.record_manager.record_sequenced_items([item3, item4, item5]) # Check there is still only one item. retrieved_items = self.record_manager.list_items(sequence_id1) self.assertEqual(len(retrieved_items), 1) # Check adding an empty list does nothing. self.record_manager.record_sequenced_items([]) retrieved_items = self.record_manager.list_items(sequence_id1) self.assertEqual(len(retrieved_items), 1) # Append a second and third item at the next positions. self.record_manager.record_sequenced_items([item4, item5]) # Check there are three items. retrieved_items = self.record_manager.list_items(sequence_id1) self.assertEqual(len(retrieved_items), 3) # Check the items are in sequential order. self.assertIsInstance(retrieved_items[0], SequencedItem) self.assertEqual(retrieved_items[0].sequence_id, item1.sequence_id) self.assertEqual(retrieved_items[0].topic, item1.topic) self.assertEqual(retrieved_items[0].state, item1.state) self.assertIsInstance(retrieved_items[1], SequencedItem) self.assertEqual(retrieved_items[1].sequence_id, item3.sequence_id) self.assertEqual(retrieved_items[1].topic, item4.topic) self.assertEqual(retrieved_items[1].state, item4.state) self.assertIsInstance(retrieved_items[2], SequencedItem) self.assertEqual(retrieved_items[2].sequence_id, item5.sequence_id) self.assertEqual(retrieved_items[2].topic, item5.topic) self.assertEqual(retrieved_items[2].state, item5.state) # Get items greater than a position. retrieved_items = self.record_manager.list_items(sequence_id1, gt=position1) self.assertEqual(len(retrieved_items), 2) self.assertEqual(retrieved_items[0].state, item4.state) self.assertEqual(retrieved_items[1].state, item5.state) # Get items greater then or equal to a position. retrieved_items = self.record_manager.list_items(sequence_id1, gte=position2) self.assertEqual(len(retrieved_items), 2) self.assertEqual(retrieved_items[0].state, item4.state) self.assertEqual(retrieved_items[1].state, item5.state) # Get items less than a position. retrieved_items = self.record_manager.list_items(sequence_id1, lt=position3) self.assertEqual(len(retrieved_items), 2) self.assertEqual(retrieved_items[0].state, item1.state) self.assertEqual(retrieved_items[1].state, item4.state) # Get items less then or equal to a position. retrieved_items = self.record_manager.list_items(sequence_id1, lte=position2) self.assertEqual(len(retrieved_items), 2) self.assertEqual(retrieved_items[0].state, item1.state) self.assertEqual(retrieved_items[1].state, item4.state) # Get items greater then or equal to a position and less then or equal to a position. retrieved_items = self.record_manager.list_items(sequence_id1, gte=position2, lte=position2) self.assertEqual(len(retrieved_items), 1) self.assertEqual(retrieved_items[0].state, item4.state) # Get items greater then or equal to a position and less then a position. retrieved_items = self.record_manager.list_items(sequence_id1, gte=position2, lt=position3) self.assertEqual(len(retrieved_items), 1) self.assertEqual(retrieved_items[0].state, item4.state) # Get items greater then a position and less then or equal to a position. retrieved_items = self.record_manager.list_items(sequence_id1, gt=position1, lte=position2) self.assertEqual(len(retrieved_items), 1) self.assertEqual(retrieved_items[0].state, item4.state) # Get items greater a position and less a position. retrieved_items = self.record_manager.list_items(sequence_id1, gt=position1, lt=position3) self.assertEqual(len(retrieved_items), 1) self.assertEqual(retrieved_items[0].state, item4.state) # Get items with a limit. retrieved_items = self.record_manager.list_items(sequence_id1, limit=1) self.assertEqual(len(retrieved_items), 1) self.assertEqual(retrieved_items[0].state, item1.state) # Get items with a limit, and with descending query (so that we get the last ones). retrieved_items = self.record_manager.list_items(sequence_id1, limit=2, query_ascending=False) self.assertEqual(2, len(retrieved_items)) self.assertEqual(retrieved_items[0].state, item4.state) self.assertEqual(retrieved_items[1].state, item5.state) # Get items with a limit and descending query, greater than a position. retrieved_items = self.record_manager.list_items(sequence_id1, limit=2, gt=position2, query_ascending=False) self.assertEqual(1, len(retrieved_items)) self.assertEqual(retrieved_items[0].state, item5.state) # Get items with a limit and descending query, less than a position. retrieved_items = self.record_manager.list_items(sequence_id1, limit=2, lt=position3, query_ascending=False) self.assertEqual(len(retrieved_items), 2) self.assertEqual(retrieved_items[0].state, item1.state) self.assertEqual(retrieved_items[1].state, item4.state) # Get items in descending order, queried in ascending order. retrieved_items = self.record_manager.list_items( sequence_id1, results_ascending=False) self.assertEqual(len(retrieved_items), 3) self.assertEqual(retrieved_items[0].state, item5.state) self.assertEqual(retrieved_items[2].state, item1.state) # Get items in descending order, queried in descending order. retrieved_items = self.record_manager.list_items( sequence_id1, query_ascending=False, results_ascending=False) self.assertEqual(len(retrieved_items), 3) self.assertEqual(retrieved_items[0].state, item5.state) self.assertEqual(retrieved_items[2].state, item1.state) # Check we can get all the sequence IDs. sequence_ids = self.record_manager.list_sequence_ids() self.assertEqual(set(sequence_ids), {sequence_id1, sequence_id2}) # Iterate over all items in all sequences. retrieved_items = [] for sequence_id in sequence_ids: retrieved_items += self.record_manager.list_items(sequence_id) # Not always in order, but check the number of events. self.assertEqual(4, len(retrieved_items)) if self.record_manager.contiguous_record_ids: # Check the record IDs are contiguous. records = self.record_manager.get_notifications() records = list(records) self.assertEqual(len(records), 4) first = None for i, record in enumerate(records): if first is None: first = record.id self.assertEqual( first + i, record.id, "Woops there's a gap: {}".format([r.id for r in records])) # Resume from after the first event. retrieved_items = self.record_manager.get_notifications(start=1, stop=3) retrieved_items = list(retrieved_items) self.assertEqual(len(retrieved_items), 2) self.assertEqual(retrieved_items[0].id, 2) self.assertEqual(retrieved_items[1].id, 3) # Delete some items. records = list(self.record_manager.get_records(sequence_id1)) self.assertTrue(len(records)) for record in records: self.record_manager.delete_record(record) records = list(self.record_manager.get_records(sequence_id1)) self.assertFalse(len(records)) with self.assertRaises(RecordConflictError): self.record_manager.raise_sequenced_item_conflict() with self.assertRaises(IndexError): self.record_manager.raise_index_error(0) with self.assertRaises(RecordConflictError): self.record_manager.raise_record_integrity_error(Exception()) with self.assertRaises(OperationalError): self.record_manager.raise_operational_error(Exception())
def test(self): sequence_id1 = uuid.uuid1() position1, position2, position3 = self.construct_positions() upstream_name = "upstream_app" self.assertEqual( self.record_manager.get_max_tracking_record_id(upstream_name), 0) self.assertFalse( self.record_manager.has_tracking_record(upstream_name, 0, 1)) # Can write events with tracking kwargs. state1 = json.dumps({"name": "value1"}).encode("utf-8") self.assertTrue(self.EXAMPLE_EVENT_TOPIC1) item1 = SequencedItem( sequence_id=sequence_id1, position=position1, topic=self.EXAMPLE_EVENT_TOPIC1, state=state1, ) tracking_kwargs1 = { "application_name": self.record_manager.application_name, "upstream_application_name": upstream_name, "pipeline_id": self.record_manager.pipeline_id, "notification_id": 1, } records1 = self.record_manager.to_records([item1]) self.record_manager.write_records(tracking_kwargs=tracking_kwargs1, records=records1) self.assertEqual( self.record_manager.get_max_tracking_record_id(upstream_name), 1) self.assertTrue( self.record_manager.has_tracking_record(upstream_name, 0, 1)) self.assertFalse( self.record_manager.has_tracking_record(upstream_name, 0, 2)) # Can't write further events with same tracking kwargs. item2 = SequencedItem( sequence_id=sequence_id1, position=position2, topic=self.EXAMPLE_EVENT_TOPIC1, state=state1, ) records2 = self.record_manager.to_records([item2]) with self.assertRaises(RecordConflictError): self.record_manager.write_records(tracking_kwargs=tracking_kwargs1, records=records2) self.assertTrue( self.record_manager.has_tracking_record(upstream_name, 0, 1)) self.assertFalse( self.record_manager.has_tracking_record(upstream_name, 0, 2)) # Can write further events with different tracking kwargs. tracking_kwargs2 = { "application_name": self.record_manager.application_name, "upstream_application_name": upstream_name, "pipeline_id": self.record_manager.pipeline_id, "notification_id": 2, } self.record_manager.write_records(tracking_kwargs=tracking_kwargs2, records=records2) self.assertTrue( self.record_manager.has_tracking_record(upstream_name, 0, 1)) self.assertTrue( self.record_manager.has_tracking_record(upstream_name, 0, 2))
def test(self): sequence_id1 = uuid.uuid1() sequence_id2 = uuid.uuid1() old_notifications = list( self.record_manager.get_notification_records()) max_notification_id = self.record_manager.get_max_notification_id() position1, position2, position3 = self.construct_positions() self.assertLess(position1, position2) self.assertLess(position2, position3) # Append an item. state1 = json.dumps({"name": "value1"}).encode("utf-8") self.assertTrue(self.EXAMPLE_EVENT_TOPIC1) item1 = SequencedItem( sequence_id=sequence_id1, position=position1, topic=self.EXAMPLE_EVENT_TOPIC1, state=state1, ) self.record_manager.record_item(item1) self.assertEqual(max_notification_id + 1, self.record_manager.get_max_notification_id()) # Append an item to a different sequence. state2 = json.dumps({"name": "value2"}).encode("utf-8") item2 = SequencedItem( sequence_id=sequence_id2, position=position1, topic=self.EXAMPLE_EVENT_TOPIC1, state=state2, ) self.record_manager.record_item(item2) self.assertEqual(max_notification_id + 2, self.record_manager.get_max_notification_id()) self.assertTrue(self.EXAMPLE_EVENT_TOPIC2) state3 = json.dumps({"name": "value3"}).encode("utf-8") item4 = SequencedItem( sequence_id=item1.sequence_id, position=position2, topic=self.EXAMPLE_EVENT_TOPIC2, state=state3, ) item5 = SequencedItem( sequence_id=item1.sequence_id, position=position3, topic=self.EXAMPLE_EVENT_TOPIC2, state=state3, ) # Append a second and third item at the next positions. self.record_manager.record_items([item4, item5]) self.assertEqual(max_notification_id + 4, self.record_manager.get_max_notification_id()) # Check the record IDs are contiguous. records = list(self.record_manager.get_notification_records()) len_old = len(old_notifications) self.assertEqual(len(records), 4 + len_old) first = None for i, record in enumerate(records): if first is None: first = record.id self.assertEqual( first + i, record.id, "Woops there's a gap: {}".format([r.id for r in records]), ) # Resume from after the first event. retrieved_items = self.record_manager.get_notification_records( start=1 + len_old, stop=3 + len_old) retrieved_items = list(retrieved_items) self.assertEqual(len(retrieved_items), 2) self.assertEqual(retrieved_items[0].id, 2 + len_old) self.assertEqual(retrieved_items[1].id, 3 + len_old)
def test(self): sequence_id1 = uuid.uuid1() sequence_id2 = uuid.uuid1() # Check repo returns empty list when there aren't any items. self.assertEqual(self.record_manager.list_items(sequence_id1), []) position1, position2, position3 = self.construct_positions() self.assertLess(position1, position2) self.assertLess(position2, position3) # Append an item. data1 = json.dumps({'name': 'value1'}) item1 = SequencedItem( sequence_id=sequence_id1, position=position1, topic=self.EXAMPLE_EVENT_TOPIC1, data=data1, ) self.record_manager.append(item1) # Append an item to a different sequence. data2 = json.dumps({'name': 'value2'}) item2 = SequencedItem( sequence_id=sequence_id2, position=position1, topic=self.EXAMPLE_EVENT_TOPIC1, data=data2, ) self.record_manager.append(item2) retrieved_item = self.record_manager.get_item(sequence_id1, position1) self.assertEqual(sequence_id1, retrieved_item.sequence_id) self.assertEqual(position1, retrieved_item.position) self.assertEqual(data1, retrieved_item.data) # Check index error is raised when item does not exist at position. with self.assertRaises(IndexError): self.record_manager.get_item(sequence_id1, position2) # Check repo returns the item. retrieved_items = self.record_manager.list_items(sequence_id1) self.assertEqual(1, len(retrieved_items), str(retrieved_items)) self.assertIsInstance(retrieved_items[0], SequencedItem) self.assertEqual(retrieved_items[0].sequence_id, item1.sequence_id) self.assertEqual(position1, retrieved_items[0].position) self.assertEqual(retrieved_items[0].data, item1.data) self.assertEqual(retrieved_items[0].topic, item1.topic) # Check raises SequencedItemConflict when appending an item at same position in same sequence. data3 = json.dumps({'name': 'value3'}) item3 = SequencedItem( sequence_id=item1.sequence_id, position=position1, topic=self.EXAMPLE_EVENT_TOPIC2, data=data3, ) self.assertEqual(item1.sequence_id, item3.sequence_id) self.assertEqual(position1, item3.position) self.assertNotEqual(item1.topic, item3.topic) self.assertNotEqual(item1.data, item3.data) # - check appending item as single item with self.assertRaises(SequencedItemConflict): self.record_manager.append(item3) item4 = SequencedItem( sequence_id=item1.sequence_id, position=position2, topic=self.EXAMPLE_EVENT_TOPIC2, data=data3, ) item5 = SequencedItem( sequence_id=item1.sequence_id, position=position3, topic=self.EXAMPLE_EVENT_TOPIC2, data=data3, ) # - check appending item as a list of items (none should be appended) with self.assertRaises(SequencedItemConflict): self.record_manager.append([item3, item4, item5]) # Check there is still only one item. retrieved_items = self.record_manager.list_items(sequence_id1) self.assertEqual(len(retrieved_items), 1) # Check adding an empty list does nothing. self.record_manager.append([]) retrieved_items = self.record_manager.list_items(sequence_id1) self.assertEqual(len(retrieved_items), 1) # Append a second and third item at the next positions. self.record_manager.append([item4, item5]) # Check there are three items. retrieved_items = self.record_manager.list_items(sequence_id1) self.assertEqual(len(retrieved_items), 3) # Check the items are in sequential order. self.assertIsInstance(retrieved_items[0], SequencedItem) self.assertEqual(retrieved_items[0].sequence_id, item1.sequence_id) self.assertEqual(retrieved_items[0].position, position1) self.assertEqual(retrieved_items[0].topic, item1.topic) self.assertEqual(retrieved_items[0].data, item1.data) self.assertIsInstance(retrieved_items[1], SequencedItem) self.assertEqual(retrieved_items[1].sequence_id, item3.sequence_id) self.assertEqual(retrieved_items[1].topic, item3.topic) self.assertEqual(retrieved_items[1].data, item3.data) self.assertEqual(retrieved_items[1].position, position2) self.assertIsInstance(retrieved_items[2], SequencedItem) self.assertEqual(retrieved_items[2].sequence_id, item5.sequence_id) self.assertEqual(retrieved_items[2].position, position3) self.assertEqual(retrieved_items[2].topic, item5.topic) self.assertEqual(retrieved_items[2].data, item5.data) # Get items greater than a position. retrieved_items = self.record_manager.list_items(sequence_id1, gt=position1) self.assertEqual(len(retrieved_items), 2) self.assertEqual(retrieved_items[0].position, position2) self.assertEqual(retrieved_items[1].position, position3) # Get items greater then or equal to a position. retrieved_items = self.record_manager.list_items(sequence_id1, gte=position2) self.assertEqual(len(retrieved_items), 2) self.assertEqual(retrieved_items[0].position, position2) self.assertEqual(retrieved_items[1].position, position3) # Get items less than a position. retrieved_items = self.record_manager.list_items(sequence_id1, lt=position3) self.assertEqual(len(retrieved_items), 2) self.assertEqual(retrieved_items[0].position, position1) self.assertEqual(retrieved_items[1].position, position2) # Get items less then or equal to a position. retrieved_items = self.record_manager.list_items(sequence_id1, lte=position2) self.assertEqual(len(retrieved_items), 2) self.assertEqual(retrieved_items[0].position, position1) self.assertEqual(retrieved_items[1].position, position2) # Get items greater then or equal to a position and less then or equal to a position. retrieved_items = self.record_manager.list_items(sequence_id1, gte=position2, lte=position2) self.assertEqual(len(retrieved_items), 1) self.assertEqual(retrieved_items[0].position, position2) # Get items greater then or equal to a position and less then a position. retrieved_items = self.record_manager.list_items(sequence_id1, gte=position2, lt=position3) self.assertEqual(len(retrieved_items), 1) self.assertEqual(retrieved_items[0].position, position2) # Get items greater then a position and less then or equal to a position. retrieved_items = self.record_manager.list_items(sequence_id1, gt=position1, lte=position2) self.assertEqual(len(retrieved_items), 1) self.assertEqual(retrieved_items[0].position, position2) # Get items greater a position and less a position. retrieved_items = self.record_manager.list_items(sequence_id1, gt=position1, lt=position3) self.assertEqual(len(retrieved_items), 1) self.assertEqual(retrieved_items[0].position, position2) # Get items with a limit. retrieved_items = self.record_manager.list_items(sequence_id1, limit=1) self.assertEqual(len(retrieved_items), 1) self.assertEqual(retrieved_items[0].position, position1) # Get items with a limit, and with descending query (so that we get the last ones). retrieved_items = self.record_manager.list_items(sequence_id1, limit=2, query_ascending=False) self.assertEqual(2, len(retrieved_items)) self.assertEqual(retrieved_items[0].position, position2) self.assertEqual(retrieved_items[1].position, position3) # Get items with a limit and descending query, greater than a position. retrieved_items = self.record_manager.list_items(sequence_id1, limit=2, gt=position2, query_ascending=False) self.assertEqual(1, len(retrieved_items)) self.assertEqual(retrieved_items[0].position, position3) # Get items with a limit and descending query, less than a position. retrieved_items = self.record_manager.list_items(sequence_id1, limit=2, lt=position3, query_ascending=False) self.assertEqual(len(retrieved_items), 2) self.assertEqual(retrieved_items[0].position, position1) self.assertEqual(retrieved_items[1].position, position2) # Get items in descending order, queried in ascending order. retrieved_items = self.record_manager.list_items(sequence_id1, results_ascending=False) self.assertEqual(len(retrieved_items), 3) self.assertEqual(retrieved_items[0].position, position3) self.assertEqual(retrieved_items[2].position, position1) # Get items in descending order, queried in descending order. retrieved_items = self.record_manager.list_items(sequence_id1, query_ascending=False, results_ascending=False) self.assertEqual(len(retrieved_items), 3) self.assertEqual(retrieved_items[0].position, position3) self.assertEqual(retrieved_items[2].position, position1) # Iterate over all items in all sequences. retrieved_items = self.record_manager.all_items() retrieved_items = list(retrieved_items) # Not always in order, but check the number of events. self.assertEqual(len(retrieved_items), 4) # Check we can get all the sequence IDs. entity_ids = set([i.sequence_id for i in retrieved_items]) self.assertEqual(entity_ids, {sequence_id1, sequence_id2}) if self.record_manager.contiguous_record_ids: # Check the record IDs are contiguous. records = self.record_manager.all_records() records = list(records) self.assertEqual(len(records), 4) first = None for i, record in enumerate(records): if first is None: first = record.id self.assertEqual(first + i, record.id, "Woops there's a gap: {}".format([r.id for r in records])) # Resume from after the first event. retrieved_items = self.record_manager.all_records(start=1, stop=3) retrieved_items = list(retrieved_items) self.assertEqual(len(retrieved_items), 2) self.assertEqual(retrieved_items[0].id, 2) self.assertEqual(retrieved_items[1].id, 3) # Delete some items. records = list(self.record_manager.all_records()) self.assertTrue(len(records)) for records in records: self.record_manager.delete_record(records) records = list(self.record_manager.all_records()) self.assertFalse(len(records)) # Check the record ID error. record_manager = self.record_manager if record_manager.contiguous_record_ids: # - for SQLite with self.assertRaises(RecordIDConflict): error = 'UNIQUE constraint failed: {}.id'.format(record_manager.record_table_name) record_manager.raise_after_integrity_error(error) # - for MySQL with self.assertRaises(RecordIDConflict): error = "Duplicate entry XXXXXXXXXX for key 'PRIMARY'" record_manager.raise_after_integrity_error(error) # - for MySQL with self.assertRaises(RecordIDConflict): error = 'duplicate key value violates unique constraint "{}_pkey"'.format( record_manager.record_table_name ) record_manager.raise_after_integrity_error(error) with self.assertRaises(SequencedItemConflict): error = '' record_manager.raise_after_integrity_error(error)
def test(self): sequence_id1 = uuid.uuid1() sequence_id2 = uuid.uuid1() # Check repo returns None when there aren't any items. self.assertEqual(self.active_record_strategy.get_items(sequence_id1), []) position1, position2, position3 = self.construct_positions() self.assertLess(position1, position2) self.assertLess(position2, position3) # Append an item. data1 = json.dumps({'name': 'value1'}) item1 = SequencedItem( sequence_id=sequence_id1, position=position1, topic=self.EXAMPLE_EVENT_TOPIC1, data=data1, ) self.active_record_strategy.append_item(item1) # Append an item to a different sequence. data2 = json.dumps({'name': 'value2'}) item2 = SequencedItem( sequence_id=sequence_id2, position=position1, topic=self.EXAMPLE_EVENT_TOPIC1, data=data2, ) self.active_record_strategy.append_item(item2) # Check the get_item() method returns item at position. retrieved_item = self.active_record_strategy.get_item( sequence_id1, position1) self.assertEqual(retrieved_item.sequence_id, sequence_id1) self.assertEqual(retrieved_item.position, position1) # Check index error is raised when item does not exist at position. with self.assertRaises(IndexError): self.active_record_strategy.get_item(sequence_id1, position2) # Check repo returns the item. retrieved_items = self.active_record_strategy.get_items(sequence_id1) self.assertEqual(len(retrieved_items), 1) self.assertIsInstance(retrieved_items[0], SequencedItem) self.assertEqual(retrieved_items[0].sequence_id, item1.sequence_id) self.assertEqual(retrieved_items[0].position, position1) self.assertEqual(retrieved_items[0].data, item1.data) self.assertEqual(retrieved_items[0].topic, item1.topic) # Check raises SequencedItemError when appending an item at same position in same sequence. data3 = json.dumps({'name': 'value3'}) item3 = SequencedItem( sequence_id=item1.sequence_id, position=position1, topic=self.EXAMPLE_EVENT_TOPIC2, data=data3, ) self.assertEqual(item1.sequence_id, item3.sequence_id) self.assertEqual(position1, item3.position) self.assertNotEqual(item1.topic, item3.topic) self.assertNotEqual(item1.data, item3.data) with self.assertRaises(SequencedItemError): self.active_record_strategy.append_item(item3) # Append a second item at the next position. item4 = SequencedItem( sequence_id=item1.sequence_id, position=position2, topic=self.EXAMPLE_EVENT_TOPIC2, data=data3, ) self.active_record_strategy.append_item(item4) # Check there are two items in the sequence. retrieved_items = self.active_record_strategy.get_items(sequence_id1) self.assertEqual(len(retrieved_items), 2) # Append a third item to the sequence at the next position. item5 = SequencedItem( sequence_id=item1.sequence_id, position=position3, topic=self.EXAMPLE_EVENT_TOPIC2, data=data3, ) self.active_record_strategy.append_item(item5) # Check there are three items. retrieved_items = self.active_record_strategy.get_items(sequence_id1) self.assertEqual(len(retrieved_items), 3) # Check the items are in sequential order. self.assertIsInstance(retrieved_items[0], SequencedItem) self.assertEqual(retrieved_items[0].sequence_id, item1.sequence_id) self.assertEqual(retrieved_items[0].position, position1) self.assertEqual(retrieved_items[0].topic, item1.topic) self.assertEqual(retrieved_items[0].data, item1.data) self.assertIsInstance(retrieved_items[1], SequencedItem) self.assertEqual(retrieved_items[1].sequence_id, item3.sequence_id) self.assertEqual(retrieved_items[1].position, position2) self.assertEqual(retrieved_items[1].topic, item3.topic) self.assertEqual(retrieved_items[1].data, item3.data) self.assertIsInstance(retrieved_items[2], SequencedItem) self.assertEqual(retrieved_items[2].sequence_id, item5.sequence_id) self.assertEqual(retrieved_items[2].position, position3) self.assertEqual(retrieved_items[2].topic, item5.topic) self.assertEqual(retrieved_items[2].data, item5.data) # Get items greater than a position. retrieved_items = self.active_record_strategy.get_items(sequence_id1, gt=position1) self.assertEqual(len(retrieved_items), 2) self.assertEqual(retrieved_items[0].position, position2) self.assertEqual(retrieved_items[1].position, position3) # Get items greater then or equal to a position. retrieved_items = self.active_record_strategy.get_items(sequence_id1, gte=position2) self.assertEqual(len(retrieved_items), 2) self.assertEqual(retrieved_items[0].position, position2) self.assertEqual(retrieved_items[1].position, position3) # Get items less than a position. retrieved_items = self.active_record_strategy.get_items(sequence_id1, lt=position3) self.assertEqual(len(retrieved_items), 2) self.assertEqual(retrieved_items[0].position, position1) self.assertEqual(retrieved_items[1].position, position2) # Get items less then or equal to a position. retrieved_items = self.active_record_strategy.get_items(sequence_id1, lte=position2) self.assertEqual(len(retrieved_items), 2) self.assertEqual(retrieved_items[0].position, position1) self.assertEqual(retrieved_items[1].position, position2) # Get items greater then or equal to a position and less then or equal to a position. retrieved_items = self.active_record_strategy.get_items(sequence_id1, gte=position2, lte=position2) self.assertEqual(len(retrieved_items), 1) self.assertEqual(retrieved_items[0].position, position2) # Get items greater then or equal to a position and less then a position. retrieved_items = self.active_record_strategy.get_items(sequence_id1, gte=position2, lt=position3) self.assertEqual(len(retrieved_items), 1) self.assertEqual(retrieved_items[0].position, position2) # Get items greater then a position and less then or equal to a position. retrieved_items = self.active_record_strategy.get_items(sequence_id1, gt=position1, lte=position2) self.assertEqual(len(retrieved_items), 1) self.assertEqual(retrieved_items[0].position, position2) # Get items greater a position and less a position. retrieved_items = self.active_record_strategy.get_items(sequence_id1, gt=position1, lt=position3) self.assertEqual(len(retrieved_items), 1) self.assertEqual(retrieved_items[0].position, position2) # Get items with a limit. retrieved_items = self.active_record_strategy.get_items(sequence_id1, limit=1) self.assertEqual(len(retrieved_items), 1) self.assertEqual(retrieved_items[0].position, position1) # Get items with a limit, and with descending query (so that we get the last ones). retrieved_items = self.active_record_strategy.get_items( sequence_id1, limit=2, query_ascending=False) self.assertEqual(len(retrieved_items), 2) self.assertEqual(retrieved_items[0].position, position2) self.assertEqual(retrieved_items[1].position, position3) # Get items with a limit and descending query, greater than a position. retrieved_items = self.active_record_strategy.get_items( sequence_id1, limit=2, gt=position2, query_ascending=False) self.assertEqual(len(retrieved_items), 1) self.assertEqual(retrieved_items[0].position, position3) # Get items with a limit and descending query, less than a position. retrieved_items = self.active_record_strategy.get_items( sequence_id1, limit=2, lt=position3, query_ascending=False) self.assertEqual(len(retrieved_items), 2) self.assertEqual(retrieved_items[0].position, position1) self.assertEqual(retrieved_items[1].position, position2) # Get items in descending order, queried in ascending order. retrieved_items = self.active_record_strategy.get_items( sequence_id1, results_ascending=False) self.assertEqual(len(retrieved_items), 3) self.assertEqual(retrieved_items[0].position, position3) self.assertEqual(retrieved_items[2].position, position1) # Get items in descending order, queried in descending order. retrieved_items = self.active_record_strategy.get_items( sequence_id1, query_ascending=False, results_ascending=False) self.assertEqual(len(retrieved_items), 3) self.assertEqual(retrieved_items[0].position, position3) self.assertEqual(retrieved_items[2].position, position1) # Iterate over all items in all sequences. retrieved_items = self.active_record_strategy.all_items() retrieved_items = list(retrieved_items) # Not always in order, but check the number of events. self.assertEqual(len(retrieved_items), 4) # Check we can get all the sequence IDs. entity_ids = set([i.sequence_id for i in retrieved_items]) self.assertEqual(entity_ids, {sequence_id1, sequence_id2})