Home | History | Annotate | Download | only in common
      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