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