1 // Copyright 2015 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 "net/base/backoff_entry.h"
6
7 #include "base/time/tick_clock.h"
8 #include "base/values.h"
9 #include "net/base/backoff_entry_serializer.h"
10 #include "testing/gtest/include/gtest/gtest.h"
11
12 namespace net {
13
14 namespace {
15
16 using base::Time;
17 using base::TimeDelta;
18 using base::TimeTicks;
19
20 BackoffEntry::Policy base_policy = {
21 0 /* num_errors_to_ignore */,
22 1000 /* initial_delay_ms */,
23 2.0 /* multiply_factor */,
24 0.0 /* jitter_factor */,
25 20000 /* maximum_backoff_ms */,
26 2000 /* entry_lifetime_ms */,
27 false /* always_use_initial_delay */
28 };
29
30 class TestTickClock : public base::TickClock {
31 public:
32 TestTickClock() = default;
33 TestTickClock(const TestTickClock&) = delete;
34 TestTickClock& operator=(const TestTickClock&) = delete;
35 ~TestTickClock() override = default;
36
NowTicks() const37 TimeTicks NowTicks() const override { return now_ticks_; }
set_now(TimeTicks now)38 void set_now(TimeTicks now) { now_ticks_ = now; }
39
40 private:
41 TimeTicks now_ticks_;
42 };
43
TEST(BackoffEntrySerializerTest,SerializeNoFailures)44 TEST(BackoffEntrySerializerTest, SerializeNoFailures) {
45 Time original_time = Time::Now();
46 TestTickClock original_ticks;
47 original_ticks.set_now(TimeTicks::Now());
48 BackoffEntry original(&base_policy, &original_ticks);
49 std::unique_ptr<base::Value> serialized =
50 BackoffEntrySerializer::SerializeToValue(original, original_time);
51
52 std::unique_ptr<BackoffEntry> deserialized =
53 BackoffEntrySerializer::DeserializeFromValue(
54 *serialized, &base_policy, &original_ticks, original_time);
55 ASSERT_TRUE(deserialized.get());
56 EXPECT_EQ(original.failure_count(), deserialized->failure_count());
57 EXPECT_EQ(original.GetReleaseTime(), deserialized->GetReleaseTime());
58 }
59
TEST(BackoffEntrySerializerTest,SerializeTimeOffsets)60 TEST(BackoffEntrySerializerTest, SerializeTimeOffsets) {
61 Time original_time = Time::FromJsTime(1430907555111); // May 2015 for realism
62 TestTickClock original_ticks;
63 BackoffEntry original(&base_policy, &original_ticks);
64 // 2 errors.
65 original.InformOfRequest(false);
66 original.InformOfRequest(false);
67 std::unique_ptr<base::Value> serialized =
68 BackoffEntrySerializer::SerializeToValue(original, original_time);
69
70 {
71 // Test that immediate deserialization round-trips.
72 std::unique_ptr<BackoffEntry> deserialized =
73 BackoffEntrySerializer::DeserializeFromValue(
74 *serialized, &base_policy, &original_ticks, original_time);
75 ASSERT_TRUE(deserialized.get());
76 EXPECT_EQ(original.failure_count(), deserialized->failure_count());
77 EXPECT_EQ(original.GetReleaseTime(), deserialized->GetReleaseTime());
78 }
79
80 {
81 // Test deserialization when wall clock has advanced but TimeTicks::Now()
82 // hasn't (e.g. device was rebooted).
83 Time later_time = original_time + TimeDelta::FromDays(1);
84 std::unique_ptr<BackoffEntry> deserialized =
85 BackoffEntrySerializer::DeserializeFromValue(
86 *serialized, &base_policy, &original_ticks, later_time);
87 ASSERT_TRUE(deserialized.get());
88 EXPECT_EQ(original.failure_count(), deserialized->failure_count());
89 // Remaining backoff duration continues decreasing while device is off.
90 // Since TimeTicks::Now() has not advanced, the absolute release time ticks
91 // will decrease accordingly.
92 EXPECT_GT(original.GetTimeUntilRelease(),
93 deserialized->GetTimeUntilRelease());
94 EXPECT_EQ(original.GetReleaseTime() - TimeDelta::FromDays(1),
95 deserialized->GetReleaseTime());
96 }
97
98 {
99 // Test deserialization when TimeTicks::Now() has advanced but wall clock
100 // hasn't (e.g. it's an hour later, but a DST change cancelled that out).
101 TestTickClock later_ticks;
102 later_ticks.set_now(TimeTicks() + TimeDelta::FromDays(1));
103 std::unique_ptr<BackoffEntry> deserialized =
104 BackoffEntrySerializer::DeserializeFromValue(
105 *serialized, &base_policy, &later_ticks, original_time);
106 ASSERT_TRUE(deserialized.get());
107 EXPECT_EQ(original.failure_count(), deserialized->failure_count());
108 // According to the wall clock, no time has passed. So remaining backoff
109 // duration is preserved, hence the absolute release time ticks increases.
110 // This isn't ideal - by also serializing the current time and time ticks,
111 // it would be possible to detect that time has passed but the wall clock
112 // went backwards, and reduce the remaining backoff duration accordingly,
113 // however the current implementation does not do this as the benefit would
114 // be somewhat marginal.
115 EXPECT_EQ(original.GetTimeUntilRelease(),
116 deserialized->GetTimeUntilRelease());
117 EXPECT_EQ(original.GetReleaseTime() + TimeDelta::FromDays(1),
118 deserialized->GetReleaseTime());
119 }
120
121 {
122 // Test deserialization when both wall clock and TimeTicks::Now() have
123 // advanced (e.g. it's just later than it used to be).
124 TestTickClock later_ticks;
125 later_ticks.set_now(TimeTicks() + TimeDelta::FromDays(1));
126 Time later_time = original_time + TimeDelta::FromDays(1);
127 std::unique_ptr<BackoffEntry> deserialized =
128 BackoffEntrySerializer::DeserializeFromValue(*serialized, &base_policy,
129 &later_ticks, later_time);
130 ASSERT_TRUE(deserialized.get());
131 EXPECT_EQ(original.failure_count(), deserialized->failure_count());
132 // Since both have advanced by the same amount, the absolute release time
133 // ticks should be preserved; the remaining backoff duration will have
134 // decreased of course, since time has passed.
135 EXPECT_GT(original.GetTimeUntilRelease(),
136 deserialized->GetTimeUntilRelease());
137 EXPECT_EQ(original.GetReleaseTime(), deserialized->GetReleaseTime());
138 }
139
140 {
141 // Test deserialization when wall clock has gone backwards but TimeTicks
142 // haven't (e.g. the system clock was fast but they fixed it).
143 EXPECT_LT(TimeDelta::FromSeconds(1), original.GetTimeUntilRelease());
144 Time earlier_time = original_time - TimeDelta::FromSeconds(1);
145 std::unique_ptr<BackoffEntry> deserialized =
146 BackoffEntrySerializer::DeserializeFromValue(
147 *serialized, &base_policy, &original_ticks, earlier_time);
148 ASSERT_TRUE(deserialized.get());
149 EXPECT_EQ(original.failure_count(), deserialized->failure_count());
150 // If only the absolute wall clock time was serialized, subtracting the
151 // (decreased) current wall clock time from the serialized wall clock time
152 // could give very large (incorrect) values for remaining backoff duration.
153 // But instead the implementation also serializes the remaining backoff
154 // duration, and doesn't allow the duration to increase beyond it's previous
155 // value during deserialization. Hence when the wall clock goes backwards
156 // the remaining backoff duration will be preserved.
157 EXPECT_EQ(original.GetTimeUntilRelease(),
158 deserialized->GetTimeUntilRelease());
159 // Since TimeTicks::Now() hasn't changed, the absolute release time ticks
160 // will be equal too in this particular case.
161 EXPECT_EQ(original.GetReleaseTime(), deserialized->GetReleaseTime());
162 }
163 }
164
165 } // namespace
166
167 } // namespace net
168