Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2016 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 #import <Foundation/Foundation.h> | |
| 6 #include <stdint.h> | |
| 7 | |
| 8 #include "base/logging.h" | |
| 9 #include "base/mac/scoped_nsobject.h" | |
| 10 #include "base/strings/string_util.h" | |
| 11 #include "base/strings/sys_string_conversions.h" | |
| 12 #include "base/synchronization/waitable_event.h" | |
| 13 #include "components/cronet/ios/cronet_c_for_grpc.h" | |
| 14 #include "components/cronet/ios/cronet_environment.h" | |
| 15 #include "components/cronet/ios/test/quic_test_server.h" | |
| 16 #include "net/base/mac/url_conversions.h" | |
| 17 #include "net/base/test_data_directory.h" | |
| 18 #include "net/cert/mock_cert_verifier.h" | |
| 19 #include "testing/gtest/include/gtest/gtest.h" | |
| 20 #include "testing/gtest_mac.h" | |
| 21 #include "url/gurl.h" | |
| 22 | |
| 23 class CronetBidirectionalStreamTest : public ::testing::Test { | |
| 24 protected: | |
| 25 CronetBidirectionalStreamTest() {} | |
| 26 ~CronetBidirectionalStreamTest() override {} | |
| 27 | |
| 28 void SetUp() override { | |
| 29 static bool initialized = false; | |
| 30 if (!initialized) { | |
| 31 initialized = true; | |
| 32 cronet::CronetEnvironment::Initialize(); | |
| 33 cronet::StartQuicTestServer(); | |
| 34 } | |
| 35 | |
| 36 cronet_environment_ = new cronet::CronetEnvironment("CronetTest/1.0.0.0"); | |
| 37 cronet_environment_->set_http2_enabled(true); | |
| 38 cronet_environment_->set_quic_enabled(true); | |
| 39 cronet_environment_->set_ssl_key_log_file_name("SSLKEYLOGFILE"); | |
| 40 | |
| 41 scoped_ptr<net::MockCertVerifier> mock_cert_verifier( | |
| 42 new net::MockCertVerifier()); | |
| 43 mock_cert_verifier->set_default_result(net::OK); | |
| 44 | |
| 45 // cronet_environment_->set_cert_verifier(std::move(mock_cert_verifier)); | |
| 46 cronet_environment_->set_host_resolver_rules( | |
| 47 "MAP test.example.com 127.0.0.1"); | |
| 48 cronet_environment_->AddQuicHint("test.example.com", 6121, 6121); | |
| 49 | |
| 50 cronet_environment_->Install(); | |
| 51 | |
| 52 cronet_engine_.obj = cronet_environment_; | |
| 53 | |
| 54 // logging::SetMinLogLevel(-5); | |
| 55 cronet_environment_->StartNetLog("cronet_netlog.json", true); | |
| 56 //[CronetEngine startNetLogToFile:@"cronet_test_netlog.json" logBytes:YES]; | |
| 57 } | |
| 58 | |
| 59 void TearDown() override { | |
| 60 // cronet::ShutdownQuicTestServer(); | |
| 61 cronet_environment_->StopNetLog(); | |
| 62 //[CronetEngine stopNetLog]; | |
| 63 //[CronetEngine uninstall]; | |
| 64 } | |
| 65 | |
| 66 cronet_engine* engine() { return &cronet_engine_; } | |
| 67 | |
| 68 private: | |
| 69 static cronet::CronetEnvironment* cronet_environment_; | |
| 70 static cronet_engine cronet_engine_; | |
| 71 }; | |
| 72 | |
| 73 cronet::CronetEnvironment* CronetBidirectionalStreamTest::cronet_environment_; | |
| 74 cronet_engine CronetBidirectionalStreamTest::cronet_engine_; | |
| 75 | |
| 76 class TestBidirectionalStreamCallback { | |
| 77 public: | |
| 78 enum ResponseStep { | |
| 79 NOTHING, | |
| 80 ON_REQUEST_HEADERS_SENT, | |
| 81 ON_RESPONSE_STARTED, | |
| 82 ON_READ_COMPLETED, | |
| 83 ON_WRITE_COMPLETED, | |
| 84 ON_TRAILERS, | |
| 85 ON_CANCELED, | |
| 86 ON_FAILED, | |
| 87 ON_SUCCEEDED | |
| 88 }; | |
| 89 | |
| 90 cronet_bidirectional_stream* stream; | |
| 91 base::WaitableEvent stream_done_event; | |
| 92 | |
| 93 // Test parameters. | |
| 94 std::map<std::string, std::string> request_headers; | |
|
xunjieli
2016/04/08 14:43:16
#include <string> <map> <list>?
mef
2016/04/08 16:43:03
Done.
| |
| 95 std::list<std::string> write_data; | |
| 96 std::string expected_negotiated_protocol; | |
| 97 ResponseStep cancel_from_step; | |
| 98 size_t read_buffer_size; | |
| 99 | |
| 100 // Test results. | |
| 101 ResponseStep response_step; | |
| 102 char* read_buffer; | |
| 103 std::map<std::string, std::string> response_headers; | |
| 104 std::map<std::string, std::string> response_trailers; | |
| 105 std::vector<std::string> read_data; | |
| 106 | |
| 107 TestBidirectionalStreamCallback() | |
| 108 : stream(nullptr), | |
| 109 stream_done_event(true, false), | |
| 110 expected_negotiated_protocol("quic/1+spdy/3"), | |
| 111 cancel_from_step(NOTHING), | |
| 112 read_buffer_size(32768), | |
| 113 response_step(NOTHING), | |
| 114 read_buffer(nullptr) {} | |
| 115 | |
| 116 ~TestBidirectionalStreamCallback() { | |
| 117 if (read_buffer) | |
| 118 delete read_buffer; | |
| 119 } | |
| 120 | |
| 121 static TestBidirectionalStreamCallback* FromStream( | |
| 122 cronet_bidirectional_stream* stream) { | |
| 123 DCHECK(stream); | |
| 124 return (TestBidirectionalStreamCallback*)stream->annotation; | |
| 125 } | |
| 126 | |
| 127 bool MaybeCancel(cronet_bidirectional_stream* stream, ResponseStep step) { | |
| 128 DCHECK(stream == this->stream); | |
| 129 response_step = step; | |
| 130 DLOG(WARNING) << "Step: " << step; | |
| 131 | |
| 132 if (step != cancel_from_step) | |
| 133 return false; | |
| 134 | |
| 135 cronet_bidirectional_stream_cancel(stream); | |
| 136 return true; | |
| 137 } | |
| 138 | |
| 139 void SignalDone() { stream_done_event.Signal(); } | |
| 140 | |
| 141 void BlockForDone() { stream_done_event.Wait(); } | |
| 142 | |
| 143 void AddWriteData(const std::string& data) { write_data.push_back(data); } | |
| 144 | |
| 145 void MaybeWriteNextData(cronet_bidirectional_stream* stream) { | |
| 146 DCHECK(stream == this->stream); | |
|
xunjieli
2016/04/08 14:43:16
DCHECK_EQ
mef
2016/04/08 16:43:03
Done.
| |
| 147 if (write_data.empty()) | |
| 148 return; | |
| 149 cronet_bidirectional_stream_write(stream, write_data.front().c_str(), | |
| 150 write_data.front().size(), | |
| 151 write_data.size() == 1); | |
| 152 } | |
| 153 | |
| 154 cronet_bidirectional_stream_callback* callback() const { return &s_callback; } | |
| 155 | |
| 156 private: | |
| 157 // C callbacks. | |
| 158 static void on_request_headers_sent_callback( | |
| 159 cronet_bidirectional_stream* stream) { | |
| 160 TestBidirectionalStreamCallback* test = FromStream(stream); | |
| 161 if (test->MaybeCancel(stream, ON_REQUEST_HEADERS_SENT)) | |
| 162 return; | |
| 163 test->MaybeWriteNextData(stream); | |
| 164 } | |
| 165 | |
| 166 static void on_response_headers_received_callback( | |
| 167 cronet_bidirectional_stream* stream, | |
| 168 const cronet_bidirectional_stream_header_array* headers, | |
| 169 const char* negotiated_protocol) { | |
| 170 TestBidirectionalStreamCallback* test = FromStream(stream); | |
| 171 ASSERT_EQ(test->expected_negotiated_protocol, | |
| 172 std::string(negotiated_protocol)); | |
| 173 for (size_t i = 0; i < headers->count; ++i) { | |
| 174 test->response_headers[headers->headers[i].key] = | |
| 175 headers->headers[i].value; | |
| 176 } | |
| 177 if (test->MaybeCancel(stream, ON_RESPONSE_STARTED)) | |
| 178 return; | |
| 179 test->read_buffer = new char[test->read_buffer_size]; | |
| 180 cronet_bidirectional_stream_read(stream, test->read_buffer, | |
| 181 test->read_buffer_size); | |
| 182 } | |
| 183 | |
| 184 static void on_read_completed_callback(cronet_bidirectional_stream* stream, | |
| 185 char* data, | |
| 186 int count) { | |
| 187 TestBidirectionalStreamCallback* test = FromStream(stream); | |
| 188 test->read_data.push_back(std::string(data, count)); | |
| 189 if (test->MaybeCancel(stream, ON_READ_COMPLETED)) | |
| 190 return; | |
| 191 if (count == 0) | |
| 192 return; | |
| 193 cronet_bidirectional_stream_read(stream, test->read_buffer, | |
| 194 test->read_buffer_size); | |
| 195 } | |
| 196 | |
| 197 static void on_write_completed_callback(cronet_bidirectional_stream* stream, | |
| 198 const char* data) { | |
| 199 TestBidirectionalStreamCallback* test = FromStream(stream); | |
| 200 ASSERT_EQ(test->write_data.front().c_str(), data); | |
| 201 if (test->MaybeCancel(stream, ON_WRITE_COMPLETED)) | |
| 202 return; | |
| 203 test->write_data.pop_front(); | |
| 204 test->MaybeWriteNextData(stream); | |
| 205 } | |
| 206 | |
| 207 static void on_response_trailers_received_callback( | |
| 208 cronet_bidirectional_stream* stream, | |
| 209 const cronet_bidirectional_stream_header_array* trailers) { | |
| 210 TestBidirectionalStreamCallback* test = FromStream(stream); | |
| 211 if (test->MaybeCancel(stream, ON_TRAILERS)) | |
| 212 return; | |
| 213 } | |
| 214 | |
| 215 static void on_succeded_callback(cronet_bidirectional_stream* stream) { | |
| 216 TestBidirectionalStreamCallback* test = FromStream(stream); | |
| 217 test->MaybeCancel(stream, ON_SUCCEEDED); | |
| 218 test->SignalDone(); | |
| 219 } | |
| 220 | |
| 221 static void on_failed_callback(cronet_bidirectional_stream* stream, | |
| 222 int net_error) { | |
| 223 TestBidirectionalStreamCallback* test = FromStream(stream); | |
| 224 test->MaybeCancel(stream, ON_FAILED); | |
| 225 test->SignalDone(); | |
| 226 } | |
| 227 | |
| 228 static void on_canceled_callback(cronet_bidirectional_stream* stream) { | |
| 229 TestBidirectionalStreamCallback* test = FromStream(stream); | |
| 230 test->MaybeCancel(stream, ON_CANCELED); | |
| 231 test->SignalDone(); | |
| 232 } | |
| 233 | |
| 234 static cronet_bidirectional_stream_callback s_callback; | |
| 235 }; | |
| 236 | |
| 237 cronet_bidirectional_stream_callback | |
| 238 TestBidirectionalStreamCallback::s_callback = { | |
| 239 on_request_headers_sent_callback, | |
| 240 on_response_headers_received_callback, | |
| 241 on_read_completed_callback, | |
| 242 on_write_completed_callback, | |
| 243 on_response_trailers_received_callback, | |
| 244 on_succeded_callback, | |
| 245 on_failed_callback, | |
| 246 on_canceled_callback}; | |
| 247 | |
| 248 TEST_F(CronetBidirectionalStreamTest, StartExampleBidiStream) { | |
| 249 TestBidirectionalStreamCallback test; | |
| 250 test.AddWriteData("Hello, "); | |
| 251 test.AddWriteData("world!"); | |
| 252 test.read_buffer_size = 2; | |
| 253 test.stream = | |
| 254 cronet_bidirectional_stream_create(engine(), &test, test.callback()); | |
| 255 DCHECK(test.stream); | |
| 256 cronet_bidirectional_stream_header headers[] = { | |
| 257 {"header1", "foo"}, {"header2", "bar"}, | |
| 258 }; | |
| 259 cronet_bidirectional_stream_header_array headers_array = {2, 2, headers}; | |
| 260 cronet_bidirectional_stream_start(test.stream, | |
| 261 "https://test.example.com:6121", 0, "POST", | |
| 262 &headers_array, false); | |
| 263 test.BlockForDone(); | |
| 264 ASSERT_EQ(std::string("404"), test.response_headers[":status"]); | |
| 265 ASSERT_EQ(TestBidirectionalStreamCallback::ON_SUCCEEDED, test.response_step); | |
| 266 ASSERT_EQ(std::string("fi"), test.read_data.front()); | |
| 267 ASSERT_EQ(std::string("file not found"), | |
| 268 base::JoinString(test.read_data, "")); | |
| 269 cronet_bidirectional_stream_destroy(test.stream); | |
| 270 } | |
| 271 | |
| 272 TEST_F(CronetBidirectionalStreamTest, CancelOnRead) { | |
| 273 TestBidirectionalStreamCallback test; | |
| 274 test.stream = | |
| 275 cronet_bidirectional_stream_create(engine(), &test, test.callback()); | |
| 276 DCHECK(test.stream); | |
| 277 test.cancel_from_step = TestBidirectionalStreamCallback::ON_READ_COMPLETED; | |
| 278 cronet_bidirectional_stream_header headers[] = { | |
| 279 {"header1", "foo"}, {"header2", "bar"}, | |
| 280 }; | |
| 281 cronet_bidirectional_stream_header_array headers_array = {2, 2, headers}; | |
| 282 cronet_bidirectional_stream_start(test.stream, | |
| 283 "https://test.example.com:6121", 0, "POST", | |
| 284 &headers_array, true); | |
| 285 test.BlockForDone(); | |
| 286 ASSERT_EQ(std::string("404"), test.response_headers[":status"]); | |
| 287 ASSERT_EQ(std::string("file not found"), test.read_data.front()); | |
| 288 ASSERT_EQ(TestBidirectionalStreamCallback::ON_CANCELED, test.response_step); | |
| 289 cronet_bidirectional_stream_destroy(test.stream); | |
| 290 } | |
| 291 | |
| 292 TEST_F(CronetBidirectionalStreamTest, CancelOnResponse) { | |
| 293 TestBidirectionalStreamCallback test; | |
| 294 test.stream = | |
| 295 cronet_bidirectional_stream_create(engine(), &test, test.callback()); | |
| 296 DCHECK(test.stream); | |
| 297 test.cancel_from_step = TestBidirectionalStreamCallback::ON_RESPONSE_STARTED; | |
| 298 cronet_bidirectional_stream_header headers[] = { | |
| 299 {"header1", "foo"}, {"header2", "bar"}, | |
| 300 }; | |
| 301 cronet_bidirectional_stream_header_array headers_array = {2, 2, headers}; | |
| 302 cronet_bidirectional_stream_start(test.stream, | |
| 303 "https://test.example.com:6121", 0, "POST", | |
| 304 &headers_array, true); | |
| 305 test.BlockForDone(); | |
| 306 ASSERT_EQ(std::string("404"), test.response_headers[":status"]); | |
| 307 ASSERT_TRUE(test.read_data.empty()); | |
| 308 ASSERT_EQ(TestBidirectionalStreamCallback::ON_CANCELED, test.response_step); | |
| 309 cronet_bidirectional_stream_destroy(test.stream); | |
| 310 } | |
| 311 | |
| 312 TEST_F(CronetBidirectionalStreamTest, GoogleIt) { | |
| 313 TestBidirectionalStreamCallback test; | |
| 314 test.stream = | |
| 315 cronet_bidirectional_stream_create(engine(), &test, test.callback()); | |
| 316 DCHECK(test.stream); | |
| 317 test.cancel_from_step = TestBidirectionalStreamCallback::ON_READ_COMPLETED; | |
| 318 test.expected_negotiated_protocol = "h2"; | |
| 319 cronet_bidirectional_stream_header headers[] = { | |
| 320 {"header1", "foo"}, {"header2", "bar"}, | |
| 321 }; | |
| 322 cronet_bidirectional_stream_header_array headers_array = {2, 2, headers}; | |
| 323 cronet_bidirectional_stream_start(test.stream, "https://www.google.com", 0, | |
| 324 "GET", &headers_array, true); | |
| 325 test.BlockForDone(); | |
| 326 ASSERT_EQ(std::string("200"), test.response_headers[":status"]); | |
| 327 ASSERT_EQ(TestBidirectionalStreamCallback::ON_CANCELED, test.response_step); | |
| 328 cronet_bidirectional_stream_destroy(test.stream); | |
| 329 } | |
| OLD | NEW |