OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 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. | |
4 | |
5 #include "ppapi/tests/test_tcp_socket.h" | |
6 | |
7 #include "ppapi/cpp/dev/tcp_socket_dev.h" | |
8 #include "ppapi/tests/testing_instance.h" | |
9 #include "ppapi/tests/test_utils.h" | |
10 | |
11 namespace { | |
12 | |
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"; | |
19 } | |
20 | |
21 } // namespace | |
22 | |
23 REGISTER_TEST_CASE(TCPSocket); | |
24 | |
25 TestTCPSocket::TestTCPSocket(TestingInstance* instance) : TestCase(instance) { | |
26 } | |
27 | |
28 bool TestTCPSocket::Init() { | |
29 if (!pp::TCPSocket_Dev::IsAvailable()) | |
30 return false; | |
31 | |
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()) | |
35 return false; | |
36 | |
37 std::string host; | |
38 uint16_t port = 0; | |
39 if (!GetLocalHostPort(instance_->pp_instance(), &host, &port)) | |
40 return false; | |
41 | |
42 if (!ResolveHost(instance_->pp_instance(), host, port, &addr_)) | |
43 return false; | |
44 | |
45 return true; | |
46 } | |
47 | |
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); | |
52 } | |
53 | |
54 std::string TestTCPSocket::TestConnect() { | |
55 pp::TCPSocket_Dev socket(instance_); | |
56 TestCompletionCallback cb(instance_->pp_instance(), callback_type()); | |
57 | |
58 cb.WaitForResult(socket.Connect(addr_, cb.GetCallback())); | |
59 CHECK_CALLBACK_BEHAVIOR(cb); | |
60 ASSERT_EQ(PP_OK, cb.result()); | |
61 | |
62 pp::NetAddress_Dev local_addr, remote_addr; | |
63 local_addr = socket.GetLocalAddress(); | |
64 remote_addr = socket.GetRemoteAddress(); | |
65 | |
66 ASSERT_NE(0, local_addr.pp_resource()); | |
67 ASSERT_NE(0, remote_addr.pp_resource()); | |
68 ASSERT_TRUE(EqualNetAddress(addr_, remote_addr)); | |
69 | |
70 socket.Close(); | |
71 | |
72 PASS(); | |
73 } | |
74 | |
75 std::string TestTCPSocket::TestReadWrite() { | |
76 pp::TCPSocket_Dev socket(instance_); | |
77 TestCompletionCallback cb(instance_->pp_instance(), callback_type()); | |
78 | |
79 cb.WaitForResult(socket.Connect(addr_, cb.GetCallback())); | |
80 CHECK_CALLBACK_BEHAVIOR(cb); | |
81 ASSERT_EQ(PP_OK, cb.result()); | |
82 | |
83 ASSERT_EQ(PP_OK, WriteStringToSocket(&socket, "GET / HTTP/1.0\r\n\r\n")); | |
84 | |
85 // Read up to the first \n and check that it looks like valid HTTP response. | |
86 std::string s; | |
87 ASSERT_EQ(PP_OK, ReadFirstLineFromSocket(&socket, &s)); | |
88 ASSERT_TRUE(ValidateHttpResponse(s)); | |
89 | |
90 PASS(); | |
91 } | |
92 | |
93 std::string TestTCPSocket::TestSetOption() { | |
94 pp::TCPSocket_Dev socket(instance_); | |
95 TestCompletionCallback cb(instance_->pp_instance(), callback_type()); | |
96 | |
97 cb.WaitForResult( | |
98 socket.SetOption(PP_TCPSOCKET_OPTION_NO_DELAY, true, cb.GetCallback())); | |
99 CHECK_CALLBACK_BEHAVIOR(cb); | |
100 ASSERT_EQ(PP_ERROR_FAILED, cb.result()); | |
101 | |
102 cb.WaitForResult(socket.Connect(addr_, cb.GetCallback())); | |
103 CHECK_CALLBACK_BEHAVIOR(cb); | |
104 ASSERT_EQ(PP_OK, cb.result()); | |
105 | |
106 cb.WaitForResult( | |
107 socket.SetOption(PP_TCPSOCKET_OPTION_NO_DELAY, true, cb.GetCallback())); | |
108 CHECK_CALLBACK_BEHAVIOR(cb); | |
109 ASSERT_EQ(PP_OK, cb.result()); | |
110 | |
111 PASS(); | |
112 } | |
113 | |
114 int32_t TestTCPSocket::ReadFirstLineFromSocket(pp::TCPSocket_Dev* socket, | |
115 std::string* s) { | |
116 char buffer[10000]; | |
117 | |
118 s->clear(); | |
119 // Make sure we don't just hang if |Read()| spews. | |
120 while (s->size() < 1000000) { | |
121 TestCompletionCallback cb(instance_->pp_instance(), callback_type()); | |
122 int32_t rv = socket->Read(buffer, sizeof(buffer), cb.GetCallback()); | |
123 if (callback_type() == PP_REQUIRED && rv != PP_OK_COMPLETIONPENDING) | |
124 return PP_ERROR_FAILED; | |
125 cb.WaitForResult(rv); | |
126 if (cb.result() < 0) | |
127 return cb.result(); | |
128 if (cb.result() == 0) | |
129 return PP_ERROR_FAILED; // Didn't get a \n-terminated line. | |
130 s->reserve(s->size() + cb.result()); | |
131 for (int32_t i = 0; i < cb.result(); i++) { | |
132 s->push_back(buffer[i]); | |
dmichael (off chromium)
2013/06/11 21:15:26
optional: I would maybe use string::copy instead o
yzshen1
2013/06/12 05:20:54
Thanks!
I tried two different versions:
==========
| |
133 if (buffer[i] == '\n') | |
134 return PP_OK; | |
135 } | |
136 } | |
137 return PP_ERROR_FAILED; | |
138 } | |
139 | |
140 int32_t TestTCPSocket::WriteStringToSocket(pp::TCPSocket_Dev* socket, | |
141 const std::string& s) { | |
142 const char* buffer = s.data(); | |
143 size_t written = 0; | |
144 while (written < s.size()) { | |
145 TestCompletionCallback cb(instance_->pp_instance(), callback_type()); | |
146 int32_t rv = socket->Write(buffer + written, s.size() - written, | |
147 cb.GetCallback()); | |
148 if (callback_type() == PP_REQUIRED && rv != PP_OK_COMPLETIONPENDING) | |
149 return PP_ERROR_FAILED; | |
150 cb.WaitForResult(rv); | |
151 if (cb.result() < 0) | |
152 return cb.result(); | |
153 if (cb.result() == 0) | |
154 return PP_ERROR_FAILED; | |
155 written += cb.result(); | |
156 } | |
157 if (written != s.size()) | |
158 return PP_ERROR_FAILED; | |
159 return PP_OK; | |
160 } | |
OLD | NEW |