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