1 /*
2 *
3 * Copyright 2015 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/grpc.h>
22 #include <grpc/support/alloc.h>
23
24 #include "src/core/ext/filters/client_channel/resolver.h"
25 #include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h"
26 #include "src/core/ext/filters/client_channel/resolver_registry.h"
27 #include "src/core/ext/filters/client_channel/server_address.h"
28 #include "src/core/lib/channel/channel_args.h"
29 #include "src/core/lib/iomgr/resolve_address.h"
30 #include "src/core/lib/iomgr/timer.h"
31 #include "src/core/lib/iomgr/work_serializer.h"
32 #include "test/core/util/test_config.h"
33
34 static gpr_mu g_mu;
35 static bool g_fail_resolution = true;
36 static std::shared_ptr<grpc_core::WorkSerializer>* g_work_serializer;
37
my_resolve_address(const char * addr,const char *,grpc_pollset_set *,grpc_closure * on_done,grpc_resolved_addresses ** addrs)38 static void my_resolve_address(const char* addr, const char* /*default_port*/,
39 grpc_pollset_set* /*interested_parties*/,
40 grpc_closure* on_done,
41 grpc_resolved_addresses** addrs) {
42 gpr_mu_lock(&g_mu);
43 GPR_ASSERT(0 == strcmp("test", addr));
44 grpc_error* error = GRPC_ERROR_NONE;
45 if (g_fail_resolution) {
46 g_fail_resolution = false;
47 gpr_mu_unlock(&g_mu);
48 error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Forced Failure");
49 } else {
50 gpr_mu_unlock(&g_mu);
51 *addrs = static_cast<grpc_resolved_addresses*>(gpr_malloc(sizeof(**addrs)));
52 (*addrs)->naddrs = 1;
53 (*addrs)->addrs = static_cast<grpc_resolved_address*>(
54 gpr_malloc(sizeof(*(*addrs)->addrs)));
55 (*addrs)->addrs[0].len = 123;
56 }
57 grpc_core::ExecCtx::Run(DEBUG_LOCATION, on_done, error);
58 }
59
60 static grpc_address_resolver_vtable test_resolver = {my_resolve_address,
61 nullptr};
62
my_dns_lookup_ares_locked(const char *,const char * addr,const char *,grpc_pollset_set *,grpc_closure * on_done,std::unique_ptr<grpc_core::ServerAddressList> * addresses,std::unique_ptr<grpc_core::ServerAddressList> *,char **,int,std::shared_ptr<grpc_core::WorkSerializer>)63 static grpc_ares_request* my_dns_lookup_ares_locked(
64 const char* /*dns_server*/, const char* addr, const char* /*default_port*/,
65 grpc_pollset_set* /*interested_parties*/, grpc_closure* on_done,
66 std::unique_ptr<grpc_core::ServerAddressList>* addresses,
67 std::unique_ptr<grpc_core::ServerAddressList>* /*balancer_addresses*/,
68 char** /*service_config_json*/, int /*query_timeout_ms*/,
69 std::shared_ptr<grpc_core::WorkSerializer> /*combiner*/) { // NOLINT
70 gpr_mu_lock(&g_mu);
71 GPR_ASSERT(0 == strcmp("test", addr));
72 grpc_error* error = GRPC_ERROR_NONE;
73 if (g_fail_resolution) {
74 g_fail_resolution = false;
75 gpr_mu_unlock(&g_mu);
76 error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Forced Failure");
77 } else {
78 gpr_mu_unlock(&g_mu);
79 *addresses = absl::make_unique<grpc_core::ServerAddressList>();
80 grpc_resolved_address dummy_resolved_address;
81 memset(&dummy_resolved_address, 0, sizeof(dummy_resolved_address));
82 dummy_resolved_address.len = 123;
83 (*addresses)->emplace_back(dummy_resolved_address, nullptr);
84 }
85 grpc_core::ExecCtx::Run(DEBUG_LOCATION, on_done, error);
86 return nullptr;
87 }
88
my_cancel_ares_request_locked(grpc_ares_request * request)89 static void my_cancel_ares_request_locked(grpc_ares_request* request) {
90 GPR_ASSERT(request == nullptr);
91 }
92
create_resolver(const char * name,std::unique_ptr<grpc_core::Resolver::ResultHandler> result_handler)93 static grpc_core::OrphanablePtr<grpc_core::Resolver> create_resolver(
94 const char* name,
95 std::unique_ptr<grpc_core::Resolver::ResultHandler> result_handler) {
96 grpc_core::ResolverFactory* factory =
97 grpc_core::ResolverRegistry::LookupResolverFactory("dns");
98 grpc_uri* uri = grpc_uri_parse(name, 0);
99 GPR_ASSERT(uri);
100 grpc_core::ResolverArgs args;
101 args.uri = uri;
102 args.work_serializer = *g_work_serializer;
103 args.result_handler = std::move(result_handler);
104 grpc_core::OrphanablePtr<grpc_core::Resolver> resolver =
105 factory->CreateResolver(std::move(args));
106 grpc_uri_destroy(uri);
107 return resolver;
108 }
109
110 class ResultHandler : public grpc_core::Resolver::ResultHandler {
111 public:
112 struct ResolverOutput {
113 grpc_core::Resolver::Result result;
114 grpc_error* error = nullptr;
115 gpr_event ev;
116
ResolverOutputResultHandler::ResolverOutput117 ResolverOutput() { gpr_event_init(&ev); }
~ResolverOutputResultHandler::ResolverOutput118 ~ResolverOutput() { GRPC_ERROR_UNREF(error); }
119 };
120
SetOutput(ResolverOutput * output)121 void SetOutput(ResolverOutput* output) {
122 gpr_atm_rel_store(&output_, reinterpret_cast<gpr_atm>(output));
123 }
124
ReturnResult(grpc_core::Resolver::Result result)125 void ReturnResult(grpc_core::Resolver::Result result) override {
126 ResolverOutput* output =
127 reinterpret_cast<ResolverOutput*>(gpr_atm_acq_load(&output_));
128 GPR_ASSERT(output != nullptr);
129 output->result = std::move(result);
130 output->error = GRPC_ERROR_NONE;
131 gpr_event_set(&output->ev, (void*)1);
132 }
133
ReturnError(grpc_error * error)134 void ReturnError(grpc_error* error) override {
135 ResolverOutput* output =
136 reinterpret_cast<ResolverOutput*>(gpr_atm_acq_load(&output_));
137 GPR_ASSERT(output != nullptr);
138 output->error = error;
139 gpr_event_set(&output->ev, (void*)1);
140 }
141
142 private:
143 gpr_atm output_ = 0; // ResolverOutput*
144 };
145
146 // interleave waiting for an event with a timer check
wait_loop(int deadline_seconds,gpr_event * ev)147 static bool wait_loop(int deadline_seconds, gpr_event* ev) {
148 while (deadline_seconds) {
149 gpr_log(GPR_DEBUG, "Test: waiting for %d more seconds", deadline_seconds);
150 if (gpr_event_wait(ev, grpc_timeout_seconds_to_deadline(1))) return true;
151 deadline_seconds--;
152
153 grpc_core::ExecCtx exec_ctx;
154 grpc_timer_check(nullptr);
155 }
156 return false;
157 }
158
main(int argc,char ** argv)159 int main(int argc, char** argv) {
160 grpc::testing::TestEnvironment env(argc, argv);
161
162 grpc_init();
163 gpr_mu_init(&g_mu);
164 auto work_serializer = std::make_shared<grpc_core::WorkSerializer>();
165 g_work_serializer = &work_serializer;
166 grpc_set_resolver_impl(&test_resolver);
167 grpc_dns_lookup_ares_locked = my_dns_lookup_ares_locked;
168 grpc_cancel_ares_request_locked = my_cancel_ares_request_locked;
169
170 {
171 grpc_core::ExecCtx exec_ctx;
172 ResultHandler* result_handler = new ResultHandler();
173 grpc_core::OrphanablePtr<grpc_core::Resolver> resolver = create_resolver(
174 "dns:test",
175 std::unique_ptr<grpc_core::Resolver::ResultHandler>(result_handler));
176 ResultHandler::ResolverOutput output1;
177 result_handler->SetOutput(&output1);
178 resolver->StartLocked();
179 grpc_core::ExecCtx::Get()->Flush();
180 GPR_ASSERT(wait_loop(5, &output1.ev));
181 GPR_ASSERT(output1.result.addresses.empty());
182 GPR_ASSERT(output1.error != GRPC_ERROR_NONE);
183
184 ResultHandler::ResolverOutput output2;
185 result_handler->SetOutput(&output2);
186 grpc_core::ExecCtx::Get()->Flush();
187 GPR_ASSERT(wait_loop(30, &output2.ev));
188 GPR_ASSERT(!output2.result.addresses.empty());
189 GPR_ASSERT(output2.error == GRPC_ERROR_NONE);
190 }
191
192 grpc_shutdown();
193 gpr_mu_destroy(&g_mu);
194 }
195