1/* 2 * Copyright (c) 2013, Google Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: 7 * 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above 11 * copyright notice, this list of conditions and the following disclaimer 12 * in the documentation and/or other materials provided with the 13 * distribution. 14 * * Neither the name of Google Inc. nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31#include "config.h" 32#include "core/html/TimeRanges.h" 33 34#include "bindings/core/v8/ExceptionStatePlaceholder.h" 35#include <gtest/gtest.h> 36 37#include <sstream> 38 39using blink::TimeRanges; 40 41static std::string ToString(const TimeRanges& ranges) 42{ 43 std::stringstream ss; 44 ss << "{"; 45 for (unsigned i = 0; i < ranges.length(); ++i) 46 ss << " [" << ranges.start(i, IGNORE_EXCEPTION) << "," << ranges.end(i, IGNORE_EXCEPTION) << ")"; 47 ss << " }"; 48 49 return ss.str(); 50} 51 52#define ASSERT_RANGE(expected, range) ASSERT_EQ(expected, ToString(*range)) 53 54TEST(TimeRanges, Empty) 55{ 56 ASSERT_RANGE("{ }", TimeRanges::create()); 57} 58 59TEST(TimeRanges, SingleRange) 60{ 61 ASSERT_RANGE("{ [1,2) }", TimeRanges::create(1, 2)); 62} 63 64TEST(TimeRanges, CreateFromWebTimeRanges) 65{ 66 blink::WebTimeRanges webRanges(static_cast<size_t>(2)); 67 webRanges[0].start = 0; 68 webRanges[0].end = 1; 69 webRanges[1].start = 2; 70 webRanges[1].end = 3; 71 ASSERT_RANGE("{ [0,1) [2,3) }", TimeRanges::create(webRanges)); 72} 73 74TEST(TimeRanges, AddOrder) 75{ 76 RefPtrWillBeRawPtr<TimeRanges> rangeA = TimeRanges::create(); 77 RefPtrWillBeRawPtr<TimeRanges> rangeB = TimeRanges::create(); 78 79 rangeA->add(0, 2); 80 rangeA->add(3, 4); 81 rangeA->add(5, 100); 82 83 std::string expected = "{ [0,2) [3,4) [5,100) }"; 84 ASSERT_RANGE(expected, rangeA); 85 86 // Add the values in rangeA to rangeB in reverse order. 87 for (int i = rangeA->length() - 1; i >= 0; --i) 88 rangeB->add(rangeA->start(i, IGNORE_EXCEPTION), rangeA->end(i, IGNORE_EXCEPTION)); 89 90 ASSERT_RANGE(expected, rangeB); 91} 92 93TEST(TimeRanges, OverlappingAdds) 94{ 95 RefPtrWillBeRawPtr<TimeRanges> ranges = TimeRanges::create(); 96 97 ranges->add(0, 2); 98 ranges->add(10, 11); 99 ASSERT_RANGE("{ [0,2) [10,11) }", ranges); 100 101 ranges->add(0, 2); 102 ASSERT_RANGE("{ [0,2) [10,11) }", ranges); 103 104 ranges->add(2, 3); 105 ASSERT_RANGE("{ [0,3) [10,11) }", ranges); 106 107 ranges->add(2, 6); 108 ASSERT_RANGE("{ [0,6) [10,11) }", ranges); 109 110 ranges->add(9, 10); 111 ASSERT_RANGE("{ [0,6) [9,11) }", ranges); 112 113 ranges->add(8, 10); 114 ASSERT_RANGE("{ [0,6) [8,11) }", ranges); 115 116 ranges->add(-1, 7); 117 ASSERT_RANGE("{ [-1,7) [8,11) }", ranges); 118 119 ranges->add(6, 9); 120 ASSERT_RANGE("{ [-1,11) }", ranges); 121} 122 123TEST(TimeRanges, IntersectWith_Self) 124{ 125 RefPtrWillBeRawPtr<TimeRanges> ranges = TimeRanges::create(0, 2); 126 127 ASSERT_RANGE("{ [0,2) }", ranges); 128 129 ranges->intersectWith(ranges.get()); 130 131 ASSERT_RANGE("{ [0,2) }", ranges); 132} 133 134TEST(TimeRanges, IntersectWith_IdenticalRange) 135{ 136 RefPtrWillBeRawPtr<TimeRanges> rangesA = TimeRanges::create(0, 2); 137 RefPtrWillBeRawPtr<TimeRanges> rangesB = rangesA->copy(); 138 139 ASSERT_RANGE("{ [0,2) }", rangesA); 140 ASSERT_RANGE("{ [0,2) }", rangesB); 141 142 rangesA->intersectWith(rangesB.get()); 143 144 ASSERT_RANGE("{ [0,2) }", rangesA); 145 ASSERT_RANGE("{ [0,2) }", rangesB); 146} 147 148TEST(TimeRanges, IntersectWith_Empty) 149{ 150 RefPtrWillBeRawPtr<TimeRanges> rangesA = TimeRanges::create(0, 2); 151 RefPtrWillBeRawPtr<TimeRanges> rangesB = TimeRanges::create(); 152 153 ASSERT_RANGE("{ [0,2) }", rangesA); 154 ASSERT_RANGE("{ }", rangesB); 155 156 rangesA->intersectWith(rangesB.get()); 157 158 ASSERT_RANGE("{ }", rangesA); 159 ASSERT_RANGE("{ }", rangesB); 160} 161 162TEST(TimeRanges, IntersectWith_DisjointRanges1) 163{ 164 RefPtrWillBeRawPtr<TimeRanges> rangesA = TimeRanges::create(); 165 RefPtrWillBeRawPtr<TimeRanges> rangesB = TimeRanges::create(); 166 167 rangesA->add(0, 1); 168 rangesA->add(4, 5); 169 170 rangesB->add(2, 3); 171 rangesB->add(6, 7); 172 173 ASSERT_RANGE("{ [0,1) [4,5) }", rangesA); 174 ASSERT_RANGE("{ [2,3) [6,7) }", rangesB); 175 176 rangesA->intersectWith(rangesB.get()); 177 178 ASSERT_RANGE("{ }", rangesA); 179 ASSERT_RANGE("{ [2,3) [6,7) }", rangesB); 180} 181 182TEST(TimeRanges, IntersectWith_DisjointRanges2) 183{ 184 RefPtrWillBeRawPtr<TimeRanges> rangesA = TimeRanges::create(); 185 RefPtrWillBeRawPtr<TimeRanges> rangesB = TimeRanges::create(); 186 187 rangesA->add(0, 1); 188 rangesA->add(4, 5); 189 190 rangesB->add(1, 4); 191 rangesB->add(5, 7); 192 193 ASSERT_RANGE("{ [0,1) [4,5) }", rangesA); 194 ASSERT_RANGE("{ [1,4) [5,7) }", rangesB); 195 196 rangesA->intersectWith(rangesB.get()); 197 198 ASSERT_RANGE("{ }", rangesA); 199 ASSERT_RANGE("{ [1,4) [5,7) }", rangesB); 200} 201 202TEST(TimeRanges, IntersectWith_CompleteOverlap1) 203{ 204 RefPtrWillBeRawPtr<TimeRanges> rangesA = TimeRanges::create(); 205 RefPtrWillBeRawPtr<TimeRanges> rangesB = TimeRanges::create(); 206 207 rangesA->add(1, 3); 208 rangesA->add(4, 5); 209 rangesA->add(6, 9); 210 211 rangesB->add(0, 10); 212 213 ASSERT_RANGE("{ [1,3) [4,5) [6,9) }", rangesA); 214 ASSERT_RANGE("{ [0,10) }", rangesB); 215 216 rangesA->intersectWith(rangesB.get()); 217 218 ASSERT_RANGE("{ [1,3) [4,5) [6,9) }", rangesA); 219 ASSERT_RANGE("{ [0,10) }", rangesB); 220} 221 222TEST(TimeRanges, IntersectWith_CompleteOverlap2) 223{ 224 RefPtrWillBeRawPtr<TimeRanges> rangesA = TimeRanges::create(); 225 RefPtrWillBeRawPtr<TimeRanges> rangesB = TimeRanges::create(); 226 227 rangesA->add(1, 3); 228 rangesA->add(4, 5); 229 rangesA->add(6, 9); 230 231 rangesB->add(1, 9); 232 233 ASSERT_RANGE("{ [1,3) [4,5) [6,9) }", rangesA); 234 ASSERT_RANGE("{ [1,9) }", rangesB); 235 236 rangesA->intersectWith(rangesB.get()); 237 238 ASSERT_RANGE("{ [1,3) [4,5) [6,9) }", rangesA); 239 ASSERT_RANGE("{ [1,9) }", rangesB); 240} 241 242TEST(TimeRanges, IntersectWith_Gaps1) 243{ 244 RefPtrWillBeRawPtr<TimeRanges> rangesA = TimeRanges::create(); 245 RefPtrWillBeRawPtr<TimeRanges> rangesB = TimeRanges::create(); 246 247 rangesA->add(0, 2); 248 rangesA->add(4, 6); 249 250 rangesB->add(1, 5); 251 252 ASSERT_RANGE("{ [0,2) [4,6) }", rangesA); 253 ASSERT_RANGE("{ [1,5) }", rangesB); 254 255 rangesA->intersectWith(rangesB.get()); 256 257 ASSERT_RANGE("{ [1,2) [4,5) }", rangesA); 258 ASSERT_RANGE("{ [1,5) }", rangesB); 259} 260 261TEST(TimeRanges, IntersectWith_Gaps2) 262{ 263 RefPtrWillBeRawPtr<TimeRanges> rangesA = TimeRanges::create(); 264 RefPtrWillBeRawPtr<TimeRanges> rangesB = TimeRanges::create(); 265 266 rangesA->add(0, 2); 267 rangesA->add(4, 6); 268 rangesA->add(8, 10); 269 270 rangesB->add(1, 9); 271 272 ASSERT_RANGE("{ [0,2) [4,6) [8,10) }", rangesA); 273 ASSERT_RANGE("{ [1,9) }", rangesB); 274 275 rangesA->intersectWith(rangesB.get()); 276 277 ASSERT_RANGE("{ [1,2) [4,6) [8,9) }", rangesA); 278 ASSERT_RANGE("{ [1,9) }", rangesB); 279} 280 281TEST(TimeRanges, IntersectWith_Gaps3) 282{ 283 RefPtrWillBeRawPtr<TimeRanges> rangesA = TimeRanges::create(); 284 RefPtrWillBeRawPtr<TimeRanges> rangesB = TimeRanges::create(); 285 286 rangesA->add(0, 2); 287 rangesA->add(4, 7); 288 rangesA->add(8, 10); 289 290 rangesB->add(1, 5); 291 rangesB->add(6, 9); 292 293 ASSERT_RANGE("{ [0,2) [4,7) [8,10) }", rangesA); 294 ASSERT_RANGE("{ [1,5) [6,9) }", rangesB); 295 296 rangesA->intersectWith(rangesB.get()); 297 298 ASSERT_RANGE("{ [1,2) [4,5) [6,7) [8,9) }", rangesA); 299 ASSERT_RANGE("{ [1,5) [6,9) }", rangesB); 300} 301 302TEST(TimeRanges, Nearest) 303{ 304 RefPtrWillBeRawPtr<TimeRanges> ranges = TimeRanges::create(); 305 ranges->add(0, 2); 306 ranges->add(5, 7); 307 308 ASSERT_EQ(0, ranges->nearest(0, 0)); 309 ASSERT_EQ(1, ranges->nearest(1, 0)); 310 ASSERT_EQ(2, ranges->nearest(2, 0)); 311 ASSERT_EQ(2, ranges->nearest(3, 0)); 312 ASSERT_EQ(5, ranges->nearest(4, 0)); 313 ASSERT_EQ(5, ranges->nearest(5, 0)); 314 ASSERT_EQ(7, ranges->nearest(8, 0)); 315 316 ranges->add(9, 11); 317 ASSERT_EQ(7, ranges->nearest(8, 6)); 318 ASSERT_EQ(7, ranges->nearest(8, 8)); 319 ASSERT_EQ(9, ranges->nearest(8, 10)); 320} 321