Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(196)

Unified Diff: net/dns/host_resolver_mojo_unittest.cc

Issue 904313003: Implement utility-side host resolver Mojo client. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@mojo-proxy-resolver
Patch Set: Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: net/dns/host_resolver_mojo_unittest.cc
diff --git a/net/dns/host_resolver_mojo_unittest.cc b/net/dns/host_resolver_mojo_unittest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..c3aa98abfb30d97915d1133355567ba30d92fe19
--- /dev/null
+++ b/net/dns/host_resolver_mojo_unittest.cc
@@ -0,0 +1,385 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/dns/host_resolver_mojo.h"
+
+#include <string>
+
+#include "base/barrier_closure.h"
+#include "base/memory/scoped_vector.h"
+#include "base/run_loop.h"
+#include "net/base/net_errors.h"
+#include "net/base/request_priority.h"
+#include "net/dns/type_converters.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/mojo/src/mojo/public/cpp/bindings/binding.h"
+#include "third_party/mojo/src/mojo/public/cpp/bindings/error_handler.h"
+
+namespace net {
+namespace {
+
+enum class ConnectionErrorSource {
+ NONE,
+ RESOLVER,
+ REQUEST,
+ CLIENT,
+};
+
+void OnResolveComplete(int* error_out,
+ const base::Closure& quit_run_loop,
+ int error) {
+ if (!quit_run_loop.is_null())
+ quit_run_loop.Run();
+ *error_out = error;
+}
+
+void Fail(int result) {
+ FAIL() << "Unexpected callback called with error " << result;
+}
+
+class MockMojoHostResolverRequest : public mojo::ErrorHandler {
+ public:
+ MockMojoHostResolverRequest(interfaces::HostResolverRequestClientPtr client,
+ const base::Closure& error_callback);
+ void OnConnectionError() override;
+
+ private:
+ interfaces::HostResolverRequestClientPtr client_;
+ const base::Closure error_callback_;
+};
+
+MockMojoHostResolverRequest::MockMojoHostResolverRequest(
+ interfaces::HostResolverRequestClientPtr client,
+ const base::Closure& error_callback)
+ : client_(client.Pass()), error_callback_(error_callback) {
+ client_.set_error_handler(this);
+}
+
+void MockMojoHostResolverRequest::OnConnectionError() {
+ error_callback_.Run();
+}
+
+struct HostResolverAction {
+ public:
+ enum Action {
+ COMPLETE,
+ DROP,
+ RETAIN,
+ };
+
+ static scoped_ptr<HostResolverAction> ReturnError(int error) {
+ scoped_ptr<HostResolverAction> result(new HostResolverAction);
+ result->error = error;
+ return result.Pass();
+ }
+
+ static scoped_ptr<HostResolverAction> ReturnResult(
+ const AddressList& address_list) {
+ scoped_ptr<HostResolverAction> result(new HostResolverAction);
+ result->addresses = interfaces::AddressList::From(address_list);
+ return result.Pass();
+ }
+
+ static scoped_ptr<HostResolverAction> DropRequest() {
+ scoped_ptr<HostResolverAction> result(new HostResolverAction);
+ result->action = DROP;
+ return result.Pass();
+ }
+
+ static scoped_ptr<HostResolverAction> RetainRequest() {
+ scoped_ptr<HostResolverAction> result(new HostResolverAction);
+ result->action = RETAIN;
+ return result.Pass();
+ }
+
+ Action action = COMPLETE;
+ interfaces::AddressListPtr addresses;
+ int error = OK;
+};
+
+class MockMojoHostResolver : public interfaces::HostResolver,
+ public mojo::ErrorHandler {
+ public:
+ explicit MockMojoHostResolver(
Anand Mistry (off Chromium) 2015/02/16 06:32:44 Can you add a destructor that does: ASSERT_EQ(resu
Sam McNally 2015/02/16 07:24:44 Done.
+ mojo::InterfaceRequest<interfaces::HostResolver> request,
+ const base::Closure& resolver_connection_error_callback,
+ const base::Closure& request_connection_error_callback);
+
+ void AddAction(scoped_ptr<HostResolverAction> action);
+
+ const mojo::Array<interfaces::HostResolverRequestInfoPtr>& requests() {
+ return requests_received_;
+ }
+
+ private:
+ // interfaces::HostResolver override.
+ void Resolve(interfaces::HostResolverRequestInfoPtr request_info,
+ interfaces::HostResolverRequestClientPtr client) override;
+
+ // mojo::ErrorHandler override.
+ void OnConnectionError() override;
+
+ mojo::Binding<interfaces::HostResolver> binding_;
+ ScopedVector<HostResolverAction> actions_;
+ size_t results_returned_ = 0;
+ mojo::Array<interfaces::HostResolverRequestInfoPtr> requests_received_;
+ const base::Closure resolver_connection_error_callback_;
+ const base::Closure request_connection_error_callback_;
+ ScopedVector<MockMojoHostResolverRequest> requests_;
+};
+
+MockMojoHostResolver::MockMojoHostResolver(
+ mojo::InterfaceRequest<interfaces::HostResolver> request,
+ const base::Closure& resolver_connection_error_callback,
+ const base::Closure& request_connection_error_callback)
+ : binding_(this, request.Pass()),
+ resolver_connection_error_callback_(resolver_connection_error_callback),
+ request_connection_error_callback_(request_connection_error_callback) {
+ binding_.set_error_handler(this);
+}
+
+void MockMojoHostResolver::OnConnectionError() {
+ resolver_connection_error_callback_.Run();
+}
+
+void MockMojoHostResolver::AddAction(scoped_ptr<HostResolverAction> action) {
+ actions_.push_back(action.release());
+}
+
+void MockMojoHostResolver::Resolve(
+ interfaces::HostResolverRequestInfoPtr request_info,
+ interfaces::HostResolverRequestClientPtr client) {
+ requests_received_.push_back(request_info.Pass());
+ ASSERT_LE(results_returned_, actions_.size());
+ switch (actions_[results_returned_]->action) {
+ case HostResolverAction::COMPLETE:
+ client->ReportResult(actions_[results_returned_]->error,
+ actions_[results_returned_]->addresses.Pass());
+ break;
+ case HostResolverAction::RETAIN:
+ requests_.push_back(new MockMojoHostResolverRequest(
+ client.Pass(), request_connection_error_callback_));
+ break;
+ case HostResolverAction::DROP:
+ client.reset();
+ break;
+ }
+ results_returned_++;
+}
+
+} // namespace
+
+class HostResolverMojoTest : public testing::Test, public mojo::ErrorHandler {
+ protected:
+ void SetUp() override {
+ interfaces::HostResolverPtr resolver_ptr;
+ mock_resolver_.reset(new MockMojoHostResolver(
+ mojo::GetProxy(&resolver_ptr),
+ base::Bind(&HostResolverMojoTest::HandleConnectionError,
+ base::Unretained(this), ConnectionErrorSource::RESOLVER),
+ base::Bind(&HostResolverMojoTest::HandleConnectionError,
+ base::Unretained(this), ConnectionErrorSource::REQUEST)));
+ resolver_.reset(new HostResolverMojo(resolver_ptr.Pass(), this));
+ }
+
+ void OnConnectionError() override {
+ HandleConnectionError(ConnectionErrorSource::CLIENT);
+ }
+
+ void HandleConnectionError(ConnectionErrorSource source) {
+ if (!run_loop_quit_closure_.is_null())
+ run_loop_quit_closure_.Run();
+ ASSERT_EQ(expected_connection_error_source_, source);
+ }
+
+ int Resolve(const HostResolver::RequestInfo& request_info,
+ AddressList* result) {
+ HostResolver::RequestHandle request_handle = nullptr;
+ base::RunLoop run_loop;
+ int error = 1;
+ resolver_->Resolve(
+ request_info, DEFAULT_PRIORITY, result,
+ base::Bind(&OnResolveComplete, &error, run_loop.QuitClosure()),
Anand Mistry (off Chromium) 2015/02/16 06:32:44 net::TestCompletionCallback
Sam McNally 2015/02/16 07:24:44 Done.
+ &request_handle, BoundNetLog());
+ run_loop.Run();
+ return error;
+ }
+
+ void WaitForConnectionError(ConnectionErrorSource source) {
+ expected_connection_error_source_ = source;
+ base::RunLoop run_loop;
+ run_loop_quit_closure_ = run_loop.QuitClosure();
+ run_loop.Run();
+ }
+
+ scoped_ptr<MockMojoHostResolver> mock_resolver_;
+
+ scoped_ptr<HostResolverMojo> resolver_;
+
+ ConnectionErrorSource expected_connection_error_source_ =
+ ConnectionErrorSource::NONE;
+ base::Closure run_loop_quit_closure_;
+};
+
+TEST_F(HostResolverMojoTest, Basic) {
+ AddressList address_list;
+ IPAddressNumber address_number;
+ ASSERT_TRUE(ParseIPLiteralToNumber("1.2.3.4", &address_number));
+ address_list.push_back(IPEndPoint(address_number, 12345));
+ address_list.push_back(
+ IPEndPoint(ConvertIPv4NumberToIPv6Number(address_number), 12345));
+ mock_resolver_->AddAction(HostResolverAction::ReturnResult(address_list));
+ HostResolver::RequestInfo request_info(
+ HostPortPair::FromString("example.com:12345"));
+ AddressList result;
+ EXPECT_EQ(OK, Resolve(request_info, &result));
+ ASSERT_EQ(2u, result.size());
+ EXPECT_EQ(address_list[0], result[0]);
+ EXPECT_EQ(address_list[1], result[1]);
+
+ ASSERT_EQ(1u, mock_resolver_->requests().size());
+ interfaces::HostResolverRequestInfo& request = *mock_resolver_->requests()[0];
+ EXPECT_EQ("example.com", request.host.To<std::string>());
+ EXPECT_EQ(12345, request.port);
+ EXPECT_EQ(interfaces::ADDRESS_FAMILY_UNSPECIFIED, request.address_family);
+ EXPECT_FALSE(request.is_my_ip_address);
+}
+
+TEST_F(HostResolverMojoTest, Multiple) {
+ AddressList address_list;
+ IPAddressNumber address_number;
+ ASSERT_TRUE(ParseIPLiteralToNumber("1.2.3.4", &address_number));
+ address_list.push_back(IPEndPoint(address_number, 12345));
+ mock_resolver_->AddAction(HostResolverAction::ReturnResult(address_list));
+ mock_resolver_->AddAction(
+ HostResolverAction::ReturnError(ERR_NAME_NOT_RESOLVED));
+ HostResolver::RequestInfo request_info1(
+ HostPortPair::FromString("example.com:12345"));
+ request_info1.set_address_family(ADDRESS_FAMILY_IPV4);
+ request_info1.set_is_my_ip_address(true);
+ HostResolver::RequestInfo request_info2(
+ HostPortPair::FromString("example.org:80"));
+ request_info2.set_address_family(ADDRESS_FAMILY_IPV6);
+ AddressList result1;
+ AddressList result2;
+ HostResolver::RequestHandle request_handle1 = nullptr;
+ HostResolver::RequestHandle request_handle2 = nullptr;
+ int error1 = 1;
+ int error2 = 1;
+ base::RunLoop run_loop;
+ base::Closure barrier = base::BarrierClosure(2, run_loop.QuitClosure());
+ resolver_->Resolve(request_info1, DEFAULT_PRIORITY, &result1,
+ base::Bind(&OnResolveComplete, &error1, barrier),
+ &request_handle1, BoundNetLog());
+ resolver_->Resolve(request_info2, DEFAULT_PRIORITY, &result2,
+ base::Bind(&OnResolveComplete, &error2, barrier),
+ &request_handle2, BoundNetLog());
+ run_loop.Run();
+ EXPECT_EQ(OK, error1);
+ EXPECT_EQ(ERR_NAME_NOT_RESOLVED, error2);
+ ASSERT_EQ(1u, result1.size());
+ EXPECT_EQ(address_list[0], result1[0]);
+ ASSERT_EQ(0u, result2.size());
+
+ ASSERT_EQ(2u, mock_resolver_->requests().size());
+ interfaces::HostResolverRequestInfo& request1 =
+ *mock_resolver_->requests()[0];
+ EXPECT_EQ("example.com", request1.host.To<std::string>());
+ EXPECT_EQ(12345, request1.port);
+ EXPECT_EQ(interfaces::ADDRESS_FAMILY_IPV4, request1.address_family);
+ EXPECT_TRUE(request1.is_my_ip_address);
+ interfaces::HostResolverRequestInfo& request2 =
+ *mock_resolver_->requests()[1];
+ EXPECT_EQ("example.org", request2.host.To<std::string>());
+ EXPECT_EQ(80, request2.port);
+ EXPECT_EQ(interfaces::ADDRESS_FAMILY_IPV6, request2.address_family);
+ EXPECT_FALSE(request2.is_my_ip_address);
+}
+
+TEST_F(HostResolverMojoTest, Error) {
+ mock_resolver_->AddAction(
+ HostResolverAction::ReturnError(ERR_NAME_NOT_RESOLVED));
+ HostResolver::RequestInfo request_info(
+ HostPortPair::FromString("example.com:8080"));
+ request_info.set_address_family(ADDRESS_FAMILY_IPV4);
+ AddressList result;
+ EXPECT_EQ(ERR_NAME_NOT_RESOLVED, Resolve(request_info, &result));
+ EXPECT_TRUE(result.empty());
+
+ ASSERT_EQ(1u, mock_resolver_->requests().size());
+ interfaces::HostResolverRequestInfo& request = *mock_resolver_->requests()[0];
+ EXPECT_EQ("example.com", request.host.To<std::string>());
+ EXPECT_EQ(8080, request.port);
+ EXPECT_EQ(interfaces::ADDRESS_FAMILY_IPV4, request.address_family);
+ EXPECT_FALSE(request.is_my_ip_address);
+}
+
+TEST_F(HostResolverMojoTest, EmptyResult) {
+ mock_resolver_->AddAction(HostResolverAction::ReturnError(OK));
+ HostResolver::RequestInfo request_info(
+ HostPortPair::FromString("example.com:8080"));
+ AddressList result;
+ EXPECT_EQ(OK, Resolve(request_info, &result));
+ EXPECT_TRUE(result.empty());
+
+ ASSERT_EQ(1u, mock_resolver_->requests().size());
+}
+
+TEST_F(HostResolverMojoTest, Cancel) {
+ mock_resolver_->AddAction(HostResolverAction::RetainRequest());
+ HostResolver::RequestInfo request_info(
+ HostPortPair::FromString("example.com:80"));
+ request_info.set_address_family(ADDRESS_FAMILY_IPV6);
+ AddressList result;
+ HostResolver::RequestHandle request_handle = nullptr;
+ resolver_->Resolve(request_info, DEFAULT_PRIORITY, &result, base::Bind(&Fail),
+ &request_handle, BoundNetLog());
+ resolver_->CancelRequest(request_handle);
+ WaitForConnectionError(ConnectionErrorSource::REQUEST);
+ EXPECT_TRUE(result.empty());
+
+ ASSERT_EQ(1u, mock_resolver_->requests().size());
+ interfaces::HostResolverRequestInfo& request = *mock_resolver_->requests()[0];
+ EXPECT_EQ("example.com", request.host.To<std::string>());
+ EXPECT_EQ(80, request.port);
+ EXPECT_EQ(interfaces::ADDRESS_FAMILY_IPV6, request.address_family);
+ EXPECT_FALSE(request.is_my_ip_address);
+}
+
+TEST_F(HostResolverMojoTest, ImplDropsClientConnection) {
+ mock_resolver_->AddAction(HostResolverAction::DropRequest());
+ HostResolver::RequestInfo request_info(
+ HostPortPair::FromString("example.com:1"));
+ AddressList result;
+ EXPECT_EQ(ERR_FAILED, Resolve(request_info, &result));
+ EXPECT_TRUE(result.empty());
+
+ ASSERT_EQ(1u, mock_resolver_->requests().size());
+ interfaces::HostResolverRequestInfo& request = *mock_resolver_->requests()[0];
+ EXPECT_EQ("example.com", request.host.To<std::string>());
+ EXPECT_EQ(1, request.port);
+ EXPECT_EQ(interfaces::ADDRESS_FAMILY_UNSPECIFIED, request.address_family);
+ EXPECT_FALSE(request.is_my_ip_address);
+}
+
+TEST_F(HostResolverMojoTest, DestroyImpl) {
+ mock_resolver_.reset();
+ WaitForConnectionError(ConnectionErrorSource::CLIENT);
+}
+
+TEST_F(HostResolverMojoTest, DestroyClient) {
+ resolver_.reset();
+ WaitForConnectionError(ConnectionErrorSource::RESOLVER);
+}
+
+TEST_F(HostResolverMojoTest, ResolveFromCache) {
+ HostResolver::RequestInfo request_info(
+ HostPortPair::FromString("example.com:8080"));
+ AddressList result;
+ EXPECT_EQ(ERR_DNS_CACHE_MISS,
+ resolver_->ResolveFromCache(request_info, &result, BoundNetLog()));
+ EXPECT_TRUE(result.empty());
+}
+
+} // namespace net

Powered by Google App Engine
This is Rietveld 408576698