1 //
2 //
3 // Copyright 2017 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 "src/core/resolver/fake/fake_resolver.h"
20
21 #include <inttypes.h>
22 #include <string.h>
23
24 #include <algorithm>
25 #include <functional>
26 #include <memory>
27 #include <string>
28 #include <type_traits>
29 #include <utility>
30 #include <vector>
31
32 #include "absl/container/inlined_vector.h"
33 #include "absl/status/statusor.h"
34 #include "absl/strings/str_format.h"
35 #include "absl/synchronization/notification.h"
36 #include "gtest/gtest.h"
37
38 #include <grpc/grpc.h>
39
40 #include "src/core/lib/address_utils/parse_address.h"
41 #include "src/core/lib/channel/channel_args.h"
42 #include "src/core/lib/config/core_configuration.h"
43 #include "src/core/lib/event_engine/default_event_engine.h"
44 #include "src/core/lib/gprpp/debug_location.h"
45 #include "src/core/lib/gprpp/orphanable.h"
46 #include "src/core/lib/gprpp/ref_counted_ptr.h"
47 #include "src/core/lib/gprpp/work_serializer.h"
48 #include "src/core/lib/iomgr/exec_ctx.h"
49 #include "src/core/lib/iomgr/resolved_address.h"
50 #include "src/core/lib/uri/uri_parser.h"
51 #include "src/core/resolver/endpoint_addresses.h"
52 #include "src/core/resolver/resolver_factory.h"
53 #include "src/core/resolver/resolver_registry.h"
54 #include "test/core/util/test_config.h"
55
56 namespace grpc_core {
57 namespace testing {
58
59 class FakeResolverTest : public ::testing::Test {
60 protected:
61 class ResultHandler : public Resolver::ResultHandler {
62 public:
SetExpectedAndNotification(Resolver::Result expected,absl::Notification * notification)63 void SetExpectedAndNotification(Resolver::Result expected,
64 absl::Notification* notification) {
65 MutexLock lock(&mu_);
66 ASSERT_EQ(notification_, nullptr);
67 expected_ = std::move(expected);
68 notification_ = notification;
69 }
70
ReportResult(Resolver::Result actual)71 void ReportResult(Resolver::Result actual) override {
72 MutexLock lock(&mu_);
73 ASSERT_NE(notification_, nullptr);
74 // TODO(roth): Check fields other than just the addresses.
75 // Note: No good way to compare result_health_callback.
76 ASSERT_TRUE(actual.addresses.ok());
77 ASSERT_EQ(actual.addresses->size(), expected_.addresses->size());
78 for (size_t i = 0; i < expected_.addresses->size(); ++i) {
79 ASSERT_EQ((*actual.addresses)[i], (*expected_.addresses)[i]);
80 }
81 notification_->Notify();
82 notification_ = nullptr;
83 }
84
85 private:
86 Mutex mu_;
87 Resolver::Result expected_ ABSL_GUARDED_BY(mu_);
88 absl::Notification* notification_ ABSL_GUARDED_BY(mu_) = nullptr;
89 };
90
BuildFakeResolver(std::shared_ptr<WorkSerializer> work_serializer,RefCountedPtr<FakeResolverResponseGenerator> response_generator,std::unique_ptr<Resolver::ResultHandler> result_handler)91 static OrphanablePtr<Resolver> BuildFakeResolver(
92 std::shared_ptr<WorkSerializer> work_serializer,
93 RefCountedPtr<FakeResolverResponseGenerator> response_generator,
94 std::unique_ptr<Resolver::ResultHandler> result_handler) {
95 ResolverFactory* factory =
96 CoreConfiguration::Get().resolver_registry().LookupResolverFactory(
97 "fake");
98 ResolverArgs args;
99 args.args = ChannelArgs().SetObject(std::move(response_generator));
100 args.work_serializer = std::move(work_serializer);
101 args.result_handler = std::move(result_handler);
102 return factory->CreateResolver(std::move(args));
103 }
104
105 // Create a new resolution containing 2 addresses.
CreateResolverResult()106 static Resolver::Result CreateResolverResult() {
107 static size_t test_counter = 0;
108 const size_t num_addresses = 2;
109 // Create address list.
110 EndpointAddressesList addresses;
111 for (size_t i = 0; i < num_addresses; ++i) {
112 std::string uri_string = absl::StrFormat(
113 "ipv4:127.0.0.1:100%" PRIuPTR, test_counter * num_addresses + i);
114 absl::StatusOr<URI> uri = URI::Parse(uri_string);
115 EXPECT_TRUE(uri.ok());
116 grpc_resolved_address address;
117 EXPECT_TRUE(grpc_parse_uri(*uri, &address));
118 absl::InlinedVector<grpc_arg, 2> args_to_add;
119 addresses.emplace_back(address, ChannelArgs());
120 }
121 ++test_counter;
122 Resolver::Result result;
123 result.addresses = std::move(addresses);
124 return result;
125 }
126
CreateResolver()127 OrphanablePtr<Resolver> CreateResolver() {
128 result_handler_ = new ResultHandler();
129 return BuildFakeResolver(
130 work_serializer_, response_generator_,
131 std::unique_ptr<Resolver::ResultHandler>(result_handler_));
132 }
133
RunSynchronously(std::function<void ()> callback)134 void RunSynchronously(std::function<void()> callback) {
135 Notification notification;
136 work_serializer_->Run(
137 [callback = std::move(callback), ¬ification]() {
138 callback();
139 notification.Notify();
140 },
141 DEBUG_LOCATION);
142 notification.WaitForNotification();
143 }
144
145 ExecCtx exec_ctx_;
146 std::shared_ptr<WorkSerializer> work_serializer_ =
147 std::make_shared<WorkSerializer>(
148 grpc_event_engine::experimental::GetDefaultEventEngine());
149 RefCountedPtr<FakeResolverResponseGenerator> response_generator_ =
150 MakeRefCounted<FakeResolverResponseGenerator>();
151 ResultHandler* result_handler_ = nullptr;
152 };
153
TEST_F(FakeResolverTest,WaitForResolverSet)154 TEST_F(FakeResolverTest, WaitForResolverSet) {
155 EXPECT_FALSE(response_generator_->WaitForResolverSet(absl::Milliseconds(1)));
156 auto resolver = CreateResolver();
157 ASSERT_NE(resolver, nullptr);
158 EXPECT_TRUE(response_generator_->WaitForResolverSet(absl::Milliseconds(1)));
159 }
160
TEST_F(FakeResolverTest,ReturnResultBeforeResolverCreated)161 TEST_F(FakeResolverTest, ReturnResultBeforeResolverCreated) {
162 // Return result via response generator.
163 Resolver::Result result = CreateResolverResult();
164 response_generator_->SetResponseAsync(result);
165 // Create and start resolver.
166 auto resolver = CreateResolver();
167 ASSERT_NE(resolver, nullptr);
168 absl::Notification notification;
169 result_handler_->SetExpectedAndNotification(std::move(result), ¬ification);
170 RunSynchronously([resolver = resolver.get()] { resolver->StartLocked(); });
171 // Expect result.
172 ASSERT_TRUE(notification.WaitForNotificationWithTimeout(
173 absl::Seconds(5 * grpc_test_slowdown_factor())));
174 }
175
TEST_F(FakeResolverTest,ReturnResultBeforeResolverStarted)176 TEST_F(FakeResolverTest, ReturnResultBeforeResolverStarted) {
177 // Create resolver.
178 auto resolver = CreateResolver();
179 ASSERT_NE(resolver, nullptr);
180 Resolver::Result result = CreateResolverResult();
181 absl::Notification notification;
182 result_handler_->SetExpectedAndNotification(result, ¬ification);
183 // Return result via response generator.
184 response_generator_->SetResponseAsync(std::move(result));
185 // Start resolver.
186 RunSynchronously([resolver = resolver.get()] { resolver->StartLocked(); });
187 // Expect result.
188 ASSERT_TRUE(notification.WaitForNotificationWithTimeout(
189 absl::Seconds(5 * grpc_test_slowdown_factor())));
190 }
191
TEST_F(FakeResolverTest,ReturnResult)192 TEST_F(FakeResolverTest, ReturnResult) {
193 // Create and start resolver.
194 auto resolver = CreateResolver();
195 ASSERT_NE(resolver, nullptr);
196 RunSynchronously([resolver = resolver.get()] { resolver->StartLocked(); });
197 Resolver::Result result = CreateResolverResult();
198 absl::Notification notification;
199 result_handler_->SetExpectedAndNotification(result, ¬ification);
200 // Return result via response generator.
201 response_generator_->SetResponseAsync(std::move(result));
202 // Expect result.
203 ASSERT_TRUE(notification.WaitForNotificationWithTimeout(
204 absl::Seconds(5 * grpc_test_slowdown_factor())));
205 }
206
TEST_F(FakeResolverTest,WaitForReresolutionRequest)207 TEST_F(FakeResolverTest, WaitForReresolutionRequest) {
208 // Create and start resolver.
209 auto resolver = CreateResolver();
210 ASSERT_NE(resolver, nullptr);
211 RunSynchronously([resolver = resolver.get()] { resolver->StartLocked(); });
212 // No re-resolution requested yet.
213 EXPECT_FALSE(
214 response_generator_->WaitForReresolutionRequest(absl::Milliseconds(1)));
215 // Request re-resolution, then try again.
216 RunSynchronously(
217 [resolver = resolver.get()] { resolver->RequestReresolutionLocked(); });
218 EXPECT_TRUE(
219 response_generator_->WaitForReresolutionRequest(absl::Milliseconds(1)));
220 }
221
222 } // namespace testing
223 } // namespace grpc_core
224
main(int argc,char ** argv)225 int main(int argc, char** argv) {
226 grpc::testing::TestEnvironment env(&argc, argv);
227 ::testing::InitGoogleTest(&argc, argv);
228 grpc::testing::TestGrpcScope grpc_scope;
229 return RUN_ALL_TESTS();
230 }
231