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