Create a test harness for QUIC integration tests using a simulator This factors out some code from QuicTransportIntegrationTest that could be reused in other similar tests. PiperOrigin-RevId: 459567821
diff --git a/build/source_list.bzl b/build/source_list.bzl index 673c5b7..e5c653b 100644 --- a/build/source_list.bzl +++ b/build/source_list.bzl
@@ -822,6 +822,7 @@ "quic/test_tools/simulator/quic_endpoint_base.h", "quic/test_tools/simulator/simulator.h", "quic/test_tools/simulator/switch.h", + "quic/test_tools/simulator/test_harness.h", "quic/test_tools/simulator/traffic_policer.h", "quic/test_tools/test_certificates.h", "quic/test_tools/test_ticket_crypter.h", @@ -916,6 +917,7 @@ "quic/test_tools/simulator/quic_endpoint_base.cc", "quic/test_tools/simulator/simulator.cc", "quic/test_tools/simulator/switch.cc", + "quic/test_tools/simulator/test_harness.cc", "quic/test_tools/simulator/traffic_policer.cc", "quic/test_tools/test_certificates.cc", "quic/test_tools/test_ticket_crypter.cc",
diff --git a/build/source_list.gni b/build/source_list.gni index 1b35497..3deabbd 100644 --- a/build/source_list.gni +++ b/build/source_list.gni
@@ -822,6 +822,7 @@ "src/quiche/quic/test_tools/simulator/quic_endpoint_base.h", "src/quiche/quic/test_tools/simulator/simulator.h", "src/quiche/quic/test_tools/simulator/switch.h", + "src/quiche/quic/test_tools/simulator/test_harness.h", "src/quiche/quic/test_tools/simulator/traffic_policer.h", "src/quiche/quic/test_tools/test_certificates.h", "src/quiche/quic/test_tools/test_ticket_crypter.h", @@ -916,6 +917,7 @@ "src/quiche/quic/test_tools/simulator/quic_endpoint_base.cc", "src/quiche/quic/test_tools/simulator/simulator.cc", "src/quiche/quic/test_tools/simulator/switch.cc", + "src/quiche/quic/test_tools/simulator/test_harness.cc", "src/quiche/quic/test_tools/simulator/traffic_policer.cc", "src/quiche/quic/test_tools/test_certificates.cc", "src/quiche/quic/test_tools/test_ticket_crypter.cc",
diff --git a/build/source_list.json b/build/source_list.json index b6386c2..f3ebe33 100644 --- a/build/source_list.json +++ b/build/source_list.json
@@ -821,6 +821,7 @@ "quiche/quic/test_tools/simulator/quic_endpoint_base.h", "quiche/quic/test_tools/simulator/simulator.h", "quiche/quic/test_tools/simulator/switch.h", + "quiche/quic/test_tools/simulator/test_harness.h", "quiche/quic/test_tools/simulator/traffic_policer.h", "quiche/quic/test_tools/test_certificates.h", "quiche/quic/test_tools/test_ticket_crypter.h", @@ -915,6 +916,7 @@ "quiche/quic/test_tools/simulator/quic_endpoint_base.cc", "quiche/quic/test_tools/simulator/simulator.cc", "quiche/quic/test_tools/simulator/switch.cc", + "quiche/quic/test_tools/simulator/test_harness.cc", "quiche/quic/test_tools/simulator/traffic_policer.cc", "quiche/quic/test_tools/test_certificates.cc", "quiche/quic/test_tools/test_ticket_crypter.cc",
diff --git a/quiche/quic/core/quic_bandwidth.h b/quiche/quic/core/quic_bandwidth.h index 26956b2..b657228 100644 --- a/quiche/quic/core/quic_bandwidth.h +++ b/quiche/quic/core/quic_bandwidth.h
@@ -76,7 +76,7 @@ int64_t ToKBytesPerSecond() const { return bits_per_second_ / 8000; } - QuicByteCount ToBytesPerPeriod(QuicTime::Delta time_period) const { + constexpr QuicByteCount ToBytesPerPeriod(QuicTime::Delta time_period) const { return bits_per_second_ * time_period.ToMicroseconds() / 8 / kNumMicrosPerSecond; } @@ -91,7 +91,7 @@ return bits_per_second_ == Infinite().ToBitsPerSecond(); } - QuicTime::Delta TransferTime(QuicByteCount bytes) const { + constexpr QuicTime::Delta TransferTime(QuicByteCount bytes) const { if (bits_per_second_ == 0) { return QuicTime::Delta::Zero(); } @@ -107,9 +107,11 @@ int64_t bits_per_second_; - friend QuicBandwidth operator+(QuicBandwidth lhs, QuicBandwidth rhs); - friend QuicBandwidth operator-(QuicBandwidth lhs, QuicBandwidth rhs); - friend QuicBandwidth operator*(QuicBandwidth lhs, float factor); + friend constexpr QuicBandwidth operator+(QuicBandwidth lhs, + QuicBandwidth rhs); + friend constexpr QuicBandwidth operator-(QuicBandwidth lhs, + QuicBandwidth rhs); + friend constexpr QuicBandwidth operator*(QuicBandwidth lhs, float rhs); }; // Non-member relational operators for QuicBandwidth. @@ -133,23 +135,25 @@ } // Non-member arithmetic operators for QuicBandwidth. -inline QuicBandwidth operator+(QuicBandwidth lhs, QuicBandwidth rhs) { +inline constexpr QuicBandwidth operator+(QuicBandwidth lhs, QuicBandwidth rhs) { return QuicBandwidth(lhs.bits_per_second_ + rhs.bits_per_second_); } -inline QuicBandwidth operator-(QuicBandwidth lhs, QuicBandwidth rhs) { +inline constexpr QuicBandwidth operator-(QuicBandwidth lhs, QuicBandwidth rhs) { return QuicBandwidth(lhs.bits_per_second_ - rhs.bits_per_second_); } -inline QuicBandwidth operator*(QuicBandwidth lhs, float rhs) { +inline constexpr QuicBandwidth operator*(QuicBandwidth lhs, float rhs) { return QuicBandwidth( static_cast<int64_t>(std::llround(lhs.bits_per_second_ * rhs))); } inline QuicBandwidth operator*(float lhs, QuicBandwidth rhs) { return rhs * lhs; } -inline QuicByteCount operator*(QuicBandwidth lhs, QuicTime::Delta rhs) { +inline constexpr QuicByteCount operator*(QuicBandwidth lhs, + QuicTime::Delta rhs) { return lhs.ToBytesPerPeriod(rhs); } -inline QuicByteCount operator*(QuicTime::Delta lhs, QuicBandwidth rhs) { +inline constexpr QuicByteCount operator*(QuicTime::Delta lhs, + QuicBandwidth rhs) { return rhs * lhs; }
diff --git a/quiche/quic/core/quic_time.h b/quiche/quic/core/quic_time.h index 0be5d3c..d6c24b5 100644 --- a/quiche/quic/core/quic_time.h +++ b/quiche/quic/core/quic_time.h
@@ -61,17 +61,19 @@ static constexpr Delta FromMicroseconds(int64_t us) { return Delta(us); } // Converts the time offset to a rounded number of seconds. - int64_t ToSeconds() const { return time_offset_ / 1000 / 1000; } + constexpr int64_t ToSeconds() const { return time_offset_ / 1000 / 1000; } // Converts the time offset to a rounded number of milliseconds. - int64_t ToMilliseconds() const { return time_offset_ / 1000; } + constexpr int64_t ToMilliseconds() const { return time_offset_ / 1000; } // Converts the time offset to a rounded number of microseconds. - int64_t ToMicroseconds() const { return time_offset_; } + constexpr int64_t ToMicroseconds() const { return time_offset_; } - bool IsZero() const { return time_offset_ == 0; } + constexpr bool IsZero() const { return time_offset_ == 0; } - bool IsInfinite() const { return time_offset_ == kQuicInfiniteTimeUs; } + constexpr bool IsInfinite() const { + return time_offset_ == kQuicInfiniteTimeUs; + } std::string ToDebuggingValue() const; @@ -81,12 +83,14 @@ friend inline QuicTime::Delta operator<<(QuicTime::Delta lhs, size_t rhs); friend inline QuicTime::Delta operator>>(QuicTime::Delta lhs, size_t rhs); - friend inline QuicTime::Delta operator+(QuicTime::Delta lhs, - QuicTime::Delta rhs); - friend inline QuicTime::Delta operator-(QuicTime::Delta lhs, - QuicTime::Delta rhs); - friend inline QuicTime::Delta operator*(QuicTime::Delta lhs, int rhs); - friend inline QuicTime::Delta operator*(QuicTime::Delta lhs, double rhs); + friend inline constexpr QuicTime::Delta operator+(QuicTime::Delta lhs, + QuicTime::Delta rhs); + friend inline constexpr QuicTime::Delta operator-(QuicTime::Delta lhs, + QuicTime::Delta rhs); + friend inline constexpr QuicTime::Delta operator*(QuicTime::Delta lhs, + int rhs); + friend inline constexpr QuicTime::Delta operator*(QuicTime::Delta lhs, + double rhs); friend inline QuicTime operator+(QuicTime lhs, QuicTime::Delta rhs); friend inline QuicTime operator-(QuicTime lhs, QuicTime::Delta rhs); @@ -242,16 +246,18 @@ } // Non-member arithmetic operators for QuicTime::Delta. -inline QuicTime::Delta operator+(QuicTime::Delta lhs, QuicTime::Delta rhs) { +inline constexpr QuicTime::Delta operator+(QuicTime::Delta lhs, + QuicTime::Delta rhs) { return QuicTime::Delta(lhs.time_offset_ + rhs.time_offset_); } -inline QuicTime::Delta operator-(QuicTime::Delta lhs, QuicTime::Delta rhs) { +inline constexpr QuicTime::Delta operator-(QuicTime::Delta lhs, + QuicTime::Delta rhs) { return QuicTime::Delta(lhs.time_offset_ - rhs.time_offset_); } -inline QuicTime::Delta operator*(QuicTime::Delta lhs, int rhs) { +inline constexpr QuicTime::Delta operator*(QuicTime::Delta lhs, int rhs) { return QuicTime::Delta(lhs.time_offset_ * rhs); } -inline QuicTime::Delta operator*(QuicTime::Delta lhs, double rhs) { +inline constexpr QuicTime::Delta operator*(QuicTime::Delta lhs, double rhs) { return QuicTime::Delta(static_cast<int64_t>( std::llround(static_cast<double>(lhs.time_offset_) * rhs))); }
diff --git a/quiche/quic/test_tools/simulator/test_harness.cc b/quiche/quic/test_tools/simulator/test_harness.cc new file mode 100644 index 0000000..e3af48e --- /dev/null +++ b/quiche/quic/test_tools/simulator/test_harness.cc
@@ -0,0 +1,35 @@ +// Copyright 2022 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 "quiche/quic/test_tools/simulator/test_harness.h" + +#include "quiche/quic/core/quic_connection.h" +#include "quiche/quic/core/quic_versions.h" +#include "quiche/quic/test_tools/quic_test_utils.h" +#include "quiche/quic/test_tools/simulator/quic_endpoint_base.h" + +namespace quic::simulator { + +QuicEndpointWithConnection::QuicEndpointWithConnection( + Simulator* simulator, const std::string& name, const std::string& peer_name, + Perspective perspective, const ParsedQuicVersionVector& supported_versions) + : QuicEndpointBase(simulator, name, peer_name) { + connection_ = std::make_unique<QuicConnection>( + quic::test::TestConnectionId(0x10), GetAddressFromName(name), + GetAddressFromName(peer_name), simulator, simulator->GetAlarmFactory(), + &writer_, + /*owns_writer=*/false, perspective, supported_versions); + connection_->SetSelfAddress(GetAddressFromName(name)); +} + +TestHarness::TestHarness() : switch_(&simulator_, "Switch", 8, 2 * kBdp) {} + +void TestHarness::WireUpEndpoints() { + client_link_.emplace(client_, switch_.port(1), kClientBandwidth, + kClientPropagationDelay); + server_link_.emplace(server_, switch_.port(2), kServerBandwidth, + kServerPropagationDelay); +} + +} // namespace quic::simulator
diff --git a/quiche/quic/test_tools/simulator/test_harness.h b/quiche/quic/test_tools/simulator/test_harness.h new file mode 100644 index 0000000..681cfa3 --- /dev/null +++ b/quiche/quic/test_tools/simulator/test_harness.h
@@ -0,0 +1,83 @@ +// Copyright 2022 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. + +#ifndef QUICHE_QUIC_TEST_TOOLS_SIMULATOR_TEST_HARNESS_H_ +#define QUICHE_QUIC_TEST_TOOLS_SIMULATOR_TEST_HARNESS_H_ + +#include <memory> + +#include "absl/types/optional.h" +#include "quiche/quic/core/quic_constants.h" +#include "quiche/quic/core/quic_versions.h" +#include "quiche/quic/test_tools/simulator/link.h" +#include "quiche/quic/test_tools/simulator/port.h" +#include "quiche/quic/test_tools/simulator/quic_endpoint_base.h" +#include "quiche/quic/test_tools/simulator/simulator.h" +#include "quiche/quic/test_tools/simulator/switch.h" + +namespace quic::simulator { + +// A subclass of QuicEndpointBase that creates the connection object for the +// caller. Uses a fixed connection ID (0x10) and IP addresses derived from the +// names supplied. +class QuicEndpointWithConnection : public QuicEndpointBase { + public: + QuicEndpointWithConnection(Simulator* simulator, const std::string& name, + const std::string& peer_name, + Perspective perspective, + const ParsedQuicVersionVector& supported_versions); +}; + +// A test harness that provides a reasonable preset for running unit tests. +class TestHarness { + public: + // The configuration of the test harness. + static constexpr QuicBandwidth kClientBandwidth = + QuicBandwidth::FromKBitsPerSecond(10000); + static constexpr QuicTime::Delta kClientPropagationDelay = + QuicTime::Delta::FromMilliseconds(2); + static constexpr QuicBandwidth kServerBandwidth = + QuicBandwidth::FromKBitsPerSecond(4000); + static constexpr QuicTime::Delta kServerPropagationDelay = + QuicTime::Delta::FromMilliseconds(50); + static constexpr QuicTime::Delta kTransferTime = + kClientBandwidth.TransferTime(kMaxOutgoingPacketSize) + + kServerBandwidth.TransferTime(kMaxOutgoingPacketSize); + static constexpr QuicTime::Delta kRtt = + (kClientPropagationDelay + kServerPropagationDelay + kTransferTime) * 2; + static constexpr QuicByteCount kBdp = kRtt * kServerBandwidth; + + static constexpr QuicTime::Delta kDefaultTimeout = + QuicTime::Delta::FromSeconds(3); + + TestHarness(); + + Simulator& simulator() { return simulator_; } + void set_client(Endpoint* client) { client_ = client; } + void set_server(Endpoint* server) { server_ = server; } + + // Connects |client_| and |server_| to a virtual switch; must be called after + // set_client/set_server are called. + void WireUpEndpoints(); + + // A convenience wrapper around Simulator::RunUntilOrTimeout(). + template <class TerminationPredicate> + bool RunUntilWithDefaultTimeout(TerminationPredicate termination_predicate) { + return simulator_.RunUntilOrTimeout(std::move(termination_predicate), + kDefaultTimeout); + } + + private: + Simulator simulator_; + Switch switch_; + absl::optional<SymmetricLink> client_link_; + absl::optional<SymmetricLink> server_link_; + + Endpoint* client_; + Endpoint* server_; +}; + +} // namespace quic::simulator + +#endif // QUICHE_QUIC_TEST_TOOLS_SIMULATOR_TEST_HARNESS_H_