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

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

Issue 2492703002: Third try at landing gRPC refactoring. Previous issue failed on the waterfall (Closed)
Patch Set: Change DCHECK Created 4 years, 1 month 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
« no previous file with comments | « components/cronet/ios/test/BUILD.gn ('k') | components/cronet/ios/test/cronet_http_test.mm » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(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 <Cronet/Cronet.h>
6
7 #include <stdint.h>
8 #include <list>
9 #include <map>
10 #include <string>
11 #include <Cronet/cronet_c_for_grpc.h>
12
13 #include "base/at_exit.h"
14 #include "base/logging.h"
15 #include "base/mac/scoped_nsobject.h"
16 #include "base/macros.h"
17 #include "base/memory/ptr_util.h"
18 #include "base/strings/string_util.h"
19 #include "base/strings/sys_string_conversions.h"
20 #include "base/synchronization/waitable_event.h"
21 #include "components/cronet/ios/test/quic_test_server.h"
22 #include "net/base/mac/url_conversions.h"
23 #include "net/base/net_errors.h"
24 #include "net/test/test_data_directory.h"
25 #include "testing/gtest/include/gtest/gtest.h"
26 #include "testing/gtest_mac.h"
27 #include "url/gurl.h"
28
29 namespace {
30
31 cronet_bidirectional_stream_header kTestHeaders[] = {
32 {"header1", "foo"},
33 {"header2", "bar"},
34 };
35 const cronet_bidirectional_stream_header_array kTestHeadersArray = {
36 2, 2, kTestHeaders};
37 } // namespace
38
39 namespace cronet {
40
41 base::AtExitManager* g_at_exit_ = nullptr;
42
43 void StartCronetIfNecessary() {
44 static bool initialized = false;
45 if (!initialized) {
46 initialized = true;
47 [Cronet setUserAgent:@"CronetTest/1.0.0.0" partial:NO];
48 [Cronet setHttp2Enabled:true];
49 [Cronet setQuicEnabled:true];
50 [Cronet setSslKeyLogFileName:@"SSLKEYLOGFILE"];
51
52 [Cronet addQuicHint:@"test.example.com"
53 port:cronet::kTestServerPort
54 altPort:cronet::kTestServerPort];
55 [Cronet enableTestCertVerifierForTesting];
56 [Cronet
57 setHostResolverRulesForTesting:@"MAP test.example.com 127.0.0.1,"
58 "MAP notfound.example.com ~NOTFOUND"];
59 [Cronet start];
60
61 // This method must be called once from the main thread.
62 if (!g_at_exit_)
63 g_at_exit_ = new base::AtExitManager;
64 }
65 }
66
67 class CronetBidirectionalStreamTest : public ::testing::TestWithParam<bool> {
68 protected:
69 CronetBidirectionalStreamTest() {}
70 ~CronetBidirectionalStreamTest() override {}
71
72 void SetUp() override {
73 StartCronetIfNecessary();
74 StartQuicTestServer();
75 [Cronet startNetLogToFile:@"cronet_netlog.json" logBytes:YES];
76 }
77
78 void TearDown() override {
79 ShutdownQuicTestServer();
80 [Cronet stopNetLog];
81 }
82
83 cronet_engine* engine() { return [Cronet getGlobalEngine]; }
84 };
85
86 class TestBidirectionalStreamCallback {
87 public:
88 enum ResponseStep {
89 NOTHING,
90 ON_STREAM_READY,
91 ON_RESPONSE_STARTED,
92 ON_READ_COMPLETED,
93 ON_WRITE_COMPLETED,
94 ON_TRAILERS,
95 ON_CANCELED,
96 ON_FAILED,
97 ON_SUCCEEDED
98 };
99
100 struct WriteData {
101 std::string buffer;
102 // If |flush| is true, then cronet_bidirectional_stream_flush() will be
103 // called after writing of the |buffer|.
104 bool flush;
105
106 WriteData(const std::string& buffer, bool flush);
107 ~WriteData();
108
109 DISALLOW_COPY_AND_ASSIGN(WriteData);
110 };
111
112 cronet_bidirectional_stream* stream;
113 base::WaitableEvent stream_done_event;
114
115 // Test parameters.
116 std::map<std::string, std::string> request_headers;
117 std::list<std::unique_ptr<WriteData>> write_data;
118 std::string expected_negotiated_protocol;
119 ResponseStep cancel_from_step;
120 size_t read_buffer_size;
121
122 // Test results.
123 ResponseStep response_step;
124 char* read_buffer;
125 std::map<std::string, std::string> response_headers;
126 std::map<std::string, std::string> response_trailers;
127 std::vector<std::string> read_data;
128 int net_error;
129
130 TestBidirectionalStreamCallback()
131 : stream(nullptr),
132 stream_done_event(base::WaitableEvent::ResetPolicy::MANUAL,
133 base::WaitableEvent::InitialState::NOT_SIGNALED),
134 expected_negotiated_protocol("quic/1+spdy/3"),
135 cancel_from_step(NOTHING),
136 read_buffer_size(32768),
137 response_step(NOTHING),
138 read_buffer(nullptr),
139 net_error(0) {}
140
141 ~TestBidirectionalStreamCallback() {
142 if (read_buffer)
143 delete read_buffer;
144 }
145
146 static TestBidirectionalStreamCallback* FromStream(
147 cronet_bidirectional_stream* stream) {
148 DCHECK(stream);
149 return (TestBidirectionalStreamCallback*)stream->annotation;
150 }
151
152 virtual bool MaybeCancel(cronet_bidirectional_stream* stream,
153 ResponseStep step) {
154 DCHECK_EQ(stream, this->stream);
155 response_step = step;
156 DLOG(WARNING) << "Step: " << step;
157
158 if (step != cancel_from_step)
159 return false;
160
161 cronet_bidirectional_stream_cancel(stream);
162 cronet_bidirectional_stream_write(stream, "abc", 3, false);
163
164 return true;
165 }
166
167 void SignalDone() { stream_done_event.Signal(); }
168
169 void BlockForDone() { stream_done_event.Wait(); }
170
171 void AddWriteData(const std::string& data) { AddWriteData(data, true); }
172 void AddWriteData(const std::string& data, bool flush) {
173 write_data.push_back(base::MakeUnique<WriteData>(data, flush));
174 }
175
176 virtual void MaybeWriteNextData(cronet_bidirectional_stream* stream) {
177 DCHECK_EQ(stream, this->stream);
178 if (write_data.empty())
179 return;
180 for (const auto& data : write_data) {
181 cronet_bidirectional_stream_write(stream, data->buffer.c_str(),
182 data->buffer.size(),
183 data == write_data.back());
184 if (data->flush) {
185 cronet_bidirectional_stream_flush(stream);
186 break;
187 }
188 }
189 }
190
191 cronet_bidirectional_stream_callback* callback() const { return &s_callback; }
192
193 private:
194 // C callbacks.
195 static void on_stream_ready_callback(cronet_bidirectional_stream* stream) {
196 TestBidirectionalStreamCallback* test = FromStream(stream);
197 if (test->MaybeCancel(stream, ON_STREAM_READY))
198 return;
199 test->MaybeWriteNextData(stream);
200 }
201
202 static void on_response_headers_received_callback(
203 cronet_bidirectional_stream* stream,
204 const cronet_bidirectional_stream_header_array* headers,
205 const char* negotiated_protocol) {
206 TestBidirectionalStreamCallback* test = FromStream(stream);
207 ASSERT_EQ(test->expected_negotiated_protocol,
208 std::string(negotiated_protocol));
209 for (size_t i = 0; i < headers->count; ++i) {
210 test->response_headers[headers->headers[i].key] =
211 headers->headers[i].value;
212 }
213 if (test->MaybeCancel(stream, ON_RESPONSE_STARTED))
214 return;
215 test->read_buffer = new char[test->read_buffer_size];
216 cronet_bidirectional_stream_read(stream, test->read_buffer,
217 test->read_buffer_size);
218 }
219
220 static void on_read_completed_callback(cronet_bidirectional_stream* stream,
221 char* data,
222 int count) {
223 TestBidirectionalStreamCallback* test = FromStream(stream);
224 test->read_data.push_back(std::string(data, count));
225 if (test->MaybeCancel(stream, ON_READ_COMPLETED))
226 return;
227 if (count == 0)
228 return;
229 cronet_bidirectional_stream_read(stream, test->read_buffer,
230 test->read_buffer_size);
231 }
232
233 static void on_write_completed_callback(cronet_bidirectional_stream* stream,
234 const char* data) {
235 TestBidirectionalStreamCallback* test = FromStream(stream);
236 ASSERT_EQ(test->write_data.front()->buffer.c_str(), data);
237 if (test->MaybeCancel(stream, ON_WRITE_COMPLETED))
238 return;
239 bool continue_writing = test->write_data.front()->flush;
240 test->write_data.pop_front();
241 if (continue_writing)
242 test->MaybeWriteNextData(stream);
243 }
244
245 static void on_response_trailers_received_callback(
246 cronet_bidirectional_stream* stream,
247 const cronet_bidirectional_stream_header_array* trailers) {
248 TestBidirectionalStreamCallback* test = FromStream(stream);
249 for (size_t i = 0; i < trailers->count; ++i) {
250 test->response_trailers[trailers->headers[i].key] =
251 trailers->headers[i].value;
252 }
253
254 if (test->MaybeCancel(stream, ON_TRAILERS))
255 return;
256 }
257
258 static void on_succeded_callback(cronet_bidirectional_stream* stream) {
259 TestBidirectionalStreamCallback* test = FromStream(stream);
260 ASSERT_TRUE(test->write_data.empty());
261 test->MaybeCancel(stream, ON_SUCCEEDED);
262 test->SignalDone();
263 }
264
265 static void on_failed_callback(cronet_bidirectional_stream* stream,
266 int net_error) {
267 TestBidirectionalStreamCallback* test = FromStream(stream);
268 test->net_error = net_error;
269 test->MaybeCancel(stream, ON_FAILED);
270 test->SignalDone();
271 }
272
273 static void on_canceled_callback(cronet_bidirectional_stream* stream) {
274 TestBidirectionalStreamCallback* test = FromStream(stream);
275 test->MaybeCancel(stream, ON_CANCELED);
276 test->SignalDone();
277 }
278
279 static cronet_bidirectional_stream_callback s_callback;
280 };
281
282 cronet_bidirectional_stream_callback
283 TestBidirectionalStreamCallback::s_callback = {
284 on_stream_ready_callback,
285 on_response_headers_received_callback,
286 on_read_completed_callback,
287 on_write_completed_callback,
288 on_response_trailers_received_callback,
289 on_succeded_callback,
290 on_failed_callback,
291 on_canceled_callback};
292
293 TestBidirectionalStreamCallback::WriteData::WriteData(const std::string& data,
294 bool flush_after)
295 : buffer(data), flush(flush_after) {}
296
297 TestBidirectionalStreamCallback::WriteData::~WriteData() {}
298
299 TEST_P(CronetBidirectionalStreamTest, StartExampleBidiStream) {
300 TestBidirectionalStreamCallback test;
301 test.AddWriteData("Hello, ");
302 test.AddWriteData("world!");
303 // Use small read buffer size to test that response is split properly.
304 test.read_buffer_size = 2;
305 test.stream =
306 cronet_bidirectional_stream_create(engine(), &test, test.callback());
307 DCHECK(test.stream);
308 cronet_bidirectional_stream_delay_request_headers_until_flush(test.stream,
309 GetParam());
310 cronet_bidirectional_stream_start(test.stream, kTestServerUrl, 0, "POST",
311 &kTestHeadersArray, false);
312 test.BlockForDone();
313 ASSERT_EQ(std::string(kHelloStatus), test.response_headers[kStatusHeader]);
314 ASSERT_EQ(std::string(kHelloHeaderValue),
315 test.response_headers[kHelloHeaderName]);
316 ASSERT_EQ(TestBidirectionalStreamCallback::ON_SUCCEEDED, test.response_step);
317 ASSERT_EQ(std::string(kHelloBodyValue, 2), test.read_data.front());
318 // Verify that individual read data joined using empty separator match
319 // expected body.
320 ASSERT_EQ(std::string(kHelloBodyValue), base::JoinString(test.read_data, ""));
321 ASSERT_EQ(std::string(kHelloTrailerValue),
322 test.response_trailers[kHelloTrailerName]);
323 cronet_bidirectional_stream_destroy(test.stream);
324 }
325
326 TEST_P(CronetBidirectionalStreamTest, SimplePutWithEmptyWriteDataAtTheEnd) {
327 TestBidirectionalStreamCallback test;
328 test.AddWriteData("Hello, ");
329 test.AddWriteData("world!");
330 test.AddWriteData("");
331 test.stream =
332 cronet_bidirectional_stream_create(engine(), &test, test.callback());
333 DCHECK(test.stream);
334 cronet_bidirectional_stream_delay_request_headers_until_flush(test.stream,
335 GetParam());
336 cronet_bidirectional_stream_start(test.stream, kTestServerUrl, 0, "PUT",
337 &kTestHeadersArray, false);
338 test.BlockForDone();
339 ASSERT_EQ(std::string(kHelloStatus), test.response_headers[kStatusHeader]);
340 ASSERT_EQ(std::string(kHelloHeaderValue),
341 test.response_headers[kHelloHeaderName]);
342 ASSERT_EQ(TestBidirectionalStreamCallback::ON_SUCCEEDED, test.response_step);
343 ASSERT_EQ(std::string(kHelloBodyValue), test.read_data.front());
344 ASSERT_EQ(std::string(kHelloTrailerValue),
345 test.response_trailers[kHelloTrailerName]);
346 cronet_bidirectional_stream_destroy(test.stream);
347 }
348
349 TEST_P(CronetBidirectionalStreamTest, SimpleGetWithFlush) {
350 TestBidirectionalStreamCallback test;
351 test.stream =
352 cronet_bidirectional_stream_create(engine(), &test, test.callback());
353 DCHECK(test.stream);
354 cronet_bidirectional_stream_disable_auto_flush(test.stream, true);
355 cronet_bidirectional_stream_delay_request_headers_until_flush(test.stream,
356 GetParam());
357 // Flush before start is ignored.
358 cronet_bidirectional_stream_flush(test.stream);
359 cronet_bidirectional_stream_start(test.stream, kTestServerUrl, 0, "GET",
360 &kTestHeadersArray, true);
361 test.BlockForDone();
362 ASSERT_EQ(std::string(kHelloStatus), test.response_headers[kStatusHeader]);
363 ASSERT_EQ(std::string(kHelloHeaderValue),
364 test.response_headers[kHelloHeaderName]);
365 ASSERT_EQ(TestBidirectionalStreamCallback::ON_SUCCEEDED, test.response_step);
366 ASSERT_EQ(std::string(kHelloBodyValue), base::JoinString(test.read_data, ""));
367 ASSERT_EQ(std::string(kHelloTrailerValue),
368 test.response_trailers[kHelloTrailerName]);
369 // Flush after done is ignored.
370 cronet_bidirectional_stream_flush(test.stream);
371 cronet_bidirectional_stream_destroy(test.stream);
372 }
373
374 TEST_P(CronetBidirectionalStreamTest, SimplePostWithFlush) {
375 TestBidirectionalStreamCallback test;
376 test.AddWriteData("Test String", false);
377 test.AddWriteData("1234567890", false);
378 test.AddWriteData("woot!", true);
379 test.stream =
380 cronet_bidirectional_stream_create(engine(), &test, test.callback());
381 DCHECK(test.stream);
382 cronet_bidirectional_stream_disable_auto_flush(test.stream, true);
383 cronet_bidirectional_stream_delay_request_headers_until_flush(test.stream,
384 GetParam());
385 // Flush before start is ignored.
386 cronet_bidirectional_stream_flush(test.stream);
387 cronet_bidirectional_stream_start(test.stream, kTestServerUrl, 0, "POST",
388 &kTestHeadersArray, false);
389 test.BlockForDone();
390 ASSERT_EQ(std::string(kHelloStatus), test.response_headers[kStatusHeader]);
391 ASSERT_EQ(std::string(kHelloHeaderValue),
392 test.response_headers[kHelloHeaderName]);
393 ASSERT_EQ(TestBidirectionalStreamCallback::ON_SUCCEEDED, test.response_step);
394 ASSERT_EQ(std::string(kHelloBodyValue), base::JoinString(test.read_data, ""));
395 ASSERT_EQ(std::string(kHelloTrailerValue),
396 test.response_trailers[kHelloTrailerName]);
397 // Flush after done is ignored.
398 cronet_bidirectional_stream_flush(test.stream);
399 cronet_bidirectional_stream_destroy(test.stream);
400 }
401
402 TEST_P(CronetBidirectionalStreamTest, SimplePostWithFlushTwice) {
403 TestBidirectionalStreamCallback test;
404 test.AddWriteData("Test String", false);
405 test.AddWriteData("1234567890", false);
406 test.AddWriteData("woot!", true);
407 test.AddWriteData("Test String", false);
408 test.AddWriteData("1234567890", false);
409 test.AddWriteData("woot!", true);
410 test.stream =
411 cronet_bidirectional_stream_create(engine(), &test, test.callback());
412 DCHECK(test.stream);
413 cronet_bidirectional_stream_disable_auto_flush(test.stream, true);
414 cronet_bidirectional_stream_delay_request_headers_until_flush(test.stream,
415 GetParam());
416 // Flush before start is ignored.
417 cronet_bidirectional_stream_flush(test.stream);
418 cronet_bidirectional_stream_start(test.stream, kTestServerUrl, 0, "POST",
419 &kTestHeadersArray, false);
420 test.BlockForDone();
421 ASSERT_EQ(std::string(kHelloStatus), test.response_headers[kStatusHeader]);
422 ASSERT_EQ(std::string(kHelloHeaderValue),
423 test.response_headers[kHelloHeaderName]);
424 ASSERT_EQ(TestBidirectionalStreamCallback::ON_SUCCEEDED, test.response_step);
425 ASSERT_EQ(std::string(kHelloBodyValue), base::JoinString(test.read_data, ""));
426 ASSERT_EQ(std::string(kHelloTrailerValue),
427 test.response_trailers[kHelloTrailerName]);
428 // Flush after done is ignored.
429 cronet_bidirectional_stream_flush(test.stream);
430 cronet_bidirectional_stream_destroy(test.stream);
431 }
432
433 TEST_P(CronetBidirectionalStreamTest, SimplePostWithFlushAfterOneWrite) {
434 TestBidirectionalStreamCallback test;
435 test.AddWriteData("Test String", false);
436 test.AddWriteData("1234567890", false);
437 test.AddWriteData("woot!", true);
438 test.stream =
439 cronet_bidirectional_stream_create(engine(), &test, test.callback());
440 DCHECK(test.stream);
441 cronet_bidirectional_stream_disable_auto_flush(test.stream, true);
442 cronet_bidirectional_stream_delay_request_headers_until_flush(test.stream,
443 GetParam());
444 // Flush before start is ignored.
445 cronet_bidirectional_stream_flush(test.stream);
446 cronet_bidirectional_stream_start(test.stream, kTestServerUrl, 0, "POST",
447 &kTestHeadersArray, false);
448 test.BlockForDone();
449 ASSERT_EQ(std::string(kHelloStatus), test.response_headers[kStatusHeader]);
450 ASSERT_EQ(std::string(kHelloHeaderValue),
451 test.response_headers[kHelloHeaderName]);
452 ASSERT_EQ(TestBidirectionalStreamCallback::ON_SUCCEEDED, test.response_step);
453 ASSERT_EQ(std::string(kHelloBodyValue), base::JoinString(test.read_data, ""));
454 ASSERT_EQ(std::string(kHelloTrailerValue),
455 test.response_trailers[kHelloTrailerName]);
456 // Flush after done is ignored.
457 cronet_bidirectional_stream_flush(test.stream);
458 cronet_bidirectional_stream_destroy(test.stream);
459 }
460
461 TEST_P(CronetBidirectionalStreamTest, TestDelayedFlush) {
462 class CustomTestBidirectionalStreamCallback
463 : public TestBidirectionalStreamCallback {
464 void MaybeWriteNextData(cronet_bidirectional_stream* stream) override {
465 DCHECK_EQ(stream, this->stream);
466 if (write_data.empty())
467 return;
468 // Write all buffers when stream is ready.
469 // Flush after "3" and "5".
470 // EndOfStream is set with "6" but not flushed, so it is not sent.
471 if (write_data.front()->buffer == "1") {
472 for (const auto& data : write_data) {
473 cronet_bidirectional_stream_write(stream, data->buffer.c_str(),
474 data->buffer.size(),
475 data == write_data.back());
476 if (data->flush) {
477 cronet_bidirectional_stream_flush(stream);
478 }
479 }
480 }
481 // Flush the final buffer with endOfStream flag.
482 if (write_data.front()->buffer == "6")
483 cronet_bidirectional_stream_flush(stream);
484 }
485 };
486
487 CustomTestBidirectionalStreamCallback test;
488 test.AddWriteData("1", false);
489 test.AddWriteData("2", false);
490 test.AddWriteData("3", true);
491 test.AddWriteData("4", false);
492 test.AddWriteData("5", true);
493 test.AddWriteData("6", false);
494 test.stream =
495 cronet_bidirectional_stream_create(engine(), &test, test.callback());
496 DCHECK(test.stream);
497 cronet_bidirectional_stream_disable_auto_flush(test.stream, true);
498 cronet_bidirectional_stream_delay_request_headers_until_flush(test.stream,
499 GetParam());
500 // Flush before start is ignored.
501 cronet_bidirectional_stream_flush(test.stream);
502 cronet_bidirectional_stream_start(test.stream, kTestServerUrl, 0, "POST",
503 &kTestHeadersArray, false);
504 test.BlockForDone();
505 // Flush after done is ignored.
506 cronet_bidirectional_stream_flush(test.stream);
507 cronet_bidirectional_stream_destroy(test.stream);
508 }
509
510 TEST_P(CronetBidirectionalStreamTest, CancelOnRead) {
511 TestBidirectionalStreamCallback test;
512 test.stream =
513 cronet_bidirectional_stream_create(engine(), &test, test.callback());
514 DCHECK(test.stream);
515 cronet_bidirectional_stream_delay_request_headers_until_flush(test.stream,
516 GetParam());
517 test.cancel_from_step = TestBidirectionalStreamCallback::ON_READ_COMPLETED;
518 cronet_bidirectional_stream_start(test.stream, kTestServerUrl, 0, "POST",
519 &kTestHeadersArray, true);
520 test.BlockForDone();
521 ASSERT_EQ(std::string(kHelloStatus), test.response_headers[kStatusHeader]);
522 ASSERT_EQ(std::string(kHelloBodyValue), test.read_data.front());
523 ASSERT_EQ(TestBidirectionalStreamCallback::ON_CANCELED, test.response_step);
524 cronet_bidirectional_stream_destroy(test.stream);
525 }
526
527 TEST_P(CronetBidirectionalStreamTest, CancelOnResponse) {
528 TestBidirectionalStreamCallback test;
529 test.stream =
530 cronet_bidirectional_stream_create(engine(), &test, test.callback());
531 DCHECK(test.stream);
532 cronet_bidirectional_stream_delay_request_headers_until_flush(test.stream,
533 GetParam());
534 test.cancel_from_step = TestBidirectionalStreamCallback::ON_RESPONSE_STARTED;
535 cronet_bidirectional_stream_start(test.stream, kTestServerUrl, 0, "POST",
536 &kTestHeadersArray, true);
537 test.BlockForDone();
538 ASSERT_EQ(std::string(kHelloStatus), test.response_headers[kStatusHeader]);
539 ASSERT_TRUE(test.read_data.empty());
540 ASSERT_EQ(TestBidirectionalStreamCallback::ON_CANCELED, test.response_step);
541 cronet_bidirectional_stream_destroy(test.stream);
542 }
543
544 TEST_P(CronetBidirectionalStreamTest, CancelOnSucceeded) {
545 TestBidirectionalStreamCallback test;
546 test.stream =
547 cronet_bidirectional_stream_create(engine(), &test, test.callback());
548 DCHECK(test.stream);
549 cronet_bidirectional_stream_delay_request_headers_until_flush(test.stream,
550 GetParam());
551 test.cancel_from_step = TestBidirectionalStreamCallback::ON_SUCCEEDED;
552 cronet_bidirectional_stream_start(test.stream, kTestServerUrl, 0, "POST",
553 &kTestHeadersArray, true);
554 test.BlockForDone();
555 ASSERT_EQ(std::string(kHelloStatus), test.response_headers[kStatusHeader]);
556 ASSERT_EQ(std::string(kHelloBodyValue), test.read_data.front());
557 ASSERT_EQ(TestBidirectionalStreamCallback::ON_SUCCEEDED, test.response_step);
558 cronet_bidirectional_stream_destroy(test.stream);
559 }
560
561 TEST_P(CronetBidirectionalStreamTest, ReadFailsBeforeRequestStarted) {
562 TestBidirectionalStreamCallback test;
563 test.stream =
564 cronet_bidirectional_stream_create(engine(), &test, test.callback());
565 DCHECK(test.stream);
566 cronet_bidirectional_stream_delay_request_headers_until_flush(test.stream,
567 GetParam());
568 char read_buffer[1];
569 cronet_bidirectional_stream_read(test.stream, read_buffer,
570 sizeof(read_buffer));
571 test.BlockForDone();
572 ASSERT_TRUE(test.read_data.empty());
573 ASSERT_EQ(TestBidirectionalStreamCallback::ON_FAILED, test.response_step);
574 ASSERT_EQ(net::ERR_UNEXPECTED, test.net_error);
575 cronet_bidirectional_stream_destroy(test.stream);
576 }
577
578 TEST_P(CronetBidirectionalStreamTest,
579 StreamFailBeforeReadIsExecutedOnNetworkThread) {
580 class CustomTestBidirectionalStreamCallback
581 : public TestBidirectionalStreamCallback {
582 bool MaybeCancel(cronet_bidirectional_stream* stream,
583 ResponseStep step) override {
584 if (step == ResponseStep::ON_READ_COMPLETED) {
585 // Shut down the server, and the stream should error out.
586 // The second call to ShutdownQuicTestServer is no-op.
587 ShutdownQuicTestServer();
588 }
589 return TestBidirectionalStreamCallback::MaybeCancel(stream, step);
590 }
591 };
592
593 CustomTestBidirectionalStreamCallback test;
594 test.AddWriteData("Hello, ");
595 test.AddWriteData("world!");
596 test.read_buffer_size = 2;
597 test.stream =
598 cronet_bidirectional_stream_create(engine(), &test, test.callback());
599 DCHECK(test.stream);
600 cronet_bidirectional_stream_delay_request_headers_until_flush(test.stream,
601 GetParam());
602 cronet_bidirectional_stream_start(test.stream, kTestServerUrl, 0, "POST",
603 &kTestHeadersArray, false);
604 test.BlockForDone();
605 ASSERT_EQ(TestBidirectionalStreamCallback::ON_FAILED, test.response_step);
606 ASSERT_EQ(net::ERR_QUIC_PROTOCOL_ERROR, test.net_error);
607 cronet_bidirectional_stream_destroy(test.stream);
608 }
609
610 TEST_P(CronetBidirectionalStreamTest, WriteFailsBeforeRequestStarted) {
611 TestBidirectionalStreamCallback test;
612 test.stream =
613 cronet_bidirectional_stream_create(engine(), &test, test.callback());
614 DCHECK(test.stream);
615 cronet_bidirectional_stream_delay_request_headers_until_flush(test.stream,
616 GetParam());
617 cronet_bidirectional_stream_write(test.stream, "1", 1, false);
618 test.BlockForDone();
619 ASSERT_TRUE(test.read_data.empty());
620 ASSERT_EQ(TestBidirectionalStreamCallback::ON_FAILED, test.response_step);
621 ASSERT_EQ(net::ERR_UNEXPECTED, test.net_error);
622 cronet_bidirectional_stream_destroy(test.stream);
623 }
624
625 TEST_P(CronetBidirectionalStreamTest, StreamFailAfterStreamReadyCallback) {
626 class CustomTestBidirectionalStreamCallback
627 : public TestBidirectionalStreamCallback {
628 bool MaybeCancel(cronet_bidirectional_stream* stream,
629 ResponseStep step) override {
630 if (step == ResponseStep::ON_STREAM_READY) {
631 // Shut down the server, and the stream should error out.
632 // The second call to ShutdownQuicTestServer is no-op.
633 ShutdownQuicTestServer();
634 }
635 return TestBidirectionalStreamCallback::MaybeCancel(stream, step);
636 }
637 };
638
639 CustomTestBidirectionalStreamCallback test;
640 test.AddWriteData("Test String");
641 test.stream =
642 cronet_bidirectional_stream_create(engine(), &test, test.callback());
643 DCHECK(test.stream);
644 cronet_bidirectional_stream_delay_request_headers_until_flush(test.stream,
645 GetParam());
646 cronet_bidirectional_stream_start(test.stream, kTestServerUrl, 0, "POST",
647 &kTestHeadersArray, false);
648 test.BlockForDone();
649 ASSERT_EQ(TestBidirectionalStreamCallback::ON_FAILED, test.response_step);
650 ASSERT_TRUE(test.net_error == net::ERR_QUIC_PROTOCOL_ERROR ||
651 test.net_error == net::ERR_QUIC_HANDSHAKE_FAILED);
652 cronet_bidirectional_stream_destroy(test.stream);
653 }
654
655 TEST_P(CronetBidirectionalStreamTest,
656 StreamFailBeforeWriteIsExecutedOnNetworkThread) {
657 class CustomTestBidirectionalStreamCallback
658 : public TestBidirectionalStreamCallback {
659 bool MaybeCancel(cronet_bidirectional_stream* stream,
660 ResponseStep step) override {
661 if (step == ResponseStep::ON_WRITE_COMPLETED) {
662 // Shut down the server, and the stream should error out.
663 // The second call to ShutdownQuicTestServer is no-op.
664 ShutdownQuicTestServer();
665 }
666 return TestBidirectionalStreamCallback::MaybeCancel(stream, step);
667 }
668 };
669
670 CustomTestBidirectionalStreamCallback test;
671 test.AddWriteData("Test String");
672 test.AddWriteData("1234567890");
673 test.AddWriteData("woot!");
674 test.stream =
675 cronet_bidirectional_stream_create(engine(), &test, test.callback());
676 DCHECK(test.stream);
677 cronet_bidirectional_stream_delay_request_headers_until_flush(test.stream,
678 GetParam());
679 cronet_bidirectional_stream_start(test.stream, kTestServerUrl, 0, "POST",
680 &kTestHeadersArray, false);
681 test.BlockForDone();
682 ASSERT_EQ(TestBidirectionalStreamCallback::ON_FAILED, test.response_step);
683 ASSERT_TRUE(test.net_error == net::ERR_QUIC_PROTOCOL_ERROR ||
684 test.net_error == net::ERR_QUIC_HANDSHAKE_FAILED);
685 cronet_bidirectional_stream_destroy(test.stream);
686 }
687
688 TEST_P(CronetBidirectionalStreamTest, FailedResolution) {
689 TestBidirectionalStreamCallback test;
690 test.stream =
691 cronet_bidirectional_stream_create(engine(), &test, test.callback());
692 DCHECK(test.stream);
693 cronet_bidirectional_stream_delay_request_headers_until_flush(test.stream,
694 GetParam());
695 test.cancel_from_step = TestBidirectionalStreamCallback::ON_FAILED;
696 cronet_bidirectional_stream_start(test.stream, "https://notfound.example.com",
697 0, "GET", &kTestHeadersArray, true);
698 test.BlockForDone();
699 ASSERT_TRUE(test.read_data.empty());
700 ASSERT_EQ(TestBidirectionalStreamCallback::ON_FAILED, test.response_step);
701 ASSERT_EQ(net::ERR_NAME_NOT_RESOLVED, test.net_error);
702 cronet_bidirectional_stream_destroy(test.stream);
703 }
704
705 INSTANTIATE_TEST_CASE_P(CronetBidirectionalStreamDelayRequestHeadersUntilFlush,
706 CronetBidirectionalStreamTest,
707 ::testing::Values(true, false));
708
709 } // namespace cronet
OLDNEW
« no previous file with comments | « components/cronet/ios/test/BUILD.gn ('k') | components/cronet/ios/test/cronet_http_test.mm » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698