1 // Copyright (c) 2011 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 "content/common/inter_process_time_ticks_converter.h" 6 7 #include "base/time/time.h" 8 #include "testing/gtest/include/gtest/gtest.h" 9 10 using base::TimeTicks; 11 12 namespace content { 13 14 namespace { 15 16 struct TestParams { 17 int64 local_lower_bound; 18 int64 remote_lower_bound; 19 int64 remote_upper_bound; 20 int64 local_upper_bound; 21 int64 test_time; 22 int64 test_delta; 23 }; 24 25 struct TestResults { 26 int64 result_time; 27 int32 result_delta; 28 bool is_skew_additive; 29 int64 skew; 30 }; 31 32 TestResults RunTest(const TestParams& params) { 33 TimeTicks local_lower_bound = TimeTicks::FromInternalValue( 34 params.local_lower_bound); 35 TimeTicks local_upper_bound = TimeTicks::FromInternalValue( 36 params.local_upper_bound); 37 TimeTicks remote_lower_bound = TimeTicks::FromInternalValue( 38 params.remote_lower_bound); 39 TimeTicks remote_upper_bound = TimeTicks::FromInternalValue( 40 params.remote_upper_bound); 41 TimeTicks test_time = TimeTicks::FromInternalValue(params.test_time); 42 43 InterProcessTimeTicksConverter converter( 44 LocalTimeTicks::FromTimeTicks(local_lower_bound), 45 LocalTimeTicks::FromTimeTicks(local_upper_bound), 46 RemoteTimeTicks::FromTimeTicks(remote_lower_bound), 47 RemoteTimeTicks::FromTimeTicks(remote_upper_bound)); 48 49 TestResults results; 50 results.result_time = converter.ToLocalTimeTicks( 51 RemoteTimeTicks::FromTimeTicks( 52 test_time)).ToTimeTicks().ToInternalValue(); 53 results.result_delta = converter.ToLocalTimeDelta( 54 RemoteTimeDelta::FromRawDelta(params.test_delta)).ToInt32(); 55 results.is_skew_additive = converter.IsSkewAdditiveForMetrics(); 56 results.skew = converter.GetSkewForMetrics().ToInternalValue(); 57 return results; 58 } 59 60 TEST(InterProcessTimeTicksConverterTest, NullTime) { 61 // Null / zero times should remain null. 62 TestParams p; 63 p.local_lower_bound = 1; 64 p.remote_lower_bound = 2; 65 p.remote_upper_bound = 5; 66 p.local_upper_bound = 6; 67 p.test_time = 0; 68 p.test_delta = 0; 69 TestResults results = RunTest(p); 70 EXPECT_EQ(0, results.result_time); 71 EXPECT_EQ(0, results.result_delta); 72 } 73 74 TEST(InterProcessTimeTicksConverterTest, NoSkew) { 75 // All times are monotonic and centered, so no adjustment should occur. 76 TestParams p; 77 p.local_lower_bound = 1; 78 p.remote_lower_bound = 2; 79 p.remote_upper_bound = 5; 80 p.local_upper_bound = 6; 81 p.test_time = 3; 82 p.test_delta = 1; 83 TestResults results = RunTest(p); 84 EXPECT_EQ(3, results.result_time); 85 EXPECT_EQ(1, results.result_delta); 86 EXPECT_TRUE(results.is_skew_additive); 87 EXPECT_EQ(0, results.skew); 88 } 89 90 TEST(InterProcessTimeTicksConverterTest, OffsetMidpoints) { 91 // All times are monotonic, but not centered. Adjust the |remote_*| times so 92 // they are centered within the |local_*| times. 93 TestParams p; 94 p.local_lower_bound = 1; 95 p.remote_lower_bound = 3; 96 p.remote_upper_bound = 6; 97 p.local_upper_bound = 6; 98 p.test_time = 4; 99 p.test_delta = 1; 100 TestResults results = RunTest(p); 101 EXPECT_EQ(3, results.result_time); 102 EXPECT_EQ(1, results.result_delta); 103 EXPECT_TRUE(results.is_skew_additive); 104 EXPECT_EQ(1, results.skew); 105 } 106 107 TEST(InterProcessTimeTicksConverterTest, DoubleEndedSkew) { 108 // |remote_lower_bound| occurs before |local_lower_bound| and 109 // |remote_upper_bound| occurs after |local_upper_bound|. We must adjust both 110 // bounds and scale down the delta. |test_time| is on the midpoint, so it 111 // doesn't change. The ratio of local time to network time is 1:2, so we scale 112 // |test_delta| to half. 113 TestParams p; 114 p.local_lower_bound = 3; 115 p.remote_lower_bound = 1; 116 p.remote_upper_bound = 9; 117 p.local_upper_bound = 7; 118 p.test_time = 5; 119 p.test_delta = 2; 120 TestResults results = RunTest(p); 121 EXPECT_EQ(5, results.result_time); 122 EXPECT_EQ(1, results.result_delta); 123 EXPECT_FALSE(results.is_skew_additive); 124 } 125 126 TEST(InterProcessTimeTicksConverterTest, FrontEndSkew) { 127 // |remote_upper_bound| is coherent, but |remote_lower_bound| is not. So we 128 // adjust the lower bound and move |test_time| out. The scale factor is 2:3, 129 // but since we use integers, the numbers truncate from 3.33 to 3 and 1.33 130 // to 1. 131 TestParams p; 132 p.local_lower_bound = 3; 133 p.remote_lower_bound = 1; 134 p.remote_upper_bound = 7; 135 p.local_upper_bound = 7; 136 p.test_time = 3; 137 p.test_delta = 2; 138 TestResults results = RunTest(p); 139 EXPECT_EQ(4, results.result_time); 140 EXPECT_EQ(1, results.result_delta); 141 EXPECT_FALSE(results.is_skew_additive); 142 } 143 144 TEST(InterProcessTimeTicksConverterTest, BackEndSkew) { 145 // Like the previous test, but |remote_lower_bound| is coherent and 146 // |remote_upper_bound| is skewed. 147 TestParams p; 148 p.local_lower_bound = 1; 149 p.remote_lower_bound = 1; 150 p.remote_upper_bound = 7; 151 p.local_upper_bound = 5; 152 p.test_time = 3; 153 p.test_delta = 2; 154 TestResults results = RunTest(p); 155 EXPECT_EQ(2, results.result_time); 156 EXPECT_EQ(1, results.result_delta); 157 EXPECT_FALSE(results.is_skew_additive); 158 } 159 160 TEST(InterProcessTimeTicksConverterTest, Instantaneous) { 161 // The bounds are all okay, but the |remote_lower_bound| and 162 // |remote_upper_bound| have the same value. No adjustments should be made and 163 // no divide-by-zero errors should occur. 164 TestParams p; 165 p.local_lower_bound = 1; 166 p.remote_lower_bound = 2; 167 p.remote_upper_bound = 2; 168 p.local_upper_bound = 3; 169 p.test_time = 2; 170 p.test_delta = 0; 171 TestResults results = RunTest(p); 172 EXPECT_EQ(2, results.result_time); 173 EXPECT_EQ(0, results.result_delta); 174 } 175 176 TEST(InterProcessTimeTicksConverterTest, OffsetInstantaneous) { 177 // The bounds are all okay, but the |remote_lower_bound| and 178 // |remote_upper_bound| have the same value and are offset from the midpoint 179 // of |local_lower_bound| and |local_upper_bound|. An offset should be applied 180 // to make the midpoints line up. 181 TestParams p; 182 p.local_lower_bound = 1; 183 p.remote_lower_bound = 3; 184 p.remote_upper_bound = 3; 185 p.local_upper_bound = 3; 186 p.test_time = 3; 187 p.test_delta = 0; 188 TestResults results = RunTest(p); 189 EXPECT_EQ(2, results.result_time); 190 EXPECT_EQ(0, results.result_delta); 191 } 192 193 TEST(InterProcessTimeTicksConverterTest, DisjointInstantaneous) { 194 // |local_lower_bound| and |local_upper_bound| are the same. No matter what 195 // the other values are, they must fit within [local_lower_bound, 196 // local_upper_bound]. So, all of the values should be adjusted so they are 197 // exactly that value. 198 TestParams p; 199 p.local_lower_bound = 1; 200 p.remote_lower_bound = 2; 201 p.remote_upper_bound = 2; 202 p.local_upper_bound = 1; 203 p.test_time = 2; 204 p.test_delta = 0; 205 TestResults results = RunTest(p); 206 EXPECT_EQ(1, results.result_time); 207 EXPECT_EQ(0, results.result_delta); 208 } 209 210 TEST(InterProcessTimeTicksConverterTest, RoundingNearEdges) { 211 // Verify that rounding never causes a value to appear outside the given 212 // |local_*| range. 213 const int kMaxRange = 101; 214 for (int i = 1; i < kMaxRange; ++i) { 215 for (int j = 1; j < kMaxRange; ++j) { 216 TestParams p; 217 p.local_lower_bound = 1; 218 p.remote_lower_bound = 1; 219 p.remote_upper_bound = j; 220 p.local_upper_bound = i; 221 222 p.test_time = 1; 223 p.test_delta = 0; 224 TestResults results = RunTest(p); 225 EXPECT_LE(1, results.result_time); 226 EXPECT_EQ(0, results.result_delta); 227 228 p.test_time = j; 229 p.test_delta = j - 1; 230 results = RunTest(p); 231 EXPECT_GE(i, results.result_time); 232 EXPECT_GE(i - 1, results.result_delta); 233 } 234 } 235 } 236 237 TEST(InterProcessTimeTicksConverterTest, DisjointRanges) { 238 TestParams p; 239 p.local_lower_bound = 10; 240 p.remote_lower_bound = 30; 241 p.remote_upper_bound = 41; 242 p.local_upper_bound = 20; 243 p.test_time = 41; 244 p.test_delta = 0; 245 TestResults results = RunTest(p); 246 EXPECT_EQ(20, results.result_time); 247 EXPECT_EQ(0, results.result_delta); 248 } 249 250 } // anonymous namespace 251 252 } // namespace content 253