xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/quic/core/quic_alarm_test.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2013 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 #include "quiche/quic/core/quic_alarm.h"
6 
7 #include "quiche/quic/core/quic_connection_context.h"
8 #include "quiche/quic/platform/api/quic_expect_bug.h"
9 #include "quiche/quic/platform/api/quic_test.h"
10 
11 using testing::ElementsAre;
12 using testing::Invoke;
13 using testing::Return;
14 
15 namespace quic {
16 namespace test {
17 namespace {
18 
19 class TraceCollector : public QuicConnectionTracer {
20  public:
21   ~TraceCollector() override = default;
22 
PrintLiteral(const char * literal)23   void PrintLiteral(const char* literal) override { trace_.push_back(literal); }
24 
PrintString(absl::string_view s)25   void PrintString(absl::string_view s) override {
26     trace_.push_back(std::string(s));
27   }
28 
trace() const29   const std::vector<std::string>& trace() const { return trace_; }
30 
31  private:
32   std::vector<std::string> trace_;
33 };
34 
35 class MockDelegate : public QuicAlarm::Delegate {
36  public:
37   MOCK_METHOD(QuicConnectionContext*, GetConnectionContext, (), (override));
38   MOCK_METHOD(void, OnAlarm, (), (override));
39 };
40 
41 class DestructiveDelegate : public QuicAlarm::DelegateWithoutContext {
42  public:
DestructiveDelegate()43   DestructiveDelegate() : alarm_(nullptr) {}
44 
set_alarm(QuicAlarm * alarm)45   void set_alarm(QuicAlarm* alarm) { alarm_ = alarm; }
46 
OnAlarm()47   void OnAlarm() override {
48     QUICHE_DCHECK(alarm_);
49     delete alarm_;
50   }
51 
52  private:
53   QuicAlarm* alarm_;
54 };
55 
56 class TestAlarm : public QuicAlarm {
57  public:
TestAlarm(QuicAlarm::Delegate * delegate)58   explicit TestAlarm(QuicAlarm::Delegate* delegate)
59       : QuicAlarm(QuicArenaScopedPtr<QuicAlarm::Delegate>(delegate)) {}
60 
scheduled() const61   bool scheduled() const { return scheduled_; }
62 
FireAlarm()63   void FireAlarm() {
64     scheduled_ = false;
65     Fire();
66   }
67 
68  protected:
SetImpl()69   void SetImpl() override {
70     QUICHE_DCHECK(deadline().IsInitialized());
71     scheduled_ = true;
72   }
73 
CancelImpl()74   void CancelImpl() override {
75     QUICHE_DCHECK(!deadline().IsInitialized());
76     scheduled_ = false;
77   }
78 
79  private:
80   bool scheduled_;
81 };
82 
83 class DestructiveAlarm : public QuicAlarm {
84  public:
DestructiveAlarm(DestructiveDelegate * delegate)85   explicit DestructiveAlarm(DestructiveDelegate* delegate)
86       : QuicAlarm(QuicArenaScopedPtr<DestructiveDelegate>(delegate)) {}
87 
FireAlarm()88   void FireAlarm() { Fire(); }
89 
90  protected:
SetImpl()91   void SetImpl() override {}
92 
CancelImpl()93   void CancelImpl() override {}
94 };
95 
96 class QuicAlarmTest : public QuicTest {
97  public:
QuicAlarmTest()98   QuicAlarmTest()
99       : delegate_(new MockDelegate()),
100         alarm_(delegate_),
101         deadline_(QuicTime::Zero() + QuicTime::Delta::FromSeconds(7)),
102         deadline2_(QuicTime::Zero() + QuicTime::Delta::FromSeconds(14)),
103         new_deadline_(QuicTime::Zero()) {}
104 
ResetAlarm()105   void ResetAlarm() { alarm_.Set(new_deadline_); }
106 
107   MockDelegate* delegate_;  // not owned
108   TestAlarm alarm_;
109   QuicTime deadline_;
110   QuicTime deadline2_;
111   QuicTime new_deadline_;
112 };
113 
TEST_F(QuicAlarmTest,IsSet)114 TEST_F(QuicAlarmTest, IsSet) { EXPECT_FALSE(alarm_.IsSet()); }
115 
TEST_F(QuicAlarmTest,Set)116 TEST_F(QuicAlarmTest, Set) {
117   QuicTime deadline = QuicTime::Zero() + QuicTime::Delta::FromSeconds(7);
118   alarm_.Set(deadline);
119   EXPECT_TRUE(alarm_.IsSet());
120   EXPECT_TRUE(alarm_.scheduled());
121   EXPECT_EQ(deadline, alarm_.deadline());
122 }
123 
TEST_F(QuicAlarmTest,Cancel)124 TEST_F(QuicAlarmTest, Cancel) {
125   QuicTime deadline = QuicTime::Zero() + QuicTime::Delta::FromSeconds(7);
126   alarm_.Set(deadline);
127   alarm_.Cancel();
128   EXPECT_FALSE(alarm_.IsSet());
129   EXPECT_FALSE(alarm_.scheduled());
130   EXPECT_EQ(QuicTime::Zero(), alarm_.deadline());
131 }
132 
TEST_F(QuicAlarmTest,PermanentCancel)133 TEST_F(QuicAlarmTest, PermanentCancel) {
134   QuicTime deadline = QuicTime::Zero() + QuicTime::Delta::FromSeconds(7);
135   alarm_.Set(deadline);
136   alarm_.PermanentCancel();
137   EXPECT_FALSE(alarm_.IsSet());
138   EXPECT_FALSE(alarm_.scheduled());
139   EXPECT_EQ(QuicTime::Zero(), alarm_.deadline());
140 
141   EXPECT_QUIC_BUG(alarm_.Set(deadline),
142                   "Set called after alarm is permanently cancelled");
143   EXPECT_TRUE(alarm_.IsPermanentlyCancelled());
144   EXPECT_FALSE(alarm_.IsSet());
145   EXPECT_FALSE(alarm_.scheduled());
146   EXPECT_EQ(QuicTime::Zero(), alarm_.deadline());
147 
148   EXPECT_QUIC_BUG(alarm_.Update(deadline, QuicTime::Delta::Zero()),
149                   "Update called after alarm is permanently cancelled");
150   EXPECT_TRUE(alarm_.IsPermanentlyCancelled());
151   EXPECT_FALSE(alarm_.IsSet());
152   EXPECT_FALSE(alarm_.scheduled());
153   EXPECT_EQ(QuicTime::Zero(), alarm_.deadline());
154 }
155 
TEST_F(QuicAlarmTest,Update)156 TEST_F(QuicAlarmTest, Update) {
157   QuicTime deadline = QuicTime::Zero() + QuicTime::Delta::FromSeconds(7);
158   alarm_.Set(deadline);
159   QuicTime new_deadline = QuicTime::Zero() + QuicTime::Delta::FromSeconds(8);
160   alarm_.Update(new_deadline, QuicTime::Delta::Zero());
161   EXPECT_TRUE(alarm_.IsSet());
162   EXPECT_TRUE(alarm_.scheduled());
163   EXPECT_EQ(new_deadline, alarm_.deadline());
164 }
165 
TEST_F(QuicAlarmTest,UpdateWithZero)166 TEST_F(QuicAlarmTest, UpdateWithZero) {
167   QuicTime deadline = QuicTime::Zero() + QuicTime::Delta::FromSeconds(7);
168   alarm_.Set(deadline);
169   alarm_.Update(QuicTime::Zero(), QuicTime::Delta::Zero());
170   EXPECT_FALSE(alarm_.IsSet());
171   EXPECT_FALSE(alarm_.scheduled());
172   EXPECT_EQ(QuicTime::Zero(), alarm_.deadline());
173 }
174 
TEST_F(QuicAlarmTest,Fire)175 TEST_F(QuicAlarmTest, Fire) {
176   QuicTime deadline = QuicTime::Zero() + QuicTime::Delta::FromSeconds(7);
177   alarm_.Set(deadline);
178   EXPECT_CALL(*delegate_, OnAlarm());
179   alarm_.FireAlarm();
180   EXPECT_FALSE(alarm_.IsSet());
181   EXPECT_FALSE(alarm_.scheduled());
182   EXPECT_EQ(QuicTime::Zero(), alarm_.deadline());
183 }
184 
TEST_F(QuicAlarmTest,FireAndResetViaSet)185 TEST_F(QuicAlarmTest, FireAndResetViaSet) {
186   alarm_.Set(deadline_);
187   new_deadline_ = deadline2_;
188   EXPECT_CALL(*delegate_, OnAlarm())
189       .WillOnce(Invoke(this, &QuicAlarmTest::ResetAlarm));
190   alarm_.FireAlarm();
191   EXPECT_TRUE(alarm_.IsSet());
192   EXPECT_TRUE(alarm_.scheduled());
193   EXPECT_EQ(deadline2_, alarm_.deadline());
194 }
195 
TEST_F(QuicAlarmTest,FireDestroysAlarm)196 TEST_F(QuicAlarmTest, FireDestroysAlarm) {
197   DestructiveDelegate* delegate(new DestructiveDelegate);
198   DestructiveAlarm* alarm = new DestructiveAlarm(delegate);
199   delegate->set_alarm(alarm);
200   QuicTime deadline = QuicTime::Zero() + QuicTime::Delta::FromSeconds(7);
201   alarm->Set(deadline);
202   // This should not crash, even though it will destroy alarm.
203   alarm->FireAlarm();
204 }
205 
TEST_F(QuicAlarmTest,NullAlarmContext)206 TEST_F(QuicAlarmTest, NullAlarmContext) {
207   QuicTime deadline = QuicTime::Zero() + QuicTime::Delta::FromSeconds(7);
208   alarm_.Set(deadline);
209 
210   EXPECT_CALL(*delegate_, GetConnectionContext()).WillOnce(Return(nullptr));
211 
212   EXPECT_CALL(*delegate_, OnAlarm()).WillOnce(Invoke([] {
213     QUIC_TRACELITERAL("Alarm fired.");
214   }));
215   alarm_.FireAlarm();
216 }
217 
TEST_F(QuicAlarmTest,AlarmContextWithNullTracer)218 TEST_F(QuicAlarmTest, AlarmContextWithNullTracer) {
219   QuicConnectionContext context;
220   ASSERT_EQ(context.tracer, nullptr);
221 
222   QuicTime deadline = QuicTime::Zero() + QuicTime::Delta::FromSeconds(7);
223   alarm_.Set(deadline);
224 
225   EXPECT_CALL(*delegate_, GetConnectionContext()).WillOnce(Return(&context));
226 
227   EXPECT_CALL(*delegate_, OnAlarm()).WillOnce(Invoke([] {
228     QUIC_TRACELITERAL("Alarm fired.");
229   }));
230   alarm_.FireAlarm();
231 }
232 
TEST_F(QuicAlarmTest,AlarmContextWithTracer)233 TEST_F(QuicAlarmTest, AlarmContextWithTracer) {
234   QuicConnectionContext context;
235   std::unique_ptr<TraceCollector> tracer = std::make_unique<TraceCollector>();
236   const TraceCollector& tracer_ref = *tracer;
237   context.tracer = std::move(tracer);
238 
239   QuicTime deadline = QuicTime::Zero() + QuicTime::Delta::FromSeconds(7);
240   alarm_.Set(deadline);
241 
242   EXPECT_CALL(*delegate_, GetConnectionContext()).WillOnce(Return(&context));
243 
244   EXPECT_CALL(*delegate_, OnAlarm()).WillOnce(Invoke([] {
245     QUIC_TRACELITERAL("Alarm fired.");
246   }));
247 
248   // Since |context| is not installed in the current thread, the messages before
249   // and after FireAlarm() should not be collected by |tracer|.
250   QUIC_TRACELITERAL("Should not be collected before alarm.");
251   alarm_.FireAlarm();
252   QUIC_TRACELITERAL("Should not be collected after alarm.");
253 
254   EXPECT_THAT(tracer_ref.trace(), ElementsAre("Alarm fired."));
255 }
256 
257 }  // namespace
258 }  // namespace test
259 }  // namespace quic
260