@@ -31,39 +31,130 @@ public void ExecuteAsync_EnsureResultNotDisposed()
31
31
}
32
32
33
33
[ Fact ]
34
- public async Task ExecuteAsync_CancellationRequested_EnsureNotRetried ( )
34
+ public async Task ExecuteAsync_CanceledBeforeExecution_EnsureNotExecuted ( )
35
35
{
36
- SetupNoDelay ( ) ;
37
36
var sut = CreateSut ( ) ;
38
- using var cts = new CancellationTokenSource ( ) ;
39
- cts . Cancel ( ) ;
40
- var context = ResilienceContextPool . Shared . Get ( cts . Token ) ;
41
37
var executed = false ;
42
38
43
- var result = await sut . ExecuteOutcomeAsync ( ( _ , _ ) => { executed = true ; return Outcome . FromResultAsValueTask ( "dummy" ) ; } , context , "state" ) ;
44
- result . Exception . ShouldBeOfType < OperationCanceledException > ( ) ;
39
+ var result = await sut . ExecuteOutcomeAsync (
40
+ ( _ , _ ) =>
41
+ {
42
+ executed = true ;
43
+ return Outcome . FromResultAsValueTask ( new object ( ) ) ;
44
+ } ,
45
+ ResilienceContextPool . Shared . Get ( new CancellationToken ( canceled : true ) ) ,
46
+ default ( object ) ) ;
47
+
48
+ result . Exception . ShouldBeAssignableTo < OperationCanceledException > ( ) ;
45
49
executed . ShouldBeFalse ( ) ;
46
50
}
47
51
48
52
[ Fact ]
49
- public async Task ExecuteAsync_CancellationRequestedAfterCallback_EnsureNotRetried ( )
53
+ public async Task ExecuteAsync_CanceledDuringExecution_EnsureResultReturned ( )
50
54
{
51
- using var cts = new CancellationTokenSource ( ) ;
55
+ var sut = CreateSut ( ) ;
56
+ using var cancellation = new CancellationTokenSource ( ) ;
57
+ var executions = 0 ;
58
+
59
+ var result = await sut . ExecuteOutcomeAsync (
60
+ ( _ , _ ) =>
61
+ {
62
+ executions ++ ;
63
+ cancellation . Cancel ( ) ;
64
+ return Outcome . FromResultAsValueTask ( new object ( ) ) ;
65
+ } ,
66
+ ResilienceContextPool . Shared . Get ( cancellation . Token ) ,
67
+ default ( object ) ) ;
68
+
69
+ result . Exception . ShouldBeNull ( ) ;
70
+ executions . ShouldBe ( 1 ) ;
71
+ }
72
+
73
+ [ Fact ]
74
+ public async Task ExecuteAsync_CanceledDuringExecution_EnsureNotExecutedAgain ( )
75
+ {
76
+ var reported = false ;
52
77
53
78
_options . ShouldHandle = _ => PredicateResult . True ( ) ;
54
- _options . OnRetry = _ =>
55
- {
56
- cts . Cancel ( ) ;
57
- return default ;
58
- } ;
79
+ _options . OnRetry =
80
+ args =>
81
+ {
82
+ reported = true ;
83
+ return default ;
84
+ } ;
59
85
60
- var sut = CreateSut ( TimeProvider . System ) ;
61
- var context = ResilienceContextPool . Shared . Get ( cts . Token ) ;
62
- var executed = false ;
86
+ var sut = CreateSut ( ) ;
87
+ using var cancellation = new CancellationTokenSource ( ) ;
88
+ var executions = 0 ;
89
+
90
+ var result = await sut . ExecuteOutcomeAsync (
91
+ ( _ , _ ) =>
92
+ {
93
+ executions ++ ;
94
+ cancellation . Cancel ( ) ;
95
+ return Outcome . FromResultAsValueTask ( new object ( ) ) ;
96
+ } ,
97
+ ResilienceContextPool . Shared . Get ( cancellation . Token ) ,
98
+ default ( object ) ) ;
99
+
100
+ result . Exception . ShouldBeAssignableTo < OperationCanceledException > ( ) ;
101
+ executions . ShouldBe ( 1 ) ;
102
+ reported . ShouldBeTrue ( ) ;
103
+ }
104
+
105
+ [ Fact ]
106
+ public async Task ExecuteAsync_CanceledAfterExecution_EnsureNotExecutedAgain ( )
107
+ {
108
+ using var cancellation = new CancellationTokenSource ( ) ;
109
+
110
+ _options . ShouldHandle = _ => PredicateResult . True ( ) ;
111
+ _options . OnRetry =
112
+ args =>
113
+ {
114
+ cancellation . Cancel ( ) ;
115
+ return default ;
116
+ } ;
117
+
118
+ var sut = CreateSut ( ) ;
119
+ var executions = 0 ;
120
+
121
+ var result = await sut . ExecuteOutcomeAsync (
122
+ ( _ , _ ) =>
123
+ {
124
+ executions ++ ;
125
+ return Outcome . FromResultAsValueTask ( new object ( ) ) ;
126
+ } ,
127
+ ResilienceContextPool . Shared . Get ( cancellation . Token ) ,
128
+ default ( object ) ) ;
129
+
130
+ result . Exception . ShouldBeAssignableTo < OperationCanceledException > ( ) ;
131
+ executions . ShouldBe ( 1 ) ;
132
+ }
133
+
134
+ [ Fact ]
135
+ public async Task ExecuteAsync_CanceledDuringDelay_EnsureNotExecutedAgain ( )
136
+ {
137
+ _options . ShouldHandle = _ => PredicateResult . True ( ) ;
138
+
139
+ using var cancellation = _timeProvider . CreateCancellationTokenSource ( _options . Delay ) ;
140
+
141
+ var sut = CreateSut ( ) ;
142
+ var executions = 0 ;
143
+
144
+ var resultTask = sut . ExecuteOutcomeAsync (
145
+ ( _ , _ ) =>
146
+ {
147
+ executions ++ ;
148
+ return Outcome . FromResultAsValueTask ( new object ( ) ) ;
149
+ } ,
150
+ ResilienceContextPool . Shared . Get ( cancellation . Token ) ,
151
+ default ( object ) ) ;
152
+
153
+ _timeProvider . Advance ( _options . Delay ) ;
154
+ var result = await resultTask ;
63
155
64
- var result = await sut . ExecuteOutcomeAsync ( ( _ , _ ) => { executed = true ; return Outcome . FromResultAsValueTask ( "dummy" ) ; } , context , "state" ) ;
65
- result . Exception . ShouldBeOfType < OperationCanceledException > ( ) ;
66
- executed . ShouldBeTrue ( ) ;
156
+ result . Exception . ShouldBeAssignableTo < OperationCanceledException > ( ) ;
157
+ executions . ShouldBe ( 1 ) ;
67
158
}
68
159
69
160
[ Fact ]
0 commit comments