tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

TestTimeUnit.cpp (9715B)


      1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #include "TimeUnits.h"
      8 #include "gtest/gtest.h"
      9 
     10 using namespace mozilla;
     11 using namespace mozilla::media;
     12 using TimeUnit = mozilla::media::TimeUnit;
     13 
     14 TEST(TimeUnit, BasicArithmetic)
     15 {
     16  const TimeUnit a(1000, 44100);
     17  {
     18    TimeUnit b = a * 10;
     19    EXPECT_EQ(b.mBase, 44100);
     20    EXPECT_EQ(b.mTicks.value(), a.mTicks.value() * 10);
     21    EXPECT_EQ(a * 10, b);
     22  }
     23  {
     24    TimeUnit b = a / 10;
     25    EXPECT_EQ(b.mBase, 44100);
     26    EXPECT_EQ(b.mTicks.value(), a.mTicks.value() / 10);
     27    EXPECT_EQ(a / 10, b);
     28  }
     29  {
     30    TimeUnit b = TimeUnit(10, 44100);
     31    b += a;
     32    EXPECT_EQ(b.mBase, 44100);
     33    EXPECT_EQ(b.mTicks.value(), a.mTicks.value() + 10);
     34    EXPECT_EQ(b - a, TimeUnit(10, 44100));
     35  }
     36  {
     37    TimeUnit b = TimeUnit(1010, 44100);
     38    b -= a;  // now 10
     39    EXPECT_EQ(b.mBase, 44100);
     40    EXPECT_EQ(b.mTicks.value(), 10);
     41    EXPECT_EQ(a + b, TimeUnit(1010, 44100));
     42  }
     43  {
     44    TimeUnit b = TimeUnit(4010, 44100);
     45    TimeUnit c = b % a;  // now 10
     46    EXPECT_EQ(c.mBase, 44100);
     47    EXPECT_EQ(c.mTicks.value(), 10);
     48  }
     49  {
     50    // Adding 6s in nanoseconds (e.g. coming from script) to a typical number
     51    // from an mp4, 9001 in base 90000
     52    TimeUnit b = TimeUnit(6000000000, 1000000000);
     53    TimeUnit c = TimeUnit(9001, 90000);
     54    TimeUnit d = c + b;
     55    EXPECT_EQ(d.mBase, 90000);
     56    EXPECT_EQ(d.mTicks.value(), 549001);
     57  }
     58  {
     59    // Subtracting 9001 in base 9000 from 6s in nanoseconds (e.g. coming from
     60    // script), converting to back to base 9000.
     61    TimeUnit b = TimeUnit(6000000000, 1000000000);
     62    TimeUnit c = TimeUnit(9001, 90000);
     63    TimeUnit d = (b - c).ToBase(90000);
     64    EXPECT_EQ(d.mBase, 90000);
     65    EXPECT_EQ(d.mTicks.value(), 530999);
     66  }
     67 }
     68 
     69 TEST(TimeUnit, Base)
     70 {
     71  {
     72    TimeUnit a = TimeUnit::FromSeconds(1);
     73    EXPECT_EQ(a.mTicks.value(), 1000000);
     74    EXPECT_EQ(a.mBase, 1000000);
     75  }
     76  {
     77    TimeUnit a = TimeUnit::FromMicroseconds(44100000000);
     78    EXPECT_EQ(a.mTicks.value(), 44100000000);
     79    EXPECT_EQ(a.mBase, 1000000);
     80  }
     81  {
     82    TimeUnit a = TimeUnit::FromSeconds(6.0);
     83    EXPECT_EQ(a.mTicks.value(), 6000000);
     84    EXPECT_EQ(a.mBase, 1000000);
     85    double error;
     86    TimeUnit b = a.ToBase(90000, error);
     87    EXPECT_EQ(error, 0);
     88    EXPECT_EQ(b.mTicks.value(), 540000);
     89    EXPECT_EQ(b.mBase, 90000);
     90  }
     91 }
     92 
     93 TEST(TimeUnit, Rounding)
     94 {
     95  int64_t usecs = 662617;
     96  double seconds = TimeUnit::FromMicroseconds(usecs).ToSeconds();
     97  TimeUnit fromSeconds = TimeUnit::FromSeconds(seconds);
     98  EXPECT_EQ(fromSeconds.mTicks.value(), usecs);
     99  // TimeUnit base is microseconds if not explicitly passed.
    100  EXPECT_EQ(fromSeconds.mBase, 1000000);
    101  EXPECT_EQ(fromSeconds.ToMicroseconds(), usecs);
    102 
    103  seconds = 4.169470123;
    104  int64_t nsecs = 4169470123;
    105  EXPECT_EQ(TimeUnit::FromSeconds(seconds, 1e9).ToNanoseconds(), nsecs);
    106  EXPECT_EQ(TimeUnit::FromSeconds(seconds, 1e9).ToMicroseconds(), nsecs / 1000);
    107 
    108  seconds = 2312312.16947012;
    109  nsecs = 2312312169470120;
    110  EXPECT_EQ(TimeUnit::FromSeconds(seconds, 1e9).ToNanoseconds(), nsecs);
    111  EXPECT_EQ(TimeUnit::FromSeconds(seconds, 1e9).ToMicroseconds(), nsecs / 1000);
    112 
    113  seconds = 2312312.169470123;
    114  nsecs = 2312312169470123;
    115  // A double doesn't have enough precision to roundtrip this time value
    116  // correctly in this base, but the number of microseconds is still correct.
    117  // This value is about 142.5 days however.
    118  // This particular calculation results in exactly 1ns of difference after
    119  // roundtrip. Enable this after remoing the MOZ_CRASH in TimeUnit::FromSeconds
    120  // EXPECT_EQ(TimeUnit::FromSeconds(seconds, 1e9).ToNanoseconds() - nsecs, 1);
    121  EXPECT_EQ(TimeUnit::FromSeconds(seconds, 1e9).ToMicroseconds(), nsecs / 1000);
    122 }
    123 
    124 TEST(TimeUnit, Comparisons)
    125 {
    126  TimeUnit a(0, 1e9);
    127  TimeUnit b(1, 1e9);
    128  TimeUnit c(1, 1e6);
    129 
    130  EXPECT_GE(b, a);
    131  EXPECT_GE(c, a);
    132  EXPECT_GE(c, b);
    133 
    134  EXPECT_GT(b, a);
    135  EXPECT_GT(c, a);
    136  EXPECT_GT(c, b);
    137 
    138  EXPECT_LE(a, b);
    139  EXPECT_LE(a, c);
    140  EXPECT_LE(b, c);
    141 
    142  EXPECT_LT(a, b);
    143  EXPECT_LT(a, c);
    144  EXPECT_LT(b, c);
    145 
    146  // Equivalence of zero regardless of the base
    147  TimeUnit d(0, 1);
    148  TimeUnit e(0, 1000);
    149  EXPECT_EQ(a, d);
    150  EXPECT_EQ(a, e);
    151 
    152  // Equivalence of time accross bases
    153  TimeUnit f(1000, 1e9);
    154  TimeUnit g(1, 1e6);
    155  EXPECT_EQ(f, g);
    156 
    157  // Comparisons with infinity, same base
    158  TimeUnit h = TimeUnit::FromInfinity();
    159  TimeUnit i = TimeUnit::Zero();
    160  EXPECT_LE(i, h);
    161  EXPECT_LT(i, h);
    162  EXPECT_GE(h, i);
    163  EXPECT_GT(h, i);
    164 
    165  // Comparisons with infinity, different base
    166  TimeUnit j = TimeUnit::FromInfinity();
    167  TimeUnit k = TimeUnit::Zero(1000000);
    168  EXPECT_LE(k, j);
    169  EXPECT_LT(k, j);
    170  EXPECT_GE(j, k);
    171  EXPECT_GT(j, k);
    172 
    173  // Comparison of very big numbers, different base that have a gcd that makes
    174  // it easy to reduce, to test the fraction reduction code
    175  TimeUnit l = TimeUnit(123123120000000, 1000000000);
    176  TimeUnit m = TimeUnit(123123120000000, 1000);
    177  EXPECT_LE(l, m);
    178  EXPECT_LT(l, m);
    179  EXPECT_GE(m, l);
    180  EXPECT_GT(m, l);
    181 
    182  // Comparison of very big numbers, different base that are co-prime: worst
    183  // cast scenario.
    184  TimeUnit n = TimeUnit(123123123123123, 1000000000);
    185  TimeUnit o = TimeUnit(123123123123123, 1000000001);
    186  EXPECT_LE(o, n);
    187  EXPECT_LT(o, n);
    188  EXPECT_GE(n, o);
    189  EXPECT_GT(n, o);
    190  // Comparison of very big numbers with different bases
    191  TimeUnit p(12312312312312312, 100000000);
    192  TimeUnit q(123123123123123119, 1000000000);
    193  TimeUnit r(123123123123123120, 1000000000);
    194  TimeUnit s(123123123123123121, 1000000000);
    195  EXPECT_LE(q, p);
    196  EXPECT_LT(q, p);
    197  EXPECT_NE(q, p);
    198  EXPECT_EQ(p, r);
    199  EXPECT_GE(s, p);
    200  EXPECT_GT(s, p);
    201  EXPECT_NE(s, p);
    202  // Comparison of different very big numbers.  There is intentionally only
    203  // one factor of 3 in numerator or denominator to reproduce bug 1909614.
    204  TimeUnit t = TimeUnit(123123123123124, 100000000 * 3);
    205  TimeUnit u = TimeUnit(123123123123124 * 3, 100000000);
    206  EXPECT_NE(t, u);
    207 
    208  // Values taken from a real website (this is about 53 years, Date.now() in
    209  // 2023).
    210  TimeUnit leftBound(74332508253360, 44100);
    211  TimeUnit rightBound(74332508297392, 44100);
    212  TimeUnit fuzz(250000, 1000000);
    213  TimeUnit time(1685544404790205, 1000000);
    214 
    215  EXPECT_LT(leftBound - fuzz, time);
    216  EXPECT_GT(time, leftBound - fuzz);
    217  EXPECT_GE(rightBound + fuzz, time);
    218  EXPECT_LT(time, rightBound + fuzz);
    219 
    220  TimeUnit zero = TimeUnit::Zero();  // default base 1e6
    221  TimeUnit datenow(
    222      151737439364679,
    223      90000);  // Also from `Date.now()` in a common base for an mp4
    224  EXPECT_NE(zero, datenow);
    225 }
    226 
    227 TEST(TimeUnit, InfinityMath)
    228 {
    229  // Operator plus/minus uses floating point behaviour for positive and
    230  // negative infinity values, i.e.:
    231  //  posInf + posInf	= inf
    232  //  posInf + negInf	= -nan
    233  //  posInf + finite = inf
    234  //  posInf - posInf	= -nan
    235  //  posInf - negInf	= inf
    236  //  posInf - finite = inf
    237  //  negInf + negInf	= -inf
    238  //  negInf + posInf	= -nan
    239  //  negInf + finite = -inf
    240  //  negInf - negInf	= -nan
    241  //  negInf - posInf	= -inf
    242  //  negInf - finite = -inf
    243  //  finite + posInf = inf
    244  //  finite - posInf = -inf
    245  //  finite + negInf = -inf
    246  //  finite - negInf = inf
    247 
    248  const TimeUnit posInf = TimeUnit::FromInfinity();
    249  EXPECT_EQ(TimeUnit::FromSeconds(mozilla::PositiveInfinity<double>()), posInf);
    250 
    251  const TimeUnit negInf = TimeUnit::FromNegativeInfinity();
    252  EXPECT_EQ(TimeUnit::FromSeconds(mozilla::NegativeInfinity<double>()), negInf);
    253 
    254  EXPECT_EQ(posInf + posInf, posInf);
    255  EXPECT_FALSE((posInf + negInf).IsValid());
    256  EXPECT_FALSE((posInf - posInf).IsValid());
    257  EXPECT_EQ(posInf - negInf, posInf);
    258  EXPECT_EQ(negInf + negInf, negInf);
    259  EXPECT_FALSE((negInf + posInf).IsValid());
    260  EXPECT_FALSE((negInf - negInf).IsValid());
    261  EXPECT_EQ(negInf - posInf, negInf);
    262 
    263  const TimeUnit finite = TimeUnit::FromSeconds(42.0);
    264  EXPECT_EQ(posInf - finite, posInf);
    265  EXPECT_EQ(posInf + finite, posInf);
    266  EXPECT_EQ(negInf - finite, negInf);
    267  EXPECT_EQ(negInf + finite, negInf);
    268 
    269  EXPECT_EQ(finite + posInf, posInf);
    270  EXPECT_EQ(finite - posInf, negInf);
    271  EXPECT_EQ(finite + negInf, negInf);
    272  EXPECT_EQ(finite - negInf, posInf);
    273 }
    274 
    275 TEST(TimeUnit, BaseConversion)
    276 {
    277  const int64_t packetSize = 1024;  // typical for AAC
    278  int64_t sampleRates[] = {16000, 44100, 48000, 88200, 96000};
    279  const double hnsPerSeconds = 10000000.;
    280  for (auto sampleRate : sampleRates) {
    281    int64_t frameCount = 0;
    282    TimeUnit pts;
    283    do {
    284      // Compute a time in hundreds of nanoseconds based of frame count, typical
    285      // on Windows platform, checking that it round trips properly.
    286      int64_t hns = AssertedCast<int64_t>(
    287          std::round(hnsPerSeconds * static_cast<double>(frameCount) /
    288                     static_cast<double>(sampleRate)));
    289      pts = TimeUnit::FromHns(hns, sampleRate);
    290      EXPECT_EQ(
    291          AssertedCast<int64_t>(std::round(pts.ToSeconds() * hnsPerSeconds)),
    292          hns);
    293      frameCount += packetSize;
    294    } while (pts.ToSeconds() < 36000);
    295  }
    296 }
    297 
    298 TEST(TimeUnit, MinimumRoundingError)
    299 {
    300  TimeUnit a(448, 48000);  // ≈9333 us
    301  TimeUnit b(1, 1000000);  // 1 us
    302  TimeUnit rv = a - b;     // should close to 9332 us as much as possible
    303  EXPECT_EQ(rv.mTicks.value(), 448);  // ≈9333 us is closer to 9332 us
    304  EXPECT_EQ(rv.mBase, 48000);
    305 
    306  TimeUnit c(11, 1000000);  // 11 us
    307  rv = a - c;               // should close to 9322 as much as possible
    308  EXPECT_EQ(rv.mTicks.value(), 447);  // ≈9312 us is closer to 9322 us
    309  EXPECT_EQ(rv.mBase, 48000);
    310 }