tor-browser

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

TestIntervalSet.cpp (23492B)


      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 <algorithm>
      8 #include <type_traits>
      9 #include <vector>
     10 
     11 #include "Intervals.h"
     12 #include "TimeUnits.h"
     13 #include "gtest/gtest.h"
     14 #include "mozilla/ErrorResult.h"
     15 #include "mozilla/dom/TimeRanges.h"
     16 
     17 using namespace mozilla;
     18 
     19 typedef media::Interval<uint8_t> ByteInterval;
     20 typedef media::Interval<int> IntInterval;
     21 typedef media::IntervalSet<int> IntIntervals;
     22 
     23 ByteInterval CreateByteInterval(int32_t aStart, int32_t aEnd) {
     24  ByteInterval test(aStart, aEnd);
     25  return test;
     26 }
     27 
     28 media::IntervalSet<uint8_t> CreateByteIntervalSet(int32_t aStart,
     29                                                  int32_t aEnd) {
     30  media::IntervalSet<uint8_t> test;
     31  test += ByteInterval(aStart, aEnd);
     32  return test;
     33 }
     34 
     35 TEST(IntervalSet, Constructors)
     36 {
     37  const int32_t start = 1;
     38  const int32_t end = 2;
     39  const int32_t fuzz = 0;
     40 
     41  // Compiler exercise.
     42  ByteInterval test1(start, end);
     43  ByteInterval test2(test1);
     44  ByteInterval test3(start, end, fuzz);
     45  ByteInterval test4(test3);
     46  ByteInterval test5 = CreateByteInterval(start, end);
     47 
     48  media::IntervalSet<uint8_t> blah1(test1);
     49  media::IntervalSet<uint8_t> blah2 = blah1;
     50  media::IntervalSet<uint8_t> blah3 = blah1 + test1;
     51  media::IntervalSet<uint8_t> blah4 = test1 + blah1;
     52  media::IntervalSet<uint8_t> blah5 = CreateByteIntervalSet(start, end);
     53  (void)test1;
     54  (void)test2;
     55  (void)test3;
     56  (void)test4;
     57  (void)test5;
     58  (void)blah1;
     59  (void)blah2;
     60  (void)blah3;
     61  (void)blah4;
     62  (void)blah5;
     63 }
     64 
     65 media::TimeInterval CreateTimeInterval(int32_t aStart, int32_t aEnd) {
     66  // Copy constructor test
     67  media::TimeUnit start = media::TimeUnit::FromMicroseconds(aStart);
     68  media::TimeUnit end;
     69  // operator=  test
     70  end = media::TimeUnit::FromMicroseconds(aEnd);
     71  media::TimeInterval ti(start, end);
     72  return ti;
     73 }
     74 
     75 media::TimeIntervals CreateTimeIntervals(int32_t aStart, int32_t aEnd) {
     76  media::TimeIntervals test;
     77  test += CreateTimeInterval(aStart, aEnd);
     78  return test;
     79 }
     80 
     81 TEST(IntervalSet, TimeIntervalsConstructors)
     82 {
     83  const auto start = media::TimeUnit::FromMicroseconds(1);
     84  const auto end = media::TimeUnit::FromMicroseconds(2);
     85  const media::TimeUnit fuzz;
     86 
     87  // Compiler exercise.
     88  media::TimeInterval test1(start, end);
     89  media::TimeInterval test2(test1);
     90  media::TimeInterval test3(start, end, fuzz);
     91  media::TimeInterval test4(test3);
     92  media::TimeInterval test5 =
     93      CreateTimeInterval(start.ToMicroseconds(), end.ToMicroseconds());
     94 
     95  media::TimeIntervals blah1(test1);
     96  media::TimeIntervals blah2(blah1);
     97  media::TimeIntervals blah3 = blah1 + test1;
     98  media::TimeIntervals blah4 = test1 + blah1;
     99  media::TimeIntervals blah5 =
    100      CreateTimeIntervals(start.ToMicroseconds(), end.ToMicroseconds());
    101  (void)test1;
    102  (void)test2;
    103  (void)test3;
    104  (void)test4;
    105  (void)test5;
    106  (void)blah1;
    107  (void)blah2;
    108  (void)blah3;
    109  (void)blah4;
    110  (void)blah5;
    111 
    112  media::TimeIntervals i0{media::TimeInterval(media::TimeUnit::FromSeconds(0),
    113                                              media::TimeUnit::FromSeconds(0))};
    114  EXPECT_TRUE(i0.IsEmpty());  // Constructing with an empty time interval.
    115 }
    116 
    117 TEST(IntervalSet, Length)
    118 {
    119  IntInterval i(15, 25);
    120  EXPECT_EQ(10, i.Length());
    121 }
    122 
    123 TEST(IntervalSet, Intersects)
    124 {
    125  EXPECT_TRUE(IntInterval(1, 5).Intersects(IntInterval(3, 4)));
    126  EXPECT_TRUE(IntInterval(1, 5).Intersects(IntInterval(3, 7)));
    127  EXPECT_TRUE(IntInterval(1, 5).Intersects(IntInterval(-1, 3)));
    128  EXPECT_TRUE(IntInterval(1, 5).Intersects(IntInterval(-1, 7)));
    129  EXPECT_FALSE(IntInterval(1, 5).Intersects(IntInterval(6, 7)));
    130  EXPECT_FALSE(IntInterval(1, 5).Intersects(IntInterval(-1, 0)));
    131  // End boundary is exclusive of the interval.
    132  EXPECT_FALSE(IntInterval(1, 5).Intersects(IntInterval(5, 7)));
    133  EXPECT_FALSE(IntInterval(1, 5).Intersects(IntInterval(0, 1)));
    134  // Empty identical interval do not intersect.
    135  EXPECT_FALSE(IntInterval(1, 1).Intersects(IntInterval(1, 1)));
    136  // Empty interval do not intersect.
    137  EXPECT_FALSE(IntInterval(1, 1).Intersects(IntInterval(2, 2)));
    138 }
    139 
    140 TEST(IntervalSet, Intersection)
    141 {
    142  IntInterval i0(10, 20);
    143  IntInterval i1(15, 25);
    144  IntInterval i = i0.Intersection(i1);
    145  EXPECT_EQ(15, i.mStart);
    146  EXPECT_EQ(20, i.mEnd);
    147  IntInterval j0(10, 20);
    148  IntInterval j1(20, 25);
    149  IntInterval j = j0.Intersection(j1);
    150  EXPECT_TRUE(j.IsEmpty());
    151  IntInterval k0(2, 2);
    152  IntInterval k1(2, 2);
    153  IntInterval k = k0.Intersection(k1);
    154  EXPECT_TRUE(k.IsEmpty());
    155 }
    156 
    157 TEST(IntervalSet, Equals)
    158 {
    159  IntInterval i0(10, 20);
    160  IntInterval i1(10, 20);
    161  EXPECT_EQ(i0, i1);
    162 
    163  IntInterval i2(5, 20);
    164  EXPECT_NE(i0, i2);
    165 
    166  IntInterval i3(10, 15);
    167  EXPECT_NE(i0, i2);
    168 }
    169 
    170 TEST(IntervalSet, IntersectionIntervalSet)
    171 {
    172  IntIntervals i0;
    173  i0 += IntInterval(5, 10);
    174  i0 += IntInterval(20, 25);
    175  i0 += IntInterval(40, 60);
    176 
    177  IntIntervals i1;
    178  i1.Add(IntInterval(7, 15));
    179  i1.Add(IntInterval(16, 27));
    180  i1.Add(IntInterval(45, 50));
    181  i1.Add(IntInterval(53, 57));
    182 
    183  IntIntervals i = media::Intersection(i0, i1);
    184 
    185  EXPECT_EQ(4u, i.Length());
    186 
    187  EXPECT_EQ(7, i[0].mStart);
    188  EXPECT_EQ(10, i[0].mEnd);
    189 
    190  EXPECT_EQ(20, i[1].mStart);
    191  EXPECT_EQ(25, i[1].mEnd);
    192 
    193  EXPECT_EQ(45, i[2].mStart);
    194  EXPECT_EQ(50, i[2].mEnd);
    195 
    196  EXPECT_EQ(53, i[3].mStart);
    197  EXPECT_EQ(57, i[3].mEnd);
    198 }
    199 
    200 template <typename T>
    201 static void Compare(const media::IntervalSet<T>& aI1,
    202                    const media::IntervalSet<T>& aI2) {
    203  EXPECT_EQ(aI1.Length(), aI2.Length());
    204  if (aI1.Length() != aI2.Length()) {
    205    return;
    206  }
    207  for (uint32_t i = 0; i < aI1.Length(); i++) {
    208    EXPECT_EQ(aI1[i].mStart, aI2[i].mStart);
    209    EXPECT_EQ(aI1[i].mEnd, aI2[i].mEnd);
    210  }
    211 }
    212 
    213 static void GeneratePermutations(const IntIntervals& aI1,
    214                                 const IntIntervals& aI2) {
    215  IntIntervals i_ref = media::Intersection(aI1, aI2);
    216  // Test all permutations possible
    217  std::vector<uint32_t> comb1;
    218  for (uint32_t i = 0; i < aI1.Length(); i++) {
    219    comb1.push_back(i);
    220  }
    221  std::vector<uint32_t> comb2;
    222  for (uint32_t i = 0; i < aI2.Length(); i++) {
    223    comb2.push_back(i);
    224  }
    225 
    226  do {
    227    do {
    228      // Create intervals according to new indexes.
    229      IntIntervals i_0;
    230      for (uint32_t i = 0; i < comb1.size(); i++) {
    231        i_0 += aI1[comb1[i]];
    232      }
    233      // Test that intervals are always normalized.
    234      Compare(aI1, i_0);
    235      IntIntervals i_1;
    236      for (uint32_t i = 0; i < comb2.size(); i++) {
    237        i_1 += aI2[comb2[i]];
    238      }
    239      Compare(aI2, i_1);
    240      // Check intersections yield the same result.
    241      Compare(i_0.Intersection(i_1), i_ref);
    242    } while (std::next_permutation(comb2.begin(), comb2.end()));
    243  } while (std::next_permutation(comb1.begin(), comb1.end()));
    244 }
    245 
    246 TEST(IntervalSet, IntersectionNormalizedIntervalSet)
    247 {
    248  IntIntervals i0;
    249  i0 += IntInterval(5, 10);
    250  i0 += IntInterval(20, 25);
    251  i0 += IntInterval(40, 60);
    252 
    253  IntIntervals i1;
    254  i1.Add(IntInterval(7, 15));
    255  i1.Add(IntInterval(16, 27));
    256  i1.Add(IntInterval(45, 50));
    257  i1.Add(IntInterval(53, 57));
    258 
    259  GeneratePermutations(i0, i1);
    260 }
    261 
    262 TEST(IntervalSet, IntersectionUnorderedNonNormalizedIntervalSet)
    263 {
    264  IntIntervals i0;
    265  i0 += IntInterval(5, 10);
    266  i0 += IntInterval(8, 25);
    267  i0 += IntInterval(24, 60);
    268 
    269  IntIntervals i1;
    270  i1.Add(IntInterval(7, 15));
    271  i1.Add(IntInterval(10, 27));
    272  i1.Add(IntInterval(45, 50));
    273  i1.Add(IntInterval(53, 57));
    274 
    275  GeneratePermutations(i0, i1);
    276 }
    277 
    278 TEST(IntervalSet, IntersectionNonNormalizedInterval)
    279 {
    280  IntIntervals i0;
    281  i0 += IntInterval(5, 10);
    282  i0 += IntInterval(8, 25);
    283  i0 += IntInterval(30, 60);
    284 
    285  media::Interval<int> i1(9, 15);
    286  i0.Intersection(i1);
    287  EXPECT_EQ(1u, i0.Length());
    288  EXPECT_EQ(i0[0].mStart, i1.mStart);
    289  EXPECT_EQ(i0[0].mEnd, i1.mEnd);
    290 }
    291 
    292 TEST(IntervalSet, IntersectionUnorderedNonNormalizedInterval)
    293 {
    294  IntIntervals i0;
    295  i0 += IntInterval(1, 3);
    296  i0 += IntInterval(1, 10);
    297  i0 += IntInterval(9, 12);
    298  i0 += IntInterval(12, 15);
    299  i0 += IntInterval(8, 25);
    300  i0 += IntInterval(30, 60);
    301  i0 += IntInterval(5, 10);
    302  i0 += IntInterval(30, 60);
    303 
    304  media::Interval<int> i1(9, 15);
    305  i0.Intersection(i1);
    306  EXPECT_EQ(1u, i0.Length());
    307  EXPECT_EQ(i0[0].mStart, i1.mStart);
    308  EXPECT_EQ(i0[0].mEnd, i1.mEnd);
    309 }
    310 
    311 static IntIntervals Duplicate(const IntIntervals& aValue) {
    312  IntIntervals value(aValue);
    313  return value;
    314 }
    315 
    316 TEST(IntervalSet, Normalize)
    317 {
    318  IntIntervals i;
    319  // Test IntervalSet<T> + Interval<T> operator.
    320  i = i + IntInterval(20, 30);
    321  // Test Internal<T> + IntervalSet<T> operator.
    322  i = IntInterval(2, 7) + i;
    323  // Test Interval<T> + IntervalSet<T> operator
    324  i = IntInterval(1, 8) + i;
    325  IntIntervals interval;
    326  interval += IntInterval(5, 10);
    327  // Test += with rval move.
    328  i += Duplicate(interval);
    329  // Test = with move and add with move.
    330  i = Duplicate(interval) + i;
    331 
    332  EXPECT_EQ(2u, i.Length());
    333 
    334  EXPECT_EQ(1, i[0].mStart);
    335  EXPECT_EQ(10, i[0].mEnd);
    336 
    337  EXPECT_EQ(20, i[1].mStart);
    338  EXPECT_EQ(30, i[1].mEnd);
    339 
    340  media::TimeIntervals ti;
    341  ti += media::TimeInterval(media::TimeUnit::FromSeconds(0.0),
    342                            media::TimeUnit::FromSeconds(3.203333));
    343  ti += media::TimeInterval(media::TimeUnit::FromSeconds(3.203366),
    344                            media::TimeUnit::FromSeconds(10.010065));
    345  EXPECT_EQ(2u, ti.Length());
    346  ti += media::TimeInterval(ti.Start(0), ti.End(0),
    347                            media::TimeUnit::FromMicroseconds(35000));
    348  EXPECT_EQ(1u, ti.Length());
    349 }
    350 
    351 TEST(IntervalSet, ContainValue)
    352 {
    353  IntIntervals i0;
    354  i0 += IntInterval(0, 10);
    355  i0 += IntInterval(15, 20);
    356  i0 += IntInterval(30, 50);
    357  EXPECT_TRUE(i0.Contains(0));  // start is inclusive.
    358  EXPECT_TRUE(i0.Contains(17));
    359  EXPECT_FALSE(i0.Contains(20));  // end boundary is exclusive.
    360  EXPECT_FALSE(i0.Contains(25));
    361 }
    362 
    363 TEST(IntervalSet, ContainValueWithFuzz)
    364 {
    365  IntIntervals i0;
    366  i0 += IntInterval(0, 10);
    367  i0 += IntInterval(15, 20, 1);
    368  i0 += IntInterval(30, 50);
    369  EXPECT_TRUE(i0.Contains(0));  // start is inclusive.
    370  EXPECT_TRUE(i0.Contains(17));
    371  EXPECT_TRUE(
    372      i0.Contains(20));  // end boundary is exclusive but we have a fuzz of 1.
    373  EXPECT_FALSE(i0.Contains(25));
    374 }
    375 
    376 TEST(IntervalSet, ContainInterval)
    377 {
    378  IntIntervals i0;
    379  i0 += IntInterval(0, 10);
    380  i0 += IntInterval(15, 20);
    381  i0 += IntInterval(30, 50);
    382  EXPECT_TRUE(i0.Contains(IntInterval(2, 8)));
    383  EXPECT_TRUE(i0.Contains(IntInterval(31, 50)));
    384  EXPECT_TRUE(i0.Contains(IntInterval(0, 10)));
    385  EXPECT_FALSE(i0.Contains(IntInterval(0, 11)));
    386  EXPECT_TRUE(i0.Contains(IntInterval(0, 5)));
    387  EXPECT_FALSE(i0.Contains(IntInterval(8, 15)));
    388  EXPECT_FALSE(i0.Contains(IntInterval(15, 30)));
    389  EXPECT_FALSE(i0.Contains(IntInterval(30, 55)));
    390 }
    391 
    392 TEST(IntervalSet, ContainIntervalWithFuzz)
    393 {
    394  IntIntervals i0;
    395  i0 += IntInterval(0, 10);
    396  i0 += IntInterval(15, 20);
    397  i0 += IntInterval(30, 50);
    398  EXPECT_TRUE(i0.Contains(IntInterval(2, 8)));
    399  EXPECT_TRUE(i0.Contains(IntInterval(31, 50)));
    400  EXPECT_TRUE(i0.Contains(IntInterval(0, 11, 1)));
    401  EXPECT_TRUE(i0.Contains(IntInterval(0, 5)));
    402  EXPECT_FALSE(i0.Contains(IntInterval(8, 15)));
    403  EXPECT_FALSE(i0.Contains(IntInterval(15, 21)));
    404  EXPECT_FALSE(i0.Contains(IntInterval(15, 30)));
    405  EXPECT_FALSE(i0.Contains(IntInterval(30, 55)));
    406 
    407  IntIntervals i1;
    408  i1 += IntInterval(0, 10, 1);
    409  i1 += IntInterval(15, 20, 1);
    410  i1 += IntInterval(30, 50, 1);
    411  EXPECT_TRUE(i1.Contains(IntInterval(2, 8)));
    412  EXPECT_TRUE(i1.Contains(IntInterval(29, 51)));
    413  EXPECT_TRUE(i1.Contains(IntInterval(0, 11, 1)));
    414  EXPECT_TRUE(i1.Contains(IntInterval(15, 21)));
    415 }
    416 
    417 TEST(IntervalSet, Span)
    418 {
    419  IntInterval i0(0, 10);
    420  IntInterval i1(20, 30);
    421  IntInterval i{i0.Span(i1)};
    422 
    423  EXPECT_EQ(i.mStart, 0);
    424  EXPECT_EQ(i.mEnd, 30);
    425 }
    426 
    427 TEST(IntervalSet, Union)
    428 {
    429  IntIntervals i0;
    430  i0 += IntInterval(5, 10);
    431  i0 += IntInterval(20, 25);
    432  i0 += IntInterval(40, 60);
    433 
    434  IntIntervals i1;
    435  i1.Add(IntInterval(7, 15));
    436  i1.Add(IntInterval(16, 27));
    437  i1.Add(IntInterval(45, 50));
    438  i1.Add(IntInterval(53, 57));
    439 
    440  IntIntervals i = media::Union(i0, i1);
    441 
    442  EXPECT_EQ(3u, i.Length());
    443 
    444  EXPECT_EQ(5, i[0].mStart);
    445  EXPECT_EQ(15, i[0].mEnd);
    446 
    447  EXPECT_EQ(16, i[1].mStart);
    448  EXPECT_EQ(27, i[1].mEnd);
    449 
    450  EXPECT_EQ(40, i[2].mStart);
    451  EXPECT_EQ(60, i[2].mEnd);
    452 }
    453 
    454 TEST(IntervalSet, UnionNotOrdered)
    455 {
    456  IntIntervals i0;
    457  i0 += IntInterval(20, 25);
    458  i0 += IntInterval(40, 60);
    459  i0 += IntInterval(5, 10);
    460 
    461  IntIntervals i1;
    462  i1.Add(IntInterval(16, 27));
    463  i1.Add(IntInterval(7, 15));
    464  i1.Add(IntInterval(53, 57));
    465  i1.Add(IntInterval(45, 50));
    466 
    467  IntIntervals i = media::Union(i0, i1);
    468 
    469  EXPECT_EQ(3u, i.Length());
    470 
    471  EXPECT_EQ(5, i[0].mStart);
    472  EXPECT_EQ(15, i[0].mEnd);
    473 
    474  EXPECT_EQ(16, i[1].mStart);
    475  EXPECT_EQ(27, i[1].mEnd);
    476 
    477  EXPECT_EQ(40, i[2].mStart);
    478  EXPECT_EQ(60, i[2].mEnd);
    479 }
    480 
    481 TEST(IntervalSet, NormalizeFuzz)
    482 {
    483  IntIntervals i0;
    484  i0 += IntInterval(11, 25, 0);
    485  i0 += IntInterval(5, 10, 1);
    486  i0 += IntInterval(40, 60, 1);
    487 
    488  EXPECT_EQ(2u, i0.Length());
    489 
    490  EXPECT_EQ(5, i0[0].mStart);
    491  EXPECT_EQ(25, i0[0].mEnd);
    492 
    493  EXPECT_EQ(40, i0[1].mStart);
    494  EXPECT_EQ(60, i0[1].mEnd);
    495 }
    496 
    497 TEST(IntervalSet, UnionFuzz)
    498 {
    499  IntIntervals i0;
    500  i0 += IntInterval(5, 10, 1);
    501  i0 += IntInterval(11, 25, 0);
    502  i0 += IntInterval(40, 60, 1);
    503  EXPECT_EQ(2u, i0.Length());
    504  EXPECT_EQ(5, i0[0].mStart);
    505  EXPECT_EQ(25, i0[0].mEnd);
    506  EXPECT_EQ(40, i0[1].mStart);
    507  EXPECT_EQ(60, i0[1].mEnd);
    508 
    509  IntIntervals i1;
    510  i1.Add(IntInterval(7, 15, 1));
    511  i1.Add(IntInterval(16, 27, 1));
    512  i1.Add(IntInterval(45, 50, 1));
    513  i1.Add(IntInterval(53, 57, 1));
    514  EXPECT_EQ(3u, i1.Length());
    515  EXPECT_EQ(7, i1[0].mStart);
    516  EXPECT_EQ(27, i1[0].mEnd);
    517  EXPECT_EQ(45, i1[1].mStart);
    518  EXPECT_EQ(50, i1[1].mEnd);
    519  EXPECT_EQ(53, i1[2].mStart);
    520  EXPECT_EQ(57, i1[2].mEnd);
    521 
    522  IntIntervals i = media::Union(i0, i1);
    523 
    524  EXPECT_EQ(2u, i.Length());
    525 
    526  EXPECT_EQ(5, i[0].mStart);
    527  EXPECT_EQ(27, i[0].mEnd);
    528 
    529  EXPECT_EQ(40, i[1].mStart);
    530  EXPECT_EQ(60, i[1].mEnd);
    531 }
    532 
    533 TEST(IntervalSet, Contiguous)
    534 {
    535  EXPECT_FALSE(IntInterval(5, 10).Contiguous(IntInterval(11, 25)));
    536  EXPECT_TRUE(IntInterval(5, 10).Contiguous(IntInterval(10, 25)));
    537  EXPECT_TRUE(IntInterval(5, 10, 1).Contiguous(IntInterval(11, 25)));
    538  EXPECT_TRUE(IntInterval(5, 10).Contiguous(IntInterval(11, 25, 1)));
    539 }
    540 
    541 TEST(IntervalSet, TimeRangesSeconds)
    542 {
    543  media::TimeIntervals i0;
    544  i0 += media::TimeInterval(media::TimeUnit::FromSeconds(20),
    545                            media::TimeUnit::FromSeconds(25));
    546  i0 += media::TimeInterval(media::TimeUnit::FromSeconds(40),
    547                            media::TimeUnit::FromSeconds(60));
    548  i0 += media::TimeInterval(media::TimeUnit::FromSeconds(5),
    549                            media::TimeUnit::FromSeconds(10));
    550 
    551  media::TimeIntervals i1;
    552  i1.Add(media::TimeInterval(media::TimeUnit::FromSeconds(16),
    553                             media::TimeUnit::FromSeconds(27)));
    554  i1.Add(media::TimeInterval(media::TimeUnit::FromSeconds(7),
    555                             media::TimeUnit::FromSeconds(15)));
    556  i1.Add(media::TimeInterval(media::TimeUnit::FromSeconds(53),
    557                             media::TimeUnit::FromSeconds(57)));
    558  i1.Add(media::TimeInterval(media::TimeUnit::FromSeconds(45),
    559                             media::TimeUnit::FromSeconds(50)));
    560 
    561  media::TimeIntervals i(i0 + i1);
    562  RefPtr<dom::TimeRanges> tr = new dom::TimeRanges(i);
    563  EXPECT_EQ(tr->Length(), i.Length());
    564  for (dom::TimeRanges::index_type index = 0; index < tr->Length(); index++) {
    565    ErrorResult rv;
    566    EXPECT_EQ(tr->Start(index, rv), i[index].mStart.ToSeconds());
    567    EXPECT_EQ(tr->Start(index, rv), i.Start(index).ToSeconds());
    568    EXPECT_EQ(tr->End(index, rv), i[index].mEnd.ToSeconds());
    569    EXPECT_EQ(tr->End(index, rv), i.End(index).ToSeconds());
    570  }
    571 }
    572 
    573 static void CheckTimeRanges(dom::TimeRanges* aTr,
    574                            const media::TimeIntervals& aTi) {
    575  RefPtr<dom::TimeRanges> tr = new dom::TimeRanges;
    576  tr->Union(aTr, 0);  // This will normalize the time range.
    577  EXPECT_EQ(tr->Length(), aTi.Length());
    578  for (dom::TimeRanges::index_type i = 0; i < tr->Length(); i++) {
    579    ErrorResult rv;
    580    EXPECT_EQ(tr->Start(i, rv), aTi[i].mStart.ToSeconds());
    581    EXPECT_EQ(tr->Start(i, rv), aTi.Start(i).ToSeconds());
    582    EXPECT_EQ(tr->End(i, rv), aTi[i].mEnd.ToSeconds());
    583    EXPECT_EQ(tr->End(i, rv), aTi.End(i).ToSeconds());
    584  }
    585 }
    586 
    587 TEST(IntervalSet, TimeRangesConversion)
    588 {
    589  RefPtr<dom::TimeRanges> tr = new dom::TimeRanges();
    590  tr->Add(20, 25);
    591  tr->Add(40, 60);
    592  tr->Add(5, 10);
    593  tr->Add(16, 27);
    594  tr->Add(53, 57);
    595  tr->Add(45, 50);
    596 
    597  // explicit copy constructor and ToTimeIntervals.
    598  media::TimeIntervals i1(tr->ToTimeIntervals());
    599  CheckTimeRanges(tr, i1);
    600 
    601  // ctor(const TimeIntervals&)
    602  RefPtr<dom::TimeRanges> tr2 = new dom::TimeRanges(tr->ToTimeIntervals());
    603  CheckTimeRanges(tr2, i1);
    604 }
    605 
    606 TEST(IntervalSet, TimeRangesMicroseconds)
    607 {
    608  media::TimeIntervals i0;
    609 
    610  i0 += media::TimeInterval(media::TimeUnit::FromMicroseconds(20),
    611                            media::TimeUnit::FromMicroseconds(25));
    612  i0 += media::TimeInterval(media::TimeUnit::FromMicroseconds(40),
    613                            media::TimeUnit::FromMicroseconds(60));
    614  i0 += media::TimeInterval(media::TimeUnit::FromMicroseconds(5),
    615                            media::TimeUnit::FromMicroseconds(10));
    616 
    617  media::TimeIntervals i1;
    618  i1.Add(media::TimeInterval(media::TimeUnit::FromMicroseconds(16),
    619                             media::TimeUnit::FromMicroseconds(27)));
    620  i1.Add(media::TimeInterval(media::TimeUnit::FromMicroseconds(7),
    621                             media::TimeUnit::FromMicroseconds(15)));
    622  i1.Add(media::TimeInterval(media::TimeUnit::FromMicroseconds(53),
    623                             media::TimeUnit::FromMicroseconds(57)));
    624  i1.Add(media::TimeInterval(media::TimeUnit::FromMicroseconds(45),
    625                             media::TimeUnit::FromMicroseconds(50)));
    626 
    627  media::TimeIntervals i(i0 + i1);
    628  RefPtr<dom::TimeRanges> tr = new dom::TimeRanges(i);
    629  EXPECT_EQ(tr->Length(), i.Length());
    630  for (dom::TimeRanges::index_type index = 0; index < tr->Length(); index++) {
    631    ErrorResult rv;
    632    EXPECT_EQ(tr->Start(index, rv), i[index].mStart.ToSeconds());
    633    EXPECT_EQ(tr->Start(index, rv), i.Start(index).ToSeconds());
    634    EXPECT_EQ(tr->End(index, rv), i[index].mEnd.ToSeconds());
    635    EXPECT_EQ(tr->End(index, rv), i.End(index).ToSeconds());
    636  }
    637 
    638  tr->Normalize();
    639  EXPECT_EQ(tr->Length(), i.Length());
    640  for (dom::TimeRanges::index_type index = 0; index < tr->Length(); index++) {
    641    ErrorResult rv;
    642    EXPECT_EQ(tr->Start(index, rv), i[index].mStart.ToSeconds());
    643    EXPECT_EQ(tr->Start(index, rv), i.Start(index).ToSeconds());
    644    EXPECT_EQ(tr->End(index, rv), i[index].mEnd.ToSeconds());
    645    EXPECT_EQ(tr->End(index, rv), i.End(index).ToSeconds());
    646  }
    647 
    648  // Check infinity values aren't lost in the conversion.
    649  tr = new dom::TimeRanges();
    650  tr->Add(0, 30);
    651  tr->Add(50, std::numeric_limits<double>::infinity());
    652  media::TimeIntervals i_oo = tr->ToTimeIntervals();
    653  RefPtr<dom::TimeRanges> tr2 = new dom::TimeRanges(i_oo);
    654  EXPECT_EQ(tr->Length(), tr2->Length());
    655  for (dom::TimeRanges::index_type index = 0; index < tr->Length(); index++) {
    656    ErrorResult rv;
    657    EXPECT_EQ(tr->Start(index, rv), tr2->Start(index, rv));
    658    EXPECT_EQ(tr->End(index, rv), tr2->End(index, rv));
    659  }
    660 }
    661 
    662 template <typename T>
    663 class Foo {
    664 public:
    665  Foo() : mArg1(1), mArg2(2), mArg3(3) {}
    666 
    667  Foo(T a1, T a2, T a3) : mArg1(a1), mArg2(a2), mArg3(a3) {}
    668 
    669  Foo<T> operator+(const Foo<T>& aOther) const {
    670    Foo<T> blah;
    671    blah.mArg1 += aOther.mArg1;
    672    blah.mArg2 += aOther.mArg2;
    673    blah.mArg3 += aOther.mArg3;
    674    return blah;
    675  }
    676  Foo<T> operator-(const Foo<T>& aOther) const {
    677    Foo<T> blah;
    678    blah.mArg1 -= aOther.mArg1;
    679    blah.mArg2 -= aOther.mArg2;
    680    blah.mArg3 -= aOther.mArg3;
    681    return blah;
    682  }
    683  bool operator<(const Foo<T>& aOther) const { return mArg1 < aOther.mArg1; }
    684  bool operator==(const Foo<T>& aOther) const { return mArg1 == aOther.mArg1; }
    685  bool operator<=(const Foo<T>& aOther) const { return mArg1 <= aOther.mArg1; }
    686 
    687 private:
    688  int32_t mArg1;
    689  int32_t mArg2;
    690  int32_t mArg3;
    691 };
    692 
    693 TEST(IntervalSet, FooIntervalSet)
    694 {
    695  media::Interval<Foo<int>> i(Foo<int>(), Foo<int>(4, 5, 6));
    696  media::IntervalSet<Foo<int>> is;
    697  is += i;
    698  is += i;
    699  is.Add(i);
    700  is = is + i;
    701  is = i + is;
    702  EXPECT_EQ(1u, is.Length());
    703  EXPECT_EQ(Foo<int>(), is[0].mStart);
    704  EXPECT_EQ(Foo<int>(4, 5, 6), is[0].mEnd);
    705 }
    706 
    707 TEST(IntervalSet, StaticAssert)
    708 {
    709  media::Interval<int> i;
    710 
    711  static_assert(
    712      std::is_same_v<nsTArray_RelocationStrategy<IntIntervals>::Type,
    713                     nsTArray_RelocateUsingMoveConstructor<IntIntervals>>,
    714      "Must use copy constructor");
    715  static_assert(
    716      std::is_same_v<
    717          nsTArray_RelocationStrategy<media::TimeIntervals>::Type,
    718          nsTArray_RelocateUsingMoveConstructor<media::TimeIntervals>>,
    719      "Must use copy constructor");
    720 }
    721 
    722 TEST(IntervalSet, Substraction)
    723 {
    724  IntIntervals i0;
    725  i0 += IntInterval(5, 10);
    726  i0 += IntInterval(20, 25);
    727  i0 += IntInterval(40, 60);
    728 
    729  IntInterval i1(8, 15);
    730  i0 -= i1;
    731 
    732  EXPECT_EQ(3u, i0.Length());
    733  EXPECT_EQ(5, i0[0].mStart);
    734  EXPECT_EQ(8, i0[0].mEnd);
    735  EXPECT_EQ(20, i0[1].mStart);
    736  EXPECT_EQ(25, i0[1].mEnd);
    737  EXPECT_EQ(40, i0[2].mStart);
    738  EXPECT_EQ(60, i0[2].mEnd);
    739 
    740  i0 = IntIntervals();
    741  i0 += IntInterval(5, 10);
    742  i0 += IntInterval(20, 25);
    743  i0 += IntInterval(40, 60);
    744  i1 = IntInterval(0, 60);
    745  i0 -= i1;
    746  EXPECT_TRUE(i0.IsEmpty());
    747 
    748  i0 = IntIntervals();
    749  i0 += IntInterval(5, 10);
    750  i0 += IntInterval(20, 25);
    751  i0 += IntInterval(40, 60);
    752  i1 = IntInterval(0, 45);
    753  i0 -= i1;
    754  EXPECT_EQ(1u, i0.Length());
    755  EXPECT_EQ(45, i0[0].mStart);
    756  EXPECT_EQ(60, i0[0].mEnd);
    757 
    758  i0 = IntIntervals();
    759  i0 += IntInterval(5, 10);
    760  i0 += IntInterval(20, 25);
    761  i0 += IntInterval(40, 60);
    762  i1 = IntInterval(8, 45);
    763  i0 -= i1;
    764  EXPECT_EQ(2u, i0.Length());
    765  EXPECT_EQ(5, i0[0].mStart);
    766  EXPECT_EQ(8, i0[0].mEnd);
    767  EXPECT_EQ(45, i0[1].mStart);
    768  EXPECT_EQ(60, i0[1].mEnd);
    769 
    770  i0 = IntIntervals();
    771  i0 += IntInterval(5, 10);
    772  i0 += IntInterval(20, 25);
    773  i0 += IntInterval(40, 60);
    774  i1 = IntInterval(8, 70);
    775  i0 -= i1;
    776  EXPECT_EQ(1u, i0.Length());
    777  EXPECT_EQ(5, i0[0].mStart);
    778  EXPECT_EQ(8, i0[0].mEnd);
    779 
    780  i0 = IntIntervals();
    781  i0 += IntInterval(0, 10);
    782  IntIntervals i2;
    783  i2 += IntInterval(4, 6);
    784  i0 -= i2;
    785  EXPECT_EQ(2u, i0.Length());
    786  EXPECT_EQ(0, i0[0].mStart);
    787  EXPECT_EQ(4, i0[0].mEnd);
    788  EXPECT_EQ(6, i0[1].mStart);
    789  EXPECT_EQ(10, i0[1].mEnd);
    790 
    791  i0 = IntIntervals();
    792  i0 += IntInterval(0, 1);
    793  i0 += IntInterval(3, 10);
    794  EXPECT_EQ(2u, i0.Length());
    795  // This fuzz should collapse i0 into [0,10).
    796  i0.SetFuzz(1);
    797  EXPECT_EQ(1u, i0.Length());
    798  EXPECT_EQ(1, i0[0].mFuzz);
    799  i2 = IntInterval(4, 6);
    800  i0 -= i2;
    801  EXPECT_EQ(2u, i0.Length());
    802  EXPECT_EQ(0, i0[0].mStart);
    803  EXPECT_EQ(4, i0[0].mEnd);
    804  EXPECT_EQ(6, i0[1].mStart);
    805  EXPECT_EQ(10, i0[1].mEnd);
    806  EXPECT_EQ(1, i0[0].mFuzz);
    807  EXPECT_EQ(1, i0[1].mFuzz);
    808 
    809  i0 = IntIntervals();
    810  i0 += IntInterval(0, 10);
    811  // [4,6) with fuzz 1 used to fail because the complementary interval set
    812  // [0,4)+[6,10) would collapse into [0,10).
    813  i2 = IntInterval(4, 6);
    814  i2.SetFuzz(1);
    815  i0 -= i2;
    816  EXPECT_EQ(2u, i0.Length());
    817  EXPECT_EQ(0, i0[0].mStart);
    818  EXPECT_EQ(4, i0[0].mEnd);
    819  EXPECT_EQ(6, i0[1].mStart);
    820  EXPECT_EQ(10, i0[1].mEnd);
    821 }