public void LargerThanOperatorWithFirstObjectNull() { TimeMarker first = null; var second = new TimeMarker(1); Assert.IsFalse(first > second); }
/// <summary> /// Moves the history back enough steps to make the last known time is equal to or smaller than the /// provided mark. /// </summary> /// <param name="mark">The mark that indicates to which point in time the roll-back should be performed.</param> /// <param name="action">The action that should be executed on each single time step which is rolled back.</param> /// <returns> /// The last recorded value. /// </returns> private T RollBackInTimeTo(TimeMarker mark, Action <TimeMarker, T> action) { { Debug.Assert(!IsAtBeginOfTime(), "Should not roll back past the beginning of time."); } bool hasChanged = false; // We assume that it is more likely that we have a more recent // point in time that we want to roll back to. So start searching // from the end of the collection var lastNode = m_PastValues.Last; while ((lastNode != null) && (lastNode.Value.Time > mark)) { m_PastValues.RemoveLast(); m_FutureValues.AddFirst(lastNode); if (action != null) { action(lastNode.Value.Time, lastNode.Value.Value); } lastNode = m_PastValues.Last; hasChanged = true; } if (hasChanged) { RaiseOnCurrentValueChange(); } return((m_PastValues.Last != null) ? m_PastValues.Last.Value.Value : default(T)); }
public void CompareToWithSmallerFirstObject() { var first = new TimeMarker(1); object second = new TimeMarker(2); Assert.IsTrue(first.CompareTo(second) < 0); }
public void CompareToWithUnequalObjectTypes() { var first = new TimeMarker(1); var second = new object(); Assert.Throws <ArgumentException>(() => first.CompareTo(second)); }
public void CompareToWithNullObject() { var first = new TimeMarker(1); object second = null; Assert.AreEqual(1, first.CompareTo(second)); }
public void CompareToOperatorWithEqualObjects() { var first = new TimeMarker(1); object second = new TimeMarker(1); Assert.AreEqual(0, first.CompareTo(second)); }
public void SmallerThanOperatorWithFirstObjectSmaller() { var first = new TimeMarker(1); var second = new TimeMarker(2); Assert.IsTrue(first < second); }
public void Clone() { var first = new TimeMarker(1); var second = new TimeMarker(first); Assert.AreEqual(first, second); }
public void SmallerThanOperatorWithEqualObjects() { var first = new TimeMarker(1); var second = new TimeMarker(1); Assert.IsFalse(first < second); }
public void SmallerThanOperatorWithBothObjectsNull() { TimeMarker first = null; TimeMarker second = null; Assert.IsFalse(first < second); }
public void SmallerThanOperatorWithSecondObjectNull() { var first = new TimeMarker(1); TimeMarker second = null; Assert.IsFalse(first < second); }
/// <summary> /// Moves the history forward enough steps to make the next future time is equal to or larger than the /// provided mark. /// </summary> /// <param name="mark">The mark that indicates to which point in time the roll-forward should be performed.</param> /// <param name="action">The action that should be executed on each single time step which is rolled back.</param> /// <returns> /// The last recorded value. /// </returns> private T RollForwardInTimeTo(TimeMarker mark, Action <TimeMarker, T> action) { { Debug.Assert(!IsAtEndOfTime(), "Should not be at the end of time."); } bool hasChanged = false; // We assume that it is more likely that we have a more recent // point in time that we want to roll forward to. So start searching // from the start of the collection while ((m_FutureValues.First != null) && (m_FutureValues.First.Value.Time <= mark)) { var lastNode = m_FutureValues.First; m_FutureValues.RemoveFirst(); m_PastValues.AddLast(lastNode); if (action != null) { action(lastNode.Value.Time, lastNode.Value.Value); } hasChanged = true; } if (hasChanged) { RaiseOnCurrentValueChange(); } return((m_PastValues.Last != null) ? m_PastValues.Last.Value.Value : default(T)); }
/// <summary> /// Stores the current value in the history list with the given marker. /// </summary> /// <param name="marker">The marker which indicates at which point on the timeline the data is stored.</param> /// <exception cref="CannotStoreValuesAtTheStartOfTimeException"> /// Thrown when <paramref name="marker"/> is equal to <see cref="TimeMarker.TheBeginOfTime"/>. /// </exception> public void StoreCurrent(TimeMarker marker) { { Lokad.Enforce.With <CannotStoreValuesAtTheStartOfTimeException>( marker > TimeMarker.TheBeginOfTime, Resources.Exceptions_Messages_CannotStoreValuesAtTheStartOfTime); } if (m_Changes.Count == 0) { return; } if (ShouldSnapshot()) { CreateSnapshot(marker); } else { m_ValueHistory.StoreCurrent(marker, m_Changes); } m_Changes = new List <IHistoryChange <T> >(); ForgetTheFuture(); }
public void RollForwardWithLocalChange() { var id = new HistoryId(); var timeline = new ObjectTimeline <MockHistoryObject>(id, BuildStorageOfType, BuildObject); var creationTime = new TimeMarker(1); timeline.AddToTimeline(); timeline.Mark(creationTime); timeline.Object.SomeValue = 1; timeline.Object.LotsOfValues.Add(2); timeline.Mark(new TimeMarker(2)); timeline.Object.SomeValue = 2; timeline.Object.LotsOfValues.Add(4); timeline.Mark(new TimeMarker(3)); timeline.RollBackTo(new TimeMarker(2)); timeline.Object.SomeValue = 3; timeline.Object.LotsOfValues.Add(8); timeline.RollForwardTo(new TimeMarker(3)); Assert.AreEqual(2, timeline.Object.SomeValue); Assert.That( timeline.Object.LotsOfValues, Is.EquivalentTo(new int[] { 2, 4 })); }
public void LargerThanOperatorWithSecondObjectNull() { var first = new TimeMarker(1); TimeMarker second = null; Assert.IsTrue(first > second); }
public void RollBackFromDeathToLife() { var id = new HistoryId(); var timeline = new ObjectTimeline <MockHistoryObject>(id, BuildStorageOfType, BuildObject); var creationTime = new TimeMarker(1); timeline.AddToTimeline(); timeline.Mark(creationTime); timeline.Object.SomeValue = 1; timeline.Object.LotsOfValues.Add(2); timeline.Mark(new TimeMarker(2)); var deletionTime = new TimeMarker(3); timeline.DeleteFromTimeline(); timeline.Mark(deletionTime); Assert.DoesNotThrow(() => timeline.RollBackTo(new TimeMarker(2))); Assert.IsTrue(timeline.IsAlive()); Assert.IsNotNull(timeline.Object); Assert.AreEqual(1, timeline.Object.SomeValue); Assert.That( timeline.Object.LotsOfValues, Is.EquivalentTo(new int[] { 2 })); }
public void RollForwardPastDeath() { var id = new HistoryId(); var timeline = new ObjectTimeline <MockHistoryObject>(id, BuildStorageOfType, BuildObject); var creationTime = new TimeMarker(1); timeline.AddToTimeline(); timeline.Mark(creationTime); timeline.Object.SomeValue = 1; timeline.Object.LotsOfValues.Add(2); timeline.Mark(new TimeMarker(2)); var deletionTime = new TimeMarker(3); timeline.DeleteFromTimeline(); timeline.Mark(deletionTime); timeline.RollBackTo(new TimeMarker(1)); Assert.IsTrue(timeline.IsAlive()); timeline.RollForwardTo(new TimeMarker(4)); Assert.IsFalse(timeline.IsAlive()); Assert.IsNull(timeline.Object); }
public void RollBackToPreviousValue() { var id = new HistoryId(); var timeline = new ObjectTimeline <MockHistoryObject>(id, BuildStorageOfType, BuildObject); var creationTime = new TimeMarker(1); timeline.AddToTimeline(); timeline.Mark(creationTime); int maximumValue = 10; for (int i = 1; i < maximumValue; i++) { timeline.Object.SomeValue = i; timeline.Object.LotsOfValues.Add(i); timeline.Mark(new TimeMarker((ulong)(i + 1))); } for (int i = maximumValue - 1; i > 0; i--) { timeline.RollBackTo(new TimeMarker((ulong)(i + 1))); Assert.AreEqual(i, timeline.Object.SomeValue); Assert.AreEqual(i, timeline.Object.LotsOfValues.Count); for (int j = 1; j <= i; j++) { Assert.IsTrue(timeline.Object.LotsOfValues.Contains(j)); } } }
public void RollBackToBeginning() { var id = new HistoryId(); var timeline = new ObjectTimeline <MockHistoryObject>(id, BuildStorageOfType, BuildObject); var creationTime = new TimeMarker(1); timeline.AddToTimeline(); timeline.Mark(creationTime); int maximumValue = 10; for (int i = 0; i < maximumValue; i++) { timeline.Object.SomeValue = i; timeline.Object.LotsOfValues.Add(i); timeline.Mark(new TimeMarker((ulong)(i + 2))); } timeline.RollBackTo(new TimeMarker(1)); Assert.IsTrue(timeline.IsAlive()); Assert.IsNotNull(timeline.Object); Assert.AreEqual(0, timeline.Object.SomeValue); Assert.AreEqual(0, timeline.Object.LotsOfValues.Count); }
/// <summary> /// Stores the current object state for the given marker. /// </summary> /// <param name="marker">The marker which indicates at which point on the timeline the data is stored.</param> public void Mark(TimeMarker marker) { if (!IsAlive() && (m_CreationTime == null)) { return; } if (!IsAlive() && (m_DeletionTime == null)) { m_DeletionTime = marker; return; } foreach (var timeline in m_Members) { Debug.Assert(timeline != null, "One of the member timelines has not been initialized."); timeline.StoreCurrent(marker); } if ((m_Object != null) && (m_CreationTime == null)) { m_CreationTime = marker; } if (m_DeletionTime != null) { m_DeletionTime = null; } }
public void DeleteFromTimeline() { var id = new HistoryId(); var timeline = new ObjectTimeline <MockHistoryObject>(id, BuildStorageOfType, BuildObject); timeline.AddToTimeline(); var creationTime = new TimeMarker(1); timeline.Mark(creationTime); Assert.IsTrue(timeline.IsAlive()); Assert.AreEqual(creationTime, timeline.CreationTime); Assert.IsNull(timeline.DeletionTime); Assert.IsNotNull(timeline.Object); timeline.DeleteFromTimeline(); var deletionTime = new TimeMarker(2); timeline.Mark(deletionTime); Assert.IsFalse(timeline.IsAlive()); Assert.AreEqual(creationTime, timeline.CreationTime); Assert.AreEqual(deletionTime, timeline.DeletionTime); Assert.IsNull(timeline.Object); }
/// <summary> /// Stores the current state with the given name and the dependencies and returns the <see cref="TimeMarker"/> that /// belongs to this change set. /// </summary> /// <param name="name">The name for the state.</param> /// <param name="dependencies">The dependencies that indicate if the current change set can be rolled back or rolled forward.</param> /// <returns>The time marker for the stored state.</returns> public TimeMarker Mark(string name, IEnumerable <UpdateFromHistoryDependency> dependencies) { m_Current = !string.IsNullOrEmpty(name) ? m_Current.Next(name) : m_Current.Next(); MarkAtTime(m_Current, dependencies); return(m_Current); }
/// <summary> /// Rolls the current value back to the value stored with the given <see cref="TimeMarker"/>. /// </summary> /// <param name="marker">The marker that indicates to which point in the history the value should be restored to.</param> public void RollBackTo(TimeMarker marker) { if (m_CreationTime == null) { // The object doesn't exist and we're trying to roll-back even further. return; } if ((m_DeletionTime != null) && (marker > m_DeletionTime)) { // Rolling back to a time after we've already died. Do nothing return; } // Roll-back to a point in time before we existed if (marker < m_CreationTime) { RollBackToStart(); } else { RollBackToPointInTime(marker); } RaiseOnRollBack(); }
private void RollFowardDependencies(TimeMarker mark) { if (!m_Dependencies.IsAtEndOfTime()) { m_Dependencies.RollForwardTo(mark); } }
/// <summary> /// Stores the current value as the default value which will be returned if there are no values stored. /// </summary> /// <exception cref="CannotSetDefaultAfterStartOfTimeException"> /// Thrown when the user tries to store the default value after one or more value have been stored. /// </exception> public void SetCurrentAsDefault() { { Lokad.Enforce.With <CannotSetDefaultAfterStartOfTimeException>( m_Markers.LastValue == null, Resources.Exceptions_Messages_CannotSetDefaultAfterStartOfTime); } // All these objects have been created between the last mark and the new one. // They're about to become embedded in history forever. var newIds = new List <HistoryId>(m_NonMarkedObjectTimelines.Count); foreach (var pair in m_NonMarkedObjectTimelines) { m_ObjectTimelines.Add(pair.Key, pair.Value); newIds.Add(pair.Key); } m_NonMarkedObjectTimelines.Clear(); m_Markers.StoreCurrent(TimeMarker.TheBeginOfTime, null); if (newIds.Count > 0) { m_CreatedObjectHistory.StoreCurrent(TimeMarker.TheBeginOfTime, newIds); } foreach (var pair in m_ObjectTimelines) { pair.Value.SetCurrentAsDefault(); } m_Current = TimeMarker.TheBeginOfTime; m_Latest = TimeMarker.TheBeginOfTime; }
private void RollForwardMarkers(TimeMarker mark) { if (!m_Markers.IsAtEndOfTime()) { m_Markers.RollForwardTo(mark); } }
private void RollBackDependencies(TimeMarker mark) { if (!m_Dependencies.IsAtBeginOfTime()) { m_Dependencies.RollBackTo(mark); } }
private void RollBackMarkers(TimeMarker mark) { if (!m_Markers.IsAtBeginOfTime()) { m_Markers.RollBackTo(mark); } }
public void LargerThanOperatorWithFirstObjectSmaller() { var first = new TimeMarker(1); var second = new TimeMarker(2); Assert.IsFalse(first > second); }
/// <summary> /// Initializes a new instance of the <see cref="TimelineMarkEventArgs"/> class. /// </summary> /// <param name="marker">The new marker.</param> /// <exception cref="ArgumentNullException"> /// Thrown if <paramref name="marker"/> is <see langword="null" />. /// </exception> public TimelineMarkEventArgs(TimeMarker marker) { { Lokad.Enforce.Argument(() => marker); } m_Marker = marker; }