Upload upstream chromium 108.0.5359.1
[platform/framework/web/chromium-efl.git] / services / proxy_resolver / host_resolver_mojo_unittest.cc
1 // Copyright 2015 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "services/proxy_resolver/host_resolver_mojo.h"
6
7 #include <memory>
8 #include <string>
9 #include <utility>
10 #include <vector>
11
12 #include "base/bind.h"
13 #include "base/test/task_environment.h"
14 #include "mojo/public/cpp/bindings/remote.h"
15 #include "net/base/ip_address.h"
16 #include "net/base/net_errors.h"
17 #include "net/base/network_anonymization_key.h"
18 #include "net/base/request_priority.h"
19 #include "net/base/test_completion_callback.h"
20 #include "net/log/net_log_with_source.h"
21 #include "net/test/event_waiter.h"
22 #include "net/test/gtest_util.h"
23 #include "testing/gmock/include/gmock/gmock.h"
24 #include "testing/gtest/include/gtest/gtest.h"
25 #include "url/gurl.h"
26 #include "url/origin.h"
27
28 using net::test::IsError;
29 using net::test::IsOk;
30
31 namespace proxy_resolver {
32 namespace {
33
34 void Fail(int result) {
35   FAIL() << "Unexpected callback called with error " << result;
36 }
37
38 class MockMojoHostResolverRequest {
39  public:
40   MockMojoHostResolverRequest(
41       mojo::PendingRemote<mojom::HostResolverRequestClient> client,
42       base::OnceClosure error_callback)
43       : client_(std::move(client)), error_callback_(std::move(error_callback)) {
44     client_.set_disconnect_handler(base::BindOnce(
45         &MockMojoHostResolverRequest::OnDisconnect, base::Unretained(this)));
46   }
47
48   void OnDisconnect() { std::move(error_callback_).Run(); }
49
50  private:
51   mojo::Remote<mojom::HostResolverRequestClient> client_;
52   base::OnceClosure error_callback_;
53 };
54
55 struct HostResolverAction {
56   enum Action {
57     COMPLETE,
58     DROP,
59     RETAIN,
60   };
61
62   static HostResolverAction ReturnError(net::Error error) {
63     HostResolverAction result;
64     result.error = error;
65     return result;
66   }
67
68   static HostResolverAction ReturnResult(
69       std::vector<net::IPAddress> addresses) {
70     HostResolverAction result;
71     result.addresses = std::move(addresses);
72     return result;
73   }
74
75   static HostResolverAction DropRequest() {
76     HostResolverAction result;
77     result.action = DROP;
78     return result;
79   }
80
81   static HostResolverAction RetainRequest() {
82     HostResolverAction result;
83     result.action = RETAIN;
84     return result;
85   }
86
87   Action action = COMPLETE;
88   std::vector<net::IPAddress> addresses;
89   net::Error error = net::OK;
90 };
91
92 class MockMojoHostResolver : public HostResolverMojo::Impl {
93  public:
94   // Information logged from a call to ResolveDns().
95   struct RequestInfo {
96     std::string hostname;
97     net::NetworkAnonymizationKey network_anonymization_key;
98
99     bool operator==(const RequestInfo& other) const {
100       return hostname == other.hostname &&
101              network_anonymization_key == other.network_anonymization_key;
102     }
103   };
104
105   explicit MockMojoHostResolver(
106       base::RepeatingClosure request_connection_error_callback)
107       : request_connection_error_callback_(
108             std::move(request_connection_error_callback)) {}
109
110   ~MockMojoHostResolver() override {
111     EXPECT_EQ(results_returned_, actions_.size());
112   }
113
114   void AddAction(HostResolverAction action) {
115     actions_.push_back(std::move(action));
116   }
117
118   const std::vector<RequestInfo>& request_info() const { return request_info_; }
119
120   void ResolveDns(
121       const std::string& hostname,
122       net::ProxyResolveDnsOperation operation,
123       const net::NetworkAnonymizationKey& network_anonymization_key,
124       mojo::PendingRemote<mojom::HostResolverRequestClient> client) override {
125     request_info_.push_back(RequestInfo{hostname, network_anonymization_key});
126     ASSERT_LE(results_returned_, actions_.size());
127     switch (actions_[results_returned_].action) {
128       case HostResolverAction::COMPLETE:
129         mojo::Remote<mojom::HostResolverRequestClient>(std::move(client))
130             ->ReportResult(actions_[results_returned_].error,
131                            actions_[results_returned_].addresses);
132         break;
133       case HostResolverAction::RETAIN:
134         requests_.push_back(std::make_unique<MockMojoHostResolverRequest>(
135             std::move(client),
136             base::BindOnce(request_connection_error_callback_)));
137         break;
138       case HostResolverAction::DROP:
139         break;
140     }
141     results_returned_++;
142   }
143
144  private:
145   std::vector<HostResolverAction> actions_;
146   size_t results_returned_ = 0;
147   std::vector<RequestInfo> request_info_;
148   base::RepeatingClosure request_connection_error_callback_;
149   std::vector<std::unique_ptr<MockMojoHostResolverRequest>> requests_;
150 };
151
152 }  // namespace
153
154 class HostResolverMojoTest : public testing::Test {
155  protected:
156   enum class ConnectionErrorSource {
157     REQUEST,
158   };
159   using Waiter = net::EventWaiter<ConnectionErrorSource>;
160
161   HostResolverMojoTest()
162       : mock_resolver_(base::BindRepeating(&Waiter::NotifyEvent,
163                                            base::Unretained(&waiter_),
164                                            ConnectionErrorSource::REQUEST)),
165         resolver_(&mock_resolver_) {}
166
167   int Resolve(const std::string& hostname,
168               const net::NetworkAnonymizationKey& network_anonymization_key,
169               std::vector<net::IPAddress>* out_addresses) {
170     std::unique_ptr<ProxyHostResolver::Request> request =
171         resolver_.CreateRequest(hostname,
172                                 net::ProxyResolveDnsOperation::DNS_RESOLVE_EX,
173                                 network_anonymization_key);
174
175     net::TestCompletionCallback callback;
176     int result = callback.GetResult(request->Start(callback.callback()));
177
178     *out_addresses = request->GetResults();
179     return result;
180   }
181
182   base::test::TaskEnvironment task_environment_;
183   Waiter waiter_;
184   MockMojoHostResolver mock_resolver_;
185   HostResolverMojo resolver_;
186 };
187
188 TEST_F(HostResolverMojoTest, Basic) {
189   const net::SchemefulSite kSite =
190       net::SchemefulSite(GURL("https://not-example.com/"));
191   const net::NetworkAnonymizationKey kNetworkAnonymizationKey(kSite, kSite);
192
193   std::vector<net::IPAddress> addresses;
194   net::IPAddress address(1, 2, 3, 4);
195   addresses.push_back(address);
196   addresses.push_back(ConvertIPv4ToIPv4MappedIPv6(address));
197   mock_resolver_.AddAction(HostResolverAction::ReturnResult(addresses));
198
199   std::vector<net::IPAddress> result;
200   EXPECT_THAT(Resolve("example.com", kNetworkAnonymizationKey, &result),
201               IsOk());
202   EXPECT_EQ(addresses, result);
203
204   ASSERT_EQ(1u, mock_resolver_.request_info().size());
205   EXPECT_EQ("example.com", mock_resolver_.request_info()[0].hostname);
206   EXPECT_EQ(kNetworkAnonymizationKey,
207             mock_resolver_.request_info()[0].network_anonymization_key);
208 }
209
210 TEST_F(HostResolverMojoTest, ResolveCachedResult) {
211   std::vector<net::IPAddress> addresses;
212   net::IPAddress address(1, 2, 3, 4);
213   addresses.push_back(address);
214   addresses.push_back(ConvertIPv4ToIPv4MappedIPv6(address));
215   mock_resolver_.AddAction(HostResolverAction::ReturnResult(addresses));
216
217   // Load results into cache.
218   std::vector<net::IPAddress> result;
219   ASSERT_THAT(Resolve("example.com", net::NetworkAnonymizationKey(), &result),
220               IsOk());
221   ASSERT_EQ(1u, mock_resolver_.request_info().size());
222
223   // Expect results from cache.
224   result.clear();
225   EXPECT_THAT(Resolve("example.com", net::NetworkAnonymizationKey(), &result),
226               IsOk());
227   EXPECT_EQ(addresses, result);
228   EXPECT_EQ(1u, mock_resolver_.request_info().size());
229 }
230
231 // Make sure the cache indexes entries by NetworkAnonymizationKey.
232 TEST_F(HostResolverMojoTest, ResolveCachedResultWithNetworkAnonymizationKey) {
233   const net::SchemefulSite kSite =
234       net::SchemefulSite(GURL("https://not-example.com/"));
235   const net::NetworkAnonymizationKey kNetworkAnonymizationKey(kSite, kSite);
236
237   std::vector<net::IPAddress> addresses1;
238   net::IPAddress address1(1, 2, 3, 4);
239   addresses1.push_back(address1);
240   addresses1.push_back(ConvertIPv4ToIPv4MappedIPv6(address1));
241   mock_resolver_.AddAction(HostResolverAction::ReturnResult(addresses1));
242
243   // Load results into cache using kNetworkAnonymizationKey.
244   std::vector<net::IPAddress> result;
245   ASSERT_THAT(Resolve("example.com", kNetworkAnonymizationKey, &result),
246               IsOk());
247   ASSERT_EQ(1u, mock_resolver_.request_info().size());
248
249   // Expect results from cache when using kNetworkAnonymizationKey.
250   result.clear();
251   EXPECT_THAT(Resolve("example.com", kNetworkAnonymizationKey, &result),
252               IsOk());
253   EXPECT_EQ(addresses1, result);
254   EXPECT_EQ(1u, mock_resolver_.request_info().size());
255
256   // A request with an empty NetworkAnonymizationKey should not use results
257   // cached using kNetworkAnonymizationKey.
258
259   std::vector<net::IPAddress> addresses2;
260   net::IPAddress address2(2, 3, 5, 8);
261   addresses2.push_back(address2);
262   addresses2.push_back(ConvertIPv4ToIPv4MappedIPv6(address2));
263   mock_resolver_.AddAction(HostResolverAction::ReturnResult(addresses2));
264
265   result.clear();
266   EXPECT_THAT(Resolve("example.com", net::NetworkAnonymizationKey(), &result),
267               IsOk());
268   EXPECT_EQ(addresses2, result);
269   EXPECT_EQ(2u, mock_resolver_.request_info().size());
270
271   // Using the empty NetworkAnonymizationKey again should result in the second
272   // cached address list.
273   result.clear();
274   EXPECT_THAT(Resolve("example.com", net::NetworkAnonymizationKey(), &result),
275               IsOk());
276   EXPECT_EQ(addresses2, result);
277   EXPECT_EQ(2u, mock_resolver_.request_info().size());
278
279   // Using kNetworkAnonymizationKey again should result in the first cached
280   // address list.
281   result.clear();
282   EXPECT_THAT(Resolve("example.com", kNetworkAnonymizationKey, &result),
283               IsOk());
284   EXPECT_EQ(addresses1, result);
285   EXPECT_EQ(2u, mock_resolver_.request_info().size());
286 }
287
288 TEST_F(HostResolverMojoTest, Multiple) {
289   std::vector<net::IPAddress> addresses;
290   addresses.emplace_back(1, 2, 3, 4);
291   mock_resolver_.AddAction(HostResolverAction::ReturnResult(addresses));
292   mock_resolver_.AddAction(
293       HostResolverAction::ReturnError(net::ERR_NAME_NOT_RESOLVED));
294
295   std::unique_ptr<ProxyHostResolver::Request> request1 =
296       resolver_.CreateRequest("example.com",
297                               net::ProxyResolveDnsOperation::DNS_RESOLVE_EX,
298                               net::NetworkAnonymizationKey());
299   std::unique_ptr<ProxyHostResolver::Request> request2 =
300       resolver_.CreateRequest("example.org",
301                               net::ProxyResolveDnsOperation::DNS_RESOLVE_EX,
302                               net::NetworkAnonymizationKey());
303   net::TestCompletionCallback callback1;
304   net::TestCompletionCallback callback2;
305   ASSERT_EQ(net::ERR_IO_PENDING, request1->Start(callback1.callback()));
306   ASSERT_EQ(net::ERR_IO_PENDING, request2->Start(callback2.callback()));
307
308   EXPECT_THAT(callback1.GetResult(net::ERR_IO_PENDING), IsOk());
309   EXPECT_THAT(callback2.GetResult(net::ERR_IO_PENDING),
310               IsError(net::ERR_NAME_NOT_RESOLVED));
311   EXPECT_EQ(addresses, request1->GetResults());
312   ASSERT_EQ(0u, request2->GetResults().size());
313
314   EXPECT_THAT(mock_resolver_.request_info(),
315               testing::ElementsAre(
316                   MockMojoHostResolver::RequestInfo{
317                       "example.com", net::NetworkAnonymizationKey()},
318                   MockMojoHostResolver::RequestInfo{
319                       "example.org", net::NetworkAnonymizationKey()}));
320 }
321
322 TEST_F(HostResolverMojoTest, Error) {
323   mock_resolver_.AddAction(
324       HostResolverAction::ReturnError(net::ERR_NAME_NOT_RESOLVED));
325
326   std::vector<net::IPAddress> result;
327   EXPECT_THAT(Resolve("example.com", net::NetworkAnonymizationKey(), &result),
328               IsError(net::ERR_NAME_NOT_RESOLVED));
329   EXPECT_TRUE(result.empty());
330
331   ASSERT_EQ(1u, mock_resolver_.request_info().size());
332   EXPECT_EQ("example.com", mock_resolver_.request_info()[0].hostname);
333 }
334
335 TEST_F(HostResolverMojoTest, EmptyResult) {
336   mock_resolver_.AddAction(HostResolverAction::ReturnError(net::OK));
337
338   std::vector<net::IPAddress> result;
339   EXPECT_THAT(Resolve("example.com", net::NetworkAnonymizationKey(), &result),
340               IsOk());
341   EXPECT_TRUE(result.empty());
342
343   ASSERT_EQ(1u, mock_resolver_.request_info().size());
344 }
345
346 TEST_F(HostResolverMojoTest, Cancel) {
347   mock_resolver_.AddAction(HostResolverAction::RetainRequest());
348
349   std::unique_ptr<ProxyHostResolver::Request> request = resolver_.CreateRequest(
350       "example.com", net::ProxyResolveDnsOperation::DNS_RESOLVE_EX,
351       net::NetworkAnonymizationKey());
352   request->Start(base::BindOnce(&Fail));
353
354   request.reset();
355   waiter_.WaitForEvent(ConnectionErrorSource::REQUEST);
356
357   ASSERT_EQ(1u, mock_resolver_.request_info().size());
358   EXPECT_EQ("example.com", mock_resolver_.request_info()[0].hostname);
359 }
360
361 TEST_F(HostResolverMojoTest, ImplDropsClientConnection) {
362   mock_resolver_.AddAction(HostResolverAction::DropRequest());
363
364   std::vector<net::IPAddress> result;
365   EXPECT_THAT(Resolve("example.com", net::NetworkAnonymizationKey(), &result),
366               IsError(net::ERR_FAILED));
367   EXPECT_TRUE(result.empty());
368
369   ASSERT_EQ(1u, mock_resolver_.request_info().size());
370   EXPECT_EQ("example.com", mock_resolver_.request_info()[0].hostname);
371 }
372
373 }  // namespace proxy_resolver