@@ -38,6 +38,7 @@ class ConcurrencyOperationTest {
3838 private static final TypeToken <Void > RESULT_TYPE = TypeToken .get (Void .class );
3939
4040 private DurableContextImpl durableContext ;
41+ private DurableContextImpl childContext ;
4142 private ExecutionManager executionManager ;
4243 private AtomicInteger operationIdCounter ;
4344 private OperationIdGenerator mockIdGenerator ;
@@ -48,11 +49,20 @@ void setUp() {
4849 executionManager = mock (ExecutionManager .class );
4950 operationIdCounter = new AtomicInteger (0 );
5051
52+ var childContext = mock (DurableContextImpl .class );
53+ this .childContext = childContext ;
54+ when (childContext .getExecutionManager ()).thenReturn (executionManager );
55+ when (childContext .getDurableConfig ())
56+ .thenReturn (DurableConfig .builder ()
57+ .withExecutorService (Executors .newCachedThreadPool ())
58+ .build ());
59+
5160 when (durableContext .getExecutionManager ()).thenReturn (executionManager );
5261 when (durableContext .getDurableConfig ())
5362 .thenReturn (DurableConfig .builder ()
5463 .withExecutorService (Executors .newCachedThreadPool ())
5564 .build ());
65+ when (durableContext .createChildContext (anyString (), anyString ())).thenReturn (childContext );
5666 when (executionManager .getCurrentThreadContext ()).thenReturn (new ThreadContext ("Root" , ThreadType .CONTEXT ));
5767 mockIdGenerator = mock (OperationIdGenerator .class );
5868 when (mockIdGenerator .nextOperationId ()).thenAnswer (inv -> "child-" + operationIdCounter .incrementAndGet ());
@@ -167,6 +177,18 @@ void singleChildAlreadySucceeds_fullCycle() throws Exception {
167177 assertFalse (functionCalled .get (), "Function should not be called during SUCCEEDED replay" );
168178 }
169179
180+ @ Test
181+ void addItem_usesRootChildContextAsParent () throws Exception {
182+ var op = createOperation (-1 , -1 , 0 );
183+
184+ op .addItem ("branch-1" , ctx -> "result" , TypeToken .get (String .class ), SER_DES );
185+
186+ // rootContext is created via durableContext.createChildContext(...) in the constructor,
187+ // so the parentContext passed to createItem must be that child context, not durableContext itself
188+ assertNotSame (durableContext , op .getLastParentContext ());
189+ assertSame (childContext , op .getLastParentContext ());
190+ }
191+
170192 // ===== Helpers =====
171193
172194 private void runJoin (TestConcurrencyOperation op ) throws InterruptedException {
@@ -182,6 +204,7 @@ static class TestConcurrencyOperation extends ConcurrencyOperation<Void> {
182204 private boolean successHandled = false ;
183205 private boolean failureHandled = false ;
184206 private final AtomicInteger executingCount = new AtomicInteger (0 );
207+ private DurableContextImpl lastParentContext ;
185208
186209 TestConcurrencyOperation (
187210 OperationIdentifier operationIdentifier ,
@@ -209,6 +232,7 @@ protected <R> ChildContextOperation<R> createItem(
209232 TypeToken <R > resultType ,
210233 SerDes serDes ,
211234 DurableContextImpl parentContext ) {
235+ lastParentContext = parentContext ;
212236 return new ChildContextOperation <R >(
213237 OperationIdentifier .of (operationId , name , OperationType .CONTEXT , OperationSubType .PARALLEL_BRANCH ),
214238 function ,
@@ -260,5 +284,9 @@ boolean isSuccessHandled() {
260284 boolean isFailureHandled () {
261285 return failureHandled ;
262286 }
287+
288+ DurableContextImpl getLastParentContext () {
289+ return lastParentContext ;
290+ }
263291 }
264292}
0 commit comments