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

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

Issue 1858483002: Cronet for iOS with C API for GRPC support. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@small
Patch Set: Address comments, bundle libboringssl.a into libcronet.a Created 4 years, 8 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
(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 #include <list>
8 #include <map>
9 #include <string>
10
11 #include "base/logging.h"
12 #include "base/mac/scoped_nsobject.h"
13 #include "base/strings/string_util.h"
14 #include "base/strings/sys_string_conversions.h"
15 #include "base/synchronization/waitable_event.h"
16 #include "components/cronet/ios/cronet_c_for_grpc.h"
17 #include "components/cronet/ios/cronet_environment.h"
18 #include "components/cronet/ios/test/quic_test_server.h"
19 #include "net/base/mac/url_conversions.h"
20 #include "net/base/net_errors.h"
21 #include "net/base/test_data_directory.h"
22 #include "net/cert/mock_cert_verifier.h"
23 #include "testing/gtest/include/gtest/gtest.h"
24 #include "testing/gtest_mac.h"
25 #include "url/gurl.h"
26
27 namespace {
28 const char kTestServerHost[] = "test.example.com";
29 const int kTestServerPort = 6121;
30 const char kTestServerUrl[] = "https://test.example.com:6121";
31
32 cronet_bidirectional_stream_header kTestHeaders[] = {
33 {"header1", "foo"},
34 {"header2", "bar"},
35 };
36 const cronet_bidirectional_stream_header_array kTestHeadersArray = {
37 2, 2, kTestHeaders};
38 } // namespace
39
40 class CronetBidirectionalStreamTest : public ::testing::Test {
41 protected:
42 CronetBidirectionalStreamTest() {}
43 ~CronetBidirectionalStreamTest() override {}
44
45 void SetUp() override {
46 static bool initialized = false;
47 if (!initialized) {
48 initialized = true;
49 // Hack to work around issues with SetUp being called multiple times
50 // during the test, and QuicTestServer not shutting down / restarting
51 // gracefully.
52 cronet::CronetEnvironment::Initialize();
53 cronet::StartQuicTestServer();
54 }
55
56 cronet_environment_ = new cronet::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 scoped_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(kTestServerHost, kTestServerPort,
70 kTestServerPort);
71
72 cronet_environment_->Start();
73
74 cronet_engine_.obj = cronet_environment_;
75
76 cronet_environment_->StartNetLog("cronet_netlog.json", true);
77 }
78
79 void TearDown() override {
80 // cronet::ShutdownQuicTestServer();
81 cronet_environment_->StopNetLog();
82 //[CronetEngine stopNetLog];
83 //[CronetEngine uninstall];
84 }
85
86 cronet_engine* engine() { return &cronet_engine_; }
87
88 private:
89 static cronet::CronetEnvironment* cronet_environment_;
90 static cronet_engine cronet_engine_;
91 };
92
93 cronet::CronetEnvironment* CronetBidirectionalStreamTest::cronet_environment_;
94 cronet_engine CronetBidirectionalStreamTest::cronet_engine_;
95
96 class TestBidirectionalStreamCallback {
97 public:
98 enum ResponseStep {
99 NOTHING,
100 ON_REQUEST_HEADERS_SENT,
101 ON_RESPONSE_STARTED,
102 ON_READ_COMPLETED,
103 ON_WRITE_COMPLETED,
104 ON_TRAILERS,
105 ON_CANCELED,
106 ON_FAILED,
107 ON_SUCCEEDED
108 };
109
110 cronet_bidirectional_stream* stream;
111 base::WaitableEvent stream_done_event;
112
113 // Test parameters.
114 std::map<std::string, std::string> request_headers;
115 std::list<std::string> write_data;
116 std::string expected_negotiated_protocol;
117 ResponseStep cancel_from_step;
118 size_t read_buffer_size;
119
120 // Test results.
121 ResponseStep response_step;
122 char* read_buffer;
123 std::map<std::string, std::string> response_headers;
124 std::map<std::string, std::string> response_trailers;
125 std::vector<std::string> read_data;
126 int net_error;
127
128 TestBidirectionalStreamCallback()
129 : stream(nullptr),
130 stream_done_event(true, false),
131 expected_negotiated_protocol("quic/1+spdy/3"),
132 cancel_from_step(NOTHING),
133 read_buffer_size(32768),
134 response_step(NOTHING),
135 read_buffer(nullptr),
136 net_error(0) {}
137
138 ~TestBidirectionalStreamCallback() {
139 if (read_buffer)
140 delete read_buffer;
141 }
142
143 static TestBidirectionalStreamCallback* FromStream(
144 cronet_bidirectional_stream* stream) {
145 DCHECK(stream);
146 return (TestBidirectionalStreamCallback*)stream->annotation;
147 }
148
149 bool MaybeCancel(cronet_bidirectional_stream* stream, ResponseStep step) {
150 DCHECK_EQ(stream, this->stream);
151 response_step = step;
152 DLOG(WARNING) << "Step: " << step;
153
154 if (step != cancel_from_step)
155 return false;
156
157 cronet_bidirectional_stream_cancel(stream);
158 return true;
159 }
160
161 void SignalDone() { stream_done_event.Signal(); }
162
163 void BlockForDone() { stream_done_event.Wait(); }
164
165 void AddWriteData(const std::string& data) { write_data.push_back(data); }
166
167 void MaybeWriteNextData(cronet_bidirectional_stream* stream) {
168 DCHECK_EQ(stream, this->stream);
169 if (write_data.empty())
170 return;
171 cronet_bidirectional_stream_write(stream, write_data.front().c_str(),
172 write_data.front().size(),
173 write_data.size() == 1);
174 }
175
176 cronet_bidirectional_stream_callback* callback() const { return &s_callback; }
177
178 private:
179 // C callbacks.
180 static void on_request_headers_sent_callback(
181 cronet_bidirectional_stream* stream) {
182 TestBidirectionalStreamCallback* test = FromStream(stream);
183 if (test->MaybeCancel(stream, ON_REQUEST_HEADERS_SENT))
184 return;
185 test->MaybeWriteNextData(stream);
186 }
187
188 static void on_response_headers_received_callback(
189 cronet_bidirectional_stream* stream,
190 const cronet_bidirectional_stream_header_array* headers,
191 const char* negotiated_protocol) {
192 TestBidirectionalStreamCallback* test = FromStream(stream);
193 ASSERT_EQ(test->expected_negotiated_protocol,
194 std::string(negotiated_protocol));
195 for (size_t i = 0; i < headers->count; ++i) {
196 test->response_headers[headers->headers[i].key] =
197 headers->headers[i].value;
198 }
199 if (test->MaybeCancel(stream, ON_RESPONSE_STARTED))
200 return;
201 test->read_buffer = new char[test->read_buffer_size];
202 cronet_bidirectional_stream_read(stream, test->read_buffer,
203 test->read_buffer_size);
204 }
205
206 static void on_read_completed_callback(cronet_bidirectional_stream* stream,
207 char* data,
208 int count) {
209 TestBidirectionalStreamCallback* test = FromStream(stream);
210 test->read_data.push_back(std::string(data, count));
211 if (test->MaybeCancel(stream, ON_READ_COMPLETED))
212 return;
213 if (count == 0)
214 return;
215 cronet_bidirectional_stream_read(stream, test->read_buffer,
216 test->read_buffer_size);
217 }
218
219 static void on_write_completed_callback(cronet_bidirectional_stream* stream,
220 const char* data) {
221 TestBidirectionalStreamCallback* test = FromStream(stream);
222 ASSERT_EQ(test->write_data.front().c_str(), data);
223 if (test->MaybeCancel(stream, ON_WRITE_COMPLETED))
224 return;
225 test->write_data.pop_front();
226 test->MaybeWriteNextData(stream);
227 }
228
229 static void on_response_trailers_received_callback(
230 cronet_bidirectional_stream* stream,
231 const cronet_bidirectional_stream_header_array* trailers) {
232 TestBidirectionalStreamCallback* test = FromStream(stream);
233 if (test->MaybeCancel(stream, ON_TRAILERS))
234 return;
235 }
236
237 static void on_succeded_callback(cronet_bidirectional_stream* stream) {
238 TestBidirectionalStreamCallback* test = FromStream(stream);
239 test->MaybeCancel(stream, ON_SUCCEEDED);
240 test->SignalDone();
241 }
242
243 static void on_failed_callback(cronet_bidirectional_stream* stream,
244 int net_error) {
245 TestBidirectionalStreamCallback* test = FromStream(stream);
246 test->net_error = net_error;
247 test->MaybeCancel(stream, ON_FAILED);
248 test->SignalDone();
249 }
250
251 static void on_canceled_callback(cronet_bidirectional_stream* stream) {
252 TestBidirectionalStreamCallback* test = FromStream(stream);
253 test->MaybeCancel(stream, ON_CANCELED);
254 test->SignalDone();
255 }
256
257 static cronet_bidirectional_stream_callback s_callback;
258 };
259
260 cronet_bidirectional_stream_callback
261 TestBidirectionalStreamCallback::s_callback = {
262 on_request_headers_sent_callback,
263 on_response_headers_received_callback,
264 on_read_completed_callback,
265 on_write_completed_callback,
266 on_response_trailers_received_callback,
267 on_succeded_callback,
268 on_failed_callback,
269 on_canceled_callback};
270
271 TEST_F(CronetBidirectionalStreamTest, StartExampleBidiStream) {
272 TestBidirectionalStreamCallback test;
273 test.AddWriteData("Hello, ");
274 test.AddWriteData("world!");
275 test.read_buffer_size = 2;
276 test.stream =
277 cronet_bidirectional_stream_create(engine(), &test, test.callback());
278 DCHECK(test.stream);
279 cronet_bidirectional_stream_start(test.stream, kTestServerUrl, 0, "POST",
280 &kTestHeadersArray, false);
281 test.BlockForDone();
282 ASSERT_EQ(std::string("404"), test.response_headers[":status"]);
283 ASSERT_EQ(TestBidirectionalStreamCallback::ON_SUCCEEDED, test.response_step);
284 ASSERT_EQ(std::string("fi"), test.read_data.front());
285 ASSERT_EQ(std::string("file not found"),
286 base::JoinString(test.read_data, ""));
287 cronet_bidirectional_stream_destroy(test.stream);
288 }
289
290 TEST_F(CronetBidirectionalStreamTest, CancelOnRead) {
291 TestBidirectionalStreamCallback test;
292 test.stream =
293 cronet_bidirectional_stream_create(engine(), &test, test.callback());
294 DCHECK(test.stream);
295 test.cancel_from_step = TestBidirectionalStreamCallback::ON_READ_COMPLETED;
296 cronet_bidirectional_stream_start(test.stream, kTestServerUrl, 0, "POST",
297 &kTestHeadersArray, true);
298 test.BlockForDone();
299 ASSERT_EQ(std::string("404"), test.response_headers[":status"]);
300 ASSERT_EQ(std::string("file not found"), test.read_data.front());
301 ASSERT_EQ(TestBidirectionalStreamCallback::ON_CANCELED, test.response_step);
302 cronet_bidirectional_stream_destroy(test.stream);
303 }
304
305 TEST_F(CronetBidirectionalStreamTest, CancelOnResponse) {
306 TestBidirectionalStreamCallback test;
307 test.stream =
308 cronet_bidirectional_stream_create(engine(), &test, test.callback());
309 DCHECK(test.stream);
310 test.cancel_from_step = TestBidirectionalStreamCallback::ON_RESPONSE_STARTED;
311 cronet_bidirectional_stream_start(test.stream, kTestServerUrl, 0, "POST",
312 &kTestHeadersArray, true);
313 test.BlockForDone();
314 ASSERT_EQ(std::string("404"), test.response_headers[":status"]);
315 ASSERT_TRUE(test.read_data.empty());
316 ASSERT_EQ(TestBidirectionalStreamCallback::ON_CANCELED, test.response_step);
317 cronet_bidirectional_stream_destroy(test.stream);
318 }
319
320 TEST_F(CronetBidirectionalStreamTest, CancelOnSucceeded) {
321 TestBidirectionalStreamCallback test;
322 test.stream =
323 cronet_bidirectional_stream_create(engine(), &test, test.callback());
324 DCHECK(test.stream);
325 test.cancel_from_step = TestBidirectionalStreamCallback::ON_SUCCEEDED;
326 cronet_bidirectional_stream_start(test.stream, kTestServerUrl, 0, "POST",
327 &kTestHeadersArray, true);
328 test.BlockForDone();
329 ASSERT_EQ(std::string("404"), test.response_headers[":status"]);
330 ASSERT_EQ(std::string("file not found"), test.read_data.front());
331 ASSERT_EQ(TestBidirectionalStreamCallback::ON_SUCCEEDED, test.response_step);
332 cronet_bidirectional_stream_destroy(test.stream);
333 }
334
335 TEST_F(CronetBidirectionalStreamTest, ReadFailsBeforeRequestStarted) {
336 TestBidirectionalStreamCallback test;
337 test.stream =
338 cronet_bidirectional_stream_create(engine(), &test, test.callback());
339 DCHECK(test.stream);
340 char read_buffer[1];
341 cronet_bidirectional_stream_read(test.stream, read_buffer,
342 sizeof(read_buffer));
343 test.BlockForDone();
344 ASSERT_TRUE(test.read_data.empty());
345 ASSERT_EQ(TestBidirectionalStreamCallback::ON_FAILED, test.response_step);
346 ASSERT_EQ(net::ERR_UNEXPECTED, test.net_error);
347 cronet_bidirectional_stream_destroy(test.stream);
348 }
349
350 TEST_F(CronetBidirectionalStreamTest, WriteFailsBeforeRequestStarted) {
351 TestBidirectionalStreamCallback test;
352 test.stream =
353 cronet_bidirectional_stream_create(engine(), &test, test.callback());
354 DCHECK(test.stream);
355 cronet_bidirectional_stream_write(test.stream, "1", 1, false);
356 test.BlockForDone();
357 ASSERT_TRUE(test.read_data.empty());
358 ASSERT_EQ(TestBidirectionalStreamCallback::ON_FAILED, test.response_step);
359 ASSERT_EQ(net::ERR_UNEXPECTED, test.net_error);
360 cronet_bidirectional_stream_destroy(test.stream);
361 }
362
363 TEST_F(CronetBidirectionalStreamTest, FailedResolution) {
364 TestBidirectionalStreamCallback test;
365 test.stream =
366 cronet_bidirectional_stream_create(engine(), &test, test.callback());
367 DCHECK(test.stream);
368 test.cancel_from_step = TestBidirectionalStreamCallback::ON_FAILED;
369 cronet_bidirectional_stream_start(test.stream, "https://notfound.example.com",
370 0, "GET", &kTestHeadersArray, true);
371 test.BlockForDone();
372 ASSERT_TRUE(test.read_data.empty());
373 ASSERT_EQ(TestBidirectionalStreamCallback::ON_FAILED, test.response_step);
374 ASSERT_EQ(net::ERR_NAME_NOT_RESOLVED, test.net_error);
375 cronet_bidirectional_stream_destroy(test.stream);
376 }
OLDNEW
« no previous file with comments | « components/cronet/ios/cronet_environment.cc ('k') | components/cronet/ios/test/cronet_test_runner.mm » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698