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_