Skip to content

Commit db4d885

Browse files
committed
add some unit tests to increase coverage
1 parent 99aeef1 commit db4d885

File tree

2 files changed

+217
-2
lines changed

2 files changed

+217
-2
lines changed

xds/src/test/java/io/grpc/xds/internal/matcher/CelEnvironmentTest.java

Lines changed: 64 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -248,8 +248,8 @@ public void lazyRequestMap_unknownKey_returnsNull() {
248248
Map<?, ?> map = (Map<?, ?>) env.find("request").get();
249249

250250
assertThat(map.get("unknown")).isNull();
251-
assertThat(map.get(123)).isNull();
252-
assertThat(map.containsKey(123)).isFalse();
251+
assertThat(map.get(new Object())).isNull();
252+
assertThat(map.containsKey(new Object())).isFalse();
253253
}
254254

255255
@Test
@@ -280,4 +280,66 @@ public void celMatcher_match_nonBooleanResult_throws() throws Exception {
280280
assertThat(e).hasMessageThat().contains("must evaluate to boolean");
281281
}
282282
}
283+
284+
@Test
285+
public void headersWrapper_get_nonStringKey_returnsNull() {
286+
MatchContext context = mock(MatchContext.class);
287+
Map<String, String> headers = new HeadersWrapper(context);
288+
assertThat(headers.get(new Object())).isNull();
289+
}
290+
291+
@Test
292+
public void headersWrapper_getHeader_binary_multipleValues() {
293+
MatchContext context = mock(MatchContext.class);
294+
Metadata metadata = new Metadata();
295+
byte[] val1 = new byte[] { 1, 2, 3 };
296+
byte[] val2 = new byte[] { 4, 5, 6 };
297+
Metadata.Key<byte[]> key = Metadata.Key.of("bin-header-bin", Metadata.BINARY_BYTE_MARSHALLER);
298+
metadata.put(key, val1);
299+
metadata.put(key, val2);
300+
when(context.getMetadata()).thenReturn(metadata);
301+
302+
Map<String, String> headers = new HeadersWrapper(context);
303+
String expected = com.google.common.io.BaseEncoding.base64().encode(val1) + ","
304+
+ com.google.common.io.BaseEncoding.base64().encode(val2);
305+
assertThat(headers.get("bin-header-bin")).isEqualTo(expected);
306+
}
307+
308+
@Test
309+
public void headersWrapper_containsKey_nonStringKey_returnsFalse() {
310+
MatchContext context = mock(MatchContext.class);
311+
Map<String, String> headers = new HeadersWrapper(context);
312+
assertThat(headers.containsKey(new Object())).isFalse();
313+
}
314+
315+
@Test
316+
public void headersWrapper_containsKey_pseudoHeader_returnsTrue() {
317+
MatchContext context = mock(MatchContext.class);
318+
when(context.getMetadata()).thenReturn(new Metadata());
319+
Map<String, String> headers = new HeadersWrapper(context);
320+
assertThat(headers.containsKey(":method")).isTrue();
321+
assertThat(headers.containsKey(":path")).isTrue();
322+
assertThat(headers.containsKey(":authority")).isTrue();
323+
}
324+
325+
@Test
326+
public void headersWrapper_keySet_containsExpectedKeys() {
327+
MatchContext context = mock(MatchContext.class);
328+
Metadata metadata = new Metadata();
329+
metadata.put(Metadata.Key.of("custom-key", Metadata.ASCII_STRING_MARSHALLER), "val");
330+
when(context.getMetadata()).thenReturn(metadata);
331+
332+
Map<String, String> headers = new HeadersWrapper(context);
333+
java.util.Set<String> keys = headers.keySet();
334+
335+
assertThat(keys).containsAtLeast("custom-key", ":method", ":path", ":authority");
336+
}
337+
338+
@Test
339+
public void headersWrapper_getHeader_missingBinaryHeader_returnsNull() {
340+
MatchContext context = mock(MatchContext.class);
341+
when(context.getMetadata()).thenReturn(new Metadata());
342+
Map<String, String> headers = new HeadersWrapper(context);
343+
assertThat(headers.get("missing-bin")).isNull();
344+
}
283345
}

xds/src/test/java/io/grpc/xds/internal/matcher/UnifiedMatcherTest.java

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,42 @@ public void celMatcher_throwsIfReturnsString() {
133133
}
134134
}
135135

136+
@Test
137+
public void celMatcher_evaluationError_returnsFalse() {
138+
CelMatcher celMatcher = createCelMatcher("int(request.path) == 0");
139+
Matcher.MatcherList.Predicate.SinglePredicate predicate =
140+
Matcher.MatcherList.Predicate.SinglePredicate.newBuilder()
141+
.setInput(TypedExtensionConfig.newBuilder()
142+
.setTypedConfig(Any.pack(
143+
com.github.xds.type.matcher.v3.HttpAttributesCelMatchInput
144+
.getDefaultInstance())))
145+
.setCustomMatch(TypedExtensionConfig.newBuilder()
146+
.setTypedConfig(Any.pack(celMatcher)))
147+
.build();
148+
Matcher proto = Matcher.newBuilder()
149+
.setMatcherList(Matcher.MatcherList.newBuilder()
150+
.addMatchers(Matcher.MatcherList.FieldMatcher.newBuilder()
151+
.setPredicate(Matcher.MatcherList.Predicate.newBuilder()
152+
.setSinglePredicate(predicate))
153+
.setOnMatch(Matcher.OnMatch.newBuilder()
154+
.setAction(TypedExtensionConfig.newBuilder().setName("matched")))))
155+
.setOnNoMatch(Matcher.OnMatch.newBuilder()
156+
.setAction(TypedExtensionConfig.newBuilder().setName("no-match")))
157+
.build();
158+
159+
UnifiedMatcher matcher = UnifiedMatcher.fromProto(proto);
160+
MatchContext context = mock(MatchContext.class);
161+
when(context.getPath()).thenReturn("not-an-int");
162+
// Ensure metadata access (if any by environment) checks out
163+
when(context.getMetadata()).thenReturn(new Metadata());
164+
when(context.getId()).thenReturn("1");
165+
166+
MatchResult result = matcher.match(context, 0);
167+
// Should return false for match, so it falls through to no-match
168+
assertThat(result.matched).isTrue();
169+
assertThat(result.actions.get(0).getName()).isEqualTo("no-match");
170+
}
171+
136172
@Test
137173
public void celStringExtractor_throwsIfReturnsBool() {
138174
try {
@@ -852,6 +888,123 @@ public void matcherRunner_checkMatch_returnsNullOnNoMatch() {
852888
assertThat(results).isNull();
853889
}
854890

891+
@Test
892+
public void predicate_missingType_throws() {
893+
Matcher.MatcherList.Predicate proto = Matcher.MatcherList.Predicate.getDefaultInstance();
894+
try {
895+
PredicateEvaluator.fromProto(proto);
896+
org.junit.Assert.fail("Should have thrown IllegalArgumentException");
897+
} catch (IllegalArgumentException e) {
898+
assertThat(e).hasMessageThat().contains("Predicate must have one of");
899+
}
900+
}
901+
902+
@Test
903+
public void celMatcher_missingExprMatch_throws() {
904+
com.github.xds.type.matcher.v3.CelMatcher celProto =
905+
com.github.xds.type.matcher.v3.CelMatcher.getDefaultInstance();
906+
Matcher.MatcherList.Predicate proto = Matcher.MatcherList.Predicate.newBuilder()
907+
.setSinglePredicate(Matcher.MatcherList.Predicate.SinglePredicate.newBuilder()
908+
.setInput(TypedExtensionConfig.newBuilder().setTypedConfig(Any.pack(
909+
com.github.xds.type.matcher.v3.HttpAttributesCelMatchInput.getDefaultInstance())))
910+
.setCustomMatch(TypedExtensionConfig.newBuilder().setTypedConfig(Any.pack(celProto))))
911+
.build();
912+
try {
913+
PredicateEvaluator.fromProto(proto);
914+
org.junit.Assert.fail("Should have thrown");
915+
} catch (IllegalArgumentException e) {
916+
assertThat(e).hasMessageThat().contains("CelMatcher must have expr_match");
917+
}
918+
}
919+
920+
@Test
921+
public void singlePredicate_unsupportedCustomMatcher_throws() {
922+
Matcher.MatcherList.Predicate proto = Matcher.MatcherList.Predicate.newBuilder()
923+
.setSinglePredicate(Matcher.MatcherList.Predicate.SinglePredicate.newBuilder()
924+
.setInput(TypedExtensionConfig.newBuilder().setTypedConfig(Any.pack(
925+
com.github.xds.type.matcher.v3.HttpAttributesCelMatchInput.getDefaultInstance())))
926+
.setCustomMatch(TypedExtensionConfig.newBuilder().setTypedConfig(
927+
Any.pack(com.google.protobuf.Empty.getDefaultInstance()))))
928+
.build();
929+
try {
930+
PredicateEvaluator.fromProto(proto);
931+
org.junit.Assert.fail("Should have thrown");
932+
} catch (IllegalArgumentException e) {
933+
assertThat(e).hasMessageThat().contains("Unsupported custom_match matcher");
934+
}
935+
}
936+
937+
@Test
938+
public void singlePredicate_missingInput_throws() {
939+
Matcher.MatcherList.Predicate proto = Matcher.MatcherList.Predicate.newBuilder()
940+
.setSinglePredicate(Matcher.MatcherList.Predicate.SinglePredicate.newBuilder()
941+
.setValueMatch(
942+
com.github.xds.type.matcher.v3.StringMatcher.newBuilder().setExact("foo")))
943+
.build();
944+
try {
945+
PredicateEvaluator.fromProto(proto);
946+
org.junit.Assert.fail("Should have thrown");
947+
} catch (IllegalArgumentException e) {
948+
assertThat(e).hasMessageThat().contains("SinglePredicate must have input");
949+
}
950+
}
951+
952+
@Test
953+
public void singlePredicate_missingMatcher_throws() {
954+
Matcher.MatcherList.Predicate proto = Matcher.MatcherList.Predicate.newBuilder()
955+
.setSinglePredicate(Matcher.MatcherList.Predicate.SinglePredicate.newBuilder()
956+
.setInput(TypedExtensionConfig.newBuilder().setTypedConfig(Any.pack(
957+
com.github.xds.type.matcher.v3.HttpAttributesCelMatchInput.getDefaultInstance()))))
958+
.build();
959+
try {
960+
PredicateEvaluator.fromProto(proto);
961+
org.junit.Assert.fail("Should have thrown");
962+
} catch (IllegalArgumentException e) {
963+
assertThat(e).hasMessageThat().contains(
964+
"SinglePredicate must have either value_match or custom_match");
965+
}
966+
}
967+
968+
@Test
969+
public void orMatcher_tooFewPredicates_throws() {
970+
Matcher.MatcherList.Predicate.PredicateList protoList =
971+
Matcher.MatcherList.Predicate.PredicateList.newBuilder()
972+
.addPredicate(Matcher.MatcherList.Predicate.newBuilder().setSinglePredicate(
973+
Matcher.MatcherList.Predicate.SinglePredicate.newBuilder()
974+
.setInput(TypedExtensionConfig.newBuilder().setName("i"))
975+
.setValueMatch(
976+
com.github.xds.type.matcher.v3.StringMatcher.newBuilder().setExact("v"))))
977+
.build();
978+
Matcher.MatcherList.Predicate proto = Matcher.MatcherList.Predicate.newBuilder()
979+
.setOrMatcher(protoList)
980+
.build();
981+
try {
982+
PredicateEvaluator.fromProto(proto);
983+
org.junit.Assert.fail("Should have thrown");
984+
} catch (IllegalArgumentException e) {
985+
assertThat(e).hasMessageThat().contains("OrMatcher must have at least 2 predicates");
986+
}
987+
}
988+
989+
@Test
990+
public void andMatcher_tooFewPredicates_throws() {
991+
Matcher.MatcherList.Predicate.PredicateList proto =
992+
Matcher.MatcherList.Predicate.PredicateList.newBuilder()
993+
.addPredicate(Matcher.MatcherList.Predicate.newBuilder().setSinglePredicate(
994+
Matcher.MatcherList.Predicate.SinglePredicate.newBuilder()
995+
.setInput(TypedExtensionConfig.newBuilder().setName("i"))
996+
.setValueMatch(
997+
com.github.xds.type.matcher.v3.StringMatcher.newBuilder().setExact("v"))))
998+
.build();
999+
try {
1000+
PredicateEvaluator.fromProto(
1001+
Matcher.MatcherList.Predicate.newBuilder().setAndMatcher(proto).build());
1002+
org.junit.Assert.fail("Should have thrown");
1003+
} catch (IllegalArgumentException e) {
1004+
assertThat(e).hasMessageThat().contains("AndMatcher must have at least 2 predicates");
1005+
}
1006+
}
1007+
8551008
@Test
8561009
public void matcherList_firstMatchWins_evenIfNestedNoMatch() {
8571010
Matcher.MatcherList.Predicate predicate = createHeaderMatchPredicate("path", "/common");

0 commit comments

Comments
 (0)