21 #include <gmock/gmock.h>
22 #include <gtest/gtest.h>
24 #include "absl/strings/str_cat.h"
46 #define GRPC_ARG_DISABLE_PARSING "disable_parsing"
49 #ifdef GRPC_ERROR_IS_ABSEIL_STATUS
50 #define CHILD_ERROR_TAG ".*children.*"
52 #define CHILD_ERROR_TAG ".*referenced_errors.*"
89 return absl::make_unique<TestParsedConfig1>(
value);
95 return "global_param value type should be a number";
99 return "global_param value type should be non-negative";
127 return absl::make_unique<TestParsedConfig1>(
value);
133 return "method_param value type should be a number";
137 return "method_param value type should be non-negative";
164 static const char*
MethodError() {
return "ErrorParser : methodError"; }
166 static const char*
GlobalError() {
return "ErrorParser : globalError"; }
178 builder->service_config_parser()->RegisterParser(
179 absl::make_unique<TestParser1>());
180 builder->service_config_parser()->RegisterParser(
181 absl::make_unique<TestParser2>());
193 const char* test_json =
"";
202 const char* test_json =
"{}";
209 const char* test_json =
210 "{\"methodConfig\": ["
211 " {\"method_param\":1},"
212 " {\"name\":[], \"method_param\":1},"
213 " {\"name\":[{\"service\":\"TestServ\"}], \"method_param\":2}"
218 const auto* vector_ptr = svc_cfg->GetMethodParsedConfigVector(
221 auto parsed_config = ((*vector_ptr)[1]).
get();
226 const char* test_json =
227 "{\"methodConfig\": ["
228 " {\"name\":[{\"service\":\"TestServ\"}]},"
229 " {\"name\":[{\"service\":\"TestServ\"}]}"
237 "multiple method configs with same name"));
242 const char* test_json =
243 "{\"methodConfig\": ["
244 " {\"name\":[{\"service\":\"TestServ\",\"method\":null}]},"
245 " {\"name\":[{\"service\":\"TestServ\"}]}"
253 "multiple method configs with same name"));
258 const char* test_json =
259 "{\"methodConfig\": ["
260 " {\"name\":[{\"service\":\"TestServ\",\"method\":\"\"}]},"
261 " {\"name\":[{\"service\":\"TestServ\"}]}"
269 "multiple method configs with same name"));
274 const char* test_json =
275 "{\"methodConfig\": ["
285 "multiple default method configs"));
290 const char* test_json =
291 "{\"methodConfig\": ["
292 " {\"name\":[{\"service\":null}]},"
301 "multiple default method configs"));
306 const char* test_json =
307 "{\"methodConfig\": ["
308 " {\"name\":[{\"service\":\"\"}]},"
317 "multiple default method configs"));
322 const char* test_json =
323 "{\"methodConfig\": [{\"name\":[{\"service\":\"TestServ\"}]}]}";
330 const char* test_json =
"{\"global_param\":5}";
337 EXPECT_EQ(svc_cfg->GetMethodParsedConfigVector(
343 const char* test_json =
"{\"global_param\":1000}";
356 const char* test_json =
"{\"global_param\":5}";
360 EXPECT_EQ(svc_cfg->GetGlobalParsedConfig(0),
nullptr);
364 const char* test_json =
"{\"global_param\":\"5\"}";
376 const char* test_json =
"{\"global_param\":-5}";
388 const char* test_json =
389 "{\"methodConfig\": [{\"name\":[{\"service\":\"TestServ\"}], "
390 "\"method_param\":5}]}";
394 const auto* vector_ptr = svc_cfg->GetMethodParsedConfigVector(
397 auto parsed_config = ((*vector_ptr)[1]).
get();
405 const char* test_json =
406 "{\"methodConfig\": [{\"name\":[{\"service\":\"TestServ\"}], "
407 "\"method_param\":5}]}";
411 const auto* vector_ptr = svc_cfg->GetMethodParsedConfigVector(
414 auto parsed_config = ((*vector_ptr)[1]).
get();
419 const char* test_json =
420 "{\"methodConfig\": [{\"name\":[{\"service\":\"TestServ\"}], "
421 "\"method_param\":\"5\"}]}";
434 const char* test_json =
435 "{\"methodConfig\": [{\"name\":[{\"service\":\"TestServ\"}], "
436 "\"method_param\":-5}]}";
448 TEST(ServiceConfigParserTest, DoubleRegistration) {
453 builder->service_config_parser()->RegisterParser(
454 absl::make_unique<ErrorParser>(
"xyzabc"));
455 builder->service_config_parser()->RegisterParser(
456 absl::make_unique<ErrorParser>(
"xyzabc"));
458 "xyzabc.*already registered");
468 builder->service_config_parser()->RegisterParser(
469 absl::make_unique<ErrorParser>(
"ep1"));
470 builder->service_config_parser()->RegisterParser(
471 absl::make_unique<ErrorParser>(
"ep2"));
483 const char* test_json =
"{}";
496 const char* test_json =
"{\"methodConfig\": [{}]}";
520 builder->service_config_parser()->RegisterParser(
521 absl::make_unique<internal::ClientChannelServiceConfigParser>());
530 const char* test_json =
"{\"loadBalancingConfig\": [{\"pick_first\":{}}]}";
534 const auto* parsed_config =
536 svc_cfg->GetGlobalParsedConfig(0));
542 const char* test_json =
543 "{\"loadBalancingConfig\": [{\"round_robin\":{}}, {}]}";
548 svc_cfg->GetGlobalParsedConfig(0));
554 const char* test_json =
555 "{\"loadBalancingConfig\": "
556 "[{\"grpclb\":{\"childPolicy\":[{\"pick_first\":{}}]}}]}";
560 const auto* parsed_config =
562 svc_cfg->GetGlobalParsedConfig(0));
568 const char* test_json =
570 " \"loadBalancingConfig\":[\n"
571 " { \"does_not_exist\":{} },\n"
572 " { \"xds_cluster_resolver_experimental\":{\n"
573 " \"discoveryMechanisms\": [\n"
574 " { \"clusterName\": \"foo\",\n"
575 " \"type\": \"EDS\"\n"
583 const auto* parsed_config =
585 svc_cfg->GetGlobalParsedConfig(0));
587 EXPECT_STREQ(lb_config->name(),
"xds_cluster_resolver_experimental");
591 const char* test_json =
"{\"loadBalancingConfig\": [{\"unknown\":{}}]}";
600 "No known policies in list: unknown"));
605 const char* test_json =
606 "{\"loadBalancingConfig\": ["
607 " {\"grpclb\":{\"childPolicy\":1}},"
608 " {\"round_robin\":{}}"
624 const char* test_json =
"{\"loadBalancingPolicy\":\"pick_first\"}";
628 const auto* parsed_config =
630 svc_cfg->GetGlobalParsedConfig(0));
631 EXPECT_EQ(parsed_config->parsed_deprecated_lb_policy(),
"pick_first");
635 const char* test_json =
"{\"loadBalancingPolicy\":\"PICK_FIRST\"}";
639 const auto* parsed_config =
641 svc_cfg->GetGlobalParsedConfig(0));
642 EXPECT_EQ(parsed_config->parsed_deprecated_lb_policy(),
"pick_first");
646 const char* test_json =
"{\"loadBalancingPolicy\":\"unknown\"}";
654 "field:loadBalancingPolicy error:Unknown lb policy"));
659 const char* test_json =
660 "{\"loadBalancingPolicy\":\"xds_cluster_resolver_experimental\"}";
668 "field:loadBalancingPolicy "
669 "error:xds_cluster_resolver_experimental requires "
670 "a config. Please use loadBalancingConfig instead."));
675 const char* test_json =
677 " \"methodConfig\": [ {\n"
679 " { \"service\": \"TestServ\", \"method\": \"TestMethod\" }\n"
681 " \"timeout\": \"5s\"\n"
687 const auto* vector_ptr = svc_cfg->GetMethodParsedConfigVector(
690 auto parsed_config = ((*vector_ptr)[0]).
get();
698 const char* test_json =
700 " \"methodConfig\": [ {\n"
702 " { \"service\": \"service\", \"method\": \"method\" }\n"
704 " \"timeout\": \"5sec\"\n"
714 "field:timeout error:type should be STRING of the form given "
715 "by google.proto.Duration"));
720 const char* test_json =
722 " \"methodConfig\": [ {\n"
724 " { \"service\": \"TestServ\", \"method\": \"TestMethod\" }\n"
726 " \"waitForReady\": true\n"
732 const auto* vector_ptr = svc_cfg->GetMethodParsedConfigVector(
735 auto parsed_config = ((*vector_ptr)[0]).
get();
747 const char* test_json =
749 " \"methodConfig\": [ {\n"
751 " { \"service\": \"service\", \"method\": \"method\" }\n"
753 " \"waitForReady\": \"true\"\n"
763 "field:waitForReady error:Type should be true/false"));
768 const char* test_json =
770 " \"healthCheckConfig\": {\n"
771 " \"serviceName\": \"health_check_service_name\"\n"
777 const auto* parsed_config =
779 svc_cfg->GetGlobalParsedConfig(0));
781 EXPECT_EQ(parsed_config->health_check_service_name(),
782 "health_check_service_name");
786 const char* test_json =
788 " \"healthCheckConfig\": {\n"
789 " \"serviceName\": \"health_check_service_name\"\n"
791 " \"healthCheckConfig\": {\n"
792 " \"serviceName\": \"health_check_service_name1\"\n"
800 "duplicate key \"healthCheckConfig\" at index 104"));
814 builder->service_config_parser()->RegisterParser(
815 absl::make_unique<internal::RetryServiceConfigParser>());
824 const char* test_json =
826 " \"retryThrottling\": {\n"
827 " \"maxTokens\": 2,\n"
828 " \"tokenRatio\": 1.0\n"
835 svc_cfg->GetGlobalParsedConfig(0));
837 EXPECT_EQ(parsed_config->max_milli_tokens(), 2000);
838 EXPECT_EQ(parsed_config->milli_token_ratio(), 1000);
842 const char* test_json =
844 " \"retryThrottling\": {\n"
854 "field:retryThrottling field:maxTokens error:Not found"
855 ".*field:retryThrottling field:tokenRatio error:Not found"));
860 const char* test_json =
862 " \"retryThrottling\": {\n"
863 " \"maxTokens\": -2,\n"
864 " \"tokenRatio\": 1.0\n"
874 "field:retryThrottling field:maxTokens error:should "
875 "be greater than zero"));
880 const char* test_json =
882 " \"retryThrottling\": {\n"
883 " \"maxTokens\": 2,\n"
884 " \"tokenRatio\": -1\n"
894 "field:retryThrottling field:tokenRatio "
895 "error:Failed parsing"));
900 const char* test_json =
902 " \"methodConfig\": [ {\n"
904 " { \"service\": \"TestServ\", \"method\": \"TestMethod\" }\n"
906 " \"retryPolicy\": {\n"
907 " \"maxAttempts\": 3,\n"
908 " \"initialBackoff\": \"1s\",\n"
909 " \"maxBackoff\": \"120s\",\n"
910 " \"backoffMultiplier\": 1.6,\n"
911 " \"retryableStatusCodes\": [ \"ABORTED\" ]\n"
918 const auto* vector_ptr = svc_cfg->GetMethodParsedConfigVector(
921 const auto* parsed_config =
924 EXPECT_EQ(parsed_config->max_attempts(), 3);
927 EXPECT_EQ(parsed_config->backoff_multiplier(), 1.6f);
928 EXPECT_EQ(parsed_config->per_attempt_recv_timeout(), absl::nullopt);
934 const char* test_json =
936 " \"methodConfig\": [ {\n"
938 " { \"service\": \"TestServ\", \"method\": \"TestMethod\" }\n"
940 " \"retryPolicy\": 5\n"
949 "field:retryPolicy error:should be of type object"));
954 const char* test_json =
956 " \"methodConfig\": [ {\n"
958 " { \"service\": \"TestServ\", \"method\": \"TestMethod\" }\n"
960 " \"retryPolicy\": {\n"
961 " \"retryableStatusCodes\": [ \"ABORTED\" ]\n"
972 ".*field:maxAttempts error:required field missing"
973 ".*field:initialBackoff error:does not exist"
974 ".*field:maxBackoff error:does not exist"
975 ".*field:backoffMultiplier error:required field missing"));
980 const char* test_json =
982 " \"methodConfig\": [ {\n"
984 " { \"service\": \"TestServ\", \"method\": \"TestMethod\" }\n"
986 " \"retryPolicy\": {\n"
987 " \"maxAttempts\": \"FOO\",\n"
988 " \"initialBackoff\": \"1s\",\n"
989 " \"maxBackoff\": \"120s\",\n"
990 " \"backoffMultiplier\": 1.6,\n"
991 " \"retryableStatusCodes\": [ \"ABORTED\" ]\n"
1002 "field:maxAttempts error:should be of type number"));
1007 const char* test_json =
1009 " \"methodConfig\": [ {\n"
1011 " { \"service\": \"TestServ\", \"method\": \"TestMethod\" }\n"
1013 " \"retryPolicy\": {\n"
1014 " \"maxAttempts\": 1,\n"
1015 " \"initialBackoff\": \"1s\",\n"
1016 " \"maxBackoff\": \"120s\",\n"
1017 " \"backoffMultiplier\": 1.6,\n"
1018 " \"retryableStatusCodes\": [ \"ABORTED\" ]\n"
1029 "field:maxAttempts error:should be at least 2"));
1034 const char* test_json =
1036 " \"methodConfig\": [ {\n"
1038 " { \"service\": \"TestServ\", \"method\": \"TestMethod\" }\n"
1040 " \"retryPolicy\": {\n"
1041 " \"maxAttempts\": 2,\n"
1042 " \"initialBackoff\": \"1sec\",\n"
1043 " \"maxBackoff\": \"120s\",\n"
1044 " \"backoffMultiplier\": 1.6,\n"
1045 " \"retryableStatusCodes\": [ \"ABORTED\" ]\n"
1056 "field:initialBackoff error:type should be STRING of the "
1057 "form given by google.proto.Duration"));
1062 const char* test_json =
1064 " \"methodConfig\": [ {\n"
1066 " { \"service\": \"TestServ\", \"method\": \"TestMethod\" }\n"
1068 " \"retryPolicy\": {\n"
1069 " \"maxAttempts\": 2,\n"
1070 " \"initialBackoff\": \"0s\",\n"
1071 " \"maxBackoff\": \"120s\",\n"
1072 " \"backoffMultiplier\": 1.6,\n"
1073 " \"retryableStatusCodes\": [ \"ABORTED\" ]\n"
1084 "field:initialBackoff error:must be greater than 0"));
1089 const char* test_json =
1091 " \"methodConfig\": [ {\n"
1093 " { \"service\": \"TestServ\", \"method\": \"TestMethod\" }\n"
1095 " \"retryPolicy\": {\n"
1096 " \"maxAttempts\": 2,\n"
1097 " \"initialBackoff\": \"1s\",\n"
1098 " \"maxBackoff\": \"120sec\",\n"
1099 " \"backoffMultiplier\": 1.6,\n"
1100 " \"retryableStatusCodes\": [ \"ABORTED\" ]\n"
1111 "field:maxBackoff error:type should be STRING of the form "
1112 "given by google.proto.Duration"));
1117 const char* test_json =
1119 " \"methodConfig\": [ {\n"
1121 " { \"service\": \"TestServ\", \"method\": \"TestMethod\" }\n"
1123 " \"retryPolicy\": {\n"
1124 " \"maxAttempts\": 2,\n"
1125 " \"initialBackoff\": \"1s\",\n"
1126 " \"maxBackoff\": \"0s\",\n"
1127 " \"backoffMultiplier\": 1.6,\n"
1128 " \"retryableStatusCodes\": [ \"ABORTED\" ]\n"
1139 "field:maxBackoff error:must be greater than 0"));
1144 const char* test_json =
1146 " \"methodConfig\": [ {\n"
1148 " { \"service\": \"TestServ\", \"method\": \"TestMethod\" }\n"
1150 " \"retryPolicy\": {\n"
1151 " \"maxAttempts\": 2,\n"
1152 " \"initialBackoff\": \"1s\",\n"
1153 " \"maxBackoff\": \"120s\",\n"
1154 " \"backoffMultiplier\": \"1.6\",\n"
1155 " \"retryableStatusCodes\": [ \"ABORTED\" ]\n"
1166 "field:backoffMultiplier error:should be of type number"));
1171 const char* test_json =
1173 " \"methodConfig\": [ {\n"
1175 " { \"service\": \"TestServ\", \"method\": \"TestMethod\" }\n"
1177 " \"retryPolicy\": {\n"
1178 " \"maxAttempts\": 2,\n"
1179 " \"initialBackoff\": \"1s\",\n"
1180 " \"maxBackoff\": \"120s\",\n"
1181 " \"backoffMultiplier\": 0,\n"
1182 " \"retryableStatusCodes\": [ \"ABORTED\" ]\n"
1193 "field:backoffMultiplier error:must be greater than 0"));
1198 const char* test_json =
1200 " \"methodConfig\": [ {\n"
1202 " { \"service\": \"TestServ\", \"method\": \"TestMethod\" }\n"
1204 " \"retryPolicy\": {\n"
1205 " \"maxAttempts\": 2,\n"
1206 " \"initialBackoff\": \"1s\",\n"
1207 " \"maxBackoff\": \"120s\",\n"
1208 " \"backoffMultiplier\": \"1.6\",\n"
1209 " \"retryableStatusCodes\": []\n"
1220 "field:retryableStatusCodes error:must be non-empty"));
1225 const char* test_json =
1227 " \"methodConfig\": [ {\n"
1229 " { \"service\": \"TestServ\", \"method\": \"TestMethod\" }\n"
1231 " \"retryPolicy\": {\n"
1232 " \"maxAttempts\": 2,\n"
1233 " \"initialBackoff\": \"1s\",\n"
1234 " \"maxBackoff\": \"120s\",\n"
1235 " \"backoffMultiplier\": \"1.6\",\n"
1236 " \"retryableStatusCodes\": 0\n"
1247 "field:retryableStatusCodes error:must be of type array"));
1252 const char* test_json =
1254 " \"methodConfig\": [ {\n"
1256 " { \"service\": \"TestServ\", \"method\": \"TestMethod\" }\n"
1258 " \"retryPolicy\": {\n"
1259 " \"maxAttempts\": 2,\n"
1260 " \"initialBackoff\": \"1s\",\n"
1261 " \"maxBackoff\": \"120s\",\n"
1262 " \"backoffMultiplier\": \"1.6\",\n"
1263 " \"retryableStatusCodes\": [\"FOO\", 2]\n"
1274 "error:failed to parse status code"
1275 ".*field:retryableStatusCodes "
1276 "error:status codes should be of type string"));
1281 const char* test_json =
1283 " \"methodConfig\": [ {\n"
1285 " { \"service\": \"TestServ\", \"method\": \"TestMethod\" }\n"
1287 " \"retryPolicy\": {\n"
1288 " \"maxAttempts\": 2,\n"
1289 " \"initialBackoff\": \"1s\",\n"
1290 " \"maxBackoff\": \"120s\",\n"
1291 " \"backoffMultiplier\": 1.6,\n"
1292 " \"perAttemptRecvTimeout\": \"1s\",\n"
1293 " \"retryableStatusCodes\": [\"ABORTED\"]\n"
1303 const auto* vector_ptr = svc_cfg->GetMethodParsedConfigVector(
1306 const auto* parsed_config =
1309 EXPECT_EQ(parsed_config->max_attempts(), 2);
1312 EXPECT_EQ(parsed_config->backoff_multiplier(), 1.6f);
1319 ValidRetryPolicyWithPerAttemptRecvTimeoutIgnoredWhenHedgingDisabled) {
1320 const char* test_json =
1322 " \"methodConfig\": [ {\n"
1324 " { \"service\": \"TestServ\", \"method\": \"TestMethod\" }\n"
1326 " \"retryPolicy\": {\n"
1327 " \"maxAttempts\": 2,\n"
1328 " \"initialBackoff\": \"1s\",\n"
1329 " \"maxBackoff\": \"120s\",\n"
1330 " \"backoffMultiplier\": 1.6,\n"
1331 " \"perAttemptRecvTimeout\": \"1s\",\n"
1332 " \"retryableStatusCodes\": [\"ABORTED\"]\n"
1339 const auto* vector_ptr = svc_cfg->GetMethodParsedConfigVector(
1342 const auto* parsed_config =
1345 EXPECT_EQ(parsed_config->max_attempts(), 2);
1348 EXPECT_EQ(parsed_config->backoff_multiplier(), 1.6f);
1349 EXPECT_EQ(parsed_config->per_attempt_recv_timeout(), absl::nullopt);
1355 ValidRetryPolicyWithPerAttemptRecvTimeoutAndUnsetRetryableStatusCodes) {
1356 const char* test_json =
1358 " \"methodConfig\": [ {\n"
1360 " { \"service\": \"TestServ\", \"method\": \"TestMethod\" }\n"
1362 " \"retryPolicy\": {\n"
1363 " \"maxAttempts\": 2,\n"
1364 " \"initialBackoff\": \"1s\",\n"
1365 " \"maxBackoff\": \"120s\",\n"
1366 " \"backoffMultiplier\": 1.6,\n"
1367 " \"perAttemptRecvTimeout\": \"1s\"\n"
1377 const auto* vector_ptr = svc_cfg->GetMethodParsedConfigVector(
1380 const auto* parsed_config =
1383 EXPECT_EQ(parsed_config->max_attempts(), 2);
1386 EXPECT_EQ(parsed_config->backoff_multiplier(), 1.6f);
1388 EXPECT_TRUE(parsed_config->retryable_status_codes().Empty());
1392 const char* test_json =
1394 " \"methodConfig\": [ {\n"
1396 " { \"service\": \"TestServ\", \"method\": \"TestMethod\" }\n"
1398 " \"retryPolicy\": {\n"
1399 " \"maxAttempts\": 2,\n"
1400 " \"initialBackoff\": \"1s\",\n"
1401 " \"maxBackoff\": \"120s\",\n"
1402 " \"backoffMultiplier\": \"1.6\",\n"
1403 " \"perAttemptRecvTimeout\": \"1sec\",\n"
1404 " \"retryableStatusCodes\": [\"ABORTED\"]\n"
1418 "field:perAttemptRecvTimeout error:type must be STRING "
1419 "of the form given by google.proto.Duration."));
1424 const char* test_json =
1426 " \"methodConfig\": [ {\n"
1428 " { \"service\": \"TestServ\", \"method\": \"TestMethod\" }\n"
1430 " \"retryPolicy\": {\n"
1431 " \"maxAttempts\": 2,\n"
1432 " \"initialBackoff\": \"1s\",\n"
1433 " \"maxBackoff\": \"120s\",\n"
1434 " \"backoffMultiplier\": \"1.6\",\n"
1435 " \"perAttemptRecvTimeout\": 1,\n"
1436 " \"retryableStatusCodes\": [\"ABORTED\"]\n"
1450 "field:perAttemptRecvTimeout error:type must be STRING "
1451 "of the form given by google.proto.Duration."));
1456 const char* test_json =
1458 " \"methodConfig\": [ {\n"
1460 " { \"service\": \"TestServ\", \"method\": \"TestMethod\" }\n"
1462 " \"retryPolicy\": {\n"
1463 " \"maxAttempts\": 2,\n"
1464 " \"initialBackoff\": \"1s\",\n"
1465 " \"maxBackoff\": \"120s\",\n"
1466 " \"backoffMultiplier\": \"1.6\",\n"
1467 " \"perAttemptRecvTimeout\": \"0s\",\n"
1468 " \"retryableStatusCodes\": [\"ABORTED\"]\n"
1482 "field:perAttemptRecvTimeout error:must be greater than 0"));
1496 builder->service_config_parser()->RegisterParser(
1497 absl::make_unique<MessageSizeParser>());
1506 const char* test_json =
1508 " \"methodConfig\": [ {\n"
1510 " { \"service\": \"TestServ\", \"method\": \"TestMethod\" }\n"
1512 " \"maxRequestMessageBytes\": 1024,\n"
1513 " \"maxResponseMessageBytes\": 1024\n"
1519 const auto* vector_ptr = svc_cfg->GetMethodParsedConfigVector(
1522 auto parsed_config =
1525 EXPECT_EQ(parsed_config->limits().max_send_size, 1024);
1526 EXPECT_EQ(parsed_config->limits().max_recv_size, 1024);
1530 const char* test_json =
1532 " \"methodConfig\": [ {\n"
1534 " { \"service\": \"TestServ\", \"method\": \"TestMethod\" }\n"
1536 " \"maxRequestMessageBytes\": -1024\n"
1546 "field:maxRequestMessageBytes error:should be non-negative"));
1551 const char* test_json =
1553 " \"methodConfig\": [ {\n"
1555 " { \"service\": \"TestServ\", \"method\": \"TestMethod\" }\n"
1557 " \"maxResponseMessageBytes\": {}\n"
1567 "field:maxResponseMessageBytes error:should be of type "