Create a helper that wraps a competing QuicEndpoint for Quartc simulator tests.

This helper owns a QuicEndpoint and a QuicAlarm, and schedules sends of X bytes
every Y ms on that endpoint.  This is the basic operation we want from competing
flows, and simplifies test cases that use competing flows by removing all the
boilerplate of setting up and maintaining alarms.

gfe-relnote: n/a (quartc test only)
PiperOrigin-RevId: 246907891
Change-Id: I23d9b65d5c97c3e5863f7f323935dae9f55a2a3a
diff --git a/quic/quartc/test/quartc_bidi_test.cc b/quic/quartc/test/quartc_bidi_test.cc
index b1c88b7..87e4cd2 100644
--- a/quic/quartc/test/quartc_bidi_test.cc
+++ b/quic/quartc/test/quartc_bidi_test.cc
@@ -10,6 +10,7 @@
 #include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
 #include "net/third_party/quiche/src/quic/quartc/simulated_packet_transport.h"
 #include "net/third_party/quiche/src/quic/quartc/test/bidi_test_runner.h"
+#include "net/third_party/quiche/src/quic/quartc/test/quartc_competing_endpoint.h"
 #include "net/third_party/quiche/src/quic/quartc/test/quic_trace_interceptor.h"
 #include "net/third_party/quiche/src/quic/quartc/test/random_packet_filter.h"
 #include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
@@ -22,19 +23,6 @@
 namespace test {
 namespace {
 
-class CompetingTransferAlarmDelegate : public quic::QuicAlarm::Delegate {
- public:
-  CompetingTransferAlarmDelegate(quic::simulator::QuicEndpoint* endpoint,
-                                 QuicByteCount bytes)
-      : endpoint_(endpoint), bytes_(bytes) {}
-
-  void OnAlarm() override { endpoint_->AddBytesToTransfer(bytes_); }
-
- private:
-  quic::simulator::QuicEndpoint* const endpoint_;
-  const QuicByteCount bytes_;
-};
-
 class QuartcBidiTest : public QuicTest {
  protected:
   QuartcBidiTest() {
@@ -89,19 +77,23 @@
         propagation_delay);
   }
 
-  void SetupCompetingEndpoints(QuicBandwidth bandwidth) {
-    competing_client_ = QuicMakeUnique<quic::simulator::QuicEndpoint>(
-        &simulator_, "competing_client", "competing_server",
-        quic::Perspective::IS_CLIENT, quic::test::TestConnectionId(3));
-    competing_server_ = QuicMakeUnique<quic::simulator::QuicEndpoint>(
-        &simulator_, "competing_server", "competing_client",
-        quic::Perspective::IS_SERVER, quic::test::TestConnectionId(3));
+  void SetupCompetingEndpoints(QuicBandwidth bandwidth,
+                               QuicTime::Delta send_interval,
+                               QuicByteCount bytes_per_interval) {
+    competing_client_ = QuicMakeUnique<QuartcCompetingEndpoint>(
+        &simulator_, send_interval, bytes_per_interval, "competing_client",
+        "competing_server", quic::Perspective::IS_CLIENT,
+        quic::test::TestConnectionId(3));
+    competing_server_ = QuicMakeUnique<QuartcCompetingEndpoint>(
+        &simulator_, send_interval, bytes_per_interval, "competing_server",
+        "competing_client", quic::Perspective::IS_SERVER,
+        quic::test::TestConnectionId(3));
 
     competing_client_link_ = QuicMakeUnique<quic::simulator::SymmetricLink>(
-        competing_client_.get(), client_switch_->port(3), 10 * bandwidth,
+        competing_client_->endpoint(), client_switch_->port(3), 10 * bandwidth,
         QuicTime::Delta::FromMicroseconds(1));
     competing_server_link_ = QuicMakeUnique<quic::simulator::SymmetricLink>(
-        competing_server_.get(), server_switch_->port(3), 10 * bandwidth,
+        competing_server_->endpoint(), server_switch_->port(3), 10 * bandwidth,
         QuicTime::Delta::FromMicroseconds(1));
   }
 
@@ -118,8 +110,8 @@
   std::unique_ptr<simulator::SymmetricLink> server_link_;
   std::unique_ptr<simulator::SymmetricLink> bottleneck_link_;
 
-  std::unique_ptr<simulator::QuicEndpoint> competing_client_;
-  std::unique_ptr<simulator::QuicEndpoint> competing_server_;
+  std::unique_ptr<QuartcCompetingEndpoint> competing_client_;
+  std::unique_ptr<QuartcCompetingEndpoint> competing_server_;
   std::unique_ptr<simulator::SymmetricLink> competing_client_link_;
   std::unique_ptr<simulator::SymmetricLink> competing_server_link_;
 
@@ -153,20 +145,8 @@
   QuicBandwidth bandwidth = QuicBandwidth::FromKBitsPerSecond(300);
   CreateTransports(bandwidth, QuicTime::Delta::FromMilliseconds(200),
                    10 * quic::kDefaultMaxPacketSize, /*loss_percent=*/2);
-  SetupCompetingEndpoints(bandwidth);
-
-  QuicTime competing_burst_time =
-      simulator_.GetClock()->Now() + QuicTime::Delta::FromSeconds(15);
-  std::unique_ptr<quic::QuicAlarm> competing_client_burst_alarm_ =
-      QuicWrapUnique(simulator_.GetAlarmFactory()->CreateAlarm(
-          new CompetingTransferAlarmDelegate(competing_client_.get(),
-                                             /*bytes=*/50 * 1024)));
-  std::unique_ptr<quic::QuicAlarm> competing_server_burst_alarm_ =
-      QuicWrapUnique(simulator_.GetAlarmFactory()->CreateAlarm(
-          new CompetingTransferAlarmDelegate(competing_server_.get(),
-                                             /*bytes=*/50 * 1024)));
-  competing_client_burst_alarm_->Set(competing_burst_time);
-  competing_server_burst_alarm_->Set(competing_burst_time);
+  SetupCompetingEndpoints(bandwidth, QuicTime::Delta::FromSeconds(15),
+                          /*bytes_per_interval=*/50 * 1024);
 
   quic::test::BidiTestRunner runner(&simulator_, client_transport_.get(),
                                     server_transport_.get());
diff --git a/quic/quartc/test/quartc_competing_endpoint.cc b/quic/quartc/test/quartc_competing_endpoint.cc
new file mode 100644
index 0000000..fe35045
--- /dev/null
+++ b/quic/quartc/test/quartc_competing_endpoint.cc
@@ -0,0 +1,42 @@
+// Copyright (c) 2019 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/quartc/test/quartc_competing_endpoint.h"
+
+#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
+
+namespace quic {
+namespace test {
+
+QuartcCompetingEndpoint::QuartcCompetingEndpoint(
+    simulator::Simulator* simulator,
+    QuicTime::Delta send_interval,
+    QuicByteCount bytes_per_interval,
+    const std::string& name,
+    const std::string& peer_name,
+    Perspective perspective,
+    QuicConnectionId connection_id)
+    : Actor(simulator, QuicStrCat(name, " actor")),
+      send_interval_(send_interval),
+      bytes_per_interval_(bytes_per_interval),
+      endpoint_(QuicMakeUnique<simulator::QuicEndpoint>(simulator,
+                                                        name,
+                                                        peer_name,
+                                                        perspective,
+                                                        connection_id)) {
+  // Schedule the first send for one send interval into the test.
+  Schedule(simulator_->GetClock()->Now() + send_interval_);
+  last_send_time_ = simulator_->GetClock()->Now();
+}
+
+void QuartcCompetingEndpoint::Act() {
+  endpoint_->AddBytesToTransfer(bytes_per_interval_);
+  if (send_interval_ > QuicTime::Delta::Zero()) {
+    Schedule(last_send_time_ + send_interval_);
+  }
+  last_send_time_ = simulator_->GetClock()->Now();
+}
+
+}  // namespace test
+}  // namespace quic
diff --git a/quic/quartc/test/quartc_competing_endpoint.h b/quic/quartc/test/quartc_competing_endpoint.h
new file mode 100644
index 0000000..3b66131
--- /dev/null
+++ b/quic/quartc/test/quartc_competing_endpoint.h
@@ -0,0 +1,53 @@
+// Copyright (c) 2019 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_QUARTC_TEST_QUARTC_COMPETING_ENDPOINT_H_
+#define QUICHE_QUIC_QUARTC_TEST_QUARTC_COMPETING_ENDPOINT_H_
+
+#include <string>
+
+#include "net/third_party/quiche/src/quic/core/quic_alarm.h"
+#include "net/third_party/quiche/src/quic/core/quic_connection_id.h"
+#include "net/third_party/quiche/src/quic/core/quic_time.h"
+#include "net/third_party/quiche/src/quic/core/quic_types.h"
+#include "net/third_party/quiche/src/quic/test_tools/simulator/actor.h"
+#include "net/third_party/quiche/src/quic/test_tools/simulator/quic_endpoint.h"
+#include "net/third_party/quiche/src/quic/test_tools/simulator/simulator.h"
+
+namespace quic {
+namespace test {
+
+// Wrapper for a QUIC endpoint that competes with a Quartc flow in simulator
+// tests.  A competing endpoint sends a fixed number of bytes at a fixed
+// frequency.
+class QuartcCompetingEndpoint : public simulator::Actor {
+ public:
+  // Creates a competing endpoint that sends |bytes_per_interval| every
+  // |send_interval|, starting one |send_interval| after it is created
+  // (according to |simulator|'s clock).
+  QuartcCompetingEndpoint(simulator::Simulator* simulator,
+                          QuicTime::Delta send_interval,
+                          QuicByteCount bytes_per_interval,
+                          const std::string& name,
+                          const std::string& peer_name,
+                          Perspective perspective,
+                          QuicConnectionId connection_id);
+
+  simulator::QuicEndpoint* endpoint() { return endpoint_.get(); }
+
+  void Act() override;
+
+ private:
+  const QuicTime::Delta send_interval_;
+  const QuicByteCount bytes_per_interval_;
+  std::unique_ptr<simulator::QuicEndpoint> endpoint_;
+  std::unique_ptr<QuicAlarm> send_alarm_;
+
+  QuicTime last_send_time_ = QuicTime::Zero();
+};
+
+}  // namespace test
+}  // namespace quic
+
+#endif  // QUICHE_QUIC_QUARTC_TEST_QUARTC_COMPETING_ENDPOINT_H_