OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2011 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_private.h" | |
6 | |
7 #include <stdlib.h> | |
8 | |
9 #include <string> | |
10 #include <vector> | |
11 //FIXME | |
yzshen1
2011/11/15 00:47:07
Please use "// TODO(somebody): What to do."
viettrungluu
2011/11/15 01:08:26
Oops, leftover cruft.
| |
12 #include <iostream> | |
13 | |
14 #include "base/string_split.h" | |
15 #include "ppapi/c/dev/ppb_url_util_dev.h" | |
16 #include "ppapi/cpp/dev/url_util_dev.h" | |
17 #include "ppapi/cpp/private/flash_tcp_socket.h" | |
18 #include "ppapi/c/pp_stdint.h" | |
yzshen1
2011/11/15 00:47:07
This is not needed since it has been included in .
viettrungluu
2011/11/15 01:08:26
Fixed. (But, AFAIK, the C++ headers don't necessar
yzshen1
2011/11/15 01:16:56
What do you mean by "C++ headers"?
| |
19 #include "ppapi/cpp/var.h" | |
20 #include "ppapi/tests/testing_instance.h" | |
21 #include "ppapi/tests/test_utils.h" | |
22 | |
23 namespace { | |
24 | |
25 // Validates the first line of an HTTP response. | |
26 bool ValidateHttpResponse(const std::string& s) { | |
27 // Just check that it begins with "HTTP/" and ends with a "\r\n". | |
28 return s.size() >= 5 && | |
29 s.substr(0, 5) == "HTTP/" && | |
30 s.substr(s.size() - 2) == "\r\n"; | |
31 } | |
32 | |
33 } // namespace | |
34 | |
35 REGISTER_TEST_CASE(TCPSocketPrivate); | |
36 | |
37 TestTCPSocketPrivate::TestTCPSocketPrivate(TestingInstance* instance) | |
38 : TestCase(instance) { | |
39 } | |
40 | |
41 bool TestTCPSocketPrivate::Init() { | |
42 if (!TCPSocketPrivate::IsAvailable()) | |
43 return false; | |
44 | |
45 // This test currently only works out-of-process (since the API is really only | |
46 // implemented in that case). | |
47 const PPB_Testing_Dev* testing = GetTestingInterface(); | |
48 if (!testing) | |
49 return false; | |
50 if (!testing->IsOutOfProcess()) | |
51 return false; | |
52 | |
53 // We need something to connect to, so we connect to the HTTP server whence we | |
yzshen1
2011/11/15 00:47:07
Haha!
So what is your plan to test the UDP API? :)
viettrungluu
2011/11/15 01:08:26
?!? Who knows. I don't even know how I'll properly
| |
54 // came. Grab the host and port. | |
55 | |
56 PP_URLComponents_Dev c; | |
yzshen1
2011/11/15 00:47:07
This name is not very descriptive.
viettrungluu
2011/11/15 01:08:26
But it's wonderfully short? I changed it to "compo
| |
57 pp::Var pp_url = pp::URLUtil_Dev::Get()->GetDocumentURL(*instance_, &c); | |
58 if (!pp_url.is_string()) | |
59 return false; | |
60 std::string url = pp_url.AsString(); | |
61 | |
62 // Only support HTTP schGeme. | |
63 if (c.scheme.len < 0) | |
64 return false; | |
65 if (url.substr(c.scheme.begin, c.scheme.len) != "http") | |
66 return false; | |
yzshen1
2011/11/15 00:47:07
You may want to use EnsureRunningOverHTTP
viettrungluu
2011/11/15 01:08:26
I'll do that in addition to what I do here....
| |
67 | |
68 // Get host. | |
69 if (c.host.len < 0) | |
70 return false; | |
71 host_ = url.substr(c.host.begin, c.host.len); | |
72 | |
73 // Get port (it's optional). | |
74 port_ = 80; // Default value. | |
75 if (c.port.len > 0) { | |
76 int i = atoi(url.substr(c.port.begin, c.port.len).c_str()); | |
77 if (i < 0 || i > 65535) | |
78 return false; | |
79 port_ = static_cast<uint16_t>(i); | |
80 } | |
81 | |
82 return true; | |
83 } | |
84 | |
85 void TestTCPSocketPrivate::RunTest() { | |
86 RUN_TEST_FORCEASYNC_AND_NOT(Basic); | |
87 RUN_TEST_FORCEASYNC_AND_NOT(ReadWrite); | |
88 RUN_TEST_FORCEASYNC_AND_NOT(ConnectAddress); | |
89 } | |
90 | |
91 std::string TestTCPSocketPrivate::TestBasic() { | |
92 TCPSocketPrivate socket(instance_); | |
93 TestCompletionCallback cb(instance_->pp_instance(), force_async_); | |
94 | |
95 int32_t rv = socket.Connect(host_.c_str(), port_, cb); | |
96 ASSERT_TRUE(!force_async_ || rv == PP_OK_COMPLETIONPENDING); | |
97 if (rv == PP_OK_COMPLETIONPENDING) | |
98 rv = cb.WaitForResult(); | |
99 ASSERT_EQ(PP_OK, rv); | |
100 | |
101 PP_NetAddress_Private unused; | |
102 // TODO(viettrungluu): check the values somehow. | |
103 ASSERT_TRUE(socket.GetLocalAddress(&unused)); | |
104 ASSERT_TRUE(socket.GetRemoteAddress(&unused)); | |
105 | |
106 socket.Disconnect(); | |
107 | |
108 PASS(); | |
109 } | |
110 | |
111 std::string TestTCPSocketPrivate::TestReadWrite() { | |
112 TCPSocketPrivate socket(instance_); | |
113 TestCompletionCallback cb(instance_->pp_instance(), force_async_); | |
114 | |
115 int32_t rv = socket.Connect(host_.c_str(), port_, cb); | |
116 ASSERT_TRUE(!force_async_ || rv == PP_OK_COMPLETIONPENDING); | |
117 if (rv == PP_OK_COMPLETIONPENDING) | |
118 rv = cb.WaitForResult(); | |
119 ASSERT_EQ(PP_OK, rv); | |
120 | |
121 ASSERT_EQ(PP_OK, WriteStringToSocket(&socket, "GET / HTTP/1.0\r\n\r\n")); | |
122 | |
123 // Read up to the first \n and check that it looks like valid HTTP response. | |
124 std::string s; | |
125 ASSERT_EQ(PP_OK, ReadFirstLineFromSocket(&socket, &s)); | |
126 ASSERT_TRUE(ValidateHttpResponse(s)); | |
127 | |
128 socket.Disconnect(); | |
129 | |
130 PASS(); | |
131 } | |
132 | |
133 std::string TestTCPSocketPrivate::TestConnectAddress() { | |
134 PP_NetAddress_Private address; | |
135 | |
136 // First, bring up a connection and grab the address. | |
137 { | |
138 TCPSocketPrivate socket(instance_); | |
139 TestCompletionCallback cb(instance_->pp_instance(), force_async_); | |
140 int32_t rv = socket.Connect(host_.c_str(), port_, cb); | |
141 ASSERT_TRUE(!force_async_ || rv == PP_OK_COMPLETIONPENDING); | |
142 if (rv == PP_OK_COMPLETIONPENDING) | |
143 rv = cb.WaitForResult(); | |
144 ASSERT_EQ(PP_OK, rv); | |
145 ASSERT_TRUE(socket.GetRemoteAddress(&address)); | |
146 // Omit the |Disconnect()| here to make sure we don't crash if we just let | |
147 // the resource be destroyed. | |
148 } | |
149 | |
150 // Connect to that address. | |
151 TCPSocketPrivate socket(instance_); | |
152 TestCompletionCallback cb(instance_->pp_instance(), force_async_); | |
153 int32_t rv = socket.ConnectWithNetAddress(&address, cb); | |
154 ASSERT_TRUE(!force_async_ || rv == PP_OK_COMPLETIONPENDING); | |
155 if (rv == PP_OK_COMPLETIONPENDING) | |
156 rv = cb.WaitForResult(); | |
157 ASSERT_EQ(PP_OK, rv); | |
158 | |
159 // Make sure we can read/write to it properly (see |TestReadWrite()|). | |
160 ASSERT_EQ(PP_OK, WriteStringToSocket(&socket, "GET / HTTP/1.0\r\n\r\n")); | |
161 std::string s; | |
162 ASSERT_EQ(PP_OK, ReadFirstLineFromSocket(&socket, &s)); | |
163 ASSERT_TRUE(ValidateHttpResponse(s)); | |
164 | |
165 socket.Disconnect(); | |
166 | |
167 PASS(); | |
168 } | |
169 | |
170 // TODO(viettrungluu): Try testing SSL somehow. | |
171 | |
172 int32_t TestTCPSocketPrivate::ReadFirstLineFromSocket(TCPSocketPrivate* socket, | |
173 std::string* s) { | |
174 char buffer[10000]; | |
175 | |
176 s->clear(); | |
177 // Make sure we don't just hang if |Read()| spews. | |
178 while (s->size() < 1000000) { | |
179 TestCompletionCallback cb(instance_->pp_instance(), force_async_); | |
180 int32_t rv = socket->Read(buffer, sizeof(buffer), cb); | |
181 if (force_async_ && rv != PP_OK_COMPLETIONPENDING) | |
182 return PP_ERROR_FAILED; | |
183 if (rv == PP_OK_COMPLETIONPENDING) | |
184 rv = cb.WaitForResult(); | |
185 if (rv < 0) | |
186 return rv; | |
187 if (rv == 0) | |
188 return PP_ERROR_FAILED; // Didn't get a \n-terminated line. | |
189 for (int32_t i = 0; i < rv; i++) { | |
190 s->push_back(buffer[i]); // Inefficiency FTW. | |
yzshen1
2011/11/15 00:47:07
Maybe this is better: find out whether there is '\
viettrungluu
2011/11/15 01:08:26
How about I just add a .reserve()?
yzshen1
2011/11/15 01:16:56
Okay.
| |
191 if (buffer[i] == '\n') | |
192 return PP_OK; | |
193 } | |
194 } | |
195 return PP_ERROR_FAILED; | |
196 } | |
197 | |
198 int32_t TestTCPSocketPrivate::WriteStringToSocket(TCPSocketPrivate* socket, | |
199 const std::string& s) { | |
200 const char* buffer = s.data(); | |
201 size_t written = 0; | |
202 while (written < s.size()) { | |
203 TestCompletionCallback cb(instance_->pp_instance(), force_async_); | |
204 int32_t rv = socket->Write(buffer + written, s.size() - written, cb); | |
205 if (force_async_ && rv != PP_OK_COMPLETIONPENDING) | |
206 return PP_ERROR_FAILED; | |
207 if (rv == PP_OK_COMPLETIONPENDING) | |
208 rv = cb.WaitForResult(); | |
209 if (rv < 0) | |
210 return rv; | |
211 if (rv == 0) | |
212 return PP_ERROR_FAILED; | |
213 written += rv; | |
214 } | |
215 if (written != s.size()) | |
216 return PP_ERROR_FAILED; | |
217 return PP_OK; | |
218 } | |
OLD | NEW |