#include "net/base/backoff_entry.h"
#include "base/containers/span.h"
#include "base/logging.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/time/tick_clock.h"
#include "base/time/time.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::TimeTicks;
const Time kParseTime =
Time::FromJsTime(1430907555111);
BackoffEntry::Policy base_policy = {
0 ,
1000 ,
2.0 ,
0.0 ,
20000 ,
2000 ,
false
};
class TestTickClock : public base::TickClock {
public:
TestTickClock() = default;
TestTickClock(const TestTickClock&) = delete;
TestTickClock& operator=(const TestTickClock&) = delete;
~TestTickClock() override = default;
TimeTicks NowTicks() const override { return now_ticks_; }
void set_now(TimeTicks now) { now_ticks_ = now; }
private:
TimeTicks now_ticks_;
};
TEST(BackoffEntrySerializerTest, SpecialCasesOfBackoffDuration) {
const base::TimeTicks kZeroTicks;
struct TestCase {
base::TimeTicks release_time;
base::TimeTicks timeticks_now;
base::TimeDelta expected_backoff_duration;
};
TestCase test_cases[] = {
{
.release_time = kZeroTicks + base::Microseconds(100),
.timeticks_now = kZeroTicks + base::Microseconds(75),
.expected_backoff_duration = base::Microseconds(25),
},
{
.release_time = kZeroTicks + base::Microseconds(25),
.timeticks_now = kZeroTicks + base::Microseconds(100),
.expected_backoff_duration = base::Microseconds(-75),
},
{
.release_time = base::TimeTicks::Min(),
.timeticks_now = kZeroTicks,
.expected_backoff_duration = base::TimeDelta(),
},
{
.release_time = base::TimeTicks::Max(),
.timeticks_now = kZeroTicks,
.expected_backoff_duration = base::TimeDelta(),
},
{
.release_time = kZeroTicks,
.timeticks_now = base::TimeTicks::Min(),
.expected_backoff_duration = base::TimeDelta(),
},
{
.release_time = kZeroTicks,
.timeticks_now = base::TimeTicks::Max(),
.expected_backoff_duration = base::TimeDelta(),
},
{
.release_time = base::TimeTicks::Min(),
.timeticks_now = base::TimeTicks::Min(),
.expected_backoff_duration = base::TimeDelta(),
},
{
.release_time = base::TimeTicks::Min(),
.timeticks_now = base::TimeTicks::Max(),
.expected_backoff_duration = base::TimeDelta(),
},
{
.release_time = base::TimeTicks::Max(),
.timeticks_now = base::TimeTicks::Min(),
.expected_backoff_duration = base::TimeDelta(),
},
{
.release_time = base::TimeTicks::Max(),
.timeticks_now = base::TimeTicks::Max(),
.expected_backoff_duration = base::TimeDelta(),
},
{
.release_time = base::TimeTicks::Max() - base::Microseconds(1),
.timeticks_now = kZeroTicks + base::Microseconds(-1),
.expected_backoff_duration = base::TimeDelta(),
},
};
size_t test_index = 0;
for (const TestCase& test_case : test_cases) {
SCOPED_TRACE(base::StringPrintf("Running test case #%zu", test_index));
++test_index;
Time original_time = base::Time::Now();
TestTickClock original_ticks;
original_ticks.set_now(test_case.timeticks_now);
BackoffEntry original(&base_policy, &original_ticks);
original.SetCustomReleaseTime(test_case.release_time);
base::Value::List serialized =
BackoffEntrySerializer::SerializeToList(original, original_time);
const std::string& serialized_backoff_duration_string =
serialized[2].GetString();
int64_t serialized_backoff_duration_us;
EXPECT_TRUE(base::StringToInt64(serialized_backoff_duration_string,
&serialized_backoff_duration_us));
base::TimeDelta serialized_backoff_duration =
base::Microseconds(serialized_backoff_duration_us);
EXPECT_EQ(serialized_backoff_duration, test_case.expected_backoff_duration);
}
}
TEST(BackoffEntrySerializerTest, SerializeFiniteReleaseTime) {
const TimeTicks release_time = TimeTicks() + base::Microseconds(5);
const Time original_time = Time::Max() - base::Microseconds(4);
TestTickClock original_ticks;
original_ticks.set_now(TimeTicks());
BackoffEntry original(&base_policy, &original_ticks);
original.SetCustomReleaseTime(release_time);
base::Value::List serialized =
BackoffEntrySerializer::SerializeToList(original, original_time);
const std::string& serialized_release_time = serialized[3].GetString();
EXPECT_EQ(serialized_release_time, "0");
std::unique_ptr<BackoffEntry> deserialized =
BackoffEntrySerializer::DeserializeFromList(serialized, &base_policy,
&original_ticks, kParseTime);
ASSERT_TRUE(deserialized.get());
EXPECT_EQ(original.GetReleaseTime(), deserialized->GetReleaseTime());
}
TEST(BackoffEntrySerializerTest, SerializeNoFailures) {
Time original_time = Time::Now();
TestTickClock original_ticks;
original_ticks.set_now(TimeTicks::Now());
BackoffEntry original(&base_policy, &original_ticks);
base::Value::List serialized =
BackoffEntrySerializer::SerializeToList(original, original_time);
std::unique_ptr<BackoffEntry> deserialized =
BackoffEntrySerializer::DeserializeFromList(
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, DeserializeNeverInfiniteReleaseTime) {
base::Value::List serialized;
serialized.Append(2);
serialized.Append(2);
serialized.Append("-9223372036854775807");
serialized.Append("2");
TestTickClock original_ticks;
original_ticks.set_now(base::TimeTicks() + base::Microseconds(-1));
base::Time time_now =
base::Time::FromDeltaSinceWindowsEpoch(base::Microseconds(-1));
std::unique_ptr<BackoffEntry> entry =
BackoffEntrySerializer::DeserializeFromList(serialized, &base_policy,
&original_ticks, time_now);
ASSERT_FALSE(entry);
}
TEST(BackoffEntrySerializerTest, SerializeTimeOffsets) {
Time original_time = Time::FromJsTime(1430907555111);
TestTickClock original_ticks;
BackoffEntry original(&base_policy, &original_ticks);
original.InformOfRequest(false);
original.InformOfRequest(false);
base::Value::List serialized =
BackoffEntrySerializer::SerializeToList(original, original_time);
{
std::unique_ptr<BackoffEntry> deserialized =
BackoffEntrySerializer::DeserializeFromList(
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());
}
{
Time later_time = original_time + base::Days(1);
std::unique_ptr<BackoffEntry> deserialized =
BackoffEntrySerializer::DeserializeFromList(
serialized, &base_policy, &original_ticks, later_time);
ASSERT_TRUE(deserialized.get());
EXPECT_EQ(original.failure_count(), deserialized->failure_count());
EXPECT_GT(original.GetTimeUntilRelease(),
deserialized->GetTimeUntilRelease());
EXPECT_EQ(original.GetReleaseTime() - base::Days(1),
deserialized->GetReleaseTime());
}
{
TestTickClock later_ticks;
later_ticks.set_now(TimeTicks() + base::Days(1));
std::unique_ptr<BackoffEntry> deserialized =
BackoffEntrySerializer::DeserializeFromList(
serialized, &base_policy, &later_ticks, original_time);
ASSERT_TRUE(deserialized.get());
EXPECT_EQ(original.failure_count(), deserialized->failure_count());
EXPECT_EQ(original.GetTimeUntilRelease(),
deserialized->GetTimeUntilRelease());
EXPECT_EQ(original.GetReleaseTime() + base::Days(1),
deserialized->GetReleaseTime());
}
{
TestTickClock later_ticks;
later_ticks.set_now(TimeTicks() + base::Days(1));
Time later_time = original_time + base::Days(1);
std::unique_ptr<BackoffEntry> deserialized =
BackoffEntrySerializer::DeserializeFromList(serialized, &base_policy,
&later_ticks, later_time);
ASSERT_TRUE(deserialized.get());
EXPECT_EQ(original.failure_count(), deserialized->failure_count());
EXPECT_GT(original.GetTimeUntilRelease(),
deserialized->GetTimeUntilRelease());
EXPECT_EQ(original.GetReleaseTime(), deserialized->GetReleaseTime());
}
{
EXPECT_LT(base::Seconds(1), original.GetTimeUntilRelease());
Time earlier_time = original_time - base::Seconds(1);
std::unique_ptr<BackoffEntry> deserialized =
BackoffEntrySerializer::DeserializeFromList(
serialized, &base_policy, &original_ticks, earlier_time);
ASSERT_TRUE(deserialized.get());
EXPECT_EQ(original.failure_count(), deserialized->failure_count());
EXPECT_EQ(original.GetTimeUntilRelease(),
deserialized->GetTimeUntilRelease());
EXPECT_EQ(original.GetReleaseTime(), deserialized->GetReleaseTime());
}
}
TEST(BackoffEntrySerializerTest, DeserializeUnknownVersion) {
base::Value::List serialized;
serialized.Append(0);
serialized.Append(0);
serialized.Append(2.0);
serialized.Append("1234");
auto deserialized = BackoffEntrySerializer::DeserializeFromList(
serialized, &base_policy, nullptr, kParseTime);
ASSERT_FALSE(deserialized);
}
TEST(BackoffEntrySerializerTest, DeserializeVersion1) {
base::Value::List serialized;
serialized.Append(SerializationFormatVersion::kVersion1);
serialized.Append(0);
serialized.Append(2.0);
serialized.Append("1234");
auto deserialized = BackoffEntrySerializer::DeserializeFromList(
serialized, &base_policy, nullptr, kParseTime);
ASSERT_TRUE(deserialized);
}
TEST(BackoffEntrySerializerTest, DeserializeVersion2) {
base::Value::List serialized;
serialized.Append(SerializationFormatVersion::kVersion2);
serialized.Append(0);
serialized.Append("2000");
serialized.Append("1234");
auto deserialized = BackoffEntrySerializer::DeserializeFromList(
serialized, &base_policy, nullptr, kParseTime);
ASSERT_TRUE(deserialized);
}
TEST(BackoffEntrySerializerTest, DeserializeVersion2NegativeDuration) {
base::Value::List serialized;
serialized.Append(SerializationFormatVersion::kVersion2);
serialized.Append(0);
serialized.Append("-2000");
serialized.Append("1234");
auto deserialized = BackoffEntrySerializer::DeserializeFromList(
serialized, &base_policy, nullptr, kParseTime);
ASSERT_TRUE(deserialized);
}
TEST(BackoffEntrySerializerTest, DeserializeVersion1WrongDurationType) {
base::Value::List serialized;
serialized.Append(SerializationFormatVersion::kVersion1);
serialized.Append(0);
serialized.Append("2000");
serialized.Append("1234");
auto deserialized = BackoffEntrySerializer::DeserializeFromList(
serialized, &base_policy, nullptr, kParseTime);
ASSERT_FALSE(deserialized);
}
TEST(BackoffEntrySerializerTest, DeserializeVersion2WrongDurationType) {
base::Value::List serialized;
serialized.Append(SerializationFormatVersion::kVersion2);
serialized.Append(0);
serialized.Append(2.0);
serialized.Append("1234");
auto deserialized = BackoffEntrySerializer::DeserializeFromList(
serialized, &base_policy, nullptr, kParseTime);
ASSERT_FALSE(deserialized);
}
}
}