1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
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 "ppapi/tests/test_host_resolver_private.h"
6
7#include "ppapi/c/private/ppb_net_address_private.h"
8#include "ppapi/cpp/module_impl.h"
9#include "ppapi/cpp/private/host_resolver_private.h"
10#include "ppapi/cpp/private/tcp_socket_private.h"
11#include "ppapi/cpp/var.h"
12#include "ppapi/tests/test_utils.h"
13#include "ppapi/tests/testing_instance.h"
14
15REGISTER_TEST_CASE(HostResolverPrivate);
16
17TestHostResolverPrivate::TestHostResolverPrivate(TestingInstance* instance)
18    : TestCase(instance) {
19}
20
21bool TestHostResolverPrivate::Init() {
22  bool host_resolver_private_is_available =
23      pp::HostResolverPrivate::IsAvailable();
24  if (!host_resolver_private_is_available)
25    instance_->AppendError("PPB_HostResolver_Private interface not available");
26
27  bool tcp_socket_private_is_available = pp::TCPSocketPrivate::IsAvailable();
28  if (!tcp_socket_private_is_available)
29    instance_->AppendError("PPB_TCPSocket_Private interface not available");
30
31  bool init_host_port =
32      GetLocalHostPort(instance_->pp_instance(), &host_, &port_);
33  if (!init_host_port)
34    instance_->AppendError("Can't init host and port");
35
36  return host_resolver_private_is_available &&
37      tcp_socket_private_is_available &&
38      init_host_port &&
39      CheckTestingInterface() &&
40      EnsureRunningOverHTTP();
41}
42
43void TestHostResolverPrivate::RunTests(const std::string& filter) {
44  RUN_TEST(Empty, filter);
45  RUN_CALLBACK_TEST(TestHostResolverPrivate, Resolve, filter);
46  RUN_CALLBACK_TEST(TestHostResolverPrivate, ResolveIPv4, filter);
47}
48
49std::string TestHostResolverPrivate::SyncConnect(pp::TCPSocketPrivate* socket,
50                                                 const std::string& host,
51                                                 uint16_t port) {
52  TestCompletionCallback callback(instance_->pp_instance(), callback_type());
53  callback.WaitForResult(
54     socket->Connect(host.c_str(), port, callback.GetCallback()));
55  CHECK_CALLBACK_BEHAVIOR(callback);
56  ASSERT_EQ(PP_OK, callback.result());
57  PASS();
58}
59
60std::string TestHostResolverPrivate::SyncConnect(
61    pp::TCPSocketPrivate* socket,
62    const PP_NetAddress_Private& address) {
63  TestCompletionCallback callback(instance_->pp_instance(), callback_type());
64  callback.WaitForResult(
65      socket->ConnectWithNetAddress(&address, callback.GetCallback()));
66  CHECK_CALLBACK_BEHAVIOR(callback);
67  ASSERT_EQ(PP_OK, callback.result());
68  PASS();
69}
70
71std::string TestHostResolverPrivate::SyncRead(pp::TCPSocketPrivate* socket,
72                                              char* buffer,
73                                              int32_t num_bytes,
74                                              int32_t* bytes_read) {
75  TestCompletionCallback callback(instance_->pp_instance(), callback_type());
76  callback.WaitForResult(
77      socket->Read(buffer, num_bytes, callback.GetCallback()));
78  CHECK_CALLBACK_BEHAVIOR(callback);
79  ASSERT_EQ(num_bytes, callback.result());
80  *bytes_read = callback.result();
81  PASS();
82}
83
84std::string TestHostResolverPrivate::SyncWrite(pp::TCPSocketPrivate* socket,
85                                               const char* buffer,
86                                               int32_t num_bytes,
87                                               int32_t* bytes_written) {
88  TestCompletionCallback callback(instance_->pp_instance(), callback_type());
89  callback.WaitForResult(
90      socket->Write(buffer, num_bytes, callback.GetCallback()));
91  CHECK_CALLBACK_BEHAVIOR(callback);
92  ASSERT_EQ(num_bytes, callback.result());
93  *bytes_written = callback.result();
94  PASS();
95}
96
97std::string TestHostResolverPrivate::CheckHTTPResponse(
98    pp::TCPSocketPrivate* socket,
99    const std::string& request,
100    const std::string& response) {
101  int32_t rv = 0;
102  ASSERT_SUBTEST_SUCCESS(
103      SyncWrite(socket, request.c_str(), request.size(), &rv));
104  std::vector<char> response_buffer(response.size());
105  ASSERT_SUBTEST_SUCCESS(
106      SyncRead(socket, &response_buffer[0], response.size(), &rv));
107  std::string actual_response(&response_buffer[0], rv);
108  if (response != actual_response) {
109    return "CheckHTTPResponse failed, expected: " + response +
110        ", actual: " + actual_response;
111  }
112  PASS();
113}
114
115std::string TestHostResolverPrivate::SyncResolve(
116    pp::HostResolverPrivate* host_resolver,
117    const std::string& host,
118    uint16_t port,
119    const PP_HostResolver_Private_Hint& hint) {
120  TestCompletionCallback callback(instance_->pp_instance(), callback_type());
121  callback.WaitForResult(
122      host_resolver->Resolve(host, port, hint, callback.GetCallback()));
123  CHECK_CALLBACK_BEHAVIOR(callback);
124  PASS();
125}
126
127std::string TestHostResolverPrivate::TestEmpty() {
128  pp::HostResolverPrivate host_resolver(instance_);
129  ASSERT_EQ(0, host_resolver.GetSize());
130  PP_NetAddress_Private address;
131  ASSERT_FALSE(host_resolver.GetNetAddress(0, &address));
132
133  PASS();
134}
135
136std::string TestHostResolverPrivate::ParametrizedTestResolve(
137    const PP_HostResolver_Private_Hint &hint) {
138  pp::HostResolverPrivate host_resolver(instance_);
139
140  ASSERT_SUBTEST_SUCCESS(SyncResolve(&host_resolver, host_, port_, hint));
141
142  const size_t size = host_resolver.GetSize();
143  ASSERT_TRUE(size >= 1);
144
145  PP_NetAddress_Private address;
146  for (size_t i = 0; i < size; ++i) {
147    ASSERT_TRUE(host_resolver.GetNetAddress(i, &address));
148
149    pp::TCPSocketPrivate socket(instance_);
150    ASSERT_SUBTEST_SUCCESS(SyncConnect(&socket, address));
151    ASSERT_SUBTEST_SUCCESS(CheckHTTPResponse(&socket,
152                                             "GET / HTTP/1.0\r\n\r\n",
153                                             "HTTP"));
154    socket.Disconnect();
155  }
156
157  ASSERT_FALSE(host_resolver.GetNetAddress(size, &address));
158  pp::Var canonical_name = host_resolver.GetCanonicalName();
159  ASSERT_TRUE(canonical_name.is_string());
160  pp::TCPSocketPrivate socket(instance_);
161  ASSERT_SUBTEST_SUCCESS(SyncConnect(&socket,
162                                     canonical_name.AsString(),
163                                     port_));
164  ASSERT_SUBTEST_SUCCESS(CheckHTTPResponse(&socket,
165                                           "GET / HTTP/1.0\r\n\r\n",
166                                           "HTTP"));
167  socket.Disconnect();
168
169  PASS();
170}
171
172std::string TestHostResolverPrivate::TestResolve() {
173  PP_HostResolver_Private_Hint hint;
174  hint.family = PP_NETADDRESSFAMILY_PRIVATE_UNSPECIFIED;
175  hint.flags = PP_HOST_RESOLVER_PRIVATE_FLAGS_CANONNAME;
176  return ParametrizedTestResolve(hint);
177}
178
179std::string TestHostResolverPrivate::TestResolveIPv4() {
180  PP_HostResolver_Private_Hint hint;
181  hint.family = PP_NETADDRESSFAMILY_PRIVATE_IPV4;
182  hint.flags = PP_HOST_RESOLVER_PRIVATE_FLAGS_CANONNAME;
183  return ParametrizedTestResolve(hint);
184}
185