• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/lb_policy_factory.h"
25 #include "src/core/ext/filters/client_channel/resolver.h"
26 #include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h"
27 #include "src/core/ext/filters/client_channel/resolver_registry.h"
28 #include "src/core/lib/channel/channel_args.h"
29 #include "src/core/lib/iomgr/combiner.h"
30 #include "src/core/lib/iomgr/resolve_address.h"
31 #include "src/core/lib/iomgr/timer.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 grpc_combiner* g_combiner;
37 
my_resolve_address(const char * addr,const char * default_port,grpc_pollset_set * interested_parties,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_CLOSURE_SCHED(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 * dns_server,const char * addr,const char * default_port,grpc_pollset_set * interested_parties,grpc_closure * on_done,grpc_lb_addresses ** lb_addrs,bool check_grpclb,char ** service_config_json,grpc_combiner * combiner)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     grpc_lb_addresses** lb_addrs, bool check_grpclb, char** service_config_json,
67     grpc_combiner* combiner) {
68   gpr_mu_lock(&g_mu);
69   GPR_ASSERT(0 == strcmp("test", addr));
70   grpc_error* error = GRPC_ERROR_NONE;
71   if (g_fail_resolution) {
72     g_fail_resolution = false;
73     gpr_mu_unlock(&g_mu);
74     error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Forced Failure");
75   } else {
76     gpr_mu_unlock(&g_mu);
77     *lb_addrs = grpc_lb_addresses_create(1, nullptr);
78     grpc_lb_addresses_set_address(*lb_addrs, 0, nullptr, 0, false, nullptr,
79                                   nullptr);
80   }
81   GRPC_CLOSURE_SCHED(on_done, error);
82   return nullptr;
83 }
84 
create_resolver(const char * name)85 static grpc_core::OrphanablePtr<grpc_core::Resolver> create_resolver(
86     const char* name) {
87   grpc_core::ResolverFactory* factory =
88       grpc_core::ResolverRegistry::LookupResolverFactory("dns");
89   grpc_uri* uri = grpc_uri_parse(name, 0);
90   GPR_ASSERT(uri);
91   grpc_core::ResolverArgs args;
92   args.uri = uri;
93   args.combiner = g_combiner;
94   grpc_core::OrphanablePtr<grpc_core::Resolver> resolver =
95       factory->CreateResolver(args);
96   grpc_uri_destroy(uri);
97   return resolver;
98 }
99 
on_done(void * ev,grpc_error * error)100 static void on_done(void* ev, grpc_error* error) {
101   gpr_event_set(static_cast<gpr_event*>(ev), (void*)1);
102 }
103 
104 // interleave waiting for an event with a timer check
wait_loop(int deadline_seconds,gpr_event * ev)105 static bool wait_loop(int deadline_seconds, gpr_event* ev) {
106   while (deadline_seconds) {
107     gpr_log(GPR_DEBUG, "Test: waiting for %d more seconds", deadline_seconds);
108     if (gpr_event_wait(ev, grpc_timeout_seconds_to_deadline(1))) return true;
109     deadline_seconds--;
110 
111     grpc_core::ExecCtx exec_ctx;
112     grpc_timer_check(nullptr);
113   }
114   return false;
115 }
116 
117 typedef struct next_args {
118   grpc_core::Resolver* resolver;
119   grpc_channel_args** result;
120   grpc_closure* on_complete;
121 } next_args;
122 
call_resolver_next_now_lock_taken(void * arg,grpc_error * error_unused)123 static void call_resolver_next_now_lock_taken(void* arg,
124                                               grpc_error* error_unused) {
125   next_args* a = static_cast<next_args*>(arg);
126   a->resolver->NextLocked(a->result, a->on_complete);
127   gpr_free(a);
128 }
129 
call_resolver_next_after_locking(grpc_core::Resolver * resolver,grpc_channel_args ** result,grpc_closure * on_complete,grpc_combiner * combiner)130 static void call_resolver_next_after_locking(grpc_core::Resolver* resolver,
131                                              grpc_channel_args** result,
132                                              grpc_closure* on_complete,
133                                              grpc_combiner* combiner) {
134   next_args* a = static_cast<next_args*>(gpr_malloc(sizeof(*a)));
135   a->resolver = resolver;
136   a->result = result;
137   a->on_complete = on_complete;
138   GRPC_CLOSURE_SCHED(GRPC_CLOSURE_CREATE(call_resolver_next_now_lock_taken, a,
139                                          grpc_combiner_scheduler(combiner)),
140                      GRPC_ERROR_NONE);
141 }
142 
main(int argc,char ** argv)143 int main(int argc, char** argv) {
144   grpc_test_init(argc, argv);
145 
146   grpc_init();
147   gpr_mu_init(&g_mu);
148   g_combiner = grpc_combiner_create();
149   grpc_set_resolver_impl(&test_resolver);
150   grpc_dns_lookup_ares_locked = my_dns_lookup_ares_locked;
151   grpc_channel_args* result = (grpc_channel_args*)1;
152 
153   {
154     grpc_core::ExecCtx exec_ctx;
155     grpc_core::OrphanablePtr<grpc_core::Resolver> resolver =
156         create_resolver("dns:test");
157     gpr_event ev1;
158     gpr_event_init(&ev1);
159     call_resolver_next_after_locking(
160         resolver.get(), &result,
161         GRPC_CLOSURE_CREATE(on_done, &ev1, grpc_schedule_on_exec_ctx),
162         g_combiner);
163     grpc_core::ExecCtx::Get()->Flush();
164     GPR_ASSERT(wait_loop(5, &ev1));
165     GPR_ASSERT(result == nullptr);
166 
167     gpr_event ev2;
168     gpr_event_init(&ev2);
169     call_resolver_next_after_locking(
170         resolver.get(), &result,
171         GRPC_CLOSURE_CREATE(on_done, &ev2, grpc_schedule_on_exec_ctx),
172         g_combiner);
173     grpc_core::ExecCtx::Get()->Flush();
174     GPR_ASSERT(wait_loop(30, &ev2));
175     GPR_ASSERT(result != nullptr);
176 
177     grpc_channel_args_destroy(result);
178     GRPC_COMBINER_UNREF(g_combiner, "test");
179   }
180 
181   grpc_shutdown();
182   gpr_mu_destroy(&g_mu);
183 }
184