OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 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/flip_server/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/flip_server/balsa_enums.h" |
| 12 #include "net/tools/flip_server/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 |
OLD | NEW |