• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *
3  * Copyright 2017 gRPC authors.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18 
19 #include <string.h>
20 
21 #include <grpc/support/alloc.h>
22 #include <grpc/support/log.h>
23 #include <grpc/support/string_util.h>
24 
25 #include "src/core/ext/filters/client_channel/lb_policy_factory.h"
26 #include "src/core/ext/filters/client_channel/parse_address.h"
27 #include "src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h"
28 #include "src/core/ext/filters/client_channel/resolver_registry.h"
29 #include "src/core/lib/channel/channel_args.h"
30 #include "src/core/lib/gprpp/ref_counted_ptr.h"
31 #include "src/core/lib/iomgr/combiner.h"
32 #include "src/core/lib/security/credentials/fake/fake_credentials.h"
33 
34 #include "test/core/util/test_config.h"
35 
build_fake_resolver(grpc_combiner * combiner,grpc_core::FakeResolverResponseGenerator * response_generator)36 static grpc_core::OrphanablePtr<grpc_core::Resolver> build_fake_resolver(
37     grpc_combiner* combiner,
38     grpc_core::FakeResolverResponseGenerator* response_generator) {
39   grpc_core::ResolverFactory* factory =
40       grpc_core::ResolverRegistry::LookupResolverFactory("fake");
41   grpc_arg generator_arg =
42       grpc_core::FakeResolverResponseGenerator::MakeChannelArg(
43           response_generator);
44   grpc_channel_args channel_args = {1, &generator_arg};
45   grpc_core::ResolverArgs args;
46   args.args = &channel_args;
47   args.combiner = combiner;
48   grpc_core::OrphanablePtr<grpc_core::Resolver> resolver =
49       factory->CreateResolver(args);
50   return resolver;
51 }
52 
53 typedef struct on_resolution_arg {
54   grpc_channel_args* resolver_result;
55   grpc_channel_args* expected_resolver_result;
56   gpr_event ev;
57 } on_resolution_arg;
58 
59 // Callback to check the resolution result is as expected.
on_resolution_cb(void * arg,grpc_error * error)60 void on_resolution_cb(void* arg, grpc_error* error) {
61   if (error != GRPC_ERROR_NONE) return;
62   on_resolution_arg* res = static_cast<on_resolution_arg*>(arg);
63   // We only check the addresses channel arg because that's the only one
64   // explicitly set by the test via
65   // FakeResolverResponseGenerator::SetResponse().
66   const grpc_lb_addresses* actual_lb_addresses =
67       grpc_lb_addresses_find_channel_arg(res->resolver_result);
68   const grpc_lb_addresses* expected_lb_addresses =
69       grpc_lb_addresses_find_channel_arg(res->expected_resolver_result);
70   GPR_ASSERT(
71       grpc_lb_addresses_cmp(actual_lb_addresses, expected_lb_addresses) == 0);
72   grpc_channel_args_destroy(res->resolver_result);
73   grpc_channel_args_destroy(res->expected_resolver_result);
74   gpr_event_set(&res->ev, (void*)1);
75 }
76 
77 // Create a new resolution containing 2 addresses.
create_new_resolver_result()78 static grpc_channel_args* create_new_resolver_result() {
79   static size_t test_counter = 0;
80   const size_t num_addresses = 2;
81   char* uri_string;
82   char* balancer_name;
83   // Create grpc_lb_addresses.
84   grpc_lb_addresses* addresses =
85       grpc_lb_addresses_create(num_addresses, nullptr);
86   for (size_t i = 0; i < num_addresses; ++i) {
87     gpr_asprintf(&uri_string, "ipv4:127.0.0.1:100%" PRIuPTR,
88                  test_counter * num_addresses + i);
89     grpc_uri* uri = grpc_uri_parse(uri_string, true);
90     gpr_asprintf(&balancer_name, "balancer%" PRIuPTR,
91                  test_counter * num_addresses + i);
92     grpc_lb_addresses_set_address_from_uri(
93         addresses, i, uri, bool(num_addresses % 2), balancer_name, nullptr);
94     gpr_free(balancer_name);
95     grpc_uri_destroy(uri);
96     gpr_free(uri_string);
97   }
98   // Convert grpc_lb_addresses to grpc_channel_args.
99   const grpc_arg addresses_arg =
100       grpc_lb_addresses_create_channel_arg(addresses);
101   grpc_channel_args* results =
102       grpc_channel_args_copy_and_add(nullptr, &addresses_arg, 1);
103   grpc_lb_addresses_destroy(addresses);
104   ++test_counter;
105   return results;
106 }
107 
create_on_resolution_arg(grpc_channel_args * results)108 static on_resolution_arg create_on_resolution_arg(grpc_channel_args* results) {
109   on_resolution_arg on_res_arg;
110   memset(&on_res_arg, 0, sizeof(on_res_arg));
111   on_res_arg.expected_resolver_result = results;
112   gpr_event_init(&on_res_arg.ev);
113   return on_res_arg;
114 }
115 
test_fake_resolver()116 static void test_fake_resolver() {
117   grpc_core::ExecCtx exec_ctx;
118   grpc_combiner* combiner = grpc_combiner_create();
119   // Create resolver.
120   grpc_core::RefCountedPtr<grpc_core::FakeResolverResponseGenerator>
121       response_generator =
122           grpc_core::MakeRefCounted<grpc_core::FakeResolverResponseGenerator>();
123   grpc_core::OrphanablePtr<grpc_core::Resolver> resolver =
124       build_fake_resolver(combiner, response_generator.get());
125   GPR_ASSERT(resolver.get() != nullptr);
126   // Test 1: normal resolution.
127   // next_results != NULL, reresolution_results == NULL.
128   // Expected response is next_results.
129   grpc_channel_args* results = create_new_resolver_result();
130   on_resolution_arg on_res_arg = create_on_resolution_arg(results);
131   grpc_closure* on_resolution = GRPC_CLOSURE_CREATE(
132       on_resolution_cb, &on_res_arg, grpc_combiner_scheduler(combiner));
133   // Resolution won't be triggered until next_results is set.
134   resolver->NextLocked(&on_res_arg.resolver_result, on_resolution);
135   response_generator->SetResponse(results);
136   grpc_core::ExecCtx::Get()->Flush();
137   GPR_ASSERT(gpr_event_wait(&on_res_arg.ev,
138                             grpc_timeout_seconds_to_deadline(5)) != nullptr);
139   // Test 2: update resolution.
140   // next_results != NULL, reresolution_results == NULL.
141   // Expected response is next_results.
142   results = create_new_resolver_result();
143   on_res_arg = create_on_resolution_arg(results);
144   on_resolution = GRPC_CLOSURE_CREATE(on_resolution_cb, &on_res_arg,
145                                       grpc_combiner_scheduler(combiner));
146   // Resolution won't be triggered until next_results is set.
147   resolver->NextLocked(&on_res_arg.resolver_result, on_resolution);
148   response_generator->SetResponse(results);
149   grpc_core::ExecCtx::Get()->Flush();
150   GPR_ASSERT(gpr_event_wait(&on_res_arg.ev,
151                             grpc_timeout_seconds_to_deadline(5)) != nullptr);
152   // Test 3: normal re-resolution.
153   // next_results == NULL, reresolution_results != NULL.
154   // Expected response is reresolution_results.
155   grpc_channel_args* reresolution_results = create_new_resolver_result();
156   on_res_arg =
157       create_on_resolution_arg(grpc_channel_args_copy(reresolution_results));
158   on_resolution = GRPC_CLOSURE_CREATE(on_resolution_cb, &on_res_arg,
159                                       grpc_combiner_scheduler(combiner));
160   resolver->NextLocked(&on_res_arg.resolver_result, on_resolution);
161   // Set reresolution_results.
162   response_generator->SetReresolutionResponse(reresolution_results);
163   // Flush here to guarantee that the response has been set.
164   grpc_core::ExecCtx::Get()->Flush();
165   // Trigger a re-resolution.
166   resolver->RequestReresolutionLocked();
167   grpc_core::ExecCtx::Get()->Flush();
168   GPR_ASSERT(gpr_event_wait(&on_res_arg.ev,
169                             grpc_timeout_seconds_to_deadline(5)) != nullptr);
170   // Test 4: repeat re-resolution.
171   // next_results == NULL, reresolution_results != NULL.
172   // Expected response is reresolution_results.
173   on_res_arg = create_on_resolution_arg(reresolution_results);
174   on_resolution = GRPC_CLOSURE_CREATE(on_resolution_cb, &on_res_arg,
175                                       grpc_combiner_scheduler(combiner));
176   resolver->NextLocked(&on_res_arg.resolver_result, on_resolution);
177   // Trigger a re-resolution.
178   resolver->RequestReresolutionLocked();
179   grpc_core::ExecCtx::Get()->Flush();
180   GPR_ASSERT(gpr_event_wait(&on_res_arg.ev,
181                             grpc_timeout_seconds_to_deadline(5)) != nullptr);
182   // Test 5: normal resolution.
183   // next_results != NULL, reresolution_results != NULL.
184   // Expected response is next_results.
185   results = create_new_resolver_result();
186   on_res_arg = create_on_resolution_arg(results);
187   on_resolution = GRPC_CLOSURE_CREATE(on_resolution_cb, &on_res_arg,
188                                       grpc_combiner_scheduler(combiner));
189   // Resolution won't be triggered until next_results is set.
190   resolver->NextLocked(&on_res_arg.resolver_result, on_resolution);
191   response_generator->SetResponse(results);
192   grpc_core::ExecCtx::Get()->Flush();
193   GPR_ASSERT(gpr_event_wait(&on_res_arg.ev,
194                             grpc_timeout_seconds_to_deadline(5)) != nullptr);
195   // Test 6: no-op.
196   // Requesting a new resolution without setting the response shouldn't trigger
197   // the resolution callback.
198   memset(&on_res_arg, 0, sizeof(on_res_arg));
199   on_resolution = GRPC_CLOSURE_CREATE(on_resolution_cb, &on_res_arg,
200                                       grpc_combiner_scheduler(combiner));
201   resolver->NextLocked(&on_res_arg.resolver_result, on_resolution);
202   grpc_core::ExecCtx::Get()->Flush();
203   GPR_ASSERT(gpr_event_wait(&on_res_arg.ev,
204                             grpc_timeout_milliseconds_to_deadline(100)) ==
205              nullptr);
206   // Clean up.
207   // Note: Need to explicitly unref the resolver and flush the exec_ctx
208   // to make sure that the final resolver callback (with error set to
209   // "Resolver Shutdown") is invoked before on_res_arg goes out of scope.
210   resolver.reset();
211   grpc_core::ExecCtx::Get()->Flush();
212   GRPC_COMBINER_UNREF(combiner, "test_fake_resolver");
213 }
214 
main(int argc,char ** argv)215 int main(int argc, char** argv) {
216   grpc_test_init(argc, argv);
217   grpc_init();
218 
219   test_fake_resolver();
220 
221   grpc_shutdown();
222   return 0;
223 }
224