1 | import Ranges from '../src/ranges';
|
2 | import {createTimeRanges} from 'video.js';
|
3 | import QUnit from 'qunit';
|
4 |
|
5 | let rangesEqual = (rangeOne, rangeTwo) => {
|
6 | if (!rangeOne || !rangeTwo) {
|
7 | return false;
|
8 | }
|
9 |
|
10 | if (rangeOne.length !== rangeTwo.length) {
|
11 | return false;
|
12 | }
|
13 |
|
14 | for (let i = 0; i < rangeOne.length; i++) {
|
15 | if (rangeOne.start(i) !== rangeTwo.start(i) ||
|
16 | rangeOne.end(i) !== rangeTwo.end(i)) {
|
17 | return false;
|
18 | }
|
19 | }
|
20 |
|
21 | return true;
|
22 | };
|
23 |
|
24 | QUnit.module('TimeRanges Utilities');
|
25 |
|
26 | QUnit.test('finds the overlapping time range', function(assert) {
|
27 | let range = Ranges.findRange(createTimeRanges([[0, 5], [6, 12]]), 3);
|
28 |
|
29 | assert.equal(range.length, 1, 'found one range');
|
30 | assert.equal(range.end(0), 5, 'inside the first buffered region');
|
31 |
|
32 | range = Ranges.findRange(createTimeRanges([[0, 5], [6, 12]]), 6);
|
33 | assert.equal(range.length, 1, 'found one range');
|
34 | assert.equal(range.end(0), 12, 'inside the second buffered region');
|
35 | });
|
36 |
|
37 | QUnit.module('Buffer Inpsection');
|
38 |
|
39 | QUnit.test('detects time range end-point changed by updates', function(assert) {
|
40 | let edge;
|
41 |
|
42 |
|
43 | edge = Ranges.findSoleUncommonTimeRangesEnd(createTimeRanges([[0, 10]]),
|
44 | createTimeRanges([[0, 11]]));
|
45 | assert.strictEqual(edge, 11, 'detected a forward addition');
|
46 |
|
47 | edge = Ranges.findSoleUncommonTimeRangesEnd(createTimeRanges([[5, 10]]),
|
48 | createTimeRanges([[0, 10]]));
|
49 | assert.strictEqual(edge, null, 'ignores backward addition');
|
50 |
|
51 | edge = Ranges.findSoleUncommonTimeRangesEnd(createTimeRanges([[5, 10]]),
|
52 | createTimeRanges([[0, 11]]));
|
53 | assert.strictEqual(edge, 11,
|
54 | 'detected a forward addition & ignores a backward addition');
|
55 |
|
56 | edge = Ranges.findSoleUncommonTimeRangesEnd(createTimeRanges([[0, 10]]),
|
57 | createTimeRanges([[0, 9]]));
|
58 | assert.strictEqual(edge, null,
|
59 | 'ignores a backwards addition resulting from a shrinking range');
|
60 |
|
61 | edge = Ranges.findSoleUncommonTimeRangesEnd(createTimeRanges([[0, 10]]),
|
62 | createTimeRanges([[2, 7]]));
|
63 | assert.strictEqual(edge, null,
|
64 | 'ignores a forward & backwards addition resulting from a shrinking ' +
|
65 | 'range');
|
66 |
|
67 | edge = Ranges.findSoleUncommonTimeRangesEnd(createTimeRanges([[2, 10]]),
|
68 | createTimeRanges([[0, 7]]));
|
69 | assert.strictEqual(
|
70 | edge,
|
71 | null,
|
72 | 'ignores a forward & backwards addition resulting from a range shifted backward'
|
73 | );
|
74 |
|
75 | edge = Ranges.findSoleUncommonTimeRangesEnd(createTimeRanges([[2, 10]]),
|
76 | createTimeRanges([[5, 15]]));
|
77 | assert.strictEqual(edge, 15,
|
78 | 'detected a forwards addition resulting from a range shifted foward');
|
79 |
|
80 |
|
81 | edge = Ranges.findSoleUncommonTimeRangesEnd(createTimeRanges([[0, 10]]),
|
82 | createTimeRanges([[0, 11], [12, 15]]));
|
83 | assert.strictEqual(edge, null, 'ignores multiple new forward additions');
|
84 |
|
85 | edge = Ranges.findSoleUncommonTimeRangesEnd(createTimeRanges([[0, 10], [20, 40]]),
|
86 | createTimeRanges([[20, 50]]));
|
87 | assert.strictEqual(edge, 50, 'detected a forward addition & ignores range removal');
|
88 |
|
89 | edge = Ranges.findSoleUncommonTimeRangesEnd(createTimeRanges([[0, 10], [20, 40]]),
|
90 | createTimeRanges([[0, 50]]));
|
91 | assert.strictEqual(edge, 50, 'detected a forward addition & ignores merges');
|
92 |
|
93 | edge = Ranges.findSoleUncommonTimeRangesEnd(createTimeRanges([[0, 10], [20, 40]]),
|
94 | createTimeRanges([[0, 40]]));
|
95 | assert.strictEqual(edge, null, 'ignores merges');
|
96 |
|
97 |
|
98 | edge = Ranges.findSoleUncommonTimeRangesEnd(createTimeRanges(),
|
99 | createTimeRanges([[0, 11]]));
|
100 | assert.strictEqual(edge, 11, 'handle an empty original TimeRanges object');
|
101 |
|
102 | edge = Ranges.findSoleUncommonTimeRangesEnd(createTimeRanges([[0, 11]]),
|
103 | createTimeRanges());
|
104 | assert.strictEqual(edge, null, 'handle an empty update TimeRanges object');
|
105 |
|
106 |
|
107 | edge = Ranges.findSoleUncommonTimeRangesEnd(null, createTimeRanges([[0, 11]]));
|
108 | assert.strictEqual(edge,
|
109 | 11,
|
110 | 'treat null original buffer as an empty TimeRanges object');
|
111 |
|
112 | edge = Ranges.findSoleUncommonTimeRangesEnd(createTimeRanges([[0, 11]]), null);
|
113 | assert.strictEqual(edge,
|
114 | null,
|
115 | 'treat null update buffer as an empty TimeRanges object');
|
116 | });
|
117 |
|
118 | QUnit.test('properly calculates time left until player rebuffers', function(assert) {
|
119 | let buffered = createTimeRanges([]);
|
120 | let currentTime = 0;
|
121 | let playbackRate = 1;
|
122 |
|
123 | let time = Ranges.timeUntilRebuffer(buffered, currentTime, playbackRate);
|
124 |
|
125 | assert.equal(time, 0, 'calculates no time until rebuffer with empty buffer');
|
126 |
|
127 | buffered = createTimeRanges([[0, 30]]);
|
128 | currentTime = 15;
|
129 |
|
130 | time = Ranges.timeUntilRebuffer(buffered, currentTime, playbackRate);
|
131 |
|
132 | assert.equal(time, 15, 'calculates time until rebuffer');
|
133 |
|
134 | playbackRate = 0.5;
|
135 |
|
136 | time = Ranges.timeUntilRebuffer(buffered, currentTime, playbackRate);
|
137 |
|
138 | assert.equal(time, 30, 'takes into account playback rate');
|
139 | });
|
140 |
|
141 | QUnit.module('Segment Percent Buffered Calculations');
|
142 |
|
143 | QUnit.test('calculates the percent buffered for segments in the simple case',
|
144 | function(assert) {
|
145 | let segmentStart = 10;
|
146 | let segmentDuration = 10;
|
147 | let currentTime = 0;
|
148 | let buffered = createTimeRanges([[15, 19]]);
|
149 | let percentBuffered = Ranges.getSegmentBufferedPercent(
|
150 | segmentStart,
|
151 | segmentDuration,
|
152 | currentTime,
|
153 | buffered);
|
154 |
|
155 | assert.equal(percentBuffered, 40, 'calculated the buffered amount correctly');
|
156 | });
|
157 |
|
158 | QUnit.test('consider the buffer before currentTime to be filled if the ' +
|
159 | 'segement begins at or before the currentTime', function(assert) {
|
160 | let segmentStart = 10;
|
161 | let segmentDuration = 10;
|
162 | let currentTime = 15;
|
163 | let buffered = createTimeRanges([[15, 19]]);
|
164 | let percentBuffered = Ranges.getSegmentBufferedPercent(
|
165 | segmentStart,
|
166 | segmentDuration,
|
167 | currentTime,
|
168 | buffered);
|
169 |
|
170 | assert.equal(percentBuffered, 90, 'calculated the buffered amount correctly');
|
171 | });
|
172 |
|
173 | QUnit.test('does not consider the buffer before currentTime as filled if the segment ' +
|
174 | 'begins after the currentTime', function(assert) {
|
175 | let segmentStart = 10;
|
176 | let segmentDuration = 10;
|
177 | let currentTime = 18;
|
178 | let buffered = createTimeRanges([[19, 30]]);
|
179 | let percentBuffered = Ranges.getSegmentBufferedPercent(
|
180 | segmentStart,
|
181 | segmentDuration,
|
182 | currentTime,
|
183 | buffered);
|
184 |
|
185 | assert.equal(percentBuffered, 10, 'calculated the buffered amount correctly');
|
186 | });
|
187 |
|
188 | QUnit.test('calculates the percent buffered for segments with multiple buffered ' +
|
189 | 'regions', function(assert) {
|
190 | let segmentStart = 10;
|
191 | let segmentDuration = 10;
|
192 | let currentTime = 0;
|
193 | let buffered = createTimeRanges([[0, 11], [12, 19]]);
|
194 | let percentBuffered = Ranges.getSegmentBufferedPercent(
|
195 | segmentStart,
|
196 | segmentDuration,
|
197 | currentTime,
|
198 | buffered);
|
199 |
|
200 | assert.equal(percentBuffered, 80, 'calculated the buffered amount correctly');
|
201 | });
|
202 |
|
203 | QUnit.test('calculates the percent buffered for segments with multiple buffered ' +
|
204 | 'regions taking into account currentTime', function(assert) {
|
205 | let segmentStart = 10;
|
206 | let segmentDuration = 10;
|
207 | let currentTime = 12;
|
208 | let buffered = createTimeRanges([[0, 11], [12, 19]]);
|
209 | let percentBuffered = Ranges.getSegmentBufferedPercent(
|
210 | segmentStart,
|
211 | segmentDuration,
|
212 | currentTime,
|
213 | buffered);
|
214 |
|
215 | assert.equal(percentBuffered, 90, 'calculated the buffered amount correctly');
|
216 | });
|
217 |
|
218 | QUnit.test('calculates the percent buffered as 0 for zero-length segments',
|
219 | function(assert) {
|
220 | let segmentStart = 10;
|
221 | let segmentDuration = 0;
|
222 | let currentTime = 0;
|
223 | let buffered = createTimeRanges([[0, 19]]);
|
224 | let percentBuffered = Ranges.getSegmentBufferedPercent(
|
225 | segmentStart,
|
226 | segmentDuration,
|
227 | currentTime,
|
228 | buffered);
|
229 |
|
230 | assert.equal(percentBuffered, 0, 'calculated the buffered amount correctly');
|
231 | });
|
232 |
|
233 | QUnit.test('calculates the percent buffered as 0 for segments that do not overlap ' +
|
234 | 'buffered regions taking into account currentTime', function(assert) {
|
235 | let segmentStart = 10;
|
236 | let segmentDuration = 10;
|
237 | let currentTime = 19;
|
238 | let buffered = createTimeRanges([[20, 30]]);
|
239 | let percentBuffered = Ranges.getSegmentBufferedPercent(
|
240 | segmentStart,
|
241 | segmentDuration,
|
242 | currentTime,
|
243 | buffered);
|
244 |
|
245 | assert.equal(percentBuffered, 0, 'calculated the buffered amount correctly');
|
246 | });
|
247 |
|
248 | QUnit.test('calculates the percent buffered for segments ' +
|
249 | 'that end before currentTime', function(assert) {
|
250 | let segmentStart = 10;
|
251 | let segmentDuration = 10;
|
252 | let currentTime = 19.6;
|
253 | let buffered = createTimeRanges([[0, 19.5]]);
|
254 | let percentBuffered = Ranges.getSegmentBufferedPercent(
|
255 | segmentStart,
|
256 | segmentDuration,
|
257 | currentTime,
|
258 | buffered);
|
259 |
|
260 | assert.equal(percentBuffered, 95, 'calculated the buffered amount correctly');
|
261 | });
|
262 |
|
263 | QUnit.test('finds next range', function(assert) {
|
264 | assert.equal(Ranges.findNextRange(createTimeRanges(), 10).length,
|
265 | 0,
|
266 | 'does not find next range in empty buffer');
|
267 | assert.equal(Ranges.findNextRange(createTimeRanges([[0, 20]]), 10).length,
|
268 | 0,
|
269 | 'does not find next range when no next ranges');
|
270 | assert.equal(Ranges.findNextRange(createTimeRanges([[0, 20]]), 30).length,
|
271 | 0,
|
272 | 'does not find next range when current time later than buffer');
|
273 | assert.equal(Ranges.findNextRange(createTimeRanges([[10, 20]]), 10).length,
|
274 | 0,
|
275 | 'does not find next range when current time is at beginning of buffer');
|
276 | assert.equal(Ranges.findNextRange(createTimeRanges([[10, 20]]), 11).length,
|
277 | 0,
|
278 | 'does not find next range when current time in middle of buffer');
|
279 | assert.equal(Ranges.findNextRange(createTimeRanges([[10, 20]]), 20).length,
|
280 | 0,
|
281 | 'does not find next range when current time is at end of buffer');
|
282 |
|
283 | assert.ok(rangesEqual(Ranges.findNextRange(createTimeRanges([[10, 20]]), 0),
|
284 | createTimeRanges([[10, 20]])),
|
285 | 'finds next range when buffer comes after time');
|
286 | assert.ok(rangesEqual(Ranges.findNextRange(createTimeRanges([[10, 20], [25, 35]]), 22),
|
287 | createTimeRanges([[25, 35]])),
|
288 | 'finds next range when time between buffers');
|
289 | assert.ok(rangesEqual(Ranges.findNextRange(createTimeRanges([[10, 20], [25, 35]]), 15),
|
290 | createTimeRanges([[25, 35]])),
|
291 | 'finds next range when time in previous buffer');
|
292 | });
|
293 |
|
294 | QUnit.test('finds gaps within ranges', function(assert) {
|
295 | assert.equal(Ranges.findGaps(createTimeRanges()).length,
|
296 | 0,
|
297 | 'does not find gap in empty buffer');
|
298 | assert.equal(Ranges.findGaps(createTimeRanges([[0, 10]])).length,
|
299 | 0,
|
300 | 'does not find gap in single buffer');
|
301 | assert.equal(Ranges.findGaps(createTimeRanges([[1, 10]])).length,
|
302 | 0,
|
303 | 'does not find gap at start of buffer');
|
304 |
|
305 | assert.ok(rangesEqual(Ranges.findGaps(createTimeRanges([[0, 10], [11, 20]])),
|
306 | createTimeRanges([[10, 11]])),
|
307 | 'finds a single gap');
|
308 | assert.ok(rangesEqual(Ranges.findGaps(createTimeRanges([[0, 10], [11, 20], [22, 30]])),
|
309 | createTimeRanges([[10, 11], [20, 22]])),
|
310 | 'finds multiple gaps');
|
311 | });
|
312 |
|
313 | QUnit.test('creates printable ranges', function(assert) {
|
314 | assert.equal(Ranges.printableRange(createTimeRanges()), '', 'empty range empty string');
|
315 | assert.equal(Ranges.printableRange(createTimeRanges([[0, 0]])),
|
316 | '0 => 0',
|
317 | 'formats range correctly');
|
318 | assert.equal(Ranges.printableRange(createTimeRanges([[0, 1]])),
|
319 | '0 => 1',
|
320 | 'formats range correctly');
|
321 | assert.equal(Ranges.printableRange(createTimeRanges([[1, -1]])),
|
322 | '1 => -1',
|
323 | 'formats range correctly');
|
324 | assert.equal(Ranges.printableRange(createTimeRanges([[10.2, 25.2]])),
|
325 | '10.2 => 25.2',
|
326 | 'formats range correctly');
|
327 | assert.equal(Ranges.printableRange(createTimeRanges([[10, 20], [30, 40]])),
|
328 | '10 => 20, 30 => 40',
|
329 | 'formats ranges correctly');
|
330 | assert.equal(Ranges.printableRange(createTimeRanges([[10, 25], [20, 40], [-1, -2]])),
|
331 | '10 => 25, 20 => 40, -1 => -2',
|
332 | 'formats ranges correctly');
|
333 | });
|