1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Use of this source code is governed by a BSD-style license that can be 3ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// found in the LICENSE file. 4ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 5ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "net/base/backoff_entry.h" 6ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "testing/gtest/include/gtest/gtest.h" 7ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 8ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsennamespace { 9ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 10ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenusing base::TimeDelta; 11ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenusing base::TimeTicks; 12ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenusing net::BackoffEntry; 13ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 14ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenBackoffEntry::Policy base_policy = { 0, 1000, 2.0, 0.0, 20000, 2000 }; 15ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 16ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenclass TestBackoffEntry : public BackoffEntry { 17ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen public: 18ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen explicit TestBackoffEntry(const Policy* const policy) 19ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen : BackoffEntry(policy), 20ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen now_(TimeTicks()) { 21ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Work around initialization in constructor not picking up 22ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // fake time. 23ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SetCustomReleaseTime(TimeTicks()); 24ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 25ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 26ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen virtual ~TestBackoffEntry() {} 27ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 28ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen virtual TimeTicks GetTimeNow() const { 29ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return now_; 30ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 31ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 32ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen void set_now(const TimeTicks& now) { 33ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen now_ = now; 34ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 35ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 36ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen private: 37ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen TimeTicks now_; 38ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 39ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DISALLOW_COPY_AND_ASSIGN(TestBackoffEntry); 40ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}; 41ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 42ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenTEST(BackoffEntryTest, BaseTest) { 43ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen TestBackoffEntry entry(&base_policy); 44ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_FALSE(entry.ShouldRejectRequest()); 45ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 46ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen entry.InformOfRequest(false); 47ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_TRUE(entry.ShouldRejectRequest()); 48ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 49ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 50ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenTEST(BackoffEntryTest, CanDiscardNeverExpires) { 51ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen BackoffEntry::Policy never_expires_policy = base_policy; 52ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen never_expires_policy.entry_lifetime_ms = -1; 53ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen TestBackoffEntry never_expires(&never_expires_policy); 54ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_FALSE(never_expires.CanDiscard()); 55ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen never_expires.set_now(TimeTicks() + TimeDelta::FromDays(100)); 56ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_FALSE(never_expires.CanDiscard()); 57ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 58ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 59ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenTEST(BackoffEntryTest, CanDiscard) { 60ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen TestBackoffEntry entry(&base_policy); 61ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Because lifetime is non-zero, we shouldn't be able to discard yet. 62ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_FALSE(entry.CanDiscard()); 63ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 64ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Test the "being used" case. 65ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen entry.InformOfRequest(false); 66ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_FALSE(entry.CanDiscard()); 67ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 68ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Test the case where there are errors but we can time out. 69ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen entry.set_now( 70ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen entry.GetReleaseTime() + TimeDelta::FromMilliseconds(1)); 71ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_FALSE(entry.CanDiscard()); 72ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen entry.set_now(entry.GetReleaseTime() + TimeDelta::FromMilliseconds( 73ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen base_policy.maximum_backoff_ms + 1)); 74ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_TRUE(entry.CanDiscard()); 75ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 76ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Test the final case (no errors, dependent only on specified lifetime). 77ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen entry.set_now(entry.GetReleaseTime() + TimeDelta::FromMilliseconds( 78ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen base_policy.entry_lifetime_ms - 1)); 79ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen entry.InformOfRequest(true); 80ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_FALSE(entry.CanDiscard()); 81ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen entry.set_now(entry.GetReleaseTime() + TimeDelta::FromMilliseconds( 82ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen base_policy.entry_lifetime_ms)); 83ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_TRUE(entry.CanDiscard()); 84ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 85ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 86ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenTEST(BackoffEntryTest, CanDiscardNotStored) { 87ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen BackoffEntry::Policy no_store_policy = base_policy; 88ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen no_store_policy.entry_lifetime_ms = 0; 89ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen TestBackoffEntry not_stored(&no_store_policy); 90ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_TRUE(not_stored.CanDiscard()); 91ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 92ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 93ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenTEST(BackoffEntryTest, ShouldIgnoreFirstTwo) { 94ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen BackoffEntry::Policy lenient_policy = base_policy; 95ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen lenient_policy.num_errors_to_ignore = 2; 96ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 97ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen BackoffEntry entry(&lenient_policy); 98ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen entry.InformOfRequest(false); 99ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_FALSE(entry.ShouldRejectRequest()); 100ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen entry.InformOfRequest(false); 101ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_FALSE(entry.ShouldRejectRequest()); 102ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen entry.InformOfRequest(false); 103ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_TRUE(entry.ShouldRejectRequest()); 104ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 105ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 106ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenTEST(BackoffEntryTest, ReleaseTimeCalculation) { 107ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen TestBackoffEntry entry(&base_policy); 108ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 109ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // With zero errors, should return "now". 110ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen TimeTicks result = entry.GetReleaseTime(); 111ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_EQ(entry.GetTimeNow(), result); 112ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 113ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // 1 error. 114ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen entry.InformOfRequest(false); 115ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen result = entry.GetReleaseTime(); 116ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_EQ(entry.GetTimeNow() + TimeDelta::FromMilliseconds(1000), result); 117ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 118ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // 2 errors. 119ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen entry.InformOfRequest(false); 120ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen result = entry.GetReleaseTime(); 121ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_EQ(entry.GetTimeNow() + TimeDelta::FromMilliseconds(2000), result); 122ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 123ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // 3 errors. 124ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen entry.InformOfRequest(false); 125ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen result = entry.GetReleaseTime(); 126ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_EQ(entry.GetTimeNow() + TimeDelta::FromMilliseconds(4000), result); 127ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 128ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // 6 errors (to check it doesn't pass maximum). 129ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen entry.InformOfRequest(false); 130ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen entry.InformOfRequest(false); 131ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen entry.InformOfRequest(false); 132ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen result = entry.GetReleaseTime(); 133ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_EQ(entry.GetTimeNow() + TimeDelta::FromMilliseconds(20000), result); 134ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 135ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 136ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenTEST(BackoffEntryTest, ReleaseTimeCalculationWithJitter) { 137ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (int i = 0; i < 10; ++i) { 138ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen BackoffEntry::Policy jittery_policy = base_policy; 139ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen jittery_policy.jitter_factor = 0.2; 140ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 141ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen TestBackoffEntry entry(&jittery_policy); 142ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 143ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen entry.InformOfRequest(false); 144ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen entry.InformOfRequest(false); 145ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen entry.InformOfRequest(false); 146ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen TimeTicks result = entry.GetReleaseTime(); 147ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_LE(entry.GetTimeNow() + TimeDelta::FromMilliseconds(3200), result); 148ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_GE(entry.GetTimeNow() + TimeDelta::FromMilliseconds(4000), result); 149ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 150ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 151ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 152ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenTEST(BackoffEntryTest, FailureThenSuccess) { 153ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen TestBackoffEntry entry(&base_policy); 154ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 155ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Failure count 1, establishes horizon. 156ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen entry.InformOfRequest(false); 157ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen TimeTicks release_time = entry.GetReleaseTime(); 158ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_EQ(TimeTicks() + TimeDelta::FromMilliseconds(1000), release_time); 159ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 160ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Success, failure count 0, should not advance past 161ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // the horizon that was already set. 162ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen entry.set_now(release_time - TimeDelta::FromMilliseconds(200)); 163ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen entry.InformOfRequest(true); 164ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_EQ(release_time, entry.GetReleaseTime()); 165ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 166ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Failure, failure count 1. 167ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen entry.InformOfRequest(false); 168ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_EQ(release_time + TimeDelta::FromMilliseconds(800), 169ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen entry.GetReleaseTime()); 170ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 171ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 172ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenTEST(BackoffEntryTest, RetainCustomHorizon) { 173ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen TestBackoffEntry custom(&base_policy); 174ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen TimeTicks custom_horizon = TimeTicks() + TimeDelta::FromDays(3); 175ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen custom.SetCustomReleaseTime(custom_horizon); 176ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen custom.InformOfRequest(false); 177ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen custom.InformOfRequest(true); 178ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen custom.set_now(TimeTicks() + TimeDelta::FromDays(2)); 179ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen custom.InformOfRequest(false); 180ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen custom.InformOfRequest(true); 181ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_EQ(custom_horizon, custom.GetReleaseTime()); 182ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 183ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Now check that once we are at or past the custom horizon, 184ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // we get normal behavior. 185ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen custom.set_now(TimeTicks() + TimeDelta::FromDays(3)); 186ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen custom.InformOfRequest(false); 187ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_EQ( 188ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen TimeTicks() + TimeDelta::FromDays(3) + TimeDelta::FromMilliseconds(1000), 189ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen custom.GetReleaseTime()); 190ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 191ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 192ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenTEST(BackoffEntryTest, RetainCustomHorizonWhenInitialErrorsIgnored) { 193ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Regression test for a bug discovered during code review. 194ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen BackoffEntry::Policy lenient_policy = base_policy; 195ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen lenient_policy.num_errors_to_ignore = 1; 196ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen TestBackoffEntry custom(&lenient_policy); 197ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen TimeTicks custom_horizon = TimeTicks() + TimeDelta::FromDays(3); 198ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen custom.SetCustomReleaseTime(custom_horizon); 199ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen custom.InformOfRequest(false); // This must not reset the horizon. 200ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXPECT_EQ(custom_horizon, custom.GetReleaseTime()); 201ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 202ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 203ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} // namespace 204