blob: 37265f47808e2a405fb455eb766067214c2be196 [file] [log] [blame]
// Copyright (c) 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "net/third_party/quiche/src/quic/core/http/quic_spdy_stream_body_buffer.h"
#include <string>
#include "net/third_party/quiche/src/quic/core/quic_stream_sequencer.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_expect_bug.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
namespace quic {
namespace test {
namespace {
class MockConsumer {
public:
MOCK_METHOD1(MarkConsumed, void(size_t num_bytes_consumed));
};
class QuicSpdyStreamBodyBufferTest : public QuicTest {
public:
QuicSpdyStreamBodyBufferTest()
: body_buffer_(std::bind(&MockConsumer::MarkConsumed,
&consumer_,
std::placeholders::_1)) {}
protected:
testing::StrictMock<MockConsumer> consumer_;
QuicSpdyStreamBodyBuffer body_buffer_;
HttpEncoder encoder_;
};
TEST_F(QuicSpdyStreamBodyBufferTest, HasBytesToRead) {
const QuicByteCount header_length = 3;
std::string body(1024, 'a');
EXPECT_CALL(consumer_, MarkConsumed(header_length));
body_buffer_.OnConsumableBytes(header_length);
EXPECT_FALSE(body_buffer_.HasBytesToRead());
EXPECT_EQ(0u, body_buffer_.total_body_bytes_received());
body_buffer_.OnDataPayload(body);
EXPECT_TRUE(body_buffer_.HasBytesToRead());
EXPECT_EQ(1024u, body_buffer_.total_body_bytes_received());
}
TEST_F(QuicSpdyStreamBodyBufferTest, PeekBody) {
const QuicByteCount header_length = 3;
std::string body(1024, 'a');
EXPECT_CALL(consumer_, MarkConsumed(header_length));
body_buffer_.OnConsumableBytes(header_length);
body_buffer_.OnDataPayload(body);
iovec vec;
EXPECT_EQ(1, body_buffer_.PeekBody(&vec, 1));
EXPECT_EQ(1024u, vec.iov_len);
EXPECT_EQ(body,
QuicStringPiece(static_cast<const char*>(vec.iov_base), 1024));
}
// Buffer receives one frame. Stream consumes payload in fragments.
TEST_F(QuicSpdyStreamBodyBufferTest, MarkConsumedPartialSingleFrame) {
testing::InSequence seq;
const QuicByteCount header_length = 3;
std::string body(1024, 'a');
EXPECT_CALL(consumer_, MarkConsumed(header_length));
body_buffer_.OnConsumableBytes(header_length);
body_buffer_.OnDataPayload(body);
EXPECT_CALL(consumer_, MarkConsumed(512));
body_buffer_.MarkBodyConsumed(512);
EXPECT_CALL(consumer_, MarkConsumed(512));
body_buffer_.MarkBodyConsumed(512);
}
// Buffer receives two frames. Stream consumes multiple times.
TEST_F(QuicSpdyStreamBodyBufferTest, MarkConsumedMultipleFrames) {
testing::InSequence seq;
const QuicByteCount header_length1 = 3;
std::string body1(1024, 'a');
EXPECT_CALL(consumer_, MarkConsumed(header_length1));
body_buffer_.OnConsumableBytes(header_length1);
body_buffer_.OnDataPayload(body1);
const QuicByteCount header_length2 = 3;
std::string body2(2048, 'b');
body_buffer_.OnConsumableBytes(header_length2);
body_buffer_.OnDataPayload(body2);
// Consume part of the first frame payload.
EXPECT_CALL(consumer_, MarkConsumed(512));
body_buffer_.MarkBodyConsumed(512);
// Consume rest of the first frame and some of the second.
EXPECT_CALL(consumer_, MarkConsumed(header_length2 + 2048));
body_buffer_.MarkBodyConsumed(2048);
// Consume rest of the second frame.
EXPECT_CALL(consumer_, MarkConsumed(512));
body_buffer_.MarkBodyConsumed(512);
}
TEST_F(QuicSpdyStreamBodyBufferTest, MarkConsumedMoreThanBuffered) {
const QuicByteCount header_length = 3;
EXPECT_CALL(consumer_, MarkConsumed(header_length));
body_buffer_.OnConsumableBytes(header_length);
std::string body(1024, 'a');
body_buffer_.OnDataPayload(body);
EXPECT_QUIC_BUG(
body_buffer_.MarkBodyConsumed(2048),
"Invalid argument to MarkBodyConsumed. expect to consume: 2048, but not "
"enough bytes available. Total bytes readable are: 1024");
}
// Buffer receives one frame. Stream reads from the buffer.
TEST_F(QuicSpdyStreamBodyBufferTest, ReadSingleBody) {
testing::InSequence seq;
const QuicByteCount header_length = 3;
std::string body(1024, 'a');
EXPECT_CALL(consumer_, MarkConsumed(header_length));
body_buffer_.OnConsumableBytes(header_length);
body_buffer_.OnDataPayload(QuicStringPiece(body));
EXPECT_CALL(consumer_, MarkConsumed(1024));
char base[1024];
iovec iov = {&base[0], 1024};
EXPECT_EQ(1024u, body_buffer_.ReadBody(&iov, 1));
EXPECT_EQ(1024u, iov.iov_len);
EXPECT_EQ(body,
QuicStringPiece(static_cast<const char*>(iov.iov_base), 1024));
}
// Buffer receives two frames. Stream reads from the buffer multiple times.
TEST_F(QuicSpdyStreamBodyBufferTest, ReadMultipleBody) {
testing::InSequence seq;
const QuicByteCount header_length1 = 3;
std::string body1(1024, 'a');
EXPECT_CALL(consumer_, MarkConsumed(header_length1));
body_buffer_.OnConsumableBytes(header_length1);
body_buffer_.OnDataPayload(body1);
const QuicByteCount header_length2 = 3;
std::string body2(2048, 'b');
body_buffer_.OnConsumableBytes(header_length2);
body_buffer_.OnDataPayload(body2);
// Read part of the first frame payload.
EXPECT_CALL(consumer_, MarkConsumed(512));
char base[512];
iovec iov = {&base[0], 512};
EXPECT_EQ(512u, body_buffer_.ReadBody(&iov, 1));
EXPECT_EQ(512u, iov.iov_len);
EXPECT_EQ(body1.substr(0, 512),
QuicStringPiece(static_cast<const char*>(iov.iov_base), 512));
// Read rest of the first frame and some of the second.
EXPECT_CALL(consumer_, MarkConsumed(header_length2 + 2048));
char base2[2048];
iovec iov2 = {&base2[0], 2048};
EXPECT_EQ(2048u, body_buffer_.ReadBody(&iov2, 1));
EXPECT_EQ(2048u, iov2.iov_len);
EXPECT_EQ(body1.substr(512, 512) + body2.substr(0, 1536),
QuicStringPiece(static_cast<const char*>(iov2.iov_base), 2048));
// Read rest of the second frame.
EXPECT_CALL(consumer_, MarkConsumed(512));
char base3[512];
iovec iov3 = {&base3[0], 512};
EXPECT_EQ(512u, body_buffer_.ReadBody(&iov3, 1));
EXPECT_EQ(512u, iov3.iov_len);
EXPECT_EQ(body2.substr(1536, 512),
QuicStringPiece(static_cast<const char*>(iov3.iov_base), 512));
}
} // anonymous namespace
} // namespace test
} // namespace quic