| // Copyright (c) 2012 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 "ppapi/tests/test_host_resolver_private.h" | 
 |  | 
 | #include <stddef.h> | 
 |  | 
 | #include "ppapi/c/private/ppb_net_address_private.h" | 
 | #include "ppapi/cpp/module_impl.h" | 
 | #include "ppapi/cpp/private/host_resolver_private.h" | 
 | #include "ppapi/cpp/private/tcp_socket_private.h" | 
 | #include "ppapi/cpp/var.h" | 
 | #include "ppapi/tests/test_utils.h" | 
 | #include "ppapi/tests/testing_instance.h" | 
 |  | 
 | REGISTER_TEST_CASE(HostResolverPrivate); | 
 |  | 
 | TestHostResolverPrivate::TestHostResolverPrivate(TestingInstance* instance) | 
 |     : TestCase(instance) { | 
 | } | 
 |  | 
 | bool TestHostResolverPrivate::Init() { | 
 |   bool host_resolver_private_is_available = | 
 |       pp::HostResolverPrivate::IsAvailable(); | 
 |   if (!host_resolver_private_is_available) | 
 |     instance_->AppendError("PPB_HostResolver_Private interface not available"); | 
 |  | 
 |   bool tcp_socket_private_is_available = pp::TCPSocketPrivate::IsAvailable(); | 
 |   if (!tcp_socket_private_is_available) | 
 |     instance_->AppendError("PPB_TCPSocket_Private interface not available"); | 
 |  | 
 |   bool init_host_port = | 
 |       GetLocalHostPort(instance_->pp_instance(), &host_, &port_); | 
 |   if (!init_host_port) | 
 |     instance_->AppendError("Can't init host and port"); | 
 |  | 
 |   return host_resolver_private_is_available && | 
 |       tcp_socket_private_is_available && | 
 |       init_host_port && | 
 |       CheckTestingInterface() && | 
 |       EnsureRunningOverHTTP(); | 
 | } | 
 |  | 
 | void TestHostResolverPrivate::RunTests(const std::string& filter) { | 
 |   RUN_TEST(Empty, filter); | 
 |   RUN_CALLBACK_TEST(TestHostResolverPrivate, Resolve, filter); | 
 |   RUN_CALLBACK_TEST(TestHostResolverPrivate, ResolveIPv4, filter); | 
 | } | 
 |  | 
 | std::string TestHostResolverPrivate::SyncConnect(pp::TCPSocketPrivate* socket, | 
 |                                                  const std::string& host, | 
 |                                                  uint16_t port) { | 
 |   TestCompletionCallback callback(instance_->pp_instance(), callback_type()); | 
 |   callback.WaitForResult( | 
 |      socket->Connect(host.c_str(), port, callback.GetCallback())); | 
 |   CHECK_CALLBACK_BEHAVIOR(callback); | 
 |   ASSERT_EQ(PP_OK, callback.result()); | 
 |   PASS(); | 
 | } | 
 |  | 
 | std::string TestHostResolverPrivate::SyncConnect( | 
 |     pp::TCPSocketPrivate* socket, | 
 |     const PP_NetAddress_Private& address) { | 
 |   TestCompletionCallback callback(instance_->pp_instance(), callback_type()); | 
 |   callback.WaitForResult( | 
 |       socket->ConnectWithNetAddress(&address, callback.GetCallback())); | 
 |   CHECK_CALLBACK_BEHAVIOR(callback); | 
 |   ASSERT_EQ(PP_OK, callback.result()); | 
 |   PASS(); | 
 | } | 
 |  | 
 | std::string TestHostResolverPrivate::SyncRead(pp::TCPSocketPrivate* socket, | 
 |                                               char* buffer, | 
 |                                               int32_t num_bytes, | 
 |                                               int32_t* bytes_read) { | 
 |   TestCompletionCallback callback(instance_->pp_instance(), callback_type()); | 
 |   callback.WaitForResult( | 
 |       socket->Read(buffer, num_bytes, callback.GetCallback())); | 
 |   CHECK_CALLBACK_BEHAVIOR(callback); | 
 |   ASSERT_EQ(num_bytes, callback.result()); | 
 |   *bytes_read = callback.result(); | 
 |   PASS(); | 
 | } | 
 |  | 
 | std::string TestHostResolverPrivate::SyncWrite(pp::TCPSocketPrivate* socket, | 
 |                                                const char* buffer, | 
 |                                                int32_t num_bytes, | 
 |                                                int32_t* bytes_written) { | 
 |   TestCompletionCallback callback(instance_->pp_instance(), callback_type()); | 
 |   callback.WaitForResult( | 
 |       socket->Write(buffer, num_bytes, callback.GetCallback())); | 
 |   CHECK_CALLBACK_BEHAVIOR(callback); | 
 |   ASSERT_EQ(num_bytes, callback.result()); | 
 |   *bytes_written = callback.result(); | 
 |   PASS(); | 
 | } | 
 |  | 
 | std::string TestHostResolverPrivate::CheckHTTPResponse( | 
 |     pp::TCPSocketPrivate* socket, | 
 |     const std::string& request, | 
 |     const std::string& response) { | 
 |   int32_t rv = 0; | 
 |   ASSERT_SUBTEST_SUCCESS( | 
 |       SyncWrite(socket, request.c_str(), static_cast<int32_t>(request.size()), | 
 |                 &rv)); | 
 |   std::vector<char> response_buffer(response.size()); | 
 |   ASSERT_SUBTEST_SUCCESS( | 
 |       SyncRead(socket, &response_buffer[0], | 
 |                static_cast<int32_t>(response.size()), &rv)); | 
 |   std::string actual_response(&response_buffer[0], rv); | 
 |   if (response != actual_response) { | 
 |     return "CheckHTTPResponse failed, expected: " + response + | 
 |         ", actual: " + actual_response; | 
 |   } | 
 |   PASS(); | 
 | } | 
 |  | 
 | std::string TestHostResolverPrivate::SyncResolve( | 
 |     pp::HostResolverPrivate* host_resolver, | 
 |     const std::string& host, | 
 |     uint16_t port, | 
 |     const PP_HostResolver_Private_Hint& hint) { | 
 |   TestCompletionCallback callback(instance_->pp_instance(), callback_type()); | 
 |   callback.WaitForResult( | 
 |       host_resolver->Resolve(host, port, hint, callback.GetCallback())); | 
 |   CHECK_CALLBACK_BEHAVIOR(callback); | 
 |   PASS(); | 
 | } | 
 |  | 
 | std::string TestHostResolverPrivate::TestEmpty() { | 
 |   pp::HostResolverPrivate host_resolver(instance_); | 
 |   ASSERT_EQ(0, host_resolver.GetSize()); | 
 |   PP_NetAddress_Private address; | 
 |   ASSERT_FALSE(host_resolver.GetNetAddress(0, &address)); | 
 |  | 
 |   PASS(); | 
 | } | 
 |  | 
 | std::string TestHostResolverPrivate::ParametrizedTestResolve( | 
 |     const PP_HostResolver_Private_Hint &hint) { | 
 |   pp::HostResolverPrivate host_resolver(instance_); | 
 |  | 
 |   ASSERT_SUBTEST_SUCCESS(SyncResolve(&host_resolver, host_, port_, hint)); | 
 |  | 
 |   const size_t size = host_resolver.GetSize(); | 
 |   ASSERT_TRUE(size >= 1); | 
 |  | 
 |   PP_NetAddress_Private address; | 
 |   for (size_t i = 0; i < size; ++i) { | 
 |     ASSERT_TRUE(host_resolver.GetNetAddress( | 
 |         static_cast<uint32_t>(i), &address)); | 
 |  | 
 |     pp::TCPSocketPrivate socket(instance_); | 
 |     ASSERT_SUBTEST_SUCCESS(SyncConnect(&socket, address)); | 
 |     ASSERT_SUBTEST_SUCCESS(CheckHTTPResponse(&socket, | 
 |                                              "GET / HTTP/1.0\r\n\r\n", | 
 |                                              "HTTP")); | 
 |     socket.Disconnect(); | 
 |   } | 
 |  | 
 |   ASSERT_FALSE(host_resolver.GetNetAddress( | 
 |       static_cast<uint32_t>(size), &address)); | 
 |   pp::Var canonical_name = host_resolver.GetCanonicalName(); | 
 |   ASSERT_TRUE(canonical_name.is_string()); | 
 |   pp::TCPSocketPrivate socket(instance_); | 
 |   ASSERT_SUBTEST_SUCCESS(SyncConnect(&socket, | 
 |                                      canonical_name.AsString(), | 
 |                                      port_)); | 
 |   ASSERT_SUBTEST_SUCCESS(CheckHTTPResponse(&socket, | 
 |                                            "GET / HTTP/1.0\r\n\r\n", | 
 |                                            "HTTP")); | 
 |   socket.Disconnect(); | 
 |  | 
 |   PASS(); | 
 | } | 
 |  | 
 | std::string TestHostResolverPrivate::TestResolve() { | 
 |   PP_HostResolver_Private_Hint hint; | 
 |   hint.family = PP_NETADDRESSFAMILY_PRIVATE_UNSPECIFIED; | 
 |   hint.flags = PP_HOST_RESOLVER_PRIVATE_FLAGS_CANONNAME; | 
 |   return ParametrizedTestResolve(hint); | 
 | } | 
 |  | 
 | std::string TestHostResolverPrivate::TestResolveIPv4() { | 
 |   PP_HostResolver_Private_Hint hint; | 
 |   hint.family = PP_NETADDRESSFAMILY_PRIVATE_IPV4; | 
 |   hint.flags = PP_HOST_RESOLVER_PRIVATE_FLAGS_CANONNAME; | 
 |   return ParametrizedTestResolve(hint); | 
 | } |