gecko-dev/dom/media/gtest/TestIntervalSet.cpp
Chris Pearce 4ffa31745b Bug 1392498 - Move TimeIntervals to dom::TimeRanges conversion into TimeRanges class. r=jya
If TimeUnits.h includes mozilla/dom/TimeRanges.h, then the build ends up
pulling in the Gecko DOM bindings, which pulls in a whole lot of JavaScript and
DOM bindings code. That makes it trickier to import GeckoMedia into Servo, and
makes Gecko's build slower, so move the code to convert TimeIntervals into
dom::TimeRanges.

Also remove an extraneous "virtual" and add "const" to some functions in TimeRanges.

MozReview-Commit-ID: BLeehaf9gCE

--HG--
extra : rebase_source : 84ef054cf8fd5b4434dc761a1b0a39803d3231f5
2017-08-21 15:08:25 +12:00

805 lines
22 KiB
C++

/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "gtest/gtest.h"
#include "mozilla/dom/TimeRanges.h"
#include "TimeUnits.h"
#include "Intervals.h"
#include <algorithm>
#include <vector>
using namespace mozilla;
typedef media::Interval<uint8_t> ByteInterval;
typedef media::Interval<int> IntInterval;
typedef media::IntervalSet<int> IntIntervals;
ByteInterval CreateByteInterval(int32_t aStart, int32_t aEnd)
{
ByteInterval test(aStart, aEnd);
return test;
}
media::IntervalSet<uint8_t> CreateByteIntervalSet(int32_t aStart, int32_t aEnd)
{
media::IntervalSet<uint8_t> test;
test += ByteInterval(aStart, aEnd);
return test;
}
TEST(IntervalSet, Constructors)
{
const int32_t start = 1;
const int32_t end = 2;
const int32_t fuzz = 0;
// Compiler exercise.
ByteInterval test1(start, end);
ByteInterval test2(test1);
ByteInterval test3(start, end, fuzz);
ByteInterval test4(test3);
ByteInterval test5 = CreateByteInterval(start, end);
media::IntervalSet<uint8_t> blah1(test1);
media::IntervalSet<uint8_t> blah2 = blah1;
media::IntervalSet<uint8_t> blah3 = blah1 + test1;
media::IntervalSet<uint8_t> blah4 = test1 + blah1;
media::IntervalSet<uint8_t> blah5 = CreateByteIntervalSet(start, end);
(void)test1; (void)test2; (void)test3; (void)test4; (void)test5;
(void)blah1; (void)blah2; (void)blah3; (void)blah4; (void)blah5;
}
media::TimeInterval CreateTimeInterval(int32_t aStart, int32_t aEnd)
{
// Copy constructor test
media::TimeUnit start = media::TimeUnit::FromMicroseconds(aStart);
media::TimeUnit end;
// operator= test
end = media::TimeUnit::FromMicroseconds(aEnd);
media::TimeInterval ti(start, end);
return ti;
}
media::TimeIntervals CreateTimeIntervals(int32_t aStart, int32_t aEnd)
{
media::TimeIntervals test;
test += CreateTimeInterval(aStart, aEnd);
return test;
}
TEST(IntervalSet, TimeIntervalsConstructors)
{
const auto start = media::TimeUnit::FromMicroseconds(1);
const auto end = media::TimeUnit::FromMicroseconds(2);
const media::TimeUnit fuzz;
// Compiler exercise.
media::TimeInterval test1(start, end);
media::TimeInterval test2(test1);
media::TimeInterval test3(start, end, fuzz);
media::TimeInterval test4(test3);
media::TimeInterval test5 =
CreateTimeInterval(start.ToMicroseconds(), end.ToMicroseconds());
media::TimeIntervals blah1(test1);
media::TimeIntervals blah2(blah1);
media::TimeIntervals blah3 = blah1 + test1;
media::TimeIntervals blah4 = test1 + blah1;
media::TimeIntervals blah5 =
CreateTimeIntervals(start.ToMicroseconds(), end.ToMicroseconds());
(void)test1; (void)test2; (void)test3; (void)test4; (void)test5;
(void)blah1; (void)blah2; (void)blah3; (void)blah4; (void)blah5;
media::TimeIntervals i0{media::TimeInterval(media::TimeUnit::FromSeconds(0),
media::TimeUnit::FromSeconds(0))};
EXPECT_EQ(0u, i0.Length()); // Constructing with an empty time interval.
}
TEST(IntervalSet, Length)
{
IntInterval i(15, 25);
EXPECT_EQ(10, i.Length());
}
TEST(IntervalSet, Intersects)
{
EXPECT_TRUE(IntInterval(1,5).Intersects(IntInterval(3,4)));
EXPECT_TRUE(IntInterval(1,5).Intersects(IntInterval(3,7)));
EXPECT_TRUE(IntInterval(1,5).Intersects(IntInterval(-1,3)));
EXPECT_TRUE(IntInterval(1,5).Intersects(IntInterval(-1,7)));
EXPECT_FALSE(IntInterval(1,5).Intersects(IntInterval(6,7)));
EXPECT_FALSE(IntInterval(1,5).Intersects(IntInterval(-1,0)));
// End boundary is exclusive of the interval.
EXPECT_FALSE(IntInterval(1,5).Intersects(IntInterval(5,7)));
EXPECT_FALSE(IntInterval(1,5).Intersects(IntInterval(0,1)));
// Empty identical interval do not intersect.
EXPECT_FALSE(IntInterval(1,1).Intersects(IntInterval(1,1)));
// Empty interval do not intersect.
EXPECT_FALSE(IntInterval(1,1).Intersects(IntInterval(2,2)));
}
TEST(IntervalSet, Intersection)
{
IntInterval i0(10, 20);
IntInterval i1(15, 25);
IntInterval i = i0.Intersection(i1);
EXPECT_EQ(15, i.mStart);
EXPECT_EQ(20, i.mEnd);
IntInterval j0(10, 20);
IntInterval j1(20, 25);
IntInterval j = j0.Intersection(j1);
EXPECT_TRUE(j.IsEmpty());
IntInterval k0(2, 2);
IntInterval k1(2, 2);
IntInterval k = k0.Intersection(k1);
EXPECT_TRUE(k.IsEmpty());
}
TEST(IntervalSet, Equals)
{
IntInterval i0(10, 20);
IntInterval i1(10, 20);
EXPECT_EQ(i0, i1);
IntInterval i2(5, 20);
EXPECT_NE(i0, i2);
IntInterval i3(10, 15);
EXPECT_NE(i0, i2);
}
TEST(IntervalSet, IntersectionIntervalSet)
{
IntIntervals i0;
i0 += IntInterval(5, 10);
i0 += IntInterval(20, 25);
i0 += IntInterval(40, 60);
IntIntervals i1;
i1.Add(IntInterval(7, 15));
i1.Add(IntInterval(16, 27));
i1.Add(IntInterval(45, 50));
i1.Add(IntInterval(53, 57));
IntIntervals i = media::Intersection(i0, i1);
EXPECT_EQ(4u, i.Length());
EXPECT_EQ(7, i[0].mStart);
EXPECT_EQ(10, i[0].mEnd);
EXPECT_EQ(20, i[1].mStart);
EXPECT_EQ(25, i[1].mEnd);
EXPECT_EQ(45, i[2].mStart);
EXPECT_EQ(50, i[2].mEnd);
EXPECT_EQ(53, i[3].mStart);
EXPECT_EQ(57, i[3].mEnd);
}
template<typename T>
static void Compare(const media::IntervalSet<T>& aI1,
const media::IntervalSet<T>& aI2)
{
EXPECT_EQ(aI1.Length(), aI2.Length());
if (aI1.Length() != aI2.Length()) {
return;
}
for (uint32_t i = 0; i < aI1.Length(); i++) {
EXPECT_EQ(aI1[i].mStart, aI2[i].mStart);
EXPECT_EQ(aI1[i].mEnd, aI2[i].mEnd);
}
}
static void GeneratePermutations(const IntIntervals& aI1,
const IntIntervals& aI2)
{
IntIntervals i_ref = media::Intersection(aI1, aI2);
// Test all permutations possible
std::vector<uint32_t> comb1;
for (uint32_t i = 0; i < aI1.Length(); i++) {
comb1.push_back(i);
}
std::vector<uint32_t> comb2;
for (uint32_t i = 0; i < aI2.Length(); i++) {
comb2.push_back(i);
}
do {
do {
// Create intervals according to new indexes.
IntIntervals i_0;
for (uint32_t i = 0; i < comb1.size(); i++) {
i_0 += aI1[comb1[i]];
}
// Test that intervals are always normalized.
Compare(aI1, i_0);
IntIntervals i_1;
for (uint32_t i = 0; i < comb2.size(); i++) {
i_1 += aI2[comb2[i]];
}
Compare(aI2, i_1);
// Check intersections yield the same result.
Compare(i_0.Intersection(i_1), i_ref);
} while (std::next_permutation(comb2.begin(), comb2.end()));
} while (std::next_permutation(comb1.begin(), comb1.end()));
}
TEST(IntervalSet, IntersectionNormalizedIntervalSet)
{
IntIntervals i0;
i0 += IntInterval(5, 10);
i0 += IntInterval(20, 25);
i0 += IntInterval(40, 60);
IntIntervals i1;
i1.Add(IntInterval(7, 15));
i1.Add(IntInterval(16, 27));
i1.Add(IntInterval(45, 50));
i1.Add(IntInterval(53, 57));
GeneratePermutations(i0, i1);
}
TEST(IntervalSet, IntersectionUnorderedNonNormalizedIntervalSet)
{
IntIntervals i0;
i0 += IntInterval(5, 10);
i0 += IntInterval(8, 25);
i0 += IntInterval(24, 60);
IntIntervals i1;
i1.Add(IntInterval(7, 15));
i1.Add(IntInterval(10, 27));
i1.Add(IntInterval(45, 50));
i1.Add(IntInterval(53, 57));
GeneratePermutations(i0, i1);
}
TEST(IntervalSet, IntersectionNonNormalizedInterval)
{
IntIntervals i0;
i0 += IntInterval(5, 10);
i0 += IntInterval(8, 25);
i0 += IntInterval(30, 60);
media::Interval<int> i1(9, 15);
i0.Intersection(i1);
EXPECT_EQ(1u, i0.Length());
EXPECT_EQ(i0[0].mStart, i1.mStart);
EXPECT_EQ(i0[0].mEnd, i1.mEnd);
}
TEST(IntervalSet, IntersectionUnorderedNonNormalizedInterval)
{
IntIntervals i0;
i0 += IntInterval(1, 3);
i0 += IntInterval(1, 10);
i0 += IntInterval(9, 12);
i0 += IntInterval(12, 15);
i0 += IntInterval(8, 25);
i0 += IntInterval(30, 60);
i0 += IntInterval(5, 10);
i0 += IntInterval(30, 60);
media::Interval<int> i1(9, 15);
i0.Intersection(i1);
EXPECT_EQ(1u, i0.Length());
EXPECT_EQ(i0[0].mStart, i1.mStart);
EXPECT_EQ(i0[0].mEnd, i1.mEnd);
}
static IntIntervals Duplicate(const IntIntervals& aValue)
{
IntIntervals value(aValue);
return value;
}
TEST(IntervalSet, Normalize)
{
IntIntervals i;
// Test IntervalSet<T> + Interval<T> operator.
i = i + IntInterval(20, 30);
// Test Internal<T> + IntervalSet<T> operator.
i = IntInterval(2, 7) + i;
// Test Interval<T> + IntervalSet<T> operator
i = IntInterval(1, 8) + i;
IntIntervals interval;
interval += IntInterval(5, 10);
// Test += with rval move.
i += Duplicate(interval);
// Test = with move and add with move.
i = Duplicate(interval) + i;
EXPECT_EQ(2u, i.Length());
EXPECT_EQ(1, i[0].mStart);
EXPECT_EQ(10, i[0].mEnd);
EXPECT_EQ(20, i[1].mStart);
EXPECT_EQ(30, i[1].mEnd);
media::TimeIntervals ti;
ti += media::TimeInterval(media::TimeUnit::FromSeconds(0.0),
media::TimeUnit::FromSeconds(3.203333));
ti += media::TimeInterval(media::TimeUnit::FromSeconds(3.203366),
media::TimeUnit::FromSeconds(10.010065));
EXPECT_EQ(2u, ti.Length());
ti += media::TimeInterval(ti.Start(0), ti.End(0), media::TimeUnit::FromMicroseconds(35000));
EXPECT_EQ(1u, ti.Length());
}
TEST(IntervalSet, ContainValue)
{
IntIntervals i0;
i0 += IntInterval(0, 10);
i0 += IntInterval(15, 20);
i0 += IntInterval(30, 50);
EXPECT_TRUE(i0.Contains(0)); // start is inclusive.
EXPECT_TRUE(i0.Contains(17));
EXPECT_FALSE(i0.Contains(20)); // end boundary is exclusive.
EXPECT_FALSE(i0.Contains(25));
}
TEST(IntervalSet, ContainValueWithFuzz)
{
IntIntervals i0;
i0 += IntInterval(0, 10);
i0 += IntInterval(15, 20, 1);
i0 += IntInterval(30, 50);
EXPECT_TRUE(i0.Contains(0)); // start is inclusive.
EXPECT_TRUE(i0.Contains(17));
EXPECT_TRUE(i0.Contains(20)); // end boundary is exclusive but we have a fuzz of 1.
EXPECT_FALSE(i0.Contains(25));
}
TEST(IntervalSet, ContainInterval)
{
IntIntervals i0;
i0 += IntInterval(0, 10);
i0 += IntInterval(15, 20);
i0 += IntInterval(30, 50);
EXPECT_TRUE(i0.Contains(IntInterval(2, 8)));
EXPECT_TRUE(i0.Contains(IntInterval(31, 50)));
EXPECT_TRUE(i0.Contains(IntInterval(0, 10)));
EXPECT_FALSE(i0.Contains(IntInterval(0, 11)));
EXPECT_TRUE(i0.Contains(IntInterval(0, 5)));
EXPECT_FALSE(i0.Contains(IntInterval(8, 15)));
EXPECT_FALSE(i0.Contains(IntInterval(15, 30)));
EXPECT_FALSE(i0.Contains(IntInterval(30, 55)));
}
TEST(IntervalSet, ContainIntervalWithFuzz)
{
IntIntervals i0;
i0 += IntInterval(0, 10);
i0 += IntInterval(15, 20);
i0 += IntInterval(30, 50);
EXPECT_TRUE(i0.Contains(IntInterval(2, 8)));
EXPECT_TRUE(i0.Contains(IntInterval(31, 50)));
EXPECT_TRUE(i0.Contains(IntInterval(0, 11, 1)));
EXPECT_TRUE(i0.Contains(IntInterval(0, 5)));
EXPECT_FALSE(i0.Contains(IntInterval(8, 15)));
EXPECT_FALSE(i0.Contains(IntInterval(15, 21)));
EXPECT_FALSE(i0.Contains(IntInterval(15, 30)));
EXPECT_FALSE(i0.Contains(IntInterval(30, 55)));
IntIntervals i1;
i1 += IntInterval(0, 10, 1);
i1 += IntInterval(15, 20, 1);
i1 += IntInterval(30, 50, 1);
EXPECT_TRUE(i1.Contains(IntInterval(2, 8)));
EXPECT_TRUE(i1.Contains(IntInterval(29, 51)));
EXPECT_TRUE(i1.Contains(IntInterval(0, 11, 1)));
EXPECT_TRUE(i1.Contains(IntInterval(15, 21)));
}
TEST(IntervalSet, Span)
{
IntInterval i0(0,10);
IntInterval i1(20,30);
IntInterval i{i0.Span(i1)};
EXPECT_EQ(i.mStart, 0);
EXPECT_EQ(i.mEnd, 30);
}
TEST(IntervalSet, Union)
{
IntIntervals i0;
i0 += IntInterval(5, 10);
i0 += IntInterval(20, 25);
i0 += IntInterval(40, 60);
IntIntervals i1;
i1.Add(IntInterval(7, 15));
i1.Add(IntInterval(16, 27));
i1.Add(IntInterval(45, 50));
i1.Add(IntInterval(53, 57));
IntIntervals i = media::Union(i0, i1);
EXPECT_EQ(3u, i.Length());
EXPECT_EQ(5, i[0].mStart);
EXPECT_EQ(15, i[0].mEnd);
EXPECT_EQ(16, i[1].mStart);
EXPECT_EQ(27, i[1].mEnd);
EXPECT_EQ(40, i[2].mStart);
EXPECT_EQ(60, i[2].mEnd);
}
TEST(IntervalSet, UnionNotOrdered)
{
IntIntervals i0;
i0 += IntInterval(20, 25);
i0 += IntInterval(40, 60);
i0 += IntInterval(5, 10);
IntIntervals i1;
i1.Add(IntInterval(16, 27));
i1.Add(IntInterval(7, 15));
i1.Add(IntInterval(53, 57));
i1.Add(IntInterval(45, 50));
IntIntervals i = media::Union(i0, i1);
EXPECT_EQ(3u, i.Length());
EXPECT_EQ(5, i[0].mStart);
EXPECT_EQ(15, i[0].mEnd);
EXPECT_EQ(16, i[1].mStart);
EXPECT_EQ(27, i[1].mEnd);
EXPECT_EQ(40, i[2].mStart);
EXPECT_EQ(60, i[2].mEnd);
}
TEST(IntervalSet, NormalizeFuzz)
{
IntIntervals i0;
i0 += IntInterval(11, 25, 0);
i0 += IntInterval(5, 10, 1);
i0 += IntInterval(40, 60, 1);
EXPECT_EQ(2u, i0.Length());
EXPECT_EQ(5, i0[0].mStart);
EXPECT_EQ(25, i0[0].mEnd);
EXPECT_EQ(40, i0[1].mStart);
EXPECT_EQ(60, i0[1].mEnd);
}
TEST(IntervalSet, UnionFuzz)
{
IntIntervals i0;
i0 += IntInterval(5, 10, 1);
i0 += IntInterval(11, 25, 0);
i0 += IntInterval(40, 60, 1);
EXPECT_EQ(2u, i0.Length());
EXPECT_EQ(5, i0[0].mStart);
EXPECT_EQ(25, i0[0].mEnd);
EXPECT_EQ(40, i0[1].mStart);
EXPECT_EQ(60, i0[1].mEnd);
IntIntervals i1;
i1.Add(IntInterval(7, 15, 1));
i1.Add(IntInterval(16, 27, 1));
i1.Add(IntInterval(45, 50, 1));
i1.Add(IntInterval(53, 57, 1));
EXPECT_EQ(3u, i1.Length());
EXPECT_EQ(7, i1[0].mStart);
EXPECT_EQ(27, i1[0].mEnd);
EXPECT_EQ(45, i1[1].mStart);
EXPECT_EQ(50, i1[1].mEnd);
EXPECT_EQ(53, i1[2].mStart);
EXPECT_EQ(57, i1[2].mEnd);
IntIntervals i = media::Union(i0, i1);
EXPECT_EQ(2u, i.Length());
EXPECT_EQ(5, i[0].mStart);
EXPECT_EQ(27, i[0].mEnd);
EXPECT_EQ(40, i[1].mStart);
EXPECT_EQ(60, i[1].mEnd);
}
TEST(IntervalSet, Contiguous)
{
EXPECT_FALSE(IntInterval(5, 10).Contiguous(IntInterval(11, 25)));
EXPECT_TRUE(IntInterval(5, 10).Contiguous(IntInterval(10, 25)));
EXPECT_TRUE(IntInterval(5, 10, 1).Contiguous(IntInterval(11, 25)));
EXPECT_TRUE(IntInterval(5, 10).Contiguous(IntInterval(11, 25, 1)));
}
TEST(IntervalSet, TimeRangesSeconds)
{
media::TimeIntervals i0;
i0 += media::TimeInterval(media::TimeUnit::FromSeconds(20), media::TimeUnit::FromSeconds(25));
i0 += media::TimeInterval(media::TimeUnit::FromSeconds(40), media::TimeUnit::FromSeconds(60));
i0 += media::TimeInterval(media::TimeUnit::FromSeconds(5), media::TimeUnit::FromSeconds(10));
media::TimeIntervals i1;
i1.Add(media::TimeInterval(media::TimeUnit::FromSeconds(16), media::TimeUnit::FromSeconds(27)));
i1.Add(media::TimeInterval(media::TimeUnit::FromSeconds(7), media::TimeUnit::FromSeconds(15)));
i1.Add(media::TimeInterval(media::TimeUnit::FromSeconds(53), media::TimeUnit::FromSeconds(57)));
i1.Add(media::TimeInterval(media::TimeUnit::FromSeconds(45), media::TimeUnit::FromSeconds(50)));
media::TimeIntervals i(i0 + i1);
RefPtr<dom::TimeRanges> tr = new dom::TimeRanges(i);
EXPECT_EQ(tr->Length(), i.Length());
for (dom::TimeRanges::index_type index = 0; index < tr->Length(); index++) {
ErrorResult rv;
EXPECT_EQ(tr->Start(index, rv), i[index].mStart.ToSeconds());
EXPECT_EQ(tr->Start(index, rv), i.Start(index).ToSeconds());
EXPECT_EQ(tr->End(index, rv), i[index].mEnd.ToSeconds());
EXPECT_EQ(tr->End(index, rv), i.End(index).ToSeconds());
}
}
static void CheckTimeRanges(dom::TimeRanges* aTr, const media::TimeIntervals& aTi)
{
RefPtr<dom::TimeRanges> tr = new dom::TimeRanges;
tr->Union(aTr, 0); // This will normalize the time range.
EXPECT_EQ(tr->Length(), aTi.Length());
for (dom::TimeRanges::index_type i = 0; i < tr->Length(); i++) {
ErrorResult rv;
EXPECT_EQ(tr->Start(i, rv), aTi[i].mStart.ToSeconds());
EXPECT_EQ(tr->Start(i, rv), aTi.Start(i).ToSeconds());
EXPECT_EQ(tr->End(i, rv), aTi[i].mEnd.ToSeconds());
EXPECT_EQ(tr->End(i, rv), aTi.End(i).ToSeconds());
}
}
TEST(IntervalSet, TimeRangesConversion)
{
RefPtr<dom::TimeRanges> tr = new dom::TimeRanges();
tr->Add(20, 25);
tr->Add(40, 60);
tr->Add(5, 10);
tr->Add(16, 27);
tr->Add(53, 57);
tr->Add(45, 50);
// explicit copy constructor and ToTimeIntervals.
media::TimeIntervals i1(tr->ToTimeIntervals());
CheckTimeRanges(tr, i1);
// ctor(const TimeIntervals&)
RefPtr<dom::TimeRanges> tr2 = new dom::TimeRanges(tr->ToTimeIntervals());
CheckTimeRanges(tr2, i1);
}
TEST(IntervalSet, TimeRangesMicroseconds)
{
media::TimeIntervals i0;
i0 += media::TimeInterval(media::TimeUnit::FromMicroseconds(20), media::TimeUnit::FromMicroseconds(25));
i0 += media::TimeInterval(media::TimeUnit::FromMicroseconds(40), media::TimeUnit::FromMicroseconds(60));
i0 += media::TimeInterval(media::TimeUnit::FromMicroseconds(5), media::TimeUnit::FromMicroseconds(10));
media::TimeIntervals i1;
i1.Add(media::TimeInterval(media::TimeUnit::FromMicroseconds(16), media::TimeUnit::FromMicroseconds(27)));
i1.Add(media::TimeInterval(media::TimeUnit::FromMicroseconds(7), media::TimeUnit::FromMicroseconds(15)));
i1.Add(media::TimeInterval(media::TimeUnit::FromMicroseconds(53), media::TimeUnit::FromMicroseconds(57)));
i1.Add(media::TimeInterval(media::TimeUnit::FromMicroseconds(45), media::TimeUnit::FromMicroseconds(50)));
media::TimeIntervals i(i0 + i1);
RefPtr<dom::TimeRanges> tr = new dom::TimeRanges(i);
EXPECT_EQ(tr->Length(), i.Length());
for (dom::TimeRanges::index_type index = 0; index < tr->Length(); index++) {
ErrorResult rv;
EXPECT_EQ(tr->Start(index, rv), i[index].mStart.ToSeconds());
EXPECT_EQ(tr->Start(index, rv), i.Start(index).ToSeconds());
EXPECT_EQ(tr->End(index, rv), i[index].mEnd.ToSeconds());
EXPECT_EQ(tr->End(index, rv), i.End(index).ToSeconds());
}
tr->Normalize();
EXPECT_EQ(tr->Length(), i.Length());
for (dom::TimeRanges::index_type index = 0; index < tr->Length(); index++) {
ErrorResult rv;
EXPECT_EQ(tr->Start(index, rv), i[index].mStart.ToSeconds());
EXPECT_EQ(tr->Start(index, rv), i.Start(index).ToSeconds());
EXPECT_EQ(tr->End(index, rv), i[index].mEnd.ToSeconds());
EXPECT_EQ(tr->End(index, rv), i.End(index).ToSeconds());
}
// Check infinity values aren't lost in the conversion.
tr = new dom::TimeRanges();
tr->Add(0, 30);
tr->Add(50, std::numeric_limits<double>::infinity());
media::TimeIntervals i_oo = tr->ToTimeIntervals();
RefPtr<dom::TimeRanges> tr2 = new dom::TimeRanges(i_oo);
EXPECT_EQ(tr->Length(), tr2->Length());
for (dom::TimeRanges::index_type index = 0; index < tr->Length(); index++) {
ErrorResult rv;
EXPECT_EQ(tr->Start(index, rv), tr2->Start(index, rv));
EXPECT_EQ(tr->End(index, rv), tr2->End(index, rv));
}
}
template<typename T>
class Foo
{
public:
Foo()
: mArg1(1)
, mArg2(2)
, mArg3(3)
{}
Foo(T a1, T a2, T a3)
: mArg1(a1)
, mArg2(a2)
, mArg3(a3)
{}
Foo<T> operator+ (const Foo<T>& aOther) const
{
Foo<T> blah;
blah.mArg1 += aOther.mArg1;
blah.mArg2 += aOther.mArg2;
blah.mArg3 += aOther.mArg3;
return blah;
}
Foo<T> operator- (const Foo<T>& aOther) const
{
Foo<T> blah;
blah.mArg1 -= aOther.mArg1;
blah.mArg2 -= aOther.mArg2;
blah.mArg3 -= aOther.mArg3;
return blah;
}
bool operator< (const Foo<T>& aOther) const
{
return mArg1 < aOther.mArg1;
}
bool operator== (const Foo<T>& aOther) const
{
return mArg1 == aOther.mArg1;
}
bool operator<= (const Foo<T>& aOther) const
{
return mArg1 <= aOther.mArg1;
}
private:
int32_t mArg1;
int32_t mArg2;
int32_t mArg3;
};
TEST(IntervalSet, FooIntervalSet)
{
media::Interval<Foo<int>> i(Foo<int>(), Foo<int>(4,5,6));
media::IntervalSet<Foo<int>> is;
is += i;
is += i;
is.Add(i);
is = is + i;
is = i + is;
EXPECT_EQ(1u, is.Length());
EXPECT_EQ(Foo<int>(), is[0].mStart);
EXPECT_EQ(Foo<int>(4,5,6), is[0].mEnd);
}
TEST(IntervalSet, StaticAssert)
{
media::Interval<int> i;
static_assert(mozilla::IsSame<nsTArray_CopyChooser<IntIntervals>::Type, nsTArray_CopyWithConstructors<IntIntervals>>::value, "Must use copy constructor");
static_assert(mozilla::IsSame<nsTArray_CopyChooser<media::TimeIntervals>::Type, nsTArray_CopyWithConstructors<media::TimeIntervals>>::value, "Must use copy constructor");
}
TEST(IntervalSet, Substraction)
{
IntIntervals i0;
i0 += IntInterval(5, 10);
i0 += IntInterval(20, 25);
i0 += IntInterval(40, 60);
IntInterval i1(8, 15);
i0 -= i1;
EXPECT_EQ(3u, i0.Length());
EXPECT_EQ(5, i0[0].mStart);
EXPECT_EQ(8, i0[0].mEnd);
EXPECT_EQ(20, i0[1].mStart);
EXPECT_EQ(25, i0[1].mEnd);
EXPECT_EQ(40, i0[2].mStart);
EXPECT_EQ(60, i0[2].mEnd);
i0 = IntIntervals();
i0 += IntInterval(5, 10);
i0 += IntInterval(20, 25);
i0 += IntInterval(40, 60);
i1 = IntInterval(0, 60);
i0 -= i1;
EXPECT_EQ(0u, i0.Length());
i0 = IntIntervals();
i0 += IntInterval(5, 10);
i0 += IntInterval(20, 25);
i0 += IntInterval(40, 60);
i1 = IntInterval(0, 45);
i0 -= i1;
EXPECT_EQ(1u, i0.Length());
EXPECT_EQ(45, i0[0].mStart);
EXPECT_EQ(60, i0[0].mEnd);
i0 = IntIntervals();
i0 += IntInterval(5, 10);
i0 += IntInterval(20, 25);
i0 += IntInterval(40, 60);
i1 = IntInterval(8, 45);
i0 -= i1;
EXPECT_EQ(2u, i0.Length());
EXPECT_EQ(5, i0[0].mStart);
EXPECT_EQ(8, i0[0].mEnd);
EXPECT_EQ(45, i0[1].mStart);
EXPECT_EQ(60, i0[1].mEnd);
i0 = IntIntervals();
i0 += IntInterval(5, 10);
i0 += IntInterval(20, 25);
i0 += IntInterval(40, 60);
i1 = IntInterval(8, 70);
i0 -= i1;
EXPECT_EQ(1u, i0.Length());
EXPECT_EQ(5, i0[0].mStart);
EXPECT_EQ(8, i0[0].mEnd);
i0 = IntIntervals();
i0 += IntInterval(0, 10);
IntIntervals i2;
i2 += IntInterval(4, 6);
i0 -= i2;
EXPECT_EQ(2u, i0.Length());
EXPECT_EQ(0, i0[0].mStart);
EXPECT_EQ(4, i0[0].mEnd);
EXPECT_EQ(6, i0[1].mStart);
EXPECT_EQ(10, i0[1].mEnd);
i0 = IntIntervals();
i0 += IntInterval(0, 1);
i0 += IntInterval(3, 10);
EXPECT_EQ(2u, i0.Length());
// This fuzz should collapse i0 into [0,10).
i0.SetFuzz(1);
EXPECT_EQ(1u, i0.Length());
EXPECT_EQ(1, i0[0].mFuzz);
i2 = IntInterval(4, 6);
i0 -= i2;
EXPECT_EQ(2u, i0.Length());
EXPECT_EQ(0, i0[0].mStart);
EXPECT_EQ(4, i0[0].mEnd);
EXPECT_EQ(6, i0[1].mStart);
EXPECT_EQ(10, i0[1].mEnd);
EXPECT_EQ(1, i0[0].mFuzz);
EXPECT_EQ(1, i0[1].mFuzz);
i0 = IntIntervals();
i0 += IntInterval(0, 10);
// [4,6) with fuzz 1 used to fail because the complementary interval set
// [0,4)+[6,10) would collapse into [0,10).
i2 = IntInterval(4, 6);
i2.SetFuzz(1);
i0 -= i2;
EXPECT_EQ(2u, i0.Length());
EXPECT_EQ(0, i0[0].mStart);
EXPECT_EQ(4, i0[0].mEnd);
EXPECT_EQ(6, i0[1].mStart);
EXPECT_EQ(10, i0[1].mEnd);
}