@@ -1029,4 +1029,80 @@ public ConfigOrError answer(
10291029
10301030 assertThat (result .errorDetail ).contains ("Maximum recursion depth of 8 exceeded" );
10311031 }
1032+
1033+ @ Test
1034+ public void clientInterceptorSkipsOnSkipFilter () {
1035+ // Setup Config with a matcher that MATCHES, but action is SkipFilter
1036+
1037+ Any skipActionAny = Any .newBuilder ()
1038+ .setTypeUrl ("type.googleapis.com/envoy.extensions.filters.common.matcher.action"
1039+ + ".v3.SkipFilter" )
1040+ .setValue (com .google .protobuf .ByteString .EMPTY )
1041+ .build ();
1042+
1043+ Matcher .OnMatch matchAction = Matcher .OnMatch .newBuilder ()
1044+ .setAction (com .github .xds .core .v3 .TypedExtensionConfig .newBuilder ()
1045+ .setName ("action" )
1046+ .setTypedConfig (skipActionAny )
1047+ .build ())
1048+ .build ();
1049+
1050+ Matcher matcher = Matcher .newBuilder ()
1051+ .setMatcherList (Matcher .MatcherList .newBuilder ()
1052+ .addMatchers (Matcher .MatcherList .FieldMatcher .newBuilder ()
1053+ .setPredicate (Matcher .MatcherList .Predicate .newBuilder ()
1054+ .setSinglePredicate (Matcher .MatcherList .Predicate .SinglePredicate .newBuilder ()
1055+ .setInput (com .github .xds .core .v3 .TypedExtensionConfig .newBuilder ()
1056+ .setName ("request_headers" )
1057+ .setTypedConfig (Any .pack (
1058+ HttpRequestHeaderMatchInput .newBuilder ()
1059+ .setHeaderName ("foo" )
1060+ .build ()))
1061+ .build ())
1062+ .setValueMatch (StringMatcher .newBuilder ().setExact ("bar" ).build ())
1063+ .build ())
1064+ .build ())
1065+ .setOnMatch (matchAction )
1066+ .build ())
1067+ .build ())
1068+ .build ();
1069+
1070+ ExtensionWithMatcher proto = ExtensionWithMatcher .newBuilder ()
1071+ .setExtensionConfig (TypedExtensionConfig .newBuilder ().setName ("composite" ).build ())
1072+ .setXdsMatcher (matcher )
1073+ .build ();
1074+
1075+ ConfigOrError <CompositeFilter .CompositeFilterConfig > result = provider
1076+ .parseFilterConfig (Any .pack (proto ));
1077+
1078+ assertThat (result .errorDetail ).isNull ();
1079+
1080+ CompositeFilter filter = (CompositeFilter ) provider .newInstance ("composite" );
1081+ ClientInterceptor interceptor = filter .buildClientInterceptor (result .config , null ,
1082+ mock (ScheduledExecutorService .class ));
1083+
1084+ Channel next = mock (Channel .class );
1085+ ClientCall nextCall = mock (ClientCall .class );
1086+ when (next .newCall (any (), any ())).thenReturn (nextCall );
1087+
1088+ MethodDescriptor .Marshaller <Void > marshaller = mock (MethodDescriptor .Marshaller .class );
1089+ MethodDescriptor <Void , Void > method = MethodDescriptor .<Void , Void >newBuilder ()
1090+ .setType (MethodDescriptor .MethodType .UNARY )
1091+ .setFullMethodName ("service/method" )
1092+ .setRequestMarshaller (marshaller )
1093+ .setResponseMarshaller (marshaller )
1094+ .build ();
1095+
1096+ ClientCall <Void , Void > call = interceptor .interceptCall (method , CallOptions .DEFAULT , next );
1097+
1098+ Metadata headers = new Metadata ();
1099+ headers .put (Metadata .Key .of ("foo" , Metadata .ASCII_STRING_MARSHALLER ), "bar" ); // This matches
1100+
1101+ call .start (mock (ClientCall .Listener .class ), headers );
1102+
1103+ // Verify it SKIPS (calls next directly, never calls fakeClientInterceptor)
1104+ verify (fakeClientInterceptor , org .mockito .Mockito .never ()).interceptCall (any (), any (), any ());
1105+ verify (next ).newCall (any (), any ());
1106+ verify (nextCall ).start (any (), eq (headers ));
1107+ }
10321108}
0 commit comments