OLD | NEW |
| (Empty) |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "net/tools/balsa/balsa_frame.h" | |
6 | |
7 #include <iterator> | |
8 #include <memory> | |
9 | |
10 #include "base/strings/string_piece.h" | |
11 #include "net/tools/balsa/balsa_enums.h" | |
12 #include "net/tools/balsa/balsa_headers.h" | |
13 #include "testing/gmock/include/gmock/gmock.h" | |
14 #include "testing/gtest/include/gtest/gtest.h" | |
15 | |
16 namespace net { | |
17 | |
18 namespace { | |
19 | |
20 using ::base::StringPiece; | |
21 using ::testing::_; | |
22 using ::testing::InSequence; | |
23 using ::testing::SaveArg; | |
24 | |
25 class Visitor : public BalsaVisitorInterface { | |
26 public: | |
27 virtual ~Visitor() {} | |
28 MOCK_METHOD2(ProcessBodyInput, void(const char*, size_t)); | |
29 MOCK_METHOD2(ProcessBodyData, void(const char*, size_t)); | |
30 MOCK_METHOD2(ProcessHeaderInput, void(const char*, size_t)); | |
31 MOCK_METHOD2(ProcessTrailerInput, void(const char*, size_t)); | |
32 MOCK_METHOD1(ProcessHeaders, void(const BalsaHeaders&)); | |
33 MOCK_METHOD8(ProcessRequestFirstLine, void(const char*, | |
34 size_t, | |
35 const char*, | |
36 size_t, | |
37 const char*, | |
38 size_t, | |
39 const char*, | |
40 size_t)); | |
41 MOCK_METHOD8(ProcessResponseFirstLine, void(const char*, | |
42 size_t, | |
43 const char*, | |
44 size_t, | |
45 const char*, | |
46 size_t, | |
47 const char*, | |
48 size_t)); | |
49 MOCK_METHOD2(ProcessChunkExtensions, void(const char*, size_t)); | |
50 MOCK_METHOD1(ProcessChunkLength, void(size_t)); | |
51 MOCK_METHOD0(HeaderDone, void()); | |
52 MOCK_METHOD0(MessageDone, void()); | |
53 MOCK_METHOD1(HandleHeaderError, void(BalsaFrame*)); | |
54 MOCK_METHOD1(HandleHeaderWarning, void(BalsaFrame*)); | |
55 MOCK_METHOD1(HandleChunkingError, void(BalsaFrame*)); | |
56 MOCK_METHOD1(HandleBodyError, void(BalsaFrame*)); | |
57 }; | |
58 | |
59 class BalsaFrameTest : public ::testing::Test { | |
60 public: | |
61 void SetUp() override { | |
62 frame_.reset(new BalsaFrame); | |
63 frame_headers_.reset(new BalsaHeaders); | |
64 visitor_.reset(new Visitor); | |
65 frame_->set_balsa_visitor(visitor_.get()); | |
66 }; | |
67 | |
68 protected: | |
69 std::unique_ptr<BalsaFrame> frame_; | |
70 std::unique_ptr<BalsaHeaders> frame_headers_; | |
71 std::unique_ptr<Visitor> visitor_; | |
72 }; | |
73 | |
74 TEST_F(BalsaFrameTest, EmptyFrame) { | |
75 ASSERT_EQ(BalsaFrameEnums::READING_HEADER_AND_FIRSTLINE, | |
76 frame_->ParseState()); | |
77 ASSERT_FALSE(frame_->MessageFullyRead()); | |
78 ASSERT_FALSE(frame_->Error()); | |
79 ASSERT_EQ(NULL, frame_->const_balsa_headers()); | |
80 ASSERT_EQ(NULL, frame_->balsa_headers()); | |
81 ASSERT_EQ(NULL, frame_->headers()); | |
82 ASSERT_EQ(NULL, frame_->mutable_headers()); | |
83 ASSERT_EQ(0u, frame_->BytesSafeToSplice()); | |
84 ASSERT_TRUE(frame_->is_request()); | |
85 ASSERT_FALSE(frame_->request_was_head()); | |
86 } | |
87 | |
88 TEST_F(BalsaFrameTest, EmptyRequest) { | |
89 const char input[] = "\r\n"; | |
90 frame_->set_balsa_headers(frame_headers_.get()); | |
91 | |
92 { | |
93 InSequence s; | |
94 // No visitor callback should be called. | |
95 } | |
96 size_t read = frame_->ProcessInput(input, strlen(input)); | |
97 EXPECT_EQ(2u, read); | |
98 ASSERT_EQ(BalsaFrameEnums::READING_HEADER_AND_FIRSTLINE, | |
99 frame_->ParseState()); | |
100 ASSERT_FALSE(frame_->Error()); | |
101 ASSERT_EQ(BalsaFrameEnums::NO_ERROR, frame_->ErrorCode()); | |
102 ASSERT_EQ(0u, frame_->BytesSafeToSplice()); | |
103 } | |
104 | |
105 TEST_F(BalsaFrameTest, GetRequest) { | |
106 const char input[] = "GET / HTTP/1.0\r\nkey1: value1\r\n\r\n"; | |
107 const char* line = NULL; | |
108 size_t line_length = 0; | |
109 const char* method = NULL; | |
110 size_t method_length = 0; | |
111 const char* request_uri = NULL; | |
112 size_t request_uri_length = 0; | |
113 const char* version = NULL; | |
114 size_t version_length = 0; | |
115 const char* header = NULL; | |
116 size_t header_length = 0; | |
117 | |
118 { | |
119 InSequence s; | |
120 EXPECT_CALL(*visitor_, ProcessRequestFirstLine(_, _, _, _, _, _, _, _)) | |
121 .WillOnce(DoAll(SaveArg<0>(&line), | |
122 SaveArg<1>(&line_length), | |
123 SaveArg<2>(&method), | |
124 SaveArg<3>(&method_length), | |
125 SaveArg<4>(&request_uri), | |
126 SaveArg<5>(&request_uri_length), | |
127 SaveArg<6>(&version), | |
128 SaveArg<7>(&version_length))); | |
129 EXPECT_CALL(*visitor_, ProcessHeaderInput(_, _)) | |
130 .WillOnce(DoAll(SaveArg<0>(&header), SaveArg<1>(&header_length))); | |
131 EXPECT_CALL(*visitor_, ProcessHeaders(_)); | |
132 EXPECT_CALL(*visitor_, HeaderDone()); | |
133 EXPECT_CALL(*visitor_, MessageDone()); | |
134 } | |
135 | |
136 frame_->set_balsa_headers(frame_headers_.get()); | |
137 ASSERT_EQ(frame_headers_.get(), frame_->const_balsa_headers()); | |
138 ASSERT_EQ(frame_headers_.get(), frame_->balsa_headers()); | |
139 ASSERT_EQ(frame_headers_.get(), frame_->headers()); | |
140 ASSERT_EQ(frame_headers_.get(), frame_->mutable_headers()); | |
141 | |
142 size_t read = frame_->ProcessInput(input, strlen(input)); | |
143 ASSERT_EQ(strlen(input), read); | |
144 ASSERT_EQ(BalsaFrameEnums::MESSAGE_FULLY_READ, frame_->ParseState()); | |
145 ASSERT_TRUE(frame_->MessageFullyRead()); | |
146 ASSERT_FALSE(frame_->Error()); | |
147 ASSERT_EQ(0u, frame_->BytesSafeToSplice()); | |
148 ASSERT_EQ("GET / HTTP/1.0", StringPiece(line, line_length)); | |
149 ASSERT_EQ("GET", StringPiece(method, method_length)); | |
150 ASSERT_EQ("/", StringPiece(request_uri, request_uri_length)); | |
151 ASSERT_EQ("HTTP/1.0", StringPiece(version, version_length)); | |
152 ASSERT_EQ(input, StringPiece(header, header_length)); | |
153 } | |
154 | |
155 TEST_F(BalsaFrameTest, HeadResponse) { | |
156 const char input[] = "HTTP/1.1 200 OK\r\n" | |
157 "Content-type: text/plain\r\n" | |
158 "Content-Length: 14\r\n\r\n"; | |
159 const char* line = NULL; | |
160 size_t line_length = 0; | |
161 const char* version = NULL; | |
162 size_t version_length = 0; | |
163 const char* status = NULL; | |
164 size_t status_length = 0; | |
165 const char* reason = NULL; | |
166 size_t reason_length = 0; | |
167 const char* header = NULL; | |
168 size_t header_length = 0; | |
169 | |
170 frame_->set_balsa_headers(frame_headers_.get()); | |
171 frame_->set_is_request(false); | |
172 frame_->set_request_was_head(true); | |
173 | |
174 { | |
175 InSequence s; | |
176 EXPECT_CALL(*visitor_, ProcessResponseFirstLine(_, _, _, _, _, _, _, _)) | |
177 .WillOnce(DoAll(SaveArg<0>(&line), | |
178 SaveArg<1>(&line_length), | |
179 SaveArg<2>(&version), | |
180 SaveArg<3>(&version_length), | |
181 SaveArg<4>(&status), | |
182 SaveArg<5>(&status_length), | |
183 SaveArg<6>(&reason), | |
184 SaveArg<7>(&reason_length))); | |
185 EXPECT_CALL(*visitor_, ProcessHeaderInput(_, _)) | |
186 .WillOnce(DoAll(SaveArg<0>(&header), SaveArg<1>(&header_length))); | |
187 EXPECT_CALL(*visitor_, ProcessHeaders(_)); | |
188 EXPECT_CALL(*visitor_, HeaderDone()); | |
189 EXPECT_CALL(*visitor_, MessageDone()); | |
190 } | |
191 | |
192 size_t read = frame_->ProcessInput(input, strlen(input)); | |
193 ASSERT_EQ(strlen(input), read); | |
194 ASSERT_EQ(BalsaFrameEnums::MESSAGE_FULLY_READ, frame_->ParseState()); | |
195 ASSERT_TRUE(frame_->MessageFullyRead()); | |
196 ASSERT_FALSE(frame_->Error()); | |
197 ASSERT_EQ(0u, frame_->BytesSafeToSplice()); | |
198 | |
199 ASSERT_EQ("HTTP/1.1 200 OK", StringPiece(line, line_length)); | |
200 ASSERT_EQ("HTTP/1.1", StringPiece(version, version_length)); | |
201 ASSERT_EQ("200", StringPiece(status, status_length)); | |
202 ASSERT_EQ("OK", StringPiece(reason, reason_length)); | |
203 ASSERT_EQ("HTTP/1.1 200 OK\r\n" | |
204 "Content-type: text/plain\r\n" | |
205 "Content-Length: 14\r\n\r\n", | |
206 StringPiece(header, header_length)); | |
207 } | |
208 | |
209 TEST_F(BalsaFrameTest, GetResponse) { | |
210 const char input[] = "HTTP/1.1 200 OK\r\n" | |
211 "Content-type: text/plain\r\n" | |
212 "Content-Length: 14\r\n\r\n" | |
213 "hello, world\r\n"; | |
214 const char* line = NULL; | |
215 size_t line_length = 0; | |
216 const char* version = NULL; | |
217 size_t version_length = 0; | |
218 const char* status = NULL; | |
219 size_t status_length = 0; | |
220 const char* reason = NULL; | |
221 size_t reason_length = 0; | |
222 const char* header = NULL; | |
223 size_t header_length = 0; | |
224 const char* body = NULL; | |
225 size_t body_length = 0; | |
226 const char* body_data = NULL; | |
227 size_t body_data_length = 0; | |
228 testing::MockFunction<void(int)> checkpoint; | |
229 | |
230 frame_->set_balsa_headers(frame_headers_.get()); | |
231 frame_->set_is_request(false); | |
232 | |
233 { | |
234 InSequence s; | |
235 EXPECT_CALL(*visitor_, ProcessResponseFirstLine(_, _, _, _, _, _, _, _)) | |
236 .WillOnce(DoAll(SaveArg<0>(&line), | |
237 SaveArg<1>(&line_length), | |
238 SaveArg<2>(&version), | |
239 SaveArg<3>(&version_length), | |
240 SaveArg<4>(&status), | |
241 SaveArg<5>(&status_length), | |
242 SaveArg<6>(&reason), | |
243 SaveArg<7>(&reason_length))); | |
244 EXPECT_CALL(*visitor_, ProcessHeaderInput(_, _)) | |
245 .WillOnce(DoAll(SaveArg<0>(&header), SaveArg<1>(&header_length))); | |
246 EXPECT_CALL(*visitor_, ProcessHeaders(_)); | |
247 EXPECT_CALL(*visitor_, HeaderDone()); | |
248 EXPECT_CALL(checkpoint, Call(0)); | |
249 EXPECT_CALL(*visitor_, ProcessBodyInput(_, _)) | |
250 .WillOnce(DoAll(SaveArg<0>(&body), SaveArg<1>(&body_length))); | |
251 EXPECT_CALL(*visitor_, ProcessBodyData(_, _)) | |
252 .WillOnce(DoAll(SaveArg<0>(&body_data), SaveArg<1>(&body_data_length))); | |
253 EXPECT_CALL(*visitor_, MessageDone()); | |
254 } | |
255 | |
256 size_t read = frame_->ProcessInput(input, strlen(input)); | |
257 ASSERT_EQ(65u, read); | |
258 ASSERT_EQ(BalsaFrameEnums::READING_CONTENT, frame_->ParseState()); | |
259 checkpoint.Call(0); | |
260 read += frame_->ProcessInput(&input[read], strlen(input) - read); | |
261 ASSERT_EQ(strlen(input), read); | |
262 ASSERT_EQ(BalsaFrameEnums::MESSAGE_FULLY_READ, frame_->ParseState()); | |
263 ASSERT_TRUE(frame_->MessageFullyRead()); | |
264 ASSERT_FALSE(frame_->Error()); | |
265 ASSERT_EQ(0u, frame_->BytesSafeToSplice()); | |
266 | |
267 ASSERT_EQ("HTTP/1.1 200 OK", StringPiece(line, line_length)); | |
268 ASSERT_EQ("HTTP/1.1", StringPiece(version, version_length)); | |
269 ASSERT_EQ("200", StringPiece(status, status_length)); | |
270 ASSERT_EQ("OK", StringPiece(reason, reason_length)); | |
271 ASSERT_EQ("HTTP/1.1 200 OK\r\n" | |
272 "Content-type: text/plain\r\n" | |
273 "Content-Length: 14\r\n\r\n", | |
274 StringPiece(header, header_length)); | |
275 ASSERT_EQ("hello, world\r\n", StringPiece(body, body_length)); | |
276 ASSERT_EQ("hello, world\r\n", StringPiece(body_data, body_data_length)); | |
277 } | |
278 | |
279 TEST_F(BalsaFrameTest, Reset) { | |
280 const char input[] = "GET / HTTP/1.0\r\nkey1: value1\r\n\r\n"; | |
281 | |
282 { | |
283 InSequence s; | |
284 EXPECT_CALL(*visitor_, ProcessRequestFirstLine(_, _, _, _, _, _, _, _)); | |
285 EXPECT_CALL(*visitor_, ProcessHeaderInput(_, _)); | |
286 EXPECT_CALL(*visitor_, ProcessHeaders(_)); | |
287 EXPECT_CALL(*visitor_, HeaderDone()); | |
288 EXPECT_CALL(*visitor_, MessageDone()); | |
289 } | |
290 | |
291 frame_->set_balsa_headers(frame_headers_.get()); | |
292 | |
293 size_t read = frame_->ProcessInput(input, strlen(input)); | |
294 ASSERT_EQ(strlen(input), read); | |
295 ASSERT_EQ(BalsaFrameEnums::MESSAGE_FULLY_READ, frame_->ParseState()); | |
296 ASSERT_TRUE(frame_->MessageFullyRead()); | |
297 ASSERT_FALSE(frame_->Error()); | |
298 | |
299 frame_->Reset(); | |
300 ASSERT_EQ(BalsaFrameEnums::READING_HEADER_AND_FIRSTLINE, | |
301 frame_->ParseState()); | |
302 ASSERT_FALSE(frame_->MessageFullyRead()); | |
303 ASSERT_FALSE(frame_->Error()); | |
304 } | |
305 | |
306 TEST_F(BalsaFrameTest, InvalidStatusCode) { | |
307 const char input[] = "HTTP/1.1 InvalidStatusCode OK\r\n" | |
308 "Content-type: text/plain\r\n" | |
309 "Content-Length: 14\r\n\r\n" | |
310 "hello, world\r\n"; | |
311 | |
312 frame_->set_balsa_headers(frame_headers_.get()); | |
313 frame_->set_is_request(false); | |
314 | |
315 { | |
316 InSequence s; | |
317 EXPECT_CALL(*visitor_, HandleHeaderError(frame_.get())); | |
318 } | |
319 | |
320 size_t read = frame_->ProcessInput(input, strlen(input)); | |
321 ASSERT_EQ(30u, read); | |
322 ASSERT_EQ(BalsaFrameEnums::PARSE_ERROR, frame_->ParseState()); | |
323 ASSERT_EQ(BalsaFrameEnums::FAILED_CONVERTING_STATUS_CODE_TO_INT, | |
324 frame_->ErrorCode()); | |
325 ASSERT_FALSE(frame_->MessageFullyRead()); | |
326 ASSERT_TRUE(frame_->Error()); | |
327 ASSERT_EQ(0u, frame_->BytesSafeToSplice()); | |
328 } | |
329 | |
330 TEST_F(BalsaFrameTest, ResetError) { | |
331 const char input[] = "HTTP/1.1 InvalidStatusCode OK\r\n" | |
332 "Content-type: text/plain\r\n" | |
333 "Content-Length: 14\r\n\r\n" | |
334 "hello, world\r\n"; | |
335 | |
336 frame_->set_balsa_headers(frame_headers_.get()); | |
337 frame_->set_is_request(false); | |
338 | |
339 { | |
340 InSequence s; | |
341 EXPECT_CALL(*visitor_, HandleHeaderError(frame_.get())); | |
342 } | |
343 | |
344 size_t read = frame_->ProcessInput(input, strlen(input)); | |
345 ASSERT_EQ(30u, read); | |
346 ASSERT_EQ(BalsaFrameEnums::PARSE_ERROR, frame_->ParseState()); | |
347 ASSERT_EQ(BalsaFrameEnums::FAILED_CONVERTING_STATUS_CODE_TO_INT, | |
348 frame_->ErrorCode()); | |
349 ASSERT_FALSE(frame_->MessageFullyRead()); | |
350 ASSERT_TRUE(frame_->Error()); | |
351 ASSERT_EQ(0u, frame_->BytesSafeToSplice()); | |
352 | |
353 frame_->Reset(); | |
354 ASSERT_EQ(BalsaFrameEnums::READING_HEADER_AND_FIRSTLINE, | |
355 frame_->ParseState()); | |
356 ASSERT_FALSE(frame_->MessageFullyRead()); | |
357 ASSERT_FALSE(frame_->Error()); | |
358 } | |
359 | |
360 TEST_F(BalsaFrameTest, RequestURITooLong) { | |
361 const char input[] = "GET / HTTP/1.0\r\n\r\n"; | |
362 | |
363 frame_->set_balsa_headers(frame_headers_.get()); | |
364 frame_->set_max_request_uri_length(0); | |
365 | |
366 { | |
367 InSequence s; | |
368 EXPECT_CALL(*visitor_, HandleHeaderError(frame_.get())); | |
369 } | |
370 | |
371 size_t read = frame_->ProcessInput(input, strlen(input)); | |
372 ASSERT_EQ(15u, read); | |
373 ASSERT_EQ(BalsaFrameEnums::PARSE_ERROR, frame_->ParseState()); | |
374 ASSERT_EQ(BalsaFrameEnums::REQUEST_URI_TOO_LONG, frame_->ErrorCode()); | |
375 ASSERT_FALSE(frame_->MessageFullyRead()); | |
376 ASSERT_TRUE(frame_->Error()); | |
377 ASSERT_EQ(0u, frame_->BytesSafeToSplice()); | |
378 } | |
379 | |
380 TEST_F(BalsaFrameTest, HeadersTooLong) { | |
381 const char input[] = "GET / HTTP/1.0\r\n\r\n"; | |
382 | |
383 frame_->set_balsa_headers(frame_headers_.get()); | |
384 frame_->set_max_header_length(0); | |
385 | |
386 { | |
387 InSequence s; | |
388 EXPECT_CALL(*visitor_, HandleHeaderError(frame_.get())); | |
389 } | |
390 | |
391 size_t read = frame_->ProcessInput(input, strlen(input)); | |
392 ASSERT_EQ(0u, read); | |
393 ASSERT_EQ(BalsaFrameEnums::PARSE_ERROR, frame_->ParseState()); | |
394 ASSERT_EQ(BalsaFrameEnums::HEADERS_TOO_LONG, frame_->ErrorCode()); | |
395 ASSERT_FALSE(frame_->MessageFullyRead()); | |
396 ASSERT_TRUE(frame_->Error()); | |
397 ASSERT_EQ(0u, frame_->BytesSafeToSplice()); | |
398 } | |
399 | |
400 TEST_F(BalsaFrameTest, InvalidHeader) { | |
401 const char input[] = "GET / HTTP/1.0\r\n" | |
402 "foo bar baz\r\n" | |
403 "Content-Type: text/plain\r\n\r\n"; | |
404 const char* line = NULL; | |
405 size_t line_length = 0; | |
406 const char* method = NULL; | |
407 size_t method_length = 0; | |
408 const char* request_uri = NULL; | |
409 size_t request_uri_length = 0; | |
410 const char* version = NULL; | |
411 size_t version_length = 0; | |
412 | |
413 frame_->set_balsa_headers(frame_headers_.get()); | |
414 | |
415 { | |
416 InSequence s; | |
417 EXPECT_CALL(*visitor_, ProcessRequestFirstLine(_, _, _, _, _, _, _, _)) | |
418 .WillOnce(DoAll(SaveArg<0>(&line), | |
419 SaveArg<1>(&line_length), | |
420 SaveArg<2>(&method), | |
421 SaveArg<3>(&method_length), | |
422 SaveArg<4>(&request_uri), | |
423 SaveArg<5>(&request_uri_length), | |
424 SaveArg<6>(&version), | |
425 SaveArg<7>(&version_length))); | |
426 EXPECT_CALL(*visitor_, ProcessHeaderInput(_, _)); | |
427 EXPECT_CALL(*visitor_, HandleHeaderWarning(frame_.get())); | |
428 EXPECT_CALL(*visitor_, ProcessHeaders(_)); | |
429 EXPECT_CALL(*visitor_, HeaderDone()); | |
430 EXPECT_CALL(*visitor_, MessageDone()); | |
431 } | |
432 | |
433 size_t read = frame_->ProcessInput(input, strlen(input)); | |
434 ASSERT_EQ(strlen(input), read); | |
435 ASSERT_EQ(BalsaFrameEnums::MESSAGE_FULLY_READ, frame_->ParseState()); | |
436 ASSERT_EQ(BalsaFrameEnums::HEADER_MISSING_COLON, frame_->ErrorCode()); | |
437 ASSERT_TRUE(frame_->MessageFullyRead()); | |
438 ASSERT_FALSE(frame_->Error()); | |
439 ASSERT_EQ(0u, frame_->BytesSafeToSplice()); | |
440 ASSERT_EQ("GET / HTTP/1.0", StringPiece(line, line_length)); | |
441 ASSERT_EQ("GET", StringPiece(method, method_length)); | |
442 ASSERT_EQ("/", StringPiece(request_uri, request_uri_length)); | |
443 ASSERT_EQ("HTTP/1.0", StringPiece(version, version_length)); | |
444 ASSERT_EQ(2, std::distance(frame_headers_->header_lines_begin(), | |
445 frame_headers_->header_lines_end())); | |
446 } | |
447 | |
448 TEST_F(BalsaFrameTest, GetResponseSplit) { | |
449 const char input[] = "HTTP/1.1 200 OK\r\n" | |
450 "Content-type: text/plain\r\n" | |
451 "Content-Length: 14\r\n\r\n" | |
452 "hello"; | |
453 const char input2[] = ", world\r\n"; | |
454 const char* body1 = NULL; | |
455 size_t body1_length = 0; | |
456 const char* body1_data = NULL; | |
457 size_t body1_data_length = 0; | |
458 const char* body2 = NULL; | |
459 size_t body2_length = 0; | |
460 const char* body2_data = NULL; | |
461 size_t body2_data_length = 0; | |
462 testing::MockFunction<void(int)> checkpoint; | |
463 | |
464 frame_->set_balsa_headers(frame_headers_.get()); | |
465 frame_->set_is_request(false); | |
466 | |
467 { | |
468 InSequence s; | |
469 EXPECT_CALL(*visitor_, ProcessResponseFirstLine(_, _, _, _, _, _, _, _)); | |
470 EXPECT_CALL(*visitor_, ProcessHeaderInput(_, _)); | |
471 EXPECT_CALL(*visitor_, ProcessHeaders(_)); | |
472 EXPECT_CALL(*visitor_, HeaderDone()); | |
473 EXPECT_CALL(checkpoint, Call(0)); | |
474 EXPECT_CALL(*visitor_, ProcessBodyInput(_, _)) | |
475 .WillOnce(DoAll(SaveArg<0>(&body1), SaveArg<1>(&body1_length))); | |
476 EXPECT_CALL(*visitor_, ProcessBodyData(_, _)) | |
477 .WillOnce(DoAll(SaveArg<0>(&body1_data), | |
478 SaveArg<1>(&body1_data_length))); | |
479 EXPECT_CALL(checkpoint, Call(1)); | |
480 EXPECT_CALL(*visitor_, ProcessBodyInput(_, _)) | |
481 .WillOnce(DoAll(SaveArg<0>(&body2), SaveArg<1>(&body2_length))); | |
482 EXPECT_CALL(*visitor_, ProcessBodyData(_, _)) | |
483 .WillOnce(DoAll(SaveArg<0>(&body2_data), | |
484 SaveArg<1>(&body2_data_length))); | |
485 EXPECT_CALL(*visitor_, MessageDone()); | |
486 } | |
487 | |
488 size_t read = frame_->ProcessInput(input, strlen(input)); | |
489 ASSERT_EQ(65u, read); | |
490 ASSERT_EQ(BalsaFrameEnums::READING_CONTENT, frame_->ParseState()); | |
491 checkpoint.Call(0); | |
492 read += frame_->ProcessInput(&input[read], strlen(input) - read); | |
493 ASSERT_EQ(strlen(input), read); | |
494 ASSERT_EQ(BalsaFrameEnums::READING_CONTENT, frame_->ParseState()); | |
495 checkpoint.Call(1); | |
496 ASSERT_EQ(9u, frame_->BytesSafeToSplice()); | |
497 read = frame_->ProcessInput(input2, strlen(input2)); | |
498 ASSERT_EQ(strlen(input2), read); | |
499 | |
500 ASSERT_EQ(BalsaFrameEnums::MESSAGE_FULLY_READ, frame_->ParseState()); | |
501 ASSERT_TRUE(frame_->MessageFullyRead()); | |
502 ASSERT_FALSE(frame_->Error()); | |
503 ASSERT_EQ(0u, frame_->BytesSafeToSplice()); | |
504 ASSERT_EQ("hello", StringPiece(body1, body1_length)); | |
505 ASSERT_EQ("hello", StringPiece(body1_data, body1_data_length)); | |
506 ASSERT_EQ(", world\r\n", StringPiece(body2, body2_length)); | |
507 ASSERT_EQ(", world\r\n", StringPiece(body2_data, body2_data_length)); | |
508 } | |
509 | |
510 TEST_F(BalsaFrameTest, GetResponseBytesSpliced) { | |
511 const char input[] = "HTTP/1.1 200 OK\r\n" | |
512 "Content-type: text/plain\r\n" | |
513 "Content-Length: 14\r\n\r\n" | |
514 "hello"; | |
515 testing::MockFunction<void(int)> checkpoint; | |
516 | |
517 frame_->set_balsa_headers(frame_headers_.get()); | |
518 frame_->set_is_request(false); | |
519 | |
520 { | |
521 InSequence s; | |
522 EXPECT_CALL(*visitor_, ProcessResponseFirstLine(_, _, _, _, _, _, _, _)); | |
523 EXPECT_CALL(*visitor_, ProcessHeaderInput(_, _)); | |
524 EXPECT_CALL(*visitor_, ProcessHeaders(_)); | |
525 EXPECT_CALL(*visitor_, HeaderDone()); | |
526 EXPECT_CALL(checkpoint, Call(0)); | |
527 EXPECT_CALL(*visitor_, ProcessBodyInput(_, _)); | |
528 EXPECT_CALL(*visitor_, ProcessBodyData(_, _)); | |
529 EXPECT_CALL(checkpoint, Call(1)); | |
530 EXPECT_CALL(checkpoint, Call(2)); | |
531 EXPECT_CALL(*visitor_, MessageDone()); | |
532 } | |
533 | |
534 size_t read = frame_->ProcessInput(input, strlen(input)); | |
535 ASSERT_EQ(65u, read); | |
536 ASSERT_EQ(BalsaFrameEnums::READING_CONTENT, frame_->ParseState()); | |
537 checkpoint.Call(0); | |
538 read += frame_->ProcessInput(&input[read], strlen(input) - read); | |
539 ASSERT_EQ(strlen(input), read); | |
540 ASSERT_EQ(BalsaFrameEnums::READING_CONTENT, frame_->ParseState()); | |
541 ASSERT_EQ(9u, frame_->BytesSafeToSplice()); | |
542 checkpoint.Call(1); | |
543 frame_->BytesSpliced(5); | |
544 ASSERT_EQ(BalsaFrameEnums::READING_CONTENT, frame_->ParseState()); | |
545 ASSERT_EQ(4u, frame_->BytesSafeToSplice()); | |
546 checkpoint.Call(2); | |
547 frame_->BytesSpliced(4); | |
548 ASSERT_EQ(BalsaFrameEnums::MESSAGE_FULLY_READ, frame_->ParseState()); | |
549 | |
550 ASSERT_TRUE(frame_->MessageFullyRead()); | |
551 ASSERT_FALSE(frame_->Error()); | |
552 ASSERT_EQ(0u, frame_->BytesSafeToSplice()); | |
553 } | |
554 | |
555 TEST_F(BalsaFrameTest, GetResponseBytesSplicedTooMany) { | |
556 const char input[] = "HTTP/1.1 200 OK\r\n" | |
557 "Content-type: text/plain\r\n" | |
558 "Content-Length: 14\r\n\r\n" | |
559 "hello"; | |
560 testing::MockFunction<void(int)> checkpoint; | |
561 | |
562 frame_->set_balsa_headers(frame_headers_.get()); | |
563 frame_->set_is_request(false); | |
564 | |
565 { | |
566 InSequence s; | |
567 EXPECT_CALL(*visitor_, ProcessResponseFirstLine(_, _, _, _, _, _, _, _)); | |
568 EXPECT_CALL(*visitor_, ProcessHeaderInput(_, _)); | |
569 EXPECT_CALL(*visitor_, ProcessHeaders(_)); | |
570 EXPECT_CALL(*visitor_, HeaderDone()); | |
571 EXPECT_CALL(checkpoint, Call(0)); | |
572 EXPECT_CALL(*visitor_, ProcessBodyInput(_, _)); | |
573 EXPECT_CALL(*visitor_, ProcessBodyData(_, _)); | |
574 EXPECT_CALL(checkpoint, Call(1)); | |
575 EXPECT_CALL(*visitor_, HandleBodyError(frame_.get())); | |
576 } | |
577 | |
578 size_t read = frame_->ProcessInput(input, strlen(input)); | |
579 ASSERT_EQ(65u, read); | |
580 ASSERT_EQ(BalsaFrameEnums::READING_CONTENT, frame_->ParseState()); | |
581 checkpoint.Call(0); | |
582 read += frame_->ProcessInput(&input[read], strlen(input) - read); | |
583 ASSERT_EQ(strlen(input), read); | |
584 ASSERT_EQ(BalsaFrameEnums::READING_CONTENT, frame_->ParseState()); | |
585 ASSERT_EQ(9u, frame_->BytesSafeToSplice()); | |
586 checkpoint.Call(1); | |
587 frame_->BytesSpliced(99); | |
588 ASSERT_EQ(BalsaFrameEnums::PARSE_ERROR, frame_->ParseState()); | |
589 ASSERT_FALSE(frame_->MessageFullyRead()); | |
590 ASSERT_TRUE(frame_->Error()); | |
591 ASSERT_EQ( | |
592 BalsaFrameEnums::CALLED_BYTES_SPLICED_AND_EXCEEDED_SAFE_SPLICE_AMOUNT, | |
593 frame_->ErrorCode()); | |
594 ASSERT_EQ(0u, frame_->BytesSafeToSplice()); | |
595 } | |
596 | |
597 } // namespace | |
598 | |
599 } // namespace net | |
OLD | NEW |