@@ -269,6 +269,7 @@ public void givenInterceptor_whenCallIntercepted_thenExtProcStubUsesSerializingE
269269
270270 proxyCall .start (Mockito .mock (ClientCall .Listener .class ), new Metadata ());
271271
272+ // Verify sidecar call uses same executor as main call
272273 ArgumentCaptor <CallOptions > sidecarOptionsCaptor = ArgumentCaptor .forClass (CallOptions .class );
273274 Mockito .verify (mockSidecarChannel ).newCall (
274275 Mockito .eq (ExternalProcessorGrpc .getProcessMethod ()),
@@ -315,6 +316,7 @@ public void givenGrpcServiceWithTimeout_whenCallIntercepted_thenExtProcStubHasCo
315316
316317 proxyCall .start (Mockito .mock (ClientCall .Listener .class ), new Metadata ());
317318
319+ // Verify sidecar call has correct deadline
318320 ArgumentCaptor <CallOptions > sidecarOptionsCaptor = ArgumentCaptor .forClass (CallOptions .class );
319321 Mockito .verify (mockSidecarChannel ).newCall (
320322 Mockito .eq (ExternalProcessorGrpc .getProcessMethod ()),
@@ -366,6 +368,7 @@ public void givenGrpcServiceWithInitialMetadata_whenCallIntercepted_thenExtProcS
366368
367369 proxyCall .start (Mockito .mock (ClientCall .Listener .class ), new Metadata ());
368370
371+ // Verify sidecar stream started with initial metadata
369372 ArgumentCaptor <Metadata > metadataCaptor = ArgumentCaptor .forClass (Metadata .class );
370373 Mockito .verify (mockSidecarCall ).start (Mockito .any (), metadataCaptor .capture ());
371374
@@ -702,6 +705,7 @@ public void givenExtProcSignaledEndOfStream_whenClientSendsMoreMessages_thenMess
702705
703706 proxyCall .sendMessage ("Too late" );
704707
708+ // Verify sidecar and raw call NOT messaged after EOS
705709 Mockito .verify (mockSidecarCall , Mockito .times (0 )).sendMessage (Mockito .any ());
706710 Mockito .verify (mockRawCall , Mockito .times (0 )).sendMessage (Mockito .any ());
707711 }
@@ -750,6 +754,7 @@ public void givenRequestBodyModeGrpc_whenHalfCloseCalled_thenSignalSentToExtProc
750754 Mockito .verify (mockSidecarCall ).sendMessage (requestCaptor .capture ());
751755 assertThat (requestCaptor .getValue ().getRequestBody ().getEndOfStreamWithoutMessage ()).isTrue ();
752756
757+ // Verify super.halfClose() was deferred
753758 Mockito .verify (mockRawCall , Mockito .never ()).halfClose ();
754759 }
755760
@@ -808,6 +813,7 @@ public void givenDeferredHalfClose_whenExtProcRespondsWithEndOfStream_thenSuperH
808813 .build ();
809814 sidecarListenerCaptor .getValue ().onMessage (resp );
810815
816+ // Verify super.halfClose() called after sidecar EOS
811817 Mockito .verify (mockRawCall ).halfClose ();
812818 }
813819
@@ -976,6 +982,7 @@ public void givenResponseBodyModeGrpc_whenExtProcRespondsWithEndOfStream_thenCli
976982
977983 rawListenerCaptor .getValue ().onClose (Status .OK , new Metadata ());
978984
985+ // Verify app listener NOT closed yet (waiting for sidecar EOS)
979986 Mockito .verify (mockAppListener , Mockito .never ()).onClose (Mockito .any (), Mockito .any ());
980987
981988 ProcessingResponse resp = ProcessingResponse .newBuilder ()
@@ -991,6 +998,7 @@ public void givenResponseBodyModeGrpc_whenExtProcRespondsWithEndOfStream_thenCli
991998 .build ();
992999 sidecarListenerCaptor .getValue ().onMessage (resp );
9931000
1001+ // Verify app listener notified with trailers
9941002 Mockito .verify (mockAppListener ).onClose (Mockito .eq (Status .OK ), Mockito .any ());
9951003 }
9961004
@@ -1037,6 +1045,7 @@ public void givenObservabilityModeTrue_whenExtProcBusy_thenIsReadyReturnsFalse()
10371045
10381046 Mockito .verify (mockSidecarCall ).start (sidecarListenerCaptor .capture (), Mockito .any ());
10391047
1048+ // Simulate sidecar is busy
10401049 Mockito .when (mockSidecarCall .isReady ()).thenReturn (false );
10411050
10421051 assertThat (proxyCall .isReady ()).isFalse ();
@@ -1083,8 +1092,10 @@ public void givenObservabilityModeFalse_whenExtProcBusy_thenIsReadyReturnsTrue()
10831092
10841093 Mockito .verify (mockSidecarCall ).start (sidecarListenerCaptor .capture (), Mockito .any ());
10851094
1095+ // Sidecar is busy
10861096 Mockito .when (mockSidecarCall .isReady ()).thenReturn (false );
10871097
1098+ // Should still be ready because observability_mode is false
10881099 assertThat (proxyCall .isReady ()).isTrue ();
10891100 }
10901101
@@ -1128,9 +1139,11 @@ public void givenRequestDrainActive_whenIsReadyCalled_thenReturnsFalse() throws
11281139
11291140 Mockito .verify (mockSidecarCall ).start (sidecarListenerCaptor .capture (), Mockito .any ());
11301141
1142+ // Send request_drain: true
11311143 ProcessingResponse resp = ProcessingResponse .newBuilder ().setRequestDrain (true ).build ();
11321144 sidecarListenerCaptor .getValue ().onMessage (resp );
11331145
1146+ // isReady() must return false during drain
11341147 assertThat (proxyCall .isReady ()).isFalse ();
11351148 }
11361149
@@ -1177,8 +1190,10 @@ public void givenCongestionInExtProc_whenExtProcBecomesReady_thenTriggersOnReady
11771190
11781191 Mockito .verify (mockSidecarCall ).start (sidecarListenerCaptor .capture (), Mockito .any ());
11791192
1193+ // Trigger sidecar onReady
11801194 sidecarListenerCaptor .getValue ().onReady ();
11811195
1196+ // Verify app listener notified
11821197 Mockito .verify (mockAppListener ).onReady ();
11831198 }
11841199
@@ -1224,11 +1239,14 @@ public void givenDrainingStream_whenExtProcStreamCompletes_thenTriggersOnReady()
12241239
12251240 Mockito .verify (mockSidecarCall ).start (sidecarListenerCaptor .capture (), Mockito .any ());
12261241
1242+ // Enter drain
12271243 sidecarListenerCaptor .getValue ().onMessage (ProcessingResponse .newBuilder ().setRequestDrain (true ).build ());
12281244 assertThat (proxyCall .isReady ()).isFalse ();
12291245
1246+ // Sidecar stream completes
12301247 sidecarListenerCaptor .getValue ().onClose (Status .OK , new Metadata ());
12311248
1249+ // Verify app listener notified to resume flow
12321250 Mockito .verify (mockAppListener ).onReady ();
12331251 assertThat (proxyCall .isReady ()).isTrue ();
12341252 }
@@ -1268,6 +1286,7 @@ public void givenObservabilityModeTrue_whenExtProcBusy_thenAppRequestsAreBuffere
12681286 .thenReturn (mockRawCall );
12691287 Mockito .when (mockRawCall .isReady ()).thenReturn (true );
12701288
1289+ // Sidecar is NOT ready
12711290 Mockito .when (mockSidecarCall .isReady ()).thenReturn (false );
12721291
12731292 CallOptions callOptions = CallOptions .DEFAULT .withExecutor (Executors .newSingleThreadExecutor ());
@@ -1276,6 +1295,7 @@ public void givenObservabilityModeTrue_whenExtProcBusy_thenAppRequestsAreBuffere
12761295
12771296 proxyCall .request (5 );
12781297
1298+ // Verify raw call NOT requested yet
12791299 Mockito .verify (mockRawCall , Mockito .never ()).request (Mockito .anyInt ());
12801300 }
12811301
@@ -1311,6 +1331,7 @@ public void givenObservabilityModeFalse_whenExtProcBusy_thenAppRequestsAreNOTBuf
13111331 Mockito .when (mockNextChannel .newCall (Mockito .any (MethodDescriptor .class ), Mockito .any (CallOptions .class )))
13121332 .thenReturn (mockRawCall );
13131333
1334+ // Sidecar is NOT ready
13141335 Mockito .when (mockSidecarCall .isReady ()).thenReturn (false );
13151336
13161337 CallOptions callOptions = CallOptions .DEFAULT .withExecutor (Executors .newSingleThreadExecutor ());
@@ -1319,6 +1340,7 @@ public void givenObservabilityModeFalse_whenExtProcBusy_thenAppRequestsAreNOTBuf
13191340
13201341 proxyCall .request (5 );
13211342
1343+ // Verify raw call requested immediately because obs_mode is false
13221344 Mockito .verify (mockRawCall ).request (5 );
13231345 }
13241346
@@ -1361,10 +1383,12 @@ public void givenRequestDrainActive_whenAppRequestsMessages_thenRequestsAreBuffe
13611383
13621384 Mockito .verify (mockSidecarCall ).start (sidecarListenerCaptor .capture (), Mockito .any ());
13631385
1386+ // Enter drain
13641387 sidecarListenerCaptor .getValue ().onMessage (ProcessingResponse .newBuilder ().setRequestDrain (true ).build ());
13651388
13661389 proxyCall .request (3 );
13671390
1391+ // Verify raw call NOT requested during drain
13681392 Mockito .verify (mockRawCall , Mockito .never ()).request (Mockito .anyInt ());
13691393 }
13701394
@@ -1401,6 +1425,7 @@ public void givenBufferedRequests_whenExtProcStreamBecomesReady_thenDataPlaneReq
14011425 .thenReturn (mockRawCall );
14021426 Mockito .when (mockRawCall .isReady ()).thenReturn (true );
14031427
1428+ // Start with sidecar NOT ready
14041429 Mockito .when (mockSidecarCall .isReady ()).thenReturn (false );
14051430
14061431 ArgumentCaptor <ClientCall .Listener <ProcessingResponse >> sidecarListenerCaptor = ArgumentCaptor .forClass (ClientCall .Listener .class );
@@ -1412,9 +1437,11 @@ public void givenBufferedRequests_whenExtProcStreamBecomesReady_thenDataPlaneReq
14121437 proxyCall .request (10 );
14131438 Mockito .verify (mockRawCall , Mockito .never ()).request (Mockito .anyInt ());
14141439
1440+ // Sidecar becomes ready
14151441 Mockito .when (mockSidecarCall .isReady ()).thenReturn (true );
14161442 sidecarListenerCaptor .getValue ().onReady ();
14171443
1444+ // Verify buffered request drained
14181445 Mockito .verify (mockRawCall ).request (10 );
14191446 }
14201447
@@ -1455,10 +1482,12 @@ public void givenExtProcStreamCompleted_whenAppRequestsMessages_thenRequestsAreF
14551482 proxyCall .start (Mockito .mock (ClientCall .Listener .class ), new Metadata ());
14561483 Mockito .verify (mockSidecarCall ).start (sidecarListenerCaptor .capture (), Mockito .any ());
14571484
1485+ // Sidecar stream completes
14581486 sidecarListenerCaptor .getValue ().onClose (Status .OK , new Metadata ());
14591487
14601488 proxyCall .request (7 );
14611489
1490+ // Verify requested immediately after sidecar is gone
14621491 Mockito .verify (mockRawCall ).request (7 );
14631492 }
14641493
@@ -1503,8 +1532,10 @@ public void givenFailureModeAllowFalse_whenExtProcStreamFails_thenDataPlaneCallI
15031532 proxyCall .start (Mockito .mock (ClientCall .Listener .class ), new Metadata ());
15041533 Mockito .verify (mockSidecarCall ).start (sidecarListenerCaptor .capture (), Mockito .any ());
15051534
1535+ // Sidecar stream fails
15061536 sidecarListenerCaptor .getValue ().onClose (Status .INTERNAL .withDescription ("Sidecar Error" ), new Metadata ());
15071537
1538+ // Verify raw call cancelled
15081539 Mockito .verify (mockRawCall ).cancel (Mockito .contains ("External processor stream failed" ), Mockito .any ());
15091540 }
15101541
@@ -1547,10 +1578,13 @@ public void givenFailureModeAllowTrue_whenExtProcStreamFails_thenDataPlaneCallFa
15471578 proxyCall .start (Mockito .mock (ClientCall .Listener .class ), new Metadata ());
15481579 Mockito .verify (mockSidecarCall ).start (sidecarListenerCaptor .capture (), Mockito .any ());
15491580
1581+ // Sidecar stream fails
15501582 sidecarListenerCaptor .getValue ().onClose (Status .INTERNAL .withDescription ("Sidecar Error" ), new Metadata ());
15511583
1584+ // Verify raw call NOT cancelled
15521585 Mockito .verify (mockRawCall , Mockito .never ()).cancel (Mockito .any (), Mockito .any ());
15531586
1587+ // Verify raw call started (failed open)
15541588 Mockito .verify (mockRawCall ).start (Mockito .any (), Mockito .any ());
15551589 }
15561590
@@ -1593,6 +1627,7 @@ public void givenImmediateResponse_whenReceived_thenDataPlaneCallIsCancelledWith
15931627 proxyCall .start (mockAppListener , new Metadata ());
15941628 Mockito .verify (mockSidecarCall ).start (sidecarListenerCaptor .capture (), Mockito .any ());
15951629
1630+ // Simulate sidecar sending ImmediateResponse (e.g., Unauthenticated)
15961631 ProcessingResponse resp = ProcessingResponse .newBuilder ()
15971632 .setImmediateResponse (ImmediateResponse .newBuilder ()
15981633 .setGrpcStatus (io .envoyproxy .envoy .service .ext_proc .v3 .GrpcStatus .newBuilder ()
@@ -1602,8 +1637,10 @@ public void givenImmediateResponse_whenReceived_thenDataPlaneCallIsCancelledWith
16021637 .build ();
16031638 sidecarListenerCaptor .getValue ().onMessage (resp );
16041639
1640+ // Verify data plane call cancelled
16051641 Mockito .verify (mockRawCall ).cancel (Mockito .contains ("Rejected by ExtProc" ), Mockito .any ());
16061642
1643+ // Verify app listener notified with the correct status
16071644 Mockito .verify (mockAppListener ).onClose (Mockito .eq (Status .UNAUTHENTICATED ), Mockito .any ());
16081645 }
16091646
@@ -1647,6 +1684,7 @@ public void givenUnsupportedCompressionInResponse_whenReceived_thenExtProcStream
16471684 proxyCall .start (Mockito .mock (ClientCall .Listener .class ), new Metadata ());
16481685 Mockito .verify (mockSidecarCall ).start (sidecarListenerCaptor .capture (), Mockito .any ());
16491686
1687+ // Simulate sidecar sending compressed body mutation (unsupported)
16501688 ProcessingResponse resp = ProcessingResponse .newBuilder ()
16511689 .setRequestBody (BodyResponse .newBuilder ()
16521690 .setResponse (CommonResponse .newBuilder ()
@@ -1716,6 +1754,7 @@ public void givenActiveRpc_whenDataPlaneCallCancelled_thenExtProcStreamIsErrored
17161754 ClientCall <String , String > proxyCall = interceptor .interceptCall (METHOD_SAY_HELLO , callOptions , mockNextChannel );
17171755 proxyCall .start (Mockito .mock (ClientCall .Listener .class ), new Metadata ());
17181756
1757+ // Application cancels the RPC
17191758 proxyCall .cancel ("User cancelled" , null );
17201759
17211760 // Verify sidecar stream also cancelled
0 commit comments