|
3 | 3 | using System.Collections.Immutable;
|
4 | 4 | using System.Diagnostics.CodeAnalysis;
|
5 | 5 | using System.Linq;
|
| 6 | +using System.Threading; |
6 | 7 | using System.Threading.Tasks;
|
7 | 8 | using AutoFixture;
|
8 | 9 | using FluentAssertions;
|
9 | 10 | using NSubstitute;
|
10 | 11 | using NSubstitute.ExceptionExtensions;
|
11 | 12 | using OpenFeature.Constant;
|
| 13 | +using OpenFeature.Error; |
12 | 14 | using OpenFeature.Model;
|
13 | 15 | using OpenFeature.Tests.Internal;
|
14 | 16 | using Xunit;
|
@@ -554,6 +556,71 @@ public async Task When_Error_Occurs_In_After_Hook_Should_Invoke_Error_Hook()
|
554 | 556 | await featureProvider.DidNotReceive().ResolveBooleanValueAsync("test", false, Arg.Any<EvaluationContext>());
|
555 | 557 | }
|
556 | 558 |
|
| 559 | + [Fact] |
| 560 | + public async Task Successful_Resolution_Should_Pass_Cancellation_Token() |
| 561 | + { |
| 562 | + var featureProvider = Substitute.For<FeatureProvider>(); |
| 563 | + var hook = Substitute.For<Hook>(); |
| 564 | + var cts = new CancellationTokenSource(); |
| 565 | + |
| 566 | + featureProvider.GetMetadata().Returns(new Metadata(null)); |
| 567 | + featureProvider.GetProviderHooks().Returns(ImmutableList<Hook>.Empty); |
| 568 | + |
| 569 | + hook.BeforeAsync(Arg.Any<HookContext<bool>>(), Arg.Any<Dictionary<string, object>>(), cts.Token).Returns(EvaluationContext.Empty); |
| 570 | + featureProvider.ResolveBooleanValueAsync(Arg.Any<string>(), Arg.Any<bool>(), Arg.Any<EvaluationContext>(), cts.Token).Returns(new ResolutionDetails<bool>("test", false)); |
| 571 | + _ = hook.AfterAsync(Arg.Any<HookContext<bool>>(), Arg.Any<FlagEvaluationDetails<bool>>(), Arg.Any<Dictionary<string, object>>(), cts.Token); |
| 572 | + _ = hook.FinallyAsync(Arg.Any<HookContext<bool>>(), Arg.Any<Dictionary<string, object>>(), cts.Token); |
| 573 | + |
| 574 | + await Api.Instance.SetProviderAsync(featureProvider); |
| 575 | + var client = Api.Instance.GetClient(); |
| 576 | + client.AddHooks(hook); |
| 577 | + |
| 578 | + await client.GetBooleanValueAsync("test", false, EvaluationContext.Empty, null, cts.Token); |
| 579 | + |
| 580 | + _ = hook.Received(1).BeforeAsync(Arg.Any<HookContext<bool>>(), Arg.Any<Dictionary<string, object>>(), cts.Token); |
| 581 | + _ = hook.Received(1).AfterAsync(Arg.Any<HookContext<bool>>(), Arg.Any<FlagEvaluationDetails<bool>>(), Arg.Any<Dictionary<string, object>>(), cts.Token); |
| 582 | + _ = hook.Received(1).FinallyAsync(Arg.Any<HookContext<bool>>(), Arg.Any<Dictionary<string, object>>(), cts.Token); |
| 583 | + } |
| 584 | + |
| 585 | + [Fact] |
| 586 | + public async Task Failed_Resolution_Should_Pass_Cancellation_Token() |
| 587 | + { |
| 588 | + var featureProvider = Substitute.For<FeatureProvider>(); |
| 589 | + var hook = Substitute.For<Hook>(); |
| 590 | + var flagOptions = new FlagEvaluationOptions(hook); |
| 591 | + var exceptionToThrow = new GeneralException("Fake Exception"); |
| 592 | + var cts = new CancellationTokenSource(); |
| 593 | + |
| 594 | + featureProvider.GetMetadata() |
| 595 | + .Returns(new Metadata(null)); |
| 596 | + |
| 597 | + featureProvider.GetProviderHooks() |
| 598 | + .Returns(ImmutableList<Hook>.Empty); |
| 599 | + |
| 600 | + hook.BeforeAsync(Arg.Any<HookContext<bool>>(), Arg.Any<ImmutableDictionary<string, object>>()) |
| 601 | + .Returns(EvaluationContext.Empty); |
| 602 | + |
| 603 | + featureProvider.ResolveBooleanValueAsync(Arg.Any<string>(), Arg.Any<bool>(), Arg.Any<EvaluationContext>()) |
| 604 | + .Throws(exceptionToThrow); |
| 605 | + |
| 606 | + hook.ErrorAsync(Arg.Any<HookContext<bool>>(), Arg.Any<Exception>(), Arg.Any<ImmutableDictionary<string, object>>()) |
| 607 | + .Returns(new ValueTask()); |
| 608 | + |
| 609 | + hook.FinallyAsync(Arg.Any<HookContext<bool>>(), Arg.Any<ImmutableDictionary<string, object>>()) |
| 610 | + .Returns(new ValueTask()); |
| 611 | + |
| 612 | + await Api.Instance.SetProviderAsync(featureProvider); |
| 613 | + var client = Api.Instance.GetClient(); |
| 614 | + |
| 615 | + await client.GetBooleanValueAsync("test", true, EvaluationContext.Empty, flagOptions, cts.Token); |
| 616 | + |
| 617 | + _ = hook.Received(1).BeforeAsync(Arg.Any<HookContext<bool>>(), Arg.Any<ImmutableDictionary<string, object>>(), cts.Token); |
| 618 | + _ = hook.Received(1).ErrorAsync(Arg.Any<HookContext<bool>>(), Arg.Any<Exception>(), Arg.Any<ImmutableDictionary<string, object>>(), cts.Token); |
| 619 | + _ = hook.Received(1).FinallyAsync(Arg.Any<HookContext<bool>>(), Arg.Any<ImmutableDictionary<string, object>>(), cts.Token); |
| 620 | + |
| 621 | + await featureProvider.DidNotReceive().ResolveBooleanValueAsync("test", false, Arg.Any<EvaluationContext>()); |
| 622 | + } |
| 623 | + |
557 | 624 | [Fact]
|
558 | 625 | public void Add_hooks_should_accept_empty_enumerable()
|
559 | 626 | {
|
|
0 commit comments