public void AddDeleteAddSameObjectInstance_MustFail() { // Due to the way version is managed it's crutial that added objects are new instances var manager = new InMemoryObjectManager(); // FIRST TRANSACTION: Add two object var firstTransaction = manager.CreateTransaction(); var firstObj = new TestObjectA(Guid.NewGuid(), "first object"); firstTransaction.Add(firstObj); firstTransaction.Commit(); // SECOND TRANSACTION: Delete first object var secondTransaction = manager.CreateTransaction(); secondTransaction.Delete(firstObj.Id); secondTransaction.Commit(); // THIRD TRANSACTION: Add first object again - same instance - must fail var thirdTransaction = manager.CreateTransaction(); Assert.Throws <OperationCanceledException>(() => thirdTransaction.Add(firstObj)); }
public void AddDeleteTest_GetObjectsMustReturnCorrectResult() { var manager = new InMemoryObjectManager(); // FIRST TRANSACTION: Add two object var firstTransaction = manager.CreateTransaction(); var firstObj = new TestObjectA(Guid.NewGuid(), "first object"); firstTransaction.Add(firstObj); var secondObj = new TestObjectA(Guid.NewGuid(), "second object"); firstTransaction.Add(secondObj); firstTransaction.Commit(); // SECOND TRANSACTION: Delete first object var secondTransaction = manager.CreateTransaction(); secondTransaction.Delete(firstObj.Id); secondTransaction.Commit(); // THIRD TRANSACTION: Delete second object var thirdTransaction = manager.CreateTransaction(); thirdTransaction.Delete(secondObj.Id); thirdTransaction.Commit(); // FORTH TRANSACTION: Add second object again var forthTransaction = manager.CreateTransaction(); forthTransaction.Add(new TestObjectA(secondObj.Id, "second object version 2")); forthTransaction.Commit(); // In version 1 we should have 2 object Assert.Equal(2, manager.GetObjects(1).Count()); // In version 1 name of first object should be "first object" Assert.Contains(manager.GetObjects(1), o => o.Id == firstObj.Id && ((TestObjectA)o).Name == "first object"); // In version 1 name of second object should be "second object" Assert.Contains(manager.GetObjects(1), o => o.Id == secondObj.Id && ((TestObjectA)o).Name == "second object"); // In version 2 we should have only 1 object Assert.Single(manager.GetObjects(2)); // In version 2 we should have the second object named "second object" Assert.Contains(manager.GetObjects(2), o => o.Id == secondObj.Id && ((TestObjectA)o).Name == "second object"); // In version 3 we should have no objects Assert.Empty(manager.GetObjects(3)); // In version 4 we should have 1 object Assert.Single(manager.GetObjects(4)); // In version 4 we should have the second object named "second object version 2" Assert.Contains(manager.GetObjects(4), o => o.Id == secondObj.Id && ((TestObjectA)o).Name == "second object version 2"); }
private ITransaction GetLoadModeTransaction() { if (_loadModeTransaction == null) { _loadModeTransaction = _objectManager.CreateTransaction(); } return(_loadModeTransaction); }
public void AddingTheSameObjectTwiceInTwoTransactions_MustFail() { var manager = new InMemoryObjectManager(); var firstTransaction = manager.CreateTransaction(); var objToAdd = new TestObjectA(Guid.NewGuid(), "hej"); firstTransaction.Add(objToAdd); firstTransaction.Commit(); var secondTransaction = manager.CreateTransaction(); Assert.Throws <OperationCanceledException>(() => secondTransaction.Add(objToAdd)); }
public void CreateTwoTransactionWithSameCustomId_MustFail() { var manager = new InMemoryObjectManager(); // First transaction var firstTransaction = manager.CreateTransaction("my custom version id 1"); var objToAdd = new TestObjectA(Guid.NewGuid(), "hej"); firstTransaction.Add(objToAdd); firstTransaction.Commit(); // Create second transaction with the same version id Assert.Throws <ArgumentException>(() => manager.CreateTransaction("my custom version id 1")); }
public void AddingObjects_GetObjectsMustReturnCorrectNumberOfObjects() { var manager = new InMemoryObjectManager(); // We should have zero object in the manager Assert.Empty(manager.GetObjects()); // FIRST TRANSACTION var firstTransaction = manager.CreateTransaction(); firstTransaction.Add(new TestObjectA(Guid.NewGuid(), "first object")); Assert.Empty(manager.GetObjects()); // We should still have zero object in the manager, because transaction is not commited yet firstTransaction.Commit(); Assert.Single(manager.GetObjects()); // We should have one object in the manager after transaction commit // SECOND TRANSACTION var secondTransaction = manager.CreateTransaction(); secondTransaction.Add(new TestObjectA(Guid.NewGuid(), "second object")); Assert.Single(manager.GetObjects()); // We should have one object in the manager before transaction commit secondTransaction.Commit(); Assert.Equal(2, manager.GetObjects().Count()); // We should have two object in the manager before transaction commit // THIRD TRANSACTION var thirdTransaction = manager.CreateTransaction(); thirdTransaction.Add(new TestObjectA(Guid.NewGuid(), "third object")); thirdTransaction.Add(new TestObjectA(Guid.NewGuid(), "forth object")); Assert.Equal(2, manager.GetObjects().Count()); // We should have two object in the manager before transaction commit thirdTransaction.Commit(); Assert.Equal(4, manager.GetObjects().Count()); // We should have four object in the manager before transaction commit // Assert that GetObjects by internal version id works Assert.Single(manager.GetObjects(1)); // In version 1 we should have 1 object Assert.Equal(2, manager.GetObjects(2).Count()); // In version 2 we should have 2 object Assert.Equal(4, manager.GetObjects(3).Count()); // In version 3 we should have 4 object }
public void AddedObject_ShouldGetCreationStateAssignedOnCommit() { var manager = new InMemoryObjectManager(); var transaction = manager.CreateTransaction(); // Internal version id should be 1 Assert.Equal(1, transaction.Version.InternalVersionId); var objToAdd = new TestObjectA(Guid.NewGuid(), "hej"); transaction.Add(objToAdd); // Creation version should not be assigned yet Assert.Null(objToAdd.CreationVersion); // Deletion version should be null Assert.Null(objToAdd.DeletionVersion); transaction.Commit(); // Creation version should now be assigned Assert.Equal(transaction.Version, objToAdd.CreationVersion); // Deletion version should still be null Assert.Null(objToAdd.DeletionVersion); }
public void UpdateObjectWithSameInstance_MustFail() { var manager = new InMemoryObjectManager(); // FIRST TRANSACTION: Add two object var firstTransaction = manager.CreateTransaction(); var firstObj = new TestObjectA(Guid.NewGuid(), "first object"); firstTransaction.Add(firstObj); firstTransaction.Commit(); // SECOND TRANSACTION: Update object using same instance - must fail var secondTransaction = manager.CreateTransaction(); Assert.Throws <OperationCanceledException>(() => secondTransaction.Update(firstObj)); }
public void DiffBetweenTwoAdjacentVersions_CheckResult() { var manager = new InMemoryObjectManager(); /////////////////////////////////////////////////////////////////////////////////////////////////////////////// // FIRST TRANSACTION var firstTransaction = manager.CreateTransaction(); var firstObj = firstTransaction.Add(new TestObjectA(Guid.NewGuid(), "first object")); var secondObj = firstTransaction.Add(new TestObjectA(Guid.NewGuid(), "second object")); var thirdObj = firstTransaction.Add(new TestObjectA(Guid.NewGuid(), "third object")); firstTransaction.Commit(); /////////////////////////////////////////////////////////////////////////////////////////////////////////////// // SECOND TRANSACTION var secondTransaction = manager.CreateTransaction(); // Insert forth object var forthObj = secondTransaction.Add(new TestObjectA(Guid.NewGuid(), "forth object")); // Delete second object secondTransaction.Delete(secondObj.Id); // Update third object var thirdObjUpdated = new TestObjectA(thirdObj.Id, "third object updated"); secondTransaction.Update(thirdObjUpdated); secondTransaction.Commit(); /////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Get the changes and assert correctness var changes = manager.GetChanges(1, 2); // We did 3 changes: add, delete and update. Assert.Equal(3, changes.Count()); Assert.Contains(changes, c => c is ObjectCreation && ((ObjectCreation)c).NewState == forthObj); Assert.Contains(changes, c => c is ObjectDeletion && c.Id == secondObj.Id); Assert.Contains(changes, c => c is ObjectModification && ((ObjectModification)c).NewState == thirdObjUpdated && ((ObjectModification)c).PreviousState == thirdObj); }
public void AddAfterRollback_MustFail() { var manager = new InMemoryObjectManager(); var firstTransaction = manager.CreateTransaction(); firstTransaction.Add(new TestObjectA(Guid.NewGuid(), "hello")); firstTransaction.Rollback(); Assert.Throws <OperationCanceledException>(() => firstTransaction.Add(new TestObjectA(Guid.NewGuid(), "kitty"))); }
public void WorkAfterRollback_ShouldNotBeCommited() { var manager = new InMemoryObjectManager(); /////////////////////////////////////////////////////////////////////////////////////////////////////////////// // FIRST TRANSACTION var firstTransaction = manager.CreateTransaction(); var firstObj = firstTransaction.Add(new TestObjectA(Guid.NewGuid(), "first object")); var secondObj = firstTransaction.Add(new TestObjectA(Guid.NewGuid(), "second object")); var thirdObj = firstTransaction.Add(new TestObjectA(Guid.NewGuid(), "third object")); firstTransaction.Commit(); /////////////////////////////////////////////////////////////////////////////////////////////////////////////// // SECOND TRANSACTION var secondTransaction = manager.CreateTransaction(); // Insert forth object var forthObj = secondTransaction.Add(new TestObjectA(Guid.NewGuid(), "forth object")); // Delete second object secondTransaction.Delete(secondObj.Id); // Update third object var thirdObjUpdated = new TestObjectA(thirdObj.Id, "third object updated"); secondTransaction.Update(thirdObjUpdated); secondTransaction.Rollback(); // In version 1 we should have 3 object Assert.Equal(3, manager.GetObjects(1).Count()); // In version 1 name of first object should be "first object" Assert.Contains(manager.GetObjects(1), o => o.Id == firstObj.Id && ((TestObjectA)o).Name == "first object"); // In version 1 name of second object should be "second object" Assert.Contains(manager.GetObjects(1), o => o.Id == secondObj.Id && ((TestObjectA)o).Name == "second object"); // Version 2 should not exist, because we did a rollback of the second transaction Assert.Throws <ArgumentException>(() => manager.GetObjects(2)); }
public void UpdateObject_GetObjectsMustReturnCorrectResult() { var manager = new InMemoryObjectManager(); // FIRST TRANSACTION: Add two object var firstTransaction = manager.CreateTransaction(); var firstObj = new TestObjectA(Guid.NewGuid(), "first object"); firstTransaction.Add(firstObj); var secondObj = new TestObjectA(Guid.NewGuid(), "second object"); firstTransaction.Add(secondObj); firstTransaction.Commit(); // SECOND TRANSACTION: Update name of second object var secondTransaction = manager.CreateTransaction(); var updatedObj = new TestObjectA(secondObj.Id, "second object updated"); secondTransaction.Update(updatedObj); secondTransaction.Commit(); // In version 1 we should have 2 object Assert.Equal(2, manager.GetObjects(1).Count()); // In version 1 name of first object should be "first object" Assert.Contains(manager.GetObjects(1), o => o.Id == firstObj.Id && ((TestObjectA)o).Name == "first object"); // In version 1 name of second object should be "second object" Assert.Contains(manager.GetObjects(1), o => o.Id == secondObj.Id && ((TestObjectA)o).Name == "second object"); // In version 2 we should still have 2 object Assert.Equal(2, manager.GetObjects(2).Count()); // In version 2 name of first object should still be "first object" Assert.Contains(manager.GetObjects(2), o => o.Id == firstObj.Id && ((TestObjectA)o).Name == "first object"); // In version 2 name of second object should be changed to "second object updated" Assert.Contains(manager.GetObjects(2), o => o.Id == secondObj.Id && ((TestObjectA)o).Name == "second object updated"); }
public void DeleteObject_GetObjectsMustReturnCorrectResult() { var manager = new InMemoryObjectManager(); // FIRST TRANSACTION: Add two object var firstTransaction = manager.CreateTransaction(); var firstObj = new TestObjectA(Guid.NewGuid(), "first object"); firstTransaction.Add(firstObj); var secondObj = new TestObjectA(Guid.NewGuid(), "second object"); firstTransaction.Add(secondObj); firstTransaction.Commit(); // SECOND TRANSACTION: Delete first object var secondTransaction = manager.CreateTransaction(); secondTransaction.Delete(firstObj.Id); secondTransaction.Commit(); // Deletion version should not be null Assert.NotNull(firstObj.DeletionVersion); // In version 1 we should have 2 object Assert.Equal(2, manager.GetObjects(1).Count()); // In version 1 name of first object should be "first object" Assert.Contains(manager.GetObjects(1), o => o.Id == firstObj.Id && ((TestObjectA)o).Name == "first object"); // In version 1 name of second object should be "second object" Assert.Contains(manager.GetObjects(1), o => o.Id == secondObj.Id && ((TestObjectA)o).Name == "second object"); // In version 2 we should have only 1 object Assert.Single(manager.GetObjects(2)); // In version 2 we should have the second object named "second object" Assert.Contains(manager.GetObjects(2), o => o.Id == secondObj.Id && ((TestObjectA)o).Name == "second object"); }
public void DeleteAfterCommit_MustFail() { var manager = new InMemoryObjectManager(); var firstTransaction = manager.CreateTransaction(); var objToAdd = new TestObjectA(Guid.NewGuid(), "hello"); firstTransaction.Add(objToAdd); firstTransaction.Commit(); Assert.Throws <OperationCanceledException>(() => firstTransaction.Delete(objToAdd.Id)); }
public void InvalidFromAndToVersionIds_ShouldFail(int fromVersionId, int toVersionId) { var manager = new InMemoryObjectManager(); /////////////////////////////////////////////////////////////////////////////////////////////////////////////// // FIRST TRANSACTION var firstTransaction = manager.CreateTransaction(); var firstObj = firstTransaction.Add(new TestObjectA(Guid.NewGuid(), "first object")); var secondObj = firstTransaction.Add(new TestObjectA(Guid.NewGuid(), "second object")); var thirdObj = firstTransaction.Add(new TestObjectA(Guid.NewGuid(), "third object")); firstTransaction.Commit(); Assert.Throws <ArgumentException>(() => manager.GetChanges(fromVersionId, toVersionId)); }
public void AddingObject_TestGetObject() { var manager = new InMemoryObjectManager(); var firstTransaction = manager.CreateTransaction("custom version id"); var objToAdd = new TestObjectA(Guid.NewGuid(), "hej"); firstTransaction.Add(objToAdd); firstTransaction.Commit(); // Asset that GetObject(guid id) workd Assert.Equal(objToAdd, manager.GetObject(objToAdd.Id)); // Asset that GetObject(guid id, long version id) works Assert.Equal(objToAdd, manager.GetObject(objToAdd.Id, 1)); // Asset that GetObject(custom, string version id ) works Assert.Equal(objToAdd, manager.GetObject(objToAdd.Id, "custom version id")); }
public void CreateTransactionWithCustomId_TestGetObject() { var manager = new InMemoryObjectManager(); var myCustomId = "my custom version id 1"; var firstTransaction = manager.CreateTransaction(myCustomId); var objToAdd = new TestObjectA(Guid.NewGuid(), "hej"); firstTransaction.Add(objToAdd); firstTransaction.Commit(); // Asser that GetObjects work with custom ids var objects = manager.GetObjects(myCustomId); Assert.Single(objects); var obj = manager.GetObject(objToAdd.Id, myCustomId); Assert.Equal(objToAdd, obj); }
public void TestConcurrentReaderOneWriter() { var manager = new InMemoryObjectManager(); // Add initial object var transaction = manager.CreateTransaction(); var objToAdd = new TestObjectA(Guid.NewGuid(), "initial"); transaction.Add(objToAdd); transaction.Commit(); // Update name of object to inital 2 transaction = manager.CreateTransaction(); var objToUpdate = new TestObjectA(objToAdd.Id, "initial 2"); transaction.Update(objToUpdate); transaction.Commit(); // Thread that create a new transaction every 10 milisecond new Thread(() => { for (int i = 0; i < 100; i++) { var transaction = manager.CreateTransaction(); var objToUpdate = new TestObjectA(objToAdd.Id, "trans version " + transaction.Version.InternalVersionId); transaction.Update(objToUpdate); //Give some time to other threads to kick in Thread.Sleep(10); transaction.Commit(); Assert.Single(manager.GetObjects(transaction.Version.InternalVersionId)); } }).Start(); // Reading thread #1 new Thread(() => { for (int i = 0; i < 100; i++) { Assert.Single(manager.GetObjects(1)); Assert.Equal("initial", ((TestObjectA)manager.GetObjects(1).First()).Name); Thread.Sleep(10); } }).Start(); // Reading thread #2 new Thread(() => { for (int i = 0; i < 100; i++) { Assert.Single(manager.GetObjects(1)); Assert.Equal("initial", ((TestObjectA)manager.GetObjects(1).First()).Name); Thread.Sleep(10); } }).Start(); // Reading thread #3 new Thread(() => { for (int i = 0; i < 100; i++) { Assert.Single(manager.GetObjects(2)); Assert.Equal("initial 2", ((TestObjectA)manager.GetObjects(2).First()).Name); Thread.Sleep(10); } }).Start(); Thread.Sleep(1500); }
public void ApplySegmentCut(SpanEquipment spanEquipment, SpanSegmentCutInfo spanSegmentCutInfo) { var version = _objectManager.GetLatestCommitedVersion(); var trans = _objectManager.CreateTransaction(); try { if (!_graphElementsById.TryGetValue(spanSegmentCutInfo.OldSpanSegmentId, out var oldSegmentGraphElement)) { throw new ApplicationException($"Cannot find span segment graph element with id: {spanSegmentCutInfo.OldSpanSegmentId} processing segment cut."); } if (!spanEquipment.TryGetSpanSegment(spanSegmentCutInfo.NewSpanSegmentId1, out var segment1withIndexInfo)) { throw new ApplicationException($"Cannot find span segment with id: {spanSegmentCutInfo.OldSpanSegmentId} in span equipment: {spanEquipment.Id} "); } if (!spanEquipment.TryGetSpanSegment(spanSegmentCutInfo.NewSpanSegmentId2, out var segment2withIndexInfo)) { throw new ApplicationException($"Cannot find span segment with id: {spanSegmentCutInfo.OldSpanSegmentId} in span equipment: {spanEquipment.Id} "); } // We need to go through all new span segments in the structure, and check if we need update the graph element due to segment index shift for (int newSegmentIndex = 0; newSegmentIndex < spanEquipment.SpanStructures[segment1withIndexInfo.StructureIndex].SpanSegments.Length; newSegmentIndex++) { var newSegment = spanEquipment.SpanStructures[segment1withIndexInfo.StructureIndex].SpanSegments[newSegmentIndex]; if (TryGetGraphElement <IUtilityGraphSegmentRef>(newSegment.Id, out var existingUtilityGraphSegmentRef)) { if (existingUtilityGraphSegmentRef.SegmentIndex != newSegmentIndex) { var newUtilityGraphElement = existingUtilityGraphSegmentRef.CreateWithNewSegmentIndex((ushort)newSegmentIndex); if (newUtilityGraphElement is UtilityGraphConnectedSegment) { trans.Update((UtilityGraphConnectedSegment)newUtilityGraphElement); } UpdateDict(newSegment.Id, newUtilityGraphElement); } } } // If existing segment is disconnected, it's not in the graph either if (oldSegmentGraphElement is UtilityGraphDisconnectedSegment) { AddDisconnectedSegment(spanEquipment, segment1withIndexInfo.StructureIndex, segment1withIndexInfo.SegmentIndex); AddDisconnectedSegment(spanEquipment, segment2withIndexInfo.StructureIndex, segment2withIndexInfo.SegmentIndex); RemoveFromDict(spanSegmentCutInfo.OldSpanSegmentId); } else { var oldConnectedGraphElement = (UtilityGraphConnectedSegment)oldSegmentGraphElement; // Create first/left segment if (oldConnectedGraphElement.InV(version) != null) { var newSegment1GraphElement = new UtilityGraphConnectedSegment(spanSegmentCutInfo.NewSpanSegmentId1, (UtilityGraphConnectedTerminal)oldConnectedGraphElement.InV(version), null, spanEquipment.Id, segment1withIndexInfo.StructureIndex, segment1withIndexInfo.SegmentIndex); trans.Add(newSegment1GraphElement); AddToDict(newSegment1GraphElement.Id, newSegment1GraphElement); } // If InV is null, then we end with a disconnected segment else { var newSegment1DisconnectedGraphElement = new UtilityGraphDisconnectedSegment(spanEquipment.Id, segment1withIndexInfo.StructureIndex, segment1withIndexInfo.SegmentIndex); AddToDict(spanSegmentCutInfo.NewSpanSegmentId1, newSegment1DisconnectedGraphElement); } // Create second/right segment if (oldConnectedGraphElement.OutV(version) != null) { var newSegment2GraphElement = new UtilityGraphConnectedSegment(spanSegmentCutInfo.NewSpanSegmentId2, null, (UtilityGraphConnectedTerminal)oldConnectedGraphElement.OutV(version), spanEquipment.Id, segment2withIndexInfo.StructureIndex, segment2withIndexInfo.SegmentIndex); trans.Add(newSegment2GraphElement); AddToDict(newSegment2GraphElement.Id, newSegment2GraphElement); } // If OutV is null, then we end with a disconnected segment else { var newSegment2DisconnectedGraphElement = new UtilityGraphDisconnectedSegment(spanEquipment.Id, segment2withIndexInfo.StructureIndex, segment2withIndexInfo.SegmentIndex); AddToDict(spanSegmentCutInfo.NewSpanSegmentId2, newSegment2DisconnectedGraphElement); } // Remove old segment trans.Delete(oldConnectedGraphElement.Id); RemoveFromDict(oldConnectedGraphElement.Id); } } finally { trans.Commit(); } }
public void CreateSimpleGraph_CheckNodeAndEdgeTraversal() { // N1 // | // E1 | // | E2 // N2-------------N3 var manager = new InMemoryObjectManager(); var trans = manager.CreateTransaction(); var n1 = new GraphNode(Guid.NewGuid()); trans.Add(n1); var n2 = new GraphNode(Guid.NewGuid()); trans.Add(n2); var n3 = new GraphNode(Guid.NewGuid()); trans.Add(n3); var e1 = new GraphEdge(Guid.NewGuid(), n1, n2); trans.Add(e1); var e2 = new GraphEdge(Guid.NewGuid(), n2, n3); trans.Add(e2); trans.Commit(); var version = trans.Version.InternalVersionId; // N1 should have zero ingoing edges Assert.Empty(n1.InE(version)); // N1 should have one outgoing edge Assert.Single(n1.OutE(version)); Assert.Contains(e1, n1.OutE(version).Where(e => e.Id == e1.Id)); // N2 should have one ingoing edge Assert.Single(n2.InE(version)); Assert.Contains(e1, n2.InE(version).Where(e => e.Id == e1.Id)); // N2 should have one outgoing edge Assert.Single(n2.OutE(version)); Assert.Contains(e2, n2.OutE(version).Where(e => e.Id == e2.Id)); // N3 should have one ingoing edges Assert.Single(n3.InE(version)); Assert.Contains(e2, n3.InE(version).Where(e => e.Id == e2.Id)); // N3 should have zero outgoing edges Assert.Empty(n3.OutE(version)); // E1 should have n1 as ingoing node Assert.Equal(n1, e1.InV(version)); // E1 should have n2 as ingoing node Assert.Equal(n2, e1.OutV(version)); // E2 should have n2 as ingoing node Assert.Equal(n2, e2.InV(version)); // E2 should have n3 as ingoing node Assert.Equal(n3, e2.OutV(version)); // Try traverse the graph from node 1 var traceResult = n1.UndirectionalDFS <GraphNode, GraphEdge>(version); Assert.Equal(5, traceResult.Count()); }
public void DiffBetweenManyVersions_CheckResult() { var manager = new InMemoryObjectManager(); /////////////////////////////////////////////////////////////////////////////////////////////////////////////// // FIRST TRANSACTION var firstTransaction = manager.CreateTransaction(); var firstObj = firstTransaction.Add(new TestObjectA(Guid.NewGuid(), "first object")); var secondObj = firstTransaction.Add(new TestObjectA(Guid.NewGuid(), "second object")); var thirdObj = firstTransaction.Add(new TestObjectA(Guid.NewGuid(), "third object")); firstTransaction.Commit(); /////////////////////////////////////////////////////////////////////////////////////////////////////////////// // SECOND TRANSACTION var secondTransaction = manager.CreateTransaction(); // Insert forth object var forthObj = secondTransaction.Add(new TestObjectA(Guid.NewGuid(), "forth object")); // Delete second object secondTransaction.Delete(secondObj.Id); // Update third object var thirdObjUpdatedFirstTime = new TestObjectA(thirdObj.Id, "third object updated first time"); secondTransaction.Update(thirdObjUpdatedFirstTime); secondTransaction.Commit(); /////////////////////////////////////////////////////////////////////////////////////////////////////////////// // THIRD TRANSACTION var thirdTransaction = manager.CreateTransaction(); // Insert fifth object var fifthObj = thirdTransaction.Add(new TestObjectA(Guid.NewGuid(), "fifth object")); // Delete first object thirdTransaction.Delete(firstObj.Id); // Update third object again var thirdObjUpdatedSecondTime = new TestObjectA(thirdObj.Id, "third object updated second time"); thirdTransaction.Update(thirdObjUpdatedSecondTime); thirdTransaction.Commit(); /////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Get the changes between version 1 and 2 and assert correctness var changes = manager.GetChanges(1, 2); // We did 3 changes: add, delete and update. Assert.Equal(3, changes.Count()); Assert.Contains(changes, c => c is ObjectCreation && ((ObjectCreation)c).NewState == forthObj); Assert.Contains(changes, c => c is ObjectDeletion && c.Id == secondObj.Id); Assert.Contains(changes, c => c is ObjectModification && ((ObjectModification)c).NewState == thirdObjUpdatedFirstTime && ((ObjectModification)c).PreviousState == thirdObj); /////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Get the changes between version 1 and 3 and assert correctness changes = manager.GetChanges(1, 3); // We did 5 changes: two add, two delete and one update. Assert.Equal(5, changes.Count()); Assert.Contains(changes, c => c is ObjectCreation && ((ObjectCreation)c).NewState == forthObj); Assert.Contains(changes, c => c is ObjectCreation && ((ObjectCreation)c).NewState == fifthObj); Assert.Contains(changes, c => c is ObjectDeletion && c.Id == firstObj.Id); Assert.Contains(changes, c => c is ObjectDeletion && c.Id == secondObj.Id); Assert.Contains(changes, c => c is ObjectModification && ((ObjectModification)c).NewState == thirdObjUpdatedSecondTime && ((ObjectModification)c).PreviousState == thirdObj); /////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Get the changes between version 2 and 3 and assert correctness changes = manager.GetChanges(2, 3); // We did 3 changes: add, delete and update. Assert.Equal(3, changes.Count()); Assert.Contains(changes, c => c is ObjectCreation && ((ObjectCreation)c).NewState == fifthObj); Assert.Contains(changes, c => c is ObjectDeletion && c.Id == firstObj.Id); Assert.Contains(changes, c => c is ObjectModification && ((ObjectModification)c).NewState == thirdObjUpdatedSecondTime && ((ObjectModification)c).PreviousState == thirdObjUpdatedFirstTime); }