Home | History | Annotate | Download | only in net
      1 // Copyright (c) 2013 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 
      5 #include <math.h>
      6 
      7 #include "base/bind.h"
      8 #include "base/bind_helpers.h"
      9 #include "base/compiler_specific.h"
     10 #include "base/message_loop/message_loop.h"
     11 #include "chrome/browser/net/network_time_tracker.h"
     12 #include "content/public/test/test_browser_thread.h"
     13 #include "net/base/network_time_notifier.h"
     14 #include "testing/gtest/include/gtest/gtest.h"
     15 
     16 namespace {
     17 
     18 // These are all in milliseconds.
     19 const int64 kLatency1 = 50;
     20 const int64 kLatency2 = 500;
     21 
     22 // Can not be smaller than 15, it's the NowFromSystemTime() resolution.
     23 const int64 kResolution1 = 17;
     24 const int64 kResolution2 = 177;
     25 
     26 const int64 kPseudoSleepTime1 = 500000001;
     27 const int64 kPseudoSleepTime2 = 1888;
     28 
     29 // A custom tick clock that will return an arbitrary time.
     30 class TestTickClock : public base::TickClock {
     31  public:
     32   explicit TestTickClock(base::TimeTicks* ticks_now) : ticks_now_(ticks_now) {}
     33   virtual ~TestTickClock() {}
     34 
     35   virtual base::TimeTicks NowTicks() OVERRIDE {
     36     return *ticks_now_;
     37   }
     38 
     39  private:
     40   base::TimeTicks* ticks_now_;
     41 };
     42 
     43 }  // namespace
     44 
     45 class NetworkTimeTrackerTest : public testing::Test {
     46  public:
     47   NetworkTimeTrackerTest()
     48       : ui_thread(content::BrowserThread::UI, &message_loop_),
     49         io_thread(content::BrowserThread::IO, &message_loop_),
     50         now_(base::Time::NowFromSystemTime()),
     51         tick_clock_(new TestTickClock(&ticks_now_)),
     52         network_time_notifier_(
     53             new net::NetworkTimeNotifier(
     54                 tick_clock_.PassAs<base::TickClock>())) {}
     55   virtual ~NetworkTimeTrackerTest() {}
     56 
     57   virtual void TearDown() OVERRIDE {
     58     message_loop_.RunUntilIdle();
     59   }
     60 
     61   base::Time Now() const {
     62     return now_ + (ticks_now_ - base::TimeTicks());
     63   }
     64 
     65   base::TimeTicks TicksNow() const {
     66     return ticks_now_;
     67   }
     68 
     69   void AddToTicksNow(int64 ms) {
     70     ticks_now_ += base::TimeDelta::FromMilliseconds(ms);
     71   }
     72 
     73   void StartTracker() {
     74     network_time_tracker_.reset(new NetworkTimeTracker());
     75     network_time_notifier_->AddObserver(
     76         network_time_tracker_->BuildObserverCallback());
     77     message_loop_.RunUntilIdle();
     78   }
     79 
     80   void StopTracker() {
     81     network_time_tracker_.reset();
     82   }
     83 
     84   // Updates the notifier's time with the specified parameters and waits until
     85   // the observers have been updated.
     86   void UpdateNetworkTime(const base::Time& network_time,
     87                          const base::TimeDelta& resolution,
     88                          const base::TimeDelta& latency,
     89                          const base::TimeTicks& post_time) {
     90     message_loop_.PostTask(
     91         FROM_HERE,
     92         base::Bind(&net::NetworkTimeNotifier::UpdateNetworkTime,
     93                    base::Unretained(network_time_notifier_.get()),
     94                    network_time,
     95                    resolution,
     96                    latency,
     97                    post_time));
     98     message_loop_.RunUntilIdle();
     99   }
    100 
    101   // Ensures the network time tracker has a network time and that the
    102   // disparity between the network time version of |ticks_now_| and the actual
    103   // |ticks_now_| value is within the uncertainty (should always be true
    104   // because the network time notifier uses |ticks_now_| for the tick clock).
    105   testing::AssertionResult ValidateExpectedTime() const {
    106     base::Time network_time;
    107     base::TimeDelta uncertainty;
    108     if (!network_time_tracker_->GetNetworkTime(TicksNow(),
    109                                                &network_time,
    110                                                &uncertainty))
    111       return testing::AssertionFailure() << "Failed to get network time.";
    112     if (fabs(static_cast<double>(Now().ToInternalValue() -
    113                                  network_time.ToInternalValue())) >
    114              static_cast<double>(uncertainty.ToInternalValue())) {
    115       return testing::AssertionFailure()
    116           << "Expected network time not within uncertainty.";
    117     }
    118     return testing::AssertionSuccess();
    119   }
    120 
    121   NetworkTimeTracker* network_time_tracker() {
    122     return network_time_tracker_.get();
    123   }
    124 
    125  private:
    126   // Message loop and threads for the tracker's internal logic.
    127   base::MessageLoop message_loop_;
    128   content::TestBrowserThread ui_thread;
    129   content::TestBrowserThread io_thread;
    130 
    131   // Used in building the current time that |tick_clock_| reports. See Now()
    132   // for details.
    133   base::Time now_;
    134   base::TimeTicks ticks_now_;
    135 
    136   // A custom clock that allows arbitrary time delays.
    137   scoped_ptr<TestTickClock> tick_clock_;
    138 
    139   // The network time notifier that receives time updates and posts them to
    140   // the tracker.
    141   scoped_ptr<net::NetworkTimeNotifier> network_time_notifier_;
    142 
    143   // The network time tracker being tested.
    144   scoped_ptr<NetworkTimeTracker> network_time_tracker_;
    145 };
    146 
    147 // Should not return a value before UpdateNetworkTime gets called.
    148 TEST_F(NetworkTimeTrackerTest, Uninitialized) {
    149   base::Time network_time;
    150   base::TimeDelta uncertainty;
    151   StartTracker();
    152   EXPECT_FALSE(network_time_tracker()->GetNetworkTime(base::TimeTicks(),
    153                                                       &network_time,
    154                                                       &uncertainty));
    155 }
    156 
    157 // Verify that the the tracker receives and properly handles updates to the
    158 // network time.
    159 TEST_F(NetworkTimeTrackerTest, NetworkTimeUpdates) {
    160   StartTracker();
    161   UpdateNetworkTime(
    162       Now(),
    163       base::TimeDelta::FromMilliseconds(kResolution1),
    164       base::TimeDelta::FromMilliseconds(kLatency1),
    165       TicksNow());
    166   EXPECT_TRUE(ValidateExpectedTime());
    167 
    168   // Fake a wait for kPseudoSleepTime1 to make sure we keep tracking.
    169   AddToTicksNow(kPseudoSleepTime1);
    170   EXPECT_TRUE(ValidateExpectedTime());
    171 
    172   // Update the time with a new now value and kLatency2.
    173   UpdateNetworkTime(
    174       Now(),
    175       base::TimeDelta::FromMilliseconds(kResolution2),
    176       base::TimeDelta::FromMilliseconds(kLatency2),
    177       TicksNow());
    178 
    179   // Fake a wait for kPseudoSleepTime2 to make sure we keep tracking still.
    180   AddToTicksNow(kPseudoSleepTime2);
    181   EXPECT_TRUE(ValidateExpectedTime());
    182 
    183   // Fake a long delay between update task post time and the network notifier
    184   // updating its network time. The uncertainty should account for the
    185   // disparity.
    186   base::Time old_now = Now();
    187   base::TimeTicks old_ticks = TicksNow();
    188   AddToTicksNow(kPseudoSleepTime2);
    189   UpdateNetworkTime(
    190       old_now,
    191       base::TimeDelta::FromMilliseconds(kResolution2),
    192       base::TimeDelta::FromMilliseconds(kLatency2),
    193       old_ticks);
    194   EXPECT_TRUE(ValidateExpectedTime());
    195 }
    196 
    197 // Starting the tracker after the network time has been set with the notifier
    198 // should update the tracker's time as well.
    199 TEST_F(NetworkTimeTrackerTest, UpdateThenStartTracker) {
    200   UpdateNetworkTime(
    201       Now(),
    202       base::TimeDelta::FromMilliseconds(kResolution1),
    203       base::TimeDelta::FromMilliseconds(kLatency1),
    204       TicksNow());
    205   StartTracker();
    206   EXPECT_TRUE(ValidateExpectedTime());
    207 }
    208 
    209 // Time updates after the tracker has been destroyed should not attempt to
    210 // dereference the destroyed tracker.
    211 TEST_F(NetworkTimeTrackerTest, UpdateAfterTrackerDestroyed) {
    212   StartTracker();
    213   StopTracker();
    214   UpdateNetworkTime(
    215       Now(),
    216       base::TimeDelta::FromMilliseconds(kResolution1),
    217       base::TimeDelta::FromMilliseconds(kLatency1),
    218       TicksNow());
    219 }
    220