1177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko// Copyright 2015 The Chromium OS Authors. All rights reserved.
2177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko// Use of this source code is governed by a BSD-style license that can be
3177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko// found in the LICENSE file.
4177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko
59ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko#include <brillo/backoff_entry.h>
6177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko#include <gtest/gtest.h>
7177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko
8177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenkousing base::TimeDelta;
9177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenkousing base::TimeTicks;
10177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko
119ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenkonamespace brillo {
12177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko
13177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex VakulenkoBackoffEntry::Policy base_policy = { 0, 1000, 2.0, 0.0, 20000, 2000, false };
14177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko
15177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenkoclass TestBackoffEntry : public BackoffEntry {
16177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko public:
17177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  explicit TestBackoffEntry(const Policy* const policy)
18177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko      : BackoffEntry(policy),
19177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko        now_(TimeTicks()) {
20177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko    // Work around initialization in constructor not picking up
21177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko    // fake time.
22177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko    SetCustomReleaseTime(TimeTicks());
23177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  }
24177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko
25177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  ~TestBackoffEntry() override {}
26177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko
27177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  TimeTicks ImplGetTimeNow() const override { return now_; }
28177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko
29177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  void set_now(const TimeTicks& now) {
30177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko    now_ = now;
31177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  }
32177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko
33177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko private:
34177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  TimeTicks now_;
35177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko
36177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  DISALLOW_COPY_AND_ASSIGN(TestBackoffEntry);
37177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko};
38177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko
39177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex VakulenkoTEST(BackoffEntryTest, BaseTest) {
40177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  TestBackoffEntry entry(&base_policy);
41177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  EXPECT_FALSE(entry.ShouldRejectRequest());
42177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  EXPECT_EQ(TimeDelta(), entry.GetTimeUntilRelease());
43177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko
44177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  entry.InformOfRequest(false);
45177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  EXPECT_TRUE(entry.ShouldRejectRequest());
46177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  EXPECT_EQ(TimeDelta::FromMilliseconds(1000), entry.GetTimeUntilRelease());
47177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko}
48177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko
49177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex VakulenkoTEST(BackoffEntryTest, CanDiscardNeverExpires) {
50177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  BackoffEntry::Policy never_expires_policy = base_policy;
51177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  never_expires_policy.entry_lifetime_ms = -1;
52177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  TestBackoffEntry never_expires(&never_expires_policy);
53177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  EXPECT_FALSE(never_expires.CanDiscard());
54177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  never_expires.set_now(TimeTicks() + TimeDelta::FromDays(100));
55177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  EXPECT_FALSE(never_expires.CanDiscard());
56177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko}
57177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko
58177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex VakulenkoTEST(BackoffEntryTest, CanDiscard) {
59177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  TestBackoffEntry entry(&base_policy);
60177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  // Because lifetime is non-zero, we shouldn't be able to discard yet.
61177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  EXPECT_FALSE(entry.CanDiscard());
62177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko
63177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  // Test the "being used" case.
64177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  entry.InformOfRequest(false);
65177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  EXPECT_FALSE(entry.CanDiscard());
66177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko
67177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  // Test the case where there are errors but we can time out.
68177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  entry.set_now(
69177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko      entry.GetReleaseTime() + TimeDelta::FromMilliseconds(1));
70177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  EXPECT_FALSE(entry.CanDiscard());
71177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  entry.set_now(entry.GetReleaseTime() + TimeDelta::FromMilliseconds(
72177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko      base_policy.maximum_backoff_ms + 1));
73177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  EXPECT_TRUE(entry.CanDiscard());
74177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko
75177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  // Test the final case (no errors, dependent only on specified lifetime).
76177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  entry.set_now(entry.GetReleaseTime() + TimeDelta::FromMilliseconds(
77177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko      base_policy.entry_lifetime_ms - 1));
78177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  entry.InformOfRequest(true);
79177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  EXPECT_FALSE(entry.CanDiscard());
80177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  entry.set_now(entry.GetReleaseTime() + TimeDelta::FromMilliseconds(
81177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko      base_policy.entry_lifetime_ms));
82177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  EXPECT_TRUE(entry.CanDiscard());
83177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko}
84177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko
85177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex VakulenkoTEST(BackoffEntryTest, CanDiscardAlwaysDelay) {
86177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  BackoffEntry::Policy always_delay_policy = base_policy;
87177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  always_delay_policy.always_use_initial_delay = true;
88177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  always_delay_policy.entry_lifetime_ms = 0;
89177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko
90177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  TestBackoffEntry entry(&always_delay_policy);
91177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko
92177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  // Because lifetime is non-zero, we shouldn't be able to discard yet.
93177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  entry.set_now(entry.GetReleaseTime() + TimeDelta::FromMilliseconds(2000));
94177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  EXPECT_TRUE(entry.CanDiscard());
95177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko
96177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  // Even with no failures, we wait until the delay before we allow discard.
97177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  entry.InformOfRequest(true);
98177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  EXPECT_FALSE(entry.CanDiscard());
99177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko
100177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  // Wait until the delay expires, and we can discard the entry again.
101177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  entry.set_now(entry.GetReleaseTime() + TimeDelta::FromMilliseconds(1000));
102177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  EXPECT_TRUE(entry.CanDiscard());
103177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko}
104177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko
105177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex VakulenkoTEST(BackoffEntryTest, CanDiscardNotStored) {
106177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  BackoffEntry::Policy no_store_policy = base_policy;
107177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  no_store_policy.entry_lifetime_ms = 0;
108177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  TestBackoffEntry not_stored(&no_store_policy);
109177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  EXPECT_TRUE(not_stored.CanDiscard());
110177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko}
111177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko
112177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex VakulenkoTEST(BackoffEntryTest, ShouldIgnoreFirstTwo) {
113177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  BackoffEntry::Policy lenient_policy = base_policy;
114177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  lenient_policy.num_errors_to_ignore = 2;
115177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko
116177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  BackoffEntry entry(&lenient_policy);
117177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko
118177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  entry.InformOfRequest(false);
119177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  EXPECT_FALSE(entry.ShouldRejectRequest());
120177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko
121177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  entry.InformOfRequest(false);
122177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  EXPECT_FALSE(entry.ShouldRejectRequest());
123177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko
124177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  entry.InformOfRequest(false);
125177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  EXPECT_TRUE(entry.ShouldRejectRequest());
126177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko}
127177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko
128177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex VakulenkoTEST(BackoffEntryTest, ReleaseTimeCalculation) {
129177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  TestBackoffEntry entry(&base_policy);
130177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko
131177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  // With zero errors, should return "now".
132177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  TimeTicks result = entry.GetReleaseTime();
133177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  EXPECT_EQ(entry.ImplGetTimeNow(), result);
134177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko
135177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  // 1 error.
136177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  entry.InformOfRequest(false);
137177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  result = entry.GetReleaseTime();
138177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  EXPECT_EQ(entry.ImplGetTimeNow() + TimeDelta::FromMilliseconds(1000), result);
139177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  EXPECT_EQ(TimeDelta::FromMilliseconds(1000), entry.GetTimeUntilRelease());
140177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko
141177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  // 2 errors.
142177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  entry.InformOfRequest(false);
143177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  result = entry.GetReleaseTime();
144177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  EXPECT_EQ(entry.ImplGetTimeNow() + TimeDelta::FromMilliseconds(2000), result);
145177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  EXPECT_EQ(TimeDelta::FromMilliseconds(2000), entry.GetTimeUntilRelease());
146177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko
147177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  // 3 errors.
148177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  entry.InformOfRequest(false);
149177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  result = entry.GetReleaseTime();
150177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  EXPECT_EQ(entry.ImplGetTimeNow() + TimeDelta::FromMilliseconds(4000), result);
151177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  EXPECT_EQ(TimeDelta::FromMilliseconds(4000), entry.GetTimeUntilRelease());
152177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko
153177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  // 6 errors (to check it doesn't pass maximum).
154177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  entry.InformOfRequest(false);
155177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  entry.InformOfRequest(false);
156177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  entry.InformOfRequest(false);
157177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  result = entry.GetReleaseTime();
158177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  EXPECT_EQ(
159177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko      entry.ImplGetTimeNow() + TimeDelta::FromMilliseconds(20000), result);
160177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko}
161177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko
162177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex VakulenkoTEST(BackoffEntryTest, ReleaseTimeCalculationAlwaysDelay) {
163177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  BackoffEntry::Policy always_delay_policy = base_policy;
164177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  always_delay_policy.always_use_initial_delay = true;
165177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  always_delay_policy.num_errors_to_ignore = 2;
166177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko
167177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  TestBackoffEntry entry(&always_delay_policy);
168177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko
169177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  // With previous requests, should return "now".
170177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  TimeTicks result = entry.GetReleaseTime();
171177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  EXPECT_EQ(TimeDelta(), entry.GetTimeUntilRelease());
172177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko
173177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  // 1 error.
174177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  entry.InformOfRequest(false);
175177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  EXPECT_EQ(TimeDelta::FromMilliseconds(1000), entry.GetTimeUntilRelease());
176177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko
177177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  // 2 errors.
178177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  entry.InformOfRequest(false);
179177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  EXPECT_EQ(TimeDelta::FromMilliseconds(1000), entry.GetTimeUntilRelease());
180177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko
181177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  // 3 errors, exponential backoff starts.
182177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  entry.InformOfRequest(false);
183177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  EXPECT_EQ(TimeDelta::FromMilliseconds(2000), entry.GetTimeUntilRelease());
184177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko
185177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  // 4 errors.
186177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  entry.InformOfRequest(false);
187177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  EXPECT_EQ(TimeDelta::FromMilliseconds(4000), entry.GetTimeUntilRelease());
188177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko
189177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  // 8 errors (to check it doesn't pass maximum).
190177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  entry.InformOfRequest(false);
191177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  entry.InformOfRequest(false);
192177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  entry.InformOfRequest(false);
193177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  entry.InformOfRequest(false);
194177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  result = entry.GetReleaseTime();
195177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  EXPECT_EQ(TimeDelta::FromMilliseconds(20000), entry.GetTimeUntilRelease());
196177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko}
197177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko
198177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex VakulenkoTEST(BackoffEntryTest, ReleaseTimeCalculationWithJitter) {
199177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  for (int i = 0; i < 10; ++i) {
200177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko    BackoffEntry::Policy jittery_policy = base_policy;
201177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko    jittery_policy.jitter_factor = 0.2;
202177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko
203177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko    TestBackoffEntry entry(&jittery_policy);
204177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko
205177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko    entry.InformOfRequest(false);
206177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko    entry.InformOfRequest(false);
207177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko    entry.InformOfRequest(false);
208177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko    TimeTicks result = entry.GetReleaseTime();
209177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko    EXPECT_LE(
210177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko        entry.ImplGetTimeNow() + TimeDelta::FromMilliseconds(3200), result);
211177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko    EXPECT_GE(
212177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko        entry.ImplGetTimeNow() + TimeDelta::FromMilliseconds(4000), result);
213177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  }
214177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko}
215177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko
216177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex VakulenkoTEST(BackoffEntryTest, FailureThenSuccess) {
217177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  TestBackoffEntry entry(&base_policy);
218177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko
219177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  // Failure count 1, establishes horizon.
220177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  entry.InformOfRequest(false);
221177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  TimeTicks release_time = entry.GetReleaseTime();
222177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  EXPECT_EQ(TimeTicks() + TimeDelta::FromMilliseconds(1000), release_time);
223177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko
224177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  // Success, failure count 0, should not advance past
225177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  // the horizon that was already set.
226177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  entry.set_now(release_time - TimeDelta::FromMilliseconds(200));
227177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  entry.InformOfRequest(true);
228177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  EXPECT_EQ(release_time, entry.GetReleaseTime());
229177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko
230177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  // Failure, failure count 1.
231177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  entry.InformOfRequest(false);
232177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  EXPECT_EQ(release_time + TimeDelta::FromMilliseconds(800),
233177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko            entry.GetReleaseTime());
234177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko}
235177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko
236177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex VakulenkoTEST(BackoffEntryTest, FailureThenSuccessAlwaysDelay) {
237177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  BackoffEntry::Policy always_delay_policy = base_policy;
238177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  always_delay_policy.always_use_initial_delay = true;
239177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  always_delay_policy.num_errors_to_ignore = 1;
240177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko
241177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  TestBackoffEntry entry(&always_delay_policy);
242177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko
243177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  // Failure count 1.
244177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  entry.InformOfRequest(false);
245177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  EXPECT_EQ(TimeDelta::FromMilliseconds(1000), entry.GetTimeUntilRelease());
246177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko
247177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  // Failure count 2.
248177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  entry.InformOfRequest(false);
249177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  EXPECT_EQ(TimeDelta::FromMilliseconds(2000), entry.GetTimeUntilRelease());
250177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  entry.set_now(entry.GetReleaseTime() + TimeDelta::FromMilliseconds(2000));
251177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko
252177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  // Success.  We should go back to the original delay.
253177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  entry.InformOfRequest(true);
254177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  EXPECT_EQ(TimeDelta::FromMilliseconds(1000), entry.GetTimeUntilRelease());
255177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko
256177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  // Failure count reaches 2 again.  We should increase the delay once more.
257177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  entry.InformOfRequest(false);
258177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  EXPECT_EQ(TimeDelta::FromMilliseconds(2000), entry.GetTimeUntilRelease());
259177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  entry.set_now(entry.GetReleaseTime() + TimeDelta::FromMilliseconds(2000));
260177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko}
261177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko
262177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex VakulenkoTEST(BackoffEntryTest, RetainCustomHorizon) {
263177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  TestBackoffEntry custom(&base_policy);
264177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  TimeTicks custom_horizon = TimeTicks() + TimeDelta::FromDays(3);
265177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  custom.SetCustomReleaseTime(custom_horizon);
266177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  custom.InformOfRequest(false);
267177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  custom.InformOfRequest(true);
268177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  custom.set_now(TimeTicks() + TimeDelta::FromDays(2));
269177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  custom.InformOfRequest(false);
270177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  custom.InformOfRequest(true);
271177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  EXPECT_EQ(custom_horizon, custom.GetReleaseTime());
272177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko
273177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  // Now check that once we are at or past the custom horizon,
274177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  // we get normal behavior.
275177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  custom.set_now(TimeTicks() + TimeDelta::FromDays(3));
276177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  custom.InformOfRequest(false);
277177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  EXPECT_EQ(
278177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko      TimeTicks() + TimeDelta::FromDays(3) + TimeDelta::FromMilliseconds(1000),
279177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko      custom.GetReleaseTime());
280177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko}
281177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko
282177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex VakulenkoTEST(BackoffEntryTest, RetainCustomHorizonWhenInitialErrorsIgnored) {
283177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  // Regression test for a bug discovered during code review.
284177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  BackoffEntry::Policy lenient_policy = base_policy;
285177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  lenient_policy.num_errors_to_ignore = 1;
286177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  TestBackoffEntry custom(&lenient_policy);
287177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  TimeTicks custom_horizon = TimeTicks() + TimeDelta::FromDays(3);
288177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  custom.SetCustomReleaseTime(custom_horizon);
289177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  custom.InformOfRequest(false);  // This must not reset the horizon.
290177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  EXPECT_EQ(custom_horizon, custom.GetReleaseTime());
291177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko}
292177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko
293177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex VakulenkoTEST(BackoffEntryTest, OverflowProtection) {
294177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  BackoffEntry::Policy large_multiply_policy = base_policy;
295177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  large_multiply_policy.multiply_factor = 256;
296177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  TestBackoffEntry custom(&large_multiply_policy);
297177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko
298177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  // Trigger enough failures such that more than 11 bits of exponent are used
299177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  // to represent the exponential backoff intermediate values. Given a multiply
300177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  // factor of 256 (2^8), 129 iterations is enough: 2^(8*(129-1)) = 2^1024.
301177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  for (int i = 0; i < 129; ++i) {
3029ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko    custom.set_now(custom.ImplGetTimeNow() + custom.GetTimeUntilRelease());
3039ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko    custom.InformOfRequest(false);
3049ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko    ASSERT_TRUE(custom.ShouldRejectRequest());
305177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  }
306177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko
307177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  // Max delay should still be respected.
308177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko  EXPECT_EQ(20000, custom.GetTimeUntilRelease().InMilliseconds());
309177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko}
310177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko
311177ddccf5dbb585aa8bab8482fa062d3a8858bc7Alex Vakulenko}  // namespace
312