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 #ifndef GRPC_SRC_CORE_RESOLVER_FAKE_FAKE_RESOLVER_H 18 #define GRPC_SRC_CORE_RESOLVER_FAKE_FAKE_RESOLVER_H 19 20 #include <grpc/support/port_platform.h> 21 22 #include <utility> 23 24 #include "absl/base/thread_annotations.h" 25 #include "absl/strings/string_view.h" 26 #include "absl/time/time.h" 27 #include "absl/types/optional.h" 28 29 #include <grpc/grpc.h> 30 31 #include "src/core/lib/gpr/useful.h" 32 #include "src/core/lib/gprpp/notification.h" 33 #include "src/core/lib/gprpp/ref_counted.h" 34 #include "src/core/lib/gprpp/ref_counted_ptr.h" 35 #include "src/core/lib/gprpp/sync.h" 36 #include "src/core/resolver/resolver.h" 37 38 #define GRPC_ARG_FAKE_RESOLVER_RESPONSE_GENERATOR \ 39 "grpc.fake_resolver.response_generator" 40 41 namespace grpc_core { 42 43 class FakeResolver; 44 45 /// A mechanism for generating responses for the fake resolver. 46 /// An instance of this class is passed to the fake resolver via a channel 47 /// argument and used to inject and trigger custom resolutions. 48 // TODO(roth): I would ideally like this to be InternallyRefCounted 49 // instead of RefCounted, but external refs are currently needed to 50 // encode this in channel args. Once channel_args are converted to C++, 51 // see if we can find a way to fix this. 52 class FakeResolverResponseGenerator final 53 : public RefCounted<FakeResolverResponseGenerator> { 54 public: 55 static const grpc_arg_pointer_vtable kChannelArgPointerVtable; 56 57 FakeResolverResponseGenerator(); 58 ~FakeResolverResponseGenerator() override; 59 60 // Instructs the fake resolver associated with the response generator 61 // instance to trigger a new resolution with the specified result. If the 62 // resolver is not available yet, delays response setting until it is. This 63 // can be called at most once before the resolver is available. 64 // notify_when_set is an optional notification to signal when the response has 65 // been set. 66 void SetResponseAndNotify(Resolver::Result result, 67 Notification* notify_when_set); 68 69 // Same as SetResponseAndNotify(), assume that async setting is fine SetResponseAsync(Resolver::Result result)70 void SetResponseAsync(Resolver::Result result) { 71 SetResponseAndNotify(std::move(result), nullptr); 72 } 73 74 // Same as SetResponseAndNotify(), but create and wait for the notification SetResponseSynchronously(Resolver::Result result)75 void SetResponseSynchronously(Resolver::Result result) { 76 Notification n; 77 SetResponseAndNotify(std::move(result), &n); 78 n.WaitForNotification(); 79 } 80 81 // Waits up to timeout for a re-resolution request. Returns true if a 82 // re-resolution request is seen, or false if timeout occurs. Returns 83 // true immediately if there was a re-resolution request since the 84 // last time this method was called. 85 bool WaitForReresolutionRequest(absl::Duration timeout); 86 87 // Wait for a resolver to be set (setting may be happening asynchronously, so 88 // this may block - consider it test only). 89 bool WaitForResolverSet(absl::Duration timeout); 90 ChannelArgName()91 static absl::string_view ChannelArgName() { 92 return GRPC_ARG_FAKE_RESOLVER_RESPONSE_GENERATOR; 93 } 94 ChannelArgsCompare(const FakeResolverResponseGenerator * a,const FakeResolverResponseGenerator * b)95 static int ChannelArgsCompare(const FakeResolverResponseGenerator* a, 96 const FakeResolverResponseGenerator* b) { 97 return QsortCompare(a, b); 98 } 99 100 private: 101 friend class FakeResolver; 102 103 // Set the corresponding FakeResolver to this generator. 104 void SetFakeResolver(RefCountedPtr<FakeResolver> resolver); 105 106 // Called by FakeResolver when re-resolution is requested. 107 void ReresolutionRequested(); 108 109 // Helper function to send a result to the resolver. 110 static void SendResultToResolver(RefCountedPtr<FakeResolver> resolver, 111 Resolver::Result result, 112 Notification* notify_when_set); 113 114 // Mutex protecting the members below. 115 Mutex mu_; 116 CondVar* resolver_set_cv_ ABSL_GUARDED_BY(mu_) = nullptr; 117 RefCountedPtr<FakeResolver> resolver_ ABSL_GUARDED_BY(mu_); 118 // Temporarily stores the result when it gets set before the response 119 // generator is seen by the FakeResolver. 120 absl::optional<Resolver::Result> result_ ABSL_GUARDED_BY(mu_); 121 122 Mutex reresolution_mu_; 123 CondVar* reresolution_cv_ ABSL_GUARDED_BY(reresolution_mu_) = nullptr; 124 bool reresolution_requested_ ABSL_GUARDED_BY(reresolution_mu_) = false; 125 }; 126 127 } // namespace grpc_core 128 129 #endif // GRPC_SRC_CORE_RESOLVER_FAKE_FAKE_RESOLVER_H 130