- add sources.
[platform/framework/web/crosswalk.git] / src / net / tools / balsa / balsa_frame_test.cc
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
9 #include "base/memory/scoped_ptr.h"
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   virtual 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   scoped_ptr<BalsaFrame> frame_;
70   scoped_ptr<BalsaHeaders> frame_headers_;
71   scoped_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