commit 7121d2323f92333e025adc14ce75a440d1767978 Author: upstream Date: Wed Sep 2 11:43:55 2026 +0200 Upstream App-vNext/Polly state of the touched files before 65d060c90f diff --git a/src/Polly.Core/Simmy/Fault/FaultGenerator.cs b/src/Polly.Core/Simmy/Fault/FaultGenerator.cs new file mode 100644 index 0000000..c5931c0 --- /dev/null +++ b/src/Polly.Core/Simmy/Fault/FaultGenerator.cs @@ -0,0 +1,83 @@ +using System.ComponentModel; +using Polly.Simmy.Utils; + +namespace Polly.Simmy.Fault; + +#pragma warning disable CA2225 // Operator overloads have named alternates +#pragma warning disable RS0026 // Do not add multiple public overloads with optional parameters + +/// +/// A generator for creating faults (exceptions) using registered delegate functions. +/// +/// +/// An instance of this class can be assigned to the property. +/// +public sealed class FaultGenerator +{ + private const int DefaultWeight = 100; + + private readonly GeneratorHelper _helper; + + /// + /// Initializes a new instance of the class. + /// + public FaultGenerator() => _helper = new(RandomUtil.Next); + + /// + /// Registers an exception generator delegate. + /// + /// The delegate that generates the exception. + /// The weight assigned to this generator. Defaults to 100. + /// The current instance of . + public FaultGenerator AddException(Func generator, int weight = DefaultWeight) + { + Guard.NotNull(generator); + + _helper.AddOutcome(_ => Outcome.FromException(generator()), weight); + + return this; + } + + /// + /// Registers an exception generator delegate that accepts a . + /// + /// The delegate that generates the exception, accepting a . + /// The weight assigned to this generator. Defaults to 100. + /// The current instance of . + public FaultGenerator AddException(Func generator, int weight = DefaultWeight) + { + Guard.NotNull(generator); + + _helper.AddOutcome(context => Outcome.FromException(generator(context)), weight); + + return this; + } + + /// + /// Registers an exception generator for a specific exception type, using the default constructor of that exception. + /// + /// The type of the exception to generate. + /// The weight assigned to this generator. Defaults to 100. + /// The current instance of . + public FaultGenerator AddException(int weight = DefaultWeight) + where TException : Exception, new() + { + _helper.AddOutcome(_ => Outcome.FromException(new TException()), weight); + + return this; + } + + /// + /// Provides an implicit conversion from to a delegate compatible with . + /// + /// The instance of . + [EditorBrowsable(EditorBrowsableState.Never)] + public static implicit operator Func>(FaultGenerator generator) + { + Guard.NotNull(generator); + + var generatorDelegate = generator._helper.CreateGenerator(); + + return args => new ValueTask(generatorDelegate(args.Context)!.Value.Exception); + } +} diff --git a/test/Polly.Core.Tests/Simmy/Fault/FaultGeneratorTests.cs b/test/Polly.Core.Tests/Simmy/Fault/FaultGeneratorTests.cs new file mode 100644 index 0000000..1b7e2cc --- /dev/null +++ b/test/Polly.Core.Tests/Simmy/Fault/FaultGeneratorTests.cs @@ -0,0 +1,50 @@ +using Polly.Simmy.Fault; + +namespace Polly.Core.Tests.Simmy.Fault; + +public class FaultGeneratorTests +{ + [Fact] + public void AddException_Generic_Ok() + { + var generator = new FaultGenerator(); + + generator.AddException(); + + Generate(generator).ShouldBeOfType(); + } + + [Fact] + public void AddException_Factory_Ok() + { + var generator = new FaultGenerator(); + + generator.AddException(() => new InvalidOperationException()); + + Generate(generator).ShouldBeOfType(); + } + + [Fact] + public void AddException_FactoryWithResilienceContext_Ok() + { + var generator = new FaultGenerator(); + + generator.AddException(context => + { + context.ShouldNotBeNull(); + + return new InvalidOperationException(); + }); + + Generate(generator).ShouldBeOfType(); + } + + private static Exception? Generate(FaultGenerator generator) + { + Func> func = generator; + + return func( + new FaultGeneratorArguments( + ResilienceContextPool.Shared.Get(TestCancellation.Token))).AsTask().Result; + } +}