1 // Copyright 2013 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.
5 #include "ppapi/tests/test_tcp_socket.h"
7 #include "ppapi/cpp/tcp_socket.h"
8 #include "ppapi/tests/test_utils.h"
9 #include "ppapi/tests/testing_instance.h"
13 // Validates the first line of an HTTP response.
14 bool ValidateHttpResponse(const std::string
& s
) {
15 // Just check that it begins with "HTTP/" and ends with a "\r\n".
16 return s
.size() >= 5 &&
17 s
.substr(0, 5) == "HTTP/" &&
18 s
.substr(s
.size() - 2) == "\r\n";
23 REGISTER_TEST_CASE(TCPSocket
);
25 TestTCPSocket::TestTCPSocket(TestingInstance
* instance
) : TestCase(instance
) {
28 bool TestTCPSocket::Init() {
29 if (!pp::TCPSocket::IsAvailable())
32 // We need something to connect to, so we connect to the HTTP server whence we
33 // came. Grab the host and port.
34 if (!EnsureRunningOverHTTP())
39 if (!GetLocalHostPort(instance_
->pp_instance(), &host
, &port
))
42 if (!ResolveHost(instance_
->pp_instance(), host
, port
, &addr_
))
48 void TestTCPSocket::RunTests(const std::string
& filter
) {
49 RUN_CALLBACK_TEST(TestTCPSocket
, Connect
, filter
);
50 RUN_CALLBACK_TEST(TestTCPSocket
, ReadWrite
, filter
);
51 RUN_CALLBACK_TEST(TestTCPSocket
, SetOption
, filter
);
54 std::string
TestTCPSocket::TestConnect() {
55 pp::TCPSocket
socket(instance_
);
56 TestCompletionCallback
cb(instance_
->pp_instance(), callback_type());
58 cb
.WaitForResult(socket
.Connect(addr_
, cb
.GetCallback()));
59 CHECK_CALLBACK_BEHAVIOR(cb
);
60 ASSERT_EQ(PP_OK
, cb
.result());
62 pp::NetAddress local_addr
, remote_addr
;
63 local_addr
= socket
.GetLocalAddress();
64 remote_addr
= socket
.GetRemoteAddress();
66 ASSERT_NE(0, local_addr
.pp_resource());
67 ASSERT_NE(0, remote_addr
.pp_resource());
68 ASSERT_TRUE(EqualNetAddress(addr_
, remote_addr
));
75 std::string
TestTCPSocket::TestReadWrite() {
76 pp::TCPSocket
socket(instance_
);
77 TestCompletionCallback
cb(instance_
->pp_instance(), callback_type());
79 cb
.WaitForResult(socket
.Connect(addr_
, cb
.GetCallback()));
80 CHECK_CALLBACK_BEHAVIOR(cb
);
81 ASSERT_EQ(PP_OK
, cb
.result());
83 ASSERT_EQ(PP_OK
, WriteStringToSocket(&socket
, "GET / HTTP/1.0\r\n\r\n"));
85 // Read up to the first \n and check that it looks like valid HTTP response.
87 ASSERT_EQ(PP_OK
, ReadFirstLineFromSocket(&socket
, &s
));
88 ASSERT_TRUE(ValidateHttpResponse(s
));
93 std::string
TestTCPSocket::TestSetOption() {
94 pp::TCPSocket
socket(instance_
);
95 TestCompletionCallback
cb_1(instance_
->pp_instance(), callback_type());
96 TestCompletionCallback
cb_2(instance_
->pp_instance(), callback_type());
97 TestCompletionCallback
cb_3(instance_
->pp_instance(), callback_type());
99 // These options cannot be set before the socket is connected.
100 int32_t result_1
= socket
.SetOption(PP_TCPSOCKET_OPTION_NO_DELAY
,
101 true, cb_1
.GetCallback());
102 int32_t result_2
= socket
.SetOption(PP_TCPSOCKET_OPTION_SEND_BUFFER_SIZE
,
103 256, cb_2
.GetCallback());
104 int32_t result_3
= socket
.SetOption(PP_TCPSOCKET_OPTION_RECV_BUFFER_SIZE
,
105 512, cb_3
.GetCallback());
107 cb_1
.WaitForResult(result_1
);
108 CHECK_CALLBACK_BEHAVIOR(cb_1
);
109 ASSERT_EQ(PP_ERROR_FAILED
, cb_1
.result());
111 cb_2
.WaitForResult(result_2
);
112 CHECK_CALLBACK_BEHAVIOR(cb_2
);
113 ASSERT_EQ(PP_ERROR_FAILED
, cb_2
.result());
115 cb_3
.WaitForResult(result_3
);
116 CHECK_CALLBACK_BEHAVIOR(cb_3
);
117 ASSERT_EQ(PP_ERROR_FAILED
, cb_3
.result());
119 cb_1
.WaitForResult(socket
.Connect(addr_
, cb_1
.GetCallback()));
120 CHECK_CALLBACK_BEHAVIOR(cb_1
);
121 ASSERT_EQ(PP_OK
, cb_1
.result());
123 result_1
= socket
.SetOption(PP_TCPSOCKET_OPTION_NO_DELAY
,
124 false, cb_1
.GetCallback());
125 result_2
= socket
.SetOption(PP_TCPSOCKET_OPTION_SEND_BUFFER_SIZE
,
126 512, cb_2
.GetCallback());
127 result_3
= socket
.SetOption(PP_TCPSOCKET_OPTION_RECV_BUFFER_SIZE
,
128 1024, cb_3
.GetCallback());
130 cb_1
.WaitForResult(result_1
);
131 CHECK_CALLBACK_BEHAVIOR(cb_1
);
132 ASSERT_EQ(PP_OK
, cb_1
.result());
134 cb_2
.WaitForResult(result_2
);
135 CHECK_CALLBACK_BEHAVIOR(cb_2
);
136 ASSERT_EQ(PP_OK
, cb_2
.result());
138 cb_3
.WaitForResult(result_3
);
139 CHECK_CALLBACK_BEHAVIOR(cb_3
);
140 ASSERT_EQ(PP_OK
, cb_3
.result());
145 int32_t TestTCPSocket::ReadFirstLineFromSocket(pp::TCPSocket
* socket
,
150 // Make sure we don't just hang if |Read()| spews.
151 while (s
->size() < 10000) {
152 TestCompletionCallback
cb(instance_
->pp_instance(), callback_type());
153 int32_t rv
= socket
->Read(buffer
, sizeof(buffer
), cb
.GetCallback());
154 if (callback_type() == PP_REQUIRED
&& rv
!= PP_OK_COMPLETIONPENDING
)
155 return PP_ERROR_FAILED
;
156 cb
.WaitForResult(rv
);
159 if (cb
.result() == 0)
160 return PP_ERROR_FAILED
; // Didn't get a \n-terminated line.
161 s
->reserve(s
->size() + cb
.result());
162 for (int32_t i
= 0; i
< cb
.result(); i
++) {
163 s
->push_back(buffer
[i
]);
164 if (buffer
[i
] == '\n')
168 return PP_ERROR_FAILED
;
171 int32_t TestTCPSocket::WriteStringToSocket(pp::TCPSocket
* socket
,
172 const std::string
& s
) {
173 const char* buffer
= s
.data();
175 while (written
< s
.size()) {
176 TestCompletionCallback
cb(instance_
->pp_instance(), callback_type());
177 int32_t rv
= socket
->Write(buffer
+ written
, s
.size() - written
,
179 if (callback_type() == PP_REQUIRED
&& rv
!= PP_OK_COMPLETIONPENDING
)
180 return PP_ERROR_FAILED
;
181 cb
.WaitForResult(rv
);
184 if (cb
.result() == 0)
185 return PP_ERROR_FAILED
;
186 written
+= cb
.result();
188 if (written
!= s
.size())
189 return PP_ERROR_FAILED
;