Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 50 additions & 6 deletions Source/Testably.Abstractions.Testing/MockTimeSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,28 @@ public INotificationHandler On
/// <summary>
/// Initializes the <see cref="MockTimeSystem" /> with a random time.
/// </summary>
public MockTimeSystem() : this(Testing.TimeProvider.Random())
public MockTimeSystem() : this(Testing.TimeProvider.Random(), options => options)
{
}

/// <summary>
/// Initializes the <see cref="MockTimeSystem" /> with a random time.
/// </summary>
public MockTimeSystem(Func<MockTimeSystemOptions, MockTimeSystemOptions> options) : this(Testing.TimeProvider.Random(), options)
{
}

/// <summary>
/// Initializes the <see cref="MockTimeSystem" /> with the specified <paramref name="time" />.
/// </summary>
public MockTimeSystem(DateTime time) : this(Testing.TimeProvider.Use(time), options => options)
{
}

/// <summary>
/// Initializes the <see cref="MockTimeSystem" /> with the specified <paramref name="time" />.
/// </summary>
public MockTimeSystem(DateTime time) : this(Testing.TimeProvider.Use(time))
public MockTimeSystem(DateTime time, Func<MockTimeSystemOptions, MockTimeSystemOptions> options) : this(Testing.TimeProvider.Use(time), options)
{
}

Expand All @@ -65,16 +79,26 @@ public MockTimeSystem(ITimeProvider timeProvider) : this(
/// <summary>
/// Initializes the <see cref="MockTimeSystem" /> with the specified <paramref name="timeProvider" />.
/// </summary>
public MockTimeSystem(ITimeProviderFactory timeProvider)
public MockTimeSystem(ITimeProviderFactory timeProvider) : this(timeProvider, options => options)
{
}

/// <summary>
/// Initializes the <see cref="MockTimeSystem" /> with the specified <paramref name="timeProvider" /> and the given <paramref name="options" />.
/// </summary>
public MockTimeSystem(ITimeProviderFactory timeProvider, Func<MockTimeSystemOptions, MockTimeSystemOptions> options)
{
MockTimeSystemOptions initialization = new();
initialization = options(initialization);

_callbackHandler = new NotificationHandler(this);
TimeProvider = timeProvider.Create(_callbackHandler.InvokeTimeChanged);
_dateTimeMock = new DateTimeMock(this, _callbackHandler);
_stopwatchFactoryMock = new StopwatchFactoryMock(this);
_threadMock = new ThreadMock(this, _callbackHandler);
_taskMock = new TaskMock(this, _callbackHandler);
_threadMock = new ThreadMock(this, _callbackHandler, initialization.AutoAdvance);
_taskMock = new TaskMock(this, _callbackHandler, initialization.AutoAdvance);
#if FEATURE_PERIODIC_TIMER
_periodicTimerFactoryMock = new PeriodicTimerFactoryMock(this);
_periodicTimerFactoryMock = new PeriodicTimerFactoryMock(this, initialization.AutoAdvance);
#endif
_timerFactoryMock = new TimerFactoryMock(this);
}
Expand Down Expand Up @@ -122,4 +146,24 @@ public MockTimeSystem WithTimerStrategy(ITimerStrategy timerStrategy)
_timerFactoryMock.SetTimerStrategy(timerStrategy);
return this;
}

/// <summary>
/// The initialization options for the <see cref="MockTimeSystem" />.
/// </summary>
public class MockTimeSystemOptions
{
/// <summary>
/// Flag indicating if the time should automatically be advanced when waiting for timers, tasks or threads to complete.
/// </summary>
internal bool AutoAdvance { get; private set; } = true;

/// <summary>
/// Disables automatic advancement of the time when waiting for timers, tasks or threads to complete.
/// </summary>
public MockTimeSystemOptions DisableAutoAdvance()
{
AutoAdvance = false;
return this;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@ namespace Testably.Abstractions.Testing.TimeSystem;
internal sealed class PeriodicTimerFactoryMock : IPeriodicTimerFactory
{
private readonly MockTimeSystem _mockTimeSystem;
private readonly bool _autoAdvance;

internal PeriodicTimerFactoryMock(MockTimeSystem timeSystem)
internal PeriodicTimerFactoryMock(MockTimeSystem timeSystem, bool autoAdvance)
{
_mockTimeSystem = timeSystem;
_autoAdvance = autoAdvance;
}

#region IPeriodicTimerFactory Members
Expand All @@ -22,7 +24,7 @@ internal PeriodicTimerFactoryMock(MockTimeSystem timeSystem)

/// <inheritdoc cref="IPeriodicTimerFactory.New(TimeSpan)" />
public IPeriodicTimer New(TimeSpan period)
=> new PeriodicTimerMock(_mockTimeSystem, period);
=> new PeriodicTimerMock(_mockTimeSystem, period, _autoAdvance);

/// <inheritdoc cref="IPeriodicTimerFactory.Wrap(PeriodicTimer)" />
public IPeriodicTimer Wrap(PeriodicTimer timer)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,15 @@ internal sealed class PeriodicTimerMock : IPeriodicTimer
private bool _isDisposed;
private DateTime _lastTime;
private readonly MockTimeSystem _timeSystem;
private readonly bool _autoAdvance;

internal PeriodicTimerMock(MockTimeSystem timeSystem,
TimeSpan period)
TimeSpan period, bool autoAdvance)
{
ThrowIfPeriodIsInvalid(period, nameof(period));

_timeSystem = timeSystem;
_autoAdvance = autoAdvance;
_lastTime = _timeSystem.DateTime.UtcNow;
Period = period;
}
Expand Down Expand Up @@ -60,8 +62,20 @@ public void Dispose()
DateTime nextTime = _lastTime + Period;
if (nextTime > now)
{
_timeSystem.TimeProvider.AdvanceBy(nextTime - now);
_lastTime = nextTime;
if (_autoAdvance)
{
_timeSystem.TimeProvider.AdvanceBy(nextTime - now);
_lastTime = nextTime;
}
else
{
using var onTimeChanged = _timeSystem.On
.TimeChanged(predicate: t => t >= nextTime);
await onTimeChanged.WaitAsync(
timeout: Timeout.InfiniteTimeSpan,
cancellationToken: cancellationToken).ConfigureAwait(false);
_lastTime = _timeSystem.DateTime.UtcNow;
}
}
else
{
Expand Down
11 changes: 9 additions & 2 deletions Source/Testably.Abstractions.Testing/TimeSystem/TaskMock.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,17 @@ namespace Testably.Abstractions.Testing.TimeSystem;

internal sealed class TaskMock : ITask
{
private readonly bool _autoAdvance;
private readonly NotificationHandler _callbackHandler;
private readonly MockTimeSystem _mockTimeSystem;

internal TaskMock(MockTimeSystem timeSystem,
NotificationHandler callbackHandler)
NotificationHandler callbackHandler,
bool autoAdvance)
{
_mockTimeSystem = timeSystem;
_callbackHandler = callbackHandler;
_autoAdvance = autoAdvance;
}

#region ITask Members
Expand Down Expand Up @@ -53,7 +56,11 @@ public Task Delay(TimeSpan delay, CancellationToken cancellationToken)
throw ExceptionFactory.TaskWasCanceled();
}

_mockTimeSystem.TimeProvider.AdvanceBy(delay);
if (_autoAdvance)
{
_mockTimeSystem.TimeProvider.AdvanceBy(delay);
}

_callbackHandler.InvokeTaskDelayCallbacks(delay);
return Task.CompletedTask;
}
Expand Down
11 changes: 9 additions & 2 deletions Source/Testably.Abstractions.Testing/TimeSystem/ThreadMock.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,17 @@ namespace Testably.Abstractions.Testing.TimeSystem;

internal sealed class ThreadMock : IThread
{
private readonly bool _autoAdvance;
private readonly NotificationHandler _callbackHandler;
private readonly MockTimeSystem _mockTimeSystem;

internal ThreadMock(MockTimeSystem timeSystem,
NotificationHandler callbackHandler)
NotificationHandler callbackHandler,
bool autoAdvance)
{
_mockTimeSystem = timeSystem;
_callbackHandler = callbackHandler;
_autoAdvance = autoAdvance;
}

#region IThread Members
Expand All @@ -33,7 +36,11 @@ public void Sleep(TimeSpan timeout)
throw ExceptionFactory.ThreadSleepOutOfRange(nameof(timeout));
}

_mockTimeSystem.TimeProvider.AdvanceBy(timeout);
if (_autoAdvance)
{
_mockTimeSystem.TimeProvider.AdvanceBy(timeout);
}

Thread.Yield();
_callbackHandler.InvokeThreadSleepCallbacks(timeout);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,11 @@ namespace Testably.Abstractions.Testing
{
public MockTimeSystem() { }
public MockTimeSystem(System.DateTime time) { }
public MockTimeSystem(System.Func<Testably.Abstractions.Testing.MockTimeSystem.MockTimeSystemOptions, Testably.Abstractions.Testing.MockTimeSystem.MockTimeSystemOptions> options) { }
public MockTimeSystem(Testably.Abstractions.Testing.TimeSystem.ITimeProvider timeProvider) { }
public MockTimeSystem(Testably.Abstractions.Testing.TimeSystem.ITimeProviderFactory timeProvider) { }
public MockTimeSystem(System.DateTime time, System.Func<Testably.Abstractions.Testing.MockTimeSystem.MockTimeSystemOptions, Testably.Abstractions.Testing.MockTimeSystem.MockTimeSystemOptions> options) { }
public MockTimeSystem(Testably.Abstractions.Testing.TimeSystem.ITimeProviderFactory timeProvider, System.Func<Testably.Abstractions.Testing.MockTimeSystem.MockTimeSystemOptions, Testably.Abstractions.Testing.MockTimeSystem.MockTimeSystemOptions> options) { }
public Testably.Abstractions.TimeSystem.IDateTime DateTime { get; }
public Testably.Abstractions.Testing.TimeSystem.INotificationHandler On { get; }
public Testably.Abstractions.TimeSystem.IPeriodicTimerFactory PeriodicTimer { get; }
Expand All @@ -115,6 +118,11 @@ namespace Testably.Abstractions.Testing
public Testably.Abstractions.Testing.TimeSystem.ITimerHandler TimerHandler { get; }
public override string ToString() { }
public Testably.Abstractions.Testing.MockTimeSystem WithTimerStrategy(Testably.Abstractions.Testing.TimeSystem.ITimerStrategy timerStrategy) { }
public class MockTimeSystemOptions
{
public MockTimeSystemOptions() { }
public Testably.Abstractions.Testing.MockTimeSystem.MockTimeSystemOptions DisableAutoAdvance() { }
}
}
public static class Notification
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,11 @@ namespace Testably.Abstractions.Testing
{
public MockTimeSystem() { }
public MockTimeSystem(System.DateTime time) { }
public MockTimeSystem(System.Func<Testably.Abstractions.Testing.MockTimeSystem.MockTimeSystemOptions, Testably.Abstractions.Testing.MockTimeSystem.MockTimeSystemOptions> options) { }
public MockTimeSystem(Testably.Abstractions.Testing.TimeSystem.ITimeProvider timeProvider) { }
public MockTimeSystem(Testably.Abstractions.Testing.TimeSystem.ITimeProviderFactory timeProvider) { }
public MockTimeSystem(System.DateTime time, System.Func<Testably.Abstractions.Testing.MockTimeSystem.MockTimeSystemOptions, Testably.Abstractions.Testing.MockTimeSystem.MockTimeSystemOptions> options) { }
public MockTimeSystem(Testably.Abstractions.Testing.TimeSystem.ITimeProviderFactory timeProvider, System.Func<Testably.Abstractions.Testing.MockTimeSystem.MockTimeSystemOptions, Testably.Abstractions.Testing.MockTimeSystem.MockTimeSystemOptions> options) { }
public Testably.Abstractions.TimeSystem.IDateTime DateTime { get; }
public Testably.Abstractions.Testing.TimeSystem.INotificationHandler On { get; }
public Testably.Abstractions.TimeSystem.IStopwatchFactory Stopwatch { get; }
Expand All @@ -113,6 +116,11 @@ namespace Testably.Abstractions.Testing
public Testably.Abstractions.Testing.TimeSystem.ITimerHandler TimerHandler { get; }
public override string ToString() { }
public Testably.Abstractions.Testing.MockTimeSystem WithTimerStrategy(Testably.Abstractions.Testing.TimeSystem.ITimerStrategy timerStrategy) { }
public class MockTimeSystemOptions
{
public MockTimeSystemOptions() { }
public Testably.Abstractions.Testing.MockTimeSystem.MockTimeSystemOptions DisableAutoAdvance() { }
}
}
public static class Notification
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,11 @@ namespace Testably.Abstractions.Testing
{
public MockTimeSystem() { }
public MockTimeSystem(System.DateTime time) { }
public MockTimeSystem(System.Func<Testably.Abstractions.Testing.MockTimeSystem.MockTimeSystemOptions, Testably.Abstractions.Testing.MockTimeSystem.MockTimeSystemOptions> options) { }
public MockTimeSystem(Testably.Abstractions.Testing.TimeSystem.ITimeProvider timeProvider) { }
public MockTimeSystem(Testably.Abstractions.Testing.TimeSystem.ITimeProviderFactory timeProvider) { }
public MockTimeSystem(System.DateTime time, System.Func<Testably.Abstractions.Testing.MockTimeSystem.MockTimeSystemOptions, Testably.Abstractions.Testing.MockTimeSystem.MockTimeSystemOptions> options) { }
public MockTimeSystem(Testably.Abstractions.Testing.TimeSystem.ITimeProviderFactory timeProvider, System.Func<Testably.Abstractions.Testing.MockTimeSystem.MockTimeSystemOptions, Testably.Abstractions.Testing.MockTimeSystem.MockTimeSystemOptions> options) { }
public Testably.Abstractions.TimeSystem.IDateTime DateTime { get; }
public Testably.Abstractions.Testing.TimeSystem.INotificationHandler On { get; }
public Testably.Abstractions.TimeSystem.IPeriodicTimerFactory PeriodicTimer { get; }
Expand All @@ -115,6 +118,11 @@ namespace Testably.Abstractions.Testing
public Testably.Abstractions.Testing.TimeSystem.ITimerHandler TimerHandler { get; }
public override string ToString() { }
public Testably.Abstractions.Testing.MockTimeSystem WithTimerStrategy(Testably.Abstractions.Testing.TimeSystem.ITimerStrategy timerStrategy) { }
public class MockTimeSystemOptions
{
public MockTimeSystemOptions() { }
public Testably.Abstractions.Testing.MockTimeSystem.MockTimeSystemOptions DisableAutoAdvance() { }
}
}
public static class Notification
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,11 @@ namespace Testably.Abstractions.Testing
{
public MockTimeSystem() { }
public MockTimeSystem(System.DateTime time) { }
public MockTimeSystem(System.Func<Testably.Abstractions.Testing.MockTimeSystem.MockTimeSystemOptions, Testably.Abstractions.Testing.MockTimeSystem.MockTimeSystemOptions> options) { }
public MockTimeSystem(Testably.Abstractions.Testing.TimeSystem.ITimeProvider timeProvider) { }
public MockTimeSystem(Testably.Abstractions.Testing.TimeSystem.ITimeProviderFactory timeProvider) { }
public MockTimeSystem(System.DateTime time, System.Func<Testably.Abstractions.Testing.MockTimeSystem.MockTimeSystemOptions, Testably.Abstractions.Testing.MockTimeSystem.MockTimeSystemOptions> options) { }
public MockTimeSystem(Testably.Abstractions.Testing.TimeSystem.ITimeProviderFactory timeProvider, System.Func<Testably.Abstractions.Testing.MockTimeSystem.MockTimeSystemOptions, Testably.Abstractions.Testing.MockTimeSystem.MockTimeSystemOptions> options) { }
public Testably.Abstractions.TimeSystem.IDateTime DateTime { get; }
public Testably.Abstractions.Testing.TimeSystem.INotificationHandler On { get; }
public Testably.Abstractions.TimeSystem.IPeriodicTimerFactory PeriodicTimer { get; }
Expand All @@ -115,6 +118,11 @@ namespace Testably.Abstractions.Testing
public Testably.Abstractions.Testing.TimeSystem.ITimerHandler TimerHandler { get; }
public override string ToString() { }
public Testably.Abstractions.Testing.MockTimeSystem WithTimerStrategy(Testably.Abstractions.Testing.TimeSystem.ITimerStrategy timerStrategy) { }
public class MockTimeSystemOptions
{
public MockTimeSystemOptions() { }
public Testably.Abstractions.Testing.MockTimeSystem.MockTimeSystemOptions DisableAutoAdvance() { }
}
}
public static class Notification
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,11 @@ namespace Testably.Abstractions.Testing
{
public MockTimeSystem() { }
public MockTimeSystem(System.DateTime time) { }
public MockTimeSystem(System.Func<Testably.Abstractions.Testing.MockTimeSystem.MockTimeSystemOptions, Testably.Abstractions.Testing.MockTimeSystem.MockTimeSystemOptions> options) { }
public MockTimeSystem(Testably.Abstractions.Testing.TimeSystem.ITimeProvider timeProvider) { }
public MockTimeSystem(Testably.Abstractions.Testing.TimeSystem.ITimeProviderFactory timeProvider) { }
public MockTimeSystem(System.DateTime time, System.Func<Testably.Abstractions.Testing.MockTimeSystem.MockTimeSystemOptions, Testably.Abstractions.Testing.MockTimeSystem.MockTimeSystemOptions> options) { }
public MockTimeSystem(Testably.Abstractions.Testing.TimeSystem.ITimeProviderFactory timeProvider, System.Func<Testably.Abstractions.Testing.MockTimeSystem.MockTimeSystemOptions, Testably.Abstractions.Testing.MockTimeSystem.MockTimeSystemOptions> options) { }
public Testably.Abstractions.TimeSystem.IDateTime DateTime { get; }
public Testably.Abstractions.Testing.TimeSystem.INotificationHandler On { get; }
public Testably.Abstractions.TimeSystem.IStopwatchFactory Stopwatch { get; }
Expand All @@ -108,6 +111,11 @@ namespace Testably.Abstractions.Testing
public Testably.Abstractions.Testing.TimeSystem.ITimerHandler TimerHandler { get; }
public override string ToString() { }
public Testably.Abstractions.Testing.MockTimeSystem WithTimerStrategy(Testably.Abstractions.Testing.TimeSystem.ITimerStrategy timerStrategy) { }
public class MockTimeSystemOptions
{
public MockTimeSystemOptions() { }
public Testably.Abstractions.Testing.MockTimeSystem.MockTimeSystemOptions DisableAutoAdvance() { }
}
}
public static class Notification
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,11 @@ namespace Testably.Abstractions.Testing
{
public MockTimeSystem() { }
public MockTimeSystem(System.DateTime time) { }
public MockTimeSystem(System.Func<Testably.Abstractions.Testing.MockTimeSystem.MockTimeSystemOptions, Testably.Abstractions.Testing.MockTimeSystem.MockTimeSystemOptions> options) { }
public MockTimeSystem(Testably.Abstractions.Testing.TimeSystem.ITimeProvider timeProvider) { }
public MockTimeSystem(Testably.Abstractions.Testing.TimeSystem.ITimeProviderFactory timeProvider) { }
public MockTimeSystem(System.DateTime time, System.Func<Testably.Abstractions.Testing.MockTimeSystem.MockTimeSystemOptions, Testably.Abstractions.Testing.MockTimeSystem.MockTimeSystemOptions> options) { }
public MockTimeSystem(Testably.Abstractions.Testing.TimeSystem.ITimeProviderFactory timeProvider, System.Func<Testably.Abstractions.Testing.MockTimeSystem.MockTimeSystemOptions, Testably.Abstractions.Testing.MockTimeSystem.MockTimeSystemOptions> options) { }
public Testably.Abstractions.TimeSystem.IDateTime DateTime { get; }
public Testably.Abstractions.Testing.TimeSystem.INotificationHandler On { get; }
public Testably.Abstractions.TimeSystem.IStopwatchFactory Stopwatch { get; }
Expand All @@ -108,6 +111,11 @@ namespace Testably.Abstractions.Testing
public Testably.Abstractions.Testing.TimeSystem.ITimerHandler TimerHandler { get; }
public override string ToString() { }
public Testably.Abstractions.Testing.MockTimeSystem WithTimerStrategy(Testably.Abstractions.Testing.TimeSystem.ITimerStrategy timerStrategy) { }
public class MockTimeSystemOptions
{
public MockTimeSystemOptions() { }
public Testably.Abstractions.Testing.MockTimeSystem.MockTimeSystemOptions DisableAutoAdvance() { }
}
}
public static class Notification
{
Expand Down
Loading
Loading