backoff_entry_serializer_unittest.cc 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406
  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. #include "net/base/backoff_entry.h"
  5. #include "base/containers/span.h"
  6. #include "base/logging.h"
  7. #include "base/strings/string_number_conversions.h"
  8. #include "base/strings/stringprintf.h"
  9. #include "base/time/tick_clock.h"
  10. #include "base/time/time.h"
  11. #include "base/values.h"
  12. #include "net/base/backoff_entry_serializer.h"
  13. #include "testing/gtest/include/gtest/gtest.h"
  14. namespace net {
  15. namespace {
  16. using base::Time;
  17. using base::TimeTicks;
  18. const Time kParseTime =
  19. Time::FromJsTime(1430907555111); // May 2015 for realism
  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. class TestTickClock : public base::TickClock {
  30. public:
  31. TestTickClock() = default;
  32. TestTickClock(const TestTickClock&) = delete;
  33. TestTickClock& operator=(const TestTickClock&) = delete;
  34. ~TestTickClock() override = default;
  35. TimeTicks NowTicks() const override { return now_ticks_; }
  36. void set_now(TimeTicks now) { now_ticks_ = now; }
  37. private:
  38. TimeTicks now_ticks_;
  39. };
  40. // This test exercises the code that computes the "backoff duration" and tests
  41. // BackoffEntrySerializer::SerializeToValue computes the backoff duration of a
  42. // BackoffEntry by subtracting two base::TimeTicks values. Note that
  43. // base::TimeTicks::operator- does not protect against overflow. Because
  44. // SerializeToValue never returns null, its resolution strategy is to default to
  45. // a zero base::TimeDelta when the subtraction would overflow.
  46. TEST(BackoffEntrySerializerTest, SpecialCasesOfBackoffDuration) {
  47. const base::TimeTicks kZeroTicks;
  48. struct TestCase {
  49. base::TimeTicks release_time;
  50. base::TimeTicks timeticks_now;
  51. base::TimeDelta expected_backoff_duration;
  52. };
  53. TestCase test_cases[] = {
  54. // Non-overflowing subtraction works as expected.
  55. {
  56. .release_time = kZeroTicks + base::Microseconds(100),
  57. .timeticks_now = kZeroTicks + base::Microseconds(75),
  58. .expected_backoff_duration = base::Microseconds(25),
  59. },
  60. {
  61. .release_time = kZeroTicks + base::Microseconds(25),
  62. .timeticks_now = kZeroTicks + base::Microseconds(100),
  63. .expected_backoff_duration = base::Microseconds(-75),
  64. },
  65. // Defaults to zero when one of the operands is +/- infinity.
  66. {
  67. .release_time = base::TimeTicks::Min(),
  68. .timeticks_now = kZeroTicks,
  69. .expected_backoff_duration = base::TimeDelta(),
  70. },
  71. {
  72. .release_time = base::TimeTicks::Max(),
  73. .timeticks_now = kZeroTicks,
  74. .expected_backoff_duration = base::TimeDelta(),
  75. },
  76. {
  77. .release_time = kZeroTicks,
  78. .timeticks_now = base::TimeTicks::Min(),
  79. .expected_backoff_duration = base::TimeDelta(),
  80. },
  81. {
  82. .release_time = kZeroTicks,
  83. .timeticks_now = base::TimeTicks::Max(),
  84. .expected_backoff_duration = base::TimeDelta(),
  85. },
  86. // Defaults to zero when both of the operands are +/- infinity.
  87. {
  88. .release_time = base::TimeTicks::Min(),
  89. .timeticks_now = base::TimeTicks::Min(),
  90. .expected_backoff_duration = base::TimeDelta(),
  91. },
  92. {
  93. .release_time = base::TimeTicks::Min(),
  94. .timeticks_now = base::TimeTicks::Max(),
  95. .expected_backoff_duration = base::TimeDelta(),
  96. },
  97. {
  98. .release_time = base::TimeTicks::Max(),
  99. .timeticks_now = base::TimeTicks::Min(),
  100. .expected_backoff_duration = base::TimeDelta(),
  101. },
  102. {
  103. .release_time = base::TimeTicks::Max(),
  104. .timeticks_now = base::TimeTicks::Max(),
  105. .expected_backoff_duration = base::TimeDelta(),
  106. },
  107. // Defaults to zero when the subtraction overflows, even when neither
  108. // operand is infinity.
  109. {
  110. .release_time = base::TimeTicks::Max() - base::Microseconds(1),
  111. .timeticks_now = kZeroTicks + base::Microseconds(-1),
  112. .expected_backoff_duration = base::TimeDelta(),
  113. },
  114. };
  115. size_t test_index = 0;
  116. for (const TestCase& test_case : test_cases) {
  117. SCOPED_TRACE(base::StringPrintf("Running test case #%zu", test_index));
  118. ++test_index;
  119. Time original_time = base::Time::Now();
  120. TestTickClock original_ticks;
  121. original_ticks.set_now(test_case.timeticks_now);
  122. BackoffEntry original(&base_policy, &original_ticks);
  123. // Set the custom release time.
  124. original.SetCustomReleaseTime(test_case.release_time);
  125. base::Value serialized =
  126. BackoffEntrySerializer::SerializeToValue(original, original_time);
  127. // Check that the serialized backoff duration matches our expectation.
  128. const std::string& serialized_backoff_duration_string =
  129. serialized.GetList()[2].GetString();
  130. int64_t serialized_backoff_duration_us;
  131. EXPECT_TRUE(base::StringToInt64(serialized_backoff_duration_string,
  132. &serialized_backoff_duration_us));
  133. base::TimeDelta serialized_backoff_duration =
  134. base::Microseconds(serialized_backoff_duration_us);
  135. EXPECT_EQ(serialized_backoff_duration, test_case.expected_backoff_duration);
  136. }
  137. }
  138. // This test verifies that BackoffEntrySerializer::SerializeToValue will not
  139. // serialize an infinite release time.
  140. //
  141. // In pseudocode, this is how absolute_release_time is computed:
  142. // backoff_duration = release_time - now;
  143. // absolute_release_time = backoff_duration + original_time;
  144. //
  145. // This test induces backoff_duration to be a nonzero duration and directly sets
  146. // original_time as a large value, such that their addition will overflow.
  147. TEST(BackoffEntrySerializerTest, SerializeFiniteReleaseTime) {
  148. const TimeTicks release_time = TimeTicks() + base::Microseconds(5);
  149. const Time original_time = Time::Max() - base::Microseconds(4);
  150. TestTickClock original_ticks;
  151. original_ticks.set_now(TimeTicks());
  152. BackoffEntry original(&base_policy, &original_ticks);
  153. original.SetCustomReleaseTime(release_time);
  154. base::Value serialized =
  155. BackoffEntrySerializer::SerializeToValue(original, original_time);
  156. // Reach into the serialization and check the string-formatted release time.
  157. const std::string& serialized_release_time =
  158. serialized.GetList()[3].GetString();
  159. EXPECT_EQ(serialized_release_time, "0");
  160. // Test that |DeserializeFromValue| notices this zero-valued release time and
  161. // does not take it at face value.
  162. std::unique_ptr<BackoffEntry> deserialized =
  163. BackoffEntrySerializer::DeserializeFromValue(serialized, &base_policy,
  164. &original_ticks, kParseTime);
  165. ASSERT_TRUE(deserialized.get());
  166. EXPECT_EQ(original.GetReleaseTime(), deserialized->GetReleaseTime());
  167. }
  168. TEST(BackoffEntrySerializerTest, SerializeNoFailures) {
  169. Time original_time = Time::Now();
  170. TestTickClock original_ticks;
  171. original_ticks.set_now(TimeTicks::Now());
  172. BackoffEntry original(&base_policy, &original_ticks);
  173. base::Value serialized =
  174. BackoffEntrySerializer::SerializeToValue(original, original_time);
  175. std::unique_ptr<BackoffEntry> deserialized =
  176. BackoffEntrySerializer::DeserializeFromValue(
  177. serialized, &base_policy, &original_ticks, original_time);
  178. ASSERT_TRUE(deserialized.get());
  179. EXPECT_EQ(original.failure_count(), deserialized->failure_count());
  180. EXPECT_EQ(original.GetReleaseTime(), deserialized->GetReleaseTime());
  181. }
  182. // Test that deserialization fails instead of producing an entry with an
  183. // infinite release time. (Regression test for https://crbug.com/1293904)
  184. TEST(BackoffEntrySerializerTest, DeserializeNeverInfiniteReleaseTime) {
  185. base::Value::List serialized;
  186. serialized.Append(2);
  187. serialized.Append(2);
  188. serialized.Append("-9223372036854775807");
  189. serialized.Append("2");
  190. TestTickClock original_ticks;
  191. original_ticks.set_now(base::TimeTicks() + base::Microseconds(-1));
  192. base::Time time_now =
  193. base::Time::FromDeltaSinceWindowsEpoch(base::Microseconds(-1));
  194. std::unique_ptr<BackoffEntry> entry =
  195. BackoffEntrySerializer::DeserializeFromValue(
  196. base::Value(std::move(serialized)), &base_policy, &original_ticks,
  197. time_now);
  198. ASSERT_FALSE(entry);
  199. }
  200. TEST(BackoffEntrySerializerTest, SerializeTimeOffsets) {
  201. Time original_time = Time::FromJsTime(1430907555111); // May 2015 for realism
  202. TestTickClock original_ticks;
  203. BackoffEntry original(&base_policy, &original_ticks);
  204. // 2 errors.
  205. original.InformOfRequest(false);
  206. original.InformOfRequest(false);
  207. base::Value serialized =
  208. BackoffEntrySerializer::SerializeToValue(original, original_time);
  209. {
  210. // Test that immediate deserialization round-trips.
  211. std::unique_ptr<BackoffEntry> deserialized =
  212. BackoffEntrySerializer::DeserializeFromValue(
  213. serialized, &base_policy, &original_ticks, original_time);
  214. ASSERT_TRUE(deserialized.get());
  215. EXPECT_EQ(original.failure_count(), deserialized->failure_count());
  216. EXPECT_EQ(original.GetReleaseTime(), deserialized->GetReleaseTime());
  217. }
  218. {
  219. // Test deserialization when wall clock has advanced but TimeTicks::Now()
  220. // hasn't (e.g. device was rebooted).
  221. Time later_time = original_time + base::Days(1);
  222. std::unique_ptr<BackoffEntry> deserialized =
  223. BackoffEntrySerializer::DeserializeFromValue(
  224. serialized, &base_policy, &original_ticks, later_time);
  225. ASSERT_TRUE(deserialized.get());
  226. EXPECT_EQ(original.failure_count(), deserialized->failure_count());
  227. // Remaining backoff duration continues decreasing while device is off.
  228. // Since TimeTicks::Now() has not advanced, the absolute release time ticks
  229. // will decrease accordingly.
  230. EXPECT_GT(original.GetTimeUntilRelease(),
  231. deserialized->GetTimeUntilRelease());
  232. EXPECT_EQ(original.GetReleaseTime() - base::Days(1),
  233. deserialized->GetReleaseTime());
  234. }
  235. {
  236. // Test deserialization when TimeTicks::Now() has advanced but wall clock
  237. // hasn't (e.g. it's an hour later, but a DST change cancelled that out).
  238. TestTickClock later_ticks;
  239. later_ticks.set_now(TimeTicks() + base::Days(1));
  240. std::unique_ptr<BackoffEntry> deserialized =
  241. BackoffEntrySerializer::DeserializeFromValue(
  242. serialized, &base_policy, &later_ticks, original_time);
  243. ASSERT_TRUE(deserialized.get());
  244. EXPECT_EQ(original.failure_count(), deserialized->failure_count());
  245. // According to the wall clock, no time has passed. So remaining backoff
  246. // duration is preserved, hence the absolute release time ticks increases.
  247. // This isn't ideal - by also serializing the current time and time ticks,
  248. // it would be possible to detect that time has passed but the wall clock
  249. // went backwards, and reduce the remaining backoff duration accordingly,
  250. // however the current implementation does not do this as the benefit would
  251. // be somewhat marginal.
  252. EXPECT_EQ(original.GetTimeUntilRelease(),
  253. deserialized->GetTimeUntilRelease());
  254. EXPECT_EQ(original.GetReleaseTime() + base::Days(1),
  255. deserialized->GetReleaseTime());
  256. }
  257. {
  258. // Test deserialization when both wall clock and TimeTicks::Now() have
  259. // advanced (e.g. it's just later than it used to be).
  260. TestTickClock later_ticks;
  261. later_ticks.set_now(TimeTicks() + base::Days(1));
  262. Time later_time = original_time + base::Days(1);
  263. std::unique_ptr<BackoffEntry> deserialized =
  264. BackoffEntrySerializer::DeserializeFromValue(serialized, &base_policy,
  265. &later_ticks, later_time);
  266. ASSERT_TRUE(deserialized.get());
  267. EXPECT_EQ(original.failure_count(), deserialized->failure_count());
  268. // Since both have advanced by the same amount, the absolute release time
  269. // ticks should be preserved; the remaining backoff duration will have
  270. // decreased of course, since time has passed.
  271. EXPECT_GT(original.GetTimeUntilRelease(),
  272. deserialized->GetTimeUntilRelease());
  273. EXPECT_EQ(original.GetReleaseTime(), deserialized->GetReleaseTime());
  274. }
  275. {
  276. // Test deserialization when wall clock has gone backwards but TimeTicks
  277. // haven't (e.g. the system clock was fast but they fixed it).
  278. EXPECT_LT(base::Seconds(1), original.GetTimeUntilRelease());
  279. Time earlier_time = original_time - base::Seconds(1);
  280. std::unique_ptr<BackoffEntry> deserialized =
  281. BackoffEntrySerializer::DeserializeFromValue(
  282. serialized, &base_policy, &original_ticks, earlier_time);
  283. ASSERT_TRUE(deserialized.get());
  284. EXPECT_EQ(original.failure_count(), deserialized->failure_count());
  285. // If only the absolute wall clock time was serialized, subtracting the
  286. // (decreased) current wall clock time from the serialized wall clock time
  287. // could give very large (incorrect) values for remaining backoff duration.
  288. // But instead the implementation also serializes the remaining backoff
  289. // duration, and doesn't allow the duration to increase beyond it's previous
  290. // value during deserialization. Hence when the wall clock goes backwards
  291. // the remaining backoff duration will be preserved.
  292. EXPECT_EQ(original.GetTimeUntilRelease(),
  293. deserialized->GetTimeUntilRelease());
  294. // Since TimeTicks::Now() hasn't changed, the absolute release time ticks
  295. // will be equal too in this particular case.
  296. EXPECT_EQ(original.GetReleaseTime(), deserialized->GetReleaseTime());
  297. }
  298. }
  299. TEST(BackoffEntrySerializerTest, DeserializeUnknownVersion) {
  300. base::Value::List serialized;
  301. serialized.Append(0); // Format version that never existed
  302. serialized.Append(0); // Failure count
  303. serialized.Append(2.0); // Backoff duration
  304. serialized.Append("1234"); // Absolute release time
  305. auto deserialized = BackoffEntrySerializer::DeserializeFromValue(
  306. base::Value(std::move(serialized)), &base_policy, nullptr, kParseTime);
  307. ASSERT_FALSE(deserialized);
  308. }
  309. TEST(BackoffEntrySerializerTest, DeserializeVersion1) {
  310. base::Value::List serialized;
  311. serialized.Append(SerializationFormatVersion::kVersion1);
  312. serialized.Append(0); // Failure count
  313. serialized.Append(2.0); // Backoff duration in seconds as double
  314. serialized.Append("1234"); // Absolute release time
  315. auto deserialized = BackoffEntrySerializer::DeserializeFromValue(
  316. base::Value(std::move(serialized)), &base_policy, nullptr, kParseTime);
  317. ASSERT_TRUE(deserialized);
  318. }
  319. TEST(BackoffEntrySerializerTest, DeserializeVersion2) {
  320. base::Value::List serialized;
  321. serialized.Append(SerializationFormatVersion::kVersion2);
  322. serialized.Append(0); // Failure count
  323. serialized.Append("2000"); // Backoff duration
  324. serialized.Append("1234"); // Absolute release time
  325. auto deserialized = BackoffEntrySerializer::DeserializeFromValue(
  326. base::Value(std::move(serialized)), &base_policy, nullptr, kParseTime);
  327. ASSERT_TRUE(deserialized);
  328. }
  329. TEST(BackoffEntrySerializerTest, DeserializeVersion2NegativeDuration) {
  330. base::Value::List serialized;
  331. serialized.Append(SerializationFormatVersion::kVersion2);
  332. serialized.Append(0); // Failure count
  333. serialized.Append("-2000"); // Backoff duration
  334. serialized.Append("1234"); // Absolute release time
  335. auto deserialized = BackoffEntrySerializer::DeserializeFromValue(
  336. base::Value(std::move(serialized)), &base_policy, nullptr, kParseTime);
  337. ASSERT_TRUE(deserialized);
  338. }
  339. TEST(BackoffEntrySerializerTest, DeserializeVersion1WrongDurationType) {
  340. base::Value::List serialized;
  341. serialized.Append(SerializationFormatVersion::kVersion1);
  342. serialized.Append(0); // Failure count
  343. serialized.Append("2000"); // Backoff duration in seconds as double
  344. serialized.Append("1234"); // Absolute release time
  345. auto deserialized = BackoffEntrySerializer::DeserializeFromValue(
  346. base::Value(std::move(serialized)), &base_policy, nullptr, kParseTime);
  347. ASSERT_FALSE(deserialized);
  348. }
  349. TEST(BackoffEntrySerializerTest, DeserializeVersion2WrongDurationType) {
  350. base::Value::List serialized;
  351. serialized.Append(SerializationFormatVersion::kVersion2);
  352. serialized.Append(0); // Failure count
  353. serialized.Append(2.0); // Backoff duration
  354. serialized.Append("1234"); // Absolute release time
  355. auto deserialized = BackoffEntrySerializer::DeserializeFromValue(
  356. base::Value(std::move(serialized)), &base_policy, nullptr, kParseTime);
  357. ASSERT_FALSE(deserialized);
  358. }
  359. } // namespace
  360. } // namespace net