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 }