Chromium Code Reviews| 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 |