blob: 2577500357bb96ce90121fcff8aeba0db8b440a1 [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/quic/platform/impl/batch_writer/quic_gso_batch_writer.h"
#include "net/third_party/quic/platform/api/quic_ptr_util.h"
#include "net/third_party/quic/platform/api/quic_test.h"
namespace quic {
namespace test {
namespace {
class TestQuicGsoBatchWriter : public QuicGsoBatchWriter {
public:
using QuicGsoBatchWriter::batch_buffer;
using QuicGsoBatchWriter::CanBatch;
using QuicGsoBatchWriter::CanBatchResult;
using QuicGsoBatchWriter::MaxSegments;
using QuicGsoBatchWriter::QuicGsoBatchWriter;
};
// TestBufferedWrite is a copy-constructible BufferedWrite.
struct TestBufferedWrite : public BufferedWrite {
using BufferedWrite::BufferedWrite;
TestBufferedWrite(const TestBufferedWrite& other)
: BufferedWrite(other.buffer,
other.buf_len,
other.self_address,
other.peer_address,
other.options ? other.options->Clone()
: std::unique_ptr<PerPacketOptions>()) {}
};
// Pointed to by all instances of |BatchCriteriaTestData|. Content not used.
static char unused_packet_buffer[kMaxPacketSize];
struct BatchCriteriaTestData {
BatchCriteriaTestData(size_t buf_len,
const QuicIpAddress& self_address,
const QuicSocketAddress& peer_address,
bool can_batch,
bool must_flush)
: buffered_write(unused_packet_buffer,
buf_len,
self_address,
peer_address),
can_batch(can_batch),
must_flush(must_flush) {}
TestBufferedWrite buffered_write;
// Expected value of CanBatchResult.can_batch when batching |buffered_write|.
bool can_batch;
// Expected value of CanBatchResult.must_flush when batching |buffered_write|.
bool must_flush;
};
std::vector<BatchCriteriaTestData> BatchCriteriaTestData_SizeDecrease() {
const QuicIpAddress self_addr;
const QuicSocketAddress peer_addr;
std::vector<BatchCriteriaTestData> test_data_table = {
// clang-format off
// buf_len self_addr peer_addr can_batch must_flush
{1350, self_addr, peer_addr, true, false},
{1350, self_addr, peer_addr, true, false},
{1350, self_addr, peer_addr, true, false},
{39, self_addr, peer_addr, true, true},
{39, self_addr, peer_addr, false, true},
{1350, self_addr, peer_addr, false, true},
// clang-format on
};
return test_data_table;
}
std::vector<BatchCriteriaTestData> BatchCriteriaTestData_SizeIncrease() {
const QuicIpAddress self_addr;
const QuicSocketAddress peer_addr;
std::vector<BatchCriteriaTestData> test_data_table = {
// clang-format off
// buf_len self_addr peer_addr can_batch must_flush
{1350, self_addr, peer_addr, true, false},
{1350, self_addr, peer_addr, true, false},
{1350, self_addr, peer_addr, true, false},
{1351, self_addr, peer_addr, false, true},
// clang-format on
};
return test_data_table;
}
std::vector<BatchCriteriaTestData> BatchCriteriaTestData_AddressChange() {
const QuicIpAddress self_addr1 = QuicIpAddress::Loopback4();
const QuicIpAddress self_addr2 = QuicIpAddress::Loopback6();
const QuicSocketAddress peer_addr1(self_addr1, 666);
const QuicSocketAddress peer_addr2(self_addr1, 777);
const QuicSocketAddress peer_addr3(self_addr2, 666);
const QuicSocketAddress peer_addr4(self_addr2, 777);
std::vector<BatchCriteriaTestData> test_data_table = {
// clang-format off
// buf_len self_addr peer_addr can_batch must_flush
{1350, self_addr1, peer_addr1, true, false},
{1350, self_addr1, peer_addr1, true, false},
{1350, self_addr1, peer_addr1, true, false},
{1350, self_addr2, peer_addr1, false, true},
{1350, self_addr1, peer_addr2, false, true},
{1350, self_addr1, peer_addr3, false, true},
{1350, self_addr1, peer_addr4, false, true},
{1350, self_addr1, peer_addr4, false, true},
// clang-format on
};
return test_data_table;
}
std::vector<BatchCriteriaTestData> BatchCriteriaTestData_MaxSegments(
size_t gso_size) {
const QuicIpAddress self_addr;
const QuicSocketAddress peer_addr;
std::vector<BatchCriteriaTestData> test_data_table;
size_t max_segments = TestQuicGsoBatchWriter::MaxSegments(gso_size);
for (size_t i = 0; i < max_segments; ++i) {
bool is_last_in_batch = (i + 1 == max_segments);
test_data_table.push_back(
{gso_size, self_addr, peer_addr, true, is_last_in_batch});
}
test_data_table.push_back({gso_size, self_addr, peer_addr, false, true});
return test_data_table;
}
TEST(QuicGsoBatchWriterTest, BatchCriteria) {
std::unique_ptr<TestQuicGsoBatchWriter> writer;
std::vector<std::vector<BatchCriteriaTestData>> test_data_tables;
test_data_tables.emplace_back(BatchCriteriaTestData_SizeDecrease());
test_data_tables.emplace_back(BatchCriteriaTestData_SizeIncrease());
test_data_tables.emplace_back(BatchCriteriaTestData_AddressChange());
test_data_tables.emplace_back(BatchCriteriaTestData_MaxSegments(1));
test_data_tables.emplace_back(BatchCriteriaTestData_MaxSegments(2));
test_data_tables.emplace_back(BatchCriteriaTestData_MaxSegments(1350));
for (size_t i = 0; i < test_data_tables.size(); ++i) {
writer = QuicMakeUnique<TestQuicGsoBatchWriter>(
QuicMakeUnique<QuicBatchWriterBuffer>(), /*fd=*/-1);
const auto& test_data_table = test_data_tables[i];
for (size_t j = 0; j < test_data_table.size(); ++j) {
const BatchCriteriaTestData& test_data = test_data_table[j];
SCOPED_TRACE(testing::Message() << "i=" << i << ", j=" << j);
TestQuicGsoBatchWriter::CanBatchResult result = writer->CanBatch(
test_data.buffered_write.buffer, test_data.buffered_write.buf_len,
test_data.buffered_write.self_address,
test_data.buffered_write.peer_address,
/*options=*/nullptr);
ASSERT_EQ(test_data.can_batch, result.can_batch);
ASSERT_EQ(test_data.must_flush, result.must_flush);
if (result.can_batch) {
ASSERT_TRUE(
writer->batch_buffer()
.PushBufferedWrite(test_data.buffered_write.buffer,
test_data.buffered_write.buf_len,
test_data.buffered_write.self_address,
test_data.buffered_write.peer_address,
/*options=*/nullptr)
.succeeded);
}
}
}
}
} // namespace
} // namespace test
} // namespace quic