Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
1 change: 1 addition & 0 deletions Feature.Flags.props
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
<DefineConstants Condition="'$(IS_NET8_OR_HIGHER)' == '1'">$(DefineConstants);FEATURE_RANDOM_ITEMS</DefineConstants>
<DefineConstants Condition="'$(IS_NET8_OR_HIGHER)' == '1'">$(DefineConstants);FEATURE_COMPRESSION_STREAM</DefineConstants>
<DefineConstants Condition="'$(IS_NET8_OR_HIGHER)' == '1'">$(DefineConstants);FEATURE_STOPWATCH_GETELAPSEDTIME</DefineConstants>
<DefineConstants Condition="'$(IS_NET8_OR_HIGHER)' == '1'">$(DefineConstants);FEATURE_PERIODIC_TIMER</DefineConstants>
Comment thread
vbreuss marked this conversation as resolved.
<DefineConstants Condition="'$(IS_NET9_OR_HIGHER)' == '1'">$(DefineConstants);FEATURE_PATH_SPAN</DefineConstants>
<DefineConstants Condition="'$(IS_NET9_OR_HIGHER)' == '1'">$(DefineConstants);FEATURE_FILE_SPAN</DefineConstants>
<DefineConstants Condition="'$(IS_NET9_OR_HIGHER)' == '1'">$(DefineConstants);FEATURE_GUID_V7</DefineConstants>
Expand Down
7 changes: 7 additions & 0 deletions Source/Testably.Abstractions.Interface/ITimeSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@ public interface ITimeSystem
/// </summary>
IDateTime DateTime { get; }

#if FEATURE_PERIODIC_TIMER
/// <summary>
/// Abstractions for <see cref="System.Threading.PeriodicTimer" />.
/// </summary>
IPeriodicTimerFactory PeriodicTimer { get; }
#endif
Comment thread
vbreuss marked this conversation as resolved.

/// <summary>
/// Abstractions for <see cref="System.Diagnostics.Stopwatch" />.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#if FEATURE_PERIODIC_TIMER
using System;
using System.Threading;
using System.Threading.Tasks;

namespace Testably.Abstractions.TimeSystem;

/// <summary>
/// Abstractions for <see cref="PeriodicTimer" />.
/// </summary>
public interface IPeriodicTimer : ITimeSystemEntity, IDisposable
{
/// <inheritdoc cref="PeriodicTimer.Period" />
TimeSpan Period { get; set; }

/// <inheritdoc cref="PeriodicTimer.WaitForNextTickAsync(CancellationToken)" />
ValueTask<bool> WaitForNextTickAsync(CancellationToken cancellationToken = default);
}
#endif
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#if FEATURE_PERIODIC_TIMER
using System;
using System.Threading;

namespace Testably.Abstractions.TimeSystem;

/// <summary>
/// Factory for abstracting creation of <see cref="PeriodicTimer" />.
/// </summary>
public interface IPeriodicTimerFactory : ITimeSystemEntity
{
/// <inheritdoc cref="PeriodicTimer(TimeSpan)" />
IPeriodicTimer New(TimeSpan period);

/// <summary>
/// Wraps the <paramref name="timer" /> to the testable <see cref="IPeriodicTimer" />.
/// </summary>
IPeriodicTimer Wrap(PeriodicTimer timer);
}
#endif
10 changes: 10 additions & 0 deletions Source/Testably.Abstractions/RealTimeSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ public sealed class RealTimeSystem : ITimeSystem
public RealTimeSystem()
{
DateTime = new DateTimeWrapper(this);
#if FEATURE_PERIODIC_TIMER
PeriodicTimer = new PeriodicTimerFactory(this);
#endif
Stopwatch = new StopwatchFactory(this);
Task = new TaskWrapper(this);
Thread = new ThreadWrapper(this);
Expand All @@ -27,6 +30,13 @@ public RealTimeSystem()
/// <inheritdoc cref="ITimeSystem.DateTime" />
public IDateTime DateTime { get; }

#if FEATURE_PERIODIC_TIMER
/// <summary>
/// Abstractions for <see cref="System.Threading.PeriodicTimer" />.
/// </summary>
Comment thread
vbreuss marked this conversation as resolved.
Outdated
public IPeriodicTimerFactory PeriodicTimer { get; }
#endif

/// <inheritdoc cref="ITimeSystem.Stopwatch" />
public IStopwatchFactory Stopwatch { get; }

Expand Down
29 changes: 29 additions & 0 deletions Source/Testably.Abstractions/TimeSystem/PeriodicTimerFactory.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#if FEATURE_PERIODIC_TIMER
using System;
using System.Threading;

namespace Testably.Abstractions.TimeSystem;

internal sealed class PeriodicTimerFactory : IPeriodicTimerFactory
{
internal PeriodicTimerFactory(RealTimeSystem timeSystem)
{
TimeSystem = timeSystem;
}

#region IPeriodicTimerFactory Members

/// <inheritdoc cref="ITimeSystemEntity.TimeSystem" />
public ITimeSystem TimeSystem { get; }

/// <inheritdoc cref="IPeriodicTimerFactory.New(TimeSpan)" />
public IPeriodicTimer New(TimeSpan period)
=> Wrap(new PeriodicTimer(period));

/// <inheritdoc cref="IPeriodicTimerFactory.Wrap(PeriodicTimer)" />
public IPeriodicTimer Wrap(PeriodicTimer timer)
=> new PeriodicTimerWrapper(TimeSystem, timer);

#endregion
}
#endif
40 changes: 40 additions & 0 deletions Source/Testably.Abstractions/TimeSystem/PeriodicTimerWrapper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#if FEATURE_PERIODIC_TIMER
using System;
using System.Threading;
using System.Threading.Tasks;

namespace Testably.Abstractions.TimeSystem;

internal sealed class PeriodicTimerWrapper : IPeriodicTimer
{
private readonly PeriodicTimer _periodicTimer;

internal PeriodicTimerWrapper(ITimeSystem timeSystem, PeriodicTimer periodicTimer)
{
TimeSystem = timeSystem;
_periodicTimer = periodicTimer;
}

#region IPeriodicTimer Members

/// <inheritdoc cref="IPeriodicTimer.Period" />
public TimeSpan Period
{
get => _periodicTimer.Period;
set => _periodicTimer.Period = value;
}

/// <inheritdoc cref="ITimeSystemEntity.TimeSystem" />
public ITimeSystem TimeSystem { get; }

/// <inheritdoc cref="IDisposable.Dispose()" />
public void Dispose()
=> _periodicTimer.Dispose();

/// <inheritdoc cref="IPeriodicTimer.WaitForNextTickAsync(CancellationToken)" />
public ValueTask<bool> WaitForNextTickAsync(CancellationToken cancellationToken = default)
=> _periodicTimer.WaitForNextTickAsync(cancellationToken);

#endregion
}
#endif
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ namespace Testably.Abstractions
{
public RealTimeSystem() { }
public Testably.Abstractions.TimeSystem.IDateTime DateTime { get; }
public Testably.Abstractions.TimeSystem.IPeriodicTimerFactory PeriodicTimer { get; }
public Testably.Abstractions.TimeSystem.IStopwatchFactory Stopwatch { get; }
public Testably.Abstractions.TimeSystem.ITask Task { get; }
public Testably.Abstractions.TimeSystem.IThread Thread { get; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ namespace Testably.Abstractions
{
public RealTimeSystem() { }
public Testably.Abstractions.TimeSystem.IDateTime DateTime { get; }
public Testably.Abstractions.TimeSystem.IPeriodicTimerFactory PeriodicTimer { get; }
public Testably.Abstractions.TimeSystem.IStopwatchFactory Stopwatch { get; }
public Testably.Abstractions.TimeSystem.ITask Task { get; }
public Testably.Abstractions.TimeSystem.IThread Thread { get; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ namespace Testably.Abstractions
{
public RealTimeSystem() { }
public Testably.Abstractions.TimeSystem.IDateTime DateTime { get; }
public Testably.Abstractions.TimeSystem.IPeriodicTimerFactory PeriodicTimer { get; }
public Testably.Abstractions.TimeSystem.IStopwatchFactory Stopwatch { get; }
public Testably.Abstractions.TimeSystem.ITask Task { get; }
public Testably.Abstractions.TimeSystem.IThread Thread { get; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ namespace Testably.Abstractions
public interface ITimeSystem
{
Testably.Abstractions.TimeSystem.IDateTime DateTime { get; }
Testably.Abstractions.TimeSystem.IPeriodicTimerFactory PeriodicTimer { get; }
Testably.Abstractions.TimeSystem.IStopwatchFactory Stopwatch { get; }
Testably.Abstractions.TimeSystem.ITask Task { get; }
Testably.Abstractions.TimeSystem.IThread Thread { get; }
Expand Down Expand Up @@ -141,6 +142,16 @@ namespace Testably.Abstractions.TimeSystem
System.DateTime UnixEpoch { get; }
System.DateTime UtcNow { get; }
}
public interface IPeriodicTimer : System.IDisposable, Testably.Abstractions.TimeSystem.ITimeSystemEntity
{
System.TimeSpan Period { get; set; }
System.Threading.Tasks.ValueTask<bool> WaitForNextTickAsync(System.Threading.CancellationToken cancellationToken = default);
}
public interface IPeriodicTimerFactory : Testably.Abstractions.TimeSystem.ITimeSystemEntity
{
Testably.Abstractions.TimeSystem.IPeriodicTimer New(System.TimeSpan period);
Testably.Abstractions.TimeSystem.IPeriodicTimer Wrap(System.Threading.PeriodicTimer timer);
}
public interface IStopwatch : Testably.Abstractions.TimeSystem.ITimeSystemEntity
{
System.TimeSpan Elapsed { get; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ namespace Testably.Abstractions
public interface ITimeSystem
{
Testably.Abstractions.TimeSystem.IDateTime DateTime { get; }
Testably.Abstractions.TimeSystem.IPeriodicTimerFactory PeriodicTimer { get; }
Testably.Abstractions.TimeSystem.IStopwatchFactory Stopwatch { get; }
Testably.Abstractions.TimeSystem.ITask Task { get; }
Testably.Abstractions.TimeSystem.IThread Thread { get; }
Expand Down Expand Up @@ -123,6 +124,16 @@ namespace Testably.Abstractions.TimeSystem
System.DateTime UnixEpoch { get; }
System.DateTime UtcNow { get; }
}
public interface IPeriodicTimer : System.IDisposable, Testably.Abstractions.TimeSystem.ITimeSystemEntity
{
System.TimeSpan Period { get; set; }
System.Threading.Tasks.ValueTask<bool> WaitForNextTickAsync(System.Threading.CancellationToken cancellationToken = default);
}
public interface IPeriodicTimerFactory : Testably.Abstractions.TimeSystem.ITimeSystemEntity
{
Testably.Abstractions.TimeSystem.IPeriodicTimer New(System.TimeSpan period);
Testably.Abstractions.TimeSystem.IPeriodicTimer Wrap(System.Threading.PeriodicTimer timer);
}
public interface IStopwatch : Testably.Abstractions.TimeSystem.ITimeSystemEntity
{
System.TimeSpan Elapsed { get; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ namespace Testably.Abstractions
public interface ITimeSystem
{
Testably.Abstractions.TimeSystem.IDateTime DateTime { get; }
Testably.Abstractions.TimeSystem.IPeriodicTimerFactory PeriodicTimer { get; }
Testably.Abstractions.TimeSystem.IStopwatchFactory Stopwatch { get; }
Testably.Abstractions.TimeSystem.ITask Task { get; }
Testably.Abstractions.TimeSystem.IThread Thread { get; }
Expand Down Expand Up @@ -127,6 +128,16 @@ namespace Testably.Abstractions.TimeSystem
System.DateTime UnixEpoch { get; }
System.DateTime UtcNow { get; }
}
public interface IPeriodicTimer : System.IDisposable, Testably.Abstractions.TimeSystem.ITimeSystemEntity
{
System.TimeSpan Period { get; set; }
System.Threading.Tasks.ValueTask<bool> WaitForNextTickAsync(System.Threading.CancellationToken cancellationToken = default);
}
public interface IPeriodicTimerFactory : Testably.Abstractions.TimeSystem.ITimeSystemEntity
{
Testably.Abstractions.TimeSystem.IPeriodicTimer New(System.TimeSpan period);
Testably.Abstractions.TimeSystem.IPeriodicTimer Wrap(System.Threading.PeriodicTimer timer);
}
public interface IStopwatch : Testably.Abstractions.TimeSystem.ITimeSystemEntity
{
System.TimeSpan Elapsed { get; }
Expand Down
35 changes: 22 additions & 13 deletions Tests/Testably.Abstractions.Parity.Tests/ParityTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,8 @@ namespace Testably.Abstractions.Parity.Tests;
public abstract class ParityTests(
TestHelpers.Parity parity)
{
#region Test Setup

public TestHelpers.Parity Parity { get; } = parity;

#endregion

[Test]
public async Task IDirectory_EnsureParityWith_Directory()
{
Expand Down Expand Up @@ -121,23 +117,25 @@ public async Task IPath_EnsureParityWith_Path()
await That(parityErrors).IsEmpty();
}

#if FEATURE_PERIODIC_TIMER
[Test]
public async Task IRandomAndIRandomFactory_EnsureParityWith_Random()
public async Task
IPeriodicTimerAndIPeriodicTimerFactory_EnsureParityWith_PeriodicTimer()
{
List<string> parityErrors = Parity.Random
.GetErrorsToInstanceType<IRandom, IRandomFactory>(
typeof(Random));
List<string> parityErrors = Parity.PeriodicTimer
.GetErrorsToInstanceType<IPeriodicTimer, IPeriodicTimerFactory>(
typeof(PeriodicTimer));

await That(parityErrors).IsEmpty();
}
#endif

[Test]
public async Task
ITimerAndITimerFactory_EnsureParityWith_Timer()
public async Task IRandomAndIRandomFactory_EnsureParityWith_Random()
{
List<string> parityErrors = Parity.Timer
.GetErrorsToInstanceType<ITimer, ITimerFactory>(
typeof(Timer));
List<string> parityErrors = Parity.Random
.GetErrorsToInstanceType<IRandom, IRandomFactory>(
typeof(Random));

await That(parityErrors).IsEmpty();
}
Expand All @@ -156,6 +154,17 @@ public async Task
await That(parityErrors).IsEmpty();
}

[Test]
public async Task
ITimerAndITimerFactory_EnsureParityWith_Timer()
{
List<string> parityErrors = Parity.Timer
.GetErrorsToInstanceType<ITimer, ITimerFactory>(
typeof(Timer));

await That(parityErrors).IsEmpty();
}

[Test]
public async Task IZipArchive_EnsureParityWith_ZipArchive()
{
Expand Down
10 changes: 10 additions & 0 deletions Tests/Testably.Abstractions.Parity.Tests/TestHelpers/Parity.cs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,16 @@ public class Parity
#pragma warning restore CS0618
});

#if FEATURE_PERIODIC_TIMER
public ParityCheck PeriodicTimer { get; } = new(excludeConstructors:
[
typeof(PeriodicTimer).GetConstructor([
typeof(TimeSpan),
typeof(TimeProvider),
]),
]);
#endif

public ParityCheck Random { get; } = new();

public ParityCheck Stopwatch { get; } = new(excludeMethods:
Expand Down
Loading