77using System . Threading ;
88using System . Threading . Tasks ;
99using DurableTask . Core ;
10- using DurableTask . Core . Entities ;
1110using DurableTask . Core . Entities . OperationFormat ;
1211using DurableTask . Core . Exceptions ;
1312using DurableTask . Core . History ;
1413using DurableTask . Core . Middleware ;
14+ using Microsoft . Azure . WebJobs . Host ;
1515using Microsoft . Azure . WebJobs . Host . Executors ;
16- using Microsoft . Extensions . Logging ;
1716using Microsoft . Extensions . Logging . Abstractions ;
1817using Microsoft . Extensions . Options ;
1918using Moq ;
@@ -31,13 +30,13 @@ public async Task CallOrchestratorAsync_DifferentInvalidOperationException_DoesN
3130 var innerException = new InvalidOperationException ( "The internal function invoker returned a task that does not support return values!" ) ;
3231 var outerException = new Exception ( "Function invocation failed." , innerException ) ;
3332
34- var ( middleware , dispatchContext ) = this . SetupOrchestratorTest ( outerException ) ;
33+ ( OutOfProcMiddleware middleware , DispatchMiddlewareContext dispatchContext ) = this . SetupOrchestratorTest ( outerException ) ;
3534
3635 // Act: should NOT throw SessionAbortedException — instead the orchestration should be marked as failed
3736 await middleware . CallOrchestratorAsync ( dispatchContext , ( ) => Task . CompletedTask ) ;
3837
3938 // Assert: the middleware should have set a failure result on the dispatch context
40- var result = dispatchContext . GetProperty < OrchestratorExecutionResult > ( ) ;
39+ OrchestratorExecutionResult result = dispatchContext . GetProperty < OrchestratorExecutionResult > ( ) ;
4140 Assert . NotNull ( result ) ;
4241 }
4342
@@ -46,16 +45,43 @@ public async Task CallOrchestratorAsync_DifferentInvalidOperationException_DoesN
4645 [ MemberData ( nameof ( PlatformLevelExceptions ) ) ]
4746 public async Task CallOrchestratorAsync_PlatformLevelException_ThrowsSessionAbortedException ( Exception exception )
4847 {
49- var ( middleware , dispatchContext ) = this . SetupOrchestratorTest ( exception ) ;
48+ ( OutOfProcMiddleware middleware , DispatchMiddlewareContext dispatchContext ) = this . SetupOrchestratorTest ( exception ) ;
5049
5150 await Assert . ThrowsAsync < SessionAbortedException > (
5251 ( ) => middleware . CallOrchestratorAsync ( dispatchContext , ( ) => Task . CompletedTask ) ) ;
52+ }
53+
54+ [ Fact ]
55+ [ Trait ( "Category" , PlatformSpecificHelpers . TestCategory ) ]
56+ public async Task CallEntityAsync_FunctionTimeoutAbortException_ThrowsSessionAbortedException ( )
57+ {
58+ var exception = new FunctionTimeoutAbortException ( "Activity A timed out! Worker channel closing" ) ;
59+
60+ ( OutOfProcMiddleware middleware , DispatchMiddlewareContext dispatchContext ) = this . SetupEntityTest ( exception ) ;
61+
62+ await Assert . ThrowsAsync < SessionAbortedException > (
63+ ( ) => middleware . CallEntityAsync ( dispatchContext , ( ) => Task . CompletedTask ) ) ;
64+ }
65+
66+ [ Fact ]
67+ [ Trait ( "Category" , PlatformSpecificHelpers . TestCategory ) ]
68+ public async Task CallActivityAsync_FunctionTimeoutAbortException_ThrowsSessionAbortedException ( )
69+ {
70+ var exception = new FunctionTimeoutAbortException ( "Activity A timed out! Worker channel closing" ) ;
71+
72+ ( OutOfProcMiddleware middleware , DispatchMiddlewareContext dispatchContext ) = this . SetupActivityTest ( exception ) ;
73+
74+ await Assert . ThrowsAsync < SessionAbortedException > (
75+ ( ) => middleware . CallActivityAsync ( dispatchContext , ( ) => Task . CompletedTask ) ) ;
5376 }
5477
5578 public static IEnumerable < object [ ] > PlatformLevelExceptions ( )
5679 {
5780 // FunctionTimeoutException (top-level)
58- yield return new object [ ] { new Host . FunctionTimeoutException ( "Function timed out." ) } ;
81+ yield return new object [ ] { new Host . FunctionTimeoutException ( "Function timed out." ) } ;
82+
83+ // FunctionTimeoutAbortException (top-level)
84+ yield return new object [ ] { new Host . FunctionTimeoutAbortException ( "Function timed out." ) } ;
5985
6086 // SessionAbortedException as InnerException (e.g. out-of-memory handling)
6187 yield return new object [ ] { new Exception ( "Function invocation failed." , new SessionAbortedException ( "Out of memory" ) ) } ;
@@ -69,24 +95,50 @@ public static IEnumerable<object[]> PlatformLevelExceptions()
6995
7096 private ( OutOfProcMiddleware middleware , DispatchMiddlewareContext context ) SetupOrchestratorTest ( Exception executorException )
7197 {
72- var ( middleware , dispatchContext ) = this . CreateMiddleware ( executorException , "TestOrchestrator" , FunctionType . Orchestrator ) ;
98+ ( OutOfProcMiddleware middleware , DispatchMiddlewareContext dispatchContext )
99+ = this . CreateMiddleware ( executorException , "TestOrchestrator" , FunctionType . Orchestrator ) ;
73100
74101 var orchestrationState = new OrchestrationRuntimeState (
75- new List < HistoryEvent >
76- {
102+ [
77103 new ExecutionStartedEvent ( - 1 , null ) { Name = "TestOrchestrator" } ,
78- } ) ;
104+ ] ) ;
79105
80106 dispatchContext . SetProperty ( orchestrationState ) ;
81107 dispatchContext . SetProperty ( new OrchestrationInstance { InstanceId = "test-instance-id" } ) ;
82108
109+ return ( middleware , dispatchContext ) ;
110+ }
111+
112+ private ( OutOfProcMiddleware middleware , DispatchMiddlewareContext context ) SetupEntityTest ( Exception executorException )
113+ {
114+ ( OutOfProcMiddleware middleware , DispatchMiddlewareContext dispatchContext )
115+ = this . CreateMiddleware ( executorException , "TestEntity" , FunctionType . Entity ) ;
116+
117+ dispatchContext . SetProperty ( new EntityBatchRequest
118+ {
119+ InstanceId = "@TestEntity@test-key" ,
120+ EntityState = null ,
121+ Operations = new List < OperationRequest > ( ) ,
122+ } ) ;
123+
124+ return ( middleware , dispatchContext ) ;
125+ }
126+
127+ private ( OutOfProcMiddleware middleware , DispatchMiddlewareContext context ) SetupActivityTest ( Exception executorException )
128+ {
129+ ( OutOfProcMiddleware middleware , DispatchMiddlewareContext dispatchContext )
130+ = this . CreateMiddleware ( executorException , "TestActivity" , FunctionType . Activity ) ;
131+
132+ dispatchContext . SetProperty ( new TaskScheduledEvent ( - 1 ) { Name = "TestActivity" } ) ;
133+ dispatchContext . SetProperty ( new OrchestrationInstance { InstanceId = "test-instance-id" } ) ;
134+
83135 return ( middleware , dispatchContext ) ;
84136 }
85137
86138 private ( OutOfProcMiddleware middleware , DispatchMiddlewareContext context ) CreateMiddleware (
87139 Exception executorException , string functionName , FunctionType functionType )
88140 {
89- var extension = CreateDurableTaskExtension ( ) ;
141+ DurableTaskExtension extension = CreateDurableTaskExtension ( ) ;
90142
91143 var mockExecutor = new Mock < ITriggeredFunctionExecutor > ( ) ;
92144 mockExecutor
@@ -131,15 +183,14 @@ private static DurableTaskExtension CreateDurableTaskExtension()
131183 new OptionsWrapper < DurableTaskOptions > ( options ) ,
132184 NullLoggerFactory . Instance ,
133185 TestHelpers . GetTestNameResolver ( ) ,
134- new [ ]
135- {
186+ [
136187 new AzureStorageDurabilityProviderFactory (
137188 new OptionsWrapper < DurableTaskOptions > ( options ) ,
138189 new TestStorageServiceClientProviderFactory ( ) ,
139190 TestHelpers . GetTestNameResolver ( ) ,
140191 NullLoggerFactory . Instance ,
141192 TestHelpers . GetMockPlatformInformationService ( ) ) ,
142- } ,
193+ ] ,
143194 new TestHostShutdownNotificationService ( ) ,
144195 new DurableHttpMessageHandlerFactory ( ) ,
145196 platformInformationService : TestHelpers . GetMockPlatformInformationService ( ) ) ;
@@ -148,13 +199,13 @@ private static DurableTaskExtension CreateDurableTaskExtension()
148199 private static WorkItemMetadata CreateWorkItemMetadata ( bool isExtendedSession , bool includeState )
149200 {
150201 // WorkItemMetadata has an internal constructor, so we use reflection to create it.
151- var ctor = typeof ( WorkItemMetadata ) . GetConstructor (
202+ ConstructorInfo ctor = typeof ( WorkItemMetadata ) . GetConstructor (
152203 BindingFlags . Instance | BindingFlags . NonPublic ,
153204 binder : null ,
154- new [ ] { typeof ( bool ) , typeof ( bool ) } ,
205+ [ typeof ( bool ) , typeof ( bool ) ] ,
155206 modifiers : null ) ;
156207 Assert . NotNull ( ctor ) ;
157- return ( WorkItemMetadata ) ctor . Invoke ( new object [ ] { isExtendedSession , includeState } ) ;
208+ return ( WorkItemMetadata ) ctor . Invoke ( [ isExtendedSession , includeState ] ) ;
158209 }
159210
160211 /// <summary>
@@ -163,12 +214,9 @@ private static WorkItemMetadata CreateWorkItemMetadata(bool isExtendedSession, b
163214 /// <c>WorkerProcessExitException</c> lives in <c>Microsoft.Azure.WebJobs.Script</c>
164215 /// (the Functions host runtime), which is too heavy to reference as a test dependency.
165216 /// </summary>
166- private class WorkerProcessExitExceptionStub : Exception
217+ private class WorkerProcessExitExceptionStub ( string message )
218+ : Exception ( message )
167219 {
168- public WorkerProcessExitExceptionStub ( string message )
169- : base ( message )
170- {
171- }
172220 }
173221 }
174222}
0 commit comments