summaryrefslogtreecommitdiffstats
path: root/components/network_time/network_time_tracker_unittest.cc
blob: b2352c0a697140d8d390ee674949934902fed93a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
// Copyright 2014 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 "components/network_time/network_time_tracker.h"

#include <math.h>

#include "base/compiler_specific.h"
#include "base/prefs/testing_pref_service.h"
#include "base/time/tick_clock.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace network_time {

namespace {

// These are all in milliseconds.
const int64 kLatency1 = 50;
const int64 kLatency2 = 500;

// Can not be smaller than 15, it's the NowFromSystemTime() resolution.
const int64 kResolution1 = 17;
const int64 kResolution2 = 177;

const int64 kPseudoSleepTime1 = 500000001;
const int64 kPseudoSleepTime2 = 1888;

// A custom tick clock that will return an arbitrary time.
class TestTickClock : public base::TickClock {
 public:
  explicit TestTickClock(base::TimeTicks* ticks_now) : ticks_now_(ticks_now) {}
  ~TestTickClock() override {}

  base::TimeTicks NowTicks() override { return *ticks_now_; }

 private:
  base::TimeTicks* ticks_now_;
};

}  // namespace

class NetworkTimeTrackerTest : public testing::Test {
 public:
  ~NetworkTimeTrackerTest() override {}

  void SetUp() override {
    NetworkTimeTracker::RegisterPrefs(pref_service_.registry());

    now_ = base::Time::NowFromSystemTime();
    network_time_tracker_.reset(new NetworkTimeTracker(
        scoped_ptr<base::TickClock>(new TestTickClock(&ticks_now_)),
        &pref_service_));
  }

  base::Time Now() const {
    return now_ + (ticks_now_ - base::TimeTicks());
  }

  base::TimeTicks TicksNow() const {
    return ticks_now_;
  }

  void AddToTicksNow(int64 ms) {
    ticks_now_ += base::TimeDelta::FromMilliseconds(ms);
  }

  // Updates the notifier's time with the specified parameters.
  void UpdateNetworkTime(const base::Time& network_time,
                         const base::TimeDelta& resolution,
                         const base::TimeDelta& latency,
                         const base::TimeTicks& post_time) {
    network_time_tracker_->UpdateNetworkTime(
        network_time, resolution, latency, post_time);
  }

  // Ensures the network time tracker has a network time and that the
  // disparity between the network time version of |ticks_now_| and the actual
  // |ticks_now_| value is within the uncertainty (should always be true
  // because the network time notifier uses |ticks_now_| for the tick clock).
  testing::AssertionResult ValidateExpectedTime() const {
    base::Time network_time;
    base::TimeDelta uncertainty;
    if (!network_time_tracker_->GetNetworkTime(TicksNow(),
                                               &network_time,
                                               &uncertainty))
      return testing::AssertionFailure() << "Failed to get network time.";
    if (fabs(static_cast<double>(Now().ToInternalValue() -
                                 network_time.ToInternalValue())) >
             static_cast<double>(uncertainty.ToInternalValue())) {
      return testing::AssertionFailure()
          << "Expected network time not within uncertainty.";
    }
    return testing::AssertionSuccess();
  }

  NetworkTimeTracker* network_time_tracker() {
    return network_time_tracker_.get();
  }

 private:
  // Used in building the current time that TestTickClock reports. See Now()
  // for details.
  base::Time now_;
  base::TimeTicks ticks_now_;

  TestingPrefServiceSimple pref_service_;

  // The network time tracker being tested.
  scoped_ptr<NetworkTimeTracker> network_time_tracker_;
};

// Should not return a value before UpdateNetworkTime gets called.
TEST_F(NetworkTimeTrackerTest, Uninitialized) {
  base::Time network_time;
  base::TimeDelta uncertainty;
  EXPECT_FALSE(network_time_tracker()->GetNetworkTime(base::TimeTicks(),
                                                      &network_time,
                                                      &uncertainty));
}

// Verify that the the tracker receives and properly handles updates to the
// network time.
TEST_F(NetworkTimeTrackerTest, NetworkTimeUpdates) {
  UpdateNetworkTime(
      Now(),
      base::TimeDelta::FromMilliseconds(kResolution1),
      base::TimeDelta::FromMilliseconds(kLatency1),
      TicksNow());
  EXPECT_TRUE(ValidateExpectedTime());

  // Fake a wait for kPseudoSleepTime1 to make sure we keep tracking.
  AddToTicksNow(kPseudoSleepTime1);
  EXPECT_TRUE(ValidateExpectedTime());

  // Update the time with a new now value and kLatency2.
  UpdateNetworkTime(
      Now(),
      base::TimeDelta::FromMilliseconds(kResolution2),
      base::TimeDelta::FromMilliseconds(kLatency2),
      TicksNow());

  // Fake a wait for kPseudoSleepTime2 to make sure we keep tracking still.
  AddToTicksNow(kPseudoSleepTime2);
  EXPECT_TRUE(ValidateExpectedTime());

  // Fake a long delay between update task post time and the network notifier
  // updating its network time. The uncertainty should account for the
  // disparity.
  base::Time old_now = Now();
  base::TimeTicks old_ticks = TicksNow();
  AddToTicksNow(kPseudoSleepTime2);
  UpdateNetworkTime(
      old_now,
      base::TimeDelta::FromMilliseconds(kResolution2),
      base::TimeDelta::FromMilliseconds(kLatency2),
      old_ticks);
  EXPECT_TRUE(ValidateExpectedTime());
}

}  // namespace network_time