Index: net/base/backoff_entry_serializer_unittest.cc |
diff --git a/net/base/backoff_entry_serializer_unittest.cc b/net/base/backoff_entry_serializer_unittest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..9799c06e717f8e3061fd4920c61e6a7b7bd6f271 |
--- /dev/null |
+++ b/net/base/backoff_entry_serializer_unittest.cc |
@@ -0,0 +1,174 @@ |
+// Copyright 2015 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "net/base/backoff_entry.h" |
+ |
+#include "base/logging.h" |
+#include "base/macros.h" |
+#include "base/time/tick_clock.h" |
+#include "base/values.h" |
+#include "net/base/backoff_entry_serializer.h" |
+#include "testing/gtest/include/gtest/gtest.h" |
+ |
+namespace net { |
+ |
+namespace { |
+ |
+using base::Time; |
+using base::TimeDelta; |
+using base::TimeTicks; |
+ |
+BackoffEntry::Policy base_policy = { |
+ 0 /* num_errors_to_ignore */, |
+ 1000 /* initial_delay_ms */, |
+ 2.0 /* multiply_factor */, |
+ 0.0 /* jitter_factor */, |
+ 20000 /* maximum_backoff_ms */, |
+ 2000 /* entry_lifetime_ms */, |
+ false /* always_use_initial_delay */ |
+}; |
+ |
+class TestTickClock : public base::TickClock { |
+ public: |
+ TestTickClock() {} |
+ ~TestTickClock() override {} |
+ |
+ TimeTicks NowTicks() override { return now_ticks_; } |
+ void set_now(TimeTicks now) { now_ticks_ = now; } |
+ |
+ private: |
+ TimeTicks now_ticks_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(TestTickClock); |
+}; |
+ |
+TEST(BackoffEntrySerializerTest, SerializeNoFailures) { |
+ Time original_time = Time::Now(); |
+ TestTickClock original_ticks; |
+ original_ticks.set_now(TimeTicks::Now()); |
+ BackoffEntry original(&base_policy, &original_ticks); |
+ scoped_ptr<base::Value> serialized = |
+ BackoffEntrySerializer::SerializeToValue(original, original_time); |
+ |
+ scoped_ptr<BackoffEntry> deserialized = |
+ BackoffEntrySerializer::DeserializeFromValue(*serialized, &base_policy, |
+ &original_ticks, |
+ original_time); |
+ ASSERT_TRUE(deserialized.get()); |
+ EXPECT_EQ(original.failure_count(), deserialized->failure_count()); |
+ EXPECT_EQ(original.GetReleaseTime(), deserialized->GetReleaseTime()); |
+} |
+ |
+TEST(BackoffEntrySerializerTest, SerializeTimeOffsets) { |
+ Time original_time = Time::FromJsTime(1430907555111); // May 2015 for realism |
+ TestTickClock original_ticks; |
+ BackoffEntry original(&base_policy, &original_ticks); |
+ // 2 errors. |
+ original.InformOfRequest(false); |
+ original.InformOfRequest(false); |
+ scoped_ptr<base::Value> serialized = |
+ BackoffEntrySerializer::SerializeToValue(original, original_time); |
+ |
+ { |
+ // Test that immediate deserialization round-trips. |
+ scoped_ptr<BackoffEntry> deserialized = |
+ BackoffEntrySerializer::DeserializeFromValue(*serialized, &base_policy, |
+ &original_ticks, |
+ original_time); |
+ ASSERT_TRUE(deserialized.get()); |
+ EXPECT_EQ(original.failure_count(), deserialized->failure_count()); |
+ EXPECT_EQ(original.GetReleaseTime(), deserialized->GetReleaseTime()); |
+ } |
+ |
+ { |
+ // Test deserialization when wall clock has advanced but TimeTicks::Now() |
+ // hasn't (e.g. device was rebooted). |
+ Time later_time = original_time + TimeDelta::FromDays(1); |
+ scoped_ptr<BackoffEntry> deserialized = |
+ BackoffEntrySerializer::DeserializeFromValue(*serialized, &base_policy, |
+ &original_ticks, |
+ later_time); |
+ ASSERT_TRUE(deserialized.get()); |
+ EXPECT_EQ(original.failure_count(), deserialized->failure_count()); |
+ // Remaining backoff duration continues decreasing while device is off. |
+ // Since TimeTicks::Now() has not advanced, the absolute release time ticks |
+ // will decrease accordingly. |
+ EXPECT_GT(original.GetTimeUntilRelease(), |
+ deserialized->GetTimeUntilRelease()); |
+ EXPECT_EQ(original.GetReleaseTime() - TimeDelta::FromDays(1), |
+ deserialized->GetReleaseTime()); |
+ } |
+ |
+ { |
+ // Test deserialization when TimeTicks::Now() has advanced but wall clock |
+ // hasn't (e.g. it's an hour later, but a DST change cancelled that out). |
+ TestTickClock later_ticks; |
+ later_ticks.set_now(TimeTicks() + TimeDelta::FromDays(1)); |
+ scoped_ptr<BackoffEntry> deserialized = |
+ BackoffEntrySerializer::DeserializeFromValue(*serialized, &base_policy, |
+ &later_ticks, |
+ original_time); |
+ ASSERT_TRUE(deserialized.get()); |
+ EXPECT_EQ(original.failure_count(), deserialized->failure_count()); |
+ // According to the wall clock, no time has passed. So remaining backoff |
+ // duration is preserved, hence the absolute release time ticks increases. |
+ // This isn't ideal - by also serializing the current time and time ticks, |
+ // it would be possible to detect that time has passed but the wall clock |
+ // went backwards, and reduce the remaining backoff duration accordingly, |
+ // however the current implementation does not do this as the benefit would |
+ // be somewhat marginal. |
+ EXPECT_EQ(original.GetTimeUntilRelease(), |
+ deserialized->GetTimeUntilRelease()); |
+ EXPECT_EQ(original.GetReleaseTime() + TimeDelta::FromDays(1), |
+ deserialized->GetReleaseTime()); |
+ } |
+ |
+ { |
+ // Test deserialization when both wall clock and TimeTicks::Now() have |
+ // advanced (e.g. it's just later than it used to be). |
+ TestTickClock later_ticks; |
+ later_ticks.set_now(TimeTicks() + TimeDelta::FromDays(1)); |
+ Time later_time = original_time + TimeDelta::FromDays(1); |
+ scoped_ptr<BackoffEntry> deserialized = |
+ BackoffEntrySerializer::DeserializeFromValue(*serialized, &base_policy, |
+ &later_ticks, later_time); |
+ ASSERT_TRUE(deserialized.get()); |
+ EXPECT_EQ(original.failure_count(), deserialized->failure_count()); |
+ // Since both have advanced by the same amount, the absolute release time |
+ // ticks should be preserved; the remaining backoff duration will have |
+ // decreased of course, since time has passed. |
+ EXPECT_GT(original.GetTimeUntilRelease(), |
+ deserialized->GetTimeUntilRelease()); |
+ EXPECT_EQ(original.GetReleaseTime(), deserialized->GetReleaseTime()); |
+ } |
+ |
+ { |
+ // Test deserialization when wall clock has gone backwards but TimeTicks |
+ // haven't (e.g. the system clock was fast but they fixed it). |
+ EXPECT_LT(TimeDelta::FromSeconds(1), original.GetTimeUntilRelease()); |
+ Time earlier_time = original_time - TimeDelta::FromSeconds(1); |
+ scoped_ptr<BackoffEntry> deserialized = |
+ BackoffEntrySerializer::DeserializeFromValue(*serialized, &base_policy, |
+ &original_ticks, |
+ earlier_time); |
+ ASSERT_TRUE(deserialized.get()); |
+ EXPECT_EQ(original.failure_count(), deserialized->failure_count()); |
+ // If only the absolute wall clock time was serialized, subtracting the |
+ // (decreased) current wall clock time from the serialized wall clock time |
+ // could give very large (incorrect) values for remaining backoff duration. |
+ // But instead the implementation also serializes the remaining backoff |
+ // duration, and doesn't allow the duration to increase beyond it's previous |
+ // value during deserialization. Hence when the wall clock goes backwards |
+ // the remaining backoff duration will be preserved. |
+ EXPECT_EQ(original.GetTimeUntilRelease(), |
+ deserialized->GetTimeUntilRelease()); |
+ // Since TimeTicks::Now() hasn't changed, the absolute release time ticks |
+ // will be equal too in this particular case. |
+ EXPECT_EQ(original.GetReleaseTime(), deserialized->GetReleaseTime()); |
+ } |
+} |
+ |
+} // namespace |
+ |
+} // namespace net |