Home | History | Annotate | Download | only in fake
      1 //
      2 // Copyright 2016 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 // This is similar to the sockaddr resolver, except that it supports a
     18 // bunch of query args that are useful for dependency injection in tests.
     19 
     20 #include <grpc/support/port_platform.h>
     21 
     22 #include <limits.h>
     23 #include <stdbool.h>
     24 #include <stdio.h>
     25 #include <stdlib.h>
     26 #include <string.h>
     27 
     28 #include <grpc/support/alloc.h>
     29 #include <grpc/support/string_util.h>
     30 
     31 #include "src/core/ext/filters/client_channel/lb_policy_factory.h"
     32 #include "src/core/ext/filters/client_channel/parse_address.h"
     33 #include "src/core/ext/filters/client_channel/resolver_registry.h"
     34 #include "src/core/lib/channel/channel_args.h"
     35 #include "src/core/lib/gpr/host_port.h"
     36 #include "src/core/lib/gpr/string.h"
     37 #include "src/core/lib/iomgr/closure.h"
     38 #include "src/core/lib/iomgr/combiner.h"
     39 #include "src/core/lib/iomgr/resolve_address.h"
     40 #include "src/core/lib/iomgr/unix_sockets_posix.h"
     41 #include "src/core/lib/slice/slice_internal.h"
     42 #include "src/core/lib/slice/slice_string_helpers.h"
     43 
     44 #include "src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h"
     45 
     46 namespace grpc_core {
     47 
     48 // This cannot be in an anonymous namespace, because it is a friend of
     49 // FakeResolverResponseGenerator.
     50 class FakeResolver : public Resolver {
     51  public:
     52   explicit FakeResolver(const ResolverArgs& args);
     53 
     54   void NextLocked(grpc_channel_args** result,
     55                   grpc_closure* on_complete) override;
     56 
     57   void RequestReresolutionLocked() override;
     58 
     59  private:
     60   friend class FakeResolverResponseGenerator;
     61 
     62   virtual ~FakeResolver();
     63 
     64   void MaybeFinishNextLocked();
     65 
     66   void ShutdownLocked() override;
     67 
     68   // passed-in parameters
     69   grpc_channel_args* channel_args_ = nullptr;
     70   // If not NULL, the next set of resolution results to be returned to
     71   // NextLocked()'s closure.
     72   grpc_channel_args* next_results_ = nullptr;
     73   // Results to use for the pretended re-resolution in
     74   // RequestReresolutionLocked().
     75   grpc_channel_args* reresolution_results_ = nullptr;
     76   // pending next completion, or NULL
     77   grpc_closure* next_completion_ = nullptr;
     78   // target result address for next completion
     79   grpc_channel_args** target_result_ = nullptr;
     80   // if true, return failure
     81   bool return_failure_ = false;
     82 };
     83 
     84 FakeResolver::FakeResolver(const ResolverArgs& args) : Resolver(args.combiner) {
     85   channel_args_ = grpc_channel_args_copy(args.args);
     86   FakeResolverResponseGenerator* response_generator =
     87       FakeResolverResponseGenerator::GetFromArgs(args.args);
     88   if (response_generator != nullptr) response_generator->resolver_ = this;
     89 }
     90 
     91 FakeResolver::~FakeResolver() {
     92   grpc_channel_args_destroy(next_results_);
     93   grpc_channel_args_destroy(reresolution_results_);
     94   grpc_channel_args_destroy(channel_args_);
     95 }
     96 
     97 void FakeResolver::NextLocked(grpc_channel_args** target_result,
     98                               grpc_closure* on_complete) {
     99   GPR_ASSERT(next_completion_ == nullptr);
    100   next_completion_ = on_complete;
    101   target_result_ = target_result;
    102   MaybeFinishNextLocked();
    103 }
    104 
    105 void FakeResolver::RequestReresolutionLocked() {
    106   if (reresolution_results_ != nullptr) {
    107     grpc_channel_args_destroy(next_results_);
    108     next_results_ = grpc_channel_args_copy(reresolution_results_);
    109     MaybeFinishNextLocked();
    110   }
    111 }
    112 
    113 void FakeResolver::MaybeFinishNextLocked() {
    114   if (next_completion_ != nullptr &&
    115       (next_results_ != nullptr || return_failure_)) {
    116     *target_result_ =
    117         return_failure_ ? nullptr
    118                         : grpc_channel_args_union(next_results_, channel_args_);
    119     grpc_channel_args_destroy(next_results_);
    120     next_results_ = nullptr;
    121     GRPC_CLOSURE_SCHED(next_completion_, GRPC_ERROR_NONE);
    122     next_completion_ = nullptr;
    123     return_failure_ = false;
    124   }
    125 }
    126 
    127 void FakeResolver::ShutdownLocked() {
    128   if (next_completion_ != nullptr) {
    129     *target_result_ = nullptr;
    130     GRPC_CLOSURE_SCHED(next_completion_, GRPC_ERROR_CREATE_FROM_STATIC_STRING(
    131                                              "Resolver Shutdown"));
    132     next_completion_ = nullptr;
    133   }
    134 }
    135 
    136 //
    137 // FakeResolverResponseGenerator
    138 //
    139 
    140 struct SetResponseClosureArg {
    141   grpc_closure set_response_closure;
    142   FakeResolverResponseGenerator* generator;
    143   grpc_channel_args* response;
    144 };
    145 
    146 void FakeResolverResponseGenerator::SetResponseLocked(void* arg,
    147                                                       grpc_error* error) {
    148   SetResponseClosureArg* closure_arg = static_cast<SetResponseClosureArg*>(arg);
    149   FakeResolver* resolver = closure_arg->generator->resolver_;
    150   grpc_channel_args_destroy(resolver->next_results_);
    151   resolver->next_results_ = closure_arg->response;
    152   resolver->MaybeFinishNextLocked();
    153   Delete(closure_arg);
    154 }
    155 
    156 void FakeResolverResponseGenerator::SetResponse(grpc_channel_args* response) {
    157   GPR_ASSERT(response != nullptr);
    158   GPR_ASSERT(resolver_ != nullptr);
    159   SetResponseClosureArg* closure_arg = New<SetResponseClosureArg>();
    160   closure_arg->generator = this;
    161   closure_arg->response = grpc_channel_args_copy(response);
    162   GRPC_CLOSURE_SCHED(
    163       GRPC_CLOSURE_INIT(&closure_arg->set_response_closure, SetResponseLocked,
    164                         closure_arg,
    165                         grpc_combiner_scheduler(resolver_->combiner())),
    166       GRPC_ERROR_NONE);
    167 }
    168 
    169 void FakeResolverResponseGenerator::SetReresolutionResponseLocked(
    170     void* arg, grpc_error* error) {
    171   SetResponseClosureArg* closure_arg = static_cast<SetResponseClosureArg*>(arg);
    172   FakeResolver* resolver = closure_arg->generator->resolver_;
    173   grpc_channel_args_destroy(resolver->reresolution_results_);
    174   resolver->reresolution_results_ = closure_arg->response;
    175   Delete(closure_arg);
    176 }
    177 
    178 void FakeResolverResponseGenerator::SetReresolutionResponse(
    179     grpc_channel_args* response) {
    180   GPR_ASSERT(resolver_ != nullptr);
    181   SetResponseClosureArg* closure_arg = New<SetResponseClosureArg>();
    182   closure_arg->generator = this;
    183   closure_arg->response =
    184       response != nullptr ? grpc_channel_args_copy(response) : nullptr;
    185   GRPC_CLOSURE_SCHED(
    186       GRPC_CLOSURE_INIT(&closure_arg->set_response_closure,
    187                         SetReresolutionResponseLocked, closure_arg,
    188                         grpc_combiner_scheduler(resolver_->combiner())),
    189       GRPC_ERROR_NONE);
    190 }
    191 
    192 void FakeResolverResponseGenerator::SetFailureLocked(void* arg,
    193                                                      grpc_error* error) {
    194   SetResponseClosureArg* closure_arg = static_cast<SetResponseClosureArg*>(arg);
    195   FakeResolver* resolver = closure_arg->generator->resolver_;
    196   resolver->return_failure_ = true;
    197   resolver->MaybeFinishNextLocked();
    198   Delete(closure_arg);
    199 }
    200 
    201 void FakeResolverResponseGenerator::SetFailure() {
    202   GPR_ASSERT(resolver_ != nullptr);
    203   SetResponseClosureArg* closure_arg = New<SetResponseClosureArg>();
    204   closure_arg->generator = this;
    205   GRPC_CLOSURE_SCHED(
    206       GRPC_CLOSURE_INIT(&closure_arg->set_response_closure, SetFailureLocked,
    207                         closure_arg,
    208                         grpc_combiner_scheduler(resolver_->combiner())),
    209       GRPC_ERROR_NONE);
    210 }
    211 
    212 namespace {
    213 
    214 static void* response_generator_arg_copy(void* p) {
    215   FakeResolverResponseGenerator* generator =
    216       static_cast<FakeResolverResponseGenerator*>(p);
    217   // TODO(roth): We currently deal with this ref manually.  Once the
    218   // new channel args code is converted to C++, find a way to track this ref
    219   // in a cleaner way.
    220   RefCountedPtr<FakeResolverResponseGenerator> copy = generator->Ref();
    221   copy.release();
    222   return p;
    223 }
    224 
    225 static void response_generator_arg_destroy(void* p) {
    226   FakeResolverResponseGenerator* generator =
    227       static_cast<FakeResolverResponseGenerator*>(p);
    228   generator->Unref();
    229 }
    230 
    231 static int response_generator_cmp(void* a, void* b) { return GPR_ICMP(a, b); }
    232 
    233 static const grpc_arg_pointer_vtable response_generator_arg_vtable = {
    234     response_generator_arg_copy, response_generator_arg_destroy,
    235     response_generator_cmp};
    236 
    237 }  // namespace
    238 
    239 grpc_arg FakeResolverResponseGenerator::MakeChannelArg(
    240     FakeResolverResponseGenerator* generator) {
    241   grpc_arg arg;
    242   arg.type = GRPC_ARG_POINTER;
    243   arg.key = (char*)GRPC_ARG_FAKE_RESOLVER_RESPONSE_GENERATOR;
    244   arg.value.pointer.p = generator;
    245   arg.value.pointer.vtable = &response_generator_arg_vtable;
    246   return arg;
    247 }
    248 
    249 FakeResolverResponseGenerator* FakeResolverResponseGenerator::GetFromArgs(
    250     const grpc_channel_args* args) {
    251   const grpc_arg* arg =
    252       grpc_channel_args_find(args, GRPC_ARG_FAKE_RESOLVER_RESPONSE_GENERATOR);
    253   if (arg == nullptr || arg->type != GRPC_ARG_POINTER) return nullptr;
    254   return static_cast<FakeResolverResponseGenerator*>(arg->value.pointer.p);
    255 }
    256 
    257 //
    258 // Factory
    259 //
    260 
    261 namespace {
    262 
    263 class FakeResolverFactory : public ResolverFactory {
    264  public:
    265   OrphanablePtr<Resolver> CreateResolver(
    266       const ResolverArgs& args) const override {
    267     return OrphanablePtr<Resolver>(New<FakeResolver>(args));
    268   }
    269 
    270   const char* scheme() const override { return "fake"; }
    271 };
    272 
    273 }  // namespace
    274 
    275 }  // namespace grpc_core
    276 
    277 void grpc_resolver_fake_init() {
    278   grpc_core::ResolverRegistry::Builder::RegisterResolverFactory(
    279       grpc_core::UniquePtr<grpc_core::ResolverFactory>(
    280           grpc_core::New<grpc_core::FakeResolverFactory>()));
    281 }
    282 
    283 void grpc_resolver_fake_shutdown() {}
    284