blob: e21dd501fe58e337ca8065ad8ab4e808fb84e6bc [file] [log] [blame]
QUICHE teama6ef0a62019-03-07 20:34:33 -05001// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef QUICHE_QUIC_TEST_TOOLS_SIMULATOR_SIMULATOR_H_
6#define QUICHE_QUIC_TEST_TOOLS_SIMULATOR_SIMULATOR_H_
7
8#include <map>
9
10#include "net/third_party/quiche/src/quic/core/quic_connection.h"
11#include "net/third_party/quiche/src/quic/core/quic_simple_buffer_allocator.h"
12#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
13#include "net/third_party/quiche/src/quic/platform/api/quic_containers.h"
14#include "net/third_party/quiche/src/quic/test_tools/simulator/actor.h"
15#include "net/third_party/quiche/src/quic/test_tools/simulator/alarm_factory.h"
16
17namespace quic {
18namespace simulator {
19
20// Simulator is responsible for scheduling actors in the simulation and
21// providing basic utility interfaces (clock, alarms, RNG and others).
22class Simulator : public QuicConnectionHelperInterface {
23 public:
24 Simulator();
25 Simulator(const Simulator&) = delete;
26 Simulator& operator=(const Simulator&) = delete;
27 ~Simulator() override;
28
29 // Schedule the specified actor. This method will ensure that |actor| is
30 // called at |new_time| at latest. If Schedule() is called multiple times
31 // before the Actor is called, Act() is called exactly once, at the earliest
32 // time requested, and the Actor has to reschedule itself manually for the
33 // subsequent times if they are still necessary.
34 void Schedule(Actor* actor, QuicTime new_time);
35
36 // Remove the specified actor from the schedule.
37 void Unschedule(Actor* actor);
38
39 // Begin QuicConnectionHelperInterface implementation.
40 const QuicClock* GetClock() const override;
41 QuicRandom* GetRandomGenerator() override;
42 QuicBufferAllocator* GetStreamSendBufferAllocator() override;
43 // End QuicConnectionHelperInterface implementation.
44
45 QuicAlarmFactory* GetAlarmFactory();
46
47 inline void set_random_generator(QuicRandom* random) {
48 random_generator_ = random;
49 }
50
51 inline bool enable_random_delays() const { return enable_random_delays_; }
52
53 // Run the simulation until either no actors are scheduled or
54 // |termination_predicate| returns true. Returns true if terminated due to
55 // predicate, and false otherwise.
56 template <class TerminationPredicate>
57 bool RunUntil(TerminationPredicate termination_predicate);
58
59 // Same as RunUntil, except this function also accepts a |deadline|, and will
60 // return false if the deadline is exceeded.
61 template <class TerminationPredicate>
62 bool RunUntilOrTimeout(TerminationPredicate termination_predicate,
63 QuicTime::Delta deadline);
64
65 // Runs the simulation for exactly the specified |time_span|.
66 void RunFor(QuicTime::Delta time_span);
67
68 private:
69 friend class Actor;
70
71 class Clock : public QuicClock {
72 public:
73 // Do not start at zero as certain code can treat zero as an invalid
74 // timestamp.
75 const QuicTime kStartTime =
76 QuicTime::Zero() + QuicTime::Delta::FromMicroseconds(1);
77
78 Clock();
79
80 QuicTime ApproximateNow() const override;
81 QuicTime Now() const override;
82 QuicWallTime WallNow() const override;
83
84 QuicTime now_;
85 };
86
87 // The delegate used for RunFor().
88 class RunForDelegate : public QuicAlarm::Delegate {
89 public:
90 explicit RunForDelegate(bool* run_for_should_stop);
91 void OnAlarm() override;
92
93 private:
94 // Pointer to |run_for_should_stop_| in the parent simulator.
95 bool* run_for_should_stop_;
96 };
97
98 // Register an actor with the simulator. Invoked by Actor constructor.
99 void AddActor(Actor* actor);
100
101 // Unregister an actor with the simulator. Invoked by Actor destructor.
102 void RemoveActor(Actor* actor);
103
104 // Finds the next scheduled actor, advances time to the schedule time and
105 // notifies the actor.
106 void HandleNextScheduledActor();
107
108 Clock clock_;
109 QuicRandom* random_generator_;
110 SimpleBufferAllocator buffer_allocator_;
111 AlarmFactory alarm_factory_;
112
113 // Alarm for RunFor() method.
114 std::unique_ptr<QuicAlarm> run_for_alarm_;
115 // Flag used to stop simulations ran via RunFor().
116 bool run_for_should_stop_;
117
118 // Indicates whether the simulator should add random delays on the links in
119 // order to avoid synchronization issues.
120 bool enable_random_delays_;
121
122 // Schedule of when the actors will be executed via an Act() call. The
123 // schedule is subject to the following invariants:
124 // - An actor cannot be scheduled for a later time than it's currently in the
125 // schedule.
126 // - An actor is removed from schedule either immediately before Act() is
127 // called or by explicitly calling Unschedule().
128 // - Each Actor appears in the map at most once.
129 std::multimap<QuicTime, Actor*> schedule_;
130 // For each actor, maintain the time it is scheduled at. The value for
131 // unscheduled actors is QuicTime::Infinite().
132 QuicUnorderedMap<Actor*, QuicTime> scheduled_times_;
vasilvvc48c8712019-03-11 13:38:16 -0700133 QuicUnorderedSet<std::string> actor_names_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500134};
135
136template <class TerminationPredicate>
137bool Simulator::RunUntil(TerminationPredicate termination_predicate) {
138 bool predicate_value = false;
139 while (true) {
140 predicate_value = termination_predicate();
141 if (predicate_value || schedule_.empty()) {
142 break;
143 }
144 HandleNextScheduledActor();
145 }
146 return predicate_value;
147}
148
149template <class TerminationPredicate>
150bool Simulator::RunUntilOrTimeout(TerminationPredicate termination_predicate,
151 QuicTime::Delta timeout) {
152 QuicTime end_time = clock_.Now() + timeout;
153 bool return_value = RunUntil([end_time, &termination_predicate, this]() {
154 return termination_predicate() || clock_.Now() >= end_time;
155 });
156
157 if (clock_.Now() >= end_time) {
158 return false;
159 }
160 return return_value;
161}
162
163} // namespace simulator
164} // namespace quic
165
166#endif // QUICHE_QUIC_TEST_TOOLS_SIMULATOR_SIMULATOR_H_