ranges.test.js 13 KB

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