1 //
2 // Copyright 2021 gRPC authors.
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16
17 #include <grpc/grpc.h>
18
19 #include <memory>
20
21 #include "absl/status/status.h"
22 #include "absl/status/statusor.h"
23 #include "gmock/gmock.h"
24 #include "gtest/gtest.h"
25 #include "src/core/lib/channel/channel_args.h"
26 #include "src/core/service_config/service_config.h"
27 #include "src/core/service_config/service_config_impl.h"
28 #include "src/core/util/ref_counted_ptr.h"
29 #include "test/core/test_util/test_config.h"
30
31 namespace grpc_core {
32 namespace {
33
34 class RlsConfigParsingTest : public ::testing::Test {
35 public:
SetUpTestSuite()36 static void SetUpTestSuite() { grpc_init(); }
37
TearDownTestSuite()38 static void TearDownTestSuite() { grpc_shutdown_blocking(); }
39 };
40
TEST_F(RlsConfigParsingTest,ValidConfig)41 TEST_F(RlsConfigParsingTest, ValidConfig) {
42 const char* service_config_json =
43 "{\n"
44 " \"loadBalancingConfig\":[{\n"
45 " \"rls_experimental\":{\n"
46 " \"routeLookupConfig\":{\n"
47 " \"lookupService\":\"rls.example.com:80\",\n"
48 " \"cacheSizeBytes\":1,\n"
49 " \"grpcKeybuilders\":[\n"
50 " {\n"
51 " \"names\":[\n"
52 " {\"service\":\"foo\"}\n"
53 " ]\n"
54 " }\n"
55 " ]\n"
56 " },\n"
57 " \"routeLookupChannelServiceConfig\": {\n"
58 " \"loadBalancingPolicy\": \"ROUND_ROBIN\"\n"
59 " },\n"
60 " \"childPolicy\":[\n"
61 " {\"unknown\":{}},\n" // Okay, since the next one exists.
62 " {\"grpclb\":{}}\n"
63 " ],\n"
64 " \"childPolicyConfigTargetFieldName\":\"target\"\n"
65 " }\n"
66 " }]\n"
67 "}\n";
68 auto service_config =
69 ServiceConfigImpl::Create(ChannelArgs(), service_config_json);
70 ASSERT_TRUE(service_config.ok()) << service_config.status();
71 EXPECT_NE(*service_config, nullptr);
72 }
73
74 //
75 // top-level fields
76 //
77
TEST_F(RlsConfigParsingTest,TopLevelRequiredFieldsMissing)78 TEST_F(RlsConfigParsingTest, TopLevelRequiredFieldsMissing) {
79 const char* service_config_json =
80 "{\n"
81 " \"loadBalancingConfig\":[{\n"
82 " \"rls_experimental\":{\n"
83 " }\n"
84 " }]\n"
85 "}\n";
86 auto service_config =
87 ServiceConfigImpl::Create(ChannelArgs(), service_config_json);
88 EXPECT_EQ(service_config.status().code(), absl::StatusCode::kInvalidArgument);
89 EXPECT_THAT(
90 service_config.status().message(),
91 ::testing::HasSubstr(
92 "errors validating RLS LB policy config: ["
93 "field:childPolicy error:field not present; "
94 "field:childPolicyConfigTargetFieldName error:field not present; "
95 "field:routeLookupConfig error:field not present]"))
96 << service_config.status();
97 }
98
TEST_F(RlsConfigParsingTest,TopLevelFieldsWrongTypes)99 TEST_F(RlsConfigParsingTest, TopLevelFieldsWrongTypes) {
100 const char* service_config_json =
101 "{\n"
102 " \"loadBalancingConfig\":[{\n"
103 " \"rls_experimental\":{\n"
104 " \"routeLookupConfig\":1,\n"
105 " \"routeLookupChannelServiceConfig\": 1,\n"
106 " \"childPolicy\":1,\n"
107 " \"childPolicyConfigTargetFieldName\":1\n"
108 " }\n"
109 " }]\n"
110 "}\n";
111 auto service_config =
112 ServiceConfigImpl::Create(ChannelArgs(), service_config_json);
113 EXPECT_EQ(service_config.status().code(), absl::StatusCode::kInvalidArgument);
114 EXPECT_EQ(service_config.status().message(),
115 "errors validating service config: ["
116 "field:loadBalancingConfig "
117 "error:errors validating RLS LB policy config: ["
118 "field:childPolicy error:is not an array; "
119 "field:childPolicyConfigTargetFieldName error:is not a string; "
120 "field:routeLookupChannelServiceConfig error:is not an object; "
121 "field:routeLookupConfig error:is not an object]]")
122 << service_config.status();
123 }
124
TEST_F(RlsConfigParsingTest,TopLevelFieldsInvalidValues)125 TEST_F(RlsConfigParsingTest, TopLevelFieldsInvalidValues) {
126 const char* service_config_json =
127 "{\n"
128 " \"loadBalancingConfig\":[{\n"
129 " \"rls_experimental\":{\n"
130 " \"childPolicy\":[\n"
131 " {\"unknown\":{}}\n"
132 " ],\n"
133 " \"childPolicyConfigTargetFieldName\":\"\"\n"
134 " }\n"
135 " }]\n"
136 "}\n";
137 auto service_config =
138 ServiceConfigImpl::Create(ChannelArgs(), service_config_json);
139 EXPECT_EQ(service_config.status().code(), absl::StatusCode::kInvalidArgument);
140 EXPECT_THAT(
141 service_config.status().message(),
142 ::testing::HasSubstr(
143 "errors validating RLS LB policy config: ["
144 "field:childPolicy error:No known policies in list: unknown; "
145 "field:childPolicyConfigTargetFieldName error:must be non-empty; "
146 "field:routeLookupConfig error:field not present]"))
147 << service_config.status();
148 }
149
TEST_F(RlsConfigParsingTest,InvalidChildPolicyConfig)150 TEST_F(RlsConfigParsingTest, InvalidChildPolicyConfig) {
151 const char* service_config_json =
152 "{\n"
153 " \"loadBalancingConfig\":[{\n"
154 " \"rls_experimental\":{\n"
155 " \"childPolicy\":[\n"
156 " {\"grpclb\":{\"childPolicy\":1}}\n"
157 " ],\n"
158 " \"childPolicyConfigTargetFieldName\":\"serviceName\"\n"
159 " }\n"
160 " }]\n"
161 "}\n";
162 auto service_config =
163 ServiceConfigImpl::Create(ChannelArgs(), service_config_json);
164 EXPECT_EQ(service_config.status().code(), absl::StatusCode::kInvalidArgument);
165 EXPECT_THAT(
166 service_config.status().message(),
167 ::testing::HasSubstr("errors validating RLS LB policy config: ["
168 "field:childPolicy error:"
169 "errors validating grpclb LB policy config: ["
170 "field:childPolicy error:type should be array]; "
171 "field:routeLookupConfig error:field not present]"))
172 << service_config.status();
173 }
174
TEST_F(RlsConfigParsingTest,InvalidRlsChannelServiceConfig)175 TEST_F(RlsConfigParsingTest, InvalidRlsChannelServiceConfig) {
176 const char* service_config_json =
177 "{\n"
178 " \"loadBalancingConfig\":[{\n"
179 " \"rls_experimental\":{\n"
180 " \"routeLookupChannelServiceConfig\": {\n"
181 " \"loadBalancingPolicy\": \"unknown\"\n"
182 " },\n"
183 " \"childPolicy\":[\n"
184 " {\"grpclb\":{}}\n"
185 " ],\n"
186 " \"childPolicyConfigTargetFieldName\":\"serviceName\"\n"
187 " }\n"
188 " }]\n"
189 "}\n";
190 auto service_config =
191 ServiceConfigImpl::Create(ChannelArgs(), service_config_json);
192 EXPECT_EQ(service_config.status().code(), absl::StatusCode::kInvalidArgument);
193 EXPECT_EQ(service_config.status().message(),
194 "errors validating service config: ["
195 "field:loadBalancingConfig "
196 "error:errors validating RLS LB policy config: ["
197 "field:routeLookupChannelServiceConfig.loadBalancingPolicy "
198 "error:unknown LB policy \"unknown\"; "
199 "field:routeLookupConfig error:field not present]]")
200 << service_config.status();
201 }
202
203 //
204 // routeLookupConfig fields
205 //
206
TEST_F(RlsConfigParsingTest,RouteLookupConfigRequiredFieldsMissing)207 TEST_F(RlsConfigParsingTest, RouteLookupConfigRequiredFieldsMissing) {
208 const char* service_config_json =
209 "{\n"
210 " \"loadBalancingConfig\":[{\n"
211 " \"rls_experimental\":{\n"
212 " \"routeLookupConfig\":{\n"
213 " }\n"
214 " }\n"
215 " }]\n"
216 "}\n";
217 auto service_config =
218 ServiceConfigImpl::Create(ChannelArgs(), service_config_json);
219 EXPECT_EQ(service_config.status().code(), absl::StatusCode::kInvalidArgument);
220 EXPECT_THAT(
221 service_config.status().message(),
222 ::testing::HasSubstr(
223 "errors validating RLS LB policy config: ["
224 "field:childPolicy error:field not present; "
225 "field:childPolicyConfigTargetFieldName error:field not present; "
226 "field:routeLookupConfig.cacheSizeBytes error:field not present; "
227 "field:routeLookupConfig.grpcKeybuilders error:field not present; "
228 "field:routeLookupConfig.lookupService error:field not present]"))
229 << service_config.status();
230 }
231
TEST_F(RlsConfigParsingTest,RouteLookupConfigFieldsWrongTypes)232 TEST_F(RlsConfigParsingTest, RouteLookupConfigFieldsWrongTypes) {
233 const char* service_config_json =
234 "{\n"
235 " \"loadBalancingConfig\":[{\n"
236 " \"rls_experimental\":{\n"
237 " \"routeLookupConfig\":{\n"
238 " \"grpcKeybuilders\":1,\n"
239 " \"name\":1,\n"
240 " \"lookupService\":1,\n"
241 " \"lookupServiceTimeout\":{},\n"
242 " \"maxAge\":{},\n"
243 " \"staleAge\":{},\n"
244 " \"cacheSizeBytes\":\"xxx\",\n"
245 " \"defaultTarget\":1\n"
246 " }\n"
247 " }\n"
248 " }]\n"
249 "}\n";
250 auto service_config =
251 ServiceConfigImpl::Create(ChannelArgs(), service_config_json);
252 EXPECT_EQ(service_config.status().code(), absl::StatusCode::kInvalidArgument);
253 EXPECT_THAT(
254 service_config.status().message(),
255 ::testing::HasSubstr(
256 "errors validating RLS LB policy config: ["
257 "field:childPolicy error:field not present; "
258 "field:childPolicyConfigTargetFieldName error:field not present; "
259 "field:routeLookupConfig.cacheSizeBytes error:"
260 "failed to parse number; "
261 "field:routeLookupConfig.defaultTarget error:is not a string; "
262 "field:routeLookupConfig.grpcKeybuilders error:is not an array; "
263 "field:routeLookupConfig.lookupService error:is not a string; "
264 "field:routeLookupConfig.lookupServiceTimeout error:is not a string; "
265 "field:routeLookupConfig.maxAge error:is not a string; "
266 "field:routeLookupConfig.staleAge error:is not a string]"))
267 << service_config.status();
268 }
269
TEST_F(RlsConfigParsingTest,RouteLookupConfigFieldsInvalidValues)270 TEST_F(RlsConfigParsingTest, RouteLookupConfigFieldsInvalidValues) {
271 const char* service_config_json =
272 "{\n"
273 " \"loadBalancingConfig\":[{\n"
274 " \"rls_experimental\":{\n"
275 " \"routeLookupConfig\":{\n"
276 " \"lookupService\":\"\",\n"
277 " \"cacheSizeBytes\":0\n"
278 " }\n"
279 " }\n"
280 " }]\n"
281 "}\n";
282 auto service_config =
283 ServiceConfigImpl::Create(ChannelArgs(), service_config_json);
284 EXPECT_EQ(service_config.status().code(), absl::StatusCode::kInvalidArgument);
285 EXPECT_THAT(
286 service_config.status().message(),
287 ::testing::HasSubstr(
288 "errors validating RLS LB policy config: ["
289 "field:childPolicy error:field not present; "
290 "field:childPolicyConfigTargetFieldName error:field not present; "
291 "field:routeLookupConfig.cacheSizeBytes error:"
292 "must be greater than 0; "
293 "field:routeLookupConfig.grpcKeybuilders error:field not present; "
294 "field:routeLookupConfig.lookupService error:"
295 "must be valid gRPC target URI]"))
296 << service_config.status();
297 }
298
299 //
300 // grpcKeybuilder fields
301 //
302
TEST_F(RlsConfigParsingTest,GrpcKeybuilderRequiredFieldsMissing)303 TEST_F(RlsConfigParsingTest, GrpcKeybuilderRequiredFieldsMissing) {
304 const char* service_config_json =
305 "{\n"
306 " \"loadBalancingConfig\":[{\n"
307 " \"rls_experimental\":{\n"
308 " \"routeLookupConfig\":{\n"
309 " \"grpcKeybuilders\":[\n"
310 " {\n"
311 " }\n"
312 " ]\n"
313 " }\n"
314 " }\n"
315 " }]\n"
316 "}\n";
317 auto service_config =
318 ServiceConfigImpl::Create(ChannelArgs(), service_config_json);
319 EXPECT_EQ(service_config.status().code(), absl::StatusCode::kInvalidArgument);
320 EXPECT_THAT(
321 service_config.status().message(),
322 ::testing::HasSubstr(
323 "errors validating RLS LB policy config: ["
324 "field:childPolicy error:field not present; "
325 "field:childPolicyConfigTargetFieldName error:field not present; "
326 "field:routeLookupConfig.cacheSizeBytes error:field not present; "
327 "field:routeLookupConfig.grpcKeybuilders[0].names error:"
328 "field not present; "
329 "field:routeLookupConfig.lookupService error:field not present]"))
330 << service_config.status();
331 }
332
TEST_F(RlsConfigParsingTest,GrpcKeybuilderWrongFieldTypes)333 TEST_F(RlsConfigParsingTest, GrpcKeybuilderWrongFieldTypes) {
334 const char* service_config_json =
335 "{\n"
336 " \"loadBalancingConfig\":[{\n"
337 " \"rls_experimental\":{\n"
338 " \"routeLookupConfig\":{\n"
339 " \"grpcKeybuilders\":[\n"
340 " {\n"
341 " \"names\":1,\n"
342 " \"headers\":1,\n"
343 " \"extraKeys\":1,\n"
344 " \"constantKeys\":1\n"
345 " }\n"
346 " ]\n"
347 " }\n"
348 " }\n"
349 " }]\n"
350 "}\n";
351 auto service_config =
352 ServiceConfigImpl::Create(ChannelArgs(), service_config_json);
353 EXPECT_EQ(service_config.status().code(), absl::StatusCode::kInvalidArgument);
354 EXPECT_THAT(
355 service_config.status().message(),
356 ::testing::HasSubstr(
357 "errors validating RLS LB policy config: ["
358 "field:childPolicy error:field not present; "
359 "field:childPolicyConfigTargetFieldName error:field not present; "
360 "field:routeLookupConfig.cacheSizeBytes error:field not present; "
361 "field:routeLookupConfig.grpcKeybuilders[0].constantKeys error:"
362 "is not an object; "
363 "field:routeLookupConfig.grpcKeybuilders[0].extraKeys error:"
364 "is not an object; "
365 "field:routeLookupConfig.grpcKeybuilders[0].headers error:"
366 "is not an array; "
367 "field:routeLookupConfig.grpcKeybuilders[0].names error:"
368 "is not an array; "
369 "field:routeLookupConfig.lookupService error:field not present]"))
370 << service_config.status();
371 }
372
TEST_F(RlsConfigParsingTest,GrpcKeybuilderInvalidValues)373 TEST_F(RlsConfigParsingTest, GrpcKeybuilderInvalidValues) {
374 const char* service_config_json =
375 "{\n"
376 " \"loadBalancingConfig\":[{\n"
377 " \"rls_experimental\":{\n"
378 " \"routeLookupConfig\":{\n"
379 " \"grpcKeybuilders\":[\n"
380 " {\n"
381 " \"names\":[],\n"
382 " \"extraKeys\":{\n"
383 " \"host\":1,\n"
384 " \"service\":1,\n"
385 " \"method\":1\n"
386 " },\n"
387 " \"constantKeys\":{\n"
388 " \"key\":1\n"
389 " }\n"
390 " }\n"
391 " ]\n"
392 " }\n"
393 " }\n"
394 " }]\n"
395 "}\n";
396 auto service_config =
397 ServiceConfigImpl::Create(ChannelArgs(), service_config_json);
398 EXPECT_EQ(service_config.status().code(), absl::StatusCode::kInvalidArgument);
399 EXPECT_THAT(
400 service_config.status().message(),
401 ::testing::HasSubstr(
402 "errors validating RLS LB policy config: ["
403 "field:childPolicy error:field not present; "
404 "field:childPolicyConfigTargetFieldName error:field not present; "
405 "field:routeLookupConfig.cacheSizeBytes error:field not present; "
406 "field:routeLookupConfig.grpcKeybuilders[0].constantKeys[\"key\"] "
407 "error:is not a string; "
408 "field:routeLookupConfig.grpcKeybuilders[0].extraKeys.host "
409 "error:is not a string; "
410 "field:routeLookupConfig.grpcKeybuilders[0].extraKeys.method "
411 "error:is not a string; "
412 "field:routeLookupConfig.grpcKeybuilders[0].extraKeys.service "
413 "error:is not a string; "
414 "field:routeLookupConfig.grpcKeybuilders[0].names "
415 "error:must be non-empty; "
416 "field:routeLookupConfig.lookupService error:field not present]"))
417 << service_config.status();
418 }
419
TEST_F(RlsConfigParsingTest,GrpcKeybuilderInvalidHeaders)420 TEST_F(RlsConfigParsingTest, GrpcKeybuilderInvalidHeaders) {
421 const char* service_config_json =
422 "{\n"
423 " \"loadBalancingConfig\":[{\n"
424 " \"rls_experimental\":{\n"
425 " \"routeLookupConfig\":{\n"
426 " \"grpcKeybuilders\":[\n"
427 " {\n"
428 " \"headers\":[\n"
429 " 1,\n"
430 " {\n"
431 " \"key\":1,\n"
432 " \"names\":1\n"
433 " },\n"
434 " {\n"
435 " \"names\":[]\n"
436 " },\n"
437 " {\n"
438 " \"key\":\"\",\n"
439 " \"names\":[1, \"\"]\n"
440 " }\n"
441 " ],\n"
442 " \"extraKeys\":{\n"
443 " \"host\": \"\"\n"
444 " },\n"
445 " \"constantKeys\":{\n"
446 " \"\":\"foo\"\n"
447 " }\n"
448 " }\n"
449 " ]\n"
450 " }\n"
451 " }\n"
452 " }]\n"
453 "}\n";
454 auto service_config =
455 ServiceConfigImpl::Create(ChannelArgs(), service_config_json);
456 EXPECT_EQ(service_config.status().code(), absl::StatusCode::kInvalidArgument);
457 EXPECT_THAT(
458 service_config.status().message(),
459 ::testing::HasSubstr(
460 "errors validating RLS LB policy config: ["
461 "field:childPolicy error:field not present; "
462 "field:childPolicyConfigTargetFieldName error:field not present; "
463 "field:routeLookupConfig.cacheSizeBytes error:field not present; "
464 "field:routeLookupConfig.grpcKeybuilders[0].constantKeys[\"\"] "
465 "error:key must be non-empty; "
466 "field:routeLookupConfig.grpcKeybuilders[0].extraKeys.host "
467 "error:must be non-empty if set; "
468 "field:routeLookupConfig.grpcKeybuilders[0].headers[0] "
469 "error:is not an object; "
470 "field:routeLookupConfig.grpcKeybuilders[0].headers[1].key "
471 "error:is not a string; "
472 "field:routeLookupConfig.grpcKeybuilders[0].headers[1].names "
473 "error:is not an array; "
474 "field:routeLookupConfig.grpcKeybuilders[0].headers[2].key "
475 "error:field not present; "
476 "field:routeLookupConfig.grpcKeybuilders[0].headers[2].names "
477 "error:must be non-empty; "
478 "field:routeLookupConfig.grpcKeybuilders[0].headers[3].key "
479 "error:must be non-empty; "
480 "field:routeLookupConfig.grpcKeybuilders[0].headers[3].names[0] "
481 "error:is not a string; "
482 "field:routeLookupConfig.grpcKeybuilders[0].headers[3].names[1] "
483 "error:must be non-empty; "
484 "field:routeLookupConfig.grpcKeybuilders[0].names "
485 "error:field not present; "
486 "field:routeLookupConfig.lookupService error:field not present]"))
487 << service_config.status();
488 }
489
TEST_F(RlsConfigParsingTest,GrpcKeybuilderNameWrongFieldTypes)490 TEST_F(RlsConfigParsingTest, GrpcKeybuilderNameWrongFieldTypes) {
491 const char* service_config_json =
492 "{\n"
493 " \"loadBalancingConfig\":[{\n"
494 " \"rls_experimental\":{\n"
495 " \"routeLookupConfig\":{\n"
496 " \"grpcKeybuilders\":[\n"
497 " {\n"
498 " \"names\":[\n"
499 " 1,\n"
500 " {\n"
501 " \"service\":1,\n"
502 " \"method\":1\n"
503 " }\n"
504 " ]\n"
505 " }\n"
506 " ]\n"
507 " }\n"
508 " }\n"
509 " }]\n"
510 "}\n";
511 auto service_config =
512 ServiceConfigImpl::Create(ChannelArgs(), service_config_json);
513 EXPECT_EQ(service_config.status().code(), absl::StatusCode::kInvalidArgument);
514 EXPECT_THAT(
515 service_config.status().message(),
516 ::testing::HasSubstr(
517 "errors validating RLS LB policy config: ["
518 "field:childPolicy error:field not present; "
519 "field:childPolicyConfigTargetFieldName error:field not present; "
520 "field:routeLookupConfig.cacheSizeBytes error:field not present; "
521 "field:routeLookupConfig.grpcKeybuilders[0].names[0] "
522 "error:is not an object; "
523 "field:routeLookupConfig.grpcKeybuilders[0].names[1].method "
524 "error:is not a string; "
525 "field:routeLookupConfig.grpcKeybuilders[0].names[1].service "
526 "error:is not a string; "
527 "field:routeLookupConfig.lookupService error:field not present]"))
528 << service_config.status();
529 }
530
TEST_F(RlsConfigParsingTest,DuplicateMethodNamesInSameKeyBuilder)531 TEST_F(RlsConfigParsingTest, DuplicateMethodNamesInSameKeyBuilder) {
532 const char* service_config_json =
533 "{\n"
534 " \"loadBalancingConfig\":[{\n"
535 " \"rls_experimental\":{\n"
536 " \"routeLookupConfig\":{\n"
537 " \"grpcKeybuilders\":[\n"
538 " {\n"
539 " \"names\":[\n"
540 " {\n"
541 " \"service\":\"foo\",\n"
542 " \"method\":\"bar\"\n"
543 " },\n"
544 " {\n"
545 " \"service\":\"foo\",\n"
546 " \"method\":\"bar\"\n"
547 " }\n"
548 " ]\n"
549 " }\n"
550 " ]\n"
551 " }\n"
552 " }\n"
553 " }]\n"
554 "}\n";
555 auto service_config =
556 ServiceConfigImpl::Create(ChannelArgs(), service_config_json);
557 EXPECT_EQ(service_config.status().code(), absl::StatusCode::kInvalidArgument);
558 EXPECT_THAT(
559 service_config.status().message(),
560 ::testing::HasSubstr(
561 "errors validating RLS LB policy config: ["
562 "field:childPolicy error:field not present; "
563 "field:childPolicyConfigTargetFieldName error:field not present; "
564 "field:routeLookupConfig.cacheSizeBytes error:field not present; "
565 "field:routeLookupConfig.grpcKeybuilders[0] "
566 "error:duplicate entry for \"/foo/bar\"; "
567 "field:routeLookupConfig.lookupService error:field not present]"))
568 << service_config.status();
569 }
570
TEST_F(RlsConfigParsingTest,DuplicateMethodNamesInDifferentKeyBuilders)571 TEST_F(RlsConfigParsingTest, DuplicateMethodNamesInDifferentKeyBuilders) {
572 const char* service_config_json =
573 "{\n"
574 " \"loadBalancingConfig\":[{\n"
575 " \"rls_experimental\":{\n"
576 " \"routeLookupConfig\":{\n"
577 " \"grpcKeybuilders\":[\n"
578 " {\n"
579 " \"names\":[\n"
580 " {\n"
581 " \"service\":\"foo\",\n"
582 " \"method\":\"bar\"\n"
583 " }\n"
584 " ]\n"
585 " },\n"
586 " {\n"
587 " \"names\":[\n"
588 " {\n"
589 " \"service\":\"foo\",\n"
590 " \"method\":\"bar\"\n"
591 " }\n"
592 " ]\n"
593 " }\n"
594 " ]\n"
595 " }\n"
596 " }\n"
597 " }]\n"
598 "}\n";
599 auto service_config =
600 ServiceConfigImpl::Create(ChannelArgs(), service_config_json);
601 EXPECT_EQ(service_config.status().code(), absl::StatusCode::kInvalidArgument);
602 EXPECT_THAT(
603 service_config.status().message(),
604 ::testing::HasSubstr(
605 "errors validating RLS LB policy config: ["
606 "field:childPolicy error:field not present; "
607 "field:childPolicyConfigTargetFieldName error:field not present; "
608 "field:routeLookupConfig.cacheSizeBytes error:field not present; "
609 "field:routeLookupConfig.grpcKeybuilders[1] "
610 "error:duplicate entry for \"/foo/bar\"; "
611 "field:routeLookupConfig.lookupService error:field not present]"))
612 << service_config.status();
613 }
614
615 } // namespace
616 } // namespace grpc_core
617
main(int argc,char ** argv)618 int main(int argc, char** argv) {
619 ::testing::InitGoogleTest(&argc, argv);
620 grpc::testing::TestEnvironment env(&argc, argv);
621 return RUN_ALL_TESTS();
622 }
623