• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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