Skip to content

Commit

Permalink
Merge branch 'main' into topic/add-global-json
Browse files Browse the repository at this point in the history
  • Loading branch information
vbreuss authored Mar 10, 2024
2 parents 41a04a9 + 7474abc commit 37c262b
Show file tree
Hide file tree
Showing 7 changed files with 77 additions and 62 deletions.
Original file line number Diff line number Diff line change
@@ -1,19 +1,13 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;

namespace Testably.Abstractions.Testing.Statistics;

internal class CallStatistics : IStatistics
{
private readonly IStatisticsGate _statisticsGate;
private readonly ConcurrentDictionary<int, MethodStatistic> _calls = new();
public IReadOnlyDictionary<int, MethodStatistic> Methods
#if NET7_0_OR_GREATER
=> _calls.AsReadOnly();
#else
=> _calls;
#endif
private readonly ConcurrentQueue<MethodStatistic> _calls = new();
public MethodStatistic[] Methods => _calls.ToArray();

public CallStatistics(IStatisticsGate statisticsGate)
{
Expand All @@ -29,7 +23,7 @@ internal IDisposable Register(string name, params ParameterDescription[] paramet
if (_statisticsGate.TryGetLock(out IDisposable release))
{
int counter = _statisticsGate.GetCounter();
_calls[counter] = new MethodStatistic(name, parameters);
_calls.Enqueue(new MethodStatistic(counter, name, parameters));
}

return release;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,5 @@ public interface IStatistics
/// <summary>
/// Lists all called mocked methods.
/// </summary>
IReadOnlyDictionary<int, MethodStatistic> Methods { get; }
MethodStatistic[] Methods { get; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ namespace Testably.Abstractions.Testing.Statistics;
/// </summary>
public sealed class MethodStatistic
{
/// <summary>
/// The global counter value to determine the order of calls.
/// </summary>
public int Counter { get; }

/// <summary>
/// The name of the called method.
/// </summary>
Expand All @@ -17,8 +22,9 @@ public sealed class MethodStatistic
/// </summary>
public ParameterDescription[] Parameters { get; }

internal MethodStatistic(string name, ParameterDescription[] parameters)
internal MethodStatistic(int counter, string name, ParameterDescription[] parameters)
{
Counter = counter;
Name = name;
Parameters = parameters;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,8 @@ public void EndRead_IAsyncResult_ShouldRegisterCall()

fileStream.EndRead(asyncResult);

sut.Statistics.FileStream["foo"].Methods.Count.Should().Be(2);
sut.Statistics.FileStream["foo"].Methods.Values.Should()
sut.Statistics.FileStream["foo"].Methods.Length.Should().Be(2);
sut.Statistics.FileStream["foo"].Methods.Should()
.ContainSingle(c => c.Name == nameof(FileSystemStream.EndRead) &&
c.Parameters.Length == 1 &&
c.Parameters[0].Is(asyncResult));
Expand All @@ -98,8 +98,8 @@ public void EndWrite_IAsyncResult_ShouldRegisterCall()

fileStream.EndWrite(asyncResult);

sut.Statistics.FileStream["foo"].Methods.Count.Should().Be(2);
sut.Statistics.FileStream["foo"].Methods.Values.Should()
sut.Statistics.FileStream["foo"].Methods.Length.Should().Be(2);
sut.Statistics.FileStream["foo"].Methods.Should()
.ContainSingle(c => c.Name == nameof(FileSystemStream.EndWrite) &&
c.Parameters.Length == 1 &&
c.Parameters[0].Is(asyncResult));
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
namespace Testably.Abstractions.Testing.Tests.Statistics;
using System.Linq;

namespace Testably.Abstractions.Testing.Tests.Statistics;

public sealed class MethodStatisticsTests
{
Expand All @@ -8,7 +10,7 @@ public void ToString_ShouldContainName()
MockFileSystem sut = new();
sut.Directory.CreateDirectory("foo");

string result = sut.Statistics.Directory.Methods[1].ToString();
string result = sut.Statistics.Directory.Methods.First().ToString();

result.Should()
.Contain(nameof(IDirectory.CreateDirectory)).And
Expand All @@ -22,7 +24,7 @@ public void ToString_ShouldContainParameters()
MockFileSystem sut = new();
sut.File.WriteAllText("foo", "bar");

string result = sut.Statistics.File.Methods[1].ToString();
string result = sut.Statistics.File.Methods.First().ToString();

result.Should()
.Contain(nameof(IFile.WriteAllText)).And
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Testably.Abstractions.Testing.Statistics;
using Testably.Abstractions.Testing.Tests.Statistics.FileSystem;
using Testably.Abstractions.Testing.Tests.TestHelpers;

Expand Down Expand Up @@ -37,14 +38,14 @@ public async Task Statistics_ShouldSupportParallelCalls()

foreach (string directory in directories)
{
sut.Statistics.Directory.Methods.Values
sut.Statistics.Directory.Methods
.Should().ContainSingle(x =>
x.Name == nameof(Directory.CreateDirectory) &&
x.Parameters.Length == 1 &&
x.Parameters[0].Is(directory));
}

sut.Statistics.Directory.Methods.Keys.Should()
sut.Statistics.Directory.Methods.Select(x => x.Counter).Should()
.BeEquivalentTo(Enumerable.Range(1, directories.Length));
}

Expand All @@ -63,7 +64,7 @@ public void Statistics_ShouldIncrementCallOrder()

for (int i = 0; i < directories.Length; i++)
{
sut.Statistics.Directory.Methods[i + 1]
sut.Statistics.Directory.Methods[i]
.Parameters[0].Is(directories[i]).Should().BeTrue();
}
}
Expand All @@ -84,10 +85,10 @@ public void Statistics_ShouldKeepCallOrder()
for (int i = 0; i < directories.Length; i++)
{
sut.Statistics.Directory.Methods
.OrderBy(x => x.Key)
.OrderBy(x => x.Counter)
.Skip(i)
.First()
.Value.Parameters[0].Is(directories[i]).Should().BeTrue();
.Parameters[0].Is(directories[i]).Should().BeTrue();
}
}

Expand All @@ -101,11 +102,23 @@ public void Statistics_ShouldUseGlobalIncrement()
using FileSystemStream stream = fileInfo.Open(FileMode.Open, FileAccess.Read);
_ = new StreamReader(stream).ReadToEnd();

sut.Statistics.Directory.Methods[1].Name.Should().Be(nameof(IDirectory.CreateDirectory));
sut.Statistics.File.Methods[2].Name.Should().Be(nameof(IFile.WriteAllText));
sut.Statistics.FileInfo.Methods[3].Name.Should().Be(nameof(IFileInfoFactory.New));
// Note: Index 4 ist used internally for creating the full path of the file info.
sut.Statistics.FileInfo["bar.txt"].Methods[5].Name.Should().Be(nameof(IFileInfo.Open));
sut.Statistics.Directory.Methods.First()
.Should().Match<MethodStatistic>(m =>
m.Name == nameof(IDirectory.CreateDirectory) &&
m.Counter == 1);
sut.Statistics.File.Methods.First()
.Should().Match<MethodStatistic>(m =>
m.Name == nameof(IFile.WriteAllText) &&
m.Counter == 2);
sut.Statistics.FileInfo.Methods.First()
.Should().Match<MethodStatistic>(m =>
m.Name == nameof(IFileInfoFactory.New) &&
m.Counter == 3);
sut.Statistics.FileInfo["bar.txt"].Methods.First()
.Should().Match<MethodStatistic>(m =>
m.Name == nameof(IFileInfo.Open) &&
// Note: Index 4 could be used internally for creating the full path of the file info.
m.Counter >= 4);
}

[Fact]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,26 +8,26 @@ public static class StatisticsTestHelpers
public static void ShouldOnlyContain(this IStatistics statistics, string name,
object?[] parameters, string because = "")
{
statistics.Methods.Count.Should().Be(1, because);
statistics.Methods.Values.Should()
statistics.Methods.Length.Should().Be(1, because);
statistics.Methods.Should()
.ContainSingle(c => c.Name == name &&
c.Parameters.SequenceEqual(parameters),
because);
}

public static void ShouldOnlyContain(this IStatistics statistics, string name)
{
statistics.Methods.Count.Should().Be(1);
statistics.Methods.Values.Should()
statistics.Methods.Length.Should().Be(1);
statistics.Methods.Should()
.ContainSingle(c => c.Name == name &&
c.Parameters.Length == 0);
}

public static void ShouldOnlyContain<T1>(this IStatistics statistics, string name,
T1 parameter1)
{
statistics.Methods.Count.Should().Be(1);
statistics.Methods.Values.Should()
statistics.Methods.Length.Should().Be(1);
statistics.Methods.Should()
.ContainSingle(c => c.Name == name &&
c.Parameters.Length == 1 &&
c.Parameters[0].Is(parameter1));
Expand All @@ -36,8 +36,8 @@ public static void ShouldOnlyContain<T1>(this IStatistics statistics, string nam
public static void ShouldOnlyContain<T1>(this IStatistics statistics, string name,
T1[] parameter1)
{
statistics.Methods.Count.Should().Be(1);
statistics.Methods.Values.Should()
statistics.Methods.Length.Should().Be(1);
statistics.Methods.Should()
.ContainSingle(c => c.Name == name &&
c.Parameters.Length == 1 &&
c.Parameters[0].Is(parameter1));
Expand All @@ -47,8 +47,8 @@ public static void ShouldOnlyContain<T1>(this IStatistics statistics, string nam
public static void ShouldOnlyContain<T1>(this IStatistics statistics, string name,
ReadOnlySpan<T1> parameter1)
{
statistics.Methods.Count.Should().Be(1);
ParameterDescription parameter = statistics.Methods.Values.Should()
statistics.Methods.Length.Should().Be(1);
ParameterDescription parameter = statistics.Methods.Should()
.ContainSingle(c => c.Name == name &&
c.Parameters.Length == 1).Which.Parameters[0];
parameter.Is(parameter1).Should().BeTrue();
Expand All @@ -57,8 +57,8 @@ public static void ShouldOnlyContain<T1>(this IStatistics statistics, string nam
public static void ShouldOnlyContain<T1, T2>(this IStatistics statistics, string name,
ReadOnlySpan<T1> parameter1, ReadOnlySpan<T2> parameter2)
{
statistics.Methods.Count.Should().Be(1);
MethodStatistic? statistic = statistics.Methods.Values.Should()
statistics.Methods.Length.Should().Be(1);
MethodStatistic? statistic = statistics.Methods.Should()
.ContainSingle(c => c.Name == name &&
c.Parameters.Length == 2).Which;
statistic.Parameters[0].Is(parameter1).Should().BeTrue();
Expand All @@ -68,8 +68,8 @@ public static void ShouldOnlyContain<T1, T2>(this IStatistics statistics, string
public static void ShouldOnlyContain<T1, T2, T3>(this IStatistics statistics, string name,
ReadOnlySpan<T1> parameter1, ReadOnlySpan<T2> parameter2, ReadOnlySpan<T3> parameter3)
{
statistics.Methods.Count.Should().Be(1);
MethodStatistic? statistic = statistics.Methods.Values.Should()
statistics.Methods.Length.Should().Be(1);
MethodStatistic? statistic = statistics.Methods.Should()
.ContainSingle(c => c.Name == name &&
c.Parameters.Length == 3).Which;
statistic.Parameters[0].Is(parameter1).Should().BeTrue();
Expand All @@ -80,8 +80,8 @@ public static void ShouldOnlyContain<T1, T2, T3>(this IStatistics statistics, st
public static void ShouldOnlyContain<T1, T2, T3, T4>(this IStatistics statistics, string name,
ReadOnlySpan<T1> parameter1, ReadOnlySpan<T2> parameter2, ReadOnlySpan<T3> parameter3, ReadOnlySpan<T4> parameter4)
{
statistics.Methods.Count.Should().Be(1);
MethodStatistic? statistic = statistics.Methods.Values.Should()
statistics.Methods.Length.Should().Be(1);
MethodStatistic? statistic = statistics.Methods.Should()
.ContainSingle(c => c.Name == name &&
c.Parameters.Length == 4).Which;
statistic.Parameters[0].Is(parameter1).Should().BeTrue();
Expand All @@ -93,8 +93,8 @@ public static void ShouldOnlyContain<T1, T2, T3, T4>(this IStatistics statistics
public static void ShouldOnlyContain<T1, T2, T3, T4>(this IStatistics statistics, string name,
ReadOnlySpan<T1> parameter1, ReadOnlySpan<T2> parameter2, T3 parameter3, T4 parameter4)
{
statistics.Methods.Count.Should().Be(1);
MethodStatistic? statistic = statistics.Methods.Values.Should()
statistics.Methods.Length.Should().Be(1);
MethodStatistic? statistic = statistics.Methods.Should()
.ContainSingle(c => c.Name == name &&
c.Parameters.Length == 4).Which;
statistic.Parameters[0].Is(parameter1).Should().BeTrue();
Expand All @@ -106,8 +106,8 @@ public static void ShouldOnlyContain<T1, T2, T3, T4>(this IStatistics statistics
public static void ShouldOnlyContain<T1, T2, T3, T4>(this IStatistics statistics, string name,
ReadOnlySpan<T1> parameter1, ReadOnlySpan<T2> parameter2, Span<T3> parameter3, T4 parameter4)
{
statistics.Methods.Count.Should().Be(1);
MethodStatistic? statistic = statistics.Methods.Values.Should()
statistics.Methods.Length.Should().Be(1);
MethodStatistic? statistic = statistics.Methods.Should()
.ContainSingle(c => c.Name == name &&
c.Parameters.Length == 4).Which;
statistic.Parameters[0].Is(parameter1).Should().BeTrue();
Expand All @@ -119,8 +119,8 @@ public static void ShouldOnlyContain<T1, T2, T3, T4>(this IStatistics statistics
public static void ShouldOnlyContain<T1, T2, T3, T4, T5>(this IStatistics statistics, string name,
ReadOnlySpan<T1> parameter1, ReadOnlySpan<T2> parameter2, ReadOnlySpan<T3> parameter3, Span<T4> parameter4, T5 parameter5)
{
statistics.Methods.Count.Should().Be(1);
MethodStatistic? statistic = statistics.Methods.Values.Should()
statistics.Methods.Length.Should().Be(1);
MethodStatistic? statistic = statistics.Methods.Should()
.ContainSingle(c => c.Name == name &&
c.Parameters.Length == 5).Which;
statistic.Parameters[0].Is(parameter1).Should().BeTrue();
Expand All @@ -133,8 +133,8 @@ public static void ShouldOnlyContain<T1, T2, T3, T4, T5>(this IStatistics statis
public static void ShouldOnlyContain<T1>(this IStatistics statistics, string name,
Span<T1> parameter1)
{
statistics.Methods.Count.Should().Be(1);
ParameterDescription parameter = statistics.Methods.Values.Should()
statistics.Methods.Length.Should().Be(1);
ParameterDescription parameter = statistics.Methods.Should()
.ContainSingle(c => c.Name == name &&
c.Parameters.Length == 1).Which.Parameters[0];
parameter.Is(parameter1).Should().BeTrue();
Expand All @@ -144,8 +144,8 @@ public static void ShouldOnlyContain<T1>(this IStatistics statistics, string nam
public static void ShouldOnlyContain<T1, T2>(this IStatistics statistics, string name,
T1 parameter1, T2 parameter2)
{
statistics.Methods.Count.Should().Be(1);
statistics.Methods.Values.Should()
statistics.Methods.Length.Should().Be(1);
statistics.Methods.Should()
.ContainSingle(c => c.Name == name &&
c.Parameters.Length == 2 &&
c.Parameters[0].Is(parameter1) &&
Expand All @@ -155,8 +155,8 @@ public static void ShouldOnlyContain<T1, T2>(this IStatistics statistics, string
public static void ShouldOnlyContain<T1, T2, T3>(this IStatistics statistics, string name,
T1 parameter1, T2 parameter2, T3 parameter3)
{
statistics.Methods.Count.Should().Be(1);
statistics.Methods.Values.Should()
statistics.Methods.Length.Should().Be(1);
statistics.Methods.Should()
.ContainSingle(c => c.Name == name &&
c.Parameters.Length == 3 &&
c.Parameters[0].Is(parameter1) &&
Expand All @@ -167,8 +167,8 @@ public static void ShouldOnlyContain<T1, T2, T3>(this IStatistics statistics, st
public static void ShouldOnlyContain<T1, T2, T3, T4>(this IStatistics statistics, string name,
T1 parameter1, T2 parameter2, T3 parameter3, T4 parameter4)
{
statistics.Methods.Count.Should().Be(1);
statistics.Methods.Values.Should()
statistics.Methods.Length.Should().Be(1);
statistics.Methods.Should()
.ContainSingle(c => c.Name == name &&
c.Parameters.Length == 4 &&
c.Parameters[0].Is(parameter1) &&
Expand All @@ -180,8 +180,8 @@ public static void ShouldOnlyContain<T1, T2, T3, T4>(this IStatistics statistics
public static void ShouldOnlyContain<T1, T2, T3, T4, T5>(this IStatistics statistics,
string name, T1 parameter1, T2 parameter2, T3 parameter3, T4 parameter4, T5 parameter5)
{
statistics.Methods.Count.Should().Be(1);
statistics.Methods.Values.Should()
statistics.Methods.Length.Should().Be(1);
statistics.Methods.Should()
.ContainSingle(c => c.Name == name &&
c.Parameters.Length == 5 &&
c.Parameters[0].Is(parameter1) &&
Expand All @@ -195,8 +195,8 @@ public static void ShouldOnlyContain<T1, T2, T3, T4, T5, T6>(this IStatistics st
string name, T1 parameter1, T2 parameter2, T3 parameter3, T4 parameter4, T5 parameter5,
T6 parameter6)
{
statistics.Methods.Count.Should().Be(1);
statistics.Methods.Values.Should()
statistics.Methods.Length.Should().Be(1);
statistics.Methods.Should()
.ContainSingle(c => c.Name == name &&
c.Parameters.Length == 6 &&
c.Parameters[0].Is(parameter1) &&
Expand Down

0 comments on commit 37c262b

Please sign in to comment.