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
16namespace net {
17
18namespace {
19
20using ::base::StringPiece;
21using ::testing::_;
22using ::testing::InSequence;
23using ::testing::SaveArg;
24
25class 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
59class 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
74TEST_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
88TEST_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
105TEST_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
155TEST_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
209TEST_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
279TEST_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
306TEST_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
330TEST_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
360TEST_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
380TEST_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
400TEST_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
448TEST_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
510TEST_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
555TEST_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
600