1 /*
2 *
3 * Copyright 2019 gRPC authors.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 */
18
19 #include <regex>
20
21 #include "absl/strings/str_cat.h"
22
23 #include <gtest/gtest.h>
24
25 #include <grpc/grpc.h>
26 #include "src/core/ext/filters/client_channel/resolver_result_parsing.h"
27 #include "src/core/ext/filters/client_channel/service_config.h"
28 #include "src/core/ext/filters/client_channel/service_config_parser.h"
29 #include "src/core/ext/filters/message_size/message_size_filter.h"
30 #include "src/core/lib/gpr/string.h"
31 #include "test/core/util/port.h"
32 #include "test/core/util/test_config.h"
33
34 namespace grpc_core {
35 namespace testing {
36
37 class TestParsedConfig1 : public ServiceConfigParser::ParsedConfig {
38 public:
TestParsedConfig1(int value)39 TestParsedConfig1(int value) : value_(value) {}
40
value() const41 int value() const { return value_; }
42
43 private:
44 int value_;
45 };
46
47 class TestParser1 : public ServiceConfigParser::Parser {
48 public:
ParseGlobalParams(const Json & json,grpc_error ** error)49 std::unique_ptr<ServiceConfigParser::ParsedConfig> ParseGlobalParams(
50 const Json& json, grpc_error** error) override {
51 GPR_DEBUG_ASSERT(error != nullptr);
52 auto it = json.object_value().find("global_param");
53 if (it != json.object_value().end()) {
54 if (it->second.type() != Json::Type::NUMBER) {
55 *error =
56 GRPC_ERROR_CREATE_FROM_STATIC_STRING(InvalidTypeErrorMessage());
57 return nullptr;
58 }
59 int value = gpr_parse_nonnegative_int(it->second.string_value().c_str());
60 if (value == -1) {
61 *error =
62 GRPC_ERROR_CREATE_FROM_STATIC_STRING(InvalidValueErrorMessage());
63 return nullptr;
64 }
65 return absl::make_unique<TestParsedConfig1>(value);
66 }
67 return nullptr;
68 }
69
InvalidTypeErrorMessage()70 static const char* InvalidTypeErrorMessage() {
71 return "global_param value type should be a number";
72 }
73
InvalidValueErrorMessage()74 static const char* InvalidValueErrorMessage() {
75 return "global_param value type should be non-negative";
76 }
77 };
78
79 class TestParser2 : public ServiceConfigParser::Parser {
80 public:
ParsePerMethodParams(const Json & json,grpc_error ** error)81 std::unique_ptr<ServiceConfigParser::ParsedConfig> ParsePerMethodParams(
82 const Json& json, grpc_error** error) override {
83 GPR_DEBUG_ASSERT(error != nullptr);
84 auto it = json.object_value().find("method_param");
85 if (it != json.object_value().end()) {
86 if (it->second.type() != Json::Type::NUMBER) {
87 *error =
88 GRPC_ERROR_CREATE_FROM_STATIC_STRING(InvalidTypeErrorMessage());
89 return nullptr;
90 }
91 int value = gpr_parse_nonnegative_int(it->second.string_value().c_str());
92 if (value == -1) {
93 *error =
94 GRPC_ERROR_CREATE_FROM_STATIC_STRING(InvalidValueErrorMessage());
95 return nullptr;
96 }
97 return absl::make_unique<TestParsedConfig1>(value);
98 }
99 return nullptr;
100 }
101
InvalidTypeErrorMessage()102 static const char* InvalidTypeErrorMessage() {
103 return "method_param value type should be a number";
104 }
105
InvalidValueErrorMessage()106 static const char* InvalidValueErrorMessage() {
107 return "method_param value type should be non-negative";
108 }
109 };
110
111 // This parser always adds errors
112 class ErrorParser : public ServiceConfigParser::Parser {
113 public:
ParsePerMethodParams(const Json &,grpc_error ** error)114 std::unique_ptr<ServiceConfigParser::ParsedConfig> ParsePerMethodParams(
115 const Json& /*json*/, grpc_error** error) override {
116 GPR_DEBUG_ASSERT(error != nullptr);
117 *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(MethodError());
118 return nullptr;
119 }
120
ParseGlobalParams(const Json &,grpc_error ** error)121 std::unique_ptr<ServiceConfigParser::ParsedConfig> ParseGlobalParams(
122 const Json& /*json*/, grpc_error** error) override {
123 GPR_DEBUG_ASSERT(error != nullptr);
124 *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(GlobalError());
125 return nullptr;
126 }
127
MethodError()128 static const char* MethodError() { return "ErrorParser : methodError"; }
129
GlobalError()130 static const char* GlobalError() { return "ErrorParser : globalError"; }
131 };
132
VerifyRegexMatch(grpc_error * error,const std::regex & regex)133 void VerifyRegexMatch(grpc_error* error, const std::regex& regex) {
134 std::smatch match;
135 std::string error_str = grpc_error_string(error);
136 EXPECT_TRUE(std::regex_search(error_str, match, regex)) << error_str;
137 GRPC_ERROR_UNREF(error);
138 }
139
140 class ServiceConfigTest : public ::testing::Test {
141 protected:
SetUp()142 void SetUp() override {
143 ServiceConfigParser::Shutdown();
144 ServiceConfigParser::Init();
145 EXPECT_EQ(
146 ServiceConfigParser::RegisterParser(absl::make_unique<TestParser1>()),
147 0);
148 EXPECT_EQ(
149 ServiceConfigParser::RegisterParser(absl::make_unique<TestParser2>()),
150 1);
151 }
152 };
153
TEST_F(ServiceConfigTest,ErrorCheck1)154 TEST_F(ServiceConfigTest, ErrorCheck1) {
155 const char* test_json = "";
156 grpc_error* error = GRPC_ERROR_NONE;
157 auto svc_cfg = ServiceConfig::Create(test_json, &error);
158 std::regex regex(std::string("JSON parse error"));
159 VerifyRegexMatch(error, regex);
160 }
161
TEST_F(ServiceConfigTest,BasicTest1)162 TEST_F(ServiceConfigTest, BasicTest1) {
163 const char* test_json = "{}";
164 grpc_error* error = GRPC_ERROR_NONE;
165 auto svc_cfg = ServiceConfig::Create(test_json, &error);
166 EXPECT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error);
167 }
168
TEST_F(ServiceConfigTest,SkipMethodConfigWithNoNameOrEmptyName)169 TEST_F(ServiceConfigTest, SkipMethodConfigWithNoNameOrEmptyName) {
170 const char* test_json =
171 "{\"methodConfig\": ["
172 " {\"method_param\":1},"
173 " {\"name\":[], \"method_param\":1},"
174 " {\"name\":[{\"service\":\"TestServ\"}], \"method_param\":2}"
175 "]}";
176 grpc_error* error = GRPC_ERROR_NONE;
177 auto svc_cfg = ServiceConfig::Create(test_json, &error);
178 ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error);
179 const auto* vector_ptr = svc_cfg->GetMethodParsedConfigVector(
180 grpc_slice_from_static_string("/TestServ/TestMethod"));
181 ASSERT_NE(vector_ptr, nullptr);
182 auto parsed_config = ((*vector_ptr)[1]).get();
183 EXPECT_EQ(static_cast<TestParsedConfig1*>(parsed_config)->value(), 2);
184 }
185
TEST_F(ServiceConfigTest,ErrorDuplicateMethodConfigNames)186 TEST_F(ServiceConfigTest, ErrorDuplicateMethodConfigNames) {
187 const char* test_json =
188 "{\"methodConfig\": ["
189 " {\"name\":[{\"service\":\"TestServ\"}]},"
190 " {\"name\":[{\"service\":\"TestServ\"}]}"
191 "]}";
192 grpc_error* error = GRPC_ERROR_NONE;
193 auto svc_cfg = ServiceConfig::Create(test_json, &error);
194 std::regex regex(
195 std::string("Service config parsing error.*referenced_errors"
196 ".*Method Params.*referenced_errors"
197 ".*methodConfig.*referenced_errors"
198 ".*multiple method configs with same name"));
199 VerifyRegexMatch(error, regex);
200 }
201
TEST_F(ServiceConfigTest,ErrorDuplicateMethodConfigNamesWithNullMethod)202 TEST_F(ServiceConfigTest, ErrorDuplicateMethodConfigNamesWithNullMethod) {
203 const char* test_json =
204 "{\"methodConfig\": ["
205 " {\"name\":[{\"service\":\"TestServ\",\"method\":null}]},"
206 " {\"name\":[{\"service\":\"TestServ\"}]}"
207 "]}";
208 grpc_error* error = GRPC_ERROR_NONE;
209 auto svc_cfg = ServiceConfig::Create(test_json, &error);
210 std::regex regex(
211 std::string("Service config parsing error.*referenced_errors"
212 ".*Method Params.*referenced_errors"
213 ".*methodConfig.*referenced_errors"
214 ".*multiple method configs with same name"));
215 VerifyRegexMatch(error, regex);
216 }
217
TEST_F(ServiceConfigTest,ErrorDuplicateMethodConfigNamesWithEmptyMethod)218 TEST_F(ServiceConfigTest, ErrorDuplicateMethodConfigNamesWithEmptyMethod) {
219 const char* test_json =
220 "{\"methodConfig\": ["
221 " {\"name\":[{\"service\":\"TestServ\",\"method\":\"\"}]},"
222 " {\"name\":[{\"service\":\"TestServ\"}]}"
223 "]}";
224 grpc_error* error = GRPC_ERROR_NONE;
225 auto svc_cfg = ServiceConfig::Create(test_json, &error);
226 std::regex regex(
227 std::string("Service config parsing error.*referenced_errors"
228 ".*Method Params.*referenced_errors"
229 ".*methodConfig.*referenced_errors"
230 ".*multiple method configs with same name"));
231 VerifyRegexMatch(error, regex);
232 }
233
TEST_F(ServiceConfigTest,ErrorDuplicateDefaultMethodConfigs)234 TEST_F(ServiceConfigTest, ErrorDuplicateDefaultMethodConfigs) {
235 const char* test_json =
236 "{\"methodConfig\": ["
237 " {\"name\":[{}]},"
238 " {\"name\":[{}]}"
239 "]}";
240 grpc_error* error = GRPC_ERROR_NONE;
241 auto svc_cfg = ServiceConfig::Create(test_json, &error);
242 std::regex regex(
243 std::string("Service config parsing error.*referenced_errors"
244 ".*Method Params.*referenced_errors"
245 ".*methodConfig.*referenced_errors"
246 ".*multiple default method configs"));
247 VerifyRegexMatch(error, regex);
248 }
249
TEST_F(ServiceConfigTest,ErrorDuplicateDefaultMethodConfigsWithNullService)250 TEST_F(ServiceConfigTest, ErrorDuplicateDefaultMethodConfigsWithNullService) {
251 const char* test_json =
252 "{\"methodConfig\": ["
253 " {\"name\":[{\"service\":null}]},"
254 " {\"name\":[{}]}"
255 "]}";
256 grpc_error* error = GRPC_ERROR_NONE;
257 auto svc_cfg = ServiceConfig::Create(test_json, &error);
258 std::regex regex(
259 std::string("Service config parsing error.*referenced_errors"
260 ".*Method Params.*referenced_errors"
261 ".*methodConfig.*referenced_errors"
262 ".*multiple default method configs"));
263 VerifyRegexMatch(error, regex);
264 }
265
TEST_F(ServiceConfigTest,ErrorDuplicateDefaultMethodConfigsWithEmptyService)266 TEST_F(ServiceConfigTest, ErrorDuplicateDefaultMethodConfigsWithEmptyService) {
267 const char* test_json =
268 "{\"methodConfig\": ["
269 " {\"name\":[{\"service\":\"\"}]},"
270 " {\"name\":[{}]}"
271 "]}";
272 grpc_error* error = GRPC_ERROR_NONE;
273 auto svc_cfg = ServiceConfig::Create(test_json, &error);
274 std::regex regex(
275 std::string("Service config parsing error.*referenced_errors"
276 ".*Method Params.*referenced_errors"
277 ".*methodConfig.*referenced_errors"
278 ".*multiple default method configs"));
279 VerifyRegexMatch(error, regex);
280 }
281
TEST_F(ServiceConfigTest,ValidMethodConfig)282 TEST_F(ServiceConfigTest, ValidMethodConfig) {
283 const char* test_json =
284 "{\"methodConfig\": [{\"name\":[{\"service\":\"TestServ\"}]}]}";
285 grpc_error* error = GRPC_ERROR_NONE;
286 auto svc_cfg = ServiceConfig::Create(test_json, &error);
287 EXPECT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error);
288 }
289
TEST_F(ServiceConfigTest,Parser1BasicTest1)290 TEST_F(ServiceConfigTest, Parser1BasicTest1) {
291 const char* test_json = "{\"global_param\":5}";
292 grpc_error* error = GRPC_ERROR_NONE;
293 auto svc_cfg = ServiceConfig::Create(test_json, &error);
294 ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error);
295 EXPECT_EQ((static_cast<TestParsedConfig1*>(svc_cfg->GetGlobalParsedConfig(0)))
296 ->value(),
297 5);
298 EXPECT_EQ(svc_cfg->GetMethodParsedConfigVector(
299 grpc_slice_from_static_string("/TestServ/TestMethod")),
300 nullptr);
301 }
302
TEST_F(ServiceConfigTest,Parser1BasicTest2)303 TEST_F(ServiceConfigTest, Parser1BasicTest2) {
304 const char* test_json = "{\"global_param\":1000}";
305 grpc_error* error = GRPC_ERROR_NONE;
306 auto svc_cfg = ServiceConfig::Create(test_json, &error);
307 ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error);
308 EXPECT_EQ((static_cast<TestParsedConfig1*>(svc_cfg->GetGlobalParsedConfig(0)))
309 ->value(),
310 1000);
311 }
312
TEST_F(ServiceConfigTest,Parser1ErrorInvalidType)313 TEST_F(ServiceConfigTest, Parser1ErrorInvalidType) {
314 const char* test_json = "{\"global_param\":\"5\"}";
315 grpc_error* error = GRPC_ERROR_NONE;
316 auto svc_cfg = ServiceConfig::Create(test_json, &error);
317 std::regex regex(
318 absl::StrCat("Service config parsing error.*referenced_errors.*"
319 "Global Params.*referenced_errors.*",
320 TestParser1::InvalidTypeErrorMessage()));
321 VerifyRegexMatch(error, regex);
322 }
323
TEST_F(ServiceConfigTest,Parser1ErrorInvalidValue)324 TEST_F(ServiceConfigTest, Parser1ErrorInvalidValue) {
325 const char* test_json = "{\"global_param\":-5}";
326 grpc_error* error = GRPC_ERROR_NONE;
327 auto svc_cfg = ServiceConfig::Create(test_json, &error);
328 std::regex regex(
329 absl::StrCat("Service config parsing error.*referenced_errors.*"
330 "Global Params.*referenced_errors.*",
331 TestParser1::InvalidValueErrorMessage()));
332 VerifyRegexMatch(error, regex);
333 }
334
TEST_F(ServiceConfigTest,Parser2BasicTest)335 TEST_F(ServiceConfigTest, Parser2BasicTest) {
336 const char* test_json =
337 "{\"methodConfig\": [{\"name\":[{\"service\":\"TestServ\"}], "
338 "\"method_param\":5}]}";
339 grpc_error* error = GRPC_ERROR_NONE;
340 auto svc_cfg = ServiceConfig::Create(test_json, &error);
341 ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error);
342 const auto* vector_ptr = svc_cfg->GetMethodParsedConfigVector(
343 grpc_slice_from_static_string("/TestServ/TestMethod"));
344 ASSERT_NE(vector_ptr, nullptr);
345 auto parsed_config = ((*vector_ptr)[1]).get();
346 EXPECT_EQ(static_cast<TestParsedConfig1*>(parsed_config)->value(), 5);
347 }
348
TEST_F(ServiceConfigTest,Parser2ErrorInvalidType)349 TEST_F(ServiceConfigTest, Parser2ErrorInvalidType) {
350 const char* test_json =
351 "{\"methodConfig\": [{\"name\":[{\"service\":\"TestServ\"}], "
352 "\"method_param\":\"5\"}]}";
353 grpc_error* error = GRPC_ERROR_NONE;
354 auto svc_cfg = ServiceConfig::Create(test_json, &error);
355 std::regex regex(
356 absl::StrCat("Service config parsing error.*referenced_errors\":\\[.*"
357 "Method Params.*referenced_errors.*methodConfig.*"
358 "referenced_errors.*",
359 TestParser2::InvalidTypeErrorMessage()));
360 VerifyRegexMatch(error, regex);
361 }
362
TEST_F(ServiceConfigTest,Parser2ErrorInvalidValue)363 TEST_F(ServiceConfigTest, Parser2ErrorInvalidValue) {
364 const char* test_json =
365 "{\"methodConfig\": [{\"name\":[{\"service\":\"TestServ\"}], "
366 "\"method_param\":-5}]}";
367 grpc_error* error = GRPC_ERROR_NONE;
368 auto svc_cfg = ServiceConfig::Create(test_json, &error);
369 std::regex regex(
370 absl::StrCat("Service config parsing error.*referenced_errors\":\\[.*"
371 "Method Params.*referenced_errors.*methodConfig.*"
372 "referenced_errors.*",
373 TestParser2::InvalidValueErrorMessage()));
374 VerifyRegexMatch(error, regex);
375 }
376
377 // Test parsing with ErrorParsers which always add errors
378 class ErroredParsersScopingTest : public ::testing::Test {
379 protected:
SetUp()380 void SetUp() override {
381 ServiceConfigParser::Shutdown();
382 ServiceConfigParser::Init();
383 EXPECT_EQ(
384 ServiceConfigParser::RegisterParser(absl::make_unique<ErrorParser>()),
385 0);
386 EXPECT_EQ(
387 ServiceConfigParser::RegisterParser(absl::make_unique<ErrorParser>()),
388 1);
389 }
390 };
391
TEST_F(ErroredParsersScopingTest,GlobalParams)392 TEST_F(ErroredParsersScopingTest, GlobalParams) {
393 const char* test_json = "{}";
394 grpc_error* error = GRPC_ERROR_NONE;
395 auto svc_cfg = ServiceConfig::Create(test_json, &error);
396 std::regex regex(absl::StrCat(
397 "Service config parsing error.*referenced_errors\":\\[.*"
398 "Global Params.*referenced_errors.*",
399 ErrorParser::GlobalError(), ".*", ErrorParser::GlobalError()));
400 VerifyRegexMatch(error, regex);
401 }
402
TEST_F(ErroredParsersScopingTest,MethodParams)403 TEST_F(ErroredParsersScopingTest, MethodParams) {
404 const char* test_json = "{\"methodConfig\": [{}]}";
405 grpc_error* error = GRPC_ERROR_NONE;
406 auto svc_cfg = ServiceConfig::Create(test_json, &error);
407 std::regex regex(absl::StrCat(
408 "Service config parsing error.*referenced_errors\":\\[.*"
409 "Global Params.*referenced_errors.*",
410 ErrorParser::GlobalError(), ".*", ErrorParser::GlobalError(),
411 ".*Method Params.*referenced_errors.*methodConfig.*referenced_errors.*",
412 ErrorParser::MethodError(), ".*", ErrorParser::MethodError()));
413 VerifyRegexMatch(error, regex);
414 }
415
416 class ClientChannelParserTest : public ::testing::Test {
417 protected:
SetUp()418 void SetUp() override {
419 ServiceConfigParser::Shutdown();
420 ServiceConfigParser::Init();
421 EXPECT_EQ(
422 ServiceConfigParser::RegisterParser(
423 absl::make_unique<internal::ClientChannelServiceConfigParser>()),
424 0);
425 }
426 };
427
TEST_F(ClientChannelParserTest,ValidLoadBalancingConfigPickFirst)428 TEST_F(ClientChannelParserTest, ValidLoadBalancingConfigPickFirst) {
429 const char* test_json = "{\"loadBalancingConfig\": [{\"pick_first\":{}}]}";
430 grpc_error* error = GRPC_ERROR_NONE;
431 auto svc_cfg = ServiceConfig::Create(test_json, &error);
432 ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error);
433 const auto* parsed_config =
434 static_cast<grpc_core::internal::ClientChannelGlobalParsedConfig*>(
435 svc_cfg->GetGlobalParsedConfig(0));
436 auto lb_config = parsed_config->parsed_lb_config();
437 EXPECT_STREQ(lb_config->name(), "pick_first");
438 }
439
TEST_F(ClientChannelParserTest,ValidLoadBalancingConfigRoundRobin)440 TEST_F(ClientChannelParserTest, ValidLoadBalancingConfigRoundRobin) {
441 const char* test_json =
442 "{\"loadBalancingConfig\": [{\"round_robin\":{}}, {}]}";
443 grpc_error* error = GRPC_ERROR_NONE;
444 auto svc_cfg = ServiceConfig::Create(test_json, &error);
445 ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error);
446 auto parsed_config =
447 static_cast<grpc_core::internal::ClientChannelGlobalParsedConfig*>(
448 svc_cfg->GetGlobalParsedConfig(0));
449 auto lb_config = parsed_config->parsed_lb_config();
450 EXPECT_STREQ(lb_config->name(), "round_robin");
451 }
452
TEST_F(ClientChannelParserTest,ValidLoadBalancingConfigGrpclb)453 TEST_F(ClientChannelParserTest, ValidLoadBalancingConfigGrpclb) {
454 const char* test_json =
455 "{\"loadBalancingConfig\": "
456 "[{\"grpclb\":{\"childPolicy\":[{\"pick_first\":{}}]}}]}";
457 grpc_error* error = GRPC_ERROR_NONE;
458 auto svc_cfg = ServiceConfig::Create(test_json, &error);
459 ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error);
460 const auto* parsed_config =
461 static_cast<grpc_core::internal::ClientChannelGlobalParsedConfig*>(
462 svc_cfg->GetGlobalParsedConfig(0));
463 auto lb_config = parsed_config->parsed_lb_config();
464 EXPECT_STREQ(lb_config->name(), "grpclb");
465 }
466
TEST_F(ClientChannelParserTest,ValidLoadBalancingConfigXds)467 TEST_F(ClientChannelParserTest, ValidLoadBalancingConfigXds) {
468 const char* test_json =
469 "{\n"
470 " \"loadBalancingConfig\":[\n"
471 " { \"does_not_exist\":{} },\n"
472 " { \"eds_experimental\":{ \"clusterName\": \"foo\" } }\n"
473 " ]\n"
474 "}";
475 grpc_error* error = GRPC_ERROR_NONE;
476 auto svc_cfg = ServiceConfig::Create(test_json, &error);
477 ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error);
478 const auto* parsed_config =
479 static_cast<grpc_core::internal::ClientChannelGlobalParsedConfig*>(
480 svc_cfg->GetGlobalParsedConfig(0));
481 auto lb_config = parsed_config->parsed_lb_config();
482 EXPECT_STREQ(lb_config->name(), "eds_experimental");
483 }
484
TEST_F(ClientChannelParserTest,UnknownLoadBalancingConfig)485 TEST_F(ClientChannelParserTest, UnknownLoadBalancingConfig) {
486 const char* test_json = "{\"loadBalancingConfig\": [{\"unknown\":{}}]}";
487 grpc_error* error = GRPC_ERROR_NONE;
488 auto svc_cfg = ServiceConfig::Create(test_json, &error);
489 std::regex regex(
490 "Service config parsing error.*referenced_errors.*"
491 "Global Params.*referenced_errors.*"
492 "Client channel global parser.*referenced_errors.*"
493 "field:loadBalancingConfig.*referenced_errors.*"
494 "No known policy");
495 VerifyRegexMatch(error, regex);
496 }
497
TEST_F(ClientChannelParserTest,InvalidGrpclbLoadBalancingConfig)498 TEST_F(ClientChannelParserTest, InvalidGrpclbLoadBalancingConfig) {
499 const char* test_json =
500 "{\"loadBalancingConfig\": ["
501 " {\"grpclb\":{\"childPolicy\":1}},"
502 " {\"round_robin\":{}}"
503 "]}";
504 grpc_error* error = GRPC_ERROR_NONE;
505 auto svc_cfg = ServiceConfig::Create(test_json, &error);
506 std::regex regex(
507 "Service config parsing error.*referenced_errors.*"
508 "Global Params.*referenced_errors.*"
509 "Client channel global parser.*referenced_errors.*"
510 "field:loadBalancingConfig.*referenced_errors.*"
511 "GrpcLb Parser.*referenced_errors.*"
512 "field:childPolicy.*referenced_errors.*"
513 "type should be array");
514 VerifyRegexMatch(error, regex);
515 }
516
TEST_F(ClientChannelParserTest,ValidLoadBalancingPolicy)517 TEST_F(ClientChannelParserTest, ValidLoadBalancingPolicy) {
518 const char* test_json = "{\"loadBalancingPolicy\":\"pick_first\"}";
519 grpc_error* error = GRPC_ERROR_NONE;
520 auto svc_cfg = ServiceConfig::Create(test_json, &error);
521 ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error);
522 const auto* parsed_config =
523 static_cast<grpc_core::internal::ClientChannelGlobalParsedConfig*>(
524 svc_cfg->GetGlobalParsedConfig(0));
525 EXPECT_EQ(parsed_config->parsed_deprecated_lb_policy(), "pick_first");
526 }
527
TEST_F(ClientChannelParserTest,ValidLoadBalancingPolicyAllCaps)528 TEST_F(ClientChannelParserTest, ValidLoadBalancingPolicyAllCaps) {
529 const char* test_json = "{\"loadBalancingPolicy\":\"PICK_FIRST\"}";
530 grpc_error* error = GRPC_ERROR_NONE;
531 auto svc_cfg = ServiceConfig::Create(test_json, &error);
532 ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error);
533 const auto* parsed_config =
534 static_cast<grpc_core::internal::ClientChannelGlobalParsedConfig*>(
535 svc_cfg->GetGlobalParsedConfig(0));
536 EXPECT_EQ(parsed_config->parsed_deprecated_lb_policy(), "pick_first");
537 }
538
TEST_F(ClientChannelParserTest,UnknownLoadBalancingPolicy)539 TEST_F(ClientChannelParserTest, UnknownLoadBalancingPolicy) {
540 const char* test_json = "{\"loadBalancingPolicy\":\"unknown\"}";
541 grpc_error* error = GRPC_ERROR_NONE;
542 auto svc_cfg = ServiceConfig::Create(test_json, &error);
543 std::regex regex(
544 "Service config parsing error.*referenced_errors.*"
545 "Global Params.*referenced_errors.*"
546 "Client channel global parser.*referenced_errors.*"
547 "field:loadBalancingPolicy error:Unknown lb policy");
548 VerifyRegexMatch(error, regex);
549 }
550
TEST_F(ClientChannelParserTest,LoadBalancingPolicyXdsNotAllowed)551 TEST_F(ClientChannelParserTest, LoadBalancingPolicyXdsNotAllowed) {
552 const char* test_json = "{\"loadBalancingPolicy\":\"eds_experimental\"}";
553 grpc_error* error = GRPC_ERROR_NONE;
554 auto svc_cfg = ServiceConfig::Create(test_json, &error);
555 std::regex regex(
556 "Service config parsing error.*referenced_errors.*"
557 "Global Params.*referenced_errors.*"
558 "Client channel global parser.*referenced_errors.*"
559 "field:loadBalancingPolicy error:eds_experimental requires "
560 "a config. Please use loadBalancingConfig instead.");
561 VerifyRegexMatch(error, regex);
562 }
563
TEST_F(ClientChannelParserTest,ValidRetryThrottling)564 TEST_F(ClientChannelParserTest, ValidRetryThrottling) {
565 const char* test_json =
566 "{\n"
567 " \"retryThrottling\": {\n"
568 " \"maxTokens\": 2,\n"
569 " \"tokenRatio\": 1.0\n"
570 " }\n"
571 "}";
572 grpc_error* error = GRPC_ERROR_NONE;
573 auto svc_cfg = ServiceConfig::Create(test_json, &error);
574 ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error);
575 const auto* parsed_config =
576 static_cast<grpc_core::internal::ClientChannelGlobalParsedConfig*>(
577 svc_cfg->GetGlobalParsedConfig(0));
578 const auto retryThrottling = parsed_config->retry_throttling();
579 ASSERT_TRUE(retryThrottling.has_value());
580 EXPECT_EQ(retryThrottling.value().max_milli_tokens, 2000);
581 EXPECT_EQ(retryThrottling.value().milli_token_ratio, 1000);
582 }
583
TEST_F(ClientChannelParserTest,RetryThrottlingMissingFields)584 TEST_F(ClientChannelParserTest, RetryThrottlingMissingFields) {
585 const char* test_json =
586 "{\n"
587 " \"retryThrottling\": {\n"
588 " }\n"
589 "}";
590 grpc_error* error = GRPC_ERROR_NONE;
591 auto svc_cfg = ServiceConfig::Create(test_json, &error);
592 std::regex regex(
593 "Service config parsing error.*referenced_errors.*"
594 "Global Params.*referenced_errors.*"
595 "Client channel global parser.*referenced_errors.*"
596 "field:retryThrottling field:maxTokens error:Not found.*"
597 "field:retryThrottling field:tokenRatio error:Not found");
598 VerifyRegexMatch(error, regex);
599 }
600
TEST_F(ClientChannelParserTest,InvalidRetryThrottlingNegativeMaxTokens)601 TEST_F(ClientChannelParserTest, InvalidRetryThrottlingNegativeMaxTokens) {
602 const char* test_json =
603 "{\n"
604 " \"retryThrottling\": {\n"
605 " \"maxTokens\": -2,\n"
606 " \"tokenRatio\": 1.0\n"
607 " }\n"
608 "}";
609 grpc_error* error = GRPC_ERROR_NONE;
610 auto svc_cfg = ServiceConfig::Create(test_json, &error);
611 std::regex regex(
612 "Service config parsing error.*referenced_errors.*"
613 "Global Params.*referenced_errors.*"
614 "Client channel global parser.*referenced_errors.*"
615 "field:retryThrottling field:maxTokens error:should "
616 "be greater than zero");
617 VerifyRegexMatch(error, regex);
618 }
619
TEST_F(ClientChannelParserTest,InvalidRetryThrottlingInvalidTokenRatio)620 TEST_F(ClientChannelParserTest, InvalidRetryThrottlingInvalidTokenRatio) {
621 const char* test_json =
622 "{\n"
623 " \"retryThrottling\": {\n"
624 " \"maxTokens\": 2,\n"
625 " \"tokenRatio\": -1\n"
626 " }\n"
627 "}";
628 grpc_error* error = GRPC_ERROR_NONE;
629 auto svc_cfg = ServiceConfig::Create(test_json, &error);
630 std::regex regex(
631 "Service config parsing error.*referenced_errors.*"
632 "Global Params.*referenced_errors.*"
633 "Client channel global parser.*referenced_errors.*"
634 "field:retryThrottling field:tokenRatio "
635 "error:Failed parsing");
636 VerifyRegexMatch(error, regex);
637 }
638
TEST_F(ClientChannelParserTest,ValidTimeout)639 TEST_F(ClientChannelParserTest, ValidTimeout) {
640 const char* test_json =
641 "{\n"
642 " \"methodConfig\": [ {\n"
643 " \"name\": [\n"
644 " { \"service\": \"TestServ\", \"method\": \"TestMethod\" }\n"
645 " ],\n"
646 " \"timeout\": \"5s\"\n"
647 " } ]\n"
648 "}";
649 grpc_error* error = GRPC_ERROR_NONE;
650 auto svc_cfg = ServiceConfig::Create(test_json, &error);
651 ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error);
652 const auto* vector_ptr = svc_cfg->GetMethodParsedConfigVector(
653 grpc_slice_from_static_string("/TestServ/TestMethod"));
654 ASSERT_NE(vector_ptr, nullptr);
655 auto parsed_config = ((*vector_ptr)[0]).get();
656 EXPECT_EQ((static_cast<grpc_core::internal::ClientChannelMethodParsedConfig*>(
657 parsed_config))
658 ->timeout(),
659 5000);
660 }
661
TEST_F(ClientChannelParserTest,InvalidTimeout)662 TEST_F(ClientChannelParserTest, InvalidTimeout) {
663 const char* test_json =
664 "{\n"
665 " \"methodConfig\": [ {\n"
666 " \"name\": [\n"
667 " { \"service\": \"service\", \"method\": \"method\" }\n"
668 " ],\n"
669 " \"timeout\": \"5sec\"\n"
670 " } ]\n"
671 "}";
672 grpc_error* error = GRPC_ERROR_NONE;
673 auto svc_cfg = ServiceConfig::Create(test_json, &error);
674 std::regex regex(
675 "Service config parsing error.*referenced_errors.*"
676 "Method Params.*referenced_errors.*"
677 "methodConfig.*referenced_errors.*"
678 "Client channel parser.*referenced_errors.*"
679 "field:timeout error:Failed parsing");
680 VerifyRegexMatch(error, regex);
681 }
682
TEST_F(ClientChannelParserTest,ValidWaitForReady)683 TEST_F(ClientChannelParserTest, ValidWaitForReady) {
684 const char* test_json =
685 "{\n"
686 " \"methodConfig\": [ {\n"
687 " \"name\": [\n"
688 " { \"service\": \"TestServ\", \"method\": \"TestMethod\" }\n"
689 " ],\n"
690 " \"waitForReady\": true\n"
691 " } ]\n"
692 "}";
693 grpc_error* error = GRPC_ERROR_NONE;
694 auto svc_cfg = ServiceConfig::Create(test_json, &error);
695 ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error);
696 const auto* vector_ptr = svc_cfg->GetMethodParsedConfigVector(
697 grpc_slice_from_static_string("/TestServ/TestMethod"));
698 ASSERT_NE(vector_ptr, nullptr);
699 auto parsed_config = ((*vector_ptr)[0]).get();
700 ASSERT_TRUE(
701 (static_cast<grpc_core::internal::ClientChannelMethodParsedConfig*>(
702 parsed_config))
703 ->wait_for_ready()
704 .has_value());
705 EXPECT_TRUE(
706 (static_cast<grpc_core::internal::ClientChannelMethodParsedConfig*>(
707 parsed_config))
708 ->wait_for_ready()
709 .value());
710 }
711
TEST_F(ClientChannelParserTest,InvalidWaitForReady)712 TEST_F(ClientChannelParserTest, InvalidWaitForReady) {
713 const char* test_json =
714 "{\n"
715 " \"methodConfig\": [ {\n"
716 " \"name\": [\n"
717 " { \"service\": \"service\", \"method\": \"method\" }\n"
718 " ],\n"
719 " \"waitForReady\": \"true\"\n"
720 " } ]\n"
721 "}";
722 grpc_error* error = GRPC_ERROR_NONE;
723 auto svc_cfg = ServiceConfig::Create(test_json, &error);
724 std::regex regex(
725 "Service config parsing error.*referenced_errors.*"
726 "Method Params.*referenced_errors.*"
727 "methodConfig.*referenced_errors.*"
728 "Client channel parser.*referenced_errors.*"
729 "field:waitForReady error:Type should be true/false");
730 VerifyRegexMatch(error, regex);
731 }
732
TEST_F(ClientChannelParserTest,ValidRetryPolicy)733 TEST_F(ClientChannelParserTest, ValidRetryPolicy) {
734 const char* test_json =
735 "{\n"
736 " \"methodConfig\": [ {\n"
737 " \"name\": [\n"
738 " { \"service\": \"TestServ\", \"method\": \"TestMethod\" }\n"
739 " ],\n"
740 " \"retryPolicy\": {\n"
741 " \"maxAttempts\": 3,\n"
742 " \"initialBackoff\": \"1s\",\n"
743 " \"maxBackoff\": \"120s\",\n"
744 " \"backoffMultiplier\": 1.6,\n"
745 " \"retryableStatusCodes\": [ \"ABORTED\" ]\n"
746 " }\n"
747 " } ]\n"
748 "}";
749 grpc_error* error = GRPC_ERROR_NONE;
750 auto svc_cfg = ServiceConfig::Create(test_json, &error);
751 ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error);
752 const auto* vector_ptr = svc_cfg->GetMethodParsedConfigVector(
753 grpc_slice_from_static_string("/TestServ/TestMethod"));
754 ASSERT_NE(vector_ptr, nullptr);
755 const auto* parsed_config =
756 static_cast<grpc_core::internal::ClientChannelMethodParsedConfig*>(
757 ((*vector_ptr)[0]).get());
758 ASSERT_NE(parsed_config->retry_policy(), nullptr);
759 EXPECT_EQ(parsed_config->retry_policy()->max_attempts, 3);
760 EXPECT_EQ(parsed_config->retry_policy()->initial_backoff, 1000);
761 EXPECT_EQ(parsed_config->retry_policy()->max_backoff, 120000);
762 EXPECT_EQ(parsed_config->retry_policy()->backoff_multiplier, 1.6f);
763 EXPECT_TRUE(parsed_config->retry_policy()->retryable_status_codes.Contains(
764 GRPC_STATUS_ABORTED));
765 }
766
TEST_F(ClientChannelParserTest,InvalidRetryPolicyMaxAttempts)767 TEST_F(ClientChannelParserTest, InvalidRetryPolicyMaxAttempts) {
768 const char* test_json =
769 "{\n"
770 " \"methodConfig\": [ {\n"
771 " \"name\": [\n"
772 " { \"service\": \"TestServ\", \"method\": \"TestMethod\" }\n"
773 " ],\n"
774 " \"retryPolicy\": {\n"
775 " \"maxAttempts\": 1,\n"
776 " \"initialBackoff\": \"1s\",\n"
777 " \"maxBackoff\": \"120s\",\n"
778 " \"backoffMultiplier\": 1.6,\n"
779 " \"retryableStatusCodes\": [ \"ABORTED\" ]\n"
780 " }\n"
781 " } ]\n"
782 "}";
783 grpc_error* error = GRPC_ERROR_NONE;
784 auto svc_cfg = ServiceConfig::Create(test_json, &error);
785 std::regex regex(
786 "Service config parsing error.*referenced_errors.*"
787 "Method Params.*referenced_errors.*"
788 "methodConfig.*referenced_errors.*"
789 "Client channel parser.*referenced_errors.*"
790 "retryPolicy.*referenced_errors.*"
791 "field:maxAttempts error:should be at least 2");
792 VerifyRegexMatch(error, regex);
793 }
794
TEST_F(ClientChannelParserTest,InvalidRetryPolicyInitialBackoff)795 TEST_F(ClientChannelParserTest, InvalidRetryPolicyInitialBackoff) {
796 const char* test_json =
797 "{\n"
798 " \"methodConfig\": [ {\n"
799 " \"name\": [\n"
800 " { \"service\": \"TestServ\", \"method\": \"TestMethod\" }\n"
801 " ],\n"
802 " \"retryPolicy\": {\n"
803 " \"maxAttempts\": 1,\n"
804 " \"initialBackoff\": \"1sec\",\n"
805 " \"maxBackoff\": \"120s\",\n"
806 " \"backoffMultiplier\": 1.6,\n"
807 " \"retryableStatusCodes\": [ \"ABORTED\" ]\n"
808 " }\n"
809 " } ]\n"
810 "}";
811 grpc_error* error = GRPC_ERROR_NONE;
812 auto svc_cfg = ServiceConfig::Create(test_json, &error);
813 std::regex regex(
814 "Service config parsing error.*referenced_errors.*"
815 "Method Params.*referenced_errors.*"
816 "methodConfig.*referenced_errors.*"
817 "Client channel parser.*referenced_errors.*"
818 "retryPolicy.*referenced_errors.*"
819 "field:initialBackoff error:Failed to parse");
820 VerifyRegexMatch(error, regex);
821 }
822
TEST_F(ClientChannelParserTest,InvalidRetryPolicyMaxBackoff)823 TEST_F(ClientChannelParserTest, InvalidRetryPolicyMaxBackoff) {
824 const char* test_json =
825 "{\n"
826 " \"methodConfig\": [ {\n"
827 " \"name\": [\n"
828 " { \"service\": \"TestServ\", \"method\": \"TestMethod\" }\n"
829 " ],\n"
830 " \"retryPolicy\": {\n"
831 " \"maxAttempts\": 1,\n"
832 " \"initialBackoff\": \"1s\",\n"
833 " \"maxBackoff\": \"120sec\",\n"
834 " \"backoffMultiplier\": 1.6,\n"
835 " \"retryableStatusCodes\": [ \"ABORTED\" ]\n"
836 " }\n"
837 " } ]\n"
838 "}";
839 grpc_error* error = GRPC_ERROR_NONE;
840 auto svc_cfg = ServiceConfig::Create(test_json, &error);
841 std::regex regex(
842 "Service config parsing error.*referenced_errors.*"
843 "Method Params.*referenced_errors.*"
844 "methodConfig.*referenced_errors.*"
845 "Client channel parser.*referenced_errors.*"
846 "retryPolicy.*referenced_errors.*"
847 "field:maxBackoff error:failed to parse");
848 VerifyRegexMatch(error, regex);
849 }
850
TEST_F(ClientChannelParserTest,InvalidRetryPolicyBackoffMultiplier)851 TEST_F(ClientChannelParserTest, InvalidRetryPolicyBackoffMultiplier) {
852 const char* test_json =
853 "{\n"
854 " \"methodConfig\": [ {\n"
855 " \"name\": [\n"
856 " { \"service\": \"TestServ\", \"method\": \"TestMethod\" }\n"
857 " ],\n"
858 " \"retryPolicy\": {\n"
859 " \"maxAttempts\": 1,\n"
860 " \"initialBackoff\": \"1s\",\n"
861 " \"maxBackoff\": \"120s\",\n"
862 " \"backoffMultiplier\": \"1.6\",\n"
863 " \"retryableStatusCodes\": [ \"ABORTED\" ]\n"
864 " }\n"
865 " } ]\n"
866 "}";
867 grpc_error* error = GRPC_ERROR_NONE;
868 auto svc_cfg = ServiceConfig::Create(test_json, &error);
869 std::regex regex(
870 "Service config parsing error.*referenced_errors.*"
871 "Method Params.*referenced_errors.*"
872 "methodConfig.*referenced_errors.*"
873 "Client channel parser.*referenced_errors.*"
874 "retryPolicy.*referenced_errors.*"
875 "field:backoffMultiplier error:should be of type number");
876 VerifyRegexMatch(error, regex);
877 }
878
TEST_F(ClientChannelParserTest,InvalidRetryPolicyRetryableStatusCodes)879 TEST_F(ClientChannelParserTest, InvalidRetryPolicyRetryableStatusCodes) {
880 const char* test_json =
881 "{\n"
882 " \"methodConfig\": [ {\n"
883 " \"name\": [\n"
884 " { \"service\": \"TestServ\", \"method\": \"TestMethod\" }\n"
885 " ],\n"
886 " \"retryPolicy\": {\n"
887 " \"maxAttempts\": 1,\n"
888 " \"initialBackoff\": \"1s\",\n"
889 " \"maxBackoff\": \"120s\",\n"
890 " \"backoffMultiplier\": \"1.6\",\n"
891 " \"retryableStatusCodes\": []\n"
892 " }\n"
893 " } ]\n"
894 "}";
895 grpc_error* error = GRPC_ERROR_NONE;
896 auto svc_cfg = ServiceConfig::Create(test_json, &error);
897 std::regex regex(
898 "Service config parsing error.*referenced_errors.*"
899 "Method Params.*referenced_errors.*"
900 "methodConfig.*referenced_errors.*"
901 "Client channel parser.*referenced_errors.*"
902 "retryPolicy.*referenced_errors.*"
903 "field:retryableStatusCodes error:should be non-empty");
904 VerifyRegexMatch(error, regex);
905 }
906
TEST_F(ClientChannelParserTest,ValidHealthCheck)907 TEST_F(ClientChannelParserTest, ValidHealthCheck) {
908 const char* test_json =
909 "{\n"
910 " \"healthCheckConfig\": {\n"
911 " \"serviceName\": \"health_check_service_name\"\n"
912 " }\n"
913 "}";
914 grpc_error* error = GRPC_ERROR_NONE;
915 auto svc_cfg = ServiceConfig::Create(test_json, &error);
916 ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error);
917 const auto* parsed_config =
918 static_cast<grpc_core::internal::ClientChannelGlobalParsedConfig*>(
919 svc_cfg->GetGlobalParsedConfig(0));
920 ASSERT_NE(parsed_config, nullptr);
921 EXPECT_STREQ(parsed_config->health_check_service_name(),
922 "health_check_service_name");
923 }
924
TEST_F(ClientChannelParserTest,InvalidHealthCheckMultipleEntries)925 TEST_F(ClientChannelParserTest, InvalidHealthCheckMultipleEntries) {
926 const char* test_json =
927 "{\n"
928 " \"healthCheckConfig\": {\n"
929 " \"serviceName\": \"health_check_service_name\"\n"
930 " },\n"
931 " \"healthCheckConfig\": {\n"
932 " \"serviceName\": \"health_check_service_name1\"\n"
933 " }\n"
934 "}";
935 grpc_error* error = GRPC_ERROR_NONE;
936 auto svc_cfg = ServiceConfig::Create(test_json, &error);
937 std::regex regex(
938 "JSON parsing failed.*referenced_errors.*"
939 "duplicate key \"healthCheckConfig\" at index 104");
940 VerifyRegexMatch(error, regex);
941 }
942
943 class MessageSizeParserTest : public ::testing::Test {
944 protected:
SetUp()945 void SetUp() override {
946 ServiceConfigParser::Shutdown();
947 ServiceConfigParser::Init();
948 EXPECT_EQ(ServiceConfigParser::RegisterParser(
949 absl::make_unique<MessageSizeParser>()),
950 0);
951 }
952 };
953
TEST_F(MessageSizeParserTest,Valid)954 TEST_F(MessageSizeParserTest, Valid) {
955 const char* test_json =
956 "{\n"
957 " \"methodConfig\": [ {\n"
958 " \"name\": [\n"
959 " { \"service\": \"TestServ\", \"method\": \"TestMethod\" }\n"
960 " ],\n"
961 " \"maxRequestMessageBytes\": 1024,\n"
962 " \"maxResponseMessageBytes\": 1024\n"
963 " } ]\n"
964 "}";
965 grpc_error* error = GRPC_ERROR_NONE;
966 auto svc_cfg = ServiceConfig::Create(test_json, &error);
967 ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error);
968 const auto* vector_ptr = svc_cfg->GetMethodParsedConfigVector(
969 grpc_slice_from_static_string("/TestServ/TestMethod"));
970 ASSERT_NE(vector_ptr, nullptr);
971 auto parsed_config =
972 static_cast<MessageSizeParsedConfig*>(((*vector_ptr)[0]).get());
973 ASSERT_NE(parsed_config, nullptr);
974 EXPECT_EQ(parsed_config->limits().max_send_size, 1024);
975 EXPECT_EQ(parsed_config->limits().max_recv_size, 1024);
976 }
977
TEST_F(MessageSizeParserTest,InvalidMaxRequestMessageBytes)978 TEST_F(MessageSizeParserTest, InvalidMaxRequestMessageBytes) {
979 const char* test_json =
980 "{\n"
981 " \"methodConfig\": [ {\n"
982 " \"name\": [\n"
983 " { \"service\": \"TestServ\", \"method\": \"TestMethod\" }\n"
984 " ],\n"
985 " \"maxRequestMessageBytes\": -1024\n"
986 " } ]\n"
987 "}";
988 grpc_error* error = GRPC_ERROR_NONE;
989 auto svc_cfg = ServiceConfig::Create(test_json, &error);
990 std::regex regex(
991 "Service config parsing error.*referenced_errors.*"
992 "Method Params.*referenced_errors.*"
993 "methodConfig.*referenced_errors.*"
994 "Message size parser.*referenced_errors.*"
995 "field:maxRequestMessageBytes error:should be non-negative");
996 VerifyRegexMatch(error, regex);
997 }
998
TEST_F(MessageSizeParserTest,InvalidMaxResponseMessageBytes)999 TEST_F(MessageSizeParserTest, InvalidMaxResponseMessageBytes) {
1000 const char* test_json =
1001 "{\n"
1002 " \"methodConfig\": [ {\n"
1003 " \"name\": [\n"
1004 " { \"service\": \"TestServ\", \"method\": \"TestMethod\" }\n"
1005 " ],\n"
1006 " \"maxResponseMessageBytes\": {}\n"
1007 " } ]\n"
1008 "}";
1009 grpc_error* error = GRPC_ERROR_NONE;
1010 auto svc_cfg = ServiceConfig::Create(test_json, &error);
1011 std::regex regex(
1012 "Service config parsing error.*referenced_errors.*"
1013 "Method Params.*referenced_errors.*"
1014 "methodConfig.*referenced_errors.*"
1015 "Message size parser.*referenced_errors.*"
1016 "field:maxResponseMessageBytes error:should be of type "
1017 "number");
1018 VerifyRegexMatch(error, regex);
1019 }
1020
1021 } // namespace testing
1022 } // namespace grpc_core
1023
main(int argc,char ** argv)1024 int main(int argc, char** argv) {
1025 // Regexes don't work in old libstdc++ versions, so just skip testing in those
1026 // cases
1027 #if defined(__GLIBCXX__) && (__GLIBCXX__ <= 20150623)
1028 gpr_log(GPR_ERROR,
1029 "Skipping service_config_test since std::regex is not supported on "
1030 "this system.");
1031 return 0;
1032 #endif
1033 ::testing::InitGoogleTest(&argc, argv);
1034 grpc::testing::TestEnvironment env(argc, argv);
1035 grpc_init();
1036 int ret = RUN_ALL_TESTS();
1037 grpc_shutdown();
1038 return ret;
1039 }
1040