Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(637)

Side by Side Diff: components/cronet/ios/test/cronet_bidirectional_stream_test.mm

Issue 2050483002: [Cronet] Coalesce small buffers into single QUIC packet in GRPC on iOS. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Address Helen's comments. Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #import <Foundation/Foundation.h> 5 #import <Foundation/Foundation.h>
6 #include <stdint.h> 6 #include <stdint.h>
7 #include <list> 7 #include <list>
8 #include <map> 8 #include <map>
9 #include <string> 9 #include <string>
10 10
11 #include "base/logging.h" 11 #include "base/logging.h"
12 #include "base/mac/scoped_nsobject.h" 12 #include "base/mac/scoped_nsobject.h"
13 #include "base/macros.h"
14 #include "base/memory/ptr_util.h"
13 #include "base/strings/string_util.h" 15 #include "base/strings/string_util.h"
14 #include "base/strings/sys_string_conversions.h" 16 #include "base/strings/sys_string_conversions.h"
15 #include "base/synchronization/waitable_event.h" 17 #include "base/synchronization/waitable_event.h"
16 #include "components/cronet/ios/cronet_c_for_grpc.h" 18 #include "components/cronet/ios/cronet_c_for_grpc.h"
17 #include "components/cronet/ios/cronet_environment.h" 19 #include "components/cronet/ios/cronet_environment.h"
18 #include "components/cronet/ios/test/quic_test_server.h" 20 #include "components/cronet/ios/test/quic_test_server.h"
19 #include "net/base/mac/url_conversions.h" 21 #include "net/base/mac/url_conversions.h"
20 #include "net/base/net_errors.h" 22 #include "net/base/net_errors.h"
21 #include "net/base/test_data_directory.h" 23 #include "net/base/test_data_directory.h"
22 #include "net/cert/mock_cert_verifier.h" 24 #include "net/cert/mock_cert_verifier.h"
23 #include "testing/gtest/include/gtest/gtest.h" 25 #include "testing/gtest/include/gtest/gtest.h"
24 #include "testing/gtest_mac.h" 26 #include "testing/gtest_mac.h"
25 #include "url/gurl.h" 27 #include "url/gurl.h"
26 28
27 namespace { 29 namespace {
28 30
29 cronet_bidirectional_stream_header kTestHeaders[] = { 31 cronet_bidirectional_stream_header kTestHeaders[] = {
30 {"header1", "foo"}, 32 {"header1", "foo"},
31 {"header2", "bar"}, 33 {"header2", "bar"},
32 }; 34 };
33 const cronet_bidirectional_stream_header_array kTestHeadersArray = { 35 const cronet_bidirectional_stream_header_array kTestHeadersArray = {
34 2, 2, kTestHeaders}; 36 2, 2, kTestHeaders};
35 } // namespace 37 } // namespace
36 38
37 namespace cronet { 39 namespace cronet {
38 40
39 class CronetBidirectionalStreamTest : public ::testing::Test { 41 class CronetBidirectionalStreamTest : public ::testing::TestWithParam<bool> {
40 protected: 42 protected:
41 CronetBidirectionalStreamTest() {} 43 CronetBidirectionalStreamTest() {}
42 ~CronetBidirectionalStreamTest() override {} 44 ~CronetBidirectionalStreamTest() override {}
43 45
44 void SetUp() override { 46 void SetUp() override {
45 static bool initialized = false; 47 static bool initialized = false;
46 if (!initialized) { 48 if (!initialized) {
47 initialized = true; 49 initialized = true;
48 // Hack to work around issues with SetUp being called multiple times 50 // Hack to work around issues with SetUp being called multiple times
49 // during the test, and QuicTestServer not shutting down / restarting 51 // during the test, and QuicTestServer not shutting down / restarting
50 // gracefully. 52 // gracefully.
51 CronetEnvironment::Initialize(); 53 CronetEnvironment::Initialize();
54 cronet_environment_ = new CronetEnvironment("CronetTest/1.0.0.0");
55 cronet_environment_->set_http2_enabled(true);
56 cronet_environment_->set_quic_enabled(true);
57 cronet_environment_->set_ssl_key_log_file_name("SSLKEYLOGFILE");
58
59 std::unique_ptr<net::MockCertVerifier> mock_cert_verifier(
60 new net::MockCertVerifier());
61 mock_cert_verifier->set_default_result(net::OK);
62
63 cronet_environment_->set_cert_verifier(std::move(mock_cert_verifier));
64 cronet_environment_->set_host_resolver_rules(
65 "MAP test.example.com 127.0.0.1,"
66 "MAP notfound.example.com ~NOTFOUND");
67 cronet_environment_->AddQuicHint(kTestServerDomain, kTestServerPort,
68 kTestServerPort);
69
70 cronet_environment_->Start();
71
72 cronet_engine_.obj = cronet_environment_;
52 } 73 }
53 74
54 StartQuicTestServer(); 75 StartQuicTestServer();
55
56 cronet_environment_ = new CronetEnvironment("CronetTest/1.0.0.0");
57 cronet_environment_->set_http2_enabled(true);
58 cronet_environment_->set_quic_enabled(true);
59 cronet_environment_->set_ssl_key_log_file_name("SSLKEYLOGFILE");
60
61 std::unique_ptr<net::MockCertVerifier> mock_cert_verifier(
62 new net::MockCertVerifier());
63 mock_cert_verifier->set_default_result(net::OK);
64
65 cronet_environment_->set_cert_verifier(std::move(mock_cert_verifier));
66 cronet_environment_->set_host_resolver_rules(
67 "MAP test.example.com 127.0.0.1,"
68 "MAP notfound.example.com ~NOTFOUND");
69 cronet_environment_->AddQuicHint(kTestServerDomain, kTestServerPort,
70 kTestServerPort);
71
72 cronet_environment_->Start();
73
74 cronet_engine_.obj = cronet_environment_;
75
76 cronet_environment_->StartNetLog("cronet_netlog.json", true); 76 cronet_environment_->StartNetLog("cronet_netlog.json", true);
77 } 77 }
78 78
79 void TearDown() override { 79 void TearDown() override {
80 ShutdownQuicTestServer(); 80 ShutdownQuicTestServer();
81 cronet_environment_->StopNetLog(); 81 cronet_environment_->StopNetLog();
82 //[CronetEngine stopNetLog];
83 //[CronetEngine uninstall];
84 } 82 }
85 83
86 cronet_engine* engine() { return &cronet_engine_; } 84 cronet_engine* engine() { return &cronet_engine_; }
87 85
88 private: 86 private:
89 static CronetEnvironment* cronet_environment_; 87 static CronetEnvironment* cronet_environment_;
90 static cronet_engine cronet_engine_; 88 static cronet_engine cronet_engine_;
91 }; 89 };
92 90
93 CronetEnvironment* CronetBidirectionalStreamTest::cronet_environment_; 91 CronetEnvironment* CronetBidirectionalStreamTest::cronet_environment_ = nullptr;
94 cronet_engine CronetBidirectionalStreamTest::cronet_engine_; 92 cronet_engine CronetBidirectionalStreamTest::cronet_engine_ = {0};
95 93
96 class TestBidirectionalStreamCallback { 94 class TestBidirectionalStreamCallback {
97 public: 95 public:
98 enum ResponseStep { 96 enum ResponseStep {
99 NOTHING, 97 NOTHING,
100 ON_STREAM_READY, 98 ON_STREAM_READY,
101 ON_RESPONSE_STARTED, 99 ON_RESPONSE_STARTED,
102 ON_READ_COMPLETED, 100 ON_READ_COMPLETED,
103 ON_WRITE_COMPLETED, 101 ON_WRITE_COMPLETED,
104 ON_TRAILERS, 102 ON_TRAILERS,
105 ON_CANCELED, 103 ON_CANCELED,
106 ON_FAILED, 104 ON_FAILED,
107 ON_SUCCEEDED 105 ON_SUCCEEDED
108 }; 106 };
109 107
108 struct WriteData {
109 std::string buffer;
110 // If |flush| is true, then cronet_bidirectional_stream_flush() will be
111 // called after writing of the |buffer|.
112 bool flush;
113
114 WriteData(const std::string& buffer, bool flush);
115 ~WriteData();
116
117 DISALLOW_COPY_AND_ASSIGN(WriteData);
118 };
119
110 cronet_bidirectional_stream* stream; 120 cronet_bidirectional_stream* stream;
111 base::WaitableEvent stream_done_event; 121 base::WaitableEvent stream_done_event;
112 122
113 // Test parameters. 123 // Test parameters.
114 std::map<std::string, std::string> request_headers; 124 std::map<std::string, std::string> request_headers;
115 std::list<std::string> write_data; 125 std::list<std::unique_ptr<WriteData>> write_data;
116 std::string expected_negotiated_protocol; 126 std::string expected_negotiated_protocol;
117 ResponseStep cancel_from_step; 127 ResponseStep cancel_from_step;
118 size_t read_buffer_size; 128 size_t read_buffer_size;
119 129
120 // Test results. 130 // Test results.
121 ResponseStep response_step; 131 ResponseStep response_step;
122 char* read_buffer; 132 char* read_buffer;
123 std::map<std::string, std::string> response_headers; 133 std::map<std::string, std::string> response_headers;
124 std::map<std::string, std::string> response_trailers; 134 std::map<std::string, std::string> response_trailers;
125 std::vector<std::string> read_data; 135 std::vector<std::string> read_data;
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
157 return false; 167 return false;
158 168
159 cronet_bidirectional_stream_cancel(stream); 169 cronet_bidirectional_stream_cancel(stream);
160 return true; 170 return true;
161 } 171 }
162 172
163 void SignalDone() { stream_done_event.Signal(); } 173 void SignalDone() { stream_done_event.Signal(); }
164 174
165 void BlockForDone() { stream_done_event.Wait(); } 175 void BlockForDone() { stream_done_event.Wait(); }
166 176
167 void AddWriteData(const std::string& data) { write_data.push_back(data); } 177 void AddWriteData(const std::string& data) { AddWriteData(data, true); }
178 void AddWriteData(const std::string& data, bool flush) {
179 write_data.push_back(base::WrapUnique(new WriteData(data, flush)));
180 }
168 181
169 virtual void MaybeWriteNextData(cronet_bidirectional_stream* stream) { 182 virtual void MaybeWriteNextData(cronet_bidirectional_stream* stream) {
170 DCHECK_EQ(stream, this->stream); 183 DCHECK_EQ(stream, this->stream);
171 if (write_data.empty()) 184 if (write_data.empty())
172 return; 185 return;
173 cronet_bidirectional_stream_write(stream, write_data.front().c_str(), 186 for (const auto& data : write_data) {
174 write_data.front().size(), 187 cronet_bidirectional_stream_write(stream, data->buffer.c_str(),
175 write_data.size() == 1); 188 data->buffer.size(),
189 data == write_data.back());
190 if (data->flush) {
191 cronet_bidirectional_stream_flush(stream);
192 break;
193 }
194 }
176 } 195 }
177 196
178 cronet_bidirectional_stream_callback* callback() const { return &s_callback; } 197 cronet_bidirectional_stream_callback* callback() const { return &s_callback; }
179 198
180 private: 199 private:
181 // C callbacks. 200 // C callbacks.
182 static void on_stream_ready_callback(cronet_bidirectional_stream* stream) { 201 static void on_stream_ready_callback(cronet_bidirectional_stream* stream) {
183 TestBidirectionalStreamCallback* test = FromStream(stream); 202 TestBidirectionalStreamCallback* test = FromStream(stream);
184 if (test->MaybeCancel(stream, ON_STREAM_READY)) 203 if (test->MaybeCancel(stream, ON_STREAM_READY))
185 return; 204 return;
(...skipping 27 matching lines...) Expand all
213 return; 232 return;
214 if (count == 0) 233 if (count == 0)
215 return; 234 return;
216 cronet_bidirectional_stream_read(stream, test->read_buffer, 235 cronet_bidirectional_stream_read(stream, test->read_buffer,
217 test->read_buffer_size); 236 test->read_buffer_size);
218 } 237 }
219 238
220 static void on_write_completed_callback(cronet_bidirectional_stream* stream, 239 static void on_write_completed_callback(cronet_bidirectional_stream* stream,
221 const char* data) { 240 const char* data) {
222 TestBidirectionalStreamCallback* test = FromStream(stream); 241 TestBidirectionalStreamCallback* test = FromStream(stream);
223 ASSERT_EQ(test->write_data.front().c_str(), data); 242 ASSERT_EQ(test->write_data.front()->buffer.c_str(), data);
224 if (test->MaybeCancel(stream, ON_WRITE_COMPLETED)) 243 if (test->MaybeCancel(stream, ON_WRITE_COMPLETED))
225 return; 244 return;
245 bool continue_writing = test->write_data.front()->flush;
226 test->write_data.pop_front(); 246 test->write_data.pop_front();
227 test->MaybeWriteNextData(stream); 247 if (continue_writing)
248 test->MaybeWriteNextData(stream);
228 } 249 }
229 250
230 static void on_response_trailers_received_callback( 251 static void on_response_trailers_received_callback(
231 cronet_bidirectional_stream* stream, 252 cronet_bidirectional_stream* stream,
232 const cronet_bidirectional_stream_header_array* trailers) { 253 const cronet_bidirectional_stream_header_array* trailers) {
233 TestBidirectionalStreamCallback* test = FromStream(stream); 254 TestBidirectionalStreamCallback* test = FromStream(stream);
234 for (size_t i = 0; i < trailers->count; ++i) { 255 for (size_t i = 0; i < trailers->count; ++i) {
235 test->response_trailers[trailers->headers[i].key] = 256 test->response_trailers[trailers->headers[i].key] =
236 trailers->headers[i].value; 257 trailers->headers[i].value;
237 } 258 }
238 259
239 if (test->MaybeCancel(stream, ON_TRAILERS)) 260 if (test->MaybeCancel(stream, ON_TRAILERS))
240 return; 261 return;
241 } 262 }
242 263
243 static void on_succeded_callback(cronet_bidirectional_stream* stream) { 264 static void on_succeded_callback(cronet_bidirectional_stream* stream) {
244 TestBidirectionalStreamCallback* test = FromStream(stream); 265 TestBidirectionalStreamCallback* test = FromStream(stream);
266 ASSERT_TRUE(test->write_data.empty());
245 test->MaybeCancel(stream, ON_SUCCEEDED); 267 test->MaybeCancel(stream, ON_SUCCEEDED);
246 test->SignalDone(); 268 test->SignalDone();
247 } 269 }
248 270
249 static void on_failed_callback(cronet_bidirectional_stream* stream, 271 static void on_failed_callback(cronet_bidirectional_stream* stream,
250 int net_error) { 272 int net_error) {
251 TestBidirectionalStreamCallback* test = FromStream(stream); 273 TestBidirectionalStreamCallback* test = FromStream(stream);
252 test->net_error = net_error; 274 test->net_error = net_error;
253 test->MaybeCancel(stream, ON_FAILED); 275 test->MaybeCancel(stream, ON_FAILED);
254 test->SignalDone(); 276 test->SignalDone();
(...skipping 12 matching lines...) Expand all
267 TestBidirectionalStreamCallback::s_callback = { 289 TestBidirectionalStreamCallback::s_callback = {
268 on_stream_ready_callback, 290 on_stream_ready_callback,
269 on_response_headers_received_callback, 291 on_response_headers_received_callback,
270 on_read_completed_callback, 292 on_read_completed_callback,
271 on_write_completed_callback, 293 on_write_completed_callback,
272 on_response_trailers_received_callback, 294 on_response_trailers_received_callback,
273 on_succeded_callback, 295 on_succeded_callback,
274 on_failed_callback, 296 on_failed_callback,
275 on_canceled_callback}; 297 on_canceled_callback};
276 298
277 TEST_F(CronetBidirectionalStreamTest, StartExampleBidiStream) { 299 TestBidirectionalStreamCallback::WriteData::WriteData(const std::string& data,
300 bool flush_after)
301 : buffer(data), flush(flush_after) {}
302
303 TestBidirectionalStreamCallback::WriteData::~WriteData() {}
304
305 TEST_P(CronetBidirectionalStreamTest, StartExampleBidiStream) {
278 TestBidirectionalStreamCallback test; 306 TestBidirectionalStreamCallback test;
279 test.AddWriteData("Hello, "); 307 test.AddWriteData("Hello, ");
280 test.AddWriteData("world!"); 308 test.AddWriteData("world!");
281 test.read_buffer_size = 2; 309 test.read_buffer_size = 2;
282 test.stream = 310 test.stream =
283 cronet_bidirectional_stream_create(engine(), &test, test.callback()); 311 cronet_bidirectional_stream_create(engine(), &test, test.callback());
284 DCHECK(test.stream); 312 DCHECK(test.stream);
313 cronet_bidirectional_stream_delay_request_headers_until_flush(test.stream,
314 GetParam());
285 cronet_bidirectional_stream_start(test.stream, kTestServerUrl, 0, "POST", 315 cronet_bidirectional_stream_start(test.stream, kTestServerUrl, 0, "POST",
286 &kTestHeadersArray, false); 316 &kTestHeadersArray, false);
287 test.BlockForDone(); 317 test.BlockForDone();
288 ASSERT_EQ(std::string(kHelloStatus), test.response_headers[kStatusHeader]); 318 ASSERT_EQ(std::string(kHelloStatus), test.response_headers[kStatusHeader]);
289 ASSERT_EQ(std::string(kHelloHeaderValue), 319 ASSERT_EQ(std::string(kHelloHeaderValue),
290 test.response_headers[kHelloHeaderName]); 320 test.response_headers[kHelloHeaderName]);
291 ASSERT_EQ(TestBidirectionalStreamCallback::ON_SUCCEEDED, test.response_step); 321 ASSERT_EQ(TestBidirectionalStreamCallback::ON_SUCCEEDED, test.response_step);
292 ASSERT_EQ(std::string(kHelloBodyValue, 2), test.read_data.front()); 322 ASSERT_EQ(std::string(kHelloBodyValue, 2), test.read_data.front());
293 ASSERT_EQ(std::string(kHelloBodyValue), base::JoinString(test.read_data, "")); 323 ASSERT_EQ(std::string(kHelloBodyValue), base::JoinString(test.read_data, ""));
294 ASSERT_EQ(std::string(kHelloTrailerValue), 324 ASSERT_EQ(std::string(kHelloTrailerValue),
295 test.response_trailers[kHelloTrailerName]); 325 test.response_trailers[kHelloTrailerName]);
296 cronet_bidirectional_stream_destroy(test.stream); 326 cronet_bidirectional_stream_destroy(test.stream);
297 } 327 }
298 328
299 TEST_F(CronetBidirectionalStreamTest, CancelOnRead) { 329 TEST_P(CronetBidirectionalStreamTest, SimpleGetWithFlush) {
300 TestBidirectionalStreamCallback test; 330 TestBidirectionalStreamCallback test;
301 test.stream = 331 test.stream =
302 cronet_bidirectional_stream_create(engine(), &test, test.callback()); 332 cronet_bidirectional_stream_create(engine(), &test, test.callback());
303 DCHECK(test.stream); 333 DCHECK(test.stream);
334 cronet_bidirectional_stream_disable_auto_flush(test.stream, true);
335 cronet_bidirectional_stream_delay_request_headers_until_flush(test.stream,
336 GetParam());
337 // Flush before start is ignored.
338 cronet_bidirectional_stream_flush(test.stream);
339 cronet_bidirectional_stream_start(test.stream, kTestServerUrl, 0, "GET",
340 &kTestHeadersArray, true);
341 test.BlockForDone();
342 ASSERT_EQ(std::string(kHelloStatus), test.response_headers[kStatusHeader]);
343 ASSERT_EQ(std::string(kHelloHeaderValue),
344 test.response_headers[kHelloHeaderName]);
345 ASSERT_EQ(TestBidirectionalStreamCallback::ON_SUCCEEDED, test.response_step);
346 ASSERT_EQ(std::string(kHelloBodyValue), base::JoinString(test.read_data, ""));
347 ASSERT_EQ(std::string(kHelloTrailerValue),
348 test.response_trailers[kHelloTrailerName]);
349 // Flush after done is ignored.
350 cronet_bidirectional_stream_flush(test.stream);
351 cronet_bidirectional_stream_destroy(test.stream);
352 }
353
354 TEST_P(CronetBidirectionalStreamTest, SimplePostWithFlush) {
355 TestBidirectionalStreamCallback test;
356 test.AddWriteData("Test String", false);
357 test.AddWriteData("1234567890", false);
358 test.AddWriteData("woot!", true);
359 test.stream =
360 cronet_bidirectional_stream_create(engine(), &test, test.callback());
361 DCHECK(test.stream);
362 cronet_bidirectional_stream_disable_auto_flush(test.stream, true);
363 cronet_bidirectional_stream_delay_request_headers_until_flush(test.stream,
364 GetParam());
365 // Flush before start is ignored.
366 cronet_bidirectional_stream_flush(test.stream);
367 cronet_bidirectional_stream_start(test.stream, kTestServerUrl, 0, "POST",
368 &kTestHeadersArray, false);
369 test.BlockForDone();
370 ASSERT_EQ(std::string(kHelloStatus), test.response_headers[kStatusHeader]);
371 ASSERT_EQ(std::string(kHelloHeaderValue),
372 test.response_headers[kHelloHeaderName]);
373 ASSERT_EQ(TestBidirectionalStreamCallback::ON_SUCCEEDED, test.response_step);
374 ASSERT_EQ(std::string(kHelloBodyValue), base::JoinString(test.read_data, ""));
375 ASSERT_EQ(std::string(kHelloTrailerValue),
376 test.response_trailers[kHelloTrailerName]);
377 // Flush after done is ignored.
378 cronet_bidirectional_stream_flush(test.stream);
379 cronet_bidirectional_stream_destroy(test.stream);
380 }
381
382 TEST_P(CronetBidirectionalStreamTest, SimplePostWithFlushTwice) {
383 TestBidirectionalStreamCallback test;
384 test.AddWriteData("Test String", false);
385 test.AddWriteData("1234567890", false);
386 test.AddWriteData("woot!", true);
387 test.AddWriteData("Test String", false);
388 test.AddWriteData("1234567890", false);
389 test.AddWriteData("woot!", true);
390 test.stream =
391 cronet_bidirectional_stream_create(engine(), &test, test.callback());
392 DCHECK(test.stream);
393 cronet_bidirectional_stream_disable_auto_flush(test.stream, true);
394 cronet_bidirectional_stream_delay_request_headers_until_flush(test.stream,
395 GetParam());
396 // Flush before start is ignored.
397 cronet_bidirectional_stream_flush(test.stream);
398 cronet_bidirectional_stream_start(test.stream, kTestServerUrl, 0, "POST",
399 &kTestHeadersArray, false);
400 test.BlockForDone();
401 ASSERT_EQ(std::string(kHelloStatus), test.response_headers[kStatusHeader]);
402 ASSERT_EQ(std::string(kHelloHeaderValue),
403 test.response_headers[kHelloHeaderName]);
404 ASSERT_EQ(TestBidirectionalStreamCallback::ON_SUCCEEDED, test.response_step);
405 ASSERT_EQ(std::string(kHelloBodyValue), base::JoinString(test.read_data, ""));
406 ASSERT_EQ(std::string(kHelloTrailerValue),
407 test.response_trailers[kHelloTrailerName]);
408 // Flush after done is ignored.
409 cronet_bidirectional_stream_flush(test.stream);
410 cronet_bidirectional_stream_destroy(test.stream);
411 }
412
413 TEST_P(CronetBidirectionalStreamTest, SimplePostWithFlushAfterOneWrite) {
414 TestBidirectionalStreamCallback test;
415 test.AddWriteData("Test String", false);
416 test.AddWriteData("1234567890", false);
417 test.AddWriteData("woot!", true);
418 test.stream =
419 cronet_bidirectional_stream_create(engine(), &test, test.callback());
420 DCHECK(test.stream);
421 cronet_bidirectional_stream_disable_auto_flush(test.stream, true);
422 cronet_bidirectional_stream_delay_request_headers_until_flush(test.stream,
423 GetParam());
424 // Flush before start is ignored.
425 cronet_bidirectional_stream_flush(test.stream);
426 cronet_bidirectional_stream_start(test.stream, kTestServerUrl, 0, "POST",
427 &kTestHeadersArray, false);
428 test.BlockForDone();
429 ASSERT_EQ(std::string(kHelloStatus), test.response_headers[kStatusHeader]);
430 ASSERT_EQ(std::string(kHelloHeaderValue),
431 test.response_headers[kHelloHeaderName]);
432 ASSERT_EQ(TestBidirectionalStreamCallback::ON_SUCCEEDED, test.response_step);
433 ASSERT_EQ(std::string(kHelloBodyValue), base::JoinString(test.read_data, ""));
434 ASSERT_EQ(std::string(kHelloTrailerValue),
435 test.response_trailers[kHelloTrailerName]);
436 // Flush after done is ignored.
437 cronet_bidirectional_stream_flush(test.stream);
438 cronet_bidirectional_stream_destroy(test.stream);
439 }
440
441 TEST_P(CronetBidirectionalStreamTest, CancelOnRead) {
442 TestBidirectionalStreamCallback test;
443 test.stream =
444 cronet_bidirectional_stream_create(engine(), &test, test.callback());
445 DCHECK(test.stream);
446 cronet_bidirectional_stream_delay_request_headers_until_flush(test.stream,
447 GetParam());
304 test.cancel_from_step = TestBidirectionalStreamCallback::ON_READ_COMPLETED; 448 test.cancel_from_step = TestBidirectionalStreamCallback::ON_READ_COMPLETED;
305 cronet_bidirectional_stream_start(test.stream, kTestServerUrl, 0, "POST", 449 cronet_bidirectional_stream_start(test.stream, kTestServerUrl, 0, "POST",
306 &kTestHeadersArray, true); 450 &kTestHeadersArray, true);
307 test.BlockForDone(); 451 test.BlockForDone();
308 ASSERT_EQ(std::string(kHelloStatus), test.response_headers[kStatusHeader]); 452 ASSERT_EQ(std::string(kHelloStatus), test.response_headers[kStatusHeader]);
309 ASSERT_EQ(std::string(kHelloBodyValue), test.read_data.front()); 453 ASSERT_EQ(std::string(kHelloBodyValue), test.read_data.front());
310 ASSERT_EQ(TestBidirectionalStreamCallback::ON_CANCELED, test.response_step); 454 ASSERT_EQ(TestBidirectionalStreamCallback::ON_CANCELED, test.response_step);
311 cronet_bidirectional_stream_destroy(test.stream); 455 cronet_bidirectional_stream_destroy(test.stream);
312 } 456 }
313 457
314 TEST_F(CronetBidirectionalStreamTest, CancelOnResponse) { 458 TEST_P(CronetBidirectionalStreamTest, CancelOnResponse) {
315 TestBidirectionalStreamCallback test; 459 TestBidirectionalStreamCallback test;
316 test.stream = 460 test.stream =
317 cronet_bidirectional_stream_create(engine(), &test, test.callback()); 461 cronet_bidirectional_stream_create(engine(), &test, test.callback());
318 DCHECK(test.stream); 462 DCHECK(test.stream);
463 cronet_bidirectional_stream_delay_request_headers_until_flush(test.stream,
464 GetParam());
319 test.cancel_from_step = TestBidirectionalStreamCallback::ON_RESPONSE_STARTED; 465 test.cancel_from_step = TestBidirectionalStreamCallback::ON_RESPONSE_STARTED;
320 cronet_bidirectional_stream_start(test.stream, kTestServerUrl, 0, "POST", 466 cronet_bidirectional_stream_start(test.stream, kTestServerUrl, 0, "POST",
321 &kTestHeadersArray, true); 467 &kTestHeadersArray, true);
322 test.BlockForDone(); 468 test.BlockForDone();
323 ASSERT_EQ(std::string(kHelloStatus), test.response_headers[kStatusHeader]); 469 ASSERT_EQ(std::string(kHelloStatus), test.response_headers[kStatusHeader]);
324 ASSERT_TRUE(test.read_data.empty()); 470 ASSERT_TRUE(test.read_data.empty());
325 ASSERT_EQ(TestBidirectionalStreamCallback::ON_CANCELED, test.response_step); 471 ASSERT_EQ(TestBidirectionalStreamCallback::ON_CANCELED, test.response_step);
326 cronet_bidirectional_stream_destroy(test.stream); 472 cronet_bidirectional_stream_destroy(test.stream);
327 } 473 }
328 474
329 TEST_F(CronetBidirectionalStreamTest, CancelOnSucceeded) { 475 TEST_P(CronetBidirectionalStreamTest, CancelOnSucceeded) {
330 TestBidirectionalStreamCallback test; 476 TestBidirectionalStreamCallback test;
331 test.stream = 477 test.stream =
332 cronet_bidirectional_stream_create(engine(), &test, test.callback()); 478 cronet_bidirectional_stream_create(engine(), &test, test.callback());
333 DCHECK(test.stream); 479 DCHECK(test.stream);
480 cronet_bidirectional_stream_delay_request_headers_until_flush(test.stream,
481 GetParam());
334 test.cancel_from_step = TestBidirectionalStreamCallback::ON_SUCCEEDED; 482 test.cancel_from_step = TestBidirectionalStreamCallback::ON_SUCCEEDED;
335 cronet_bidirectional_stream_start(test.stream, kTestServerUrl, 0, "POST", 483 cronet_bidirectional_stream_start(test.stream, kTestServerUrl, 0, "POST",
336 &kTestHeadersArray, true); 484 &kTestHeadersArray, true);
337 test.BlockForDone(); 485 test.BlockForDone();
338 ASSERT_EQ(std::string(kHelloStatus), test.response_headers[kStatusHeader]); 486 ASSERT_EQ(std::string(kHelloStatus), test.response_headers[kStatusHeader]);
339 ASSERT_EQ(std::string(kHelloBodyValue), test.read_data.front()); 487 ASSERT_EQ(std::string(kHelloBodyValue), test.read_data.front());
340 ASSERT_EQ(TestBidirectionalStreamCallback::ON_SUCCEEDED, test.response_step); 488 ASSERT_EQ(TestBidirectionalStreamCallback::ON_SUCCEEDED, test.response_step);
341 cronet_bidirectional_stream_destroy(test.stream); 489 cronet_bidirectional_stream_destroy(test.stream);
342 } 490 }
343 491
344 TEST_F(CronetBidirectionalStreamTest, ReadFailsBeforeRequestStarted) { 492 TEST_P(CronetBidirectionalStreamTest, ReadFailsBeforeRequestStarted) {
345 TestBidirectionalStreamCallback test; 493 TestBidirectionalStreamCallback test;
346 test.stream = 494 test.stream =
347 cronet_bidirectional_stream_create(engine(), &test, test.callback()); 495 cronet_bidirectional_stream_create(engine(), &test, test.callback());
348 DCHECK(test.stream); 496 DCHECK(test.stream);
497 cronet_bidirectional_stream_delay_request_headers_until_flush(test.stream,
498 GetParam());
349 char read_buffer[1]; 499 char read_buffer[1];
350 cronet_bidirectional_stream_read(test.stream, read_buffer, 500 cronet_bidirectional_stream_read(test.stream, read_buffer,
351 sizeof(read_buffer)); 501 sizeof(read_buffer));
352 test.BlockForDone(); 502 test.BlockForDone();
353 ASSERT_TRUE(test.read_data.empty()); 503 ASSERT_TRUE(test.read_data.empty());
354 ASSERT_EQ(TestBidirectionalStreamCallback::ON_FAILED, test.response_step); 504 ASSERT_EQ(TestBidirectionalStreamCallback::ON_FAILED, test.response_step);
355 ASSERT_EQ(net::ERR_UNEXPECTED, test.net_error); 505 ASSERT_EQ(net::ERR_UNEXPECTED, test.net_error);
356 cronet_bidirectional_stream_destroy(test.stream); 506 cronet_bidirectional_stream_destroy(test.stream);
357 } 507 }
358 508
359 TEST_F(CronetBidirectionalStreamTest, 509 TEST_P(CronetBidirectionalStreamTest,
360 StreamFailBeforeReadIsExecutedOnNetworkThread) { 510 StreamFailBeforeReadIsExecutedOnNetworkThread) {
361 class CustomTestBidirectionalStreamCallback 511 class CustomTestBidirectionalStreamCallback
362 : public TestBidirectionalStreamCallback { 512 : public TestBidirectionalStreamCallback {
363 bool MaybeCancel(cronet_bidirectional_stream* stream, 513 bool MaybeCancel(cronet_bidirectional_stream* stream,
364 ResponseStep step) override { 514 ResponseStep step) override {
365 if (step == ResponseStep::ON_READ_COMPLETED) { 515 if (step == ResponseStep::ON_READ_COMPLETED) {
366 // Shut down the server, and the stream should error out. 516 // Shut down the server, and the stream should error out.
367 // The second call to ShutdownQuicTestServer is no-op. 517 // The second call to ShutdownQuicTestServer is no-op.
368 ShutdownQuicTestServer(); 518 ShutdownQuicTestServer();
369 } 519 }
370 return TestBidirectionalStreamCallback::MaybeCancel(stream, step); 520 return TestBidirectionalStreamCallback::MaybeCancel(stream, step);
371 } 521 }
372 }; 522 };
373 523
374 CustomTestBidirectionalStreamCallback test; 524 CustomTestBidirectionalStreamCallback test;
375 test.AddWriteData("Hello, "); 525 test.AddWriteData("Hello, ");
376 test.AddWriteData("world!"); 526 test.AddWriteData("world!");
377 test.read_buffer_size = 2; 527 test.read_buffer_size = 2;
378 test.stream = 528 test.stream =
379 cronet_bidirectional_stream_create(engine(), &test, test.callback()); 529 cronet_bidirectional_stream_create(engine(), &test, test.callback());
380 DCHECK(test.stream); 530 DCHECK(test.stream);
531 cronet_bidirectional_stream_delay_request_headers_until_flush(test.stream,
532 GetParam());
381 cronet_bidirectional_stream_start(test.stream, kTestServerUrl, 0, "POST", 533 cronet_bidirectional_stream_start(test.stream, kTestServerUrl, 0, "POST",
382 &kTestHeadersArray, false); 534 &kTestHeadersArray, false);
383 test.BlockForDone(); 535 test.BlockForDone();
384 ASSERT_EQ(TestBidirectionalStreamCallback::ON_FAILED, test.response_step); 536 ASSERT_EQ(TestBidirectionalStreamCallback::ON_FAILED, test.response_step);
385 ASSERT_EQ(net::ERR_QUIC_PROTOCOL_ERROR, test.net_error); 537 ASSERT_EQ(net::ERR_QUIC_PROTOCOL_ERROR, test.net_error);
386 cronet_bidirectional_stream_destroy(test.stream); 538 cronet_bidirectional_stream_destroy(test.stream);
387 } 539 }
388 540
389 TEST_F(CronetBidirectionalStreamTest, WriteFailsBeforeRequestStarted) { 541 TEST_P(CronetBidirectionalStreamTest, WriteFailsBeforeRequestStarted) {
390 TestBidirectionalStreamCallback test; 542 TestBidirectionalStreamCallback test;
391 test.stream = 543 test.stream =
392 cronet_bidirectional_stream_create(engine(), &test, test.callback()); 544 cronet_bidirectional_stream_create(engine(), &test, test.callback());
393 DCHECK(test.stream); 545 DCHECK(test.stream);
546 cronet_bidirectional_stream_delay_request_headers_until_flush(test.stream,
547 GetParam());
394 cronet_bidirectional_stream_write(test.stream, "1", 1, false); 548 cronet_bidirectional_stream_write(test.stream, "1", 1, false);
395 test.BlockForDone(); 549 test.BlockForDone();
396 ASSERT_TRUE(test.read_data.empty()); 550 ASSERT_TRUE(test.read_data.empty());
397 ASSERT_EQ(TestBidirectionalStreamCallback::ON_FAILED, test.response_step); 551 ASSERT_EQ(TestBidirectionalStreamCallback::ON_FAILED, test.response_step);
398 ASSERT_EQ(net::ERR_UNEXPECTED, test.net_error); 552 ASSERT_EQ(net::ERR_UNEXPECTED, test.net_error);
399 cronet_bidirectional_stream_destroy(test.stream); 553 cronet_bidirectional_stream_destroy(test.stream);
400 } 554 }
401 555
402 TEST_F(CronetBidirectionalStreamTest, 556 TEST_P(CronetBidirectionalStreamTest,
403 StreamFailBeforeWriteIsExecutedOnNetworkThread) { 557 StreamFailBeforeWriteIsExecutedOnNetworkThread) {
404 class CustomTestBidirectionalStreamCallback 558 class CustomTestBidirectionalStreamCallback
405 : public TestBidirectionalStreamCallback { 559 : public TestBidirectionalStreamCallback {
406 bool MaybeCancel(cronet_bidirectional_stream* stream, 560 bool MaybeCancel(cronet_bidirectional_stream* stream,
407 ResponseStep step) override { 561 ResponseStep step) override {
408 if (step == ResponseStep::ON_WRITE_COMPLETED) { 562 if (step == ResponseStep::ON_WRITE_COMPLETED) {
409 // Shut down the server, and the stream should error out. 563 // Shut down the server, and the stream should error out.
410 // The second call to ShutdownQuicTestServer is no-op. 564 // The second call to ShutdownQuicTestServer is no-op.
411 ShutdownQuicTestServer(); 565 ShutdownQuicTestServer();
412 } 566 }
413 return TestBidirectionalStreamCallback::MaybeCancel(stream, step); 567 return TestBidirectionalStreamCallback::MaybeCancel(stream, step);
414 } 568 }
415 }; 569 };
416 570
417 CustomTestBidirectionalStreamCallback test; 571 CustomTestBidirectionalStreamCallback test;
418 test.AddWriteData("Test String"); 572 test.AddWriteData("Test String");
419 test.AddWriteData("1234567890"); 573 test.AddWriteData("1234567890");
420 test.AddWriteData("woot!"); 574 test.AddWriteData("woot!");
421 test.stream = 575 test.stream =
422 cronet_bidirectional_stream_create(engine(), &test, test.callback()); 576 cronet_bidirectional_stream_create(engine(), &test, test.callback());
423 DCHECK(test.stream); 577 DCHECK(test.stream);
578 cronet_bidirectional_stream_delay_request_headers_until_flush(test.stream,
579 GetParam());
424 cronet_bidirectional_stream_start(test.stream, kTestServerUrl, 0, "POST", 580 cronet_bidirectional_stream_start(test.stream, kTestServerUrl, 0, "POST",
425 &kTestHeadersArray, false); 581 &kTestHeadersArray, false);
426 test.BlockForDone(); 582 test.BlockForDone();
427 ASSERT_EQ(TestBidirectionalStreamCallback::ON_FAILED, test.response_step); 583 ASSERT_EQ(TestBidirectionalStreamCallback::ON_FAILED, test.response_step);
428 ASSERT_EQ(net::ERR_QUIC_PROTOCOL_ERROR, test.net_error); 584 ASSERT_TRUE(test.net_error == net::ERR_QUIC_PROTOCOL_ERROR ||
585 test.net_error == net::ERR_QUIC_HANDSHAKE_FAILED);
429 cronet_bidirectional_stream_destroy(test.stream); 586 cronet_bidirectional_stream_destroy(test.stream);
430 } 587 }
431 588
432 TEST_F(CronetBidirectionalStreamTest, FailedResolution) { 589 TEST_P(CronetBidirectionalStreamTest, FailedResolution) {
433 TestBidirectionalStreamCallback test; 590 TestBidirectionalStreamCallback test;
434 test.stream = 591 test.stream =
435 cronet_bidirectional_stream_create(engine(), &test, test.callback()); 592 cronet_bidirectional_stream_create(engine(), &test, test.callback());
436 DCHECK(test.stream); 593 DCHECK(test.stream);
594 cronet_bidirectional_stream_delay_request_headers_until_flush(test.stream,
595 GetParam());
437 test.cancel_from_step = TestBidirectionalStreamCallback::ON_FAILED; 596 test.cancel_from_step = TestBidirectionalStreamCallback::ON_FAILED;
438 cronet_bidirectional_stream_start(test.stream, "https://notfound.example.com", 597 cronet_bidirectional_stream_start(test.stream, "https://notfound.example.com",
439 0, "GET", &kTestHeadersArray, true); 598 0, "GET", &kTestHeadersArray, true);
440 test.BlockForDone(); 599 test.BlockForDone();
441 ASSERT_TRUE(test.read_data.empty()); 600 ASSERT_TRUE(test.read_data.empty());
442 ASSERT_EQ(TestBidirectionalStreamCallback::ON_FAILED, test.response_step); 601 ASSERT_EQ(TestBidirectionalStreamCallback::ON_FAILED, test.response_step);
443 ASSERT_EQ(net::ERR_NAME_NOT_RESOLVED, test.net_error); 602 ASSERT_EQ(net::ERR_NAME_NOT_RESOLVED, test.net_error);
444 cronet_bidirectional_stream_destroy(test.stream); 603 cronet_bidirectional_stream_destroy(test.stream);
445 } 604 }
446 605
606 INSTANTIATE_TEST_CASE_P(CronetBidirectionalStreamDelayRequestHeadersUntilFlush,
607 CronetBidirectionalStreamTest,
608 ::testing::Values(true, false));
609
447 } // namespace cronet 610 } // namespace cronet
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698