• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2019 gRPC authors.
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //     http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16 
17 #include <regex>
18 
19 #include <gmock/gmock.h>
20 #include <gtest/gtest.h>
21 
22 #include <grpc/grpc.h>
23 #include <grpc/slice.h>
24 
25 #include "src/core/ext/filters/client_channel/xds/xds_bootstrap.h"
26 #include "test/core/util/test_config.h"
27 
28 namespace grpc_core {
29 namespace testing {
30 
VerifyRegexMatch(grpc_error * error,const std::regex & e)31 void VerifyRegexMatch(grpc_error* error, const std::regex& e) {
32   std::smatch match;
33   std::string s(grpc_error_string(error));
34   EXPECT_TRUE(std::regex_search(s, match, e));
35   GRPC_ERROR_UNREF(error);
36 }
37 
TEST(XdsBootstrapTest,Basic)38 TEST(XdsBootstrapTest, Basic) {
39   const char* json_str =
40       "{"
41       "  \"xds_servers\": ["
42       "    {"
43       "      \"server_uri\": \"fake:///lb\","
44       "      \"channel_creds\": ["
45       "        {"
46       "          \"type\": \"fake\","
47       "          \"ignore\": 0"
48       "        }"
49       "      ],"
50       "      \"ignore\": 0"
51       "    },"
52       "    {"
53       "      \"server_uri\": \"ignored\","
54       "      \"channel_creds\": ["
55       "        {"
56       "          \"type\": \"ignored\","
57       "          \"ignore\": 0"
58       "        }"
59       "      ],"
60       "      \"ignore\": 0"
61       "    }"
62       "  ],"
63       "  \"node\": {"
64       "    \"id\": \"foo\","
65       "    \"cluster\": \"bar\","
66       "    \"locality\": {"
67       "      \"region\": \"milky_way\","
68       "      \"zone\": \"sol_system\","
69       "      \"subzone\": \"earth\","
70       "      \"ignore\": {}"
71       "    },"
72       "    \"metadata\": {"
73       "      \"foo\": 1,"
74       "      \"bar\": 2"
75       "    },"
76       "    \"ignore\": \"whee\""
77       "  },"
78       "  \"ignore\": {}"
79       "}";
80   grpc_error* error = GRPC_ERROR_NONE;
81   Json json = Json::Parse(json_str, &error);
82   ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error);
83   grpc_core::XdsBootstrap bootstrap(std::move(json), &error);
84   EXPECT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error);
85   EXPECT_EQ(bootstrap.server().server_uri, "fake:///lb");
86   ASSERT_EQ(bootstrap.server().channel_creds.size(), 1UL);
87   EXPECT_EQ(bootstrap.server().channel_creds[0].type, "fake");
88   EXPECT_EQ(bootstrap.server().channel_creds[0].config.type(),
89             Json::Type::JSON_NULL);
90   ASSERT_NE(bootstrap.node(), nullptr);
91   EXPECT_EQ(bootstrap.node()->id, "foo");
92   EXPECT_EQ(bootstrap.node()->cluster, "bar");
93   EXPECT_EQ(bootstrap.node()->locality_region, "milky_way");
94   EXPECT_EQ(bootstrap.node()->locality_zone, "sol_system");
95   EXPECT_EQ(bootstrap.node()->locality_subzone, "earth");
96   ASSERT_EQ(bootstrap.node()->metadata.type(), Json::Type::OBJECT);
97   EXPECT_THAT(bootstrap.node()->metadata.object_value(),
98               ::testing::ElementsAre(
99                   ::testing::Pair(
100                       ::testing::Eq("bar"),
101                       ::testing::AllOf(
102                           ::testing::Property(&Json::type, Json::Type::NUMBER),
103                           ::testing::Property(&Json::string_value, "2"))),
104                   ::testing::Pair(
105                       ::testing::Eq("foo"),
106                       ::testing::AllOf(
107                           ::testing::Property(&Json::type, Json::Type::NUMBER),
108                           ::testing::Property(&Json::string_value, "1")))));
109 }
110 
TEST(XdsBootstrapTest,ValidWithoutChannelCredsAndNode)111 TEST(XdsBootstrapTest, ValidWithoutChannelCredsAndNode) {
112   const char* json_str =
113       "{"
114       "  \"xds_servers\": ["
115       "    {"
116       "      \"server_uri\": \"fake:///lb\""
117       "    }"
118       "  ]"
119       "}";
120   grpc_error* error = GRPC_ERROR_NONE;
121   Json json = Json::Parse(json_str, &error);
122   ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error);
123   grpc_core::XdsBootstrap bootstrap(std::move(json), &error);
124   EXPECT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error);
125   EXPECT_EQ(bootstrap.server().server_uri, "fake:///lb");
126   EXPECT_EQ(bootstrap.server().channel_creds.size(), 0UL);
127   EXPECT_EQ(bootstrap.node(), nullptr);
128 }
129 
TEST(XdsBootstrapTest,MissingXdsServers)130 TEST(XdsBootstrapTest, MissingXdsServers) {
131   grpc_error* error = GRPC_ERROR_NONE;
132   Json json = Json::Parse("{}", &error);
133   ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error);
134   grpc_core::XdsBootstrap bootstrap(std::move(json), &error);
135   gpr_log(GPR_ERROR, "%s", grpc_error_string(error));
136   ASSERT_TRUE(error != GRPC_ERROR_NONE);
137   std::regex e(std::string("\"xds_servers\" field not present"));
138   VerifyRegexMatch(error, e);
139 }
140 
TEST(XdsBootstrapTest,TopFieldsWrongTypes)141 TEST(XdsBootstrapTest, TopFieldsWrongTypes) {
142   const char* json_str =
143       "{"
144       "  \"xds_servers\":1,"
145       "  \"node\":1"
146       "}";
147   grpc_error* error = GRPC_ERROR_NONE;
148   Json json = Json::Parse(json_str, &error);
149   ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error);
150   grpc_core::XdsBootstrap bootstrap(std::move(json), &error);
151   gpr_log(GPR_ERROR, "%s", grpc_error_string(error));
152   ASSERT_TRUE(error != GRPC_ERROR_NONE);
153   std::regex e(
154       std::string("\"xds_servers\" field is not an array(.*)"
155                   "\"node\" field is not an object"));
156   VerifyRegexMatch(error, e);
157 }
158 
TEST(XdsBootstrapTest,XdsServerMissingServerUri)159 TEST(XdsBootstrapTest, XdsServerMissingServerUri) {
160   const char* json_str =
161       "{"
162       "  \"xds_servers\":[{}]"
163       "}";
164   grpc_error* error = GRPC_ERROR_NONE;
165   Json json = Json::Parse(json_str, &error);
166   ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error);
167   grpc_core::XdsBootstrap bootstrap(std::move(json), &error);
168   gpr_log(GPR_ERROR, "%s", grpc_error_string(error));
169   ASSERT_TRUE(error != GRPC_ERROR_NONE);
170   std::regex e(
171       std::string("errors parsing \"xds_servers\" array(.*)"
172                   "errors parsing index 0(.*)"
173                   "\"server_uri\" field not present"));
174   VerifyRegexMatch(error, e);
175 }
176 
TEST(XdsBootstrapTest,XdsServerUriAndCredsWrongTypes)177 TEST(XdsBootstrapTest, XdsServerUriAndCredsWrongTypes) {
178   const char* json_str =
179       "{"
180       "  \"xds_servers\":["
181       "    {"
182       "      \"server_uri\":1,"
183       "      \"channel_creds\":1"
184       "    }"
185       "  ]"
186       "}";
187   grpc_error* error = GRPC_ERROR_NONE;
188   Json json = Json::Parse(json_str, &error);
189   ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error);
190   grpc_core::XdsBootstrap bootstrap(std::move(json), &error);
191   gpr_log(GPR_ERROR, "%s", grpc_error_string(error));
192   ASSERT_TRUE(error != GRPC_ERROR_NONE);
193   std::regex e(
194       std::string("errors parsing \"xds_servers\" array(.*)"
195                   "errors parsing index 0(.*)"
196                   "\"server_uri\" field is not a string(.*)"
197                   "\"channel_creds\" field is not an array"));
198   VerifyRegexMatch(error, e);
199 }
200 
TEST(XdsBootstrapTest,ChannelCredsFieldsWrongTypes)201 TEST(XdsBootstrapTest, ChannelCredsFieldsWrongTypes) {
202   const char* json_str =
203       "{"
204       "  \"xds_servers\":["
205       "    {"
206       "      \"server_uri\":\"foo\","
207       "      \"channel_creds\":["
208       "        {"
209       "          \"type\":0,"
210       "          \"config\":1"
211       "        }"
212       "      ]"
213       "    }"
214       "  ]"
215       "}";
216   grpc_error* error = GRPC_ERROR_NONE;
217   Json json = Json::Parse(json_str, &error);
218   ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error);
219   grpc_core::XdsBootstrap bootstrap(std::move(json), &error);
220   gpr_log(GPR_ERROR, "%s", grpc_error_string(error));
221   ASSERT_TRUE(error != GRPC_ERROR_NONE);
222   std::regex e(
223       std::string("errors parsing \"xds_servers\" array(.*)"
224                   "errors parsing index 0(.*)"
225                   "errors parsing \"channel_creds\" array(.*)"
226                   "errors parsing index 0(.*)"
227                   "\"type\" field is not a string(.*)"
228                   "\"config\" field is not an object"));
229   VerifyRegexMatch(error, e);
230 }
231 
TEST(XdsBootstrapTest,NodeFieldsWrongTypes)232 TEST(XdsBootstrapTest, NodeFieldsWrongTypes) {
233   const char* json_str =
234       "{"
235       "  \"node\":{"
236       "    \"id\":0,"
237       "    \"cluster\":0,"
238       "    \"locality\":0,"
239       "    \"metadata\":0"
240       "  }"
241       "}";
242   grpc_error* error = GRPC_ERROR_NONE;
243   Json json = Json::Parse(json_str, &error);
244   ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error);
245   grpc_core::XdsBootstrap bootstrap(std::move(json), &error);
246   gpr_log(GPR_ERROR, "%s", grpc_error_string(error));
247   ASSERT_TRUE(error != GRPC_ERROR_NONE);
248   std::regex e(
249       std::string("errors parsing \"node\" object(.*)"
250                   "\"id\" field is not a string(.*)"
251                   "\"cluster\" field is not a string(.*)"
252                   "\"locality\" field is not an object(.*)"
253                   "\"metadata\" field is not an object"));
254   VerifyRegexMatch(error, e);
255 }
256 
TEST(XdsBootstrapTest,LocalityFieldsWrongType)257 TEST(XdsBootstrapTest, LocalityFieldsWrongType) {
258   const char* json_str =
259       "{"
260       "  \"node\":{"
261       "    \"locality\":{"
262       "      \"region\":0,"
263       "      \"zone\":0,"
264       "      \"subzone\":0"
265       "    }"
266       "  }"
267       "}";
268   grpc_error* error = GRPC_ERROR_NONE;
269   Json json = Json::Parse(json_str, &error);
270   ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error);
271   grpc_core::XdsBootstrap bootstrap(std::move(json), &error);
272   gpr_log(GPR_ERROR, "%s", grpc_error_string(error));
273   ASSERT_TRUE(error != GRPC_ERROR_NONE);
274   std::regex e(
275       std::string("errors parsing \"node\" object(.*)"
276                   "errors parsing \"locality\" object(.*)"
277                   "\"region\" field is not a string(.*)"
278                   "\"zone\" field is not a string(.*)"
279                   "\"subzone\" field is not a string"));
280   VerifyRegexMatch(error, e);
281 }
282 
283 }  // namespace testing
284 }  // namespace grpc_core
285 
main(int argc,char ** argv)286 int main(int argc, char** argv) {
287 // Regexes don't work in old libstdc++ versions, so just skip testing in those
288 // cases
289 #if defined(__GLIBCXX__) && (__GLIBCXX__ <= 20150623)
290   gpr_log(GPR_ERROR,
291           "Skipping xds_bootstrap_test since std::regex is not supported on "
292           "this system.");
293   return 0;
294 #endif
295   ::testing::InitGoogleTest(&argc, argv);
296   grpc::testing::TestEnvironment env(argc, argv);
297   grpc_init();
298   int ret = RUN_ALL_TESTS();
299   grpc_shutdown();
300   return ret;
301 }
302