1*6777b538SAndroid Build Coastguard Worker// Copyright 2021 The Chromium Authors 2*6777b538SAndroid Build Coastguard Worker// Use of this source code is governed by a BSD-style license that can be 3*6777b538SAndroid Build Coastguard Worker// found in the LICENSE file. 4*6777b538SAndroid Build Coastguard Worker 5*6777b538SAndroid Build Coastguard Worker#include "base/time/time.h" 6*6777b538SAndroid Build Coastguard Worker 7*6777b538SAndroid Build Coastguard Worker#include "base/test/gtest_util.h" 8*6777b538SAndroid Build Coastguard Worker#include "testing/gtest/include/gtest/gtest.h" 9*6777b538SAndroid Build Coastguard Worker 10*6777b538SAndroid Build Coastguard Workernamespace { 11*6777b538SAndroid Build Coastguard Worker 12*6777b538SAndroid Build Coastguard Workerclass ScopedTimebase { 13*6777b538SAndroid Build Coastguard Worker public: 14*6777b538SAndroid Build Coastguard Worker explicit ScopedTimebase(mach_timebase_info_data_t timebase) { 15*6777b538SAndroid Build Coastguard Worker orig_timebase_ = base::TimeTicks::SetMachTimebaseInfoForTesting(timebase); 16*6777b538SAndroid Build Coastguard Worker } 17*6777b538SAndroid Build Coastguard Worker 18*6777b538SAndroid Build Coastguard Worker ScopedTimebase(const ScopedTimebase&) = delete; 19*6777b538SAndroid Build Coastguard Worker 20*6777b538SAndroid Build Coastguard Worker ScopedTimebase& operator=(const ScopedTimebase&) = delete; 21*6777b538SAndroid Build Coastguard Worker 22*6777b538SAndroid Build Coastguard Worker ~ScopedTimebase() { 23*6777b538SAndroid Build Coastguard Worker base::TimeTicks::SetMachTimebaseInfoForTesting(orig_timebase_); 24*6777b538SAndroid Build Coastguard Worker } 25*6777b538SAndroid Build Coastguard Worker 26*6777b538SAndroid Build Coastguard Worker private: 27*6777b538SAndroid Build Coastguard Worker mach_timebase_info_data_t orig_timebase_; 28*6777b538SAndroid Build Coastguard Worker}; 29*6777b538SAndroid Build Coastguard Worker 30*6777b538SAndroid Build Coastguard Workermach_timebase_info_data_t kIntelTimebase = {1, 1}; 31*6777b538SAndroid Build Coastguard Worker 32*6777b538SAndroid Build Coastguard Worker// A sample (not definitive) timebase for M1. 33*6777b538SAndroid Build Coastguard Workermach_timebase_info_data_t kM1Timebase = {125, 3}; 34*6777b538SAndroid Build Coastguard Worker 35*6777b538SAndroid Build Coastguard Worker} // namespace 36*6777b538SAndroid Build Coastguard Worker 37*6777b538SAndroid Build Coastguard Workernamespace base { 38*6777b538SAndroid Build Coastguard Workernamespace { 39*6777b538SAndroid Build Coastguard Worker 40*6777b538SAndroid Build Coastguard Workerbase::Time NoonOnDate(int year, int month, int day) { 41*6777b538SAndroid Build Coastguard Worker const base::Time::Exploded exploded = { 42*6777b538SAndroid Build Coastguard Worker .year = year, .month = month, .day_of_month = day, .hour = 12}; 43*6777b538SAndroid Build Coastguard Worker base::Time imploded; 44*6777b538SAndroid Build Coastguard Worker CHECK(base::Time::FromUTCExploded(exploded, &imploded)); 45*6777b538SAndroid Build Coastguard Worker return imploded; 46*6777b538SAndroid Build Coastguard Worker} 47*6777b538SAndroid Build Coastguard Worker 48*6777b538SAndroid Build Coastguard Workervoid CheckRoundTrip(int y, int m, int d) { 49*6777b538SAndroid Build Coastguard Worker base::Time original = NoonOnDate(y, m, d); 50*6777b538SAndroid Build Coastguard Worker base::Time roundtrip = Time::FromNSDate(original.ToNSDate()); 51*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(original, roundtrip); 52*6777b538SAndroid Build Coastguard Worker} 53*6777b538SAndroid Build Coastguard Worker 54*6777b538SAndroid Build Coastguard WorkerTEST(TimeMacTest, RoundTripNSDate) { 55*6777b538SAndroid Build Coastguard Worker CheckRoundTrip(1911, 12, 14); 56*6777b538SAndroid Build Coastguard Worker CheckRoundTrip(1924, 9, 28); 57*6777b538SAndroid Build Coastguard Worker CheckRoundTrip(1926, 5, 12); 58*6777b538SAndroid Build Coastguard Worker CheckRoundTrip(1969, 7, 24); 59*6777b538SAndroid Build Coastguard Worker} 60*6777b538SAndroid Build Coastguard Worker 61*6777b538SAndroid Build Coastguard WorkerTEST(TimeMacTest, MachTimeToMicrosecondsIntelTimebase) { 62*6777b538SAndroid Build Coastguard Worker ScopedTimebase timebase(kIntelTimebase); 63*6777b538SAndroid Build Coastguard Worker 64*6777b538SAndroid Build Coastguard Worker // Perform the conversion. 65*6777b538SAndroid Build Coastguard Worker uint64_t kArbitraryTicks = 59090101000; 66*6777b538SAndroid Build Coastguard Worker TimeDelta result = TimeDelta::FromMachTime(kArbitraryTicks); 67*6777b538SAndroid Build Coastguard Worker 68*6777b538SAndroid Build Coastguard Worker // With Intel the output should be the input. 69*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(Nanoseconds(kArbitraryTicks), result); 70*6777b538SAndroid Build Coastguard Worker} 71*6777b538SAndroid Build Coastguard Worker 72*6777b538SAndroid Build Coastguard WorkerTEST(TimeMacTest, MachTimeToMicrosecondsM1Timebase) { 73*6777b538SAndroid Build Coastguard Worker ScopedTimebase timebase(kM1Timebase); 74*6777b538SAndroid Build Coastguard Worker 75*6777b538SAndroid Build Coastguard Worker // Use a tick count that's divisible by 3. 76*6777b538SAndroid Build Coastguard Worker const uint64_t kArbitraryTicks = 92738127000; 77*6777b538SAndroid Build Coastguard Worker TimeDelta result = TimeDelta::FromMachTime(kArbitraryTicks); 78*6777b538SAndroid Build Coastguard Worker 79*6777b538SAndroid Build Coastguard Worker const uint64_t kExpectedResult = 80*6777b538SAndroid Build Coastguard Worker kArbitraryTicks * kM1Timebase.numer / kM1Timebase.denom; 81*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(Nanoseconds(kExpectedResult), result); 82*6777b538SAndroid Build Coastguard Worker} 83*6777b538SAndroid Build Coastguard Worker 84*6777b538SAndroid Build Coastguard Worker// Tests MachTimeToMicroseconds when 85*6777b538SAndroid Build Coastguard Worker// mach_timebase_info_data_t.numer and mach_timebase_info_data_t.denom 86*6777b538SAndroid Build Coastguard Worker// are equal. 87*6777b538SAndroid Build Coastguard WorkerTEST(TimeMacTest, MachTimeToMicrosecondsEqualTimebaseMembers) { 88*6777b538SAndroid Build Coastguard Worker // These members would produce overflow but don't because 89*6777b538SAndroid Build Coastguard Worker // MachTimeToMicroseconds should skip the timebase conversion 90*6777b538SAndroid Build Coastguard Worker // when they're equal. 91*6777b538SAndroid Build Coastguard Worker ScopedTimebase timebase({UINT_MAX, UINT_MAX}); 92*6777b538SAndroid Build Coastguard Worker 93*6777b538SAndroid Build Coastguard Worker uint64_t kArbitraryTicks = 175920053729; 94*6777b538SAndroid Build Coastguard Worker TimeDelta result = TimeDelta::FromMachTime(kArbitraryTicks); 95*6777b538SAndroid Build Coastguard Worker 96*6777b538SAndroid Build Coastguard Worker // With a unity timebase the output should be the input. 97*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(Nanoseconds(kArbitraryTicks), result); 98*6777b538SAndroid Build Coastguard Worker} 99*6777b538SAndroid Build Coastguard Worker 100*6777b538SAndroid Build Coastguard WorkerTEST(TimeMacTest, MachTimeToMicrosecondsOverflowDetection) { 101*6777b538SAndroid Build Coastguard Worker const uint32_t kArbitraryNumer = 1234567; 102*6777b538SAndroid Build Coastguard Worker ScopedTimebase timebase({kArbitraryNumer, 1}); 103*6777b538SAndroid Build Coastguard Worker 104*6777b538SAndroid Build Coastguard Worker // Expect an overflow. 105*6777b538SAndroid Build Coastguard Worker EXPECT_CHECK_DEATH( 106*6777b538SAndroid Build Coastguard Worker TimeDelta::FromMachTime(std::numeric_limits<uint64_t>::max())); 107*6777b538SAndroid Build Coastguard Worker} 108*6777b538SAndroid Build Coastguard Worker 109*6777b538SAndroid Build Coastguard Worker// Tests that there's no overflow in MachTimeToMicroseconds even with 110*6777b538SAndroid Build Coastguard Worker// std::numeric_limits<uint64_t>::max() ticks on Intel. 111*6777b538SAndroid Build Coastguard WorkerTEST(TimeMacTest, MachTimeToMicrosecondsNoOverflowIntel) { 112*6777b538SAndroid Build Coastguard Worker ScopedTimebase timebase(kIntelTimebase); 113*6777b538SAndroid Build Coastguard Worker 114*6777b538SAndroid Build Coastguard Worker // The incoming Mach time ticks are on the order of nanoseconds while the 115*6777b538SAndroid Build Coastguard Worker // return result is microseconds. Even though we're passing in the largest 116*6777b538SAndroid Build Coastguard Worker // tick count the result should be orders of magnitude smaller. On Intel the 117*6777b538SAndroid Build Coastguard Worker // mapping from ticks to nanoseconds is 1:1 so we wouldn't ever expect an 118*6777b538SAndroid Build Coastguard Worker // overflow when applying the timebase conversion. 119*6777b538SAndroid Build Coastguard Worker TimeDelta::FromMachTime(std::numeric_limits<uint64_t>::max()); 120*6777b538SAndroid Build Coastguard Worker} 121*6777b538SAndroid Build Coastguard Worker 122*6777b538SAndroid Build Coastguard Worker// Tests that there's no overflow in MachTimeToMicroseconds even with 123*6777b538SAndroid Build Coastguard Worker// std::numeric_limits<uint64_t>::max() ticks on M1. 124*6777b538SAndroid Build Coastguard WorkerTEST(TimeMacTest, MachTimeToMicrosecondsNoOverflowM1) { 125*6777b538SAndroid Build Coastguard Worker ScopedTimebase timebase(kM1Timebase); 126*6777b538SAndroid Build Coastguard Worker 127*6777b538SAndroid Build Coastguard Worker // The incoming Mach time ticks are on the order of nanoseconds while the 128*6777b538SAndroid Build Coastguard Worker // return result is microseconds. Even though we're passing in the largest 129*6777b538SAndroid Build Coastguard Worker // tick count the result should be orders of magnitude smaller. Expect that 130*6777b538SAndroid Build Coastguard Worker // FromMachTime(), when applying the timebase conversion, is smart enough to 131*6777b538SAndroid Build Coastguard Worker // not multiply first and generate an overflow. 132*6777b538SAndroid Build Coastguard Worker TimeDelta::FromMachTime(std::numeric_limits<uint64_t>::max()); 133*6777b538SAndroid Build Coastguard Worker} 134*6777b538SAndroid Build Coastguard Worker 135*6777b538SAndroid Build Coastguard Worker// Tests that there's no underflow in MachTimeToMicroseconds on Intel. 136*6777b538SAndroid Build Coastguard WorkerTEST(TimeMacTest, MachTimeToMicrosecondsNoUnderflowIntel) { 137*6777b538SAndroid Build Coastguard Worker ScopedTimebase timebase(kIntelTimebase); 138*6777b538SAndroid Build Coastguard Worker 139*6777b538SAndroid Build Coastguard Worker // On Intel the timebase conversion is 1:1, so min ticks is one microsecond 140*6777b538SAndroid Build Coastguard Worker // worth of nanoseconds. 141*6777b538SAndroid Build Coastguard Worker const uint64_t kMinimumTicks = base::Time::kNanosecondsPerMicrosecond; 142*6777b538SAndroid Build Coastguard Worker const uint64_t kOneMicrosecond = 1; 143*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(kOneMicrosecond, 144*6777b538SAndroid Build Coastguard Worker TimeDelta::FromMachTime(kMinimumTicks).InMicroseconds() * 1UL); 145*6777b538SAndroid Build Coastguard Worker 146*6777b538SAndroid Build Coastguard Worker // If we have even one fewer tick (i.e. not enough ticks to constitute a full 147*6777b538SAndroid Build Coastguard Worker // microsecond) the integer rounding should result in 0 microseconds. 148*6777b538SAndroid Build Coastguard Worker const uint64_t kZeroMicroseconds = 0; 149*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(kZeroMicroseconds, 150*6777b538SAndroid Build Coastguard Worker TimeDelta::FromMachTime(kMinimumTicks - 1).InMicroseconds() * 1UL); 151*6777b538SAndroid Build Coastguard Worker} 152*6777b538SAndroid Build Coastguard Worker 153*6777b538SAndroid Build Coastguard Worker// Tests that there's no underflow in MachTimeToMicroseconds for M1. 154*6777b538SAndroid Build Coastguard WorkerTEST(TimeMacTest, MachTimeToMicrosecondsNoUnderflowM1) { 155*6777b538SAndroid Build Coastguard Worker ScopedTimebase timebase(kM1Timebase); 156*6777b538SAndroid Build Coastguard Worker 157*6777b538SAndroid Build Coastguard Worker // Microseconds is mach_time multiplied by kM1Timebase.numer / 158*6777b538SAndroid Build Coastguard Worker // (kM1Timebase.denom * base::Time::kNanosecondsPerMicrosecond). Inverting 159*6777b538SAndroid Build Coastguard Worker // that should be the minimum number of ticks to get a single microsecond in 160*6777b538SAndroid Build Coastguard Worker // return. If we get zero it means an underflow in the conversion. For example 161*6777b538SAndroid Build Coastguard Worker // if FromMachTime() first divides mach_time by kM1Timebase.denom * 162*6777b538SAndroid Build Coastguard Worker // base::Time::kNanosecondsPerMicrosecond we'll get zero back. 163*6777b538SAndroid Build Coastguard Worker const uint64_t kMinimumTicks = 164*6777b538SAndroid Build Coastguard Worker (kM1Timebase.denom * base::Time::kNanosecondsPerMicrosecond) / 165*6777b538SAndroid Build Coastguard Worker kM1Timebase.numer; 166*6777b538SAndroid Build Coastguard Worker const uint64_t kOneMicrosecond = 1; 167*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(kOneMicrosecond, 168*6777b538SAndroid Build Coastguard Worker TimeDelta::FromMachTime(kMinimumTicks).InMicroseconds() * 1UL); 169*6777b538SAndroid Build Coastguard Worker 170*6777b538SAndroid Build Coastguard Worker // If we have even one fewer tick (i.e. not enough ticks to constitute a full 171*6777b538SAndroid Build Coastguard Worker // microsecond) the integer rounding should result in 0 microseconds. 172*6777b538SAndroid Build Coastguard Worker const uint64_t kZeroMicroseconds = 0; 173*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(kZeroMicroseconds, 174*6777b538SAndroid Build Coastguard Worker TimeDelta::FromMachTime(kMinimumTicks - 1).InMicroseconds() * 1UL); 175*6777b538SAndroid Build Coastguard Worker} 176*6777b538SAndroid Build Coastguard Worker 177*6777b538SAndroid Build Coastguard Worker} // namespace 178*6777b538SAndroid Build Coastguard Worker} // namespace base 179