diff --git a/Directory.Packages.props b/Directory.Packages.props index 72028ddf63..6552ed4c44 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -8,6 +8,8 @@ + + @@ -41,27 +43,27 @@ - + - - - - - - - - + + + + + + + + - + - - - + + + @@ -72,7 +74,7 @@ - + @@ -95,14 +97,14 @@ - + - - - - - + + + + + diff --git a/TUnit.Core/Hooks/InstanceHookMethod.cs b/TUnit.Core/Hooks/InstanceHookMethod.cs index d8fe0219ab..a2176b6a06 100644 --- a/TUnit.Core/Hooks/InstanceHookMethod.cs +++ b/TUnit.Core/Hooks/InstanceHookMethod.cs @@ -1,4 +1,6 @@ -using System.Diagnostics.CodeAnalysis; +using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; +using System.Reflection; namespace TUnit.Core.Hooks; @@ -21,6 +23,16 @@ public required Type InitClassType public Func? Body { get; init; } + /// + /// The base method definition for this hook (i.e. ), + /// used by the engine to deduplicate virtual hook methods that are overridden in a derived + /// class. Optional — when null, the engine resolves it via reflection from + /// and the metadata name/parameters. Set directly by the reflection discovery path which already + /// holds a at registration time. + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public MethodInfo? BaseDefinition { get; init; } + public ValueTask ExecuteAsync(TestContext context, CancellationToken cancellationToken) { // Skip instance hooks if this is a pre-skipped test diff --git a/TUnit.Core/TUnit.Core.targets b/TUnit.Core/TUnit.Core.targets index 79c14222ea..b72f4fbaeb 100644 --- a/TUnit.Core/TUnit.Core.targets +++ b/TUnit.Core/TUnit.Core.targets @@ -8,7 +8,7 @@ - <_TUnitPolyfillVersion>9.24.1 + <_TUnitPolyfillVersion>10.0.0 <_TUnitNeedsPolyfill Condition="'$(TargetFramework)' == 'netstandard2.0' or '$(TargetFramework)' == 'netstandard2.1' or '$(TargetFrameworkIdentifier)' == '.NETFramework'">true diff --git a/TUnit.Engine/Discovery/ReflectionHookDiscoveryService.cs b/TUnit.Engine/Discovery/ReflectionHookDiscoveryService.cs index 328093ca6d..5b73d487a6 100644 --- a/TUnit.Engine/Discovery/ReflectionHookDiscoveryService.cs +++ b/TUnit.Engine/Discovery/ReflectionHookDiscoveryService.cs @@ -713,7 +713,8 @@ private static void RegisterInstanceBeforeHook( HookExecutor = GetHookExecutor(method), Order = order, RegistrationIndex = Interlocked.Increment(ref _registrationIndex), - Body = CreateInstanceHookDelegate(type, method) + Body = CreateInstanceHookDelegate(type, method), + BaseDefinition = method.GetBaseDefinition() }; bag.Add(hook); } @@ -738,7 +739,8 @@ private static void RegisterInstanceAfterHook( HookExecutor = GetHookExecutor(method), Order = order, RegistrationIndex = Interlocked.Increment(ref _registrationIndex), - Body = CreateInstanceHookDelegate(type, method) + Body = CreateInstanceHookDelegate(type, method), + BaseDefinition = method.GetBaseDefinition() }; bag.Add(hook); } diff --git a/TUnit.Engine/Services/HookDelegateBuilder.cs b/TUnit.Engine/Services/HookDelegateBuilder.cs index 6f78f1a99a..dc58d56358 100644 --- a/TUnit.Engine/Services/HookDelegateBuilder.cs +++ b/TUnit.Engine/Services/HookDelegateBuilder.cs @@ -53,6 +53,46 @@ private static Type GetCachedGenericTypeDefinition(Type type) return _genericTypeDefinitionCache.GetOrAdd(type, static t => t.GetGenericTypeDefinition()); } + /// + /// When walking the class hierarchy from derived to base collecting instance hooks, a virtual + /// hook method overridden in a derived class is registered twice — once on the base type, once + /// on the derived type — but virtual dispatch causes both registrations to invoke the same + /// override. This helper records the base method definition for each hook seen so far and + /// returns true when a hook's underlying method has already been collected via a more-derived + /// override. See issue #5428. + /// + private static bool IsOverriddenByMoreDerivedHook(InstanceHookMethod hook, HashSet seenBaseDefinitions) + { + // Prefer the pre-resolved BaseDefinition (set by the reflection discovery path). + // The source-generated path doesn't currently populate it, so fall back to a one-shot + // reflection lookup keyed by name + parameter types. Result is cached in the parent + // _beforeTestHooksCache / _afterTestHooksCache, so this only runs on first build per type. + var baseDefinition = hook.BaseDefinition ?? ResolveBaseDefinition(hook); + if (baseDefinition is null) + { + return false; + } + + return !seenBaseDefinitions.Add(baseDefinition); + } + + private static MethodInfo? ResolveBaseDefinition(InstanceHookMethod hook) + { + var parameters = hook.MethodInfo.Parameters; + var paramTypes = parameters.Length == 0 + ? Type.EmptyTypes + : parameters.Select(p => p.Type).ToArray(); + + var methodInfo = hook.ClassType.GetMethod( + hook.MethodInfo.Name, + BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly, + binder: null, + types: paramTypes, + modifiers: null); + + return methodInfo?.GetBaseDefinition(); + } + public async ValueTask InitializeAsync() { await _logger.LogDebugAsync("Building global hook delegates...").ConfigureAwait(false); @@ -191,6 +231,13 @@ private async Task>> BuildBeforeTes { var hooksByType = new List<(Type type, List<(int order, int registrationIndex, NamedHookDelegate hook)> hooks)>(); + // Tracks base method definitions (via MethodInfo.GetBaseDefinition()) of hooks we've + // already collected from more-derived types. Used to skip virtual hook methods that + // are overridden in a derived class — without this, both the base method registration + // AND the override registration would run, but virtual dispatch makes them invoke the + // same override, causing it to execute twice. See issue #5428. + var seenBaseDefinitions = new HashSet(); + // Collect hooks for each type in the hierarchy var currentType = type; while (currentType != null) @@ -201,6 +248,11 @@ private async Task>> BuildBeforeTes { foreach (var hook in sourceHooks) { + if (IsOverriddenByMoreDerivedHook(hook, seenBaseDefinitions)) + { + continue; + } + var namedHook = await CreateInstanceHookDelegateAsync(hook); typeHooks.Add((hook.Order, hook.RegistrationIndex, namedHook)); } @@ -214,6 +266,11 @@ private async Task>> BuildBeforeTes { foreach (var hook in openTypeHooks) { + if (IsOverriddenByMoreDerivedHook(hook, seenBaseDefinitions)) + { + continue; + } + var namedHook = await CreateInstanceHookDelegateAsync(hook); typeHooks.Add((hook.Order, hook.RegistrationIndex, namedHook)); } @@ -258,6 +315,10 @@ private async Task>> BuildAfterTest { var hooksByType = new List<(Type type, List<(int order, int registrationIndex, NamedHookDelegate hook)> hooks)>(); + // See note in BuildBeforeTestHooksAsync — same dedup needed for After(Test) hooks + // so virtual overrides don't execute twice (issue #5428). + var seenBaseDefinitions = new HashSet(); + // Collect hooks for each type in the hierarchy var currentType = type; while (currentType != null) @@ -268,6 +329,11 @@ private async Task>> BuildAfterTest { foreach (var hook in sourceHooks) { + if (IsOverriddenByMoreDerivedHook(hook, seenBaseDefinitions)) + { + continue; + } + var namedHook = await CreateInstanceHookDelegateAsync(hook); typeHooks.Add((hook.Order, hook.RegistrationIndex, namedHook)); } @@ -281,6 +347,11 @@ private async Task>> BuildAfterTest { foreach (var hook in openTypeHooks) { + if (IsOverriddenByMoreDerivedHook(hook, seenBaseDefinitions)) + { + continue; + } + var namedHook = await CreateInstanceHookDelegateAsync(hook); typeHooks.Add((hook.Order, hook.RegistrationIndex, namedHook)); } diff --git a/TUnit.Mocks.SourceGenerator.Tests/MockGeneratorTests.cs b/TUnit.Mocks.SourceGenerator.Tests/MockGeneratorTests.cs index 3ecae0221a..6c1906756d 100644 --- a/TUnit.Mocks.SourceGenerator.Tests/MockGeneratorTests.cs +++ b/TUnit.Mocks.SourceGenerator.Tests/MockGeneratorTests.cs @@ -105,6 +105,120 @@ void M() return VerifyGeneratorOutput(source); } + [Test] + public Task Interface_With_Nullable_Event() + { + // Regression test for #5424: nullable event handler types must + // preserve nullability in generated explicit interface implementation, + // otherwise CS8615 (nullability mismatch) is emitted. + var source = """ + #nullable enable + using System; + using TUnit.Mocks; + + public interface IFoo + { + event EventHandler? Something; + } + + public class TestUsage + { + void M() + { + var mock = Mock.Of(); + } + } + """; + + return VerifyGeneratorOutput(source); + } + + [Test] + public Task Interface_With_Nullable_Event_Args() + { + // Regression test for https://github.com/thomhurst/TUnit/issues/5425 + // Nullability of generic event handler type arguments must be preserved + // in the generated mock to avoid CS8604. + var source = """ + #nullable enable + using System; + using TUnit.Mocks; + + public interface IFoo + { + event EventHandler Something; + } + + public class TestUsage + { + void M() + { + var mock = Mock.Of(); + } + } + """; + + return VerifyGeneratorOutput(source); + } + + [Test] + public Task Interface_With_Nullable_Event_And_Nullable_Args() + { + // Combined regression for #5424 + #5425: both the delegate itself and + // its generic type argument are nullable (`EventHandler?`). + var source = """ + #nullable enable + using System; + using TUnit.Mocks; + + public interface IFoo + { + event EventHandler? Something; + } + + public class TestUsage + { + void M() + { + var mock = Mock.Of(); + } + } + """; + + return VerifyGeneratorOutput(source); + } + + [Test] + public Task Interface_With_Multiple_Multi_Parameter_Events() + { + // Regression test for #5423: RaiseEvent dispatch generated duplicate + // `__argArray` locals in the same switch when more than one event used + // a multi-parameter delegate (CS0128 / CS0165). + var source = """ + using System; + using TUnit.Mocks; + + public delegate void FirstHandler(object sender, string value); + public delegate void SecondHandler(object sender, int value); + + public interface IDualEvents + { + event FirstHandler First; + event SecondHandler Second; + } + + public class TestUsage + { + void M() + { + var mock = Mock.Of(); + } + } + """; + + return VerifyGeneratorOutput(source); + } + [Test] public Task Interface_Inheriting_Multiple_Interfaces() { diff --git a/TUnit.Mocks.SourceGenerator.Tests/Snapshots/Interface_With_Events.verified.txt b/TUnit.Mocks.SourceGenerator.Tests/Snapshots/Interface_With_Events.verified.txt index ac17e57599..9c8262682c 100644 --- a/TUnit.Mocks.SourceGenerator.Tests/Snapshots/Interface_With_Events.verified.txt +++ b/TUnit.Mocks.SourceGenerator.Tests/Snapshots/Interface_With_Events.verified.txt @@ -94,8 +94,10 @@ namespace TUnit.Mocks.Generated switch (eventName) { case "ItemAdded": - Raise_ItemAdded((string)args!); - break; + { + Raise_ItemAdded((string)args!); + break; + } default: throw new global::System.InvalidOperationException($"No event named '{eventName}' exists on this mock."); } diff --git a/TUnit.Mocks.SourceGenerator.Tests/Snapshots/Interface_With_Mixed_Members.verified.txt b/TUnit.Mocks.SourceGenerator.Tests/Snapshots/Interface_With_Mixed_Members.verified.txt index 9e5754d76c..56827be02f 100644 --- a/TUnit.Mocks.SourceGenerator.Tests/Snapshots/Interface_With_Mixed_Members.verified.txt +++ b/TUnit.Mocks.SourceGenerator.Tests/Snapshots/Interface_With_Mixed_Members.verified.txt @@ -129,8 +129,10 @@ namespace TUnit.Mocks.Generated switch (eventName) { case "StatusChanged": - Raise_StatusChanged((string)args!); - break; + { + Raise_StatusChanged((string)args!); + break; + } default: throw new global::System.InvalidOperationException($"No event named '{eventName}' exists on this mock."); } diff --git a/TUnit.Mocks.SourceGenerator.Tests/Snapshots/Interface_With_Multiple_Multi_Parameter_Events.verified.txt b/TUnit.Mocks.SourceGenerator.Tests/Snapshots/Interface_With_Multiple_Multi_Parameter_Events.verified.txt new file mode 100644 index 0000000000..d268fa175b --- /dev/null +++ b/TUnit.Mocks.SourceGenerator.Tests/Snapshots/Interface_With_Multiple_Multi_Parameter_Events.verified.txt @@ -0,0 +1,203 @@ +// +#nullable enable + +namespace TUnit.Mocks.Generated +{ + public sealed class IDualEventsMock : global::TUnit.Mocks.Mock, global::IDualEvents + { + [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)] + internal IDualEventsMock(global::IDualEvents mockObject, global::TUnit.Mocks.MockEngine engine) + : base(mockObject, engine) { } + + event global::FirstHandler global::IDualEvents.First { add => Object.First += value; remove => Object.First -= value; } + + event global::SecondHandler global::IDualEvents.Second { add => Object.Second += value; remove => Object.Second -= value; } + } +} + + +// ===== FILE SEPARATOR ===== + +// +#nullable enable + +namespace TUnit.Mocks.Generated +{ + [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)] + public readonly struct IDualEvents_MockEvents + { + internal readonly global::TUnit.Mocks.MockEngine Engine; + + internal IDualEvents_MockEvents(global::TUnit.Mocks.MockEngine engine) => Engine = engine; + } + + public static class IDualEvents_MockEventsExtensions + { + extension(global::TUnit.Mocks.Mock mock) + { + public IDualEvents_MockEvents Events => new(global::TUnit.Mocks.MockRegistry.GetEngine(mock)); + } + + extension(IDualEvents_MockEvents events) + { + public global::TUnit.Mocks.EventSubscriptionAccessor First + => new(events.Engine, "First"); + + public global::TUnit.Mocks.EventSubscriptionAccessor Second + => new(events.Engine, "Second"); + } + } +} + + +// ===== FILE SEPARATOR ===== + +// +#nullable enable + +namespace TUnit.Mocks.Generated +{ + file sealed class IDualEventsMockImpl : global::IDualEvents, global::TUnit.Mocks.IRaisable, global::TUnit.Mocks.IMockObject + { + private readonly global::TUnit.Mocks.MockEngine _engine; + + [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)] + global::TUnit.Mocks.IMock? global::TUnit.Mocks.IMockObject.MockWrapper { get; set; } + + internal IDualEventsMockImpl(global::TUnit.Mocks.MockEngine engine) + { + _engine = engine; + } + + private global::FirstHandler? _backing_First; + + public event global::FirstHandler? First + { + add { _backing_First += value; _engine.RecordEventSubscription("First", true); } + remove { _backing_First -= value; _engine.RecordEventSubscription("First", false); } + } + + [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)] + internal void Raise_First(object sender, string value) + { + _backing_First?.Invoke(sender, value); + } + + private global::SecondHandler? _backing_Second; + + public event global::SecondHandler? Second + { + add { _backing_Second += value; _engine.RecordEventSubscription("Second", true); } + remove { _backing_Second -= value; _engine.RecordEventSubscription("Second", false); } + } + + [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)] + internal void Raise_Second(object sender, int value) + { + _backing_Second?.Invoke(sender, value); + } + + [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)] + public void RaiseEvent(string eventName, object? args) + { + switch (eventName) + { + case "First": + { + if (args is object?[] __argArray) + { + Raise_First((object)__argArray[0], (string)__argArray[1]); + } + else + { + throw new global::System.ArgumentException($"Event 'First' requires an object[] of arguments."); + } + break; + } + case "Second": + { + if (args is object?[] __argArray) + { + Raise_Second((object)__argArray[0], (int)__argArray[1]); + } + else + { + throw new global::System.ArgumentException($"Event 'Second' requires an object[] of arguments."); + } + break; + } + default: + throw new global::System.InvalidOperationException($"No event named '{eventName}' exists on this mock."); + } + } + } + + file static class IDualEventsMockFactory + { + [global::System.Runtime.CompilerServices.ModuleInitializer] + internal static void Register() + { + global::TUnit.Mocks.MockRegistry.RegisterFactory(Create); + } + + internal static global::TUnit.Mocks.Mock Create(global::TUnit.Mocks.MockBehavior behavior, object[] constructorArgs) + { + if (constructorArgs.Length > 0) throw new global::System.ArgumentException($"Interface mock 'global::IDualEvents' does not support constructor arguments, but {constructorArgs.Length} were provided."); + var engine = new global::TUnit.Mocks.MockEngine(behavior); + var impl = new IDualEventsMockImpl(engine); + engine.Raisable = impl; + var mock = new IDualEventsMock(impl, engine); + return mock; + } + } +} + + +// ===== FILE SEPARATOR ===== + +// +#nullable enable + +namespace TUnit.Mocks.Generated +{ + public static class IDualEvents_MockMemberExtensions + { + public static void RaiseFirst(this global::TUnit.Mocks.Mock mock, object sender, string value) + { + ((global::TUnit.Mocks.IRaisable)global::TUnit.Mocks.MockRegistry.GetEngine(mock).Raisable!).RaiseEvent("First", (object?)new object?[] { sender, value }); + } + + public static void RaiseSecond(this global::TUnit.Mocks.Mock mock, object sender, int value) + { + ((global::TUnit.Mocks.IRaisable)global::TUnit.Mocks.MockRegistry.GetEngine(mock).Raisable!).RaiseEvent("Second", (object?)new object?[] { sender, value }); + } + } +} + + +// ===== FILE SEPARATOR ===== + +// +#nullable enable + +namespace TUnit.Mocks +{ + public static class IDualEvents_MockStaticExtension + { + extension(global::IDualEvents) + { + public static global::TUnit.Mocks.Generated.IDualEventsMock Mock(global::TUnit.Mocks.MockBehavior behavior = global::TUnit.Mocks.MockBehavior.Loose) + { + return (global::TUnit.Mocks.Generated.IDualEventsMock)global::TUnit.Mocks.Mock.Of(behavior); + } + } + } +} + + +// ===== FILE SEPARATOR ===== + +// +#nullable enable + +namespace TUnit.Mocks.Generated; \ No newline at end of file diff --git a/TUnit.Mocks.SourceGenerator.Tests/Snapshots/Interface_With_Nullable_Event.verified.txt b/TUnit.Mocks.SourceGenerator.Tests/Snapshots/Interface_With_Nullable_Event.verified.txt new file mode 100644 index 0000000000..7700682253 --- /dev/null +++ b/TUnit.Mocks.SourceGenerator.Tests/Snapshots/Interface_With_Nullable_Event.verified.txt @@ -0,0 +1,160 @@ +// +#nullable enable + +namespace TUnit.Mocks.Generated +{ + public sealed class IFooMock : global::TUnit.Mocks.Mock, global::IFoo + { + [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)] + internal IFooMock(global::IFoo mockObject, global::TUnit.Mocks.MockEngine engine) + : base(mockObject, engine) { } + + event global::System.EventHandler? global::IFoo.Something { add => Object.Something += value; remove => Object.Something -= value; } + } +} + + +// ===== FILE SEPARATOR ===== + +// +#nullable enable + +namespace TUnit.Mocks.Generated +{ + [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)] + public readonly struct IFoo_MockEvents + { + internal readonly global::TUnit.Mocks.MockEngine Engine; + + internal IFoo_MockEvents(global::TUnit.Mocks.MockEngine engine) => Engine = engine; + } + + public static class IFoo_MockEventsExtensions + { + extension(global::TUnit.Mocks.Mock mock) + { + public IFoo_MockEvents Events => new(global::TUnit.Mocks.MockRegistry.GetEngine(mock)); + } + + extension(IFoo_MockEvents events) + { + public global::TUnit.Mocks.EventSubscriptionAccessor Something + => new(events.Engine, "Something"); + } + } +} + + +// ===== FILE SEPARATOR ===== + +// +#nullable enable + +namespace TUnit.Mocks.Generated +{ + file sealed class IFooMockImpl : global::IFoo, global::TUnit.Mocks.IRaisable, global::TUnit.Mocks.IMockObject + { + private readonly global::TUnit.Mocks.MockEngine _engine; + + [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)] + global::TUnit.Mocks.IMock? global::TUnit.Mocks.IMockObject.MockWrapper { get; set; } + + internal IFooMockImpl(global::TUnit.Mocks.MockEngine engine) + { + _engine = engine; + } + + private global::System.EventHandler? _backing_Something; + + public event global::System.EventHandler? Something + { + add { _backing_Something += value; _engine.RecordEventSubscription("Something", true); } + remove { _backing_Something -= value; _engine.RecordEventSubscription("Something", false); } + } + + [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)] + internal void Raise_Something(string e) + { + _backing_Something?.Invoke(this, e); + } + + [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)] + public void RaiseEvent(string eventName, object? args) + { + switch (eventName) + { + case "Something": + { + Raise_Something((string)args!); + break; + } + default: + throw new global::System.InvalidOperationException($"No event named '{eventName}' exists on this mock."); + } + } + } + + file static class IFooMockFactory + { + [global::System.Runtime.CompilerServices.ModuleInitializer] + internal static void Register() + { + global::TUnit.Mocks.MockRegistry.RegisterFactory(Create); + } + + internal static global::TUnit.Mocks.Mock Create(global::TUnit.Mocks.MockBehavior behavior, object[] constructorArgs) + { + if (constructorArgs.Length > 0) throw new global::System.ArgumentException($"Interface mock 'global::IFoo' does not support constructor arguments, but {constructorArgs.Length} were provided."); + var engine = new global::TUnit.Mocks.MockEngine(behavior); + var impl = new IFooMockImpl(engine); + engine.Raisable = impl; + var mock = new IFooMock(impl, engine); + return mock; + } + } +} + + +// ===== FILE SEPARATOR ===== + +// +#nullable enable + +namespace TUnit.Mocks.Generated +{ + public static class IFoo_MockMemberExtensions + { + public static void RaiseSomething(this global::TUnit.Mocks.Mock mock, string e) + { + ((global::TUnit.Mocks.IRaisable)global::TUnit.Mocks.MockRegistry.GetEngine(mock).Raisable!).RaiseEvent("Something", (object?)e); + } + } +} + + +// ===== FILE SEPARATOR ===== + +// +#nullable enable + +namespace TUnit.Mocks +{ + public static class IFoo_MockStaticExtension + { + extension(global::IFoo) + { + public static global::TUnit.Mocks.Generated.IFooMock Mock(global::TUnit.Mocks.MockBehavior behavior = global::TUnit.Mocks.MockBehavior.Loose) + { + return (global::TUnit.Mocks.Generated.IFooMock)global::TUnit.Mocks.Mock.Of(behavior); + } + } + } +} + + +// ===== FILE SEPARATOR ===== + +// +#nullable enable + +namespace TUnit.Mocks.Generated; \ No newline at end of file diff --git a/TUnit.Mocks.SourceGenerator.Tests/Snapshots/Interface_With_Nullable_Event_And_Nullable_Args.verified.txt b/TUnit.Mocks.SourceGenerator.Tests/Snapshots/Interface_With_Nullable_Event_And_Nullable_Args.verified.txt new file mode 100644 index 0000000000..382753abce --- /dev/null +++ b/TUnit.Mocks.SourceGenerator.Tests/Snapshots/Interface_With_Nullable_Event_And_Nullable_Args.verified.txt @@ -0,0 +1,160 @@ +// +#nullable enable + +namespace TUnit.Mocks.Generated +{ + public sealed class IFooMock : global::TUnit.Mocks.Mock, global::IFoo + { + [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)] + internal IFooMock(global::IFoo mockObject, global::TUnit.Mocks.MockEngine engine) + : base(mockObject, engine) { } + + event global::System.EventHandler? global::IFoo.Something { add => Object.Something += value; remove => Object.Something -= value; } + } +} + + +// ===== FILE SEPARATOR ===== + +// +#nullable enable + +namespace TUnit.Mocks.Generated +{ + [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)] + public readonly struct IFoo_MockEvents + { + internal readonly global::TUnit.Mocks.MockEngine Engine; + + internal IFoo_MockEvents(global::TUnit.Mocks.MockEngine engine) => Engine = engine; + } + + public static class IFoo_MockEventsExtensions + { + extension(global::TUnit.Mocks.Mock mock) + { + public IFoo_MockEvents Events => new(global::TUnit.Mocks.MockRegistry.GetEngine(mock)); + } + + extension(IFoo_MockEvents events) + { + public global::TUnit.Mocks.EventSubscriptionAccessor Something + => new(events.Engine, "Something"); + } + } +} + + +// ===== FILE SEPARATOR ===== + +// +#nullable enable + +namespace TUnit.Mocks.Generated +{ + file sealed class IFooMockImpl : global::IFoo, global::TUnit.Mocks.IRaisable, global::TUnit.Mocks.IMockObject + { + private readonly global::TUnit.Mocks.MockEngine _engine; + + [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)] + global::TUnit.Mocks.IMock? global::TUnit.Mocks.IMockObject.MockWrapper { get; set; } + + internal IFooMockImpl(global::TUnit.Mocks.MockEngine engine) + { + _engine = engine; + } + + private global::System.EventHandler? _backing_Something; + + public event global::System.EventHandler? Something + { + add { _backing_Something += value; _engine.RecordEventSubscription("Something", true); } + remove { _backing_Something -= value; _engine.RecordEventSubscription("Something", false); } + } + + [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)] + internal void Raise_Something(string? e) + { + _backing_Something?.Invoke(this, e); + } + + [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)] + public void RaiseEvent(string eventName, object? args) + { + switch (eventName) + { + case "Something": + { + Raise_Something((string?)args!); + break; + } + default: + throw new global::System.InvalidOperationException($"No event named '{eventName}' exists on this mock."); + } + } + } + + file static class IFooMockFactory + { + [global::System.Runtime.CompilerServices.ModuleInitializer] + internal static void Register() + { + global::TUnit.Mocks.MockRegistry.RegisterFactory(Create); + } + + internal static global::TUnit.Mocks.Mock Create(global::TUnit.Mocks.MockBehavior behavior, object[] constructorArgs) + { + if (constructorArgs.Length > 0) throw new global::System.ArgumentException($"Interface mock 'global::IFoo' does not support constructor arguments, but {constructorArgs.Length} were provided."); + var engine = new global::TUnit.Mocks.MockEngine(behavior); + var impl = new IFooMockImpl(engine); + engine.Raisable = impl; + var mock = new IFooMock(impl, engine); + return mock; + } + } +} + + +// ===== FILE SEPARATOR ===== + +// +#nullable enable + +namespace TUnit.Mocks.Generated +{ + public static class IFoo_MockMemberExtensions + { + public static void RaiseSomething(this global::TUnit.Mocks.Mock mock, string? e) + { + ((global::TUnit.Mocks.IRaisable)global::TUnit.Mocks.MockRegistry.GetEngine(mock).Raisable!).RaiseEvent("Something", (object?)e); + } + } +} + + +// ===== FILE SEPARATOR ===== + +// +#nullable enable + +namespace TUnit.Mocks +{ + public static class IFoo_MockStaticExtension + { + extension(global::IFoo) + { + public static global::TUnit.Mocks.Generated.IFooMock Mock(global::TUnit.Mocks.MockBehavior behavior = global::TUnit.Mocks.MockBehavior.Loose) + { + return (global::TUnit.Mocks.Generated.IFooMock)global::TUnit.Mocks.Mock.Of(behavior); + } + } + } +} + + +// ===== FILE SEPARATOR ===== + +// +#nullable enable + +namespace TUnit.Mocks.Generated; \ No newline at end of file diff --git a/TUnit.Mocks.SourceGenerator.Tests/Snapshots/Interface_With_Nullable_Event_Args.verified.txt b/TUnit.Mocks.SourceGenerator.Tests/Snapshots/Interface_With_Nullable_Event_Args.verified.txt new file mode 100644 index 0000000000..44d26a5fb2 --- /dev/null +++ b/TUnit.Mocks.SourceGenerator.Tests/Snapshots/Interface_With_Nullable_Event_Args.verified.txt @@ -0,0 +1,160 @@ +// +#nullable enable + +namespace TUnit.Mocks.Generated +{ + public sealed class IFooMock : global::TUnit.Mocks.Mock, global::IFoo + { + [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)] + internal IFooMock(global::IFoo mockObject, global::TUnit.Mocks.MockEngine engine) + : base(mockObject, engine) { } + + event global::System.EventHandler global::IFoo.Something { add => Object.Something += value; remove => Object.Something -= value; } + } +} + + +// ===== FILE SEPARATOR ===== + +// +#nullable enable + +namespace TUnit.Mocks.Generated +{ + [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)] + public readonly struct IFoo_MockEvents + { + internal readonly global::TUnit.Mocks.MockEngine Engine; + + internal IFoo_MockEvents(global::TUnit.Mocks.MockEngine engine) => Engine = engine; + } + + public static class IFoo_MockEventsExtensions + { + extension(global::TUnit.Mocks.Mock mock) + { + public IFoo_MockEvents Events => new(global::TUnit.Mocks.MockRegistry.GetEngine(mock)); + } + + extension(IFoo_MockEvents events) + { + public global::TUnit.Mocks.EventSubscriptionAccessor Something + => new(events.Engine, "Something"); + } + } +} + + +// ===== FILE SEPARATOR ===== + +// +#nullable enable + +namespace TUnit.Mocks.Generated +{ + file sealed class IFooMockImpl : global::IFoo, global::TUnit.Mocks.IRaisable, global::TUnit.Mocks.IMockObject + { + private readonly global::TUnit.Mocks.MockEngine _engine; + + [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)] + global::TUnit.Mocks.IMock? global::TUnit.Mocks.IMockObject.MockWrapper { get; set; } + + internal IFooMockImpl(global::TUnit.Mocks.MockEngine engine) + { + _engine = engine; + } + + private global::System.EventHandler? _backing_Something; + + public event global::System.EventHandler? Something + { + add { _backing_Something += value; _engine.RecordEventSubscription("Something", true); } + remove { _backing_Something -= value; _engine.RecordEventSubscription("Something", false); } + } + + [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)] + internal void Raise_Something(string? e) + { + _backing_Something?.Invoke(this, e); + } + + [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)] + public void RaiseEvent(string eventName, object? args) + { + switch (eventName) + { + case "Something": + { + Raise_Something((string?)args!); + break; + } + default: + throw new global::System.InvalidOperationException($"No event named '{eventName}' exists on this mock."); + } + } + } + + file static class IFooMockFactory + { + [global::System.Runtime.CompilerServices.ModuleInitializer] + internal static void Register() + { + global::TUnit.Mocks.MockRegistry.RegisterFactory(Create); + } + + internal static global::TUnit.Mocks.Mock Create(global::TUnit.Mocks.MockBehavior behavior, object[] constructorArgs) + { + if (constructorArgs.Length > 0) throw new global::System.ArgumentException($"Interface mock 'global::IFoo' does not support constructor arguments, but {constructorArgs.Length} were provided."); + var engine = new global::TUnit.Mocks.MockEngine(behavior); + var impl = new IFooMockImpl(engine); + engine.Raisable = impl; + var mock = new IFooMock(impl, engine); + return mock; + } + } +} + + +// ===== FILE SEPARATOR ===== + +// +#nullable enable + +namespace TUnit.Mocks.Generated +{ + public static class IFoo_MockMemberExtensions + { + public static void RaiseSomething(this global::TUnit.Mocks.Mock mock, string? e) + { + ((global::TUnit.Mocks.IRaisable)global::TUnit.Mocks.MockRegistry.GetEngine(mock).Raisable!).RaiseEvent("Something", (object?)e); + } + } +} + + +// ===== FILE SEPARATOR ===== + +// +#nullable enable + +namespace TUnit.Mocks +{ + public static class IFoo_MockStaticExtension + { + extension(global::IFoo) + { + public static global::TUnit.Mocks.Generated.IFooMock Mock(global::TUnit.Mocks.MockBehavior behavior = global::TUnit.Mocks.MockBehavior.Loose) + { + return (global::TUnit.Mocks.Generated.IFooMock)global::TUnit.Mocks.Mock.Of(behavior); + } + } + } +} + + +// ===== FILE SEPARATOR ===== + +// +#nullable enable + +namespace TUnit.Mocks.Generated; \ No newline at end of file diff --git a/TUnit.Mocks.SourceGenerator.Tests/Snapshots/Partial_Mock_With_Generic_Constrained_Virtual_Methods.verified.txt b/TUnit.Mocks.SourceGenerator.Tests/Snapshots/Partial_Mock_With_Generic_Constrained_Virtual_Methods.verified.txt index 23de6dc4a0..f985714752 100644 --- a/TUnit.Mocks.SourceGenerator.Tests/Snapshots/Partial_Mock_With_Generic_Constrained_Virtual_Methods.verified.txt +++ b/TUnit.Mocks.SourceGenerator.Tests/Snapshots/Partial_Mock_With_Generic_Constrained_Virtual_Methods.verified.txt @@ -21,7 +21,7 @@ namespace TUnit.Mocks.Generated { return __result; } - return base.GetById(id); + return base.GetById(id); } public override void Save(T entity) @@ -30,7 +30,7 @@ namespace TUnit.Mocks.Generated { return; } - base.Save(entity); + base.Save(entity); } public override TResult Transform(TInput input) @@ -39,7 +39,7 @@ namespace TUnit.Mocks.Generated { return __result; } - return base.Transform(input); + return base.Transform(input); } public override global::System.Collections.Generic.IEnumerable GetAll() diff --git a/TUnit.Mocks.SourceGenerator/Builders/MockBridgeBuilder.cs b/TUnit.Mocks.SourceGenerator/Builders/MockBridgeBuilder.cs index 7acbd90561..b650f77aed 100644 --- a/TUnit.Mocks.SourceGenerator/Builders/MockBridgeBuilder.cs +++ b/TUnit.Mocks.SourceGenerator/Builders/MockBridgeBuilder.cs @@ -36,7 +36,7 @@ public static string Build(MockTypeModel model) private static void BuildBridgeInterface(CodeWriter writer, MockTypeModel model, string safeName) { writer.AppendLine("[global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]"); - using (writer.Block($"public interface {safeName}Mockable : {model.FullyQualifiedName}")) + using (writer.Block($"{model.Visibility} interface {safeName}Mockable : {model.FullyQualifiedName}")) { bool first = true; diff --git a/TUnit.Mocks.SourceGenerator/Builders/MockEventsBuilder.cs b/TUnit.Mocks.SourceGenerator/Builders/MockEventsBuilder.cs index c3473370c6..2da5f20742 100644 --- a/TUnit.Mocks.SourceGenerator/Builders/MockEventsBuilder.cs +++ b/TUnit.Mocks.SourceGenerator/Builders/MockEventsBuilder.cs @@ -18,7 +18,7 @@ public static string Build(MockTypeModel model) { // Lightweight struct holding engine reference — no allocation writer.AppendLine("[global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]"); - using (writer.Block($"public readonly struct {safeName}_MockEvents")) + using (writer.Block($"{model.Visibility} readonly struct {safeName}_MockEvents")) { writer.AppendLine($"internal readonly global::TUnit.Mocks.MockEngine<{mockableType}> Engine;"); writer.AppendLine(); @@ -27,7 +27,7 @@ public static string Build(MockTypeModel model) writer.AppendLine(); - using (writer.Block($"public static class {safeName}_MockEventsExtensions")) + using (writer.Block($"{model.Visibility} static class {safeName}_MockEventsExtensions")) { // Extension property on Mock — non-nullable, only present when type has events using (writer.Block($"extension(global::TUnit.Mocks.Mock<{mockableType}> mock)")) diff --git a/TUnit.Mocks.SourceGenerator/Builders/MockImplBuilder.cs b/TUnit.Mocks.SourceGenerator/Builders/MockImplBuilder.cs index c617603e18..d3469de74e 100644 --- a/TUnit.Mocks.SourceGenerator/Builders/MockImplBuilder.cs +++ b/TUnit.Mocks.SourceGenerator/Builders/MockImplBuilder.cs @@ -569,7 +569,7 @@ private static void GeneratePartialMethodBody(CodeWriter writer, MockMemberModel writer.AppendLine("return;"); writer.DecreaseIndent(); writer.AppendLine("}"); - writer.AppendLine($"base.{method.Name}({argPassList});"); + writer.AppendLine($"base.{method.Name}{GetTypeParameterList(method)}({argPassList});"); } else if (method.IsVoid && method.IsAsync) { @@ -589,7 +589,7 @@ private static void GeneratePartialMethodBody(CodeWriter writer, MockMemberModel } writer.DecreaseIndent(); writer.AppendLine("}"); - writer.AppendLine($"return base.{method.Name}({argPassList});"); + writer.AppendLine($"return base.{method.Name}{GetTypeParameterList(method)}({argPassList});"); } else if (method.IsAsync) { @@ -619,7 +619,7 @@ private static void GeneratePartialMethodBody(CodeWriter writer, MockMemberModel } writer.DecreaseIndent(); writer.AppendLine("}"); - writer.AppendLine($"return base.{method.Name}({argPassList});"); + writer.AppendLine($"return base.{method.Name}{GetTypeParameterList(method)}({argPassList});"); } else if (method.IsRefStructReturn) { @@ -638,7 +638,7 @@ private static void GeneratePartialMethodBody(CodeWriter writer, MockMemberModel } writer.DecreaseIndent(); writer.AppendLine("}"); - writer.AppendLine($"return base.{method.Name}({argPassList});"); + writer.AppendLine($"return base.{method.Name}{GetTypeParameterList(method)}({argPassList});"); } else if (method.IsReturnTypeStaticAbstractInterface) { @@ -650,7 +650,7 @@ private static void GeneratePartialMethodBody(CodeWriter writer, MockMemberModel writer.AppendLine("return __result;"); writer.DecreaseIndent(); writer.AppendLine("}"); - writer.AppendLine($"return base.{method.Name}({argPassList});"); + writer.AppendLine($"return base.{method.Name}{GetTypeParameterList(method)}({argPassList});"); } else { @@ -662,7 +662,7 @@ private static void GeneratePartialMethodBody(CodeWriter writer, MockMemberModel writer.AppendLine("return __result;"); writer.DecreaseIndent(); writer.AppendLine("}"); - writer.AppendLine($"return base.{method.Name}({argPassList});"); + writer.AppendLine($"return base.{method.Name}{GetTypeParameterList(method)}({argPassList});"); } } @@ -946,11 +946,11 @@ private static void GeneratePartialProperty(CodeWriter writer, MockMemberModel p private static void GenerateEvent(CodeWriter writer, MockEventModel evt) { // Backing delegate field - writer.AppendLine($"private {evt.EventHandlerType}? _backing_{evt.Name};"); + writer.AppendLine($"private {evt.EventHandlerTypeNonNullable}? _backing_{evt.Name};"); writer.AppendLine(); // Event add/remove accessors - writer.AppendLine($"public event {evt.EventHandlerType}? {evt.Name}"); + writer.AppendLine($"public event {evt.EventHandlerTypeNonNullable}? {evt.Name}"); writer.OpenBrace(); writer.AppendLine($"add {{ _backing_{evt.Name} += value; _engine.RecordEventSubscription(\"{evt.Name}\", true); }}"); writer.AppendLine($"remove {{ _backing_{evt.Name} -= value; _engine.RecordEventSubscription(\"{evt.Name}\", false); }}"); @@ -979,11 +979,11 @@ private static void GenerateEvent(CodeWriter writer, MockEventModel evt) private static void GeneratePartialEvent(CodeWriter writer, MockEventModel evt) { // Backing delegate field - writer.AppendLine($"private {evt.EventHandlerType}? _backing_{evt.Name};"); + writer.AppendLine($"private {evt.EventHandlerTypeNonNullable}? _backing_{evt.Name};"); writer.AppendLine(); // Event add/remove accessors with override - writer.AppendLine($"public override event {evt.EventHandlerType}? {evt.Name}"); + writer.AppendLine($"public override event {evt.EventHandlerTypeNonNullable}? {evt.Name}"); writer.OpenBrace(); writer.AppendLine($"add {{ _backing_{evt.Name} += value; _engine.RecordEventSubscription(\"{evt.Name}\", true); }}"); writer.AppendLine($"remove {{ _backing_{evt.Name} -= value; _engine.RecordEventSubscription(\"{evt.Name}\", false); }}"); @@ -1027,6 +1027,10 @@ private static void GenerateRaiseEventDispatch(CodeWriter writer, MockTypeModel { writer.AppendLine($"case \"{evt.Name}\":"); writer.IncreaseIndent(); + // Brace each case so locals (e.g. the `args` pattern variable below) get + // their own scope and don't collide across cases. + writer.AppendLine("{"); + writer.IncreaseIndent(); // Determine how to invoke: if the event handler has parameters matching EventArgs, pass args if (evt.RaiseParameterList.Length == 0) @@ -1064,6 +1068,8 @@ private static void GenerateRaiseEventDispatch(CodeWriter writer, MockTypeModel writer.AppendLine("break;"); writer.DecreaseIndent(); + writer.AppendLine("}"); + writer.DecreaseIndent(); } writer.AppendLine("default:"); diff --git a/TUnit.Mocks.SourceGenerator/Builders/MockMembersBuilder.cs b/TUnit.Mocks.SourceGenerator/Builders/MockMembersBuilder.cs index 465a211023..a96c9dd4c0 100644 --- a/TUnit.Mocks.SourceGenerator/Builders/MockMembersBuilder.cs +++ b/TUnit.Mocks.SourceGenerator/Builders/MockMembersBuilder.cs @@ -37,12 +37,18 @@ public static string Build(MockTypeModel model) using (writer.Block("namespace TUnit.Mocks.Generated")) { // Extension methods class - using (writer.Block($"public static class {safeName}_MockMemberExtensions")) + using (writer.Block($"{model.Visibility} static class {safeName}_MockMemberExtensions")) { bool firstMember = true; + // Pre-compute which methods need their `out` parameters kept in the extension + // signature to avoid CS0111 collisions. A method needs disambiguation when + // some other method on the model shares the same name AND the same + // matchable-parameter signature (i.e. parameters excluding out). + var methodsWithDisambiguation = ApplyOutDisambiguation(model.Methods); + // Methods - foreach (var method in model.Methods) + foreach (var method in methodsWithDisambiguation) { if (!firstMember) writer.AppendLine(); firstMember = false; @@ -77,13 +83,27 @@ public static string Build(MockTypeModel model) { if (!ShouldGenerateTypedWrapper(method, hasEvents)) continue; writer.AppendLine(); - GenerateUnifiedSealedClass(writer, method, safeName, instanceEventArray); + GenerateUnifiedSealedClass(writer, method, safeName, instanceEventArray, model.Visibility); } } return writer.ToString(); } + private static void EmitOutParamDefaults(CodeWriter writer, MockMemberModel method) + { + if (!method.KeepOutParamsInExtensionSignature) return; + // Out params are assigned `default!` because the extension method never actually invokes + // the mocked method — it only *configures* a setup. The out value is never observed by + // caller code: this setup-configuration call returns a MockMethodCall, not the mocked + // result. For reference types this suppresses the CS8625 nullable warning on an unused + // assignment that exists solely to satisfy the `out` contract. + foreach (var op in method.Parameters.Where(p => p.Direction == ParameterDirection.Out)) + { + writer.AppendLine($"{op.Name} = default!;"); + } + } + private static bool ShouldGenerateTypedWrapper(MockMemberModel method, bool hasEvents) { if (method.IsGenericMethod) return false; @@ -113,7 +133,7 @@ private static string GetSafeMemberName(string name) => MockMemberNames.Contains(name) ? name + "_" : name; private static void GenerateUnifiedSealedClass(CodeWriter writer, MockMemberModel method, string safeName, - EquatableArray events) + EquatableArray events, string visibility) { var setupReturnType = method.IsAsync && !method.IsVoid ? method.UnwrappedReturnType @@ -127,18 +147,18 @@ private static void GenerateUnifiedSealedClass(CodeWriter writer, MockMemberMode // Ref struct returns use the void wrapper (can't use ref structs as generic type args) if (method.IsVoid || method.IsRefStructReturn) { - GenerateVoidUnifiedClass(writer, wrapperName, matchableParams, events, method.Parameters, hasRefStructParams, allNonOutParams, method.SpanReturnElementType, method.ReturnType, + GenerateVoidUnifiedClass(writer, wrapperName, visibility, matchableParams, events, method.Parameters, hasRefStructParams, allNonOutParams, method.SpanReturnElementType, method.ReturnType, isAsync: method.IsAsync, isValueTask: method.IsValueTask); } else if (method.IsReturnTypeStaticAbstractInterface) { // Static-abstract interface returns can't be used as generic type args (CS8920) // Use object? to preserve .Returns() capability - GenerateReturnUnifiedClass(writer, wrapperName, matchableParams, "object?", events, method.Parameters, hasRefStructParams, allNonOutParams); + GenerateReturnUnifiedClass(writer, wrapperName, matchableParams, "object?", events, method.Parameters, hasRefStructParams, allNonOutParams, visibility); } else { - GenerateReturnUnifiedClass(writer, wrapperName, matchableParams, setupReturnType, events, method.Parameters, hasRefStructParams, allNonOutParams, + GenerateReturnUnifiedClass(writer, wrapperName, matchableParams, setupReturnType, events, method.Parameters, hasRefStructParams, allNonOutParams, visibility, isAsync: method.IsAsync, isValueTask: method.IsValueTask, fullReturnType: method.ReturnType); } } @@ -146,13 +166,14 @@ private static void GenerateUnifiedSealedClass(CodeWriter writer, MockMemberMode private static void GenerateReturnUnifiedClass(CodeWriter writer, string wrapperName, List nonOutParams, string returnType, EquatableArray events, EquatableArray allParameters, bool hasRefStructParams, List allNonOutParams, + string visibility, bool isAsync = false, bool isValueTask = false, string? fullReturnType = null) { var builderType = $"global::TUnit.Mocks.Setup.MethodSetupBuilder<{returnType}>"; var hasOutRef = allParameters.Any(p => p.Direction == ParameterDirection.Out || p.Direction == ParameterDirection.Ref); writer.AppendLine("[global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]"); - using (writer.Block($"public sealed class {wrapperName} : global::TUnit.Mocks.Verification.ICallVerification")) + using (writer.Block($"{visibility} sealed class {wrapperName} : global::TUnit.Mocks.Verification.ICallVerification")) { // Fields writer.AppendLine("private readonly global::TUnit.Mocks.IMockEngineAccess _engine;"); @@ -254,7 +275,7 @@ private static void GenerateReturnUnifiedClass(CodeWriter writer, string wrapper } } - private static void GenerateVoidUnifiedClass(CodeWriter writer, string wrapperName, + private static void GenerateVoidUnifiedClass(CodeWriter writer, string wrapperName, string visibility, List nonOutParams, EquatableArray events, EquatableArray allParameters, bool hasRefStructParams, List allNonOutParams, string? spanReturnElementType = null, string? spanReturnType = null, @@ -264,7 +285,7 @@ private static void GenerateVoidUnifiedClass(CodeWriter writer, string wrapperNa var hasOutRef = allParameters.Any(p => p.Direction == ParameterDirection.Out || p.Direction == ParameterDirection.Ref); writer.AppendLine($"[global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]"); - using (writer.Block($"public sealed class {wrapperName} : global::TUnit.Mocks.Verification.ICallVerification")) + using (writer.Block($"{visibility} sealed class {wrapperName} : global::TUnit.Mocks.Verification.ICallVerification")) { // Fields writer.AppendLine("private readonly global::TUnit.Mocks.IMockEngineAccess _engine;"); @@ -577,6 +598,54 @@ private static void GenerateMemberMethod(CodeWriter writer, MockMemberModel meth } } + /// + /// Returns the input methods, with + /// set to true on any method whose generated extension method would otherwise collide with + /// another overload. Methods are grouped by (name, type-arity, matchable-parameter signature); + /// any group with more than one entry causes its out-bearing members to be flagged. + /// The matchable-parameter signature includes parameter direction (ref/in/by-value) so that + /// overloads differing only by direction (e.g. Foo(int) vs Foo(ref int)) are not + /// treated as collisions. + /// + private static IEnumerable ApplyOutDisambiguation(EquatableArray methods) + { + var flagged = new HashSet(); + var byKey = new Dictionary>(System.StringComparer.Ordinal); + foreach (var m in methods) + { + var matchable = string.Join(",", m.Parameters + .Where(p => p.Direction != ParameterDirection.Out) + .Select(p => $"{p.Direction}:{p.FullyQualifiedType}")); + var typeArity = m.TypeParameters.Length; + var key = $"{m.Name}`{typeArity}({matchable})"; + if (!byKey.TryGetValue(key, out var list)) + { + list = new List(); + byKey[key] = list; + } + list.Add(m); + } + foreach (var group in byKey.Values) + { + if (group.Count < 2) continue; + foreach (var m in group) + { + if (m.Parameters.Any(p => p.Direction == ParameterDirection.Out)) + { + flagged.Add(m.MemberId); + } + } + } + + if (flagged.Count == 0) + { + return methods; + } + return methods.Select(m => flagged.Contains(m.MemberId) + ? m with { KeepOutParamsInExtensionSignature = true } + : m); + } + private static (bool UseTypedWrapper, string ReturnType, string SetupReturnType) GetReturnTypeInfo( MockMemberModel method, MockTypeModel model, string safeName) { @@ -633,6 +702,8 @@ private static void EmitMemberMethodBody(CodeWriter writer, MockMemberModel meth using (writer.Block($"public static {returnType} {safeMemberName}{typeParams}({fullParamList}){constraints}")) { + EmitOutParamDefaults(writer, method); + // Build matchers array var matchableParams = includeRefStructArgs ? method.Parameters.Where(p => p.Direction != ParameterDirection.Out).ToList() @@ -717,7 +788,16 @@ private static void EmitSingleFuncOverload(CodeWriter writer, MockMemberModel me for (int i = 0; i < method.Parameters.Length; i++) { var p = method.Parameters[i]; - if (p.Direction == ParameterDirection.Out) continue; + if (p.Direction == ParameterDirection.Out) + { + // Keep out params only when needed to disambiguate colliding overloads. + // Callers of the disambiguated overload must write `out _` at the call site. + if (method.KeepOutParamsInExtensionSignature) + { + paramParts.Add($"out {p.FullyQualifiedType} {p.Name}"); + } + continue; + } if (funcIndices.Contains(i)) { @@ -757,6 +837,8 @@ private static void EmitSingleFuncOverload(CodeWriter writer, MockMemberModel me using (writer.Block($"public static {returnType} {safeMemberName}{typeParams}({fullParamList}){constraints}")) { + EmitOutParamDefaults(writer, method); + // Convert Func params to Arg via implicit conversion foreach (var idx in funcIndices.OrderBy(i => i)) { @@ -876,7 +958,19 @@ private static string GetArgParameterList(MockMemberModel method, bool includeRe var parts = new List(); foreach (var p in method.Parameters) { - if (p.Direction == ParameterDirection.Out) continue; + if (p.Direction == ParameterDirection.Out) + { + // Normally out params are omitted from the extension signature so callers + // don't have to write `out _`. But when another overload of this method has + // the same matchable-parameter signature (e.g. GenerateSasUri(perms, expires) + // vs GenerateSasUri(perms, expires, out string)), we MUST keep the out param + // in the signature, otherwise CS0111 fires on the generated extensions. + if (method.KeepOutParamsInExtensionSignature) + { + parts.Add($"out {p.FullyQualifiedType} {p.Name}"); + } + continue; + } if (p.IsRefStruct) { if (includeRefStructArgs) diff --git a/TUnit.Mocks.SourceGenerator/Builders/MockStaticExtensionBuilder.cs b/TUnit.Mocks.SourceGenerator/Builders/MockStaticExtensionBuilder.cs index 1f829d4c0f..4fc99519e8 100644 --- a/TUnit.Mocks.SourceGenerator/Builders/MockStaticExtensionBuilder.cs +++ b/TUnit.Mocks.SourceGenerator/Builders/MockStaticExtensionBuilder.cs @@ -23,11 +23,11 @@ public static string Build(MockTypeModel model) using (writer.Block("namespace TUnit.Mocks")) { - using (writer.Block($"public static class {extensionClassName}_MockStaticExtension")) + using (writer.Block($"{model.Visibility} static class {extensionClassName}_MockStaticExtension")) { using (writer.Block($"extension({model.FullyQualifiedName})")) { - using (writer.Block($"public static global::{mockNamespace}.{shortName}Mock Mock(global::TUnit.Mocks.MockBehavior behavior = global::TUnit.Mocks.MockBehavior.Loose)")) + using (writer.Block($"{model.Visibility} static global::{mockNamespace}.{shortName}Mock Mock(global::TUnit.Mocks.MockBehavior behavior = global::TUnit.Mocks.MockBehavior.Loose)")) { writer.AppendLine($"return (global::{mockNamespace}.{shortName}Mock)global::TUnit.Mocks.Mock.Of<{mockableType}>(behavior);"); } diff --git a/TUnit.Mocks.SourceGenerator/Builders/MockWrapperTypeBuilder.cs b/TUnit.Mocks.SourceGenerator/Builders/MockWrapperTypeBuilder.cs index d9e9b824d7..494cf625e1 100644 --- a/TUnit.Mocks.SourceGenerator/Builders/MockWrapperTypeBuilder.cs +++ b/TUnit.Mocks.SourceGenerator/Builders/MockWrapperTypeBuilder.cs @@ -37,7 +37,7 @@ public static string Build(MockTypeModel model) using (writer.Block($"namespace {mockNamespace}")) { - using (writer.Block($"public sealed class {safeName}Mock : global::TUnit.Mocks.Mock<{mockableType}>, {model.FullyQualifiedName}")) + using (writer.Block($"{model.Visibility} sealed class {safeName}Mock : global::TUnit.Mocks.Mock<{mockableType}>, {model.FullyQualifiedName}")) { writer.AppendLine("[global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]"); writer.AppendLine($"internal {safeName}Mock({mockableType} mockObject, global::TUnit.Mocks.MockEngine<{mockableType}> engine)"); diff --git a/TUnit.Mocks.SourceGenerator/Discovery/MemberDiscovery.cs b/TUnit.Mocks.SourceGenerator/Discovery/MemberDiscovery.cs index 5580e2c5d1..68125b6fe1 100644 --- a/TUnit.Mocks.SourceGenerator/Discovery/MemberDiscovery.cs +++ b/TUnit.Mocks.SourceGenerator/Discovery/MemberDiscovery.cs @@ -649,7 +649,7 @@ private static MockMemberModel CreateIndexerModel(IPropertySymbol indexer, ref i private static MockEventModel CreateEventModel(IEventSymbol evt, string? explicitInterfaceName, string? declaringInterfaceName = null) { - var eventHandlerType = evt.Type.GetFullyQualifiedName(); + var eventHandlerType = evt.Type.GetFullyQualifiedNameWithNullability(); // Determine if this is an EventHandler pattern (sender + args) var isEventHandlerPattern = IsEventHandlerType(evt.Type); diff --git a/TUnit.Mocks.SourceGenerator/Discovery/MockTypeDiscovery.cs b/TUnit.Mocks.SourceGenerator/Discovery/MockTypeDiscovery.cs index 0b46b819e0..ff317f3f00 100644 --- a/TUnit.Mocks.SourceGenerator/Discovery/MockTypeDiscovery.cs +++ b/TUnit.Mocks.SourceGenerator/Discovery/MockTypeDiscovery.cs @@ -174,7 +174,8 @@ public static ImmutableArray TransformToModels(GeneratorSyntaxCon ), AdditionalInterfaceNames = new EquatableArray(additionalInterfaceNames.MoveToImmutable()), Constructors = singleTypeModel.Constructors, - HasStaticAbstractMembers = methods.Any(m => m.IsStaticAbstract) || properties.Any(p => p.IsStaticAbstract) || events.Any(e => e.IsStaticAbstract) + HasStaticAbstractMembers = methods.Any(m => m.IsStaticAbstract) || properties.Any(p => p.IsStaticAbstract) || events.Any(e => e.IsStaticAbstract), + IsPublic = IsEffectivelyPublic(namedType) }; return ImmutableArray.Create(singleTypeModel, multiTypeModel); @@ -319,6 +320,7 @@ private static bool HasStaticAbstractMembers(INamedTypeSymbol interfaceType) Properties = EquatableArray.Empty, Events = EquatableArray.Empty, AllInterfaces = EquatableArray.Empty, + IsPublic = IsEffectivelyPublic(delegateType), }; } @@ -367,10 +369,27 @@ private static ImmutableArray BuildModelWithTransitiveDependencie .ToImmutableArray() ), Constructors = constructors, - HasStaticAbstractMembers = methods.Any(m => m.IsStaticAbstract) || properties.Any(p => p.IsStaticAbstract) || events.Any(e => e.IsStaticAbstract) + HasStaticAbstractMembers = methods.Any(m => m.IsStaticAbstract) || properties.Any(p => p.IsStaticAbstract) || events.Any(e => e.IsStaticAbstract), + IsPublic = IsEffectivelyPublic(namedType) }; } + /// + /// Returns true if the type's effective accessibility is public — i.e., the type itself + /// and all its containing types are declared public. Generated wrapper/extension classes + /// for types that are not effectively public must themselves be internal to avoid + /// CS9338 / CS0051 inconsistent accessibility errors. (See issue #5426.) + /// + private static bool IsEffectivelyPublic(INamedTypeSymbol type) + { + for (INamedTypeSymbol? t = type; t is not null; t = t.ContainingType) + { + if (t.DeclaredAccessibility != Accessibility.Public) + return false; + } + return true; + } + // ─── IFoo.Mock() static extension discovery ──────────────────── /// diff --git a/TUnit.Mocks.SourceGenerator/Models/MockEventModel.cs b/TUnit.Mocks.SourceGenerator/Models/MockEventModel.cs index 639bb71c63..ac5fb74e32 100644 --- a/TUnit.Mocks.SourceGenerator/Models/MockEventModel.cs +++ b/TUnit.Mocks.SourceGenerator/Models/MockEventModel.cs @@ -5,8 +5,19 @@ namespace TUnit.Mocks.SourceGenerator.Models; internal sealed record MockEventModel : IEquatable { public string Name { get; init; } = ""; + /// + /// The fully qualified event handler type, with nullable annotations + /// preserved from the declaring interface. Used when emitting explicit + /// interface event implementations so that nullability matches the + /// interface declaration (otherwise CS8615 is emitted, see issue #5424). + /// For the always-nullable backing delegate field, use + /// and append ?. + /// public string EventHandlerType { get; init; } = ""; + /// The handler type with any trailing nullable annotation removed. + public string EventHandlerTypeNonNullable => EventHandlerType.TrimEnd('?'); + /// /// The argument expression for invoking the backing delegate. /// E.g., "this, args" for EventHandler<string>, or "arg1, arg2" for Action<string, int>. diff --git a/TUnit.Mocks.SourceGenerator/Models/MockMemberModel.cs b/TUnit.Mocks.SourceGenerator/Models/MockMemberModel.cs index e123ef3fe6..78a38556ce 100644 --- a/TUnit.Mocks.SourceGenerator/Models/MockMemberModel.cs +++ b/TUnit.Mocks.SourceGenerator/Models/MockMemberModel.cs @@ -45,6 +45,19 @@ internal sealed record MockMemberModel : IEquatable /// public bool IsReturnTypeStaticAbstractInterface { get; init; } + /// + /// True when this method's out parameters must be kept in the generated extension + /// method signature to avoid CS0111 collisions with a sibling overload that shares the same + /// matchable-parameter signature (e.g. BlobClient.GenerateSasUri(perms, expires) vs + /// GenerateSasUri(perms, expires, out string stringToSign)). When true, callers must + /// pass out _ at the call site for the disambiguated overload. + /// Computed transiently inside by examining + /// the full method set; never set on models flowing through the incremental pipeline. + /// Excluded from / because + /// it is a derived per-build flag, not part of model identity. + /// + public bool KeepOutParamsInExtensionSignature { get; init; } + /// /// For methods returning ReadOnlySpan<T> or Span<T>, the fully qualified element type. /// Null for non-span return types. Used to support configurable span return values via array conversion. diff --git a/TUnit.Mocks.SourceGenerator/Models/MockTypeModel.cs b/TUnit.Mocks.SourceGenerator/Models/MockTypeModel.cs index 51d0241643..e5b59cb1ec 100644 --- a/TUnit.Mocks.SourceGenerator/Models/MockTypeModel.cs +++ b/TUnit.Mocks.SourceGenerator/Models/MockTypeModel.cs @@ -24,6 +24,16 @@ internal sealed record MockTypeModel : IEquatable public EquatableArray Constructors { get; init; } = EquatableArray.Empty; public bool HasStaticAbstractMembers { get; init; } + /// + /// True if the mocked type's effective accessibility is public (the type itself and all + /// containing types are public). When false, generated wrapper/extension types must be + /// declared internal to avoid CS9338/CS0051 inconsistent accessibility errors. + /// + public bool IsPublic { get; init; } = true; + + /// The C# visibility keyword to emit on generated wrapper/extension types. + public string Visibility => IsPublic ? "public" : "internal"; + public bool Equals(MockTypeModel? other) { if (other is null) return false; @@ -35,6 +45,7 @@ public bool Equals(MockTypeModel? other) && IsPartialMock == other.IsPartialMock && IsDelegateType == other.IsDelegateType && IsWrapMock == other.IsWrapMock + && IsPublic == other.IsPublic && Methods.Equals(other.Methods) && Properties.Equals(other.Properties) && Events.Equals(other.Events) @@ -53,6 +64,7 @@ public override int GetHashCode() hash = hash * 31 + IsPartialMock.GetHashCode(); hash = hash * 31 + IsDelegateType.GetHashCode(); hash = hash * 31 + IsWrapMock.GetHashCode(); + hash = hash * 31 + IsPublic.GetHashCode(); hash = hash * 31 + Methods.GetHashCode(); hash = hash * 31 + Properties.GetHashCode(); hash = hash * 31 + Events.GetHashCode(); diff --git a/TUnit.Mocks.Tests/EventTests.cs b/TUnit.Mocks.Tests/EventTests.cs index 5026d21186..288a9eefd9 100644 --- a/TUnit.Mocks.Tests/EventTests.cs +++ b/TUnit.Mocks.Tests/EventTests.cs @@ -1,7 +1,17 @@ +using System.ComponentModel; using TUnit.Mocks; namespace TUnit.Mocks.Tests; +/// +/// Regression interface for #5423: multiple multi-parameter events on the +/// same interface previously caused CS0128 in the generated RaiseEvent switch. +/// +// Public because the mock generator emits public extension types that take this interface as a parameter. +public interface IMultiEventNotifier : INotifyPropertyChanging, INotifyPropertyChanged +{ +} + /// /// Test interface with events for mocking. /// @@ -82,4 +92,27 @@ public async Task Unsubscribe_From_Event_Stops_Notifications() // Assert — only one notification await Assert.That(callCount).IsEqualTo(1); } + + /// + /// Regression test for #5423. An interface inheriting two interfaces, each + /// declaring a multi-parameter event, must produce a generated mock that + /// compiles and dispatches each event independently through RaiseEvent. + /// + [Test] + public async Task Mock_With_Multiple_Multi_Parameter_Events_Compiles_And_Raises() + { + var mock = Mock.Of(); + var notifier = mock.Object; + + string? changingProperty = null; + string? changedProperty = null; + notifier.PropertyChanging += (_, e) => changingProperty = e.PropertyName; + notifier.PropertyChanged += (_, e) => changedProperty = e.PropertyName; + + mock.RaisePropertyChanging(notifier, new PropertyChangingEventArgs("Foo")); + mock.RaisePropertyChanged(notifier, new PropertyChangedEventArgs("Bar")); + + await Assert.That(changingProperty).IsEqualTo("Foo"); + await Assert.That(changedProperty).IsEqualTo("Bar"); + } } diff --git a/TUnit.Mocks.Tests/Issue5425Tests.cs b/TUnit.Mocks.Tests/Issue5425Tests.cs new file mode 100644 index 0000000000..6dc35e9b8e --- /dev/null +++ b/TUnit.Mocks.Tests/Issue5425Tests.cs @@ -0,0 +1,65 @@ +#nullable enable + +// Promote the nullability warnings that #5424 / #5425 produced into errors so any +// regression in the source generator (where the generated mock loses nullability +// information from the source event) breaks this project's build instead of +// silently emitting warnings. +// +// CS8604 — Possible null reference argument (#5425) +// CS8612 — Nullability mismatch in implemented type (#5424) +// CS8613 — Nullability mismatch in return type +// CS8614 — Nullability mismatch in parameter type +// CS8615 — Nullability mismatch in implemented member +#pragma warning error CS8604 +#pragma warning error CS8612 +#pragma warning error CS8613 +#pragma warning error CS8614 +#pragma warning error CS8615 + +namespace TUnit.Mocks.Tests; + +// Compile-time regression coverage for: +// - https://github.com/thomhurst/TUnit/issues/5424 — nullable delegate type +// - https://github.com/thomhurst/TUnit/issues/5425 — nullable generic type argument +// +// If the source generator stops preserving nullability on event handler types, +// the generated mock will mismatch these source declarations and this file will +// fail to compile. +public class Issue5425Tests +{ + public interface IWithNullableTypeArg + { + event EventHandler Something; + } + + public interface IWithNullableEvent + { + event EventHandler? Something; + } + + public interface IWithBothNullable + { + event EventHandler? Something; + } + + [Test] + public async Task Can_Mock_Event_With_Nullable_Type_Argument() + { + var mock = Mock.Of(); + await Assert.That(mock).IsNotNull(); + } + + [Test] + public async Task Can_Mock_Nullable_Event() + { + var mock = Mock.Of(); + await Assert.That(mock).IsNotNull(); + } + + [Test] + public async Task Can_Mock_Nullable_Event_With_Nullable_Type_Argument() + { + var mock = Mock.Of(); + await Assert.That(mock).IsNotNull(); + } +} diff --git a/TUnit.Mocks.Tests/Issue5426Tests.cs b/TUnit.Mocks.Tests/Issue5426Tests.cs new file mode 100644 index 0000000000..3a3cdaf2a8 --- /dev/null +++ b/TUnit.Mocks.Tests/Issue5426Tests.cs @@ -0,0 +1,62 @@ +namespace TUnit.Mocks.Tests; + +// Reproduction and regression tests for https://github.com/thomhurst/TUnit/issues/5426 +// CS9338 / CS0051: Generated mock wrapper and extension classes were always emitted as `public`, +// even when the source interface (or its containing type) was non-public. This produced +// inconsistent-accessibility errors at compile time. +// +// These tests are *compile-time* regressions: if the source generator emits `public` for any of +// the types below, this file fails to compile and the test project will not build. +public class Issue5426Tests +{ + internal interface IInternalDatabaseService + { + Task GetOpenOrdersAsync(); + Task UpdateOrderProgressAsync(int orderId, InternalProcessingStatus status); + } + + internal enum InternalProcessingStatus + { + Pending, + Done, + } + + internal sealed record InternalOrderId(int Value); + + internal interface IInternalOrderRepository + { + InternalOrderId Get(int id); + } + + [Test] + public async Task Can_Mock_Internal_Interface_With_Generic_Task_Method() + { + var mock = Mock.Of(MockBehavior.Loose); + mock.GetOpenOrdersAsync().Returns(42); + + var result = await mock.Object.GetOpenOrdersAsync(); + + await Assert.That(result).IsEqualTo(42); + } + + [Test] + public async Task Can_Mock_Internal_Interface_With_Internal_Parameter_Type() + { + var mock = Mock.Of(MockBehavior.Loose); + mock.UpdateOrderProgressAsync(Arg.Any(), Arg.Any()) + .Returns(); + + await mock.Object.UpdateOrderProgressAsync(1, InternalProcessingStatus.Done); + } + + [Test] + public async Task Can_Mock_Internal_Interface_With_Internal_Return_Type() + { + var mock = Mock.Of(MockBehavior.Loose); + mock.Get(Arg.Any()).Returns(new InternalOrderId(7)); + + var result = mock.Object.Get(1); + + await Assert.That(result.Value).IsEqualTo(7); + } +} diff --git a/TUnit.Mocks.Tests/Issue5434Tests.cs b/TUnit.Mocks.Tests/Issue5434Tests.cs new file mode 100644 index 0000000000..0c60ce255d --- /dev/null +++ b/TUnit.Mocks.Tests/Issue5434Tests.cs @@ -0,0 +1,49 @@ +using Azure.Data.Tables; +using Azure.Storage.Blobs; +using Azure.Storage.Sas; + +namespace TUnit.Mocks.Tests; + +// Reproduction and regression tests for https://github.com/thomhurst/TUnit/issues/5434 +// BlobClient: CS0111 duplicate GenerateSasUri / GenerateUserDelegationSasUri members in generated extensions. +// TableClient: CS0411 type inference failures for generic methods (GetEntity, GetEntityAsync, +// GetEntityIfExists, GetEntityIfExistsAsync, Query, QueryAsync) in generated impl factory. +public class Issue5434Tests +{ + [Test] + public void Can_Mock_BlobClient() + { + var mock = Mock.Of(MockBehavior.Strict); + _ = mock.Object; + } + + [Test] + public void Can_Mock_TableClient() + { + var mock = Mock.Of(MockBehavior.Strict); + _ = mock.Object; + } + + // Exercises the disambiguated overload that keeps `out string stringToSign` in its + // signature to distinguish it from GenerateSasUri(perms, expires). This call would not + // compile if `keepOutParams` disambiguation regressed. + [Test] + public void Can_Configure_BlobClient_GenerateSasUri_OutOverload() + { + var mock = Mock.Of(MockBehavior.Loose); + _ = mock.GenerateSasUri(Arg.Any(), Arg.Any(), out _); + } + + // Exercises the generic-return-type override path. This would not compile if + // the base.GetEntity(...) call in the generated override was missing the type argument. + [Test] + public void Can_Configure_TableClient_GetEntity_Generic() + { + var mock = Mock.Of(MockBehavior.Loose); + _ = mock.GetEntity( + Arg.Any(), + Arg.Any(), + Arg.Any>(), + Arg.Any()); + } +} diff --git a/TUnit.Mocks.Tests/TUnit.Mocks.Tests.csproj b/TUnit.Mocks.Tests/TUnit.Mocks.Tests.csproj index e16011c09f..2b7f98ea61 100644 --- a/TUnit.Mocks.Tests/TUnit.Mocks.Tests.csproj +++ b/TUnit.Mocks.Tests/TUnit.Mocks.Tests.csproj @@ -9,6 +9,8 @@ + + diff --git a/TUnit.PublicAPI/Tests.Core_Library_Has_No_API_Changes.DotNet10_0.verified.txt b/TUnit.PublicAPI/Tests.Core_Library_Has_No_API_Changes.DotNet10_0.verified.txt index a8ef282b22..ccf949b734 100644 --- a/TUnit.PublicAPI/Tests.Core_Library_Has_No_API_Changes.DotNet10_0.verified.txt +++ b/TUnit.PublicAPI/Tests.Core_Library_Has_No_API_Changes.DotNet10_0.verified.txt @@ -2321,6 +2321,7 @@ namespace .Hooks public class InstanceHookMethod : ., <.>, .<.TestContext> { public InstanceHookMethod() { } + public .MethodInfo? BaseDefinition { get; init; } public ? Body { get; init; } [.(..PublicMethods)] public override ClassType { get; } diff --git a/TUnit.PublicAPI/Tests.Core_Library_Has_No_API_Changes.DotNet8_0.verified.txt b/TUnit.PublicAPI/Tests.Core_Library_Has_No_API_Changes.DotNet8_0.verified.txt index e9ed0a0976..415ded6100 100644 --- a/TUnit.PublicAPI/Tests.Core_Library_Has_No_API_Changes.DotNet8_0.verified.txt +++ b/TUnit.PublicAPI/Tests.Core_Library_Has_No_API_Changes.DotNet8_0.verified.txt @@ -2321,6 +2321,7 @@ namespace .Hooks public class InstanceHookMethod : ., <.>, .<.TestContext> { public InstanceHookMethod() { } + public .MethodInfo? BaseDefinition { get; init; } public ? Body { get; init; } [.(..PublicMethods)] public override ClassType { get; } diff --git a/TUnit.PublicAPI/Tests.Core_Library_Has_No_API_Changes.DotNet9_0.verified.txt b/TUnit.PublicAPI/Tests.Core_Library_Has_No_API_Changes.DotNet9_0.verified.txt index f2934aed1c..6110f69efb 100644 --- a/TUnit.PublicAPI/Tests.Core_Library_Has_No_API_Changes.DotNet9_0.verified.txt +++ b/TUnit.PublicAPI/Tests.Core_Library_Has_No_API_Changes.DotNet9_0.verified.txt @@ -2321,6 +2321,7 @@ namespace .Hooks public class InstanceHookMethod : ., <.>, .<.TestContext> { public InstanceHookMethod() { } + public .MethodInfo? BaseDefinition { get; init; } public ? Body { get; init; } [.(..PublicMethods)] public override ClassType { get; } diff --git a/TUnit.PublicAPI/Tests.Core_Library_Has_No_API_Changes.Net4_7.verified.txt b/TUnit.PublicAPI/Tests.Core_Library_Has_No_API_Changes.Net4_7.verified.txt index e0b73a707b..035b2b9241 100644 --- a/TUnit.PublicAPI/Tests.Core_Library_Has_No_API_Changes.Net4_7.verified.txt +++ b/TUnit.PublicAPI/Tests.Core_Library_Has_No_API_Changes.Net4_7.verified.txt @@ -2264,6 +2264,7 @@ namespace .Hooks public class InstanceHookMethod : ., <.>, .<.TestContext> { public InstanceHookMethod() { } + public .MethodInfo? BaseDefinition { get; init; } public ? Body { get; init; } public override ClassType { get; } public required InitClassType { init; } diff --git a/TUnit.Templates/content/TUnit.AspNet.FSharp/TestProject/TestProject.fsproj b/TUnit.Templates/content/TUnit.AspNet.FSharp/TestProject/TestProject.fsproj index 67046d0579..1475d58407 100644 --- a/TUnit.Templates/content/TUnit.AspNet.FSharp/TestProject/TestProject.fsproj +++ b/TUnit.Templates/content/TUnit.AspNet.FSharp/TestProject/TestProject.fsproj @@ -10,8 +10,8 @@ - - + + diff --git a/TUnit.Templates/content/TUnit.AspNet/TestProject/TestProject.csproj b/TUnit.Templates/content/TUnit.AspNet/TestProject/TestProject.csproj index 7d1a6bb7c4..7d238a6aac 100644 --- a/TUnit.Templates/content/TUnit.AspNet/TestProject/TestProject.csproj +++ b/TUnit.Templates/content/TUnit.AspNet/TestProject/TestProject.csproj @@ -9,7 +9,7 @@ - + diff --git a/TUnit.Templates/content/TUnit.FSharp/TestProject.fsproj b/TUnit.Templates/content/TUnit.FSharp/TestProject.fsproj index e54e2d4f2b..97cbbb76fd 100644 --- a/TUnit.Templates/content/TUnit.FSharp/TestProject.fsproj +++ b/TUnit.Templates/content/TUnit.FSharp/TestProject.fsproj @@ -10,8 +10,8 @@ - - + + diff --git a/TUnit.Templates/content/TUnit.Playwright/TestProject.csproj b/TUnit.Templates/content/TUnit.Playwright/TestProject.csproj index 3afa031893..82e19449cb 100644 --- a/TUnit.Templates/content/TUnit.Playwright/TestProject.csproj +++ b/TUnit.Templates/content/TUnit.Playwright/TestProject.csproj @@ -8,7 +8,7 @@ - + diff --git a/TUnit.Templates/content/TUnit.VB/TestProject.vbproj b/TUnit.Templates/content/TUnit.VB/TestProject.vbproj index 5c876549a2..400d72887c 100644 --- a/TUnit.Templates/content/TUnit.VB/TestProject.vbproj +++ b/TUnit.Templates/content/TUnit.VB/TestProject.vbproj @@ -8,6 +8,6 @@ - + diff --git a/TUnit.TestProject/VirtualHookOverrideTests.cs b/TUnit.TestProject/VirtualHookOverrideTests.cs new file mode 100644 index 0000000000..b81754f58a --- /dev/null +++ b/TUnit.TestProject/VirtualHookOverrideTests.cs @@ -0,0 +1,67 @@ +using TUnit.Assertions; +using TUnit.Assertions.Extensions; +using TUnit.Core; +using TUnit.TestProject.Attributes; + +namespace TUnit.TestProject; + +// Regression test for https://github.com/thomhurst/TUnit/issues/5428 +// A virtual [Before(Test)]/[After(Test)] hook in a base class that is overridden +// in a derived class (also marked with the same hook attribute) should only execute +// the override once — not twice — because both registrations would otherwise be +// invoked via virtual dispatch on the same instance. +public class VirtualHookOverrideTests +{ + public class BaseTestClass + { + public int SetupCalls; + public int TeardownCalls; + + [Before(Test)] + public virtual Task SetupAsync() + { + SetupCalls++; + return Task.CompletedTask; + } + + [After(Test)] + public virtual Task TeardownAsync() + { + TeardownCalls++; + return Task.CompletedTask; + } + } + + public class DerivedTestClass : BaseTestClass + { + [Before(Test)] + public override async Task SetupAsync() + { + await base.SetupAsync(); + } + + [After(Test)] + public override async Task TeardownAsync() + { + await base.TeardownAsync(); + } + + [Test] + [EngineTest(ExpectedResult.Pass)] + public async Task Override_Should_Run_Once() + { + // TeardownCalls is verified by AfterTeardownAssertion below — by the time + // this test method runs, TeardownAsync has not yet executed (it's an After + // hook), so we can't assert it here. The dedicated [After(Test)] hook with + // Order = int.MaxValue runs last and performs the assertion. + await Assert.That(SetupCalls).IsEqualTo(1); + } + + // Runs after TeardownAsync to verify the After(Test) override also deduplicates. + [After(Test, Order = int.MaxValue)] + public async Task AfterTeardownAssertion() + { + await Assert.That(TeardownCalls).IsEqualTo(1); + } + } +} diff --git a/docs/docs/benchmarks/AsyncTests.md b/docs/docs/benchmarks/AsyncTests.md index c687a6e985..d0d70244d4 100644 --- a/docs/docs/benchmarks/AsyncTests.md +++ b/docs/docs/benchmarks/AsyncTests.md @@ -7,7 +7,7 @@ sidebar_position: 2 # AsyncTests Benchmark :::info Last Updated -This benchmark was automatically generated on **2026-04-05** from the latest CI run. +This benchmark was automatically generated on **2026-04-07** from the latest CI run. **Environment:** Ubuntu Latest • .NET SDK 10.0.201 ::: @@ -16,11 +16,11 @@ This benchmark was automatically generated on **2026-04-05** from the latest CI | Framework | Version | Mean | Median | StdDev | |-----------|---------|------|--------|--------| -| **TUnit** | 1.28.0 | 505.7 ms | 505.2 ms | 6.82 ms | -| NUnit | 4.5.1 | 706.6 ms | 706.2 ms | 6.41 ms | -| MSTest | 4.1.0 | 656.9 ms | 655.8 ms | 16.14 ms | -| xUnit3 | 3.2.2 | 768.3 ms | 768.5 ms | 5.76 ms | -| **TUnit (AOT)** | 1.28.0 | 122.6 ms | 122.6 ms | 0.16 ms | +| **TUnit** | 1.28.7 | 537.0 ms | 533.7 ms | 8.59 ms | +| NUnit | 4.5.1 | 723.0 ms | 719.3 ms | 11.39 ms | +| MSTest | 4.1.0 | 642.5 ms | 642.3 ms | 7.56 ms | +| xUnit3 | 3.2.2 | 780.5 ms | 780.5 ms | 6.61 ms | +| **TUnit (AOT)** | 1.28.7 | 122.7 ms | 122.7 ms | 0.26 ms | ## 📈 Visual Comparison @@ -58,8 +58,8 @@ This benchmark was automatically generated on **2026-04-05** from the latest CI xychart-beta title "AsyncTests Performance Comparison" x-axis ["TUnit", "NUnit", "MSTest", "xUnit3", "TUnit_AOT"] - y-axis "Time (ms)" 0 --> 922 - bar [505.7, 706.6, 656.9, 768.3, 122.6] + y-axis "Time (ms)" 0 --> 937 + bar [537, 723, 642.5, 780.5, 122.7] ``` ## 🎯 Key Insights @@ -72,4 +72,4 @@ This benchmark compares TUnit's performance against NUnit, MSTest, xUnit3 using View the [benchmarks overview](/docs/benchmarks) for methodology details and environment information. ::: -*Last generated: 2026-04-05T12:17:42.432Z* +*Last generated: 2026-04-07T00:41:20.830Z* diff --git a/docs/docs/benchmarks/BuildTime.md b/docs/docs/benchmarks/BuildTime.md index 2f0757f4f4..5910ddc7c6 100644 --- a/docs/docs/benchmarks/BuildTime.md +++ b/docs/docs/benchmarks/BuildTime.md @@ -7,7 +7,7 @@ sidebar_position: 8 # Build Performance Benchmark :::info Last Updated -This benchmark was automatically generated on **2026-04-05** from the latest CI run. +This benchmark was automatically generated on **2026-04-07** from the latest CI run. **Environment:** Ubuntu Latest • .NET SDK 10.0.201 ::: @@ -18,10 +18,10 @@ Compilation time comparison across frameworks: | Framework | Version | Mean | Median | StdDev | |-----------|---------|------|--------|--------| -| **TUnit** | 1.28.0 | 1.820 s | 1.826 s | 0.0207 s | -| Build_NUnit | 4.5.1 | 1.626 s | 1.622 s | 0.0143 s | -| Build_MSTest | 4.1.0 | 1.708 s | 1.710 s | 0.0147 s | -| Build_xUnit3 | 3.2.2 | 1.671 s | 1.663 s | 0.0193 s | +| **TUnit** | 1.28.7 | 1.789 s | 1.789 s | 0.0248 s | +| Build_NUnit | 4.5.1 | 1.601 s | 1.599 s | 0.0171 s | +| Build_MSTest | 4.1.0 | 1.655 s | 1.657 s | 0.0210 s | +| Build_xUnit3 | 3.2.2 | 1.598 s | 1.600 s | 0.0185 s | ## 📈 Visual Comparison @@ -60,7 +60,7 @@ xychart-beta title "Build Time Comparison" x-axis ["Build_TUnit", "Build_NUnit", "Build_MSTest", "Build_xUnit3"] y-axis "Time (s)" 0 --> 3 - bar [1.82, 1.626, 1.708, 1.671] + bar [1.789, 1.601, 1.655, 1.598] ``` --- @@ -69,4 +69,4 @@ xychart-beta View the [benchmarks overview](/docs/benchmarks) for methodology details and environment information. ::: -*Last generated: 2026-04-05T12:17:42.434Z* +*Last generated: 2026-04-07T00:41:20.832Z* diff --git a/docs/docs/benchmarks/DataDrivenTests.md b/docs/docs/benchmarks/DataDrivenTests.md index 58b0ffc527..21ecc7435a 100644 --- a/docs/docs/benchmarks/DataDrivenTests.md +++ b/docs/docs/benchmarks/DataDrivenTests.md @@ -7,7 +7,7 @@ sidebar_position: 3 # DataDrivenTests Benchmark :::info Last Updated -This benchmark was automatically generated on **2026-04-05** from the latest CI run. +This benchmark was automatically generated on **2026-04-07** from the latest CI run. **Environment:** Ubuntu Latest • .NET SDK 10.0.201 ::: @@ -16,11 +16,11 @@ This benchmark was automatically generated on **2026-04-05** from the latest CI | Framework | Version | Mean | Median | StdDev | |-----------|---------|------|--------|--------| -| **TUnit** | 1.28.0 | 469.70 ms | 467.78 ms | 5.628 ms | -| NUnit | 4.5.1 | 565.08 ms | 565.43 ms | 5.414 ms | -| MSTest | 4.1.0 | 533.97 ms | 534.35 ms | 7.510 ms | -| xUnit3 | 3.2.2 | 607.03 ms | 604.60 ms | 6.753 ms | -| **TUnit (AOT)** | 1.28.0 | 23.48 ms | 23.37 ms | 0.751 ms | +| **TUnit** | 1.28.7 | 477.77 ms | 476.42 ms | 4.391 ms | +| NUnit | 4.5.1 | 572.28 ms | 570.99 ms | 10.671 ms | +| MSTest | 4.1.0 | 475.82 ms | 474.11 ms | 6.745 ms | +| xUnit3 | 3.2.2 | 601.72 ms | 601.20 ms | 5.797 ms | +| **TUnit (AOT)** | 1.28.7 | 24.35 ms | 24.27 ms | 0.602 ms | ## 📈 Visual Comparison @@ -58,8 +58,8 @@ This benchmark was automatically generated on **2026-04-05** from the latest CI xychart-beta title "DataDrivenTests Performance Comparison" x-axis ["TUnit", "NUnit", "MSTest", "xUnit3", "TUnit_AOT"] - y-axis "Time (ms)" 0 --> 729 - bar [469.7, 565.08, 533.97, 607.03, 23.48] + y-axis "Time (ms)" 0 --> 723 + bar [477.77, 572.28, 475.82, 601.72, 24.35] ``` ## 🎯 Key Insights @@ -72,4 +72,4 @@ This benchmark compares TUnit's performance against NUnit, MSTest, xUnit3 using View the [benchmarks overview](/docs/benchmarks) for methodology details and environment information. ::: -*Last generated: 2026-04-05T12:17:42.433Z* +*Last generated: 2026-04-07T00:41:20.831Z* diff --git a/docs/docs/benchmarks/MassiveParallelTests.md b/docs/docs/benchmarks/MassiveParallelTests.md index 7e31402616..3788b0c3bb 100644 --- a/docs/docs/benchmarks/MassiveParallelTests.md +++ b/docs/docs/benchmarks/MassiveParallelTests.md @@ -7,7 +7,7 @@ sidebar_position: 4 # MassiveParallelTests Benchmark :::info Last Updated -This benchmark was automatically generated on **2026-04-05** from the latest CI run. +This benchmark was automatically generated on **2026-04-07** from the latest CI run. **Environment:** Ubuntu Latest • .NET SDK 10.0.201 ::: @@ -16,11 +16,11 @@ This benchmark was automatically generated on **2026-04-05** from the latest CI | Framework | Version | Mean | Median | StdDev | |-----------|---------|------|--------|--------| -| **TUnit** | 1.28.0 | 664.9 ms | 665.0 ms | 2.53 ms | -| NUnit | 4.5.1 | 1,250.3 ms | 1,249.9 ms | 7.27 ms | -| MSTest | 4.1.0 | 2,978.5 ms | 2,979.2 ms | 10.39 ms | -| xUnit3 | 3.2.2 | 3,113.2 ms | 3,111.6 ms | 11.60 ms | -| **TUnit (AOT)** | 1.28.0 | 228.5 ms | 228.5 ms | 0.51 ms | +| **TUnit** | 1.28.7 | 655.8 ms | 655.1 ms | 3.64 ms | +| NUnit | 4.5.1 | 1,209.7 ms | 1,208.3 ms | 5.22 ms | +| MSTest | 4.1.0 | 2,949.8 ms | 2,950.1 ms | 6.09 ms | +| xUnit3 | 3.2.2 | 3,078.4 ms | 3,076.3 ms | 10.02 ms | +| **TUnit (AOT)** | 1.28.7 | 229.8 ms | 229.8 ms | 0.54 ms | ## 📈 Visual Comparison @@ -58,8 +58,8 @@ This benchmark was automatically generated on **2026-04-05** from the latest CI xychart-beta title "MassiveParallelTests Performance Comparison" x-axis ["TUnit", "NUnit", "MSTest", "xUnit3", "TUnit_AOT"] - y-axis "Time (ms)" 0 --> 3736 - bar [664.9, 1250.3, 2978.5, 3113.2, 228.5] + y-axis "Time (ms)" 0 --> 3695 + bar [655.8, 1209.7, 2949.8, 3078.4, 229.8] ``` ## 🎯 Key Insights @@ -72,4 +72,4 @@ This benchmark compares TUnit's performance against NUnit, MSTest, xUnit3 using View the [benchmarks overview](/docs/benchmarks) for methodology details and environment information. ::: -*Last generated: 2026-04-05T12:17:42.433Z* +*Last generated: 2026-04-07T00:41:20.831Z* diff --git a/docs/docs/benchmarks/MatrixTests.md b/docs/docs/benchmarks/MatrixTests.md index 20fde6c30a..57a70921c8 100644 --- a/docs/docs/benchmarks/MatrixTests.md +++ b/docs/docs/benchmarks/MatrixTests.md @@ -7,7 +7,7 @@ sidebar_position: 5 # MatrixTests Benchmark :::info Last Updated -This benchmark was automatically generated on **2026-04-05** from the latest CI run. +This benchmark was automatically generated on **2026-04-07** from the latest CI run. **Environment:** Ubuntu Latest • .NET SDK 10.0.201 ::: @@ -16,11 +16,11 @@ This benchmark was automatically generated on **2026-04-05** from the latest CI | Framework | Version | Mean | Median | StdDev | |-----------|---------|------|--------|--------| -| **TUnit** | 1.28.0 | 631.5 ms | 632.6 ms | 15.52 ms | -| NUnit | 4.5.1 | 1,674.5 ms | 1,681.0 ms | 10.40 ms | -| MSTest | 4.1.0 | 1,555.3 ms | 1,553.1 ms | 11.07 ms | -| xUnit3 | 3.2.2 | 1,697.4 ms | 1,695.2 ms | 9.00 ms | -| **TUnit (AOT)** | 1.28.0 | 127.7 ms | 127.7 ms | 0.43 ms | +| **TUnit** | 1.28.7 | 576.1 ms | 576.5 ms | 2.99 ms | +| NUnit | 4.5.1 | 1,599.7 ms | 1,599.7 ms | 7.78 ms | +| MSTest | 4.1.0 | 1,514.0 ms | 1,513.5 ms | 4.78 ms | +| xUnit3 | 3.2.2 | 1,646.2 ms | 1,646.6 ms | 4.29 ms | +| **TUnit (AOT)** | 1.28.7 | 125.6 ms | 125.5 ms | 0.47 ms | ## 📈 Visual Comparison @@ -58,8 +58,8 @@ This benchmark was automatically generated on **2026-04-05** from the latest CI xychart-beta title "MatrixTests Performance Comparison" x-axis ["TUnit", "NUnit", "MSTest", "xUnit3", "TUnit_AOT"] - y-axis "Time (ms)" 0 --> 2037 - bar [631.5, 1674.5, 1555.3, 1697.4, 127.7] + y-axis "Time (ms)" 0 --> 1976 + bar [576.1, 1599.7, 1514, 1646.2, 125.6] ``` ## 🎯 Key Insights @@ -72,4 +72,4 @@ This benchmark compares TUnit's performance against NUnit, MSTest, xUnit3 using View the [benchmarks overview](/docs/benchmarks) for methodology details and environment information. ::: -*Last generated: 2026-04-05T12:17:42.433Z* +*Last generated: 2026-04-07T00:41:20.831Z* diff --git a/docs/docs/benchmarks/ScaleTests.md b/docs/docs/benchmarks/ScaleTests.md index e085ec5404..bcb885e26b 100644 --- a/docs/docs/benchmarks/ScaleTests.md +++ b/docs/docs/benchmarks/ScaleTests.md @@ -7,7 +7,7 @@ sidebar_position: 6 # ScaleTests Benchmark :::info Last Updated -This benchmark was automatically generated on **2026-04-05** from the latest CI run. +This benchmark was automatically generated on **2026-04-07** from the latest CI run. **Environment:** Ubuntu Latest • .NET SDK 10.0.201 ::: @@ -16,11 +16,11 @@ This benchmark was automatically generated on **2026-04-05** from the latest CI | Framework | Version | Mean | Median | StdDev | |-----------|---------|------|--------|--------| -| **TUnit** | 1.28.0 | 491.08 ms | 490.42 ms | 2.965 ms | -| NUnit | 4.5.1 | 615.08 ms | 614.65 ms | 6.136 ms | -| MSTest | 4.1.0 | 484.99 ms | 485.09 ms | 5.586 ms | -| xUnit3 | 3.2.2 | 618.10 ms | 617.83 ms | 6.935 ms | -| **TUnit (AOT)** | 1.28.0 | 34.31 ms | 33.79 ms | 2.304 ms | +| **TUnit** | 1.28.7 | 445.59 ms | 444.78 ms | 4.222 ms | +| NUnit | 4.5.1 | 566.13 ms | 562.76 ms | 7.771 ms | +| MSTest | 4.1.0 | 553.10 ms | 551.91 ms | 13.281 ms | +| xUnit3 | 3.2.2 | 585.75 ms | 588.12 ms | 7.012 ms | +| **TUnit (AOT)** | 1.28.7 | 36.53 ms | 36.72 ms | 3.464 ms | ## 📈 Visual Comparison @@ -58,8 +58,8 @@ This benchmark was automatically generated on **2026-04-05** from the latest CI xychart-beta title "ScaleTests Performance Comparison" x-axis ["TUnit", "NUnit", "MSTest", "xUnit3", "TUnit_AOT"] - y-axis "Time (ms)" 0 --> 742 - bar [491.08, 615.08, 484.99, 618.1, 34.31] + y-axis "Time (ms)" 0 --> 703 + bar [445.59, 566.13, 553.1, 585.75, 36.53] ``` ## 🎯 Key Insights @@ -72,4 +72,4 @@ This benchmark compares TUnit's performance against NUnit, MSTest, xUnit3 using View the [benchmarks overview](/docs/benchmarks) for methodology details and environment information. ::: -*Last generated: 2026-04-05T12:17:42.433Z* +*Last generated: 2026-04-07T00:41:20.832Z* diff --git a/docs/docs/benchmarks/SetupTeardownTests.md b/docs/docs/benchmarks/SetupTeardownTests.md index 3da16b9150..f8d80ec6a0 100644 --- a/docs/docs/benchmarks/SetupTeardownTests.md +++ b/docs/docs/benchmarks/SetupTeardownTests.md @@ -7,7 +7,7 @@ sidebar_position: 7 # SetupTeardownTests Benchmark :::info Last Updated -This benchmark was automatically generated on **2026-04-05** from the latest CI run. +This benchmark was automatically generated on **2026-04-07** from the latest CI run. **Environment:** Ubuntu Latest • .NET SDK 10.0.201 ::: @@ -16,11 +16,11 @@ This benchmark was automatically generated on **2026-04-05** from the latest CI | Framework | Version | Mean | Median | StdDev | |-----------|---------|------|--------|--------| -| **TUnit** | 1.28.0 | 572.6 ms | 572.7 ms | 2.38 ms | -| NUnit | 4.5.1 | 1,183.8 ms | 1,182.1 ms | 9.10 ms | -| MSTest | 4.1.0 | 1,103.4 ms | 1,102.0 ms | 5.06 ms | -| xUnit3 | 3.2.2 | 1,239.0 ms | 1,237.5 ms | 8.66 ms | -| **TUnit (AOT)** | 1.28.0 | NA | NA | NA | +| **TUnit** | 1.28.7 | 582.0 ms | 579.9 ms | 5.86 ms | +| NUnit | 4.5.1 | 1,227.8 ms | 1,224.4 ms | 12.92 ms | +| MSTest | 4.1.0 | 1,150.4 ms | 1,149.8 ms | 7.80 ms | +| xUnit3 | 3.2.2 | 1,275.3 ms | 1,276.5 ms | 5.95 ms | +| **TUnit (AOT)** | 1.28.7 | NA | NA | NA | ## 📈 Visual Comparison @@ -58,8 +58,8 @@ This benchmark was automatically generated on **2026-04-05** from the latest CI xychart-beta title "SetupTeardownTests Performance Comparison" x-axis ["TUnit", "NUnit", "MSTest", "xUnit3", "TUnit_AOT"] - y-axis "Time (ms)" 0 --> 1487 - bar [572.6, 1183.8, 1103.4, 1239, 0] + y-axis "Time (ms)" 0 --> 1531 + bar [582, 1227.8, 1150.4, 1275.3, 0] ``` ## 🎯 Key Insights @@ -72,4 +72,4 @@ This benchmark compares TUnit's performance against NUnit, MSTest, xUnit3 using View the [benchmarks overview](/docs/benchmarks) for methodology details and environment information. ::: -*Last generated: 2026-04-05T12:17:42.434Z* +*Last generated: 2026-04-07T00:41:20.832Z* diff --git a/docs/docs/benchmarks/index.md b/docs/docs/benchmarks/index.md index 09d1008efb..64651fc92e 100644 --- a/docs/docs/benchmarks/index.md +++ b/docs/docs/benchmarks/index.md @@ -7,7 +7,7 @@ sidebar_position: 1 # Performance Benchmarks :::info Last Updated -These benchmarks were automatically generated on **2026-04-05** from the latest CI run. +These benchmarks were automatically generated on **2026-04-07** from the latest CI run. **Environment:** Ubuntu Latest • .NET SDK 10.0.201 ::: @@ -37,7 +37,7 @@ These benchmarks compare TUnit against the most popular .NET testing frameworks: | Framework | Version Tested | |-----------|----------------| -| **TUnit** | 1.28.0 | +| **TUnit** | 1.28.7 | | **xUnit v3** | 3.2.2 | | **NUnit** | 4.5.1 | | **MSTest** | 4.1.0 | @@ -80,4 +80,4 @@ These benchmarks run automatically daily via [GitHub Actions](https://github.com Each benchmark runs multiple iterations with statistical analysis to ensure accuracy. Results may vary based on hardware and test characteristics. ::: -*Last generated: 2026-04-05T12:17:42.434Z* +*Last generated: 2026-04-07T00:41:20.833Z* diff --git a/docs/docs/benchmarks/mocks/Callback.md b/docs/docs/benchmarks/mocks/Callback.md index 9c3924c9ea..2784b94a3e 100644 --- a/docs/docs/benchmarks/mocks/Callback.md +++ b/docs/docs/benchmarks/mocks/Callback.md @@ -7,7 +7,7 @@ sidebar_position: 2 # Callback Benchmark :::info Last Updated -This benchmark was automatically generated on **2026-04-05** from the latest CI run. +This benchmark was automatically generated on **2026-04-07** from the latest CI run. **Environment:** Ubuntu Latest • .NET SDK 10.0.201 ::: @@ -18,12 +18,12 @@ Callback registration and execution: | Library | Mean | Error | StdDev | Allocated | |---------|------|-------|--------|-----------| -| **TUnit.Mocks** | 651.9 ns | 2.29 ns | 1.91 ns | 3.06 KB | -| Imposter | 483.2 ns | 3.31 ns | 3.09 ns | 2.66 KB | -| Mockolate | 540.0 ns | 10.61 ns | 18.59 ns | 1.8 KB | -| Moq | 184,643.6 ns | 1,840.32 ns | 1,721.44 ns | 13.14 KB | -| NSubstitute | 4,630.0 ns | 48.81 ns | 45.66 ns | 7.93 KB | -| FakeItEasy | 5,166.1 ns | 84.52 ns | 79.06 ns | 7.44 KB | +| **TUnit.Mocks** | 746.7 ns | 14.03 ns | 14.40 ns | 3.06 KB | +| Imposter | 500.0 ns | 9.96 ns | 19.42 ns | 2.66 KB | +| Mockolate | 517.9 ns | 7.25 ns | 6.06 ns | 1.8 KB | +| Moq | 188,044.7 ns | 1,407.17 ns | 1,316.27 ns | 13.3 KB | +| NSubstitute | 4,661.9 ns | 52.37 ns | 48.99 ns | 7.93 KB | +| FakeItEasy | 5,463.0 ns | 75.66 ns | 70.77 ns | 7.44 KB | ```mermaid %%{init: { @@ -49,8 +49,8 @@ Callback registration and execution: xychart-beta title "Callback Performance Comparison" x-axis ["TUnit.Mocks", "Imposter", "Mockolate", "Moq", "NSubstitute", "FakeItEasy"] - y-axis "Time (ns)" 0 --> 221573 - bar [651.9, 483.2, 540, 184643.6, 4630, 5166.1] + y-axis "Time (ns)" 0 --> 225654 + bar [746.7, 500, 517.9, 188044.7, 4661.9, 5463] ``` --- @@ -59,12 +59,12 @@ xychart-beta | Library | Mean | Error | StdDev | Allocated | |---------|------|-------|--------|-----------| -| **TUnit.Mocks** | 772.7 ns | 4.57 ns | 4.27 ns | 3.23 KB | -| Imposter | 541.6 ns | 10.67 ns | 15.97 ns | 2.82 KB | -| Mockolate | 662.3 ns | 11.28 ns | 10.55 ns | 2.13 KB | -| Moq | 194,142.1 ns | 1,422.32 ns | 1,330.44 ns | 13.84 KB | -| NSubstitute | 5,128.9 ns | 70.64 ns | 62.62 ns | 8.53 KB | -| FakeItEasy | 6,309.5 ns | 114.70 ns | 101.68 ns | 9.26 KB | +| **TUnit.Mocks** | 814.2 ns | 14.65 ns | 13.70 ns | 3.15 KB | +| Imposter | 598.2 ns | 11.57 ns | 11.36 ns | 2.82 KB | +| Mockolate | 676.7 ns | 13.37 ns | 19.59 ns | 2.13 KB | +| Moq | 193,932.5 ns | 2,062.51 ns | 1,929.28 ns | 13.73 KB | +| NSubstitute | 5,182.1 ns | 65.78 ns | 61.53 ns | 8.53 KB | +| FakeItEasy | 6,631.6 ns | 75.42 ns | 70.55 ns | 9.4 KB | ```mermaid %%{init: { @@ -90,8 +90,8 @@ xychart-beta xychart-beta title "Callback (with args) Performance Comparison" x-axis ["TUnit.Mocks", "Imposter", "Mockolate", "Moq", "NSubstitute", "FakeItEasy"] - y-axis "Time (ns)" 0 --> 232971 - bar [772.7, 541.6, 662.3, 194142.1, 5128.9, 6309.5] + y-axis "Time (ns)" 0 --> 232719 + bar [814.2, 598.2, 676.7, 193932.5, 5182.1, 6631.6] ``` ## 🎯 Key Insights @@ -104,4 +104,4 @@ This benchmark compares **TUnit.Mocks** (source-generated) against runtime proxy View the [mock benchmarks overview](/docs/benchmarks/mocks) for methodology details and environment information. ::: -*Last generated: 2026-04-05T03:32:35.400Z* +*Last generated: 2026-04-07T03:21:31.527Z* diff --git a/docs/docs/benchmarks/mocks/CombinedWorkflow.md b/docs/docs/benchmarks/mocks/CombinedWorkflow.md index 4bcd0e27b2..2c92695f19 100644 --- a/docs/docs/benchmarks/mocks/CombinedWorkflow.md +++ b/docs/docs/benchmarks/mocks/CombinedWorkflow.md @@ -7,7 +7,7 @@ sidebar_position: 3 # CombinedWorkflow Benchmark :::info Last Updated -This benchmark was automatically generated on **2026-04-05** from the latest CI run. +This benchmark was automatically generated on **2026-04-07** from the latest CI run. **Environment:** Ubuntu Latest • .NET SDK 10.0.201 ::: @@ -18,12 +18,12 @@ Full workflow: create → setup → invoke → verify: | Library | Mean | Error | StdDev | Allocated | |---------|------|-------|--------|-----------| -| **TUnit.Mocks** | 1.864 μs | 0.0168 μs | 0.0157 μs | 6.01 KB | -| Imposter | 2.623 μs | 0.0306 μs | 0.0287 μs | 15.71 KB | -| Mockolate | 2.346 μs | 0.0240 μs | 0.0224 μs | 7.09 KB | -| Moq | 403.794 μs | 2.7482 μs | 2.5707 μs | 36.38 KB | -| NSubstitute | 16.942 μs | 0.1111 μs | 0.1039 μs | 26.72 KB | -| FakeItEasy | 18.390 μs | 0.2776 μs | 0.2461 μs | 25.52 KB | +| **TUnit.Mocks** | 2.035 μs | 0.0399 μs | 0.0491 μs | 6.14 KB | +| Imposter | 2.746 μs | 0.0511 μs | 0.0478 μs | 15.71 KB | +| Mockolate | 2.562 μs | 0.0510 μs | 0.0681 μs | 7.09 KB | +| Moq | 403.167 μs | 3.3674 μs | 2.8119 μs | 36.74 KB | +| NSubstitute | 17.244 μs | 0.2324 μs | 0.2174 μs | 26.72 KB | +| FakeItEasy | 18.200 μs | 0.3194 μs | 0.3280 μs | 25.52 KB | ```mermaid %%{init: { @@ -49,8 +49,8 @@ Full workflow: create → setup → invoke → verify: xychart-beta title "CombinedWorkflow Performance Comparison" x-axis ["TUnit.Mocks", "Imposter", "Mockolate", "Moq", "NSubstitute", "FakeItEasy"] - y-axis "Time (μs)" 0 --> 485 - bar [1.864, 2.623, 2.346, 403.794, 16.942, 18.39] + y-axis "Time (μs)" 0 --> 484 + bar [2.035, 2.746, 2.562, 403.167, 17.244, 18.2] ``` ## 🎯 Key Insights @@ -63,4 +63,4 @@ This benchmark compares **TUnit.Mocks** (source-generated) against runtime proxy View the [mock benchmarks overview](/docs/benchmarks/mocks) for methodology details and environment information. ::: -*Last generated: 2026-04-05T03:32:35.400Z* +*Last generated: 2026-04-07T03:21:31.527Z* diff --git a/docs/docs/benchmarks/mocks/Invocation.md b/docs/docs/benchmarks/mocks/Invocation.md index 609b544197..7c5e7460a4 100644 --- a/docs/docs/benchmarks/mocks/Invocation.md +++ b/docs/docs/benchmarks/mocks/Invocation.md @@ -7,7 +7,7 @@ sidebar_position: 4 # Invocation Benchmark :::info Last Updated -This benchmark was automatically generated on **2026-04-05** from the latest CI run. +This benchmark was automatically generated on **2026-04-07** from the latest CI run. **Environment:** Ubuntu Latest • .NET SDK 10.0.201 ::: @@ -18,12 +18,12 @@ Calling methods on mock objects: | Library | Mean | Error | StdDev | Allocated | |---------|------|-------|--------|-----------| -| **TUnit.Mocks** | 368.7 ns | 234.41 ns | 12.85 ns | 176 B | -| Imposter | 367.0 ns | 102.23 ns | 5.60 ns | 168 B | -| Mockolate | 796.7 ns | 374.54 ns | 20.53 ns | 640 B | -| Moq | 913.9 ns | 344.02 ns | 18.86 ns | 376 B | -| NSubstitute | 809.3 ns | 236.18 ns | 12.95 ns | 304 B | -| FakeItEasy | 2,020.7 ns | 645.01 ns | 35.35 ns | 944 B | +| **TUnit.Mocks** | 261.5 ns | 85.01 ns | 4.66 ns | 120 B | +| Imposter | 296.5 ns | 100.09 ns | 5.49 ns | 168 B | +| Mockolate | 707.3 ns | 238.12 ns | 13.05 ns | 640 B | +| Moq | 838.3 ns | 187.87 ns | 10.30 ns | 376 B | +| NSubstitute | 752.6 ns | 191.36 ns | 10.49 ns | 304 B | +| FakeItEasy | 1,883.0 ns | 949.75 ns | 52.06 ns | 944 B | ```mermaid %%{init: { @@ -49,8 +49,8 @@ Calling methods on mock objects: xychart-beta title "Invocation Performance Comparison" x-axis ["TUnit.Mocks", "Imposter", "Mockolate", "Moq", "NSubstitute", "FakeItEasy"] - y-axis "Time (ns)" 0 --> 2425 - bar [368.7, 367, 796.7, 913.9, 809.3, 2020.7] + y-axis "Time (ns)" 0 --> 2260 + bar [261.5, 296.5, 707.3, 838.3, 752.6, 1883] ``` --- @@ -59,12 +59,12 @@ xychart-beta | Library | Mean | Error | StdDev | Allocated | |---------|------|-------|--------|-----------| -| **TUnit.Mocks** | 227.7 ns | 147.17 ns | 8.07 ns | 112 B | -| Imposter | 364.0 ns | 148.82 ns | 8.16 ns | 168 B | -| Mockolate | 722.7 ns | 357.53 ns | 19.60 ns | 520 B | -| Moq | 608.3 ns | 45.72 ns | 2.51 ns | 296 B | -| NSubstitute | 720.7 ns | 116.44 ns | 6.38 ns | 328 B | -| FakeItEasy | 1,753.1 ns | 715.60 ns | 39.22 ns | 776 B | +| **TUnit.Mocks** | 157.6 ns | 68.10 ns | 3.73 ns | 88 B | +| Imposter | 302.9 ns | 87.59 ns | 4.80 ns | 168 B | +| Mockolate | 551.7 ns | 483.54 ns | 26.50 ns | 520 B | +| Moq | 547.3 ns | 352.10 ns | 19.30 ns | 296 B | +| NSubstitute | 594.6 ns | 152.85 ns | 8.38 ns | 272 B | +| FakeItEasy | 1,584.9 ns | 360.99 ns | 19.79 ns | 776 B | ```mermaid %%{init: { @@ -90,8 +90,8 @@ xychart-beta xychart-beta title "Invocation (String) Performance Comparison" x-axis ["TUnit.Mocks", "Imposter", "Mockolate", "Moq", "NSubstitute", "FakeItEasy"] - y-axis "Time (ns)" 0 --> 2104 - bar [227.7, 364, 722.7, 608.3, 720.7, 1753.1] + y-axis "Time (ns)" 0 --> 1902 + bar [157.6, 302.9, 551.7, 547.3, 594.6, 1584.9] ``` --- @@ -100,12 +100,12 @@ xychart-beta | Library | Mean | Error | StdDev | Allocated | |---------|------|-------|--------|-----------| -| **TUnit.Mocks** | 39,741.9 ns | 12,503.76 ns | 685.37 ns | 18048 B | -| Imposter | 37,376.4 ns | 54,157.26 ns | 2,968.54 ns | 16800 B | -| Mockolate | 77,269.3 ns | 43,532.15 ns | 2,386.14 ns | 64000 B | -| Moq | 88,134.5 ns | 65,537.69 ns | 3,592.34 ns | 37600 B | -| NSubstitute | 81,687.5 ns | 38,698.53 ns | 2,121.20 ns | 36448 B | -| FakeItEasy | 207,688.7 ns | 7,905.08 ns | 433.30 ns | 94400 B | +| **TUnit.Mocks** | 25,713.5 ns | 8,104.61 ns | 444.24 ns | 11936 B | +| Imposter | 28,487.4 ns | 10,084.31 ns | 552.76 ns | 16800 B | +| Mockolate | 66,299.9 ns | 33,448.67 ns | 1,833.43 ns | 64000 B | +| Moq | 79,836.2 ns | 20,420.16 ns | 1,119.30 ns | 37600 B | +| NSubstitute | 74,687.4 ns | 39,403.14 ns | 2,159.82 ns | 30848 B | +| FakeItEasy | 182,809.1 ns | 61,051.13 ns | 3,346.42 ns | 94400 B | ```mermaid %%{init: { @@ -131,8 +131,8 @@ xychart-beta xychart-beta title "Invocation (100 calls) Performance Comparison" x-axis ["TUnit.Mocks", "Imposter", "Mockolate", "Moq", "NSubstitute", "FakeItEasy"] - y-axis "Time (ns)" 0 --> 249227 - bar [39741.9, 37376.4, 77269.3, 88134.5, 81687.5, 207688.7] + y-axis "Time (ns)" 0 --> 219371 + bar [25713.5, 28487.4, 66299.9, 79836.2, 74687.4, 182809.1] ``` ## 🎯 Key Insights @@ -145,4 +145,4 @@ This benchmark compares **TUnit.Mocks** (source-generated) against runtime proxy View the [mock benchmarks overview](/docs/benchmarks/mocks) for methodology details and environment information. ::: -*Last generated: 2026-04-05T03:32:35.400Z* +*Last generated: 2026-04-07T03:21:31.527Z* diff --git a/docs/docs/benchmarks/mocks/MockCreation.md b/docs/docs/benchmarks/mocks/MockCreation.md index b588c82193..5698cd5602 100644 --- a/docs/docs/benchmarks/mocks/MockCreation.md +++ b/docs/docs/benchmarks/mocks/MockCreation.md @@ -7,7 +7,7 @@ sidebar_position: 5 # MockCreation Benchmark :::info Last Updated -This benchmark was automatically generated on **2026-04-05** from the latest CI run. +This benchmark was automatically generated on **2026-04-07** from the latest CI run. **Environment:** Ubuntu Latest • .NET SDK 10.0.201 ::: @@ -18,12 +18,12 @@ Mock instance creation performance: | Library | Mean | Error | StdDev | Allocated | |---------|------|-------|--------|-----------| -| **TUnit.Mocks** | 37.32 ns | 0.593 ns | 0.554 ns | 200 B | -| Imposter | 94.75 ns | 1.223 ns | 1.144 ns | 440 B | -| Mockolate | 68.77 ns | 0.875 ns | 0.775 ns | 384 B | -| Moq | 1,377.57 ns | 26.231 ns | 24.536 ns | 2048 B | -| NSubstitute | 1,867.26 ns | 19.052 ns | 17.821 ns | 5000 B | -| FakeItEasy | 1,774.46 ns | 24.029 ns | 21.301 ns | 2715 B | +| **TUnit.Mocks** | 34.95 ns | 0.706 ns | 0.626 ns | 200 B | +| Imposter | 88.70 ns | 1.127 ns | 0.999 ns | 440 B | +| Mockolate | 63.69 ns | 1.006 ns | 0.840 ns | 384 B | +| Moq | 1,412.49 ns | 23.782 ns | 22.246 ns | 2048 B | +| NSubstitute | 1,821.28 ns | 21.288 ns | 18.871 ns | 5000 B | +| FakeItEasy | 1,749.58 ns | 25.421 ns | 22.535 ns | 2715 B | ```mermaid %%{init: { @@ -49,8 +49,8 @@ Mock instance creation performance: xychart-beta title "MockCreation Performance Comparison" x-axis ["TUnit.Mocks", "Imposter", "Mockolate", "Moq", "NSubstitute", "FakeItEasy"] - y-axis "Time (ns)" 0 --> 2241 - bar [37.32, 94.75, 68.77, 1377.57, 1867.26, 1774.46] + y-axis "Time (ns)" 0 --> 2186 + bar [34.95, 88.7, 63.69, 1412.49, 1821.28, 1749.58] ``` --- @@ -59,12 +59,12 @@ xychart-beta | Library | Mean | Error | StdDev | Allocated | |---------|------|-------|--------|-----------| -| **TUnit.Mocks** | 37.30 ns | 0.425 ns | 0.397 ns | 200 B | -| Imposter | 145.91 ns | 1.850 ns | 1.545 ns | 696 B | -| Mockolate | 69.91 ns | 1.155 ns | 1.081 ns | 384 B | -| Moq | 1,342.37 ns | 7.233 ns | 6.411 ns | 1912 B | -| NSubstitute | 1,821.67 ns | 10.874 ns | 9.639 ns | 5000 B | -| FakeItEasy | 1,876.09 ns | 37.231 ns | 34.826 ns | 2715 B | +| **TUnit.Mocks** | 36.22 ns | 0.593 ns | 0.555 ns | 200 B | +| Imposter | 138.26 ns | 1.636 ns | 1.531 ns | 696 B | +| Mockolate | 64.42 ns | 0.694 ns | 0.615 ns | 384 B | +| Moq | 1,277.66 ns | 10.361 ns | 8.652 ns | 1912 B | +| NSubstitute | 1,891.54 ns | 17.627 ns | 16.489 ns | 5000 B | +| FakeItEasy | 1,863.22 ns | 26.136 ns | 23.169 ns | 2715 B | ```mermaid %%{init: { @@ -90,8 +90,8 @@ xychart-beta xychart-beta title "MockCreation (Repository) Performance Comparison" x-axis ["TUnit.Mocks", "Imposter", "Mockolate", "Moq", "NSubstitute", "FakeItEasy"] - y-axis "Time (ns)" 0 --> 2252 - bar [37.3, 145.91, 69.91, 1342.37, 1821.67, 1876.09] + y-axis "Time (ns)" 0 --> 2270 + bar [36.22, 138.26, 64.42, 1277.66, 1891.54, 1863.22] ``` ## 🎯 Key Insights @@ -104,4 +104,4 @@ This benchmark compares **TUnit.Mocks** (source-generated) against runtime proxy View the [mock benchmarks overview](/docs/benchmarks/mocks) for methodology details and environment information. ::: -*Last generated: 2026-04-05T03:32:35.400Z* +*Last generated: 2026-04-07T03:21:31.527Z* diff --git a/docs/docs/benchmarks/mocks/Setup.md b/docs/docs/benchmarks/mocks/Setup.md index 3aadbfb9d2..61b47168e3 100644 --- a/docs/docs/benchmarks/mocks/Setup.md +++ b/docs/docs/benchmarks/mocks/Setup.md @@ -7,7 +7,7 @@ sidebar_position: 6 # Setup Benchmark :::info Last Updated -This benchmark was automatically generated on **2026-04-05** from the latest CI run. +This benchmark was automatically generated on **2026-04-07** from the latest CI run. **Environment:** Ubuntu Latest • .NET SDK 10.0.201 ::: @@ -18,12 +18,12 @@ Mock behavior configuration (returns, matchers): | Library | Mean | Error | StdDev | Allocated | |---------|------|-------|--------|-----------| -| **TUnit.Mocks** | 492.4 ns | 1.09 ns | 0.85 ns | 2.03 KB | -| Imposter | 774.2 ns | 6.49 ns | 6.07 ns | 6.12 KB | -| Mockolate | 424.9 ns | 1.96 ns | 1.53 ns | 2.03 KB | -| Moq | 421,701.0 ns | 1,383.27 ns | 1,155.09 ns | 28.76 KB | -| NSubstitute | 5,305.7 ns | 48.80 ns | 40.75 ns | 9.01 KB | -| FakeItEasy | 8,075.6 ns | 43.50 ns | 38.56 ns | 10.53 KB | +| **TUnit.Mocks** | 524.9 ns | 6.89 ns | 6.45 ns | 2.03 KB | +| Imposter | 828.1 ns | 14.57 ns | 12.91 ns | 6.12 KB | +| Mockolate | 472.7 ns | 8.07 ns | 7.54 ns | 2.03 KB | +| Moq | 421,754.9 ns | 913.17 ns | 762.54 ns | 28.68 KB | +| NSubstitute | 5,616.3 ns | 54.64 ns | 51.11 ns | 9.01 KB | +| FakeItEasy | 8,118.4 ns | 91.41 ns | 85.50 ns | 10.45 KB | ```mermaid %%{init: { @@ -49,8 +49,8 @@ Mock behavior configuration (returns, matchers): xychart-beta title "Setup Performance Comparison" x-axis ["TUnit.Mocks", "Imposter", "Mockolate", "Moq", "NSubstitute", "FakeItEasy"] - y-axis "Time (ns)" 0 --> 506042 - bar [492.4, 774.2, 424.9, 421701, 5305.7, 8075.6] + y-axis "Time (ns)" 0 --> 506106 + bar [524.9, 828.1, 472.7, 421754.9, 5616.3, 8118.4] ``` --- @@ -59,12 +59,12 @@ xychart-beta | Library | Mean | Error | StdDev | Allocated | |---------|------|-------|--------|-----------| -| **TUnit.Mocks** | 681.9 ns | 3.15 ns | 2.63 ns | 2.7 KB | -| Imposter | 1,306.9 ns | 13.63 ns | 12.75 ns | 10.59 KB | -| Mockolate | 663.5 ns | 2.66 ns | 2.36 ns | 3.07 KB | -| Moq | 112,440.0 ns | 780.25 ns | 691.67 ns | 16.53 KB | -| NSubstitute | 11,663.3 ns | 33.90 ns | 30.05 ns | 20.47 KB | -| FakeItEasy | 7,415.3 ns | 67.45 ns | 59.80 ns | 11.71 KB | +| **TUnit.Mocks** | 749.2 ns | 12.24 ns | 11.45 ns | 2.7 KB | +| Imposter | 1,401.7 ns | 25.11 ns | 23.48 ns | 10.59 KB | +| Mockolate | 712.9 ns | 14.02 ns | 16.14 ns | 3.07 KB | +| Moq | 112,999.3 ns | 705.96 ns | 625.82 ns | 16.53 KB | +| NSubstitute | 12,404.1 ns | 101.82 ns | 90.27 ns | 20.31 KB | +| FakeItEasy | 7,566.5 ns | 82.43 ns | 77.11 ns | 11.71 KB | ```mermaid %%{init: { @@ -90,8 +90,8 @@ xychart-beta xychart-beta title "Setup (Multiple) Performance Comparison" x-axis ["TUnit.Mocks", "Imposter", "Mockolate", "Moq", "NSubstitute", "FakeItEasy"] - y-axis "Time (ns)" 0 --> 134928 - bar [681.9, 1306.9, 663.5, 112440, 11663.3, 7415.3] + y-axis "Time (ns)" 0 --> 135600 + bar [749.2, 1401.7, 712.9, 112999.3, 12404.1, 7566.5] ``` ## 🎯 Key Insights @@ -104,4 +104,4 @@ This benchmark compares **TUnit.Mocks** (source-generated) against runtime proxy View the [mock benchmarks overview](/docs/benchmarks/mocks) for methodology details and environment information. ::: -*Last generated: 2026-04-05T03:32:35.400Z* +*Last generated: 2026-04-07T03:21:31.527Z* diff --git a/docs/docs/benchmarks/mocks/Verification.md b/docs/docs/benchmarks/mocks/Verification.md index 1db123c816..e75479cf70 100644 --- a/docs/docs/benchmarks/mocks/Verification.md +++ b/docs/docs/benchmarks/mocks/Verification.md @@ -7,7 +7,7 @@ sidebar_position: 7 # Verification Benchmark :::info Last Updated -This benchmark was automatically generated on **2026-04-05** from the latest CI run. +This benchmark was automatically generated on **2026-04-07** from the latest CI run. **Environment:** Ubuntu Latest • .NET SDK 10.0.201 ::: @@ -18,12 +18,12 @@ Verifying mock method calls: | Library | Mean | Error | StdDev | Allocated | |---------|------|-------|--------|-----------| -| **TUnit.Mocks** | 764.91 ns | 11.322 ns | 10.591 ns | 2984 B | -| Imposter | 769.71 ns | 8.790 ns | 8.222 ns | 4688 B | -| Mockolate | 950.06 ns | 12.760 ns | 11.936 ns | 3152 B | -| Moq | 339,526.09 ns | 1,819.383 ns | 1,701.852 ns | 24325 B | -| NSubstitute | 6,281.01 ns | 63.710 ns | 56.478 ns | 10064 B | -| FakeItEasy | 7,432.16 ns | 52.771 ns | 49.362 ns | 10722 B | +| **TUnit.Mocks** | 922.60 ns | 7.808 ns | 7.303 ns | 3048 B | +| Imposter | 844.24 ns | 16.870 ns | 37.383 ns | 4688 B | +| Mockolate | 1,053.70 ns | 5.925 ns | 5.252 ns | 3152 B | +| Moq | 267,438.83 ns | 1,931.282 ns | 1,806.523 ns | 24557 B | +| NSubstitute | 6,451.74 ns | 12.044 ns | 10.677 ns | 10176 B | +| FakeItEasy | 7,110.46 ns | 38.252 ns | 33.909 ns | 10731 B | ```mermaid %%{init: { @@ -49,8 +49,8 @@ Verifying mock method calls: xychart-beta title "Verification Performance Comparison" x-axis ["TUnit.Mocks", "Imposter", "Mockolate", "Moq", "NSubstitute", "FakeItEasy"] - y-axis "Time (ns)" 0 --> 407432 - bar [764.91, 769.71, 950.06, 339526.09, 6281.01, 7432.16] + y-axis "Time (ns)" 0 --> 320927 + bar [922.6, 844.24, 1053.7, 267438.83, 6451.74, 7110.46] ``` --- @@ -59,12 +59,12 @@ xychart-beta | Library | Mean | Error | StdDev | Allocated | |---------|------|-------|--------|-----------| -| **TUnit.Mocks** | 84.48 ns | 0.911 ns | 0.853 ns | 376 B | -| Imposter | 337.65 ns | 6.597 ns | 6.775 ns | 2400 B | -| Mockolate | 225.18 ns | 2.159 ns | 2.019 ns | 952 B | -| Moq | 87,077.29 ns | 491.297 ns | 435.522 ns | 6918 B | -| NSubstitute | 3,594.29 ns | 27.965 ns | 24.790 ns | 7088 B | -| FakeItEasy | 3,489.27 ns | 32.051 ns | 29.981 ns | 5209 B | +| **TUnit.Mocks** | 97.18 ns | 1.636 ns | 1.531 ns | 376 B | +| Imposter | 406.52 ns | 8.044 ns | 12.758 ns | 2400 B | +| Mockolate | 254.73 ns | 1.878 ns | 1.756 ns | 952 B | +| Moq | 65,371.08 ns | 459.145 ns | 383.407 ns | 6925 B | +| NSubstitute | 3,524.13 ns | 17.207 ns | 15.253 ns | 7088 B | +| FakeItEasy | 3,655.87 ns | 29.015 ns | 27.140 ns | 5218 B | ```mermaid %%{init: { @@ -90,8 +90,8 @@ xychart-beta xychart-beta title "Verification (Never) Performance Comparison" x-axis ["TUnit.Mocks", "Imposter", "Mockolate", "Moq", "NSubstitute", "FakeItEasy"] - y-axis "Time (ns)" 0 --> 104493 - bar [84.48, 337.65, 225.18, 87077.29, 3594.29, 3489.27] + y-axis "Time (ns)" 0 --> 78446 + bar [97.18, 406.52, 254.73, 65371.08, 3524.13, 3655.87] ``` --- @@ -100,12 +100,12 @@ xychart-beta | Library | Mean | Error | StdDev | Allocated | |---------|------|-------|--------|-----------| -| **TUnit.Mocks** | 1,380.27 ns | 6.781 ns | 6.343 ns | 4416 B | -| Imposter | 1,817.52 ns | 16.933 ns | 15.839 ns | 11192 B | -| Mockolate | 1,876.89 ns | 9.292 ns | 8.691 ns | 5496 B | -| Moq | 468,799.88 ns | 3,322.719 ns | 3,108.074 ns | 34699 B | -| NSubstitute | 11,571.76 ns | 53.285 ns | 49.843 ns | 16762 B | -| FakeItEasy | 13,488.64 ns | 178.615 ns | 149.151 ns | 19233 B | +| **TUnit.Mocks** | 1,563.81 ns | 13.064 ns | 12.220 ns | 4544 B | +| Imposter | 2,013.84 ns | 40.150 ns | 61.313 ns | 11192 B | +| Mockolate | 2,011.89 ns | 13.868 ns | 12.972 ns | 5496 B | +| Moq | 353,473.50 ns | 3,057.036 ns | 2,709.983 ns | 34670 B | +| NSubstitute | 11,427.85 ns | 64.576 ns | 57.245 ns | 16762 B | +| FakeItEasy | 12,260.11 ns | 85.726 ns | 75.993 ns | 19238 B | ```mermaid %%{init: { @@ -131,8 +131,8 @@ xychart-beta xychart-beta title "Verification (Multiple) Performance Comparison" x-axis ["TUnit.Mocks", "Imposter", "Mockolate", "Moq", "NSubstitute", "FakeItEasy"] - y-axis "Time (ns)" 0 --> 562560 - bar [1380.27, 1817.52, 1876.89, 468799.88, 11571.76, 13488.64] + y-axis "Time (ns)" 0 --> 424169 + bar [1563.81, 2013.84, 2011.89, 353473.5, 11427.85, 12260.11] ``` ## 🎯 Key Insights @@ -145,4 +145,4 @@ This benchmark compares **TUnit.Mocks** (source-generated) against runtime proxy View the [mock benchmarks overview](/docs/benchmarks/mocks) for methodology details and environment information. ::: -*Last generated: 2026-04-05T03:32:35.400Z* +*Last generated: 2026-04-07T03:21:31.527Z* diff --git a/docs/docs/benchmarks/mocks/index.md b/docs/docs/benchmarks/mocks/index.md index 7ae7599da4..e741929d75 100644 --- a/docs/docs/benchmarks/mocks/index.md +++ b/docs/docs/benchmarks/mocks/index.md @@ -7,7 +7,7 @@ sidebar_position: 1 # Mock Library Benchmarks :::info Last Updated -These benchmarks were automatically generated on **2026-04-05** from the latest CI run. +These benchmarks were automatically generated on **2026-04-07** from the latest CI run. **Environment:** Ubuntu Latest • .NET SDK 10.0.201 ::: @@ -51,7 +51,7 @@ Each benchmark category tests a specific aspect of mocking library usage: - **Tool**: BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat) - **OS**: Ubuntu Latest (GitHub Actions) -- **Runtime**: .NET 10.0.5 (10.0.5, 10.0.526.15411), X64 RyuJIT x86-64-v3 +- **Runtime**: .NET 10.0.5 (10.0.5, 10.0.526.15411), X64 RyuJIT x86-64-v4 - **Statistical Rigor**: Multiple iterations with warm-up and outlier detection - **Memory**: Allocation tracking enabled via `[MemoryDiagnoser]` @@ -76,4 +76,4 @@ These benchmarks run automatically daily via [GitHub Actions](https://github.com Each benchmark runs multiple iterations with statistical analysis to ensure accuracy. Results may vary based on hardware and test characteristics. ::: -*Last generated: 2026-04-05T03:32:35.400Z* +*Last generated: 2026-04-07T03:21:31.527Z* diff --git a/docs/package.json b/docs/package.json index 14a32c403d..025f83bd7b 100644 --- a/docs/package.json +++ b/docs/package.json @@ -15,9 +15,9 @@ "typecheck": "tsc" }, "dependencies": { - "@docusaurus/core": "3.9.2", - "@docusaurus/preset-classic": "3.9.2", - "@docusaurus/theme-mermaid": "^3.9.2", + "@docusaurus/core": "3.10.0", + "@docusaurus/preset-classic": "3.10.0", + "@docusaurus/theme-mermaid": "^3.10.0", "@mdx-js/react": "^3.1.1", "clsx": "^2.1.1", "prism-react-renderer": "^2.4.1", @@ -25,9 +25,9 @@ "react-dom": "^19.2.4" }, "devDependencies": { - "@docusaurus/module-type-aliases": "3.9.2", - "@docusaurus/tsconfig": "3.9.2", - "@docusaurus/types": "3.9.2", + "@docusaurus/module-type-aliases": "3.10.0", + "@docusaurus/tsconfig": "3.10.0", + "@docusaurus/types": "3.10.0", "docusaurus-plugin-llms": "^0.3.0", "typescript": "~6.0.0" }, diff --git a/docs/static/benchmarks/AsyncTests.json b/docs/static/benchmarks/AsyncTests.json index b48e72e835..554d6ea3fe 100644 --- a/docs/static/benchmarks/AsyncTests.json +++ b/docs/static/benchmarks/AsyncTests.json @@ -1,5 +1,5 @@ { - "timestamp": "2026-04-05T12:17:42.432Z", + "timestamp": "2026-04-07T00:41:20.831Z", "category": "AsyncTests", "environment": { "benchmarkDotNetVersion": "BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)", @@ -9,43 +9,43 @@ "results": [ { "Method": "TUnit", - "Version": "1.28.0", - "Mean": "505.7 ms", - "Error": "7.29 ms", - "StdDev": "6.82 ms", - "Median": "505.2 ms" + "Version": "1.28.7", + "Mean": "537.0 ms", + "Error": "9.18 ms", + "StdDev": "8.59 ms", + "Median": "533.7 ms" }, { "Method": "NUnit", "Version": "4.5.1", - "Mean": "706.6 ms", - "Error": "7.68 ms", - "StdDev": "6.41 ms", - "Median": "706.2 ms" + "Mean": "723.0 ms", + "Error": "12.17 ms", + "StdDev": "11.39 ms", + "Median": "719.3 ms" }, { "Method": "MSTest", "Version": "4.1.0", - "Mean": "656.9 ms", - "Error": "12.76 ms", - "StdDev": "16.14 ms", - "Median": "655.8 ms" + "Mean": "642.5 ms", + "Error": "8.53 ms", + "StdDev": "7.56 ms", + "Median": "642.3 ms" }, { "Method": "xUnit3", "Version": "3.2.2", - "Mean": "768.3 ms", - "Error": "6.50 ms", - "StdDev": "5.76 ms", - "Median": "768.5 ms" + "Mean": "780.5 ms", + "Error": "7.07 ms", + "StdDev": "6.61 ms", + "Median": "780.5 ms" }, { "Method": "TUnit_AOT", - "Version": "1.28.0", - "Mean": "122.6 ms", - "Error": "0.18 ms", - "StdDev": "0.16 ms", - "Median": "122.6 ms" + "Version": "1.28.7", + "Mean": "122.7 ms", + "Error": "0.30 ms", + "StdDev": "0.26 ms", + "Median": "122.7 ms" } ] } \ No newline at end of file diff --git a/docs/static/benchmarks/BuildTime.json b/docs/static/benchmarks/BuildTime.json index dc9786b661..362dda6860 100644 --- a/docs/static/benchmarks/BuildTime.json +++ b/docs/static/benchmarks/BuildTime.json @@ -1,5 +1,5 @@ { - "timestamp": "2026-04-05T12:17:42.434Z", + "timestamp": "2026-04-07T00:41:20.833Z", "category": "BuildTime", "environment": { "benchmarkDotNetVersion": "BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)", @@ -9,35 +9,35 @@ "results": [ { "Method": "Build_TUnit", - "Version": "1.28.0", - "Mean": "1.820 s", - "Error": "0.0222 s", - "StdDev": "0.0207 s", - "Median": "1.826 s" + "Version": "1.28.7", + "Mean": "1.789 s", + "Error": "0.0279 s", + "StdDev": "0.0248 s", + "Median": "1.789 s" }, { "Method": "Build_NUnit", "Version": "4.5.1", - "Mean": "1.626 s", - "Error": "0.0162 s", - "StdDev": "0.0143 s", - "Median": "1.622 s" + "Mean": "1.601 s", + "Error": "0.0182 s", + "StdDev": "0.0171 s", + "Median": "1.599 s" }, { "Method": "Build_MSTest", "Version": "4.1.0", - "Mean": "1.708 s", - "Error": "0.0165 s", - "StdDev": "0.0147 s", - "Median": "1.710 s" + "Mean": "1.655 s", + "Error": "0.0225 s", + "StdDev": "0.0210 s", + "Median": "1.657 s" }, { "Method": "Build_xUnit3", "Version": "3.2.2", - "Mean": "1.671 s", - "Error": "0.0218 s", - "StdDev": "0.0193 s", - "Median": "1.663 s" + "Mean": "1.598 s", + "Error": "0.0197 s", + "StdDev": "0.0185 s", + "Median": "1.600 s" } ] } \ No newline at end of file diff --git a/docs/static/benchmarks/DataDrivenTests.json b/docs/static/benchmarks/DataDrivenTests.json index abde858504..1ab623756d 100644 --- a/docs/static/benchmarks/DataDrivenTests.json +++ b/docs/static/benchmarks/DataDrivenTests.json @@ -1,5 +1,5 @@ { - "timestamp": "2026-04-05T12:17:42.433Z", + "timestamp": "2026-04-07T00:41:20.831Z", "category": "DataDrivenTests", "environment": { "benchmarkDotNetVersion": "BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)", @@ -9,43 +9,43 @@ "results": [ { "Method": "TUnit", - "Version": "1.28.0", - "Mean": "469.70 ms", - "Error": "6.349 ms", - "StdDev": "5.628 ms", - "Median": "467.78 ms" + "Version": "1.28.7", + "Mean": "477.77 ms", + "Error": "4.953 ms", + "StdDev": "4.391 ms", + "Median": "476.42 ms" }, { "Method": "NUnit", "Version": "4.5.1", - "Mean": "565.08 ms", - "Error": "6.483 ms", - "StdDev": "5.414 ms", - "Median": "565.43 ms" + "Mean": "572.28 ms", + "Error": "11.407 ms", + "StdDev": "10.671 ms", + "Median": "570.99 ms" }, { "Method": "MSTest", "Version": "4.1.0", - "Mean": "533.97 ms", - "Error": "8.472 ms", - "StdDev": "7.510 ms", - "Median": "534.35 ms" + "Mean": "475.82 ms", + "Error": "7.211 ms", + "StdDev": "6.745 ms", + "Median": "474.11 ms" }, { "Method": "xUnit3", "Version": "3.2.2", - "Mean": "607.03 ms", - "Error": "7.618 ms", - "StdDev": "6.753 ms", - "Median": "604.60 ms" + "Mean": "601.72 ms", + "Error": "6.540 ms", + "StdDev": "5.797 ms", + "Median": "601.20 ms" }, { "Method": "TUnit_AOT", - "Version": "1.28.0", - "Mean": "23.48 ms", - "Error": "0.465 ms", - "StdDev": "0.751 ms", - "Median": "23.37 ms" + "Version": "1.28.7", + "Mean": "24.35 ms", + "Error": "0.476 ms", + "StdDev": "0.602 ms", + "Median": "24.27 ms" } ] } \ No newline at end of file diff --git a/docs/static/benchmarks/MassiveParallelTests.json b/docs/static/benchmarks/MassiveParallelTests.json index e3d246a6cb..3ab195ae43 100644 --- a/docs/static/benchmarks/MassiveParallelTests.json +++ b/docs/static/benchmarks/MassiveParallelTests.json @@ -1,5 +1,5 @@ { - "timestamp": "2026-04-05T12:17:42.433Z", + "timestamp": "2026-04-07T00:41:20.831Z", "category": "MassiveParallelTests", "environment": { "benchmarkDotNetVersion": "BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)", @@ -9,43 +9,43 @@ "results": [ { "Method": "TUnit", - "Version": "1.28.0", - "Mean": "664.9 ms", - "Error": "2.85 ms", - "StdDev": "2.53 ms", - "Median": "665.0 ms" + "Version": "1.28.7", + "Mean": "655.8 ms", + "Error": "3.89 ms", + "StdDev": "3.64 ms", + "Median": "655.1 ms" }, { "Method": "NUnit", "Version": "4.5.1", - "Mean": "1,250.3 ms", - "Error": "8.21 ms", - "StdDev": "7.27 ms", - "Median": "1,249.9 ms" + "Mean": "1,209.7 ms", + "Error": "5.89 ms", + "StdDev": "5.22 ms", + "Median": "1,208.3 ms" }, { "Method": "MSTest", "Version": "4.1.0", - "Mean": "2,978.5 ms", - "Error": "11.11 ms", - "StdDev": "10.39 ms", - "Median": "2,979.2 ms" + "Mean": "2,949.8 ms", + "Error": "6.87 ms", + "StdDev": "6.09 ms", + "Median": "2,950.1 ms" }, { "Method": "xUnit3", "Version": "3.2.2", - "Mean": "3,113.2 ms", - "Error": "12.40 ms", - "StdDev": "11.60 ms", - "Median": "3,111.6 ms" + "Mean": "3,078.4 ms", + "Error": "10.71 ms", + "StdDev": "10.02 ms", + "Median": "3,076.3 ms" }, { "Method": "TUnit_AOT", - "Version": "1.28.0", - "Mean": "228.5 ms", - "Error": "0.55 ms", - "StdDev": "0.51 ms", - "Median": "228.5 ms" + "Version": "1.28.7", + "Mean": "229.8 ms", + "Error": "0.65 ms", + "StdDev": "0.54 ms", + "Median": "229.8 ms" } ] } \ No newline at end of file diff --git a/docs/static/benchmarks/MatrixTests.json b/docs/static/benchmarks/MatrixTests.json index 2fde0a4ca6..db57118a2e 100644 --- a/docs/static/benchmarks/MatrixTests.json +++ b/docs/static/benchmarks/MatrixTests.json @@ -1,5 +1,5 @@ { - "timestamp": "2026-04-05T12:17:42.433Z", + "timestamp": "2026-04-07T00:41:20.831Z", "category": "MatrixTests", "environment": { "benchmarkDotNetVersion": "BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)", @@ -9,43 +9,43 @@ "results": [ { "Method": "TUnit", - "Version": "1.28.0", - "Mean": "631.5 ms", - "Error": "12.27 ms", - "StdDev": "15.52 ms", - "Median": "632.6 ms" + "Version": "1.28.7", + "Mean": "576.1 ms", + "Error": "3.37 ms", + "StdDev": "2.99 ms", + "Median": "576.5 ms" }, { "Method": "NUnit", "Version": "4.5.1", - "Mean": "1,674.5 ms", - "Error": "12.45 ms", - "StdDev": "10.40 ms", - "Median": "1,681.0 ms" + "Mean": "1,599.7 ms", + "Error": "8.78 ms", + "StdDev": "7.78 ms", + "Median": "1,599.7 ms" }, { "Method": "MSTest", "Version": "4.1.0", - "Mean": "1,555.3 ms", - "Error": "12.49 ms", - "StdDev": "11.07 ms", - "Median": "1,553.1 ms" + "Mean": "1,514.0 ms", + "Error": "5.73 ms", + "StdDev": "4.78 ms", + "Median": "1,513.5 ms" }, { "Method": "xUnit3", "Version": "3.2.2", - "Mean": "1,697.4 ms", - "Error": "9.62 ms", - "StdDev": "9.00 ms", - "Median": "1,695.2 ms" + "Mean": "1,646.2 ms", + "Error": "5.14 ms", + "StdDev": "4.29 ms", + "Median": "1,646.6 ms" }, { "Method": "TUnit_AOT", - "Version": "1.28.0", - "Mean": "127.7 ms", - "Error": "0.51 ms", - "StdDev": "0.43 ms", - "Median": "127.7 ms" + "Version": "1.28.7", + "Mean": "125.6 ms", + "Error": "0.53 ms", + "StdDev": "0.47 ms", + "Median": "125.5 ms" } ] } \ No newline at end of file diff --git a/docs/static/benchmarks/ScaleTests.json b/docs/static/benchmarks/ScaleTests.json index e65a8c24fe..29f81adbcc 100644 --- a/docs/static/benchmarks/ScaleTests.json +++ b/docs/static/benchmarks/ScaleTests.json @@ -1,5 +1,5 @@ { - "timestamp": "2026-04-05T12:17:42.434Z", + "timestamp": "2026-04-07T00:41:20.832Z", "category": "ScaleTests", "environment": { "benchmarkDotNetVersion": "BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)", @@ -9,43 +9,43 @@ "results": [ { "Method": "TUnit", - "Version": "1.28.0", - "Mean": "491.08 ms", - "Error": "3.345 ms", - "StdDev": "2.965 ms", - "Median": "490.42 ms" + "Version": "1.28.7", + "Mean": "445.59 ms", + "Error": "4.514 ms", + "StdDev": "4.222 ms", + "Median": "444.78 ms" }, { "Method": "NUnit", "Version": "4.5.1", - "Mean": "615.08 ms", - "Error": "6.560 ms", - "StdDev": "6.136 ms", - "Median": "614.65 ms" + "Mean": "566.13 ms", + "Error": "8.308 ms", + "StdDev": "7.771 ms", + "Median": "562.76 ms" }, { "Method": "MSTest", "Version": "4.1.0", - "Mean": "484.99 ms", - "Error": "5.972 ms", - "StdDev": "5.586 ms", - "Median": "485.09 ms" + "Mean": "553.10 ms", + "Error": "10.814 ms", + "StdDev": "13.281 ms", + "Median": "551.91 ms" }, { "Method": "xUnit3", "Version": "3.2.2", - "Mean": "618.10 ms", - "Error": "8.305 ms", - "StdDev": "6.935 ms", - "Median": "617.83 ms" + "Mean": "585.75 ms", + "Error": "7.910 ms", + "StdDev": "7.012 ms", + "Median": "588.12 ms" }, { "Method": "TUnit_AOT", - "Version": "1.28.0", - "Mean": "34.31 ms", - "Error": "0.790 ms", - "StdDev": "2.304 ms", - "Median": "33.79 ms" + "Version": "1.28.7", + "Mean": "36.53 ms", + "Error": "1.181 ms", + "StdDev": "3.464 ms", + "Median": "36.72 ms" } ] } \ No newline at end of file diff --git a/docs/static/benchmarks/SetupTeardownTests.json b/docs/static/benchmarks/SetupTeardownTests.json index caac5920e5..d2c84ca472 100644 --- a/docs/static/benchmarks/SetupTeardownTests.json +++ b/docs/static/benchmarks/SetupTeardownTests.json @@ -1,5 +1,5 @@ { - "timestamp": "2026-04-05T12:17:42.434Z", + "timestamp": "2026-04-07T00:41:20.832Z", "category": "SetupTeardownTests", "environment": { "benchmarkDotNetVersion": "BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)", @@ -9,39 +9,39 @@ "results": [ { "Method": "TUnit", - "Version": "1.28.0", - "Mean": "572.6 ms", - "Error": "2.68 ms", - "StdDev": "2.38 ms", - "Median": "572.7 ms" + "Version": "1.28.7", + "Mean": "582.0 ms", + "Error": "6.26 ms", + "StdDev": "5.86 ms", + "Median": "579.9 ms" }, { "Method": "NUnit", "Version": "4.5.1", - "Mean": "1,183.8 ms", - "Error": "10.26 ms", - "StdDev": "9.10 ms", - "Median": "1,182.1 ms" + "Mean": "1,227.8 ms", + "Error": "13.81 ms", + "StdDev": "12.92 ms", + "Median": "1,224.4 ms" }, { "Method": "MSTest", "Version": "4.1.0", - "Mean": "1,103.4 ms", - "Error": "5.41 ms", - "StdDev": "5.06 ms", - "Median": "1,102.0 ms" + "Mean": "1,150.4 ms", + "Error": "8.34 ms", + "StdDev": "7.80 ms", + "Median": "1,149.8 ms" }, { "Method": "xUnit3", "Version": "3.2.2", - "Mean": "1,239.0 ms", - "Error": "9.77 ms", - "StdDev": "8.66 ms", - "Median": "1,237.5 ms" + "Mean": "1,275.3 ms", + "Error": "6.71 ms", + "StdDev": "5.95 ms", + "Median": "1,276.5 ms" }, { "Method": "TUnit_AOT", - "Version": "1.28.0", + "Version": "1.28.7", "Mean": "NA", "Error": "NA", "StdDev": "NA", diff --git a/docs/static/benchmarks/historical.json b/docs/static/benchmarks/historical.json index 645117b77a..3addac52f2 100644 --- a/docs/static/benchmarks/historical.json +++ b/docs/static/benchmarks/historical.json @@ -1,12 +1,4 @@ [ - { - "date": "2026-01-12", - "environment": "Ubuntu" - }, - { - "date": "2026-01-12", - "environment": "Ubuntu" - }, { "date": "2026-01-13", "environment": "Ubuntu" @@ -358,5 +350,13 @@ { "date": "2026-04-05", "environment": "Ubuntu" + }, + { + "date": "2026-04-06", + "environment": "Ubuntu" + }, + { + "date": "2026-04-07", + "environment": "Ubuntu" } ] \ No newline at end of file diff --git a/docs/static/benchmarks/latest.json b/docs/static/benchmarks/latest.json index 81f10c5f54..c0ac3c7475 100644 --- a/docs/static/benchmarks/latest.json +++ b/docs/static/benchmarks/latest.json @@ -1,5 +1,5 @@ { - "timestamp": "2026-04-05T12:17:42.435Z", + "timestamp": "2026-04-07T00:41:20.833Z", "environment": { "benchmarkDotNetVersion": "BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)", "sdk": ".NET SDK 10.0.201", @@ -9,249 +9,249 @@ "AsyncTests": [ { "Method": "TUnit", - "Version": "1.28.0", - "Mean": "505.7 ms", - "Error": "7.29 ms", - "StdDev": "6.82 ms", - "Median": "505.2 ms" + "Version": "1.28.7", + "Mean": "537.0 ms", + "Error": "9.18 ms", + "StdDev": "8.59 ms", + "Median": "533.7 ms" }, { "Method": "NUnit", "Version": "4.5.1", - "Mean": "706.6 ms", - "Error": "7.68 ms", - "StdDev": "6.41 ms", - "Median": "706.2 ms" + "Mean": "723.0 ms", + "Error": "12.17 ms", + "StdDev": "11.39 ms", + "Median": "719.3 ms" }, { "Method": "MSTest", "Version": "4.1.0", - "Mean": "656.9 ms", - "Error": "12.76 ms", - "StdDev": "16.14 ms", - "Median": "655.8 ms" + "Mean": "642.5 ms", + "Error": "8.53 ms", + "StdDev": "7.56 ms", + "Median": "642.3 ms" }, { "Method": "xUnit3", "Version": "3.2.2", - "Mean": "768.3 ms", - "Error": "6.50 ms", - "StdDev": "5.76 ms", - "Median": "768.5 ms" + "Mean": "780.5 ms", + "Error": "7.07 ms", + "StdDev": "6.61 ms", + "Median": "780.5 ms" }, { "Method": "TUnit_AOT", - "Version": "1.28.0", - "Mean": "122.6 ms", - "Error": "0.18 ms", - "StdDev": "0.16 ms", - "Median": "122.6 ms" + "Version": "1.28.7", + "Mean": "122.7 ms", + "Error": "0.30 ms", + "StdDev": "0.26 ms", + "Median": "122.7 ms" } ], "DataDrivenTests": [ { "Method": "TUnit", - "Version": "1.28.0", - "Mean": "469.70 ms", - "Error": "6.349 ms", - "StdDev": "5.628 ms", - "Median": "467.78 ms" + "Version": "1.28.7", + "Mean": "477.77 ms", + "Error": "4.953 ms", + "StdDev": "4.391 ms", + "Median": "476.42 ms" }, { "Method": "NUnit", "Version": "4.5.1", - "Mean": "565.08 ms", - "Error": "6.483 ms", - "StdDev": "5.414 ms", - "Median": "565.43 ms" + "Mean": "572.28 ms", + "Error": "11.407 ms", + "StdDev": "10.671 ms", + "Median": "570.99 ms" }, { "Method": "MSTest", "Version": "4.1.0", - "Mean": "533.97 ms", - "Error": "8.472 ms", - "StdDev": "7.510 ms", - "Median": "534.35 ms" + "Mean": "475.82 ms", + "Error": "7.211 ms", + "StdDev": "6.745 ms", + "Median": "474.11 ms" }, { "Method": "xUnit3", "Version": "3.2.2", - "Mean": "607.03 ms", - "Error": "7.618 ms", - "StdDev": "6.753 ms", - "Median": "604.60 ms" + "Mean": "601.72 ms", + "Error": "6.540 ms", + "StdDev": "5.797 ms", + "Median": "601.20 ms" }, { "Method": "TUnit_AOT", - "Version": "1.28.0", - "Mean": "23.48 ms", - "Error": "0.465 ms", - "StdDev": "0.751 ms", - "Median": "23.37 ms" + "Version": "1.28.7", + "Mean": "24.35 ms", + "Error": "0.476 ms", + "StdDev": "0.602 ms", + "Median": "24.27 ms" } ], "MassiveParallelTests": [ { "Method": "TUnit", - "Version": "1.28.0", - "Mean": "664.9 ms", - "Error": "2.85 ms", - "StdDev": "2.53 ms", - "Median": "665.0 ms" + "Version": "1.28.7", + "Mean": "655.8 ms", + "Error": "3.89 ms", + "StdDev": "3.64 ms", + "Median": "655.1 ms" }, { "Method": "NUnit", "Version": "4.5.1", - "Mean": "1,250.3 ms", - "Error": "8.21 ms", - "StdDev": "7.27 ms", - "Median": "1,249.9 ms" + "Mean": "1,209.7 ms", + "Error": "5.89 ms", + "StdDev": "5.22 ms", + "Median": "1,208.3 ms" }, { "Method": "MSTest", "Version": "4.1.0", - "Mean": "2,978.5 ms", - "Error": "11.11 ms", - "StdDev": "10.39 ms", - "Median": "2,979.2 ms" + "Mean": "2,949.8 ms", + "Error": "6.87 ms", + "StdDev": "6.09 ms", + "Median": "2,950.1 ms" }, { "Method": "xUnit3", "Version": "3.2.2", - "Mean": "3,113.2 ms", - "Error": "12.40 ms", - "StdDev": "11.60 ms", - "Median": "3,111.6 ms" + "Mean": "3,078.4 ms", + "Error": "10.71 ms", + "StdDev": "10.02 ms", + "Median": "3,076.3 ms" }, { "Method": "TUnit_AOT", - "Version": "1.28.0", - "Mean": "228.5 ms", - "Error": "0.55 ms", - "StdDev": "0.51 ms", - "Median": "228.5 ms" + "Version": "1.28.7", + "Mean": "229.8 ms", + "Error": "0.65 ms", + "StdDev": "0.54 ms", + "Median": "229.8 ms" } ], "MatrixTests": [ { "Method": "TUnit", - "Version": "1.28.0", - "Mean": "631.5 ms", - "Error": "12.27 ms", - "StdDev": "15.52 ms", - "Median": "632.6 ms" + "Version": "1.28.7", + "Mean": "576.1 ms", + "Error": "3.37 ms", + "StdDev": "2.99 ms", + "Median": "576.5 ms" }, { "Method": "NUnit", "Version": "4.5.1", - "Mean": "1,674.5 ms", - "Error": "12.45 ms", - "StdDev": "10.40 ms", - "Median": "1,681.0 ms" + "Mean": "1,599.7 ms", + "Error": "8.78 ms", + "StdDev": "7.78 ms", + "Median": "1,599.7 ms" }, { "Method": "MSTest", "Version": "4.1.0", - "Mean": "1,555.3 ms", - "Error": "12.49 ms", - "StdDev": "11.07 ms", - "Median": "1,553.1 ms" + "Mean": "1,514.0 ms", + "Error": "5.73 ms", + "StdDev": "4.78 ms", + "Median": "1,513.5 ms" }, { "Method": "xUnit3", "Version": "3.2.2", - "Mean": "1,697.4 ms", - "Error": "9.62 ms", - "StdDev": "9.00 ms", - "Median": "1,695.2 ms" + "Mean": "1,646.2 ms", + "Error": "5.14 ms", + "StdDev": "4.29 ms", + "Median": "1,646.6 ms" }, { "Method": "TUnit_AOT", - "Version": "1.28.0", - "Mean": "127.7 ms", - "Error": "0.51 ms", - "StdDev": "0.43 ms", - "Median": "127.7 ms" + "Version": "1.28.7", + "Mean": "125.6 ms", + "Error": "0.53 ms", + "StdDev": "0.47 ms", + "Median": "125.5 ms" } ], "ScaleTests": [ { "Method": "TUnit", - "Version": "1.28.0", - "Mean": "491.08 ms", - "Error": "3.345 ms", - "StdDev": "2.965 ms", - "Median": "490.42 ms" + "Version": "1.28.7", + "Mean": "445.59 ms", + "Error": "4.514 ms", + "StdDev": "4.222 ms", + "Median": "444.78 ms" }, { "Method": "NUnit", "Version": "4.5.1", - "Mean": "615.08 ms", - "Error": "6.560 ms", - "StdDev": "6.136 ms", - "Median": "614.65 ms" + "Mean": "566.13 ms", + "Error": "8.308 ms", + "StdDev": "7.771 ms", + "Median": "562.76 ms" }, { "Method": "MSTest", "Version": "4.1.0", - "Mean": "484.99 ms", - "Error": "5.972 ms", - "StdDev": "5.586 ms", - "Median": "485.09 ms" + "Mean": "553.10 ms", + "Error": "10.814 ms", + "StdDev": "13.281 ms", + "Median": "551.91 ms" }, { "Method": "xUnit3", "Version": "3.2.2", - "Mean": "618.10 ms", - "Error": "8.305 ms", - "StdDev": "6.935 ms", - "Median": "617.83 ms" + "Mean": "585.75 ms", + "Error": "7.910 ms", + "StdDev": "7.012 ms", + "Median": "588.12 ms" }, { "Method": "TUnit_AOT", - "Version": "1.28.0", - "Mean": "34.31 ms", - "Error": "0.790 ms", - "StdDev": "2.304 ms", - "Median": "33.79 ms" + "Version": "1.28.7", + "Mean": "36.53 ms", + "Error": "1.181 ms", + "StdDev": "3.464 ms", + "Median": "36.72 ms" } ], "SetupTeardownTests": [ { "Method": "TUnit", - "Version": "1.28.0", - "Mean": "572.6 ms", - "Error": "2.68 ms", - "StdDev": "2.38 ms", - "Median": "572.7 ms" + "Version": "1.28.7", + "Mean": "582.0 ms", + "Error": "6.26 ms", + "StdDev": "5.86 ms", + "Median": "579.9 ms" }, { "Method": "NUnit", "Version": "4.5.1", - "Mean": "1,183.8 ms", - "Error": "10.26 ms", - "StdDev": "9.10 ms", - "Median": "1,182.1 ms" + "Mean": "1,227.8 ms", + "Error": "13.81 ms", + "StdDev": "12.92 ms", + "Median": "1,224.4 ms" }, { "Method": "MSTest", "Version": "4.1.0", - "Mean": "1,103.4 ms", - "Error": "5.41 ms", - "StdDev": "5.06 ms", - "Median": "1,102.0 ms" + "Mean": "1,150.4 ms", + "Error": "8.34 ms", + "StdDev": "7.80 ms", + "Median": "1,149.8 ms" }, { "Method": "xUnit3", "Version": "3.2.2", - "Mean": "1,239.0 ms", - "Error": "9.77 ms", - "StdDev": "8.66 ms", - "Median": "1,237.5 ms" + "Mean": "1,275.3 ms", + "Error": "6.71 ms", + "StdDev": "5.95 ms", + "Median": "1,276.5 ms" }, { "Method": "TUnit_AOT", - "Version": "1.28.0", + "Version": "1.28.7", "Mean": "NA", "Error": "NA", "StdDev": "NA", @@ -263,35 +263,35 @@ "BuildTime": [ { "Method": "Build_TUnit", - "Version": "1.28.0", - "Mean": "1.820 s", - "Error": "0.0222 s", - "StdDev": "0.0207 s", - "Median": "1.826 s" + "Version": "1.28.7", + "Mean": "1.789 s", + "Error": "0.0279 s", + "StdDev": "0.0248 s", + "Median": "1.789 s" }, { "Method": "Build_NUnit", "Version": "4.5.1", - "Mean": "1.626 s", - "Error": "0.0162 s", - "StdDev": "0.0143 s", - "Median": "1.622 s" + "Mean": "1.601 s", + "Error": "0.0182 s", + "StdDev": "0.0171 s", + "Median": "1.599 s" }, { "Method": "Build_MSTest", "Version": "4.1.0", - "Mean": "1.708 s", - "Error": "0.0165 s", - "StdDev": "0.0147 s", - "Median": "1.710 s" + "Mean": "1.655 s", + "Error": "0.0225 s", + "StdDev": "0.0210 s", + "Median": "1.657 s" }, { "Method": "Build_xUnit3", "Version": "3.2.2", - "Mean": "1.671 s", - "Error": "0.0218 s", - "StdDev": "0.0193 s", - "Median": "1.663 s" + "Mean": "1.598 s", + "Error": "0.0197 s", + "StdDev": "0.0185 s", + "Median": "1.600 s" } ] }, @@ -299,6 +299,6 @@ "runtimeCategories": 6, "buildCategories": 1, "totalBenchmarks": 7, - "lastUpdated": "2026-04-05T12:17:42.432Z" + "lastUpdated": "2026-04-07T00:41:20.830Z" } } \ No newline at end of file diff --git a/docs/static/benchmarks/mocks/Callback.json b/docs/static/benchmarks/mocks/Callback.json index 901aab44c1..432ecf018a 100644 --- a/docs/static/benchmarks/mocks/Callback.json +++ b/docs/static/benchmarks/mocks/Callback.json @@ -1,120 +1,120 @@ { - "timestamp": "2026-04-05T03:32:35.400Z", + "timestamp": "2026-04-07T03:21:31.527Z", "category": "Callback", "description": "Callback registration and execution", "environment": { "benchmarkDotNetVersion": "BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)", "sdk": ".NET SDK 10.0.201", - "host": ".NET 10.0.5 (10.0.5, 10.0.526.15411), X64 RyuJIT x86-64-v3" + "host": ".NET 10.0.5 (10.0.5, 10.0.526.15411), X64 RyuJIT x86-64-v4" }, "results": [ { "Method": "TUnit.Mocks", - "Mean": "651.9 ns", - "Error": "2.29 ns", - "StdDev": "1.91 ns", + "Mean": "746.7 ns", + "Error": "14.03 ns", + "StdDev": "14.40 ns", "Gen0": "0.1869", "Gen1": "0.0019", "Allocated": "3.06 KB" }, { "Method": "Imposter", - "Mean": "483.2 ns", - "Error": "3.31 ns", - "StdDev": "3.09 ns", + "Mean": "500.0 ns", + "Error": "9.96 ns", + "StdDev": "19.42 ns", "Gen0": "0.1621", "Gen1": "0.0010", "Allocated": "2.66 KB" }, { "Method": "Mockolate", - "Mean": "540.0 ns", - "Error": "10.61 ns", - "StdDev": "18.59 ns", + "Mean": "517.9 ns", + "Error": "7.25 ns", + "StdDev": "6.06 ns", "Gen0": "0.1097", "Gen1": "-", "Allocated": "1.8 KB" }, { "Method": "Moq", - "Mean": "184,643.6 ns", - "Error": "1,840.32 ns", - "StdDev": "1,721.44 ns", + "Mean": "188,044.7 ns", + "Error": "1,407.17 ns", + "StdDev": "1,316.27 ns", "Gen0": "0.4883", "Gen1": "-", - "Allocated": "13.14 KB" + "Allocated": "13.3 KB" }, { "Method": "NSubstitute", - "Mean": "4,630.0 ns", - "Error": "48.81 ns", - "StdDev": "45.66 ns", + "Mean": "4,661.9 ns", + "Error": "52.37 ns", + "StdDev": "48.99 ns", "Gen0": "0.4807", "Gen1": "0.0076", "Allocated": "7.93 KB" }, { "Method": "FakeItEasy", - "Mean": "5,166.1 ns", - "Error": "84.52 ns", - "StdDev": "79.06 ns", + "Mean": "5,463.0 ns", + "Error": "75.66 ns", + "StdDev": "70.77 ns", "Gen0": "0.4501", "Gen1": "0.0153", "Allocated": "7.44 KB" }, { "Method": "'TUnit.Mocks (with args)'", - "Mean": "772.7 ns", - "Error": "4.57 ns", - "StdDev": "4.27 ns", - "Gen0": "0.1974", + "Mean": "814.2 ns", + "Error": "14.65 ns", + "StdDev": "13.70 ns", + "Gen0": "0.1926", "Gen1": "0.0019", - "Allocated": "3.23 KB" + "Allocated": "3.15 KB" }, { "Method": "'Imposter (with args)'", - "Mean": "541.6 ns", - "Error": "10.67 ns", - "StdDev": "15.97 ns", + "Mean": "598.2 ns", + "Error": "11.57 ns", + "StdDev": "11.36 ns", "Gen0": "0.1726", "Gen1": "0.0010", "Allocated": "2.82 KB" }, { "Method": "'Mockolate (with args)'", - "Mean": "662.3 ns", - "Error": "11.28 ns", - "StdDev": "10.55 ns", + "Mean": "676.7 ns", + "Error": "13.37 ns", + "StdDev": "19.59 ns", "Gen0": "0.1297", "Gen1": "-", "Allocated": "2.13 KB" }, { "Method": "'Moq (with args)'", - "Mean": "194,142.1 ns", - "Error": "1,422.32 ns", - "StdDev": "1,330.44 ns", + "Mean": "193,932.5 ns", + "Error": "2,062.51 ns", + "StdDev": "1,929.28 ns", "Gen0": "0.4883", "Gen1": "-", - "Allocated": "13.84 KB" + "Allocated": "13.73 KB" }, { "Method": "'NSubstitute (with args)'", - "Mean": "5,128.9 ns", - "Error": "70.64 ns", - "StdDev": "62.62 ns", - "Gen0": "0.4883", - "Gen1": "-", + "Mean": "5,182.1 ns", + "Error": "65.78 ns", + "StdDev": "61.53 ns", + "Gen0": "0.5188", + "Gen1": "0.0076", "Allocated": "8.53 KB" }, { "Method": "'FakeItEasy (with args)'", - "Mean": "6,309.5 ns", - "Error": "114.70 ns", - "StdDev": "101.68 ns", + "Mean": "6,631.6 ns", + "Error": "75.42 ns", + "StdDev": "70.55 ns", "Gen0": "0.5493", "Gen1": "0.0610", - "Allocated": "9.26 KB" + "Allocated": "9.4 KB" } ] } \ No newline at end of file diff --git a/docs/static/benchmarks/mocks/CombinedWorkflow.json b/docs/static/benchmarks/mocks/CombinedWorkflow.json index 211645eaef..7ee1a896a8 100644 --- a/docs/static/benchmarks/mocks/CombinedWorkflow.json +++ b/docs/static/benchmarks/mocks/CombinedWorkflow.json @@ -1,63 +1,63 @@ { - "timestamp": "2026-04-05T03:32:35.400Z", + "timestamp": "2026-04-07T03:21:31.527Z", "category": "CombinedWorkflow", "description": "Full workflow: create → setup → invoke → verify", "environment": { "benchmarkDotNetVersion": "BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)", "sdk": ".NET SDK 10.0.201", - "host": ".NET 10.0.5 (10.0.5, 10.0.526.15411), X64 RyuJIT x86-64-v3" + "host": ".NET 10.0.5 (10.0.5, 10.0.526.15411), X64 RyuJIT x86-64-v4" }, "results": [ { "Method": "TUnit.Mocks", - "Mean": "1.864 μs", - "Error": "0.0168 μs", - "StdDev": "0.0157 μs", - "Gen0": "0.3662", - "Gen1": "0.0057", - "Allocated": "6.01 KB" + "Mean": "2.035 μs", + "Error": "0.0399 μs", + "StdDev": "0.0491 μs", + "Gen0": "0.3738", + "Gen1": "0.0038", + "Allocated": "6.14 KB" }, { "Method": "Imposter", - "Mean": "2.623 μs", - "Error": "0.0306 μs", - "StdDev": "0.0287 μs", + "Mean": "2.746 μs", + "Error": "0.0511 μs", + "StdDev": "0.0478 μs", "Gen0": "0.9613", "Gen1": "0.0458", "Allocated": "15.71 KB" }, { "Method": "Mockolate", - "Mean": "2.346 μs", - "Error": "0.0240 μs", - "StdDev": "0.0224 μs", + "Mean": "2.562 μs", + "Error": "0.0510 μs", + "StdDev": "0.0681 μs", "Gen0": "0.4311", "Gen1": "0.0038", "Allocated": "7.09 KB" }, { "Method": "Moq", - "Mean": "403.794 μs", - "Error": "2.7482 μs", - "StdDev": "2.5707 μs", + "Mean": "403.167 μs", + "Error": "3.3674 μs", + "StdDev": "2.8119 μs", "Gen0": "1.9531", "Gen1": "0.9766", - "Allocated": "36.38 KB" + "Allocated": "36.74 KB" }, { "Method": "NSubstitute", - "Mean": "16.942 μs", - "Error": "0.1111 μs", - "StdDev": "0.1039 μs", + "Mean": "17.244 μs", + "Error": "0.2324 μs", + "StdDev": "0.2174 μs", "Gen0": "1.6174", "Gen1": "0.0305", "Allocated": "26.72 KB" }, { "Method": "FakeItEasy", - "Mean": "18.390 μs", - "Error": "0.2776 μs", - "StdDev": "0.2461 μs", + "Mean": "18.200 μs", + "Error": "0.3194 μs", + "StdDev": "0.3280 μs", "Gen0": "1.4648", "Gen1": "0.1221", "Allocated": "25.52 KB" diff --git a/docs/static/benchmarks/mocks/Invocation.json b/docs/static/benchmarks/mocks/Invocation.json index b461535e0c..4690a21209 100644 --- a/docs/static/benchmarks/mocks/Invocation.json +++ b/docs/static/benchmarks/mocks/Invocation.json @@ -1,173 +1,173 @@ { - "timestamp": "2026-04-05T03:32:35.400Z", + "timestamp": "2026-04-07T03:21:31.527Z", "category": "Invocation", "description": "Calling methods on mock objects", "environment": { "benchmarkDotNetVersion": "BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)", "sdk": ".NET SDK 10.0.201", - "host": ".NET 10.0.5 (10.0.5, 10.0.526.15411), X64 RyuJIT x86-64-v3" + "host": ".NET 10.0.5 (10.0.5, 10.0.526.15411), X64 RyuJIT x86-64-v4" }, "results": [ { "Method": "TUnit.Mocks", - "Mean": "368.7 ns", - "Error": "234.41 ns", - "StdDev": "12.85 ns", - "Gen0": "0.0057", - "Gen1": "0.0048", - "Allocated": "176 B" + "Mean": "261.5 ns", + "Error": "85.01 ns", + "StdDev": "4.66 ns", + "Gen0": "0.0062", + "Gen1": "0.0057", + "Allocated": "120 B" }, { "Method": "Imposter", - "Mean": "367.0 ns", - "Error": "102.23 ns", - "StdDev": "5.60 ns", - "Gen0": "0.0067", - "Gen1": "0.0062", + "Mean": "296.5 ns", + "Error": "100.09 ns", + "StdDev": "5.49 ns", + "Gen0": "0.0100", + "Gen1": "0.0095", "Allocated": "168 B" }, { "Method": "Mockolate", - "Mean": "796.7 ns", - "Error": "374.54 ns", - "StdDev": "20.53 ns", - "Gen0": "0.0248", - "Gen1": "0.0124", + "Mean": "707.3 ns", + "Error": "238.12 ns", + "StdDev": "13.05 ns", + "Gen0": "0.0381", + "Gen1": "0.0191", "Allocated": "640 B" }, { "Method": "Moq", - "Mean": "913.9 ns", - "Error": "344.02 ns", - "StdDev": "18.86 ns", - "Gen0": "0.0143", - "Gen1": "0.0134", + "Mean": "838.3 ns", + "Error": "187.87 ns", + "StdDev": "10.30 ns", + "Gen0": "0.0219", + "Gen1": "0.0210", "Allocated": "376 B" }, { "Method": "NSubstitute", - "Mean": "809.3 ns", - "Error": "236.18 ns", - "StdDev": "12.95 ns", - "Gen0": "0.0114", - "Gen1": "0.0105", + "Mean": "752.6 ns", + "Error": "191.36 ns", + "StdDev": "10.49 ns", + "Gen0": "0.0172", + "Gen1": "0.0162", "Allocated": "304 B" }, { "Method": "FakeItEasy", - "Mean": "2,020.7 ns", - "Error": "645.01 ns", - "StdDev": "35.35 ns", - "Gen0": "0.0362", - "Gen1": "0.0343", + "Mean": "1,883.0 ns", + "Error": "949.75 ns", + "StdDev": "52.06 ns", + "Gen0": "0.0553", + "Gen1": "0.0534", "Allocated": "944 B" }, { "Method": "'TUnit.Mocks (String)'", - "Mean": "227.7 ns", - "Error": "147.17 ns", - "StdDev": "8.07 ns", - "Gen0": "0.0041", - "Gen1": "0.0038", - "Allocated": "112 B" + "Mean": "157.6 ns", + "Error": "68.10 ns", + "StdDev": "3.73 ns", + "Gen0": "0.0048", + "Gen1": "0.0045", + "Allocated": "88 B" }, { "Method": "'Imposter (String)'", - "Mean": "364.0 ns", - "Error": "148.82 ns", - "StdDev": "8.16 ns", - "Gen0": "0.0067", - "Gen1": "0.0062", + "Mean": "302.9 ns", + "Error": "87.59 ns", + "StdDev": "4.80 ns", + "Gen0": "0.0100", + "Gen1": "0.0095", "Allocated": "168 B" }, { "Method": "'Mockolate (String)'", - "Mean": "722.7 ns", - "Error": "357.53 ns", - "StdDev": "19.60 ns", - "Gen0": "0.0200", - "Gen1": "0.0095", + "Mean": "551.7 ns", + "Error": "483.54 ns", + "StdDev": "26.50 ns", + "Gen0": "0.0305", + "Gen1": "0.0153", "Allocated": "520 B" }, { "Method": "'Moq (String)'", - "Mean": "608.3 ns", - "Error": "45.72 ns", - "StdDev": "2.51 ns", - "Gen0": "0.0114", - "Gen1": "0.0105", + "Mean": "547.3 ns", + "Error": "352.10 ns", + "StdDev": "19.30 ns", + "Gen0": "0.0172", + "Gen1": "0.0162", "Allocated": "296 B" }, { "Method": "'NSubstitute (String)'", - "Mean": "720.7 ns", - "Error": "116.44 ns", - "StdDev": "6.38 ns", - "Gen0": "0.0124", - "Gen1": "0.0114", - "Allocated": "328 B" + "Mean": "594.6 ns", + "Error": "152.85 ns", + "StdDev": "8.38 ns", + "Gen0": "0.0153", + "Gen1": "0.0143", + "Allocated": "272 B" }, { "Method": "'FakeItEasy (String)'", - "Mean": "1,753.1 ns", - "Error": "715.60 ns", - "StdDev": "39.22 ns", - "Gen0": "0.0305", - "Gen1": "0.0286", + "Mean": "1,584.9 ns", + "Error": "360.99 ns", + "StdDev": "19.79 ns", + "Gen0": "0.0458", + "Gen1": "0.0439", "Allocated": "776 B" }, { "Method": "'TUnit.Mocks (100 calls)'", - "Mean": "39,741.9 ns", - "Error": "12,503.76 ns", - "StdDev": "685.37 ns", + "Mean": "25,713.5 ns", + "Error": "8,104.61 ns", + "StdDev": "444.24 ns", "Gen0": "0.6104", - "Gen1": "0.5493", - "Allocated": "18048 B" + "Gen1": "0.5798", + "Allocated": "11936 B" }, { "Method": "'Imposter (100 calls)'", - "Mean": "37,376.4 ns", - "Error": "54,157.26 ns", - "StdDev": "2,968.54 ns", - "Gen0": "0.6104", - "Gen1": "0.5493", + "Mean": "28,487.4 ns", + "Error": "10,084.31 ns", + "StdDev": "552.76 ns", + "Gen0": "0.9766", + "Gen1": "0.9155", "Allocated": "16800 B" }, { "Method": "'Mockolate (100 calls)'", - "Mean": "77,269.3 ns", - "Error": "43,532.15 ns", - "StdDev": "2,386.14 ns", - "Gen0": "2.4414", - "Gen1": "1.2207", + "Mean": "66,299.9 ns", + "Error": "33,448.67 ns", + "StdDev": "1,833.43 ns", + "Gen0": "3.7842", + "Gen1": "1.8311", "Allocated": "64000 B" }, { "Method": "'Moq (100 calls)'", - "Mean": "88,134.5 ns", - "Error": "65,537.69 ns", - "StdDev": "3,592.34 ns", - "Gen0": "1.4648", - "Gen1": "1.3428", + "Mean": "79,836.2 ns", + "Error": "20,420.16 ns", + "StdDev": "1,119.30 ns", + "Gen0": "2.1973", + "Gen1": "2.0752", "Allocated": "37600 B" }, { "Method": "'NSubstitute (100 calls)'", - "Mean": "81,687.5 ns", - "Error": "38,698.53 ns", - "StdDev": "2,121.20 ns", - "Gen0": "1.3428", - "Gen1": "1.2207", - "Allocated": "36448 B" + "Mean": "74,687.4 ns", + "Error": "39,403.14 ns", + "StdDev": "2,159.82 ns", + "Gen0": "1.7090", + "Gen1": "1.5869", + "Allocated": "30848 B" }, { "Method": "'FakeItEasy (100 calls)'", - "Mean": "207,688.7 ns", - "Error": "7,905.08 ns", - "StdDev": "433.30 ns", - "Gen0": "3.6621", - "Gen1": "3.4180", + "Mean": "182,809.1 ns", + "Error": "61,051.13 ns", + "StdDev": "3,346.42 ns", + "Gen0": "5.6152", + "Gen1": "5.3711", "Allocated": "94400 B" } ] diff --git a/docs/static/benchmarks/mocks/MockCreation.json b/docs/static/benchmarks/mocks/MockCreation.json index c120f06703..e0a575a1eb 100644 --- a/docs/static/benchmarks/mocks/MockCreation.json +++ b/docs/static/benchmarks/mocks/MockCreation.json @@ -1,18 +1,18 @@ { - "timestamp": "2026-04-05T03:32:35.400Z", + "timestamp": "2026-04-07T03:21:31.527Z", "category": "MockCreation", "description": "Mock instance creation performance", "environment": { "benchmarkDotNetVersion": "BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)", "sdk": ".NET SDK 10.0.201", - "host": ".NET 10.0.5 (10.0.5, 10.0.526.15411), X64 RyuJIT x86-64-v3" + "host": ".NET 10.0.5 (10.0.5, 10.0.526.15411), X64 RyuJIT x86-64-v4" }, "results": [ { "Method": "TUnit.Mocks", - "Mean": "37.32 ns", - "Error": "0.593 ns", - "StdDev": "0.554 ns", + "Mean": "34.95 ns", + "Error": "0.706 ns", + "StdDev": "0.626 ns", "Gen0": "0.0119", "Gen1": "-", "Gen2": "-", @@ -20,9 +20,9 @@ }, { "Method": "Imposter", - "Mean": "94.75 ns", - "Error": "1.223 ns", - "StdDev": "1.144 ns", + "Mean": "88.70 ns", + "Error": "1.127 ns", + "StdDev": "0.999 ns", "Gen0": "0.0262", "Gen1": "-", "Gen2": "-", @@ -30,9 +30,9 @@ }, { "Method": "Mockolate", - "Mean": "68.77 ns", - "Error": "0.875 ns", - "StdDev": "0.775 ns", + "Mean": "63.69 ns", + "Error": "1.006 ns", + "StdDev": "0.840 ns", "Gen0": "0.0229", "Gen1": "-", "Gen2": "-", @@ -40,9 +40,9 @@ }, { "Method": "Moq", - "Mean": "1,377.57 ns", - "Error": "26.231 ns", - "StdDev": "24.536 ns", + "Mean": "1,412.49 ns", + "Error": "23.782 ns", + "StdDev": "22.246 ns", "Gen0": "0.1221", "Gen1": "-", "Gen2": "-", @@ -50,9 +50,9 @@ }, { "Method": "NSubstitute", - "Mean": "1,867.26 ns", - "Error": "19.052 ns", - "StdDev": "17.821 ns", + "Mean": "1,821.28 ns", + "Error": "21.288 ns", + "StdDev": "18.871 ns", "Gen0": "0.2975", "Gen1": "0.0019", "Gen2": "-", @@ -60,9 +60,9 @@ }, { "Method": "FakeItEasy", - "Mean": "1,774.46 ns", - "Error": "24.029 ns", - "StdDev": "21.301 ns", + "Mean": "1,749.58 ns", + "Error": "25.421 ns", + "StdDev": "22.535 ns", "Gen0": "0.1602", "Gen1": "0.0038", "Gen2": "0.0019", @@ -70,9 +70,9 @@ }, { "Method": "'TUnit.Mocks (Repository)'", - "Mean": "37.30 ns", - "Error": "0.425 ns", - "StdDev": "0.397 ns", + "Mean": "36.22 ns", + "Error": "0.593 ns", + "StdDev": "0.555 ns", "Gen0": "0.0119", "Gen1": "-", "Gen2": "-", @@ -80,9 +80,9 @@ }, { "Method": "'Imposter (Repository)'", - "Mean": "145.91 ns", - "Error": "1.850 ns", - "StdDev": "1.545 ns", + "Mean": "138.26 ns", + "Error": "1.636 ns", + "StdDev": "1.531 ns", "Gen0": "0.0415", "Gen1": "-", "Gen2": "-", @@ -90,9 +90,9 @@ }, { "Method": "'Mockolate (Repository)'", - "Mean": "69.91 ns", - "Error": "1.155 ns", - "StdDev": "1.081 ns", + "Mean": "64.42 ns", + "Error": "0.694 ns", + "StdDev": "0.615 ns", "Gen0": "0.0229", "Gen1": "-", "Gen2": "-", @@ -100,9 +100,9 @@ }, { "Method": "'Moq (Repository)'", - "Mean": "1,342.37 ns", - "Error": "7.233 ns", - "StdDev": "6.411 ns", + "Mean": "1,277.66 ns", + "Error": "10.361 ns", + "StdDev": "8.652 ns", "Gen0": "0.1125", "Gen1": "-", "Gen2": "-", @@ -110,9 +110,9 @@ }, { "Method": "'NSubstitute (Repository)'", - "Mean": "1,821.67 ns", - "Error": "10.874 ns", - "StdDev": "9.639 ns", + "Mean": "1,891.54 ns", + "Error": "17.627 ns", + "StdDev": "16.489 ns", "Gen0": "0.2975", "Gen1": "0.0019", "Gen2": "-", @@ -120,9 +120,9 @@ }, { "Method": "'FakeItEasy (Repository)'", - "Mean": "1,876.09 ns", - "Error": "37.231 ns", - "StdDev": "34.826 ns", + "Mean": "1,863.22 ns", + "Error": "26.136 ns", + "StdDev": "23.169 ns", "Gen0": "0.1602", "Gen1": "0.0038", "Gen2": "0.0019", diff --git a/docs/static/benchmarks/mocks/Setup.json b/docs/static/benchmarks/mocks/Setup.json index 12d3cbf51a..308f3cb069 100644 --- a/docs/static/benchmarks/mocks/Setup.json +++ b/docs/static/benchmarks/mocks/Setup.json @@ -1,117 +1,117 @@ { - "timestamp": "2026-04-05T03:32:35.400Z", + "timestamp": "2026-04-07T03:21:31.527Z", "category": "Setup", "description": "Mock behavior configuration (returns, matchers)", "environment": { "benchmarkDotNetVersion": "BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)", "sdk": ".NET SDK 10.0.201", - "host": ".NET 10.0.5 (10.0.5, 10.0.526.15411), X64 RyuJIT x86-64-v3" + "host": ".NET 10.0.5 (10.0.5, 10.0.526.15411), X64 RyuJIT x86-64-v4" }, "results": [ { "Method": "TUnit.Mocks", - "Mean": "492.4 ns", - "Error": "1.09 ns", - "StdDev": "0.85 ns", + "Mean": "524.9 ns", + "Error": "6.89 ns", + "StdDev": "6.45 ns", "Gen0": "0.1240", "Gen1": "-", "Allocated": "2.03 KB" }, { "Method": "Imposter", - "Mean": "774.2 ns", - "Error": "6.49 ns", - "StdDev": "6.07 ns", + "Mean": "828.1 ns", + "Error": "14.57 ns", + "StdDev": "12.91 ns", "Gen0": "0.3738", "Gen1": "0.0076", "Allocated": "6.12 KB" }, { "Method": "Mockolate", - "Mean": "424.9 ns", - "Error": "1.96 ns", - "StdDev": "1.53 ns", + "Mean": "472.7 ns", + "Error": "8.07 ns", + "StdDev": "7.54 ns", "Gen0": "0.1240", "Gen1": "0.0010", "Allocated": "2.03 KB" }, { "Method": "Moq", - "Mean": "421,701.0 ns", - "Error": "1,383.27 ns", - "StdDev": "1,155.09 ns", + "Mean": "421,754.9 ns", + "Error": "913.17 ns", + "StdDev": "762.54 ns", "Gen0": "0.9766", "Gen1": "-", - "Allocated": "28.76 KB" + "Allocated": "28.68 KB" }, { "Method": "NSubstitute", - "Mean": "5,305.7 ns", - "Error": "48.80 ns", - "StdDev": "40.75 ns", + "Mean": "5,616.3 ns", + "Error": "54.64 ns", + "StdDev": "51.11 ns", "Gen0": "0.5493", - "Gen1": "-", + "Gen1": "0.0076", "Allocated": "9.01 KB" }, { "Method": "FakeItEasy", - "Mean": "8,075.6 ns", - "Error": "43.50 ns", - "StdDev": "38.56 ns", - "Gen0": "0.6409", + "Mean": "8,118.4 ns", + "Error": "91.41 ns", + "StdDev": "85.50 ns", + "Gen0": "0.6256", "Gen1": "0.0153", - "Allocated": "10.53 KB" + "Allocated": "10.45 KB" }, { "Method": "'TUnit.Mocks (Multiple)'", - "Mean": "681.9 ns", - "Error": "3.15 ns", - "StdDev": "2.63 ns", + "Mean": "749.2 ns", + "Error": "12.24 ns", + "StdDev": "11.45 ns", "Gen0": "0.1650", "Gen1": "0.0010", "Allocated": "2.7 KB" }, { "Method": "'Imposter (Multiple)'", - "Mean": "1,306.9 ns", - "Error": "13.63 ns", - "StdDev": "12.75 ns", + "Mean": "1,401.7 ns", + "Error": "25.11 ns", + "StdDev": "23.48 ns", "Gen0": "0.6485", "Gen1": "0.0248", "Allocated": "10.59 KB" }, { "Method": "'Mockolate (Multiple)'", - "Mean": "663.5 ns", - "Error": "2.66 ns", - "StdDev": "2.36 ns", + "Mean": "712.9 ns", + "Error": "14.02 ns", + "StdDev": "16.14 ns", "Gen0": "0.1879", "Gen1": "0.0019", "Allocated": "3.07 KB" }, { "Method": "'Moq (Multiple)'", - "Mean": "112,440.0 ns", - "Error": "780.25 ns", - "StdDev": "691.67 ns", + "Mean": "112,999.3 ns", + "Error": "705.96 ns", + "StdDev": "625.82 ns", "Gen0": "0.9766", "Gen1": "0.7324", "Allocated": "16.53 KB" }, { "Method": "'NSubstitute (Multiple)'", - "Mean": "11,663.3 ns", - "Error": "33.90 ns", - "StdDev": "30.05 ns", - "Gen0": "1.2512", - "Gen1": "0.0458", - "Allocated": "20.47 KB" + "Mean": "12,404.1 ns", + "Error": "101.82 ns", + "StdDev": "90.27 ns", + "Gen0": "1.2207", + "Gen1": "-", + "Allocated": "20.31 KB" }, { "Method": "'FakeItEasy (Multiple)'", - "Mean": "7,415.3 ns", - "Error": "67.45 ns", - "StdDev": "59.80 ns", + "Mean": "7,566.5 ns", + "Error": "82.43 ns", + "StdDev": "77.11 ns", "Gen0": "0.6714", "Gen1": "0.0610", "Allocated": "11.71 KB" diff --git a/docs/static/benchmarks/mocks/Verification.json b/docs/static/benchmarks/mocks/Verification.json index d9dd78dbd0..d04f3d22dc 100644 --- a/docs/static/benchmarks/mocks/Verification.json +++ b/docs/static/benchmarks/mocks/Verification.json @@ -1,174 +1,192 @@ { - "timestamp": "2026-04-05T03:32:35.400Z", + "timestamp": "2026-04-07T03:21:31.527Z", "category": "Verification", "description": "Verifying mock method calls", "environment": { "benchmarkDotNetVersion": "BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)", "sdk": ".NET SDK 10.0.201", - "host": ".NET 10.0.5 (10.0.5, 10.0.526.15411), X64 RyuJIT x86-64-v3" + "host": ".NET 10.0.5 (10.0.5, 10.0.526.15411), X64 RyuJIT x86-64-v4" }, "results": [ { "Method": "TUnit.Mocks", - "Mean": "764.91 ns", - "Error": "11.322 ns", - "StdDev": "10.591 ns", - "Gen0": "0.1783", + "Mean": "922.60 ns", + "Error": "7.808 ns", + "StdDev": "7.303 ns", + "Gen0": "0.1211", "Gen1": "0.0010", - "Allocated": "2984 B" + "Gen2": "-", + "Allocated": "3048 B" }, { "Method": "Imposter", - "Mean": "769.71 ns", - "Error": "8.790 ns", - "StdDev": "8.222 ns", - "Gen0": "0.2794", - "Gen1": "0.0038", + "Mean": "844.24 ns", + "Error": "16.870 ns", + "StdDev": "37.383 ns", + "Gen0": "0.1860", + "Gen1": "0.0029", + "Gen2": "-", "Allocated": "4688 B" }, { "Method": "Mockolate", - "Mean": "950.06 ns", - "Error": "12.760 ns", - "StdDev": "11.936 ns", - "Gen0": "0.1879", - "Gen1": "0.0010", + "Mean": "1,053.70 ns", + "Error": "5.925 ns", + "StdDev": "5.252 ns", + "Gen0": "0.1240", + "Gen1": "-", + "Gen2": "-", "Allocated": "3152 B" }, { "Method": "Moq", - "Mean": "339,526.09 ns", - "Error": "1,819.383 ns", - "StdDev": "1,701.852 ns", + "Mean": "267,438.83 ns", + "Error": "1,931.282 ns", + "StdDev": "1,806.523 ns", "Gen0": "0.9766", "Gen1": "-", - "Allocated": "24325 B" + "Gen2": "-", + "Allocated": "24557 B" }, { "Method": "NSubstitute", - "Mean": "6,281.01 ns", - "Error": "63.710 ns", - "StdDev": "56.478 ns", - "Gen0": "0.5493", + "Mean": "6,451.74 ns", + "Error": "12.044 ns", + "StdDev": "10.677 ns", + "Gen0": "0.4044", "Gen1": "-", - "Allocated": "10064 B" + "Gen2": "-", + "Allocated": "10176 B" }, { "Method": "FakeItEasy", - "Mean": "7,432.16 ns", - "Error": "52.771 ns", - "StdDev": "49.362 ns", - "Gen0": "0.6409", + "Mean": "7,110.46 ns", + "Error": "38.252 ns", + "StdDev": "33.909 ns", + "Gen0": "0.4272", "Gen1": "0.0153", - "Allocated": "10722 B" + "Gen2": "0.0076", + "Allocated": "10731 B" }, { "Method": "'TUnit.Mocks (Never)'", - "Mean": "84.48 ns", - "Error": "0.911 ns", - "StdDev": "0.853 ns", - "Gen0": "0.0224", + "Mean": "97.18 ns", + "Error": "1.636 ns", + "StdDev": "1.531 ns", + "Gen0": "0.0149", "Gen1": "-", + "Gen2": "-", "Allocated": "376 B" }, { "Method": "'Imposter (Never)'", - "Mean": "337.65 ns", - "Error": "6.597 ns", - "StdDev": "6.775 ns", - "Gen0": "0.1431", - "Gen1": "0.0010", + "Mean": "406.52 ns", + "Error": "8.044 ns", + "StdDev": "12.758 ns", + "Gen0": "0.0954", + "Gen1": "0.0005", + "Gen2": "-", "Allocated": "2400 B" }, { "Method": "'Mockolate (Never)'", - "Mean": "225.18 ns", - "Error": "2.159 ns", - "StdDev": "2.019 ns", - "Gen0": "0.0567", + "Mean": "254.73 ns", + "Error": "1.878 ns", + "StdDev": "1.756 ns", + "Gen0": "0.0377", "Gen1": "-", + "Gen2": "-", "Allocated": "952 B" }, { "Method": "'Moq (Never)'", - "Mean": "87,077.29 ns", - "Error": "491.297 ns", - "StdDev": "435.522 ns", + "Mean": "65,371.08 ns", + "Error": "459.145 ns", + "StdDev": "383.407 ns", "Gen0": "0.2441", - "Gen1": "-", - "Allocated": "6918 B" + "Gen1": "0.1221", + "Gen2": "-", + "Allocated": "6925 B" }, { "Method": "'NSubstitute (Never)'", - "Mean": "3,594.29 ns", - "Error": "27.965 ns", - "StdDev": "24.790 ns", - "Gen0": "0.4234", - "Gen1": "0.0038", + "Mean": "3,524.13 ns", + "Error": "17.207 ns", + "StdDev": "15.253 ns", + "Gen0": "0.2823", + "Gen1": "-", + "Gen2": "-", "Allocated": "7088 B" }, { "Method": "'FakeItEasy (Never)'", - "Mean": "3,489.27 ns", - "Error": "32.051 ns", - "StdDev": "29.981 ns", - "Gen0": "0.3052", - "Gen1": "0.0305", - "Allocated": "5209 B" + "Mean": "3,655.87 ns", + "Error": "29.015 ns", + "StdDev": "27.140 ns", + "Gen0": "0.2060", + "Gen1": "0.0076", + "Gen2": "0.0038", + "Allocated": "5218 B" }, { "Method": "'TUnit.Mocks (Multiple)'", - "Mean": "1,380.27 ns", - "Error": "6.781 ns", - "StdDev": "6.343 ns", - "Gen0": "0.2632", + "Mean": "1,563.81 ns", + "Error": "13.064 ns", + "StdDev": "12.220 ns", + "Gen0": "0.1793", "Gen1": "0.0019", - "Allocated": "4416 B" + "Gen2": "-", + "Allocated": "4544 B" }, { "Method": "'Imposter (Multiple)'", - "Mean": "1,817.52 ns", - "Error": "16.933 ns", - "StdDev": "15.839 ns", - "Gen0": "0.6676", - "Gen1": "0.0210", + "Mean": "2,013.84 ns", + "Error": "40.150 ns", + "StdDev": "61.313 ns", + "Gen0": "0.4425", + "Gen1": "0.0114", + "Gen2": "-", "Allocated": "11192 B" }, { "Method": "'Mockolate (Multiple)'", - "Mean": "1,876.89 ns", - "Error": "9.292 ns", - "StdDev": "8.691 ns", - "Gen0": "0.3281", - "Gen1": "0.0019", + "Mean": "2,011.89 ns", + "Error": "13.868 ns", + "StdDev": "12.972 ns", + "Gen0": "0.2174", + "Gen1": "-", + "Gen2": "-", "Allocated": "5496 B" }, { "Method": "'Moq (Multiple)'", - "Mean": "468,799.88 ns", - "Error": "3,322.719 ns", - "StdDev": "3,108.074 ns", - "Gen0": "1.9531", - "Gen1": "0.9766", - "Allocated": "34699 B" + "Mean": "353,473.50 ns", + "Error": "3,057.036 ns", + "StdDev": "2,709.983 ns", + "Gen0": "0.9766", + "Gen1": "-", + "Gen2": "-", + "Allocated": "34670 B" }, { "Method": "'NSubstitute (Multiple)'", - "Mean": "11,571.76 ns", - "Error": "53.285 ns", - "StdDev": "49.843 ns", - "Gen0": "0.9918", - "Gen1": "0.0153", + "Mean": "11,427.85 ns", + "Error": "64.576 ns", + "StdDev": "57.245 ns", + "Gen0": "0.6104", + "Gen1": "-", + "Gen2": "-", "Allocated": "16762 B" }, { "Method": "'FakeItEasy (Multiple)'", - "Mean": "13,488.64 ns", - "Error": "178.615 ns", - "StdDev": "149.151 ns", - "Gen0": "1.0986", + "Mean": "12,260.11 ns", + "Error": "85.726 ns", + "StdDev": "75.993 ns", + "Gen0": "0.7324", "Gen1": "-", - "Allocated": "19233 B" + "Gen2": "-", + "Allocated": "19238 B" } ] } \ No newline at end of file diff --git a/docs/static/benchmarks/mocks/latest.json b/docs/static/benchmarks/mocks/latest.json index a9d218743e..550838e570 100644 --- a/docs/static/benchmarks/mocks/latest.json +++ b/docs/static/benchmarks/mocks/latest.json @@ -1,172 +1,172 @@ { - "timestamp": "2026-04-05T03:32:35.400Z", + "timestamp": "2026-04-07T03:21:31.527Z", "environment": { "benchmarkDotNetVersion": "BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)", "sdk": ".NET SDK 10.0.201", - "host": ".NET 10.0.5 (10.0.5, 10.0.526.15411), X64 RyuJIT x86-64-v3" + "host": ".NET 10.0.5 (10.0.5, 10.0.526.15411), X64 RyuJIT x86-64-v4" }, "categories": { "Callback": [ { "Method": "TUnit.Mocks", - "Mean": "651.9 ns", - "Error": "2.29 ns", - "StdDev": "1.91 ns", + "Mean": "746.7 ns", + "Error": "14.03 ns", + "StdDev": "14.40 ns", "Gen0": "0.1869", "Gen1": "0.0019", "Allocated": "3.06 KB" }, { "Method": "Imposter", - "Mean": "483.2 ns", - "Error": "3.31 ns", - "StdDev": "3.09 ns", + "Mean": "500.0 ns", + "Error": "9.96 ns", + "StdDev": "19.42 ns", "Gen0": "0.1621", "Gen1": "0.0010", "Allocated": "2.66 KB" }, { "Method": "Mockolate", - "Mean": "540.0 ns", - "Error": "10.61 ns", - "StdDev": "18.59 ns", + "Mean": "517.9 ns", + "Error": "7.25 ns", + "StdDev": "6.06 ns", "Gen0": "0.1097", "Gen1": "-", "Allocated": "1.8 KB" }, { "Method": "Moq", - "Mean": "184,643.6 ns", - "Error": "1,840.32 ns", - "StdDev": "1,721.44 ns", + "Mean": "188,044.7 ns", + "Error": "1,407.17 ns", + "StdDev": "1,316.27 ns", "Gen0": "0.4883", "Gen1": "-", - "Allocated": "13.14 KB" + "Allocated": "13.3 KB" }, { "Method": "NSubstitute", - "Mean": "4,630.0 ns", - "Error": "48.81 ns", - "StdDev": "45.66 ns", + "Mean": "4,661.9 ns", + "Error": "52.37 ns", + "StdDev": "48.99 ns", "Gen0": "0.4807", "Gen1": "0.0076", "Allocated": "7.93 KB" }, { "Method": "FakeItEasy", - "Mean": "5,166.1 ns", - "Error": "84.52 ns", - "StdDev": "79.06 ns", + "Mean": "5,463.0 ns", + "Error": "75.66 ns", + "StdDev": "70.77 ns", "Gen0": "0.4501", "Gen1": "0.0153", "Allocated": "7.44 KB" }, { "Method": "'TUnit.Mocks (with args)'", - "Mean": "772.7 ns", - "Error": "4.57 ns", - "StdDev": "4.27 ns", - "Gen0": "0.1974", + "Mean": "814.2 ns", + "Error": "14.65 ns", + "StdDev": "13.70 ns", + "Gen0": "0.1926", "Gen1": "0.0019", - "Allocated": "3.23 KB" + "Allocated": "3.15 KB" }, { "Method": "'Imposter (with args)'", - "Mean": "541.6 ns", - "Error": "10.67 ns", - "StdDev": "15.97 ns", + "Mean": "598.2 ns", + "Error": "11.57 ns", + "StdDev": "11.36 ns", "Gen0": "0.1726", "Gen1": "0.0010", "Allocated": "2.82 KB" }, { "Method": "'Mockolate (with args)'", - "Mean": "662.3 ns", - "Error": "11.28 ns", - "StdDev": "10.55 ns", + "Mean": "676.7 ns", + "Error": "13.37 ns", + "StdDev": "19.59 ns", "Gen0": "0.1297", "Gen1": "-", "Allocated": "2.13 KB" }, { "Method": "'Moq (with args)'", - "Mean": "194,142.1 ns", - "Error": "1,422.32 ns", - "StdDev": "1,330.44 ns", + "Mean": "193,932.5 ns", + "Error": "2,062.51 ns", + "StdDev": "1,929.28 ns", "Gen0": "0.4883", "Gen1": "-", - "Allocated": "13.84 KB" + "Allocated": "13.73 KB" }, { "Method": "'NSubstitute (with args)'", - "Mean": "5,128.9 ns", - "Error": "70.64 ns", - "StdDev": "62.62 ns", - "Gen0": "0.4883", - "Gen1": "-", + "Mean": "5,182.1 ns", + "Error": "65.78 ns", + "StdDev": "61.53 ns", + "Gen0": "0.5188", + "Gen1": "0.0076", "Allocated": "8.53 KB" }, { "Method": "'FakeItEasy (with args)'", - "Mean": "6,309.5 ns", - "Error": "114.70 ns", - "StdDev": "101.68 ns", + "Mean": "6,631.6 ns", + "Error": "75.42 ns", + "StdDev": "70.55 ns", "Gen0": "0.5493", "Gen1": "0.0610", - "Allocated": "9.26 KB" + "Allocated": "9.4 KB" } ], "CombinedWorkflow": [ { "Method": "TUnit.Mocks", - "Mean": "1.864 μs", - "Error": "0.0168 μs", - "StdDev": "0.0157 μs", - "Gen0": "0.3662", - "Gen1": "0.0057", - "Allocated": "6.01 KB" + "Mean": "2.035 μs", + "Error": "0.0399 μs", + "StdDev": "0.0491 μs", + "Gen0": "0.3738", + "Gen1": "0.0038", + "Allocated": "6.14 KB" }, { "Method": "Imposter", - "Mean": "2.623 μs", - "Error": "0.0306 μs", - "StdDev": "0.0287 μs", + "Mean": "2.746 μs", + "Error": "0.0511 μs", + "StdDev": "0.0478 μs", "Gen0": "0.9613", "Gen1": "0.0458", "Allocated": "15.71 KB" }, { "Method": "Mockolate", - "Mean": "2.346 μs", - "Error": "0.0240 μs", - "StdDev": "0.0224 μs", + "Mean": "2.562 μs", + "Error": "0.0510 μs", + "StdDev": "0.0681 μs", "Gen0": "0.4311", "Gen1": "0.0038", "Allocated": "7.09 KB" }, { "Method": "Moq", - "Mean": "403.794 μs", - "Error": "2.7482 μs", - "StdDev": "2.5707 μs", + "Mean": "403.167 μs", + "Error": "3.3674 μs", + "StdDev": "2.8119 μs", "Gen0": "1.9531", "Gen1": "0.9766", - "Allocated": "36.38 KB" + "Allocated": "36.74 KB" }, { "Method": "NSubstitute", - "Mean": "16.942 μs", - "Error": "0.1111 μs", - "StdDev": "0.1039 μs", + "Mean": "17.244 μs", + "Error": "0.2324 μs", + "StdDev": "0.2174 μs", "Gen0": "1.6174", "Gen1": "0.0305", "Allocated": "26.72 KB" }, { "Method": "FakeItEasy", - "Mean": "18.390 μs", - "Error": "0.2776 μs", - "StdDev": "0.2461 μs", + "Mean": "18.200 μs", + "Error": "0.3194 μs", + "StdDev": "0.3280 μs", "Gen0": "1.4648", "Gen1": "0.1221", "Allocated": "25.52 KB" @@ -175,173 +175,173 @@ "Invocation": [ { "Method": "TUnit.Mocks", - "Mean": "368.7 ns", - "Error": "234.41 ns", - "StdDev": "12.85 ns", - "Gen0": "0.0057", - "Gen1": "0.0048", - "Allocated": "176 B" + "Mean": "261.5 ns", + "Error": "85.01 ns", + "StdDev": "4.66 ns", + "Gen0": "0.0062", + "Gen1": "0.0057", + "Allocated": "120 B" }, { "Method": "Imposter", - "Mean": "367.0 ns", - "Error": "102.23 ns", - "StdDev": "5.60 ns", - "Gen0": "0.0067", - "Gen1": "0.0062", + "Mean": "296.5 ns", + "Error": "100.09 ns", + "StdDev": "5.49 ns", + "Gen0": "0.0100", + "Gen1": "0.0095", "Allocated": "168 B" }, { "Method": "Mockolate", - "Mean": "796.7 ns", - "Error": "374.54 ns", - "StdDev": "20.53 ns", - "Gen0": "0.0248", - "Gen1": "0.0124", + "Mean": "707.3 ns", + "Error": "238.12 ns", + "StdDev": "13.05 ns", + "Gen0": "0.0381", + "Gen1": "0.0191", "Allocated": "640 B" }, { "Method": "Moq", - "Mean": "913.9 ns", - "Error": "344.02 ns", - "StdDev": "18.86 ns", - "Gen0": "0.0143", - "Gen1": "0.0134", + "Mean": "838.3 ns", + "Error": "187.87 ns", + "StdDev": "10.30 ns", + "Gen0": "0.0219", + "Gen1": "0.0210", "Allocated": "376 B" }, { "Method": "NSubstitute", - "Mean": "809.3 ns", - "Error": "236.18 ns", - "StdDev": "12.95 ns", - "Gen0": "0.0114", - "Gen1": "0.0105", + "Mean": "752.6 ns", + "Error": "191.36 ns", + "StdDev": "10.49 ns", + "Gen0": "0.0172", + "Gen1": "0.0162", "Allocated": "304 B" }, { "Method": "FakeItEasy", - "Mean": "2,020.7 ns", - "Error": "645.01 ns", - "StdDev": "35.35 ns", - "Gen0": "0.0362", - "Gen1": "0.0343", + "Mean": "1,883.0 ns", + "Error": "949.75 ns", + "StdDev": "52.06 ns", + "Gen0": "0.0553", + "Gen1": "0.0534", "Allocated": "944 B" }, { "Method": "'TUnit.Mocks (String)'", - "Mean": "227.7 ns", - "Error": "147.17 ns", - "StdDev": "8.07 ns", - "Gen0": "0.0041", - "Gen1": "0.0038", - "Allocated": "112 B" + "Mean": "157.6 ns", + "Error": "68.10 ns", + "StdDev": "3.73 ns", + "Gen0": "0.0048", + "Gen1": "0.0045", + "Allocated": "88 B" }, { "Method": "'Imposter (String)'", - "Mean": "364.0 ns", - "Error": "148.82 ns", - "StdDev": "8.16 ns", - "Gen0": "0.0067", - "Gen1": "0.0062", + "Mean": "302.9 ns", + "Error": "87.59 ns", + "StdDev": "4.80 ns", + "Gen0": "0.0100", + "Gen1": "0.0095", "Allocated": "168 B" }, { "Method": "'Mockolate (String)'", - "Mean": "722.7 ns", - "Error": "357.53 ns", - "StdDev": "19.60 ns", - "Gen0": "0.0200", - "Gen1": "0.0095", + "Mean": "551.7 ns", + "Error": "483.54 ns", + "StdDev": "26.50 ns", + "Gen0": "0.0305", + "Gen1": "0.0153", "Allocated": "520 B" }, { "Method": "'Moq (String)'", - "Mean": "608.3 ns", - "Error": "45.72 ns", - "StdDev": "2.51 ns", - "Gen0": "0.0114", - "Gen1": "0.0105", + "Mean": "547.3 ns", + "Error": "352.10 ns", + "StdDev": "19.30 ns", + "Gen0": "0.0172", + "Gen1": "0.0162", "Allocated": "296 B" }, { "Method": "'NSubstitute (String)'", - "Mean": "720.7 ns", - "Error": "116.44 ns", - "StdDev": "6.38 ns", - "Gen0": "0.0124", - "Gen1": "0.0114", - "Allocated": "328 B" + "Mean": "594.6 ns", + "Error": "152.85 ns", + "StdDev": "8.38 ns", + "Gen0": "0.0153", + "Gen1": "0.0143", + "Allocated": "272 B" }, { "Method": "'FakeItEasy (String)'", - "Mean": "1,753.1 ns", - "Error": "715.60 ns", - "StdDev": "39.22 ns", - "Gen0": "0.0305", - "Gen1": "0.0286", + "Mean": "1,584.9 ns", + "Error": "360.99 ns", + "StdDev": "19.79 ns", + "Gen0": "0.0458", + "Gen1": "0.0439", "Allocated": "776 B" }, { "Method": "'TUnit.Mocks (100 calls)'", - "Mean": "39,741.9 ns", - "Error": "12,503.76 ns", - "StdDev": "685.37 ns", + "Mean": "25,713.5 ns", + "Error": "8,104.61 ns", + "StdDev": "444.24 ns", "Gen0": "0.6104", - "Gen1": "0.5493", - "Allocated": "18048 B" + "Gen1": "0.5798", + "Allocated": "11936 B" }, { "Method": "'Imposter (100 calls)'", - "Mean": "37,376.4 ns", - "Error": "54,157.26 ns", - "StdDev": "2,968.54 ns", - "Gen0": "0.6104", - "Gen1": "0.5493", + "Mean": "28,487.4 ns", + "Error": "10,084.31 ns", + "StdDev": "552.76 ns", + "Gen0": "0.9766", + "Gen1": "0.9155", "Allocated": "16800 B" }, { "Method": "'Mockolate (100 calls)'", - "Mean": "77,269.3 ns", - "Error": "43,532.15 ns", - "StdDev": "2,386.14 ns", - "Gen0": "2.4414", - "Gen1": "1.2207", + "Mean": "66,299.9 ns", + "Error": "33,448.67 ns", + "StdDev": "1,833.43 ns", + "Gen0": "3.7842", + "Gen1": "1.8311", "Allocated": "64000 B" }, { "Method": "'Moq (100 calls)'", - "Mean": "88,134.5 ns", - "Error": "65,537.69 ns", - "StdDev": "3,592.34 ns", - "Gen0": "1.4648", - "Gen1": "1.3428", + "Mean": "79,836.2 ns", + "Error": "20,420.16 ns", + "StdDev": "1,119.30 ns", + "Gen0": "2.1973", + "Gen1": "2.0752", "Allocated": "37600 B" }, { "Method": "'NSubstitute (100 calls)'", - "Mean": "81,687.5 ns", - "Error": "38,698.53 ns", - "StdDev": "2,121.20 ns", - "Gen0": "1.3428", - "Gen1": "1.2207", - "Allocated": "36448 B" + "Mean": "74,687.4 ns", + "Error": "39,403.14 ns", + "StdDev": "2,159.82 ns", + "Gen0": "1.7090", + "Gen1": "1.5869", + "Allocated": "30848 B" }, { "Method": "'FakeItEasy (100 calls)'", - "Mean": "207,688.7 ns", - "Error": "7,905.08 ns", - "StdDev": "433.30 ns", - "Gen0": "3.6621", - "Gen1": "3.4180", + "Mean": "182,809.1 ns", + "Error": "61,051.13 ns", + "StdDev": "3,346.42 ns", + "Gen0": "5.6152", + "Gen1": "5.3711", "Allocated": "94400 B" } ], "MockCreation": [ { "Method": "TUnit.Mocks", - "Mean": "37.32 ns", - "Error": "0.593 ns", - "StdDev": "0.554 ns", + "Mean": "34.95 ns", + "Error": "0.706 ns", + "StdDev": "0.626 ns", "Gen0": "0.0119", "Gen1": "-", "Gen2": "-", @@ -349,9 +349,9 @@ }, { "Method": "Imposter", - "Mean": "94.75 ns", - "Error": "1.223 ns", - "StdDev": "1.144 ns", + "Mean": "88.70 ns", + "Error": "1.127 ns", + "StdDev": "0.999 ns", "Gen0": "0.0262", "Gen1": "-", "Gen2": "-", @@ -359,9 +359,9 @@ }, { "Method": "Mockolate", - "Mean": "68.77 ns", - "Error": "0.875 ns", - "StdDev": "0.775 ns", + "Mean": "63.69 ns", + "Error": "1.006 ns", + "StdDev": "0.840 ns", "Gen0": "0.0229", "Gen1": "-", "Gen2": "-", @@ -369,9 +369,9 @@ }, { "Method": "Moq", - "Mean": "1,377.57 ns", - "Error": "26.231 ns", - "StdDev": "24.536 ns", + "Mean": "1,412.49 ns", + "Error": "23.782 ns", + "StdDev": "22.246 ns", "Gen0": "0.1221", "Gen1": "-", "Gen2": "-", @@ -379,9 +379,9 @@ }, { "Method": "NSubstitute", - "Mean": "1,867.26 ns", - "Error": "19.052 ns", - "StdDev": "17.821 ns", + "Mean": "1,821.28 ns", + "Error": "21.288 ns", + "StdDev": "18.871 ns", "Gen0": "0.2975", "Gen1": "0.0019", "Gen2": "-", @@ -389,9 +389,9 @@ }, { "Method": "FakeItEasy", - "Mean": "1,774.46 ns", - "Error": "24.029 ns", - "StdDev": "21.301 ns", + "Mean": "1,749.58 ns", + "Error": "25.421 ns", + "StdDev": "22.535 ns", "Gen0": "0.1602", "Gen1": "0.0038", "Gen2": "0.0019", @@ -399,9 +399,9 @@ }, { "Method": "'TUnit.Mocks (Repository)'", - "Mean": "37.30 ns", - "Error": "0.425 ns", - "StdDev": "0.397 ns", + "Mean": "36.22 ns", + "Error": "0.593 ns", + "StdDev": "0.555 ns", "Gen0": "0.0119", "Gen1": "-", "Gen2": "-", @@ -409,9 +409,9 @@ }, { "Method": "'Imposter (Repository)'", - "Mean": "145.91 ns", - "Error": "1.850 ns", - "StdDev": "1.545 ns", + "Mean": "138.26 ns", + "Error": "1.636 ns", + "StdDev": "1.531 ns", "Gen0": "0.0415", "Gen1": "-", "Gen2": "-", @@ -419,9 +419,9 @@ }, { "Method": "'Mockolate (Repository)'", - "Mean": "69.91 ns", - "Error": "1.155 ns", - "StdDev": "1.081 ns", + "Mean": "64.42 ns", + "Error": "0.694 ns", + "StdDev": "0.615 ns", "Gen0": "0.0229", "Gen1": "-", "Gen2": "-", @@ -429,9 +429,9 @@ }, { "Method": "'Moq (Repository)'", - "Mean": "1,342.37 ns", - "Error": "7.233 ns", - "StdDev": "6.411 ns", + "Mean": "1,277.66 ns", + "Error": "10.361 ns", + "StdDev": "8.652 ns", "Gen0": "0.1125", "Gen1": "-", "Gen2": "-", @@ -439,9 +439,9 @@ }, { "Method": "'NSubstitute (Repository)'", - "Mean": "1,821.67 ns", - "Error": "10.874 ns", - "StdDev": "9.639 ns", + "Mean": "1,891.54 ns", + "Error": "17.627 ns", + "StdDev": "16.489 ns", "Gen0": "0.2975", "Gen1": "0.0019", "Gen2": "-", @@ -449,9 +449,9 @@ }, { "Method": "'FakeItEasy (Repository)'", - "Mean": "1,876.09 ns", - "Error": "37.231 ns", - "StdDev": "34.826 ns", + "Mean": "1,863.22 ns", + "Error": "26.136 ns", + "StdDev": "23.169 ns", "Gen0": "0.1602", "Gen1": "0.0038", "Gen2": "0.0019", @@ -461,108 +461,108 @@ "Setup": [ { "Method": "TUnit.Mocks", - "Mean": "492.4 ns", - "Error": "1.09 ns", - "StdDev": "0.85 ns", + "Mean": "524.9 ns", + "Error": "6.89 ns", + "StdDev": "6.45 ns", "Gen0": "0.1240", "Gen1": "-", "Allocated": "2.03 KB" }, { "Method": "Imposter", - "Mean": "774.2 ns", - "Error": "6.49 ns", - "StdDev": "6.07 ns", + "Mean": "828.1 ns", + "Error": "14.57 ns", + "StdDev": "12.91 ns", "Gen0": "0.3738", "Gen1": "0.0076", "Allocated": "6.12 KB" }, { "Method": "Mockolate", - "Mean": "424.9 ns", - "Error": "1.96 ns", - "StdDev": "1.53 ns", + "Mean": "472.7 ns", + "Error": "8.07 ns", + "StdDev": "7.54 ns", "Gen0": "0.1240", "Gen1": "0.0010", "Allocated": "2.03 KB" }, { "Method": "Moq", - "Mean": "421,701.0 ns", - "Error": "1,383.27 ns", - "StdDev": "1,155.09 ns", + "Mean": "421,754.9 ns", + "Error": "913.17 ns", + "StdDev": "762.54 ns", "Gen0": "0.9766", "Gen1": "-", - "Allocated": "28.76 KB" + "Allocated": "28.68 KB" }, { "Method": "NSubstitute", - "Mean": "5,305.7 ns", - "Error": "48.80 ns", - "StdDev": "40.75 ns", + "Mean": "5,616.3 ns", + "Error": "54.64 ns", + "StdDev": "51.11 ns", "Gen0": "0.5493", - "Gen1": "-", + "Gen1": "0.0076", "Allocated": "9.01 KB" }, { "Method": "FakeItEasy", - "Mean": "8,075.6 ns", - "Error": "43.50 ns", - "StdDev": "38.56 ns", - "Gen0": "0.6409", + "Mean": "8,118.4 ns", + "Error": "91.41 ns", + "StdDev": "85.50 ns", + "Gen0": "0.6256", "Gen1": "0.0153", - "Allocated": "10.53 KB" + "Allocated": "10.45 KB" }, { "Method": "'TUnit.Mocks (Multiple)'", - "Mean": "681.9 ns", - "Error": "3.15 ns", - "StdDev": "2.63 ns", + "Mean": "749.2 ns", + "Error": "12.24 ns", + "StdDev": "11.45 ns", "Gen0": "0.1650", "Gen1": "0.0010", "Allocated": "2.7 KB" }, { "Method": "'Imposter (Multiple)'", - "Mean": "1,306.9 ns", - "Error": "13.63 ns", - "StdDev": "12.75 ns", + "Mean": "1,401.7 ns", + "Error": "25.11 ns", + "StdDev": "23.48 ns", "Gen0": "0.6485", "Gen1": "0.0248", "Allocated": "10.59 KB" }, { "Method": "'Mockolate (Multiple)'", - "Mean": "663.5 ns", - "Error": "2.66 ns", - "StdDev": "2.36 ns", + "Mean": "712.9 ns", + "Error": "14.02 ns", + "StdDev": "16.14 ns", "Gen0": "0.1879", "Gen1": "0.0019", "Allocated": "3.07 KB" }, { "Method": "'Moq (Multiple)'", - "Mean": "112,440.0 ns", - "Error": "780.25 ns", - "StdDev": "691.67 ns", + "Mean": "112,999.3 ns", + "Error": "705.96 ns", + "StdDev": "625.82 ns", "Gen0": "0.9766", "Gen1": "0.7324", "Allocated": "16.53 KB" }, { "Method": "'NSubstitute (Multiple)'", - "Mean": "11,663.3 ns", - "Error": "33.90 ns", - "StdDev": "30.05 ns", - "Gen0": "1.2512", - "Gen1": "0.0458", - "Allocated": "20.47 KB" + "Mean": "12,404.1 ns", + "Error": "101.82 ns", + "StdDev": "90.27 ns", + "Gen0": "1.2207", + "Gen1": "-", + "Allocated": "20.31 KB" }, { "Method": "'FakeItEasy (Multiple)'", - "Mean": "7,415.3 ns", - "Error": "67.45 ns", - "StdDev": "59.80 ns", + "Mean": "7,566.5 ns", + "Error": "82.43 ns", + "StdDev": "77.11 ns", "Gen0": "0.6714", "Gen1": "0.0610", "Allocated": "11.71 KB" @@ -571,171 +571,189 @@ "Verification": [ { "Method": "TUnit.Mocks", - "Mean": "764.91 ns", - "Error": "11.322 ns", - "StdDev": "10.591 ns", - "Gen0": "0.1783", + "Mean": "922.60 ns", + "Error": "7.808 ns", + "StdDev": "7.303 ns", + "Gen0": "0.1211", "Gen1": "0.0010", - "Allocated": "2984 B" + "Gen2": "-", + "Allocated": "3048 B" }, { "Method": "Imposter", - "Mean": "769.71 ns", - "Error": "8.790 ns", - "StdDev": "8.222 ns", - "Gen0": "0.2794", - "Gen1": "0.0038", + "Mean": "844.24 ns", + "Error": "16.870 ns", + "StdDev": "37.383 ns", + "Gen0": "0.1860", + "Gen1": "0.0029", + "Gen2": "-", "Allocated": "4688 B" }, { "Method": "Mockolate", - "Mean": "950.06 ns", - "Error": "12.760 ns", - "StdDev": "11.936 ns", - "Gen0": "0.1879", - "Gen1": "0.0010", + "Mean": "1,053.70 ns", + "Error": "5.925 ns", + "StdDev": "5.252 ns", + "Gen0": "0.1240", + "Gen1": "-", + "Gen2": "-", "Allocated": "3152 B" }, { "Method": "Moq", - "Mean": "339,526.09 ns", - "Error": "1,819.383 ns", - "StdDev": "1,701.852 ns", + "Mean": "267,438.83 ns", + "Error": "1,931.282 ns", + "StdDev": "1,806.523 ns", "Gen0": "0.9766", "Gen1": "-", - "Allocated": "24325 B" + "Gen2": "-", + "Allocated": "24557 B" }, { "Method": "NSubstitute", - "Mean": "6,281.01 ns", - "Error": "63.710 ns", - "StdDev": "56.478 ns", - "Gen0": "0.5493", + "Mean": "6,451.74 ns", + "Error": "12.044 ns", + "StdDev": "10.677 ns", + "Gen0": "0.4044", "Gen1": "-", - "Allocated": "10064 B" + "Gen2": "-", + "Allocated": "10176 B" }, { "Method": "FakeItEasy", - "Mean": "7,432.16 ns", - "Error": "52.771 ns", - "StdDev": "49.362 ns", - "Gen0": "0.6409", + "Mean": "7,110.46 ns", + "Error": "38.252 ns", + "StdDev": "33.909 ns", + "Gen0": "0.4272", "Gen1": "0.0153", - "Allocated": "10722 B" + "Gen2": "0.0076", + "Allocated": "10731 B" }, { "Method": "'TUnit.Mocks (Never)'", - "Mean": "84.48 ns", - "Error": "0.911 ns", - "StdDev": "0.853 ns", - "Gen0": "0.0224", + "Mean": "97.18 ns", + "Error": "1.636 ns", + "StdDev": "1.531 ns", + "Gen0": "0.0149", "Gen1": "-", + "Gen2": "-", "Allocated": "376 B" }, { "Method": "'Imposter (Never)'", - "Mean": "337.65 ns", - "Error": "6.597 ns", - "StdDev": "6.775 ns", - "Gen0": "0.1431", - "Gen1": "0.0010", + "Mean": "406.52 ns", + "Error": "8.044 ns", + "StdDev": "12.758 ns", + "Gen0": "0.0954", + "Gen1": "0.0005", + "Gen2": "-", "Allocated": "2400 B" }, { "Method": "'Mockolate (Never)'", - "Mean": "225.18 ns", - "Error": "2.159 ns", - "StdDev": "2.019 ns", - "Gen0": "0.0567", + "Mean": "254.73 ns", + "Error": "1.878 ns", + "StdDev": "1.756 ns", + "Gen0": "0.0377", "Gen1": "-", + "Gen2": "-", "Allocated": "952 B" }, { "Method": "'Moq (Never)'", - "Mean": "87,077.29 ns", - "Error": "491.297 ns", - "StdDev": "435.522 ns", + "Mean": "65,371.08 ns", + "Error": "459.145 ns", + "StdDev": "383.407 ns", "Gen0": "0.2441", - "Gen1": "-", - "Allocated": "6918 B" + "Gen1": "0.1221", + "Gen2": "-", + "Allocated": "6925 B" }, { "Method": "'NSubstitute (Never)'", - "Mean": "3,594.29 ns", - "Error": "27.965 ns", - "StdDev": "24.790 ns", - "Gen0": "0.4234", - "Gen1": "0.0038", + "Mean": "3,524.13 ns", + "Error": "17.207 ns", + "StdDev": "15.253 ns", + "Gen0": "0.2823", + "Gen1": "-", + "Gen2": "-", "Allocated": "7088 B" }, { "Method": "'FakeItEasy (Never)'", - "Mean": "3,489.27 ns", - "Error": "32.051 ns", - "StdDev": "29.981 ns", - "Gen0": "0.3052", - "Gen1": "0.0305", - "Allocated": "5209 B" + "Mean": "3,655.87 ns", + "Error": "29.015 ns", + "StdDev": "27.140 ns", + "Gen0": "0.2060", + "Gen1": "0.0076", + "Gen2": "0.0038", + "Allocated": "5218 B" }, { "Method": "'TUnit.Mocks (Multiple)'", - "Mean": "1,380.27 ns", - "Error": "6.781 ns", - "StdDev": "6.343 ns", - "Gen0": "0.2632", + "Mean": "1,563.81 ns", + "Error": "13.064 ns", + "StdDev": "12.220 ns", + "Gen0": "0.1793", "Gen1": "0.0019", - "Allocated": "4416 B" + "Gen2": "-", + "Allocated": "4544 B" }, { "Method": "'Imposter (Multiple)'", - "Mean": "1,817.52 ns", - "Error": "16.933 ns", - "StdDev": "15.839 ns", - "Gen0": "0.6676", - "Gen1": "0.0210", + "Mean": "2,013.84 ns", + "Error": "40.150 ns", + "StdDev": "61.313 ns", + "Gen0": "0.4425", + "Gen1": "0.0114", + "Gen2": "-", "Allocated": "11192 B" }, { "Method": "'Mockolate (Multiple)'", - "Mean": "1,876.89 ns", - "Error": "9.292 ns", - "StdDev": "8.691 ns", - "Gen0": "0.3281", - "Gen1": "0.0019", + "Mean": "2,011.89 ns", + "Error": "13.868 ns", + "StdDev": "12.972 ns", + "Gen0": "0.2174", + "Gen1": "-", + "Gen2": "-", "Allocated": "5496 B" }, { "Method": "'Moq (Multiple)'", - "Mean": "468,799.88 ns", - "Error": "3,322.719 ns", - "StdDev": "3,108.074 ns", - "Gen0": "1.9531", - "Gen1": "0.9766", - "Allocated": "34699 B" + "Mean": "353,473.50 ns", + "Error": "3,057.036 ns", + "StdDev": "2,709.983 ns", + "Gen0": "0.9766", + "Gen1": "-", + "Gen2": "-", + "Allocated": "34670 B" }, { "Method": "'NSubstitute (Multiple)'", - "Mean": "11,571.76 ns", - "Error": "53.285 ns", - "StdDev": "49.843 ns", - "Gen0": "0.9918", - "Gen1": "0.0153", + "Mean": "11,427.85 ns", + "Error": "64.576 ns", + "StdDev": "57.245 ns", + "Gen0": "0.6104", + "Gen1": "-", + "Gen2": "-", "Allocated": "16762 B" }, { "Method": "'FakeItEasy (Multiple)'", - "Mean": "13,488.64 ns", - "Error": "178.615 ns", - "StdDev": "149.151 ns", - "Gen0": "1.0986", + "Mean": "12,260.11 ns", + "Error": "85.726 ns", + "StdDev": "75.993 ns", + "Gen0": "0.7324", "Gen1": "-", - "Allocated": "19233 B" + "Gen2": "-", + "Allocated": "19238 B" } ] }, "stats": { "categoryCount": 6, "totalBenchmarks": 78, - "lastUpdated": "2026-04-05T03:32:35.400Z" + "lastUpdated": "2026-04-07T03:21:31.527Z" } } \ No newline at end of file diff --git a/docs/static/benchmarks/mocks/summary.json b/docs/static/benchmarks/mocks/summary.json index 9e133e2caa..61d1d96f79 100644 --- a/docs/static/benchmarks/mocks/summary.json +++ b/docs/static/benchmarks/mocks/summary.json @@ -7,7 +7,7 @@ "Setup", "Verification" ], - "timestamp": "2026-04-05", + "timestamp": "2026-04-07", "environment": "Ubuntu Latest • .NET SDK 10.0.201", "libraries": [ "TUnit.Mocks", diff --git a/docs/static/benchmarks/summary.json b/docs/static/benchmarks/summary.json index bd67c5debd..8188a11a48 100644 --- a/docs/static/benchmarks/summary.json +++ b/docs/static/benchmarks/summary.json @@ -10,6 +10,6 @@ "build": [ "BuildTime" ], - "timestamp": "2026-04-05", + "timestamp": "2026-04-07", "environment": "Ubuntu Latest • .NET SDK 10.0.201" } \ No newline at end of file diff --git a/docs/yarn.lock b/docs/yarn.lock index 255c99e7f7..569187eabe 100644 --- a/docs/yarn.lock +++ b/docs/yarn.lock @@ -2,41 +2,6 @@ # yarn lockfile v1 -"@ai-sdk/gateway@2.0.23": - version "2.0.23" - resolved "https://registry.npmjs.org/@ai-sdk/gateway/-/gateway-2.0.23.tgz" - integrity sha512-qmX7afPRszUqG5hryHF3UN8ITPIRSGmDW6VYCmByzjoUkgm3MekzSx2hMV1wr0P+llDeuXb378SjqUfpvWJulg== - dependencies: - "@ai-sdk/provider" "2.0.0" - "@ai-sdk/provider-utils" "3.0.19" - "@vercel/oidc" "3.0.5" - -"@ai-sdk/provider-utils@3.0.19": - version "3.0.19" - resolved "https://registry.npmjs.org/@ai-sdk/provider-utils/-/provider-utils-3.0.19.tgz" - integrity sha512-W41Wc9/jbUVXVwCN/7bWa4IKe8MtxO3EyA0Hfhx6grnmiYlCvpI8neSYWFE0zScXJkgA/YK3BRybzgyiXuu6JA== - dependencies: - "@ai-sdk/provider" "2.0.0" - "@standard-schema/spec" "^1.0.0" - eventsource-parser "^3.0.6" - -"@ai-sdk/provider@2.0.0": - version "2.0.0" - resolved "https://registry.npmjs.org/@ai-sdk/provider/-/provider-2.0.0.tgz" - integrity sha512-6o7Y2SeO9vFKB8lArHXehNuusnpddKPk7xqL7T2/b+OvXMRIXUO1rR4wcv1hAFUAT9avGZshty3Wlua/XA7TvA== - dependencies: - json-schema "^0.4.0" - -"@ai-sdk/react@^2.0.30": - version "2.0.118" - resolved "https://registry.npmjs.org/@ai-sdk/react/-/react-2.0.118.tgz" - integrity sha512-K/5VVEGTIu9SWrdQ0s/11OldFU8IjprDzeE6TaC2fOcQWhG7dGVGl9H8Z32QBHzdfJyMhFUxEyFKSOgA2j9+VQ== - dependencies: - "@ai-sdk/provider-utils" "3.0.19" - ai "5.0.116" - swr "^2.2.5" - throttleit "2.1.0" - "@algolia/abtesting@1.12.1": version "1.12.1" resolved "https://registry.npmjs.org/@algolia/abtesting/-/abtesting-1.12.1.tgz" @@ -55,6 +20,14 @@ "@algolia/autocomplete-plugin-algolia-insights" "1.19.2" "@algolia/autocomplete-shared" "1.19.2" +"@algolia/autocomplete-core@^1.19.2": + version "1.19.8" + resolved "https://registry.yarnpkg.com/@algolia/autocomplete-core/-/autocomplete-core-1.19.8.tgz#7c84c771d28643fb00d09026c05013fb97aeea23" + integrity sha512-3YEorYg44niXcm7gkft3nXYItHd44e8tmh4D33CTszPgP0QWkaLEaFywiNyJBo7UL/mqObA/G9RYuU7R8tN1IA== + dependencies: + "@algolia/autocomplete-plugin-algolia-insights" "1.19.8" + "@algolia/autocomplete-shared" "1.19.8" + "@algolia/autocomplete-plugin-algolia-insights@1.19.2": version "1.19.2" resolved "https://registry.npmjs.org/@algolia/autocomplete-plugin-algolia-insights/-/autocomplete-plugin-algolia-insights-1.19.2.tgz" @@ -62,11 +35,23 @@ dependencies: "@algolia/autocomplete-shared" "1.19.2" +"@algolia/autocomplete-plugin-algolia-insights@1.19.8": + version "1.19.8" + resolved "https://registry.yarnpkg.com/@algolia/autocomplete-plugin-algolia-insights/-/autocomplete-plugin-algolia-insights-1.19.8.tgz#f60d21edbe2a42e6d4e2215430733e3f51641471" + integrity sha512-ZvJWO8ZZJDpc1LNM2TTBdmQsZBLMR4rU5iNR2OYvEeFBiaf/0ESnRSSLQbryarJY4SVxtoz6A2ZtDMNM+iQEAA== + dependencies: + "@algolia/autocomplete-shared" "1.19.8" + "@algolia/autocomplete-shared@1.19.2": version "1.19.2" resolved "https://registry.npmjs.org/@algolia/autocomplete-shared/-/autocomplete-shared-1.19.2.tgz" integrity sha512-jEazxZTVD2nLrC+wYlVHQgpBoBB5KPStrJxLzsIFl6Kqd1AlG9sIAGl39V5tECLpIQzB3Qa2T6ZPJ1ChkwMK/w== +"@algolia/autocomplete-shared@1.19.8": + version "1.19.8" + resolved "https://registry.yarnpkg.com/@algolia/autocomplete-shared/-/autocomplete-shared-1.19.8.tgz#5d723d8bdb448efbb1b0e1c7ff94cc18e5b1dc0e" + integrity sha512-h5hf2t8ejF6vlOgvLaZzQbWs5SyH2z4PAWygNAvvD/2RI29hdQ54ldUGwqVuj9Srs+n8XUKTPUqb7fvhBhQrnQ== + "@algolia/client-abtesting@5.46.1": version "5.46.1" resolved "https://registry.npmjs.org/@algolia/client-abtesting/-/client-abtesting-5.46.1.tgz" @@ -1055,13 +1040,6 @@ "@babel/plugin-transform-modules-commonjs" "^7.27.1" "@babel/plugin-transform-typescript" "^7.28.5" -"@babel/runtime-corejs3@^7.25.9": - version "7.28.4" - resolved "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.28.4.tgz" - integrity sha512-h7iEYiW4HebClDEhtvFObtPmIvrd1SSfpI9EhOeKk4CtIK/ngBWFpuhCzhdmRKtg71ylcue+9I6dv54XYO1epQ== - dependencies: - core-js-pure "^3.43.0" - "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.3", "@babel/runtime@^7.12.13", "@babel/runtime@^7.12.5", "@babel/runtime@^7.25.9": version "7.28.4" resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.4.tgz" @@ -1523,34 +1501,29 @@ resolved "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz" integrity sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw== -"@docsearch/core@4.3.1": - version "4.3.1" - resolved "https://registry.npmjs.org/@docsearch/core/-/core-4.3.1.tgz" - integrity sha512-ktVbkePE+2h9RwqCUMbWXOoebFyDOxHqImAqfs+lC8yOU+XwEW4jgvHGJK079deTeHtdhUNj0PXHSnhJINvHzQ== +"@docsearch/core@4.6.2": + version "4.6.2" + resolved "https://registry.yarnpkg.com/@docsearch/core/-/core-4.6.2.tgz#0a6fdc13b1eb12153cb19316f911479b67f7bd58" + integrity sha512-/S0e6Dj7Zcm8m9Rru49YEX49dhU11be68c+S/BCyN8zQsTTgkKzXlhRbVL5mV6lOLC2+ZRRryaTdcm070Ug2oA== -"@docsearch/css@4.3.2": - version "4.3.2" - resolved "https://registry.npmjs.org/@docsearch/css/-/css-4.3.2.tgz" - integrity sha512-K3Yhay9MgkBjJJ0WEL5MxnACModX9xuNt3UlQQkDEDZJZ0+aeWKtOkxHNndMRkMBnHdYvQjxkm6mdlneOtU1IQ== +"@docsearch/css@4.6.2": + version "4.6.2" + resolved "https://registry.yarnpkg.com/@docsearch/css/-/css-4.6.2.tgz#986776619dccbf798176c75e858cc22f5e710bb4" + integrity sha512-fH/cn8BjEEdM2nJdjNMHIvOVYupG6AIDtFVDgIZrNzdCSj4KXr9kd+hsehqsNGYjpUjObeKYKvgy/IwCb1jZYQ== -"@docsearch/react@^3.9.0 || ^4.1.0": - version "4.3.2" - resolved "https://registry.npmjs.org/@docsearch/react/-/react-4.3.2.tgz" - integrity sha512-74SFD6WluwvgsOPqifYOviEEVwDxslxfhakTlra+JviaNcs7KK/rjsPj89kVEoQc9FUxRkAofaJnHIR7pb4TSQ== +"@docsearch/react@^3.9.0 || ^4.3.2": + version "4.6.2" + resolved "https://registry.yarnpkg.com/@docsearch/react/-/react-4.6.2.tgz#e6c65fb87fb943eefaa936debe6d31bb51b25056" + integrity sha512-/BbtGFtqVOGwZx0dw/UfhN/0/DmMQYnulY4iv0tPRhC2JCXv0ka/+izwt3Jzo1ZxXS/2eMvv9zHsBJOK1I9f/w== dependencies: - "@ai-sdk/react" "^2.0.30" "@algolia/autocomplete-core" "1.19.2" - "@docsearch/core" "4.3.1" - "@docsearch/css" "4.3.2" - ai "^5.0.30" - algoliasearch "^5.28.0" - marked "^16.3.0" - zod "^4.1.8" - -"@docusaurus/babel@3.9.2": - version "3.9.2" - resolved "https://registry.npmjs.org/@docusaurus/babel/-/babel-3.9.2.tgz" - integrity sha512-GEANdi/SgER+L7Japs25YiGil/AUDnFFHaCGPBbundxoWtCkA2lmy7/tFmgED4y1htAy6Oi4wkJEQdGssnw9MA== + "@docsearch/core" "4.6.2" + "@docsearch/css" "4.6.2" + +"@docusaurus/babel@3.10.0": + version "3.10.0" + resolved "https://registry.npmjs.org/@docusaurus/babel/-/babel-3.10.0.tgz" + integrity sha512-mqCJhCZNZUDg0zgDEaPTM4DnRsisa24HdqTy/qn/MQlbwhTb4WVaZg6ZyX6yIVKqTz8fS1hBMgM+98z+BeJJDg== dependencies: "@babel/core" "^7.25.9" "@babel/generator" "^7.25.9" @@ -1560,25 +1533,24 @@ "@babel/preset-react" "^7.25.9" "@babel/preset-typescript" "^7.25.9" "@babel/runtime" "^7.25.9" - "@babel/runtime-corejs3" "^7.25.9" "@babel/traverse" "^7.25.9" - "@docusaurus/logger" "3.9.2" - "@docusaurus/utils" "3.9.2" + "@docusaurus/logger" "3.10.0" + "@docusaurus/utils" "3.10.0" babel-plugin-dynamic-import-node "^2.3.3" fs-extra "^11.1.1" tslib "^2.6.0" -"@docusaurus/bundler@3.9.2": - version "3.9.2" - resolved "https://registry.npmjs.org/@docusaurus/bundler/-/bundler-3.9.2.tgz" - integrity sha512-ZOVi6GYgTcsZcUzjblpzk3wH1Fya2VNpd5jtHoCCFcJlMQ1EYXZetfAnRHLcyiFeBABaI1ltTYbOBtH/gahGVA== +"@docusaurus/bundler@3.10.0": + version "3.10.0" + resolved "https://registry.npmjs.org/@docusaurus/bundler/-/bundler-3.10.0.tgz" + integrity sha512-iONUGZGgp+lAkw/cJZH6irONcF4p8+278IsdRlq8lYhxGjkoNUs0w7F4gVXBYSNChq5KG5/JleTSsdJySShxow== dependencies: "@babel/core" "^7.25.9" - "@docusaurus/babel" "3.9.2" - "@docusaurus/cssnano-preset" "3.9.2" - "@docusaurus/logger" "3.9.2" - "@docusaurus/types" "3.9.2" - "@docusaurus/utils" "3.9.2" + "@docusaurus/babel" "3.10.0" + "@docusaurus/cssnano-preset" "3.10.0" + "@docusaurus/logger" "3.10.0" + "@docusaurus/types" "3.10.0" + "@docusaurus/utils" "3.10.0" babel-loader "^9.2.1" clean-css "^5.3.3" copy-webpack-plugin "^11.0.0" @@ -1598,18 +1570,18 @@ webpack "^5.95.0" webpackbar "^6.0.1" -"@docusaurus/core@3.9.2": - version "3.9.2" - resolved "https://registry.npmjs.org/@docusaurus/core/-/core-3.9.2.tgz" - integrity sha512-HbjwKeC+pHUFBfLMNzuSjqFE/58+rLVKmOU3lxQrpsxLBOGosYco/Q0GduBb0/jEMRiyEqjNT/01rRdOMWq5pw== - dependencies: - "@docusaurus/babel" "3.9.2" - "@docusaurus/bundler" "3.9.2" - "@docusaurus/logger" "3.9.2" - "@docusaurus/mdx-loader" "3.9.2" - "@docusaurus/utils" "3.9.2" - "@docusaurus/utils-common" "3.9.2" - "@docusaurus/utils-validation" "3.9.2" +"@docusaurus/core@3.10.0": + version "3.10.0" + resolved "https://registry.npmjs.org/@docusaurus/core/-/core-3.10.0.tgz" + integrity sha512-mgLdQsO8xppnQZc3LPi+Mf+PkPeyxJeIx11AXAq/14fsaMefInQiMEZUUmrc7J+956G/f7MwE7tn8KZgi3iRcA== + dependencies: + "@docusaurus/babel" "3.10.0" + "@docusaurus/bundler" "3.10.0" + "@docusaurus/logger" "3.10.0" + "@docusaurus/mdx-loader" "3.10.0" + "@docusaurus/utils" "3.10.0" + "@docusaurus/utils-common" "3.10.0" + "@docusaurus/utils-validation" "3.10.0" boxen "^6.2.1" chalk "^4.1.2" chokidar "^3.5.3" @@ -1621,7 +1593,7 @@ escape-html "^1.0.3" eta "^2.2.0" eval "^0.1.8" - execa "5.1.1" + execa "^5.1.1" fs-extra "^11.1.1" html-tags "^3.3.1" html-webpack-plugin "^5.6.0" @@ -1632,12 +1604,12 @@ prompts "^2.4.2" react-helmet-async "npm:@slorber/react-helmet-async@1.3.0" react-loadable "npm:@docusaurus/react-loadable@6.0.0" - react-loadable-ssr-addon-v5-slorber "^1.0.1" + react-loadable-ssr-addon-v5-slorber "^1.0.3" react-router "^5.3.4" react-router-config "^5.1.1" react-router-dom "^5.3.4" semver "^7.5.4" - serve-handler "^6.1.6" + serve-handler "^6.1.7" tinypool "^1.0.2" tslib "^2.6.0" update-notifier "^6.0.2" @@ -1646,32 +1618,32 @@ webpack-dev-server "^5.2.2" webpack-merge "^6.0.1" -"@docusaurus/cssnano-preset@3.9.2": - version "3.9.2" - resolved "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-3.9.2.tgz" - integrity sha512-8gBKup94aGttRduABsj7bpPFTX7kbwu+xh3K9NMCF5K4bWBqTFYW+REKHF6iBVDHRJ4grZdIPbvkiHd/XNKRMQ== +"@docusaurus/cssnano-preset@3.10.0": + version "3.10.0" + resolved "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-3.10.0.tgz" + integrity sha512-qzSshTO1DB3TYW+dPUal5KHM7XPc5YQfzF3Kdb2NDACJUyGbNcFtw3tGkCJlYwhNCRKbZcmwraKUS1i5dcHdGg== dependencies: cssnano-preset-advanced "^6.1.2" postcss "^8.5.4" postcss-sort-media-queries "^5.2.0" tslib "^2.6.0" -"@docusaurus/logger@3.9.2": - version "3.9.2" - resolved "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.9.2.tgz" - integrity sha512-/SVCc57ByARzGSU60c50rMyQlBuMIJCjcsJlkphxY6B0GV4UH3tcA1994N8fFfbJ9kX3jIBe/xg3XP5qBtGDbA== +"@docusaurus/logger@3.10.0": + version "3.10.0" + resolved "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.10.0.tgz" + integrity sha512-9jrZzFuBH1LDRlZ7cznAhCLmAZ3HSDqgwdrSSZdGHq9SPUOQgXXu8mnxe2ZRB9NS1PCpMTIOVUqDtZPIhMafZg== dependencies: chalk "^4.1.2" tslib "^2.6.0" -"@docusaurus/mdx-loader@3.9.2": - version "3.9.2" - resolved "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-3.9.2.tgz" - integrity sha512-wiYoGwF9gdd6rev62xDU8AAM8JuLI/hlwOtCzMmYcspEkzecKrP8J8X+KpYnTlACBUUtXNJpSoCwFWJhLRevzQ== +"@docusaurus/mdx-loader@3.10.0": + version "3.10.0" + resolved "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-3.10.0.tgz" + integrity sha512-mQQV97080AH4PYNs087l202NMDqRopZA4mg5W76ZZyTFrmWhJ3mHg+8A+drJVENxw5/Q+wHMHLgsx+9z1nEs0A== dependencies: - "@docusaurus/logger" "3.9.2" - "@docusaurus/utils" "3.9.2" - "@docusaurus/utils-validation" "3.9.2" + "@docusaurus/logger" "3.10.0" + "@docusaurus/utils" "3.10.0" + "@docusaurus/utils-validation" "3.10.0" "@mdx-js/mdx" "^3.0.0" "@slorber/remark-comment" "^1.0.0" escape-html "^1.0.3" @@ -1694,12 +1666,12 @@ vfile "^6.0.1" webpack "^5.88.1" -"@docusaurus/module-type-aliases@3.9.2": - version "3.9.2" - resolved "https://registry.npmjs.org/@docusaurus/module-type-aliases/-/module-type-aliases-3.9.2.tgz" - integrity sha512-8qVe2QA9hVLzvnxP46ysuofJUIc/yYQ82tvA/rBTrnpXtCjNSFLxEZfd5U8cYZuJIVlkPxamsIgwd5tGZXfvew== +"@docusaurus/module-type-aliases@3.10.0": + version "3.10.0" + resolved "https://registry.npmjs.org/@docusaurus/module-type-aliases/-/module-type-aliases-3.10.0.tgz" + integrity sha512-/1O0Zg8w3DFrYX/I6Fbss7OJrtZw1QoyjDhegiFNHVi9A9Y0gQ3jUAytVxF6ywpAWpLyLxch8nN8H/V3XfzdJQ== dependencies: - "@docusaurus/types" "3.9.2" + "@docusaurus/types" "3.10.0" "@types/history" "^4.7.11" "@types/react" "*" "@types/react-router-config" "*" @@ -1707,20 +1679,21 @@ react-helmet-async "npm:@slorber/react-helmet-async@1.3.0" react-loadable "npm:@docusaurus/react-loadable@6.0.0" -"@docusaurus/plugin-content-blog@3.9.2": - version "3.9.2" - resolved "https://registry.npmjs.org/@docusaurus/plugin-content-blog/-/plugin-content-blog-3.9.2.tgz" - integrity sha512-3I2HXy3L1QcjLJLGAoTvoBnpOwa6DPUa3Q0dMK19UTY9mhPkKQg/DYhAGTiBUKcTR0f08iw7kLPqOhIgdV3eVQ== - dependencies: - "@docusaurus/core" "3.9.2" - "@docusaurus/logger" "3.9.2" - "@docusaurus/mdx-loader" "3.9.2" - "@docusaurus/theme-common" "3.9.2" - "@docusaurus/types" "3.9.2" - "@docusaurus/utils" "3.9.2" - "@docusaurus/utils-common" "3.9.2" - "@docusaurus/utils-validation" "3.9.2" +"@docusaurus/plugin-content-blog@3.10.0": + version "3.10.0" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-blog/-/plugin-content-blog-3.10.0.tgz#10095291b637440847854ecb2c8afcd8746debd7" + integrity sha512-RuTz68DhB7CL96QO5UsFbciD7GPYq6QV+YMfF9V0+N4ZgLhJIBgpVAr8GobrKF6NRe5cyWWETU5z5T834piG9g== + dependencies: + "@docusaurus/core" "3.10.0" + "@docusaurus/logger" "3.10.0" + "@docusaurus/mdx-loader" "3.10.0" + "@docusaurus/theme-common" "3.10.0" + "@docusaurus/types" "3.10.0" + "@docusaurus/utils" "3.10.0" + "@docusaurus/utils-common" "3.10.0" + "@docusaurus/utils-validation" "3.10.0" cheerio "1.0.0-rc.12" + combine-promises "^1.1.0" feed "^4.2.2" fs-extra "^11.1.1" lodash "^4.17.21" @@ -1731,20 +1704,20 @@ utility-types "^3.10.0" webpack "^5.88.1" -"@docusaurus/plugin-content-docs@3.9.2": - version "3.9.2" - resolved "https://registry.npmjs.org/@docusaurus/plugin-content-docs/-/plugin-content-docs-3.9.2.tgz" - integrity sha512-C5wZsGuKTY8jEYsqdxhhFOe1ZDjH0uIYJ9T/jebHwkyxqnr4wW0jTkB72OMqNjsoQRcb0JN3PcSeTwFlVgzCZg== - dependencies: - "@docusaurus/core" "3.9.2" - "@docusaurus/logger" "3.9.2" - "@docusaurus/mdx-loader" "3.9.2" - "@docusaurus/module-type-aliases" "3.9.2" - "@docusaurus/theme-common" "3.9.2" - "@docusaurus/types" "3.9.2" - "@docusaurus/utils" "3.9.2" - "@docusaurus/utils-common" "3.9.2" - "@docusaurus/utils-validation" "3.9.2" +"@docusaurus/plugin-content-docs@3.10.0": + version "3.10.0" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-docs/-/plugin-content-docs-3.10.0.tgz#9c4ea1d5a405340f28c281d2e4586c695a7c65a5" + integrity sha512-9BjHhf15ct8Z7TThTC0xRndKDVvMKmVsAGAN7W9FpNRzfMdScOGcXtLmcCWtJGvAezjOJIm6CxOYCy3Io5+RnQ== + dependencies: + "@docusaurus/core" "3.10.0" + "@docusaurus/logger" "3.10.0" + "@docusaurus/mdx-loader" "3.10.0" + "@docusaurus/module-type-aliases" "3.10.0" + "@docusaurus/theme-common" "3.10.0" + "@docusaurus/types" "3.10.0" + "@docusaurus/utils" "3.10.0" + "@docusaurus/utils-common" "3.10.0" + "@docusaurus/utils-validation" "3.10.0" "@types/react-router-config" "^5.0.7" combine-promises "^1.1.0" fs-extra "^11.1.1" @@ -1755,144 +1728,145 @@ utility-types "^3.10.0" webpack "^5.88.1" -"@docusaurus/plugin-content-pages@3.9.2": - version "3.9.2" - resolved "https://registry.npmjs.org/@docusaurus/plugin-content-pages/-/plugin-content-pages-3.9.2.tgz" - integrity sha512-s4849w/p4noXUrGpPUF0BPqIAfdAe76BLaRGAGKZ1gTDNiGxGcpsLcwJ9OTi1/V8A+AzvsmI9pkjie2zjIQZKA== - dependencies: - "@docusaurus/core" "3.9.2" - "@docusaurus/mdx-loader" "3.9.2" - "@docusaurus/types" "3.9.2" - "@docusaurus/utils" "3.9.2" - "@docusaurus/utils-validation" "3.9.2" +"@docusaurus/plugin-content-pages@3.10.0": + version "3.10.0" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-pages/-/plugin-content-pages-3.10.0.tgz#7670cbb3c849f434949f542bfdfded1580a13165" + integrity sha512-5amX8kEJI+nIGtuLVjYk59Y5utEJ3CHETFOPEE4cooIRLA4xM4iBsA6zFgu4ljcopeYwvBzFEWf5g2I6Yb9SkA== + dependencies: + "@docusaurus/core" "3.10.0" + "@docusaurus/mdx-loader" "3.10.0" + "@docusaurus/types" "3.10.0" + "@docusaurus/utils" "3.10.0" + "@docusaurus/utils-validation" "3.10.0" fs-extra "^11.1.1" tslib "^2.6.0" webpack "^5.88.1" -"@docusaurus/plugin-css-cascade-layers@3.9.2": - version "3.9.2" - resolved "https://registry.npmjs.org/@docusaurus/plugin-css-cascade-layers/-/plugin-css-cascade-layers-3.9.2.tgz" - integrity sha512-w1s3+Ss+eOQbscGM4cfIFBlVg/QKxyYgj26k5AnakuHkKxH6004ZtuLe5awMBotIYF2bbGDoDhpgQ4r/kcj4rQ== +"@docusaurus/plugin-css-cascade-layers@3.10.0": + version "3.10.0" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-css-cascade-layers/-/plugin-css-cascade-layers-3.10.0.tgz#71e318d842be95f92be6c3dca00ceea4971d0edb" + integrity sha512-6q1vtt5FJcg5osgkHeM1euErECNqEZ5Z1j69yiNx2luEBIso+nxCkS9nqj8w+MK5X7rvKEToGhFfOFWncs51pQ== dependencies: - "@docusaurus/core" "3.9.2" - "@docusaurus/types" "3.9.2" - "@docusaurus/utils" "3.9.2" - "@docusaurus/utils-validation" "3.9.2" + "@docusaurus/core" "3.10.0" + "@docusaurus/types" "3.10.0" + "@docusaurus/utils" "3.10.0" + "@docusaurus/utils-validation" "3.10.0" tslib "^2.6.0" -"@docusaurus/plugin-debug@3.9.2": - version "3.9.2" - resolved "https://registry.npmjs.org/@docusaurus/plugin-debug/-/plugin-debug-3.9.2.tgz" - integrity sha512-j7a5hWuAFxyQAkilZwhsQ/b3T7FfHZ+0dub6j/GxKNFJp2h9qk/P1Bp7vrGASnvA9KNQBBL1ZXTe7jlh4VdPdA== +"@docusaurus/plugin-debug@3.10.0": + version "3.10.0" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-debug/-/plugin-debug-3.10.0.tgz#e77f924604e1e09d5d90fe0bdf23a3be8ea3307e" + integrity sha512-XcljKN+G+nmmK69uQA1d9BlYU3ZftG3T3zpK8/7Hf/wrOlV7TA4Ampdrdwkg0jElKdKAoSnPhCO0/U3bQGsVQQ== dependencies: - "@docusaurus/core" "3.9.2" - "@docusaurus/types" "3.9.2" - "@docusaurus/utils" "3.9.2" + "@docusaurus/core" "3.10.0" + "@docusaurus/types" "3.10.0" + "@docusaurus/utils" "3.10.0" fs-extra "^11.1.1" react-json-view-lite "^2.3.0" tslib "^2.6.0" -"@docusaurus/plugin-google-analytics@3.9.2": - version "3.9.2" - resolved "https://registry.npmjs.org/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-3.9.2.tgz" - integrity sha512-mAwwQJ1Us9jL/lVjXtErXto4p4/iaLlweC54yDUK1a97WfkC6Z2k5/769JsFgwOwOP+n5mUQGACXOEQ0XDuVUw== +"@docusaurus/plugin-google-analytics@3.10.0": + version "3.10.0" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-3.10.0.tgz#22c7e976fe4d970c7cd1c73c9723d9a5786c6e37" + integrity sha512-hTEoodatpBZnUat5nFExbuTGA1lhWGy7vZGuTew5Q3QDtGKFpSJLYmZJhdTjvCFwv1+qQ67hgAVlKdJOB8TXow== dependencies: - "@docusaurus/core" "3.9.2" - "@docusaurus/types" "3.9.2" - "@docusaurus/utils-validation" "3.9.2" + "@docusaurus/core" "3.10.0" + "@docusaurus/types" "3.10.0" + "@docusaurus/utils-validation" "3.10.0" tslib "^2.6.0" -"@docusaurus/plugin-google-gtag@3.9.2": - version "3.9.2" - resolved "https://registry.npmjs.org/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-3.9.2.tgz" - integrity sha512-YJ4lDCphabBtw19ooSlc1MnxtYGpjFV9rEdzjLsUnBCeis2djUyCozZaFhCg6NGEwOn7HDDyMh0yzcdRpnuIvA== +"@docusaurus/plugin-google-gtag@3.10.0": + version "3.10.0" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-3.10.0.tgz#c38a2ba638257851cc845b934506b80c08d47f96" + integrity sha512-iB/Zzjv/eelJRbdULZqzWCbgMgJ7ht4ONVjXtN3+BI/muil6S87gQ1OJyPwlXD+ELdKkitC7bWv5eJdYOZLhrQ== dependencies: - "@docusaurus/core" "3.9.2" - "@docusaurus/types" "3.9.2" - "@docusaurus/utils-validation" "3.9.2" - "@types/gtag.js" "^0.0.12" + "@docusaurus/core" "3.10.0" + "@docusaurus/types" "3.10.0" + "@docusaurus/utils-validation" "3.10.0" + "@types/gtag.js" "^0.0.20" tslib "^2.6.0" -"@docusaurus/plugin-google-tag-manager@3.9.2": - version "3.9.2" - resolved "https://registry.npmjs.org/@docusaurus/plugin-google-tag-manager/-/plugin-google-tag-manager-3.9.2.tgz" - integrity sha512-LJtIrkZN/tuHD8NqDAW1Tnw0ekOwRTfobWPsdO15YxcicBo2ykKF0/D6n0vVBfd3srwr9Z6rzrIWYrMzBGrvNw== +"@docusaurus/plugin-google-tag-manager@3.10.0": + version "3.10.0" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-google-tag-manager/-/plugin-google-tag-manager-3.10.0.tgz#5469c923cc1ad4608399d0b17e5fcacd8e030d56" + integrity sha512-FEjZxqKgLHa+Wez/EgKxRwvArNCWIScfyEQD95rot7jkxp6nonjI5XIbGfO/iYhM5Qinwe8aIEQHP2KZtpqVuA== dependencies: - "@docusaurus/core" "3.9.2" - "@docusaurus/types" "3.9.2" - "@docusaurus/utils-validation" "3.9.2" + "@docusaurus/core" "3.10.0" + "@docusaurus/types" "3.10.0" + "@docusaurus/utils-validation" "3.10.0" tslib "^2.6.0" -"@docusaurus/plugin-sitemap@3.9.2": - version "3.9.2" - resolved "https://registry.npmjs.org/@docusaurus/plugin-sitemap/-/plugin-sitemap-3.9.2.tgz" - integrity sha512-WLh7ymgDXjG8oPoM/T4/zUP7KcSuFYRZAUTl8vR6VzYkfc18GBM4xLhcT+AKOwun6kBivYKUJf+vlqYJkm+RHw== - dependencies: - "@docusaurus/core" "3.9.2" - "@docusaurus/logger" "3.9.2" - "@docusaurus/types" "3.9.2" - "@docusaurus/utils" "3.9.2" - "@docusaurus/utils-common" "3.9.2" - "@docusaurus/utils-validation" "3.9.2" +"@docusaurus/plugin-sitemap@3.10.0": + version "3.10.0" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-sitemap/-/plugin-sitemap-3.10.0.tgz#35d59d46803f279f22aa64fc1bd18c048f12662b" + integrity sha512-DVTSLjB97hIjmayGnGcBfognCeI7ZuUKgEnU7Oz81JYqXtVg94mVTthDjq3QHTylYNeCUbkaW8VF0FDLcc8pPw== + dependencies: + "@docusaurus/core" "3.10.0" + "@docusaurus/logger" "3.10.0" + "@docusaurus/types" "3.10.0" + "@docusaurus/utils" "3.10.0" + "@docusaurus/utils-common" "3.10.0" + "@docusaurus/utils-validation" "3.10.0" fs-extra "^11.1.1" sitemap "^7.1.1" tslib "^2.6.0" -"@docusaurus/plugin-svgr@3.9.2": - version "3.9.2" - resolved "https://registry.npmjs.org/@docusaurus/plugin-svgr/-/plugin-svgr-3.9.2.tgz" - integrity sha512-n+1DE+5b3Lnf27TgVU5jM1d4x5tUh2oW5LTsBxJX4PsAPV0JGcmI6p3yLYtEY0LRVEIJh+8RsdQmRE66wSV8mw== +"@docusaurus/plugin-svgr@3.10.0": + version "3.10.0" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-svgr/-/plugin-svgr-3.10.0.tgz#8ada2e6dd8318d20206a9b044fc091a5794ba3f0" + integrity sha512-lNljBESaETZqVBMPqkrGchr+UPT1eZzEPLmJhz8I76BxbjqgsUnRvrq6lQJ9sYjgmgX52KB7kkgczqd2yzoswQ== dependencies: - "@docusaurus/core" "3.9.2" - "@docusaurus/types" "3.9.2" - "@docusaurus/utils" "3.9.2" - "@docusaurus/utils-validation" "3.9.2" + "@docusaurus/core" "3.10.0" + "@docusaurus/types" "3.10.0" + "@docusaurus/utils" "3.10.0" + "@docusaurus/utils-validation" "3.10.0" "@svgr/core" "8.1.0" "@svgr/webpack" "^8.1.0" tslib "^2.6.0" webpack "^5.88.1" -"@docusaurus/preset-classic@3.9.2": - version "3.9.2" - resolved "https://registry.npmjs.org/@docusaurus/preset-classic/-/preset-classic-3.9.2.tgz" - integrity sha512-IgyYO2Gvaigi21LuDIe+nvmN/dfGXAiMcV/murFqcpjnZc7jxFAxW+9LEjdPt61uZLxG4ByW/oUmX/DDK9t/8w== - dependencies: - "@docusaurus/core" "3.9.2" - "@docusaurus/plugin-content-blog" "3.9.2" - "@docusaurus/plugin-content-docs" "3.9.2" - "@docusaurus/plugin-content-pages" "3.9.2" - "@docusaurus/plugin-css-cascade-layers" "3.9.2" - "@docusaurus/plugin-debug" "3.9.2" - "@docusaurus/plugin-google-analytics" "3.9.2" - "@docusaurus/plugin-google-gtag" "3.9.2" - "@docusaurus/plugin-google-tag-manager" "3.9.2" - "@docusaurus/plugin-sitemap" "3.9.2" - "@docusaurus/plugin-svgr" "3.9.2" - "@docusaurus/theme-classic" "3.9.2" - "@docusaurus/theme-common" "3.9.2" - "@docusaurus/theme-search-algolia" "3.9.2" - "@docusaurus/types" "3.9.2" - -"@docusaurus/theme-classic@3.9.2": - version "3.9.2" - resolved "https://registry.npmjs.org/@docusaurus/theme-classic/-/theme-classic-3.9.2.tgz" - integrity sha512-IGUsArG5hhekXd7RDb11v94ycpJpFdJPkLnt10fFQWOVxAtq5/D7hT6lzc2fhyQKaaCE62qVajOMKL7OiAFAIA== - dependencies: - "@docusaurus/core" "3.9.2" - "@docusaurus/logger" "3.9.2" - "@docusaurus/mdx-loader" "3.9.2" - "@docusaurus/module-type-aliases" "3.9.2" - "@docusaurus/plugin-content-blog" "3.9.2" - "@docusaurus/plugin-content-docs" "3.9.2" - "@docusaurus/plugin-content-pages" "3.9.2" - "@docusaurus/theme-common" "3.9.2" - "@docusaurus/theme-translations" "3.9.2" - "@docusaurus/types" "3.9.2" - "@docusaurus/utils" "3.9.2" - "@docusaurus/utils-common" "3.9.2" - "@docusaurus/utils-validation" "3.9.2" +"@docusaurus/preset-classic@3.10.0": + version "3.10.0" + resolved "https://registry.yarnpkg.com/@docusaurus/preset-classic/-/preset-classic-3.10.0.tgz#74b6facdaf568bcd41ec90cae9aebb7ca0ac8619" + integrity sha512-kw/Ye02Hc6xP1OdTswy8yxQEHg0fdPpyWAQRxr5b2x3h7LlG2Zgbb5BDFROnXDDMpUxB7YejlocJIE5HIEfpNA== + dependencies: + "@docusaurus/core" "3.10.0" + "@docusaurus/plugin-content-blog" "3.10.0" + "@docusaurus/plugin-content-docs" "3.10.0" + "@docusaurus/plugin-content-pages" "3.10.0" + "@docusaurus/plugin-css-cascade-layers" "3.10.0" + "@docusaurus/plugin-debug" "3.10.0" + "@docusaurus/plugin-google-analytics" "3.10.0" + "@docusaurus/plugin-google-gtag" "3.10.0" + "@docusaurus/plugin-google-tag-manager" "3.10.0" + "@docusaurus/plugin-sitemap" "3.10.0" + "@docusaurus/plugin-svgr" "3.10.0" + "@docusaurus/theme-classic" "3.10.0" + "@docusaurus/theme-common" "3.10.0" + "@docusaurus/theme-search-algolia" "3.10.0" + "@docusaurus/types" "3.10.0" + +"@docusaurus/theme-classic@3.10.0": + version "3.10.0" + resolved "https://registry.yarnpkg.com/@docusaurus/theme-classic/-/theme-classic-3.10.0.tgz#d937915c691189f27ced649c822994d839ea565b" + integrity sha512-9msCAsRdN+UG+RwPwCFb0uKy4tGoPh5YfBozXeGUtIeAgsMdn6f3G/oY861luZ3t8S2ET8S9Y/1GnpJAGWytww== + dependencies: + "@docusaurus/core" "3.10.0" + "@docusaurus/logger" "3.10.0" + "@docusaurus/mdx-loader" "3.10.0" + "@docusaurus/module-type-aliases" "3.10.0" + "@docusaurus/plugin-content-blog" "3.10.0" + "@docusaurus/plugin-content-docs" "3.10.0" + "@docusaurus/plugin-content-pages" "3.10.0" + "@docusaurus/theme-common" "3.10.0" + "@docusaurus/theme-translations" "3.10.0" + "@docusaurus/types" "3.10.0" + "@docusaurus/utils" "3.10.0" + "@docusaurus/utils-common" "3.10.0" + "@docusaurus/utils-validation" "3.10.0" "@mdx-js/react" "^3.0.0" clsx "^2.0.0" + copy-text-to-clipboard "^3.2.0" infima "0.2.0-alpha.45" lodash "^4.17.21" nprogress "^0.2.0" @@ -1904,15 +1878,15 @@ tslib "^2.6.0" utility-types "^3.10.0" -"@docusaurus/theme-common@3.9.2": - version "3.9.2" - resolved "https://registry.npmjs.org/@docusaurus/theme-common/-/theme-common-3.9.2.tgz" - integrity sha512-6c4DAbR6n6nPbnZhY2V3tzpnKnGL+6aOsLvFL26VRqhlczli9eWG0VDUNoCQEPnGwDMhPS42UhSAnz5pThm5Ag== +"@docusaurus/theme-common@3.10.0": + version "3.10.0" + resolved "https://registry.npmjs.org/@docusaurus/theme-common/-/theme-common-3.10.0.tgz" + integrity sha512-Dkp1YXKn16ByCJAdIjbDIOpVb4Z66MsVD694/ilX1vAAHaVEMrVsf/NPd9VgreyFx08rJ9GqV1MtzsbTcU73Kg== dependencies: - "@docusaurus/mdx-loader" "3.9.2" - "@docusaurus/module-type-aliases" "3.9.2" - "@docusaurus/utils" "3.9.2" - "@docusaurus/utils-common" "3.9.2" + "@docusaurus/mdx-loader" "3.10.0" + "@docusaurus/module-type-aliases" "3.10.0" + "@docusaurus/utils" "3.10.0" + "@docusaurus/utils-common" "3.10.0" "@types/history" "^4.7.11" "@types/react" "*" "@types/react-router-config" "*" @@ -1922,32 +1896,33 @@ tslib "^2.6.0" utility-types "^3.10.0" -"@docusaurus/theme-mermaid@^3.9.2": - version "3.9.2" - resolved "https://registry.npmjs.org/@docusaurus/theme-mermaid/-/theme-mermaid-3.9.2.tgz" - integrity sha512-5vhShRDq/ntLzdInsQkTdoKWSzw8d1jB17sNPYhA/KvYYFXfuVEGHLM6nrf8MFbV8TruAHDG21Fn3W4lO8GaDw== - dependencies: - "@docusaurus/core" "3.9.2" - "@docusaurus/module-type-aliases" "3.9.2" - "@docusaurus/theme-common" "3.9.2" - "@docusaurus/types" "3.9.2" - "@docusaurus/utils-validation" "3.9.2" +"@docusaurus/theme-mermaid@^3.10.0": + version "3.10.0" + resolved "https://registry.npmjs.org/@docusaurus/theme-mermaid/-/theme-mermaid-3.10.0.tgz" + integrity sha512-Y2xrlwhIJ80oOZIO3PXL6A7J869splfcMI87E3NKpYsy3zJxOyV+BP1QMtGi59ajKgU868HPuyyn6J+6BZGOBg== + dependencies: + "@docusaurus/core" "3.10.0" + "@docusaurus/module-type-aliases" "3.10.0" + "@docusaurus/theme-common" "3.10.0" + "@docusaurus/types" "3.10.0" + "@docusaurus/utils-validation" "3.10.0" mermaid ">=11.6.0" tslib "^2.6.0" -"@docusaurus/theme-search-algolia@3.9.2": - version "3.9.2" - resolved "https://registry.npmjs.org/@docusaurus/theme-search-algolia/-/theme-search-algolia-3.9.2.tgz" - integrity sha512-GBDSFNwjnh5/LdkxCKQHkgO2pIMX1447BxYUBG2wBiajS21uj64a+gH/qlbQjDLxmGrbrllBrtJkUHxIsiwRnw== - dependencies: - "@docsearch/react" "^3.9.0 || ^4.1.0" - "@docusaurus/core" "3.9.2" - "@docusaurus/logger" "3.9.2" - "@docusaurus/plugin-content-docs" "3.9.2" - "@docusaurus/theme-common" "3.9.2" - "@docusaurus/theme-translations" "3.9.2" - "@docusaurus/utils" "3.9.2" - "@docusaurus/utils-validation" "3.9.2" +"@docusaurus/theme-search-algolia@3.10.0": + version "3.10.0" + resolved "https://registry.yarnpkg.com/@docusaurus/theme-search-algolia/-/theme-search-algolia-3.10.0.tgz#0ff57fe58db6abde8f5ad2877e459cd2fa6e7464" + integrity sha512-f5FPKI08e3JRG63vR/o4qeuUVHUHzFzM0nnF+AkB67soAZgNsKJRf2qmUZvlQkGwlV+QFkKe4D0ANMh1jToU3g== + dependencies: + "@algolia/autocomplete-core" "^1.19.2" + "@docsearch/react" "^3.9.0 || ^4.3.2" + "@docusaurus/core" "3.10.0" + "@docusaurus/logger" "3.10.0" + "@docusaurus/plugin-content-docs" "3.10.0" + "@docusaurus/theme-common" "3.10.0" + "@docusaurus/theme-translations" "3.10.0" + "@docusaurus/utils" "3.10.0" + "@docusaurus/utils-validation" "3.10.0" algoliasearch "^5.37.0" algoliasearch-helper "^3.26.0" clsx "^2.0.0" @@ -1957,23 +1932,23 @@ tslib "^2.6.0" utility-types "^3.10.0" -"@docusaurus/theme-translations@3.9.2": - version "3.9.2" - resolved "https://registry.npmjs.org/@docusaurus/theme-translations/-/theme-translations-3.9.2.tgz" - integrity sha512-vIryvpP18ON9T9rjgMRFLr2xJVDpw1rtagEGf8Ccce4CkTrvM/fRB8N2nyWYOW5u3DdjkwKw5fBa+3tbn9P4PA== +"@docusaurus/theme-translations@3.10.0": + version "3.10.0" + resolved "https://registry.yarnpkg.com/@docusaurus/theme-translations/-/theme-translations-3.10.0.tgz#8fdc23d29bd7f907db49c36cf65e2123d96be300" + integrity sha512-L9IbFLwTc5+XdgH45iQYufLn0SVZd6BUNelDbKIFlH+E4hhjuj/XHWAFMX/w2K59rfy8wak9McOaei7BSUfRPA== dependencies: fs-extra "^11.1.1" tslib "^2.6.0" -"@docusaurus/tsconfig@3.9.2": - version "3.9.2" - resolved "https://registry.npmjs.org/@docusaurus/tsconfig/-/tsconfig-3.9.2.tgz" - integrity sha512-j6/Fp4Rlpxsc632cnRnl5HpOWeb6ZKssDj6/XzzAzVGXXfm9Eptx3rxCC+fDzySn9fHTS+CWJjPineCR1bB5WQ== +"@docusaurus/tsconfig@3.10.0": + version "3.10.0" + resolved "https://registry.yarnpkg.com/@docusaurus/tsconfig/-/tsconfig-3.10.0.tgz#f40a57248828f0503a5f355cf30aa59941c9baaa" + integrity sha512-TXdC3WXuPrdQAexLvjUJfnYf3YKEgEqAs5nK0Q88pRBCW7t7oN4ILvWYb3A5Z1wlSXyXGWW/mCUmLEhdWsjnDQ== -"@docusaurus/types@3.9.2": - version "3.9.2" - resolved "https://registry.npmjs.org/@docusaurus/types/-/types-3.9.2.tgz" - integrity sha512-Ux1JUNswg+EfUEmajJjyhIohKceitY/yzjRUpu04WXgvVz+fbhVC0p+R0JhvEu4ytw8zIAys2hrdpQPBHRIa8Q== +"@docusaurus/types@3.10.0": + version "3.10.0" + resolved "https://registry.npmjs.org/@docusaurus/types/-/types-3.10.0.tgz" + integrity sha512-F0dOt3FOoO20rRaFK7whGFQZ3ggyrWEdQc/c8/UiRuzhtg4y1w9FspXH5zpCT07uMnJKBPGh+qNazbNlCQqvSw== dependencies: "@mdx-js/mdx" "^3.0.0" "@types/history" "^4.7.11" @@ -1986,38 +1961,38 @@ webpack "^5.95.0" webpack-merge "^5.9.0" -"@docusaurus/utils-common@3.9.2": - version "3.9.2" - resolved "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.9.2.tgz" - integrity sha512-I53UC1QctruA6SWLvbjbhCpAw7+X7PePoe5pYcwTOEXD/PxeP8LnECAhTHHwWCblyUX5bMi4QLRkxvyZ+IT8Aw== +"@docusaurus/utils-common@3.10.0": + version "3.10.0" + resolved "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.10.0.tgz" + integrity sha512-JyL7sb9QVDgYvudIS81Dv0lsWm7le0vGZSDwsztxWam1SPBqrnkvBy9UYL/amh6pbybkyYTd3CMTkO24oMlCSw== dependencies: - "@docusaurus/types" "3.9.2" + "@docusaurus/types" "3.10.0" tslib "^2.6.0" -"@docusaurus/utils-validation@3.9.2": - version "3.9.2" - resolved "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.9.2.tgz" - integrity sha512-l7yk3X5VnNmATbwijJkexdhulNsQaNDwoagiwujXoxFbWLcxHQqNQ+c/IAlzrfMMOfa/8xSBZ7KEKDesE/2J7A== +"@docusaurus/utils-validation@3.10.0": + version "3.10.0" + resolved "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.10.0.tgz" + integrity sha512-c+6n2+ZPOJtWWc8Bb/EYdpSDfjYEScdCu9fB/SNjOmSCf1IdVnGf2T53o0tsz0gDRtCL90tifTL0JE/oMuP1Mw== dependencies: - "@docusaurus/logger" "3.9.2" - "@docusaurus/utils" "3.9.2" - "@docusaurus/utils-common" "3.9.2" + "@docusaurus/logger" "3.10.0" + "@docusaurus/utils" "3.10.0" + "@docusaurus/utils-common" "3.10.0" fs-extra "^11.2.0" joi "^17.9.2" js-yaml "^4.1.0" lodash "^4.17.21" tslib "^2.6.0" -"@docusaurus/utils@3.9.2": - version "3.9.2" - resolved "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.9.2.tgz" - integrity sha512-lBSBiRruFurFKXr5Hbsl2thmGweAPmddhF3jb99U4EMDA5L+e5Y1rAkOS07Nvrup7HUMBDrCV45meaxZnt28nQ== +"@docusaurus/utils@3.10.0": + version "3.10.0" + resolved "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.10.0.tgz" + integrity sha512-T3B0WTigsIthe0D4LQa2k+7bJY+c3WS+Wq2JhcznOSpn1lSN64yNtHQXboCj3QnUs1EuAZszQG1SHKu5w5ZrlA== dependencies: - "@docusaurus/logger" "3.9.2" - "@docusaurus/types" "3.9.2" - "@docusaurus/utils-common" "3.9.2" + "@docusaurus/logger" "3.10.0" + "@docusaurus/types" "3.10.0" + "@docusaurus/utils-common" "3.10.0" escape-string-regexp "^4.0.0" - execa "5.1.1" + execa "^5.1.1" file-loader "^6.2.0" fs-extra "^11.1.1" github-slugger "^1.5.0" @@ -2238,11 +2213,6 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" -"@opentelemetry/api@1.9.0": - version "1.9.0" - resolved "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.0.tgz" - integrity sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg== - "@pnpm/config.env-replace@^1.1.0": version "1.1.0" resolved "https://registry.npmjs.org/@pnpm/config.env-replace/-/config.env-replace-1.1.0.tgz" @@ -2310,11 +2280,6 @@ micromark-util-character "^1.1.0" micromark-util-symbol "^1.0.1" -"@standard-schema/spec@^1.0.0": - version "1.1.0" - resolved "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz" - integrity sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w== - "@svgr/babel-plugin-add-jsx-attribute@8.0.0": version "8.0.0" resolved "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-8.0.0.tgz" @@ -2728,10 +2693,10 @@ resolved "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.16.tgz" integrity sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg== -"@types/gtag.js@^0.0.12": - version "0.0.12" - resolved "https://registry.npmjs.org/@types/gtag.js/-/gtag.js-0.0.12.tgz" - integrity sha512-YQV9bUsemkzG81Ea295/nF/5GijnD2Af7QhEofh7xu+kvCN6RdodgNwwGWXB5GMI3NoyvQo0odNctoH/qLMIpg== +"@types/gtag.js@^0.0.20": + version "0.0.20" + resolved "https://registry.yarnpkg.com/@types/gtag.js/-/gtag.js-0.0.20.tgz#e47edabb4ed5ecac90a079275958e6c929d7c08a" + integrity sha512-wwAbk3SA2QeU67unN7zPxjEHmPmlXwZXZvQEpbEUQuMCRGgKyE1m6XDuTUA9b6pCGb/GqJmdfMOY5LuDjJSbbg== "@types/hast@^3.0.0": version "3.0.4" @@ -2969,11 +2934,6 @@ resolved "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz" integrity sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g== -"@vercel/oidc@3.0.5": - version "3.0.5" - resolved "https://registry.npmjs.org/@vercel/oidc/-/oidc-3.0.5.tgz" - integrity sha512-fnYhv671l+eTTp48gB4zEsTW/YtRgRPnkI2nT7x6qw5rkI1Lq2hTmQIpHPgyThI0znLK+vX2n9XxKdXZ7BUbbw== - "@webassemblyjs/ast@1.14.1", "@webassemblyjs/ast@^1.14.1": version "1.14.1" resolved "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz" @@ -3148,16 +3108,6 @@ aggregate-error@^3.0.0: clean-stack "^2.0.0" indent-string "^4.0.0" -ai@5.0.116, ai@^5.0.30: - version "5.0.116" - resolved "https://registry.npmjs.org/ai/-/ai-5.0.116.tgz" - integrity sha512-+2hYJ80/NcDWuv9K2/MLP3cTCFgwWHmHlS1tOpFUKKcmLbErAAlE/S2knsKboc3PNAu8pQkDr2N3K/Vle7ENgQ== - dependencies: - "@ai-sdk/gateway" "2.0.23" - "@ai-sdk/provider" "2.0.0" - "@ai-sdk/provider-utils" "3.0.19" - "@opentelemetry/api" "1.9.0" - ajv-formats@^2.1.1: version "2.1.1" resolved "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz" @@ -3204,7 +3154,7 @@ algoliasearch-helper@^3.26.0: dependencies: "@algolia/events" "^4.0.1" -algoliasearch@^5.28.0, algoliasearch@^5.37.0: +algoliasearch@^5.37.0: version "5.46.1" resolved "https://registry.npmjs.org/algoliasearch/-/algoliasearch-5.46.1.tgz" integrity sha512-39ol8Ulqb3MntofkXHlrcXKyU8BU0PXvQrXPBIX6eXj/EO4VT7651mhGVORI2oF8ydya9nFzT3fYDoqme/KL6w== @@ -3362,7 +3312,7 @@ bail@^2.0.0: balanced-match@^4.0.2: version "4.0.4" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-4.0.4.tgz#bfb10662feed8196a2c62e7c68e17720c274179a" + resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz" integrity sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA== baseline-browser-mapping@^2.9.0: @@ -3883,6 +3833,11 @@ cookie@~0.7.1: resolved "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz" integrity sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w== +copy-text-to-clipboard@^3.2.0: + version "3.2.2" + resolved "https://registry.yarnpkg.com/copy-text-to-clipboard/-/copy-text-to-clipboard-3.2.2.tgz#99bc79db3f2d355ec33a08d573aff6804491ddb9" + integrity sha512-T6SqyLd1iLuqPA90J5N4cTalrtovCySh58iiZDGJ6FGznbclKh4UI+FGacQSgFzwKG77W7XT5gwbVEbd9cIH1A== + copy-webpack-plugin@^11.0.0: version "11.0.0" resolved "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-11.0.0.tgz" @@ -3902,11 +3857,6 @@ core-js-compat@^3.43.0: dependencies: browserslist "^4.28.0" -core-js-pure@^3.43.0: - version "3.47.0" - resolved "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.47.0.tgz" - integrity sha512-BcxeDbzUrRnXGYIVAGFtcGQVNpFcUhVjr6W7F8XktvQW2iJP9e66GP6xdKotCRFlrxBvNIBrhwKteRXqMV86Nw== - core-js@^3.31.1: version "3.47.0" resolved "https://registry.npmjs.org/core-js/-/core-js-3.47.0.tgz" @@ -4545,7 +4495,7 @@ depd@~1.1.2: resolved "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz" integrity sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ== -dequal@^2.0.0, dequal@^2.0.3: +dequal@^2.0.0: version "2.0.3" resolved "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz" integrity sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA== @@ -4967,12 +4917,7 @@ events@^3.2.0: resolved "https://registry.npmjs.org/events/-/events-3.3.0.tgz" integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== -eventsource-parser@^3.0.6: - version "3.0.6" - resolved "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-3.0.6.tgz" - integrity sha512-Vo1ab+QXPzZ4tCa8SwIHJFaSzy4R6SHf7BY79rFBDf0idraZWAkYrDjDj8uWaSm3S2TK+hJ7/t1CEmZ7jXw+pg== - -execa@5.1.1: +execa@^5.1.1: version "5.1.1" resolved "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz" integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== @@ -5963,7 +5908,7 @@ is-yarn-global@^0.4.0: isarray@0.0.1: version "0.0.1" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" + resolved "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" integrity sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ== isarray@~1.0.0: @@ -6073,11 +6018,6 @@ json-schema-traverse@^1.0.0: resolved "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz" integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== -json-schema@^0.4.0: - version "0.4.0" - resolved "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz" - integrity sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA== - json5@^2.1.2, json5@^2.2.3: version "2.2.3" resolved "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz" @@ -6266,7 +6206,7 @@ markdown-table@^3.0.0: resolved "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.4.tgz" integrity sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw== -marked@^16.2.1, marked@^16.3.0: +marked@^16.2.1: version "16.4.2" resolved "https://registry.npmjs.org/marked/-/marked-16.4.2.tgz" integrity sha512-TI3V8YYWvkVf3KJe1dRkpnjs68JUPyEa5vjKrp1XEEJUAOaQc+Qj+L1qWbPd0SJuAdQkFU0h73sXXqwDYxsiDA== @@ -7060,7 +7000,7 @@ minimalistic-assert@^1.0.0: resolved "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz" integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== -minimatch@10.2.5, minimatch@3.1.2, minimatch@^9.0.3: +minimatch@10.2.5, minimatch@3.1.5, minimatch@^9.0.3: version "10.2.5" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-10.2.5.tgz#bd48687a0be38ed2961399105600f832095861d1" integrity sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg== @@ -7433,7 +7373,7 @@ path-parse@^1.0.7: path-to-regexp@3.3.0: version "3.3.0" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-3.3.0.tgz#f7f31d32e8518c2660862b644414b6d5c63a611b" + resolved "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-3.3.0.tgz" integrity sha512-qyCH421YQPS2WFDxDjftfc1ZR5WKQzVzqsp4n9M2kQhVOo/ByahFoUNJfl58kOcEGfQ//7weFTDhm+ss8Ecxgw== path-to-regexp@8.4.2: @@ -7443,14 +7383,14 @@ path-to-regexp@8.4.2: path-to-regexp@^1.7.0: version "1.9.0" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.9.0.tgz#5dc0753acbf8521ca2e0f137b4578b917b10cf24" + resolved "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.9.0.tgz" integrity sha512-xIp7/apCFJuUHdDLWe8O1HIkb0kQrOMb/0u6FXQjemHn/ii5LrIzU6bdECnsiTF/GjZkMEKg1xdiZwNqDYlZ6g== dependencies: isarray "0.0.1" path-to-regexp@~0.1.12: version "0.1.13" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.13.tgz#9b22ec16bc3ab88d05a0c7e369869421401ab17d" + resolved "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.13.tgz" integrity sha512-A/AGNMFN3c8bOlvV9RreMdrv7jsmF9XIfDeCd87+I8RNg6s78BhJxMu69NEMHBSJFxKidViTEdruRwEk/WIKqA== path-type@^4.0.0: @@ -8222,10 +8162,10 @@ react-json-view-lite@^2.3.0: resolved "https://registry.npmjs.org/react-json-view-lite/-/react-json-view-lite-2.5.0.tgz" integrity sha512-tk7o7QG9oYyELWHL8xiMQ8x4WzjCzbWNyig3uexmkLb54r8jO0yH3WCWx8UZS0c49eSA4QUmG5caiRJ8fAn58g== -react-loadable-ssr-addon-v5-slorber@^1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/react-loadable-ssr-addon-v5-slorber/-/react-loadable-ssr-addon-v5-slorber-1.0.1.tgz" - integrity sha512-lq3Lyw1lGku8zUEJPDxsNm1AfYHBrO9Y1+olAYwpUJ2IGFBskM0DMKok97A6LWUpHm+o7IvQBOWu9MLenp9Z+A== +react-loadable-ssr-addon-v5-slorber@^1.0.3: + version "1.0.3" + resolved "https://registry.npmjs.org/react-loadable-ssr-addon-v5-slorber/-/react-loadable-ssr-addon-v5-slorber-1.0.3.tgz" + integrity sha512-GXfh9VLwB5ERaCsU6RULh7tkemeX15aNh6wuMEBtfdyMa7fFG8TXrhXlx1SoEK2Ty/l6XIkzzYIQmyaWW3JgdQ== dependencies: "@babel/runtime" "^7.10.3" @@ -8724,15 +8664,15 @@ serialize-javascript@7.0.5, serialize-javascript@^6.0.0, serialize-javascript@^6 resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-7.0.5.tgz#c798cc0552ffbb08981914a42a8756e339d0d5b1" integrity sha512-F4LcB0UqUl1zErq+1nYEEzSHJnIwb3AF2XWB94b+afhrekOUijwooAYqFyRbjYkm2PAKBabx6oYv/xDxNi8IBw== -serve-handler@^6.1.6: - version "6.1.6" - resolved "https://registry.npmjs.org/serve-handler/-/serve-handler-6.1.6.tgz" - integrity sha512-x5RL9Y2p5+Sh3D38Fh9i/iQ5ZK+e4xuXRd/pGbM4D13tgo/MGwbttUk8emytcr1YYzBYs+apnUngBDFYfpjPuQ== +serve-handler@^6.1.7: + version "6.1.7" + resolved "https://registry.npmjs.org/serve-handler/-/serve-handler-6.1.7.tgz" + integrity sha512-CinAq1xWb0vR3twAv9evEU8cNWkXCb9kd5ePAHUKJBkOsUpR1wt/CvGdeca7vqumL1U5cSaeVQ6zZMxiJ3yWsg== dependencies: bytes "3.0.0" content-disposition "0.5.2" mime-types "2.1.18" - minimatch "3.1.2" + minimatch "3.1.5" path-is-inside "1.0.2" path-to-regexp "3.3.0" range-parser "1.2.0" @@ -9142,14 +9082,6 @@ svgo@4.0.1, svgo@^3.0.2, svgo@^3.2.0: picocolors "^1.1.1" sax "^1.5.0" -swr@^2.2.5: - version "2.3.8" - resolved "https://registry.npmjs.org/swr/-/swr-2.3.8.tgz" - integrity sha512-gaCPRVoMq8WGDcWj9p4YWzCMPHzE0WNl6W8ADIx9c3JBEIdMkJGMzW+uzXvxHMltwcYACr9jP+32H8/hgwMR7w== - dependencies: - dequal "^2.0.3" - use-sync-external-store "^1.6.0" - tapable@^2.0.0, tapable@^2.2.0, tapable@^2.2.1, tapable@^2.3.0: version "2.3.0" resolved "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz" @@ -9181,11 +9113,6 @@ thingies@^2.5.0: resolved "https://registry.npmjs.org/thingies/-/thingies-2.5.0.tgz" integrity sha512-s+2Bwztg6PhWUD7XMfeYm5qliDdSiZm7M7n8KjTkIsm3l/2lgVRc2/Gx/v+ZX8lT4FMA+i8aQvhcWylldc+ZNw== -throttleit@2.1.0: - version "2.1.0" - resolved "https://registry.npmjs.org/throttleit/-/throttleit-2.1.0.tgz" - integrity sha512-nt6AMGKW1p/70DF/hGBdJB57B8Tspmbp5gfJ8ilhLnt7kkr2ye7hzD6NVG8GGErk2HWF34igrL2CXmNIkzKqKw== - thunky@^1.0.2: version "1.1.0" resolved "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz" @@ -9445,11 +9372,6 @@ url-loader@^4.1.1: mime-types "^2.1.27" schema-utils "^3.0.0" -use-sync-external-store@^1.6.0: - version "1.6.0" - resolved "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz" - integrity sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w== - util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" @@ -9806,11 +9728,6 @@ yocto-queue@^1.0.0: resolved "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.2.2.tgz" integrity sha512-4LCcse/U2MHZ63HAJVE+v71o7yOdIe4cZ70Wpf8D/IyjDKYQLV5GD46B+hSTjJsvV5PztjvHoU580EftxjDZFQ== -zod@^4.1.8: - version "4.2.1" - resolved "https://registry.npmjs.org/zod/-/zod-4.2.1.tgz" - integrity sha512-0wZ1IRqGGhMP76gLqz8EyfBXKk0J2qo2+H3fi4mcUP/KtTocoX08nmIAHl1Z2kJIZbZee8KOpBCSNPRgauucjw== - zwitch@^2.0.0: version "2.0.4" resolved "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz" diff --git a/examples/CloudShop/CloudShop.Tests/CloudShop.Tests.csproj b/examples/CloudShop/CloudShop.Tests/CloudShop.Tests.csproj index 760a9cf209..05ec37f3db 100644 --- a/examples/CloudShop/CloudShop.Tests/CloudShop.Tests.csproj +++ b/examples/CloudShop/CloudShop.Tests/CloudShop.Tests.csproj @@ -22,7 +22,7 @@ - +