service_config_test.cc 61 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582
  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. #include "src/core/lib/service_config/service_config.h"
  19. #include <gmock/gmock.h>
  20. #include <gtest/gtest.h>
  21. #include "absl/strings/str_cat.h"
  22. #include <grpc/grpc.h>
  23. #include "src/core/ext/filters/client_channel/resolver_result_parsing.h"
  24. #include "src/core/ext/filters/client_channel/retry_service_config.h"
  25. #include "src/core/ext/filters/message_size/message_size_filter.h"
  26. #include "src/core/lib/gpr/string.h"
  27. #include "src/core/lib/gprpp/time.h"
  28. #include "src/core/lib/service_config/service_config_impl.h"
  29. #include "src/core/lib/service_config/service_config_parser.h"
  30. #include "test/core/util/port.h"
  31. #include "test/core/util/test_config.h"
  32. namespace grpc_core {
  33. namespace testing {
  34. //
  35. // ServiceConfig tests
  36. //
  37. // Set this channel arg to true to disable parsing.
  38. #define GRPC_ARG_DISABLE_PARSING "disable_parsing"
  39. // A regular expression to enter referenced or child errors.
  40. #ifdef GRPC_ERROR_IS_ABSEIL_STATUS
  41. #define CHILD_ERROR_TAG ".*children.*"
  42. #else
  43. #define CHILD_ERROR_TAG ".*referenced_errors.*"
  44. #endif
  45. class TestParsedConfig1 : public ServiceConfigParser::ParsedConfig {
  46. public:
  47. explicit TestParsedConfig1(int value) : value_(value) {}
  48. int value() const { return value_; }
  49. private:
  50. int value_;
  51. };
  52. class TestParser1 : public ServiceConfigParser::Parser {
  53. public:
  54. absl::string_view name() const override { return "test_parser_1"; }
  55. std::unique_ptr<ServiceConfigParser::ParsedConfig> ParseGlobalParams(
  56. const grpc_channel_args* args, const Json& json,
  57. grpc_error_handle* error) override {
  58. GPR_DEBUG_ASSERT(error != nullptr);
  59. if (grpc_channel_args_find_bool(args, GRPC_ARG_DISABLE_PARSING, false)) {
  60. return nullptr;
  61. }
  62. auto it = json.object_value().find("global_param");
  63. if (it != json.object_value().end()) {
  64. if (it->second.type() != Json::Type::NUMBER) {
  65. *error =
  66. GRPC_ERROR_CREATE_FROM_STATIC_STRING(InvalidTypeErrorMessage());
  67. return nullptr;
  68. }
  69. int value = gpr_parse_nonnegative_int(it->second.string_value().c_str());
  70. if (value == -1) {
  71. *error =
  72. GRPC_ERROR_CREATE_FROM_STATIC_STRING(InvalidValueErrorMessage());
  73. return nullptr;
  74. }
  75. return absl::make_unique<TestParsedConfig1>(value);
  76. }
  77. return nullptr;
  78. }
  79. static const char* InvalidTypeErrorMessage() {
  80. return "global_param value type should be a number";
  81. }
  82. static const char* InvalidValueErrorMessage() {
  83. return "global_param value type should be non-negative";
  84. }
  85. };
  86. class TestParser2 : public ServiceConfigParser::Parser {
  87. public:
  88. absl::string_view name() const override { return "test_parser_2"; }
  89. std::unique_ptr<ServiceConfigParser::ParsedConfig> ParsePerMethodParams(
  90. const grpc_channel_args* args, const Json& json,
  91. grpc_error_handle* error) override {
  92. GPR_DEBUG_ASSERT(error != nullptr);
  93. if (grpc_channel_args_find_bool(args, GRPC_ARG_DISABLE_PARSING, false)) {
  94. return nullptr;
  95. }
  96. auto it = json.object_value().find("method_param");
  97. if (it != json.object_value().end()) {
  98. if (it->second.type() != Json::Type::NUMBER) {
  99. *error =
  100. GRPC_ERROR_CREATE_FROM_STATIC_STRING(InvalidTypeErrorMessage());
  101. return nullptr;
  102. }
  103. int value = gpr_parse_nonnegative_int(it->second.string_value().c_str());
  104. if (value == -1) {
  105. *error =
  106. GRPC_ERROR_CREATE_FROM_STATIC_STRING(InvalidValueErrorMessage());
  107. return nullptr;
  108. }
  109. return absl::make_unique<TestParsedConfig1>(value);
  110. }
  111. return nullptr;
  112. }
  113. static const char* InvalidTypeErrorMessage() {
  114. return "method_param value type should be a number";
  115. }
  116. static const char* InvalidValueErrorMessage() {
  117. return "method_param value type should be non-negative";
  118. }
  119. };
  120. // This parser always adds errors
  121. class ErrorParser : public ServiceConfigParser::Parser {
  122. public:
  123. explicit ErrorParser(absl::string_view name) : name_(name) {}
  124. absl::string_view name() const override { return name_; }
  125. std::unique_ptr<ServiceConfigParser::ParsedConfig> ParsePerMethodParams(
  126. const grpc_channel_args* /*arg*/, const Json& /*json*/,
  127. grpc_error_handle* error) override {
  128. GPR_DEBUG_ASSERT(error != nullptr);
  129. *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(MethodError());
  130. return nullptr;
  131. }
  132. std::unique_ptr<ServiceConfigParser::ParsedConfig> ParseGlobalParams(
  133. const grpc_channel_args* /*arg*/, const Json& /*json*/,
  134. grpc_error_handle* error) override {
  135. GPR_DEBUG_ASSERT(error != nullptr);
  136. *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(GlobalError());
  137. return nullptr;
  138. }
  139. static const char* MethodError() { return "ErrorParser : methodError"; }
  140. static const char* GlobalError() { return "ErrorParser : globalError"; }
  141. private:
  142. absl::string_view name_;
  143. };
  144. class ServiceConfigTest : public ::testing::Test {
  145. protected:
  146. void SetUp() override {
  147. CoreConfiguration::Reset();
  148. CoreConfiguration::BuildSpecialConfiguration(
  149. [](CoreConfiguration::Builder* builder) {
  150. builder->service_config_parser()->RegisterParser(
  151. absl::make_unique<TestParser1>());
  152. builder->service_config_parser()->RegisterParser(
  153. absl::make_unique<TestParser2>());
  154. });
  155. EXPECT_EQ(CoreConfiguration::Get().service_config_parser().GetParserIndex(
  156. "test_parser_1"),
  157. 0);
  158. EXPECT_EQ(CoreConfiguration::Get().service_config_parser().GetParserIndex(
  159. "test_parser_2"),
  160. 1);
  161. }
  162. };
  163. TEST_F(ServiceConfigTest, ErrorCheck1) {
  164. const char* test_json = "";
  165. grpc_error_handle error = GRPC_ERROR_NONE;
  166. auto svc_cfg = ServiceConfigImpl::Create(nullptr, test_json, &error);
  167. EXPECT_THAT(grpc_error_std_string(error),
  168. ::testing::ContainsRegex("JSON parse error"));
  169. GRPC_ERROR_UNREF(error);
  170. }
  171. TEST_F(ServiceConfigTest, BasicTest1) {
  172. const char* test_json = "{}";
  173. grpc_error_handle error = GRPC_ERROR_NONE;
  174. auto svc_cfg = ServiceConfigImpl::Create(nullptr, test_json, &error);
  175. EXPECT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error);
  176. }
  177. TEST_F(ServiceConfigTest, SkipMethodConfigWithNoNameOrEmptyName) {
  178. const char* test_json =
  179. "{\"methodConfig\": ["
  180. " {\"method_param\":1},"
  181. " {\"name\":[], \"method_param\":1},"
  182. " {\"name\":[{\"service\":\"TestServ\"}], \"method_param\":2}"
  183. "]}";
  184. grpc_error_handle error = GRPC_ERROR_NONE;
  185. auto svc_cfg = ServiceConfigImpl::Create(nullptr, test_json, &error);
  186. ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error);
  187. const auto* vector_ptr = svc_cfg->GetMethodParsedConfigVector(
  188. grpc_slice_from_static_string("/TestServ/TestMethod"));
  189. ASSERT_NE(vector_ptr, nullptr);
  190. auto parsed_config = ((*vector_ptr)[1]).get();
  191. EXPECT_EQ(static_cast<TestParsedConfig1*>(parsed_config)->value(), 2);
  192. }
  193. TEST_F(ServiceConfigTest, ErrorDuplicateMethodConfigNames) {
  194. const char* test_json =
  195. "{\"methodConfig\": ["
  196. " {\"name\":[{\"service\":\"TestServ\"}]},"
  197. " {\"name\":[{\"service\":\"TestServ\"}]}"
  198. "]}";
  199. grpc_error_handle error = GRPC_ERROR_NONE;
  200. auto svc_cfg = ServiceConfigImpl::Create(nullptr, test_json, &error);
  201. EXPECT_THAT(grpc_error_std_string(error),
  202. ::testing::ContainsRegex(
  203. "Service config parsing error" CHILD_ERROR_TAG
  204. "Method Params" CHILD_ERROR_TAG "methodConfig" CHILD_ERROR_TAG
  205. "multiple method configs with same name"));
  206. GRPC_ERROR_UNREF(error);
  207. }
  208. TEST_F(ServiceConfigTest, ErrorDuplicateMethodConfigNamesWithNullMethod) {
  209. const char* test_json =
  210. "{\"methodConfig\": ["
  211. " {\"name\":[{\"service\":\"TestServ\",\"method\":null}]},"
  212. " {\"name\":[{\"service\":\"TestServ\"}]}"
  213. "]}";
  214. grpc_error_handle error = GRPC_ERROR_NONE;
  215. auto svc_cfg = ServiceConfigImpl::Create(nullptr, test_json, &error);
  216. EXPECT_THAT(grpc_error_std_string(error),
  217. ::testing::ContainsRegex(
  218. "Service config parsing error" CHILD_ERROR_TAG
  219. "Method Params" CHILD_ERROR_TAG "methodConfig" CHILD_ERROR_TAG
  220. "multiple method configs with same name"));
  221. GRPC_ERROR_UNREF(error);
  222. }
  223. TEST_F(ServiceConfigTest, ErrorDuplicateMethodConfigNamesWithEmptyMethod) {
  224. const char* test_json =
  225. "{\"methodConfig\": ["
  226. " {\"name\":[{\"service\":\"TestServ\",\"method\":\"\"}]},"
  227. " {\"name\":[{\"service\":\"TestServ\"}]}"
  228. "]}";
  229. grpc_error_handle error = GRPC_ERROR_NONE;
  230. auto svc_cfg = ServiceConfigImpl::Create(nullptr, test_json, &error);
  231. EXPECT_THAT(grpc_error_std_string(error),
  232. ::testing::ContainsRegex(
  233. "Service config parsing error" CHILD_ERROR_TAG
  234. "Method Params" CHILD_ERROR_TAG "methodConfig" CHILD_ERROR_TAG
  235. "multiple method configs with same name"));
  236. GRPC_ERROR_UNREF(error);
  237. }
  238. TEST_F(ServiceConfigTest, ErrorDuplicateDefaultMethodConfigs) {
  239. const char* test_json =
  240. "{\"methodConfig\": ["
  241. " {\"name\":[{}]},"
  242. " {\"name\":[{}]}"
  243. "]}";
  244. grpc_error_handle error = GRPC_ERROR_NONE;
  245. auto svc_cfg = ServiceConfigImpl::Create(nullptr, test_json, &error);
  246. EXPECT_THAT(grpc_error_std_string(error),
  247. ::testing::ContainsRegex(
  248. "Service config parsing error" CHILD_ERROR_TAG
  249. "Method Params" CHILD_ERROR_TAG "methodConfig" CHILD_ERROR_TAG
  250. "multiple default method configs"));
  251. GRPC_ERROR_UNREF(error);
  252. }
  253. TEST_F(ServiceConfigTest, ErrorDuplicateDefaultMethodConfigsWithNullService) {
  254. const char* test_json =
  255. "{\"methodConfig\": ["
  256. " {\"name\":[{\"service\":null}]},"
  257. " {\"name\":[{}]}"
  258. "]}";
  259. grpc_error_handle error = GRPC_ERROR_NONE;
  260. auto svc_cfg = ServiceConfigImpl::Create(nullptr, test_json, &error);
  261. EXPECT_THAT(grpc_error_std_string(error),
  262. ::testing::ContainsRegex(
  263. "Service config parsing error" CHILD_ERROR_TAG
  264. "Method Params" CHILD_ERROR_TAG "methodConfig" CHILD_ERROR_TAG
  265. "multiple default method configs"));
  266. GRPC_ERROR_UNREF(error);
  267. }
  268. TEST_F(ServiceConfigTest, ErrorDuplicateDefaultMethodConfigsWithEmptyService) {
  269. const char* test_json =
  270. "{\"methodConfig\": ["
  271. " {\"name\":[{\"service\":\"\"}]},"
  272. " {\"name\":[{}]}"
  273. "]}";
  274. grpc_error_handle error = GRPC_ERROR_NONE;
  275. auto svc_cfg = ServiceConfigImpl::Create(nullptr, test_json, &error);
  276. EXPECT_THAT(grpc_error_std_string(error),
  277. ::testing::ContainsRegex(
  278. "Service config parsing error" CHILD_ERROR_TAG
  279. "Method Params" CHILD_ERROR_TAG "methodConfig" CHILD_ERROR_TAG
  280. "multiple default method configs"));
  281. GRPC_ERROR_UNREF(error);
  282. }
  283. TEST_F(ServiceConfigTest, ValidMethodConfig) {
  284. const char* test_json =
  285. "{\"methodConfig\": [{\"name\":[{\"service\":\"TestServ\"}]}]}";
  286. grpc_error_handle error = GRPC_ERROR_NONE;
  287. auto svc_cfg = ServiceConfigImpl::Create(nullptr, test_json, &error);
  288. EXPECT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error);
  289. }
  290. TEST_F(ServiceConfigTest, Parser1BasicTest1) {
  291. const char* test_json = "{\"global_param\":5}";
  292. grpc_error_handle error = GRPC_ERROR_NONE;
  293. auto svc_cfg = ServiceConfigImpl::Create(nullptr, test_json, &error);
  294. ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_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. const char* test_json = "{\"global_param\":1000}";
  304. grpc_error_handle error = GRPC_ERROR_NONE;
  305. auto svc_cfg = ServiceConfigImpl::Create(nullptr, test_json, &error);
  306. ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error);
  307. EXPECT_EQ((static_cast<TestParsedConfig1*>(svc_cfg->GetGlobalParsedConfig(0)))
  308. ->value(),
  309. 1000);
  310. }
  311. TEST_F(ServiceConfigTest, Parser1DisabledViaChannelArg) {
  312. grpc_arg arg = grpc_channel_arg_integer_create(
  313. const_cast<char*>(GRPC_ARG_DISABLE_PARSING), 1);
  314. grpc_channel_args args = {1, &arg};
  315. const char* test_json = "{\"global_param\":5}";
  316. grpc_error_handle error = GRPC_ERROR_NONE;
  317. auto svc_cfg = ServiceConfigImpl::Create(&args, test_json, &error);
  318. ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error);
  319. EXPECT_EQ(svc_cfg->GetGlobalParsedConfig(0), nullptr);
  320. }
  321. TEST_F(ServiceConfigTest, Parser1ErrorInvalidType) {
  322. const char* test_json = "{\"global_param\":\"5\"}";
  323. grpc_error_handle error = GRPC_ERROR_NONE;
  324. auto svc_cfg = ServiceConfigImpl::Create(nullptr, test_json, &error);
  325. EXPECT_THAT(grpc_error_std_string(error),
  326. ::testing::ContainsRegex(
  327. absl::StrCat("Service config parsing error" CHILD_ERROR_TAG
  328. "Global Params" CHILD_ERROR_TAG,
  329. TestParser1::InvalidTypeErrorMessage())));
  330. GRPC_ERROR_UNREF(error);
  331. }
  332. TEST_F(ServiceConfigTest, Parser1ErrorInvalidValue) {
  333. const char* test_json = "{\"global_param\":-5}";
  334. grpc_error_handle error = GRPC_ERROR_NONE;
  335. auto svc_cfg = ServiceConfigImpl::Create(nullptr, test_json, &error);
  336. EXPECT_THAT(grpc_error_std_string(error),
  337. ::testing::ContainsRegex(
  338. absl::StrCat("Service config parsing error" CHILD_ERROR_TAG
  339. "Global Params" CHILD_ERROR_TAG,
  340. TestParser1::InvalidValueErrorMessage())));
  341. GRPC_ERROR_UNREF(error);
  342. }
  343. TEST_F(ServiceConfigTest, Parser2BasicTest) {
  344. const char* test_json =
  345. "{\"methodConfig\": [{\"name\":[{\"service\":\"TestServ\"}], "
  346. "\"method_param\":5}]}";
  347. grpc_error_handle error = GRPC_ERROR_NONE;
  348. auto svc_cfg = ServiceConfigImpl::Create(nullptr, test_json, &error);
  349. ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error);
  350. const auto* vector_ptr = svc_cfg->GetMethodParsedConfigVector(
  351. grpc_slice_from_static_string("/TestServ/TestMethod"));
  352. ASSERT_NE(vector_ptr, nullptr);
  353. auto parsed_config = ((*vector_ptr)[1]).get();
  354. EXPECT_EQ(static_cast<TestParsedConfig1*>(parsed_config)->value(), 5);
  355. }
  356. TEST_F(ServiceConfigTest, Parser2DisabledViaChannelArg) {
  357. grpc_arg arg = grpc_channel_arg_integer_create(
  358. const_cast<char*>(GRPC_ARG_DISABLE_PARSING), 1);
  359. grpc_channel_args args = {1, &arg};
  360. const char* test_json =
  361. "{\"methodConfig\": [{\"name\":[{\"service\":\"TestServ\"}], "
  362. "\"method_param\":5}]}";
  363. grpc_error_handle error = GRPC_ERROR_NONE;
  364. auto svc_cfg = ServiceConfigImpl::Create(&args, test_json, &error);
  365. ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error);
  366. const auto* vector_ptr = svc_cfg->GetMethodParsedConfigVector(
  367. grpc_slice_from_static_string("/TestServ/TestMethod"));
  368. ASSERT_NE(vector_ptr, nullptr);
  369. auto parsed_config = ((*vector_ptr)[1]).get();
  370. EXPECT_EQ(parsed_config, nullptr);
  371. }
  372. TEST_F(ServiceConfigTest, Parser2ErrorInvalidType) {
  373. const char* test_json =
  374. "{\"methodConfig\": [{\"name\":[{\"service\":\"TestServ\"}], "
  375. "\"method_param\":\"5\"}]}";
  376. grpc_error_handle error = GRPC_ERROR_NONE;
  377. auto svc_cfg = ServiceConfigImpl::Create(nullptr, test_json, &error);
  378. EXPECT_THAT(
  379. grpc_error_std_string(error),
  380. ::testing::ContainsRegex(absl::StrCat(
  381. "Service config parsing error" CHILD_ERROR_TAG
  382. "Method Params" CHILD_ERROR_TAG "methodConfig" CHILD_ERROR_TAG,
  383. TestParser2::InvalidTypeErrorMessage())));
  384. GRPC_ERROR_UNREF(error);
  385. }
  386. TEST_F(ServiceConfigTest, Parser2ErrorInvalidValue) {
  387. const char* test_json =
  388. "{\"methodConfig\": [{\"name\":[{\"service\":\"TestServ\"}], "
  389. "\"method_param\":-5}]}";
  390. grpc_error_handle error = GRPC_ERROR_NONE;
  391. auto svc_cfg = ServiceConfigImpl::Create(nullptr, test_json, &error);
  392. EXPECT_THAT(
  393. grpc_error_std_string(error),
  394. ::testing::ContainsRegex(absl::StrCat(
  395. "Service config parsing error" CHILD_ERROR_TAG
  396. "Method Params" CHILD_ERROR_TAG "methodConfig" CHILD_ERROR_TAG,
  397. TestParser2::InvalidValueErrorMessage())));
  398. GRPC_ERROR_UNREF(error);
  399. }
  400. TEST(ServiceConfigParserTest, DoubleRegistration) {
  401. CoreConfiguration::Reset();
  402. ASSERT_DEATH_IF_SUPPORTED(
  403. CoreConfiguration::BuildSpecialConfiguration(
  404. [](CoreConfiguration::Builder* builder) {
  405. builder->service_config_parser()->RegisterParser(
  406. absl::make_unique<ErrorParser>("xyzabc"));
  407. builder->service_config_parser()->RegisterParser(
  408. absl::make_unique<ErrorParser>("xyzabc"));
  409. }),
  410. "xyzabc.*already registered");
  411. }
  412. // Test parsing with ErrorParsers which always add errors
  413. class ErroredParsersScopingTest : public ::testing::Test {
  414. protected:
  415. void SetUp() override {
  416. CoreConfiguration::Reset();
  417. CoreConfiguration::BuildSpecialConfiguration(
  418. [](CoreConfiguration::Builder* builder) {
  419. builder->service_config_parser()->RegisterParser(
  420. absl::make_unique<ErrorParser>("ep1"));
  421. builder->service_config_parser()->RegisterParser(
  422. absl::make_unique<ErrorParser>("ep2"));
  423. });
  424. EXPECT_EQ(
  425. CoreConfiguration::Get().service_config_parser().GetParserIndex("ep1"),
  426. 0);
  427. EXPECT_EQ(
  428. CoreConfiguration::Get().service_config_parser().GetParserIndex("ep2"),
  429. 1);
  430. }
  431. };
  432. TEST_F(ErroredParsersScopingTest, GlobalParams) {
  433. const char* test_json = "{}";
  434. grpc_error_handle error = GRPC_ERROR_NONE;
  435. auto svc_cfg = ServiceConfigImpl::Create(nullptr, test_json, &error);
  436. EXPECT_THAT(
  437. grpc_error_std_string(error),
  438. ::testing::ContainsRegex(absl::StrCat(
  439. "Service config parsing error" CHILD_ERROR_TAG
  440. "Global Params" CHILD_ERROR_TAG,
  441. ErrorParser::GlobalError(), ".*", ErrorParser::GlobalError())));
  442. GRPC_ERROR_UNREF(error);
  443. }
  444. TEST_F(ErroredParsersScopingTest, MethodParams) {
  445. const char* test_json = "{\"methodConfig\": [{}]}";
  446. grpc_error_handle error = GRPC_ERROR_NONE;
  447. auto svc_cfg = ServiceConfigImpl::Create(nullptr, test_json, &error);
  448. EXPECT_THAT(
  449. grpc_error_std_string(error),
  450. ::testing::ContainsRegex(absl::StrCat(
  451. "Service config parsing error" CHILD_ERROR_TAG
  452. "Global Params" CHILD_ERROR_TAG,
  453. ErrorParser::GlobalError(), ".*", ErrorParser::GlobalError(),
  454. ".*Method Params" CHILD_ERROR_TAG "methodConfig" CHILD_ERROR_TAG,
  455. ErrorParser::MethodError(), ".*", ErrorParser::MethodError())));
  456. GRPC_ERROR_UNREF(error);
  457. }
  458. //
  459. // client_channel parser tests
  460. //
  461. class ClientChannelParserTest : public ::testing::Test {
  462. protected:
  463. void SetUp() override {
  464. CoreConfiguration::Reset();
  465. CoreConfiguration::BuildSpecialConfiguration(
  466. [](CoreConfiguration::Builder* builder) {
  467. builder->service_config_parser()->RegisterParser(
  468. absl::make_unique<internal::ClientChannelServiceConfigParser>());
  469. });
  470. EXPECT_EQ(CoreConfiguration::Get().service_config_parser().GetParserIndex(
  471. "client_channel"),
  472. 0);
  473. }
  474. };
  475. TEST_F(ClientChannelParserTest, ValidLoadBalancingConfigPickFirst) {
  476. const char* test_json = "{\"loadBalancingConfig\": [{\"pick_first\":{}}]}";
  477. grpc_error_handle error = GRPC_ERROR_NONE;
  478. auto svc_cfg = ServiceConfigImpl::Create(nullptr, test_json, &error);
  479. ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error);
  480. const auto* parsed_config =
  481. static_cast<internal::ClientChannelGlobalParsedConfig*>(
  482. svc_cfg->GetGlobalParsedConfig(0));
  483. auto lb_config = parsed_config->parsed_lb_config();
  484. EXPECT_STREQ(lb_config->name(), "pick_first");
  485. }
  486. TEST_F(ClientChannelParserTest, ValidLoadBalancingConfigRoundRobin) {
  487. const char* test_json =
  488. "{\"loadBalancingConfig\": [{\"round_robin\":{}}, {}]}";
  489. grpc_error_handle error = GRPC_ERROR_NONE;
  490. auto svc_cfg = ServiceConfigImpl::Create(nullptr, test_json, &error);
  491. ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error);
  492. auto parsed_config = static_cast<internal::ClientChannelGlobalParsedConfig*>(
  493. svc_cfg->GetGlobalParsedConfig(0));
  494. auto lb_config = parsed_config->parsed_lb_config();
  495. EXPECT_STREQ(lb_config->name(), "round_robin");
  496. }
  497. TEST_F(ClientChannelParserTest, ValidLoadBalancingConfigGrpclb) {
  498. const char* test_json =
  499. "{\"loadBalancingConfig\": "
  500. "[{\"grpclb\":{\"childPolicy\":[{\"pick_first\":{}}]}}]}";
  501. grpc_error_handle error = GRPC_ERROR_NONE;
  502. auto svc_cfg = ServiceConfigImpl::Create(nullptr, test_json, &error);
  503. ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error);
  504. const auto* parsed_config =
  505. static_cast<internal::ClientChannelGlobalParsedConfig*>(
  506. svc_cfg->GetGlobalParsedConfig(0));
  507. auto lb_config = parsed_config->parsed_lb_config();
  508. EXPECT_STREQ(lb_config->name(), "grpclb");
  509. }
  510. TEST_F(ClientChannelParserTest, ValidLoadBalancingConfigXds) {
  511. const char* test_json =
  512. "{\n"
  513. " \"loadBalancingConfig\":[\n"
  514. " { \"does_not_exist\":{} },\n"
  515. " { \"xds_cluster_resolver_experimental\":{\n"
  516. " \"discoveryMechanisms\": [\n"
  517. " { \"clusterName\": \"foo\",\n"
  518. " \"type\": \"EDS\"\n"
  519. " } ]\n"
  520. " } }\n"
  521. " ]\n"
  522. "}";
  523. grpc_error_handle error = GRPC_ERROR_NONE;
  524. auto svc_cfg = ServiceConfigImpl::Create(nullptr, test_json, &error);
  525. ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error);
  526. const auto* parsed_config =
  527. static_cast<internal::ClientChannelGlobalParsedConfig*>(
  528. svc_cfg->GetGlobalParsedConfig(0));
  529. auto lb_config = parsed_config->parsed_lb_config();
  530. EXPECT_STREQ(lb_config->name(), "xds_cluster_resolver_experimental");
  531. }
  532. TEST_F(ClientChannelParserTest, UnknownLoadBalancingConfig) {
  533. const char* test_json = "{\"loadBalancingConfig\": [{\"unknown\":{}}]}";
  534. grpc_error_handle error = GRPC_ERROR_NONE;
  535. auto svc_cfg = ServiceConfigImpl::Create(nullptr, test_json, &error);
  536. EXPECT_THAT(
  537. grpc_error_std_string(error),
  538. ::testing::ContainsRegex("Service config parsing error" CHILD_ERROR_TAG
  539. "Global Params" CHILD_ERROR_TAG
  540. "Client channel global parser" CHILD_ERROR_TAG
  541. "field:loadBalancingConfig" CHILD_ERROR_TAG
  542. "No known policies in list: unknown"));
  543. GRPC_ERROR_UNREF(error);
  544. }
  545. TEST_F(ClientChannelParserTest, InvalidGrpclbLoadBalancingConfig) {
  546. const char* test_json =
  547. "{\"loadBalancingConfig\": ["
  548. " {\"grpclb\":{\"childPolicy\":1}},"
  549. " {\"round_robin\":{}}"
  550. "]}";
  551. grpc_error_handle error = GRPC_ERROR_NONE;
  552. auto svc_cfg = ServiceConfigImpl::Create(nullptr, test_json, &error);
  553. EXPECT_THAT(grpc_error_std_string(error),
  554. ::testing::ContainsRegex(
  555. "Service config parsing error" CHILD_ERROR_TAG
  556. "Global Params" CHILD_ERROR_TAG
  557. "Client channel global parser" CHILD_ERROR_TAG
  558. "field:loadBalancingConfig" CHILD_ERROR_TAG
  559. "GrpcLb Parser" CHILD_ERROR_TAG
  560. "field:childPolicy" CHILD_ERROR_TAG "type should be array"));
  561. GRPC_ERROR_UNREF(error);
  562. }
  563. TEST_F(ClientChannelParserTest, ValidLoadBalancingPolicy) {
  564. const char* test_json = "{\"loadBalancingPolicy\":\"pick_first\"}";
  565. grpc_error_handle error = GRPC_ERROR_NONE;
  566. auto svc_cfg = ServiceConfigImpl::Create(nullptr, test_json, &error);
  567. ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error);
  568. const auto* parsed_config =
  569. static_cast<internal::ClientChannelGlobalParsedConfig*>(
  570. svc_cfg->GetGlobalParsedConfig(0));
  571. EXPECT_EQ(parsed_config->parsed_deprecated_lb_policy(), "pick_first");
  572. }
  573. TEST_F(ClientChannelParserTest, ValidLoadBalancingPolicyAllCaps) {
  574. const char* test_json = "{\"loadBalancingPolicy\":\"PICK_FIRST\"}";
  575. grpc_error_handle error = GRPC_ERROR_NONE;
  576. auto svc_cfg = ServiceConfigImpl::Create(nullptr, test_json, &error);
  577. ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error);
  578. const auto* parsed_config =
  579. static_cast<internal::ClientChannelGlobalParsedConfig*>(
  580. svc_cfg->GetGlobalParsedConfig(0));
  581. EXPECT_EQ(parsed_config->parsed_deprecated_lb_policy(), "pick_first");
  582. }
  583. TEST_F(ClientChannelParserTest, UnknownLoadBalancingPolicy) {
  584. const char* test_json = "{\"loadBalancingPolicy\":\"unknown\"}";
  585. grpc_error_handle error = GRPC_ERROR_NONE;
  586. auto svc_cfg = ServiceConfigImpl::Create(nullptr, test_json, &error);
  587. EXPECT_THAT(grpc_error_std_string(error),
  588. ::testing::ContainsRegex(
  589. "Service config parsing error" CHILD_ERROR_TAG
  590. "Global Params" CHILD_ERROR_TAG
  591. "Client channel global parser" CHILD_ERROR_TAG
  592. "field:loadBalancingPolicy error:Unknown lb policy"));
  593. GRPC_ERROR_UNREF(error);
  594. }
  595. TEST_F(ClientChannelParserTest, LoadBalancingPolicyXdsNotAllowed) {
  596. const char* test_json =
  597. "{\"loadBalancingPolicy\":\"xds_cluster_resolver_experimental\"}";
  598. grpc_error_handle error = GRPC_ERROR_NONE;
  599. auto svc_cfg = ServiceConfigImpl::Create(nullptr, test_json, &error);
  600. EXPECT_THAT(grpc_error_std_string(error),
  601. ::testing::ContainsRegex(
  602. "Service config parsing error" CHILD_ERROR_TAG
  603. "Global Params" CHILD_ERROR_TAG
  604. "Client channel global parser" CHILD_ERROR_TAG
  605. "field:loadBalancingPolicy "
  606. "error:xds_cluster_resolver_experimental requires "
  607. "a config. Please use loadBalancingConfig instead."));
  608. GRPC_ERROR_UNREF(error);
  609. }
  610. TEST_F(ClientChannelParserTest, ValidTimeout) {
  611. const char* test_json =
  612. "{\n"
  613. " \"methodConfig\": [ {\n"
  614. " \"name\": [\n"
  615. " { \"service\": \"TestServ\", \"method\": \"TestMethod\" }\n"
  616. " ],\n"
  617. " \"timeout\": \"5s\"\n"
  618. " } ]\n"
  619. "}";
  620. grpc_error_handle error = GRPC_ERROR_NONE;
  621. auto svc_cfg = ServiceConfigImpl::Create(nullptr, test_json, &error);
  622. ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error);
  623. const auto* vector_ptr = svc_cfg->GetMethodParsedConfigVector(
  624. grpc_slice_from_static_string("/TestServ/TestMethod"));
  625. ASSERT_NE(vector_ptr, nullptr);
  626. auto parsed_config = ((*vector_ptr)[0]).get();
  627. EXPECT_EQ(
  628. (static_cast<internal::ClientChannelMethodParsedConfig*>(parsed_config))
  629. ->timeout(),
  630. Duration::Seconds(5));
  631. }
  632. TEST_F(ClientChannelParserTest, InvalidTimeout) {
  633. const char* test_json =
  634. "{\n"
  635. " \"methodConfig\": [ {\n"
  636. " \"name\": [\n"
  637. " { \"service\": \"service\", \"method\": \"method\" }\n"
  638. " ],\n"
  639. " \"timeout\": \"5sec\"\n"
  640. " } ]\n"
  641. "}";
  642. grpc_error_handle error = GRPC_ERROR_NONE;
  643. auto svc_cfg = ServiceConfigImpl::Create(nullptr, test_json, &error);
  644. EXPECT_THAT(grpc_error_std_string(error),
  645. ::testing::ContainsRegex(
  646. "Service config parsing error" CHILD_ERROR_TAG
  647. "Method Params" CHILD_ERROR_TAG "methodConfig" CHILD_ERROR_TAG
  648. "Client channel parser" CHILD_ERROR_TAG
  649. "field:timeout error:type should be STRING of the form given "
  650. "by google.proto.Duration"));
  651. GRPC_ERROR_UNREF(error);
  652. }
  653. TEST_F(ClientChannelParserTest, ValidWaitForReady) {
  654. const char* test_json =
  655. "{\n"
  656. " \"methodConfig\": [ {\n"
  657. " \"name\": [\n"
  658. " { \"service\": \"TestServ\", \"method\": \"TestMethod\" }\n"
  659. " ],\n"
  660. " \"waitForReady\": true\n"
  661. " } ]\n"
  662. "}";
  663. grpc_error_handle error = GRPC_ERROR_NONE;
  664. auto svc_cfg = ServiceConfigImpl::Create(nullptr, test_json, &error);
  665. ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error);
  666. const auto* vector_ptr = svc_cfg->GetMethodParsedConfigVector(
  667. grpc_slice_from_static_string("/TestServ/TestMethod"));
  668. ASSERT_NE(vector_ptr, nullptr);
  669. auto parsed_config = ((*vector_ptr)[0]).get();
  670. ASSERT_TRUE(
  671. (static_cast<internal::ClientChannelMethodParsedConfig*>(parsed_config))
  672. ->wait_for_ready()
  673. .has_value());
  674. EXPECT_TRUE(
  675. (static_cast<internal::ClientChannelMethodParsedConfig*>(parsed_config))
  676. ->wait_for_ready()
  677. .value());
  678. }
  679. TEST_F(ClientChannelParserTest, InvalidWaitForReady) {
  680. const char* test_json =
  681. "{\n"
  682. " \"methodConfig\": [ {\n"
  683. " \"name\": [\n"
  684. " { \"service\": \"service\", \"method\": \"method\" }\n"
  685. " ],\n"
  686. " \"waitForReady\": \"true\"\n"
  687. " } ]\n"
  688. "}";
  689. grpc_error_handle error = GRPC_ERROR_NONE;
  690. auto svc_cfg = ServiceConfigImpl::Create(nullptr, test_json, &error);
  691. EXPECT_THAT(grpc_error_std_string(error),
  692. ::testing::ContainsRegex(
  693. "Service config parsing error" CHILD_ERROR_TAG
  694. "Method Params" CHILD_ERROR_TAG "methodConfig" CHILD_ERROR_TAG
  695. "Client channel parser" CHILD_ERROR_TAG
  696. "field:waitForReady error:Type should be true/false"));
  697. GRPC_ERROR_UNREF(error);
  698. }
  699. TEST_F(ClientChannelParserTest, ValidHealthCheck) {
  700. const char* test_json =
  701. "{\n"
  702. " \"healthCheckConfig\": {\n"
  703. " \"serviceName\": \"health_check_service_name\"\n"
  704. " }\n"
  705. "}";
  706. grpc_error_handle error = GRPC_ERROR_NONE;
  707. auto svc_cfg = ServiceConfigImpl::Create(nullptr, test_json, &error);
  708. ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error);
  709. const auto* parsed_config =
  710. static_cast<internal::ClientChannelGlobalParsedConfig*>(
  711. svc_cfg->GetGlobalParsedConfig(0));
  712. ASSERT_NE(parsed_config, nullptr);
  713. EXPECT_EQ(parsed_config->health_check_service_name(),
  714. "health_check_service_name");
  715. }
  716. TEST_F(ClientChannelParserTest, InvalidHealthCheckMultipleEntries) {
  717. const char* test_json =
  718. "{\n"
  719. " \"healthCheckConfig\": {\n"
  720. " \"serviceName\": \"health_check_service_name\"\n"
  721. " },\n"
  722. " \"healthCheckConfig\": {\n"
  723. " \"serviceName\": \"health_check_service_name1\"\n"
  724. " }\n"
  725. "}";
  726. grpc_error_handle error = GRPC_ERROR_NONE;
  727. auto svc_cfg = ServiceConfigImpl::Create(nullptr, test_json, &error);
  728. EXPECT_THAT(grpc_error_std_string(error),
  729. ::testing::ContainsRegex(
  730. "JSON parsing failed" CHILD_ERROR_TAG
  731. "duplicate key \"healthCheckConfig\" at index 104"));
  732. GRPC_ERROR_UNREF(error);
  733. }
  734. //
  735. // retry parser tests
  736. //
  737. class RetryParserTest : public ::testing::Test {
  738. protected:
  739. void SetUp() override {
  740. CoreConfiguration::Reset();
  741. CoreConfiguration::BuildSpecialConfiguration(
  742. [](CoreConfiguration::Builder* builder) {
  743. builder->service_config_parser()->RegisterParser(
  744. absl::make_unique<internal::RetryServiceConfigParser>());
  745. });
  746. EXPECT_EQ(CoreConfiguration::Get().service_config_parser().GetParserIndex(
  747. "retry"),
  748. 0);
  749. }
  750. };
  751. TEST_F(RetryParserTest, ValidRetryThrottling) {
  752. const char* test_json =
  753. "{\n"
  754. " \"retryThrottling\": {\n"
  755. " \"maxTokens\": 2,\n"
  756. " \"tokenRatio\": 1.0\n"
  757. " }\n"
  758. "}";
  759. grpc_error_handle error = GRPC_ERROR_NONE;
  760. auto svc_cfg = ServiceConfigImpl::Create(nullptr, test_json, &error);
  761. ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error);
  762. const auto* parsed_config = static_cast<internal::RetryGlobalConfig*>(
  763. svc_cfg->GetGlobalParsedConfig(0));
  764. ASSERT_NE(parsed_config, nullptr);
  765. EXPECT_EQ(parsed_config->max_milli_tokens(), 2000);
  766. EXPECT_EQ(parsed_config->milli_token_ratio(), 1000);
  767. }
  768. TEST_F(RetryParserTest, RetryThrottlingMissingFields) {
  769. const char* test_json =
  770. "{\n"
  771. " \"retryThrottling\": {\n"
  772. " }\n"
  773. "}";
  774. grpc_error_handle error = GRPC_ERROR_NONE;
  775. auto svc_cfg = ServiceConfigImpl::Create(nullptr, test_json, &error);
  776. EXPECT_THAT(
  777. grpc_error_std_string(error),
  778. ::testing::ContainsRegex(
  779. "Service config parsing error" CHILD_ERROR_TAG
  780. "Global Params" CHILD_ERROR_TAG "retryThrottling" CHILD_ERROR_TAG
  781. "field:retryThrottling field:maxTokens error:Not found"
  782. ".*field:retryThrottling field:tokenRatio error:Not found"));
  783. GRPC_ERROR_UNREF(error);
  784. }
  785. TEST_F(RetryParserTest, InvalidRetryThrottlingNegativeMaxTokens) {
  786. const char* test_json =
  787. "{\n"
  788. " \"retryThrottling\": {\n"
  789. " \"maxTokens\": -2,\n"
  790. " \"tokenRatio\": 1.0\n"
  791. " }\n"
  792. "}";
  793. grpc_error_handle error = GRPC_ERROR_NONE;
  794. auto svc_cfg = ServiceConfigImpl::Create(nullptr, test_json, &error);
  795. EXPECT_THAT(
  796. grpc_error_std_string(error),
  797. ::testing::ContainsRegex(
  798. "Service config parsing error" CHILD_ERROR_TAG
  799. "Global Params" CHILD_ERROR_TAG "retryThrottling" CHILD_ERROR_TAG
  800. "field:retryThrottling field:maxTokens error:should "
  801. "be greater than zero"));
  802. GRPC_ERROR_UNREF(error);
  803. }
  804. TEST_F(RetryParserTest, InvalidRetryThrottlingInvalidTokenRatio) {
  805. const char* test_json =
  806. "{\n"
  807. " \"retryThrottling\": {\n"
  808. " \"maxTokens\": 2,\n"
  809. " \"tokenRatio\": -1\n"
  810. " }\n"
  811. "}";
  812. grpc_error_handle error = GRPC_ERROR_NONE;
  813. auto svc_cfg = ServiceConfigImpl::Create(nullptr, test_json, &error);
  814. EXPECT_THAT(
  815. grpc_error_std_string(error),
  816. ::testing::ContainsRegex("Service config parsing error" CHILD_ERROR_TAG
  817. "Global Params" CHILD_ERROR_TAG
  818. "retryThrottling" CHILD_ERROR_TAG
  819. "field:retryThrottling field:tokenRatio "
  820. "error:Failed parsing"));
  821. GRPC_ERROR_UNREF(error);
  822. }
  823. TEST_F(RetryParserTest, ValidRetryPolicy) {
  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\": 3,\n"
  832. " \"initialBackoff\": \"1s\",\n"
  833. " \"maxBackoff\": \"120s\",\n"
  834. " \"backoffMultiplier\": 1.6,\n"
  835. " \"retryableStatusCodes\": [ \"ABORTED\" ]\n"
  836. " }\n"
  837. " } ]\n"
  838. "}";
  839. grpc_error_handle error = GRPC_ERROR_NONE;
  840. auto svc_cfg = ServiceConfigImpl::Create(nullptr, test_json, &error);
  841. ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error);
  842. const auto* vector_ptr = svc_cfg->GetMethodParsedConfigVector(
  843. grpc_slice_from_static_string("/TestServ/TestMethod"));
  844. ASSERT_NE(vector_ptr, nullptr);
  845. const auto* parsed_config =
  846. static_cast<internal::RetryMethodConfig*>(((*vector_ptr)[0]).get());
  847. ASSERT_NE(parsed_config, nullptr);
  848. EXPECT_EQ(parsed_config->max_attempts(), 3);
  849. EXPECT_EQ(parsed_config->initial_backoff(), Duration::Seconds(1));
  850. EXPECT_EQ(parsed_config->max_backoff(), Duration::Minutes(2));
  851. EXPECT_EQ(parsed_config->backoff_multiplier(), 1.6f);
  852. EXPECT_EQ(parsed_config->per_attempt_recv_timeout(), absl::nullopt);
  853. EXPECT_TRUE(
  854. parsed_config->retryable_status_codes().Contains(GRPC_STATUS_ABORTED));
  855. }
  856. TEST_F(RetryParserTest, InvalidRetryPolicyWrongType) {
  857. const char* test_json =
  858. "{\n"
  859. " \"methodConfig\": [ {\n"
  860. " \"name\": [\n"
  861. " { \"service\": \"TestServ\", \"method\": \"TestMethod\" }\n"
  862. " ],\n"
  863. " \"retryPolicy\": 5\n"
  864. " } ]\n"
  865. "}";
  866. grpc_error_handle error = GRPC_ERROR_NONE;
  867. auto svc_cfg = ServiceConfigImpl::Create(nullptr, test_json, &error);
  868. EXPECT_THAT(grpc_error_std_string(error),
  869. ::testing::ContainsRegex(
  870. "Service config parsing error" CHILD_ERROR_TAG
  871. "Method Params" CHILD_ERROR_TAG "methodConfig" CHILD_ERROR_TAG
  872. "field:retryPolicy error:should be of type object"));
  873. GRPC_ERROR_UNREF(error);
  874. }
  875. TEST_F(RetryParserTest, InvalidRetryPolicyRequiredFieldsMissing) {
  876. const char* test_json =
  877. "{\n"
  878. " \"methodConfig\": [ {\n"
  879. " \"name\": [\n"
  880. " { \"service\": \"TestServ\", \"method\": \"TestMethod\" }\n"
  881. " ],\n"
  882. " \"retryPolicy\": {\n"
  883. " \"retryableStatusCodes\": [ \"ABORTED\" ]\n"
  884. " }\n"
  885. " } ]\n"
  886. "}";
  887. grpc_error_handle error = GRPC_ERROR_NONE;
  888. auto svc_cfg = ServiceConfigImpl::Create(nullptr, test_json, &error);
  889. EXPECT_THAT(grpc_error_std_string(error),
  890. ::testing::ContainsRegex(
  891. "Service config parsing error" CHILD_ERROR_TAG
  892. "Method Params" CHILD_ERROR_TAG "methodConfig" CHILD_ERROR_TAG
  893. "retryPolicy" CHILD_ERROR_TAG
  894. ".*field:maxAttempts error:required field missing"
  895. ".*field:initialBackoff error:does not exist"
  896. ".*field:maxBackoff error:does not exist"
  897. ".*field:backoffMultiplier error:required field missing"));
  898. GRPC_ERROR_UNREF(error);
  899. }
  900. TEST_F(RetryParserTest, InvalidRetryPolicyMaxAttemptsWrongType) {
  901. const char* test_json =
  902. "{\n"
  903. " \"methodConfig\": [ {\n"
  904. " \"name\": [\n"
  905. " { \"service\": \"TestServ\", \"method\": \"TestMethod\" }\n"
  906. " ],\n"
  907. " \"retryPolicy\": {\n"
  908. " \"maxAttempts\": \"FOO\",\n"
  909. " \"initialBackoff\": \"1s\",\n"
  910. " \"maxBackoff\": \"120s\",\n"
  911. " \"backoffMultiplier\": 1.6,\n"
  912. " \"retryableStatusCodes\": [ \"ABORTED\" ]\n"
  913. " }\n"
  914. " } ]\n"
  915. "}";
  916. grpc_error_handle error = GRPC_ERROR_NONE;
  917. auto svc_cfg = ServiceConfigImpl::Create(nullptr, test_json, &error);
  918. EXPECT_THAT(grpc_error_std_string(error),
  919. ::testing::ContainsRegex(
  920. "Service config parsing error" CHILD_ERROR_TAG
  921. "Method Params" CHILD_ERROR_TAG "methodConfig" CHILD_ERROR_TAG
  922. "retryPolicy" CHILD_ERROR_TAG
  923. "field:maxAttempts error:should be of type number"));
  924. GRPC_ERROR_UNREF(error);
  925. }
  926. TEST_F(RetryParserTest, InvalidRetryPolicyMaxAttemptsBadValue) {
  927. const char* test_json =
  928. "{\n"
  929. " \"methodConfig\": [ {\n"
  930. " \"name\": [\n"
  931. " { \"service\": \"TestServ\", \"method\": \"TestMethod\" }\n"
  932. " ],\n"
  933. " \"retryPolicy\": {\n"
  934. " \"maxAttempts\": 1,\n"
  935. " \"initialBackoff\": \"1s\",\n"
  936. " \"maxBackoff\": \"120s\",\n"
  937. " \"backoffMultiplier\": 1.6,\n"
  938. " \"retryableStatusCodes\": [ \"ABORTED\" ]\n"
  939. " }\n"
  940. " } ]\n"
  941. "}";
  942. grpc_error_handle error = GRPC_ERROR_NONE;
  943. auto svc_cfg = ServiceConfigImpl::Create(nullptr, test_json, &error);
  944. EXPECT_THAT(grpc_error_std_string(error),
  945. ::testing::ContainsRegex(
  946. "Service config parsing error" CHILD_ERROR_TAG
  947. "Method Params" CHILD_ERROR_TAG "methodConfig" CHILD_ERROR_TAG
  948. "retryPolicy" CHILD_ERROR_TAG
  949. "field:maxAttempts error:should be at least 2"));
  950. GRPC_ERROR_UNREF(error);
  951. }
  952. TEST_F(RetryParserTest, InvalidRetryPolicyInitialBackoffWrongType) {
  953. const char* test_json =
  954. "{\n"
  955. " \"methodConfig\": [ {\n"
  956. " \"name\": [\n"
  957. " { \"service\": \"TestServ\", \"method\": \"TestMethod\" }\n"
  958. " ],\n"
  959. " \"retryPolicy\": {\n"
  960. " \"maxAttempts\": 2,\n"
  961. " \"initialBackoff\": \"1sec\",\n"
  962. " \"maxBackoff\": \"120s\",\n"
  963. " \"backoffMultiplier\": 1.6,\n"
  964. " \"retryableStatusCodes\": [ \"ABORTED\" ]\n"
  965. " }\n"
  966. " } ]\n"
  967. "}";
  968. grpc_error_handle error = GRPC_ERROR_NONE;
  969. auto svc_cfg = ServiceConfigImpl::Create(nullptr, test_json, &error);
  970. EXPECT_THAT(grpc_error_std_string(error),
  971. ::testing::ContainsRegex(
  972. "Service config parsing error" CHILD_ERROR_TAG
  973. "Method Params" CHILD_ERROR_TAG "methodConfig" CHILD_ERROR_TAG
  974. "retryPolicy" CHILD_ERROR_TAG
  975. "field:initialBackoff error:type should be STRING of the "
  976. "form given by google.proto.Duration"));
  977. GRPC_ERROR_UNREF(error);
  978. }
  979. TEST_F(RetryParserTest, InvalidRetryPolicyInitialBackoffBadValue) {
  980. const char* test_json =
  981. "{\n"
  982. " \"methodConfig\": [ {\n"
  983. " \"name\": [\n"
  984. " { \"service\": \"TestServ\", \"method\": \"TestMethod\" }\n"
  985. " ],\n"
  986. " \"retryPolicy\": {\n"
  987. " \"maxAttempts\": 2,\n"
  988. " \"initialBackoff\": \"0s\",\n"
  989. " \"maxBackoff\": \"120s\",\n"
  990. " \"backoffMultiplier\": 1.6,\n"
  991. " \"retryableStatusCodes\": [ \"ABORTED\" ]\n"
  992. " }\n"
  993. " } ]\n"
  994. "}";
  995. grpc_error_handle error = GRPC_ERROR_NONE;
  996. auto svc_cfg = ServiceConfigImpl::Create(nullptr, test_json, &error);
  997. EXPECT_THAT(grpc_error_std_string(error),
  998. ::testing::ContainsRegex(
  999. "Service config parsing error" CHILD_ERROR_TAG
  1000. "Method Params" CHILD_ERROR_TAG "methodConfig" CHILD_ERROR_TAG
  1001. "retryPolicy" CHILD_ERROR_TAG
  1002. "field:initialBackoff error:must be greater than 0"));
  1003. GRPC_ERROR_UNREF(error);
  1004. }
  1005. TEST_F(RetryParserTest, InvalidRetryPolicyMaxBackoffWrongType) {
  1006. const char* test_json =
  1007. "{\n"
  1008. " \"methodConfig\": [ {\n"
  1009. " \"name\": [\n"
  1010. " { \"service\": \"TestServ\", \"method\": \"TestMethod\" }\n"
  1011. " ],\n"
  1012. " \"retryPolicy\": {\n"
  1013. " \"maxAttempts\": 2,\n"
  1014. " \"initialBackoff\": \"1s\",\n"
  1015. " \"maxBackoff\": \"120sec\",\n"
  1016. " \"backoffMultiplier\": 1.6,\n"
  1017. " \"retryableStatusCodes\": [ \"ABORTED\" ]\n"
  1018. " }\n"
  1019. " } ]\n"
  1020. "}";
  1021. grpc_error_handle error = GRPC_ERROR_NONE;
  1022. auto svc_cfg = ServiceConfigImpl::Create(nullptr, test_json, &error);
  1023. EXPECT_THAT(grpc_error_std_string(error),
  1024. ::testing::ContainsRegex(
  1025. "Service config parsing error" CHILD_ERROR_TAG
  1026. "Method Params" CHILD_ERROR_TAG "methodConfig" CHILD_ERROR_TAG
  1027. "retryPolicy" CHILD_ERROR_TAG
  1028. "field:maxBackoff error:type should be STRING of the form "
  1029. "given by google.proto.Duration"));
  1030. GRPC_ERROR_UNREF(error);
  1031. }
  1032. TEST_F(RetryParserTest, InvalidRetryPolicyMaxBackoffBadValue) {
  1033. const char* test_json =
  1034. "{\n"
  1035. " \"methodConfig\": [ {\n"
  1036. " \"name\": [\n"
  1037. " { \"service\": \"TestServ\", \"method\": \"TestMethod\" }\n"
  1038. " ],\n"
  1039. " \"retryPolicy\": {\n"
  1040. " \"maxAttempts\": 2,\n"
  1041. " \"initialBackoff\": \"1s\",\n"
  1042. " \"maxBackoff\": \"0s\",\n"
  1043. " \"backoffMultiplier\": 1.6,\n"
  1044. " \"retryableStatusCodes\": [ \"ABORTED\" ]\n"
  1045. " }\n"
  1046. " } ]\n"
  1047. "}";
  1048. grpc_error_handle error = GRPC_ERROR_NONE;
  1049. auto svc_cfg = ServiceConfigImpl::Create(nullptr, test_json, &error);
  1050. EXPECT_THAT(grpc_error_std_string(error),
  1051. ::testing::ContainsRegex(
  1052. "Service config parsing error" CHILD_ERROR_TAG
  1053. "Method Params" CHILD_ERROR_TAG "methodConfig" CHILD_ERROR_TAG
  1054. "retryPolicy" CHILD_ERROR_TAG
  1055. "field:maxBackoff error:must be greater than 0"));
  1056. GRPC_ERROR_UNREF(error);
  1057. }
  1058. TEST_F(RetryParserTest, InvalidRetryPolicyBackoffMultiplierWrongType) {
  1059. const char* test_json =
  1060. "{\n"
  1061. " \"methodConfig\": [ {\n"
  1062. " \"name\": [\n"
  1063. " { \"service\": \"TestServ\", \"method\": \"TestMethod\" }\n"
  1064. " ],\n"
  1065. " \"retryPolicy\": {\n"
  1066. " \"maxAttempts\": 2,\n"
  1067. " \"initialBackoff\": \"1s\",\n"
  1068. " \"maxBackoff\": \"120s\",\n"
  1069. " \"backoffMultiplier\": \"1.6\",\n"
  1070. " \"retryableStatusCodes\": [ \"ABORTED\" ]\n"
  1071. " }\n"
  1072. " } ]\n"
  1073. "}";
  1074. grpc_error_handle error = GRPC_ERROR_NONE;
  1075. auto svc_cfg = ServiceConfigImpl::Create(nullptr, test_json, &error);
  1076. EXPECT_THAT(grpc_error_std_string(error),
  1077. ::testing::ContainsRegex(
  1078. "Service config parsing error" CHILD_ERROR_TAG
  1079. "Method Params" CHILD_ERROR_TAG "methodConfig" CHILD_ERROR_TAG
  1080. "retryPolicy" CHILD_ERROR_TAG
  1081. "field:backoffMultiplier error:should be of type number"));
  1082. GRPC_ERROR_UNREF(error);
  1083. }
  1084. TEST_F(RetryParserTest, InvalidRetryPolicyBackoffMultiplierBadValue) {
  1085. const char* test_json =
  1086. "{\n"
  1087. " \"methodConfig\": [ {\n"
  1088. " \"name\": [\n"
  1089. " { \"service\": \"TestServ\", \"method\": \"TestMethod\" }\n"
  1090. " ],\n"
  1091. " \"retryPolicy\": {\n"
  1092. " \"maxAttempts\": 2,\n"
  1093. " \"initialBackoff\": \"1s\",\n"
  1094. " \"maxBackoff\": \"120s\",\n"
  1095. " \"backoffMultiplier\": 0,\n"
  1096. " \"retryableStatusCodes\": [ \"ABORTED\" ]\n"
  1097. " }\n"
  1098. " } ]\n"
  1099. "}";
  1100. grpc_error_handle error = GRPC_ERROR_NONE;
  1101. auto svc_cfg = ServiceConfigImpl::Create(nullptr, test_json, &error);
  1102. EXPECT_THAT(grpc_error_std_string(error),
  1103. ::testing::ContainsRegex(
  1104. "Service config parsing error" CHILD_ERROR_TAG
  1105. "Method Params" CHILD_ERROR_TAG "methodConfig" CHILD_ERROR_TAG
  1106. "retryPolicy" CHILD_ERROR_TAG
  1107. "field:backoffMultiplier error:must be greater than 0"));
  1108. GRPC_ERROR_UNREF(error);
  1109. }
  1110. TEST_F(RetryParserTest, InvalidRetryPolicyEmptyRetryableStatusCodes) {
  1111. const char* test_json =
  1112. "{\n"
  1113. " \"methodConfig\": [ {\n"
  1114. " \"name\": [\n"
  1115. " { \"service\": \"TestServ\", \"method\": \"TestMethod\" }\n"
  1116. " ],\n"
  1117. " \"retryPolicy\": {\n"
  1118. " \"maxAttempts\": 2,\n"
  1119. " \"initialBackoff\": \"1s\",\n"
  1120. " \"maxBackoff\": \"120s\",\n"
  1121. " \"backoffMultiplier\": \"1.6\",\n"
  1122. " \"retryableStatusCodes\": []\n"
  1123. " }\n"
  1124. " } ]\n"
  1125. "}";
  1126. grpc_error_handle error = GRPC_ERROR_NONE;
  1127. auto svc_cfg = ServiceConfigImpl::Create(nullptr, test_json, &error);
  1128. EXPECT_THAT(grpc_error_std_string(error),
  1129. ::testing::ContainsRegex(
  1130. "Service config parsing error" CHILD_ERROR_TAG
  1131. "Method Params" CHILD_ERROR_TAG "methodConfig" CHILD_ERROR_TAG
  1132. "retryPolicy" CHILD_ERROR_TAG
  1133. "field:retryableStatusCodes error:must be non-empty"));
  1134. GRPC_ERROR_UNREF(error);
  1135. }
  1136. TEST_F(RetryParserTest, InvalidRetryPolicyRetryableStatusCodesWrongType) {
  1137. const char* test_json =
  1138. "{\n"
  1139. " \"methodConfig\": [ {\n"
  1140. " \"name\": [\n"
  1141. " { \"service\": \"TestServ\", \"method\": \"TestMethod\" }\n"
  1142. " ],\n"
  1143. " \"retryPolicy\": {\n"
  1144. " \"maxAttempts\": 2,\n"
  1145. " \"initialBackoff\": \"1s\",\n"
  1146. " \"maxBackoff\": \"120s\",\n"
  1147. " \"backoffMultiplier\": \"1.6\",\n"
  1148. " \"retryableStatusCodes\": 0\n"
  1149. " }\n"
  1150. " } ]\n"
  1151. "}";
  1152. grpc_error_handle error = GRPC_ERROR_NONE;
  1153. auto svc_cfg = ServiceConfigImpl::Create(nullptr, test_json, &error);
  1154. EXPECT_THAT(grpc_error_std_string(error),
  1155. ::testing::ContainsRegex(
  1156. "Service config parsing error" CHILD_ERROR_TAG
  1157. "Method Params" CHILD_ERROR_TAG "methodConfig" CHILD_ERROR_TAG
  1158. "retryPolicy" CHILD_ERROR_TAG
  1159. "field:retryableStatusCodes error:must be of type array"));
  1160. GRPC_ERROR_UNREF(error);
  1161. }
  1162. TEST_F(RetryParserTest, InvalidRetryPolicyUnparseableRetryableStatusCodes) {
  1163. const char* test_json =
  1164. "{\n"
  1165. " \"methodConfig\": [ {\n"
  1166. " \"name\": [\n"
  1167. " { \"service\": \"TestServ\", \"method\": \"TestMethod\" }\n"
  1168. " ],\n"
  1169. " \"retryPolicy\": {\n"
  1170. " \"maxAttempts\": 2,\n"
  1171. " \"initialBackoff\": \"1s\",\n"
  1172. " \"maxBackoff\": \"120s\",\n"
  1173. " \"backoffMultiplier\": \"1.6\",\n"
  1174. " \"retryableStatusCodes\": [\"FOO\", 2]\n"
  1175. " }\n"
  1176. " } ]\n"
  1177. "}";
  1178. grpc_error_handle error = GRPC_ERROR_NONE;
  1179. auto svc_cfg = ServiceConfigImpl::Create(nullptr, test_json, &error);
  1180. EXPECT_THAT(grpc_error_std_string(error),
  1181. ::testing::ContainsRegex(
  1182. "Service config parsing error" CHILD_ERROR_TAG
  1183. "Method Params" CHILD_ERROR_TAG "methodConfig" CHILD_ERROR_TAG
  1184. "retryPolicy" CHILD_ERROR_TAG "field:retryableStatusCodes "
  1185. "error:failed to parse status code"
  1186. ".*field:retryableStatusCodes "
  1187. "error:status codes should be of type string"));
  1188. GRPC_ERROR_UNREF(error);
  1189. }
  1190. TEST_F(RetryParserTest, ValidRetryPolicyWithPerAttemptRecvTimeout) {
  1191. const char* test_json =
  1192. "{\n"
  1193. " \"methodConfig\": [ {\n"
  1194. " \"name\": [\n"
  1195. " { \"service\": \"TestServ\", \"method\": \"TestMethod\" }\n"
  1196. " ],\n"
  1197. " \"retryPolicy\": {\n"
  1198. " \"maxAttempts\": 2,\n"
  1199. " \"initialBackoff\": \"1s\",\n"
  1200. " \"maxBackoff\": \"120s\",\n"
  1201. " \"backoffMultiplier\": 1.6,\n"
  1202. " \"perAttemptRecvTimeout\": \"1s\",\n"
  1203. " \"retryableStatusCodes\": [\"ABORTED\"]\n"
  1204. " }\n"
  1205. " } ]\n"
  1206. "}";
  1207. grpc_error_handle error = GRPC_ERROR_NONE;
  1208. grpc_arg arg = grpc_channel_arg_integer_create(
  1209. const_cast<char*>(GRPC_ARG_EXPERIMENTAL_ENABLE_HEDGING), 1);
  1210. grpc_channel_args args = {1, &arg};
  1211. auto svc_cfg = ServiceConfigImpl::Create(&args, test_json, &error);
  1212. ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error);
  1213. const auto* vector_ptr = svc_cfg->GetMethodParsedConfigVector(
  1214. grpc_slice_from_static_string("/TestServ/TestMethod"));
  1215. ASSERT_NE(vector_ptr, nullptr);
  1216. const auto* parsed_config =
  1217. static_cast<internal::RetryMethodConfig*>(((*vector_ptr)[0]).get());
  1218. ASSERT_NE(parsed_config, nullptr);
  1219. EXPECT_EQ(parsed_config->max_attempts(), 2);
  1220. EXPECT_EQ(parsed_config->initial_backoff(), Duration::Seconds(1));
  1221. EXPECT_EQ(parsed_config->max_backoff(), Duration::Minutes(2));
  1222. EXPECT_EQ(parsed_config->backoff_multiplier(), 1.6f);
  1223. EXPECT_EQ(parsed_config->per_attempt_recv_timeout(), Duration::Seconds(1));
  1224. EXPECT_TRUE(
  1225. parsed_config->retryable_status_codes().Contains(GRPC_STATUS_ABORTED));
  1226. }
  1227. TEST_F(RetryParserTest,
  1228. ValidRetryPolicyWithPerAttemptRecvTimeoutIgnoredWhenHedgingDisabled) {
  1229. const char* test_json =
  1230. "{\n"
  1231. " \"methodConfig\": [ {\n"
  1232. " \"name\": [\n"
  1233. " { \"service\": \"TestServ\", \"method\": \"TestMethod\" }\n"
  1234. " ],\n"
  1235. " \"retryPolicy\": {\n"
  1236. " \"maxAttempts\": 2,\n"
  1237. " \"initialBackoff\": \"1s\",\n"
  1238. " \"maxBackoff\": \"120s\",\n"
  1239. " \"backoffMultiplier\": 1.6,\n"
  1240. " \"perAttemptRecvTimeout\": \"1s\",\n"
  1241. " \"retryableStatusCodes\": [\"ABORTED\"]\n"
  1242. " }\n"
  1243. " } ]\n"
  1244. "}";
  1245. grpc_error_handle error = GRPC_ERROR_NONE;
  1246. auto svc_cfg = ServiceConfigImpl::Create(nullptr, test_json, &error);
  1247. ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error);
  1248. const auto* vector_ptr = svc_cfg->GetMethodParsedConfigVector(
  1249. grpc_slice_from_static_string("/TestServ/TestMethod"));
  1250. ASSERT_NE(vector_ptr, nullptr);
  1251. const auto* parsed_config =
  1252. static_cast<internal::RetryMethodConfig*>(((*vector_ptr)[0]).get());
  1253. ASSERT_NE(parsed_config, nullptr);
  1254. EXPECT_EQ(parsed_config->max_attempts(), 2);
  1255. EXPECT_EQ(parsed_config->initial_backoff(), Duration::Seconds(1));
  1256. EXPECT_EQ(parsed_config->max_backoff(), Duration::Minutes(2));
  1257. EXPECT_EQ(parsed_config->backoff_multiplier(), 1.6f);
  1258. EXPECT_EQ(parsed_config->per_attempt_recv_timeout(), absl::nullopt);
  1259. EXPECT_TRUE(
  1260. parsed_config->retryable_status_codes().Contains(GRPC_STATUS_ABORTED));
  1261. }
  1262. TEST_F(RetryParserTest,
  1263. ValidRetryPolicyWithPerAttemptRecvTimeoutAndUnsetRetryableStatusCodes) {
  1264. const char* test_json =
  1265. "{\n"
  1266. " \"methodConfig\": [ {\n"
  1267. " \"name\": [\n"
  1268. " { \"service\": \"TestServ\", \"method\": \"TestMethod\" }\n"
  1269. " ],\n"
  1270. " \"retryPolicy\": {\n"
  1271. " \"maxAttempts\": 2,\n"
  1272. " \"initialBackoff\": \"1s\",\n"
  1273. " \"maxBackoff\": \"120s\",\n"
  1274. " \"backoffMultiplier\": 1.6,\n"
  1275. " \"perAttemptRecvTimeout\": \"1s\"\n"
  1276. " }\n"
  1277. " } ]\n"
  1278. "}";
  1279. grpc_error_handle error = GRPC_ERROR_NONE;
  1280. grpc_arg arg = grpc_channel_arg_integer_create(
  1281. const_cast<char*>(GRPC_ARG_EXPERIMENTAL_ENABLE_HEDGING), 1);
  1282. grpc_channel_args args = {1, &arg};
  1283. auto svc_cfg = ServiceConfigImpl::Create(&args, test_json, &error);
  1284. ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error);
  1285. const auto* vector_ptr = svc_cfg->GetMethodParsedConfigVector(
  1286. grpc_slice_from_static_string("/TestServ/TestMethod"));
  1287. ASSERT_NE(vector_ptr, nullptr);
  1288. const auto* parsed_config =
  1289. static_cast<internal::RetryMethodConfig*>(((*vector_ptr)[0]).get());
  1290. ASSERT_NE(parsed_config, nullptr);
  1291. EXPECT_EQ(parsed_config->max_attempts(), 2);
  1292. EXPECT_EQ(parsed_config->initial_backoff(), Duration::Seconds(1));
  1293. EXPECT_EQ(parsed_config->max_backoff(), Duration::Minutes(2));
  1294. EXPECT_EQ(parsed_config->backoff_multiplier(), 1.6f);
  1295. EXPECT_EQ(parsed_config->per_attempt_recv_timeout(), Duration::Seconds(1));
  1296. EXPECT_TRUE(parsed_config->retryable_status_codes().Empty());
  1297. }
  1298. TEST_F(RetryParserTest, InvalidRetryPolicyPerAttemptRecvTimeoutUnparseable) {
  1299. const char* test_json =
  1300. "{\n"
  1301. " \"methodConfig\": [ {\n"
  1302. " \"name\": [\n"
  1303. " { \"service\": \"TestServ\", \"method\": \"TestMethod\" }\n"
  1304. " ],\n"
  1305. " \"retryPolicy\": {\n"
  1306. " \"maxAttempts\": 2,\n"
  1307. " \"initialBackoff\": \"1s\",\n"
  1308. " \"maxBackoff\": \"120s\",\n"
  1309. " \"backoffMultiplier\": \"1.6\",\n"
  1310. " \"perAttemptRecvTimeout\": \"1sec\",\n"
  1311. " \"retryableStatusCodes\": [\"ABORTED\"]\n"
  1312. " }\n"
  1313. " } ]\n"
  1314. "}";
  1315. grpc_error_handle error = GRPC_ERROR_NONE;
  1316. grpc_arg arg = grpc_channel_arg_integer_create(
  1317. const_cast<char*>(GRPC_ARG_EXPERIMENTAL_ENABLE_HEDGING), 1);
  1318. grpc_channel_args args = {1, &arg};
  1319. auto svc_cfg = ServiceConfigImpl::Create(&args, test_json, &error);
  1320. EXPECT_THAT(grpc_error_std_string(error),
  1321. ::testing::ContainsRegex(
  1322. "Service config parsing error" CHILD_ERROR_TAG
  1323. "Method Params" CHILD_ERROR_TAG "methodConfig" CHILD_ERROR_TAG
  1324. "retryPolicy" CHILD_ERROR_TAG
  1325. "field:perAttemptRecvTimeout error:type must be STRING "
  1326. "of the form given by google.proto.Duration."));
  1327. GRPC_ERROR_UNREF(error);
  1328. }
  1329. TEST_F(RetryParserTest, InvalidRetryPolicyPerAttemptRecvTimeoutWrongType) {
  1330. const char* test_json =
  1331. "{\n"
  1332. " \"methodConfig\": [ {\n"
  1333. " \"name\": [\n"
  1334. " { \"service\": \"TestServ\", \"method\": \"TestMethod\" }\n"
  1335. " ],\n"
  1336. " \"retryPolicy\": {\n"
  1337. " \"maxAttempts\": 2,\n"
  1338. " \"initialBackoff\": \"1s\",\n"
  1339. " \"maxBackoff\": \"120s\",\n"
  1340. " \"backoffMultiplier\": \"1.6\",\n"
  1341. " \"perAttemptRecvTimeout\": 1,\n"
  1342. " \"retryableStatusCodes\": [\"ABORTED\"]\n"
  1343. " }\n"
  1344. " } ]\n"
  1345. "}";
  1346. grpc_error_handle error = GRPC_ERROR_NONE;
  1347. grpc_arg arg = grpc_channel_arg_integer_create(
  1348. const_cast<char*>(GRPC_ARG_EXPERIMENTAL_ENABLE_HEDGING), 1);
  1349. grpc_channel_args args = {1, &arg};
  1350. auto svc_cfg = ServiceConfigImpl::Create(&args, test_json, &error);
  1351. EXPECT_THAT(grpc_error_std_string(error),
  1352. ::testing::ContainsRegex(
  1353. "Service config parsing error" CHILD_ERROR_TAG
  1354. "Method Params" CHILD_ERROR_TAG "methodConfig" CHILD_ERROR_TAG
  1355. "retryPolicy" CHILD_ERROR_TAG
  1356. "field:perAttemptRecvTimeout error:type must be STRING "
  1357. "of the form given by google.proto.Duration."));
  1358. GRPC_ERROR_UNREF(error);
  1359. }
  1360. TEST_F(RetryParserTest, InvalidRetryPolicyPerAttemptRecvTimeoutBadValue) {
  1361. const char* test_json =
  1362. "{\n"
  1363. " \"methodConfig\": [ {\n"
  1364. " \"name\": [\n"
  1365. " { \"service\": \"TestServ\", \"method\": \"TestMethod\" }\n"
  1366. " ],\n"
  1367. " \"retryPolicy\": {\n"
  1368. " \"maxAttempts\": 2,\n"
  1369. " \"initialBackoff\": \"1s\",\n"
  1370. " \"maxBackoff\": \"120s\",\n"
  1371. " \"backoffMultiplier\": \"1.6\",\n"
  1372. " \"perAttemptRecvTimeout\": \"0s\",\n"
  1373. " \"retryableStatusCodes\": [\"ABORTED\"]\n"
  1374. " }\n"
  1375. " } ]\n"
  1376. "}";
  1377. grpc_error_handle error = GRPC_ERROR_NONE;
  1378. grpc_arg arg = grpc_channel_arg_integer_create(
  1379. const_cast<char*>(GRPC_ARG_EXPERIMENTAL_ENABLE_HEDGING), 1);
  1380. grpc_channel_args args = {1, &arg};
  1381. auto svc_cfg = ServiceConfigImpl::Create(&args, test_json, &error);
  1382. EXPECT_THAT(grpc_error_std_string(error),
  1383. ::testing::ContainsRegex(
  1384. "Service config parsing error" CHILD_ERROR_TAG
  1385. "Method Params" CHILD_ERROR_TAG "methodConfig" CHILD_ERROR_TAG
  1386. "retryPolicy" CHILD_ERROR_TAG
  1387. "field:perAttemptRecvTimeout error:must be greater than 0"));
  1388. GRPC_ERROR_UNREF(error);
  1389. }
  1390. //
  1391. // message_size parser tests
  1392. //
  1393. class MessageSizeParserTest : public ::testing::Test {
  1394. protected:
  1395. void SetUp() override {
  1396. CoreConfiguration::Reset();
  1397. CoreConfiguration::BuildSpecialConfiguration(
  1398. [](CoreConfiguration::Builder* builder) {
  1399. builder->service_config_parser()->RegisterParser(
  1400. absl::make_unique<MessageSizeParser>());
  1401. });
  1402. EXPECT_EQ(CoreConfiguration::Get().service_config_parser().GetParserIndex(
  1403. "message_size"),
  1404. 0);
  1405. }
  1406. };
  1407. TEST_F(MessageSizeParserTest, Valid) {
  1408. const char* test_json =
  1409. "{\n"
  1410. " \"methodConfig\": [ {\n"
  1411. " \"name\": [\n"
  1412. " { \"service\": \"TestServ\", \"method\": \"TestMethod\" }\n"
  1413. " ],\n"
  1414. " \"maxRequestMessageBytes\": 1024,\n"
  1415. " \"maxResponseMessageBytes\": 1024\n"
  1416. " } ]\n"
  1417. "}";
  1418. grpc_error_handle error = GRPC_ERROR_NONE;
  1419. auto svc_cfg = ServiceConfigImpl::Create(nullptr, test_json, &error);
  1420. ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error);
  1421. const auto* vector_ptr = svc_cfg->GetMethodParsedConfigVector(
  1422. grpc_slice_from_static_string("/TestServ/TestMethod"));
  1423. ASSERT_NE(vector_ptr, nullptr);
  1424. auto parsed_config =
  1425. static_cast<MessageSizeParsedConfig*>(((*vector_ptr)[0]).get());
  1426. ASSERT_NE(parsed_config, nullptr);
  1427. EXPECT_EQ(parsed_config->limits().max_send_size, 1024);
  1428. EXPECT_EQ(parsed_config->limits().max_recv_size, 1024);
  1429. }
  1430. TEST_F(MessageSizeParserTest, InvalidMaxRequestMessageBytes) {
  1431. const char* test_json =
  1432. "{\n"
  1433. " \"methodConfig\": [ {\n"
  1434. " \"name\": [\n"
  1435. " { \"service\": \"TestServ\", \"method\": \"TestMethod\" }\n"
  1436. " ],\n"
  1437. " \"maxRequestMessageBytes\": -1024\n"
  1438. " } ]\n"
  1439. "}";
  1440. grpc_error_handle error = GRPC_ERROR_NONE;
  1441. auto svc_cfg = ServiceConfigImpl::Create(nullptr, test_json, &error);
  1442. EXPECT_THAT(grpc_error_std_string(error),
  1443. ::testing::ContainsRegex(
  1444. "Service config parsing error" CHILD_ERROR_TAG
  1445. "Method Params" CHILD_ERROR_TAG "methodConfig" CHILD_ERROR_TAG
  1446. "Message size parser" CHILD_ERROR_TAG
  1447. "field:maxRequestMessageBytes error:should be non-negative"));
  1448. GRPC_ERROR_UNREF(error);
  1449. }
  1450. TEST_F(MessageSizeParserTest, InvalidMaxResponseMessageBytes) {
  1451. const char* test_json =
  1452. "{\n"
  1453. " \"methodConfig\": [ {\n"
  1454. " \"name\": [\n"
  1455. " { \"service\": \"TestServ\", \"method\": \"TestMethod\" }\n"
  1456. " ],\n"
  1457. " \"maxResponseMessageBytes\": {}\n"
  1458. " } ]\n"
  1459. "}";
  1460. grpc_error_handle error = GRPC_ERROR_NONE;
  1461. auto svc_cfg = ServiceConfigImpl::Create(nullptr, test_json, &error);
  1462. EXPECT_THAT(grpc_error_std_string(error),
  1463. ::testing::ContainsRegex(
  1464. "Service config parsing error" CHILD_ERROR_TAG
  1465. "Method Params" CHILD_ERROR_TAG "methodConfig" CHILD_ERROR_TAG
  1466. "Message size parser" CHILD_ERROR_TAG
  1467. "field:maxResponseMessageBytes error:should be of type "
  1468. "number"));
  1469. GRPC_ERROR_UNREF(error);
  1470. }
  1471. } // namespace testing
  1472. } // namespace grpc_core
  1473. int main(int argc, char** argv) {
  1474. ::testing::InitGoogleTest(&argc, argv);
  1475. grpc::testing::TestEnvironment env(argc, argv);
  1476. grpc_init();
  1477. int ret = RUN_ALL_TESTS();
  1478. grpc_shutdown();
  1479. return ret;
  1480. }