9628b848 by David LaPalomento

Add "parser" support for more m3u8 tags

Regexes and tests for m3u8 tags that are likely to be relevant to playback. High-level m3u8 tests are still failing because their is still no "interpretation" of the incoming parse stream.
1 parent 98b95881
1 (function(parseInt, undefined) { 1 (function(parseInt, undefined) {
2 var Stream, Tokenizer, Parser; 2 var
3 parseAttributes = function(attributes) {
4 var
5 attrs = attributes.split(','),
6 i = attrs.length,
7 result = {},
8 attr;
9 while (i--) {
10 attr = attrs[i].split('=');
11 result[attr[0]] = attr[1];
12 }
13 return result;
14 },
15 Stream,
16 Tokenizer,
17 Parser;
3 18
4 Stream = function() { 19 Stream = function() {
5 var listeners = {}; 20 var listeners = {};
...@@ -107,6 +122,122 @@ ...@@ -107,6 +122,122 @@
107 this.trigger('data', event); 122 this.trigger('data', event);
108 return; 123 return;
109 } 124 }
125 match = (/^#EXT-X-TARGETDURATION:?([0-9.]*)?/).exec(line);
126 if (match) {
127 event = {
128 type: 'tag',
129 tagType: 'targetduration'
130 };
131 if (match[1]) {
132 event.duration = parseInt(match[1], 10);
133 }
134 this.trigger('data', event);
135 return;
136 }
137 match = (/^#EXT-X-VERSION:?([0-9.]*)?/).exec(line);
138 if (match) {
139 event = {
140 type: 'tag',
141 tagType: 'version'
142 };
143 if (match[1]) {
144 event.version = parseInt(match[1], 10);
145 }
146 this.trigger('data', event);
147 return;
148 }
149 match = (/^#EXT-X-MEDIA-SEQUENCE:?([0-9.]*)?/).exec(line);
150 if (match) {
151 event = {
152 type: 'tag',
153 tagType: 'media-sequence'
154 };
155 if (match[1]) {
156 event.number = parseInt(match[1], 10);
157 }
158 this.trigger('data', event);
159 return;
160 }
161 match = (/^#EXT-X-PLAYLIST-TYPE:?(.*)?$/).exec(line);
162 if (match) {
163 event = {
164 type: 'tag',
165 tagType: 'playlist-type'
166 };
167 if (match[1]) {
168 event.playlistType = match[1];
169 }
170 this.trigger('data', event);
171 return;
172 }
173 match = (/^#EXT-X-BYTERANGE:?([0-9.]*)?@?([0-9.]*)?/).exec(line);
174 if (match) {
175 event = {
176 type: 'tag',
177 tagType: 'byterange'
178 };
179 if (match[1]) {
180 event.length = parseInt(match[1], 10);
181 }
182 if (match[2]) {
183 event.offset = parseInt(match[2], 10);
184 }
185 this.trigger('data', event);
186 return;
187 }
188 match = (/^#EXT-X-ALLOW-CACHE:?(YES|NO)?/).exec(line);
189 if (match) {
190 event = {
191 type: 'tag',
192 tagType: 'allow-cache'
193 };
194 if (match[1]) {
195 event.allowed = !(/NO/).test(match[1]);
196 }
197 this.trigger('data', event);
198 return;
199 }
200 match = (/^#EXT-X-STREAM-INF:?(.*)$/).exec(line);
201 if (match) {
202 event = {
203 type: 'tag',
204 tagType: 'stream-inf'
205 };
206 if (match[1]) {
207 event.attributes = parseAttributes(match[1]);
208
209 if (event.attributes.RESOLUTION) {
210 (function() {
211 var
212 split = event.attributes.RESOLUTION.split('x'),
213 resolution = {};
214 if (split[0]) {
215 resolution.width = parseInt(split[0], 10);
216 }
217 if (split[1]) {
218 resolution.height = parseInt(split[1], 10);
219 }
220 event.attributes.RESOLUTION = resolution;
221 })();
222 }
223 if (event.attributes.BANDWIDTH) {
224 event.attributes.BANDWIDTH = parseInt(event.attributes.BANDWIDTH, 10);
225 }
226 if (event.attributes['PROGRAM-ID']) {
227 event.attributes['PROGRAM-ID'] = parseInt(event.attributes['PROGRAM-ID'], 10);
228 }
229 }
230 this.trigger('data', event);
231 return;
232 }
233 match = (/^#EXT-X-ENDLIST/).exec(line);
234 if (match) {
235 this.trigger('data', {
236 type: 'tag',
237 tagType: 'endlist'
238 });
239 return;
240 }
110 241
111 // unknown tag type 242 // unknown tag type
112 this.trigger('data', { 243 this.trigger('data', {
......
...@@ -39,11 +39,11 @@ ...@@ -39,11 +39,11 @@
39 var data = manifestController.parseManifest(window.brightcove_playlist_data); 39 var data = manifestController.parseManifest(window.brightcove_playlist_data);
40 40
41 ok(data); 41 ok(data);
42 equal(data.playlists.length, 4, 'Has correct rendition count'); 42 strictEqual(data.playlists.length, 4, 'Has correct rendition count');
43 equal(data.playlists[0].attributes.bandwidth, 240000, 'First rendition index bandwidth is correct'); 43 strictEqual(data.playlists[0].attributes.bandwidth, 240000, 'First rendition index bandwidth is correct');
44 equal(data.playlists[0].attributes.programId, 1, 'First rendition index program-id is correct'); 44 strictEqual(data.playlists[0].attributes.programId, 1, 'First rendition index program-id is correct');
45 equal(data.playlists[0].attributes.resolution.width, 396, 'First rendition index resolution width is correct'); 45 strictEqual(data.playlists[0].attributes.resolution.width, 396, 'First rendition index resolution width is correct');
46 equal(data.playlists[0].attributes.resolution.height, 224, 'First rendition index resolution height is correct'); 46 strictEqual(data.playlists[0].attributes.resolution.height, 224, 'First rendition index resolution height is correct');
47 }); 47 });
48 48
49 test('should get a manifest from an external URL', function() { 49 test('should get a manifest from an external URL', function() {
...@@ -81,9 +81,9 @@ ...@@ -81,9 +81,9 @@
81 }); 81 });
82 tokenizer.push('#EXTM3U\nmovie.ts\n'); 82 tokenizer.push('#EXTM3U\nmovie.ts\n');
83 83
84 equal(2, lines.length, 'two lines are ready'); 84 strictEqual(2, lines.length, 'two lines are ready');
85 equal('#EXTM3U', lines.shift(), 'the first line is the first token'); 85 strictEqual('#EXTM3U', lines.shift(), 'the first line is the first token');
86 equal('movie.ts', lines.shift(), 'the second line is the second token'); 86 strictEqual('movie.ts', lines.shift(), 'the second line is the second token');
87 }); 87 });
88 test('empty lines become empty strings', function() { 88 test('empty lines become empty strings', function() {
89 var lines = []; 89 var lines = [];
...@@ -92,9 +92,9 @@ ...@@ -92,9 +92,9 @@
92 }); 92 });
93 tokenizer.push('\n\n'); 93 tokenizer.push('\n\n');
94 94
95 equal(2, lines.length, 'two lines are ready'); 95 strictEqual(2, lines.length, 'two lines are ready');
96 equal('', lines.shift(), 'the first line is empty'); 96 strictEqual('', lines.shift(), 'the first line is empty');
97 equal('', lines.shift(), 'the second line is empty'); 97 strictEqual('', lines.shift(), 'the second line is empty');
98 }); 98 });
99 test('handles lines broken across appends', function() { 99 test('handles lines broken across appends', function() {
100 var lines = []; 100 var lines = [];
...@@ -102,12 +102,12 @@ ...@@ -102,12 +102,12 @@
102 lines.push(line); 102 lines.push(line);
103 }); 103 });
104 tokenizer.push('#EXTM'); 104 tokenizer.push('#EXTM');
105 equal(0, lines.length, 'no lines are ready'); 105 strictEqual(0, lines.length, 'no lines are ready');
106 106
107 tokenizer.push('3U\nmovie.ts\n'); 107 tokenizer.push('3U\nmovie.ts\n');
108 equal(2, lines.length, 'two lines are ready'); 108 strictEqual(2, lines.length, 'two lines are ready');
109 equal('#EXTM3U', lines.shift(), 'the first line is the first token'); 109 strictEqual('#EXTM3U', lines.shift(), 'the first line is the first token');
110 equal('movie.ts', lines.shift(), 'the second line is the second token'); 110 strictEqual('movie.ts', lines.shift(), 'the second line is the second token');
111 }); 111 });
112 test('stops sending events after deregistering', function() { 112 test('stops sending events after deregistering', function() {
113 var 113 var
...@@ -123,12 +123,12 @@ ...@@ -123,12 +123,12 @@
123 tokenizer.on('data', temporary); 123 tokenizer.on('data', temporary);
124 tokenizer.on('data', permanent); 124 tokenizer.on('data', permanent);
125 tokenizer.push('line one\n'); 125 tokenizer.push('line one\n');
126 equal(temporaryLines.length, permanentLines.length, 'both callbacks receive the event'); 126 strictEqual(temporaryLines.length, permanentLines.length, 'both callbacks receive the event');
127 127
128 ok(tokenizer.off('data', temporary), 'a listener was removed'); 128 ok(tokenizer.off('data', temporary), 'a listener was removed');
129 tokenizer.push('line two\n'); 129 tokenizer.push('line two\n');
130 equal(1, temporaryLines.length, 'no new events are received'); 130 strictEqual(1, temporaryLines.length, 'no new events are received');
131 equal(2, permanentLines.length, 'new events are still received'); 131 strictEqual(2, permanentLines.length, 'new events are still received');
132 }); 132 });
133 133
134 module('M3U8 Parser', { 134 module('M3U8 Parser', {
...@@ -148,8 +148,8 @@ ...@@ -148,8 +148,8 @@
148 tokenizer.push(manifest); 148 tokenizer.push(manifest);
149 149
150 ok(element, 'an event was triggered'); 150 ok(element, 'an event was triggered');
151 equal(element.type, 'comment', 'the type is comment'); 151 strictEqual(element.type, 'comment', 'the type is comment');
152 equal(element.text, 152 strictEqual(element.text,
153 manifest.slice(1, manifest.length - 1), 153 manifest.slice(1, manifest.length - 1),
154 'the comment text is parsed'); 154 'the comment text is parsed');
155 }); 155 });
...@@ -163,8 +163,8 @@ ...@@ -163,8 +163,8 @@
163 tokenizer.push(manifest); 163 tokenizer.push(manifest);
164 164
165 ok(element, 'an event was triggered'); 165 ok(element, 'an event was triggered');
166 equal(element.type, 'uri', 'the type is uri'); 166 strictEqual(element.type, 'uri', 'the type is uri');
167 equal(element.uri, 167 strictEqual(element.uri,
168 manifest.substring(0, manifest.length - 1), 168 manifest.substring(0, manifest.length - 1),
169 'the uri text is parsed'); 169 'the uri text is parsed');
170 }); 170 });
...@@ -178,11 +178,13 @@ ...@@ -178,11 +178,13 @@
178 tokenizer.push(manifest); 178 tokenizer.push(manifest);
179 179
180 ok(element, 'an event was triggered'); 180 ok(element, 'an event was triggered');
181 equal(element.type, 'tag', 'the type is tag'); 181 strictEqual(element.type, 'tag', 'the type is tag');
182 equal(element.data, 182 strictEqual(element.data,
183 manifest.slice(4, manifest.length - 1), 183 manifest.slice(4, manifest.length - 1),
184 'unknown tag data is preserved'); 184 'unknown tag data is preserved');
185 }); 185 });
186
187 // #EXTM3U
186 test('parses #EXTM3U tags', function() { 188 test('parses #EXTM3U tags', function() {
187 var 189 var
188 manifest = '#EXTM3U\n', 190 manifest = '#EXTM3U\n',
...@@ -193,9 +195,11 @@ ...@@ -193,9 +195,11 @@
193 tokenizer.push(manifest); 195 tokenizer.push(manifest);
194 196
195 ok(element, 'an event was triggered'); 197 ok(element, 'an event was triggered');
196 equal(element.type, 'tag', 'the line type is tag'); 198 strictEqual(element.type, 'tag', 'the line type is tag');
197 equal(element.tagType, 'm3u', 'the tag type is m3u'); 199 strictEqual(element.tagType, 'm3u', 'the tag type is m3u');
198 }); 200 });
201
202 // #EXTINF
199 test('parses minimal #EXTINF tags', function() { 203 test('parses minimal #EXTINF tags', function() {
200 var 204 var
201 manifest = '#EXTINF\n', 205 manifest = '#EXTINF\n',
...@@ -206,8 +210,8 @@ ...@@ -206,8 +210,8 @@
206 tokenizer.push(manifest); 210 tokenizer.push(manifest);
207 211
208 ok(element, 'an event was triggered'); 212 ok(element, 'an event was triggered');
209 equal(element.type, 'tag', 'the line type is tag'); 213 strictEqual(element.type, 'tag', 'the line type is tag');
210 equal(element.tagType, 'inf', 'the tag type is inf'); 214 strictEqual(element.tagType, 'inf', 'the tag type is inf');
211 }); 215 });
212 test('parses #EXTINF tags with durations', function() { 216 test('parses #EXTINF tags with durations', function() {
213 var 217 var
...@@ -219,18 +223,18 @@ ...@@ -219,18 +223,18 @@
219 tokenizer.push(manifest); 223 tokenizer.push(manifest);
220 224
221 ok(element, 'an event was triggered'); 225 ok(element, 'an event was triggered');
222 equal(element.type, 'tag', 'the line type is tag'); 226 strictEqual(element.type, 'tag', 'the line type is tag');
223 equal(element.tagType, 'inf', 'the tag type is inf'); 227 strictEqual(element.tagType, 'inf', 'the tag type is inf');
224 equal(element.duration, 15, 'the duration is parsed'); 228 strictEqual(element.duration, 15, 'the duration is parsed');
225 ok(!('title' in element), 'no title is parsed'); 229 ok(!('title' in element), 'no title is parsed');
226 230
227 manifest = '#EXTINF:21,\n' 231 manifest = '#EXTINF:21,\n'
228 tokenizer.push(manifest); 232 tokenizer.push(manifest);
229 233
230 ok(element, 'an event was triggered'); 234 ok(element, 'an event was triggered');
231 equal(element.type, 'tag', 'the line type is tag'); 235 strictEqual(element.type, 'tag', 'the line type is tag');
232 equal(element.tagType, 'inf', 'the tag type is inf'); 236 strictEqual(element.tagType, 'inf', 'the tag type is inf');
233 equal(element.duration, 21, 'the duration is parsed'); 237 strictEqual(element.duration, 21, 'the duration is parsed');
234 ok(!('title' in element), 'no title is parsed'); 238 ok(!('title' in element), 'no title is parsed');
235 }); 239 });
236 test('parses #EXTINF tags with a duration and title', function() { 240 test('parses #EXTINF tags with a duration and title', function() {
...@@ -243,13 +247,302 @@ ...@@ -243,13 +247,302 @@
243 tokenizer.push(manifest); 247 tokenizer.push(manifest);
244 248
245 ok(element, 'an event was triggered'); 249 ok(element, 'an event was triggered');
246 equal(element.type, 'tag', 'the line type is tag'); 250 strictEqual(element.type, 'tag', 'the line type is tag');
247 equal(element.tagType, 'inf', 'the tag type is inf'); 251 strictEqual(element.tagType, 'inf', 'the tag type is inf');
248 equal(element.duration, 13, 'the duration is parsed'); 252 strictEqual(element.duration, 13, 'the duration is parsed');
249 equal(element.title, 253 strictEqual(element.title,
250 manifest.substring(manifest.indexOf(',') + 1, manifest.length - 1), 254 manifest.substring(manifest.indexOf(',') + 1, manifest.length - 1),
251 'the title is parsed'); 255 'the title is parsed');
252 }); 256 });
257
258 // #EXT-X-TARGETDURATION
259 test('parses minimal #EXT-X-TARGETDURATION tags', function() {
260 var
261 manifest = '#EXT-X-TARGETDURATION\n',
262 element;
263 parser.on('data', function(elem) {
264 element = elem;
265 });
266 tokenizer.push(manifest);
267
268 ok(element, 'an event was triggered');
269 strictEqual(element.type, 'tag', 'the line type is tag');
270 strictEqual(element.tagType, 'targetduration', 'the tag type is targetduration');
271 ok(!('duration' in element), 'no duration is parsed');
272 });
273 test('parses #EXT-X-TARGETDURATION with duration', function() {
274 var
275 manifest = '#EXT-X-TARGETDURATION:47\n',
276 element;
277 parser.on('data', function(elem) {
278 element = elem;
279 });
280 tokenizer.push(manifest);
281
282 ok(element, 'an event was triggered');
283 strictEqual(element.type, 'tag', 'the line type is tag');
284 strictEqual(element.tagType, 'targetduration', 'the tag type is targetduration');
285 strictEqual(element.duration, 47, 'the duration is parsed');
286 });
287
288 // #EXT-X-VERSION
289 test('parses minimal #EXT-X-VERSION tags', function() {
290 var
291 manifest = '#EXT-X-VERSION:\n',
292 element;
293 parser.on('data', function(elem) {
294 element = elem;
295 });
296 tokenizer.push(manifest);
297
298 ok(element, 'an event was triggered');
299 strictEqual(element.type, 'tag', 'the line type is tag');
300 strictEqual(element.tagType, 'version', 'the tag type is version');
301 ok(!('version' in element), 'no version is present');
302 });
303 test('parses #EXT-X-VERSION with a version', function() {
304 var
305 manifest = '#EXT-X-VERSION:99\n',
306 element;
307 parser.on('data', function(elem) {
308 element = elem;
309 });
310 tokenizer.push(manifest);
311
312 ok(element, 'an event was triggered');
313 strictEqual(element.type, 'tag', 'the line type is tag');
314 strictEqual(element.tagType, 'version', 'the tag type is version');
315 strictEqual(element.version, 99, 'the version is parsed');
316 });
317
318 // #EXT-X-MEDIA-SEQUENCE
319 test('parses minimal #EXT-X-MEDIA-SEQUENCE tags', function() {
320 var
321 manifest = '#EXT-X-MEDIA-SEQUENCE\n',
322 element;
323 parser.on('data', function(elem) {
324 element = elem;
325 });
326 tokenizer.push(manifest);
327
328 ok(element, 'an event was triggered');
329 strictEqual(element.type, 'tag', 'the line type is tag');
330 strictEqual(element.tagType, 'media-sequence', 'the tag type is media-sequence');
331 ok(!('number' in element), 'no number is present');
332 });
333 test('parses #EXT-X-MEDIA-SEQUENCE with sequence numbers', function() {
334 var
335 manifest = '#EXT-X-MEDIA-SEQUENCE:109\n',
336 element;
337 parser.on('data', function(elem) {
338 element = elem;
339 });
340 tokenizer.push(manifest);
341
342 ok(element, 'an event was triggered');
343 strictEqual(element.type, 'tag', 'the line type is tag');
344 strictEqual(element.tagType, 'media-sequence', 'the tag type is media-sequence');
345 ok(element.number, 109, 'the number is parsed');
346 });
347
348 // #EXT-X-PLAYLIST-TYPE
349 test('parses minimal #EXT-X-PLAYLIST-TYPE tags', function() {
350 var
351 manifest = '#EXT-X-PLAYLIST-TYPE:\n',
352 element;
353 parser.on('data', function(elem) {
354 element = elem;
355 });
356 tokenizer.push(manifest);
357
358 ok(element, 'an event was triggered');
359 strictEqual(element.type, 'tag', 'the line type is tag');
360 strictEqual(element.tagType, 'playlist-type', 'the tag type is playlist-type');
361 ok(!('playlistType' in element), 'no playlist type is present');
362 });
363 test('parses #EXT-X-PLAYLIST-TYPE with mutability info', function() {
364 var
365 manifest = '#EXT-X-PLAYLIST-TYPE:EVENT\n',
366 element;
367 parser.on('data', function(elem) {
368 element = elem;
369 });
370 tokenizer.push(manifest);
371
372 ok(element, 'an event was triggered');
373 strictEqual(element.type, 'tag', 'the line type is tag');
374 strictEqual(element.tagType, 'playlist-type', 'the tag type is playlist-type');
375 strictEqual(element.playlistType, 'EVENT', 'the playlist type is EVENT');
376
377 manifest = '#EXT-X-PLAYLIST-TYPE:VOD\n';
378 tokenizer.push(manifest);
379 ok(element, 'an event was triggered');
380 strictEqual(element.type, 'tag', 'the line type is tag');
381 strictEqual(element.tagType, 'playlist-type', 'the tag type is playlist-type');
382 strictEqual(element.playlistType, 'VOD', 'the playlist type is VOD');
383
384 manifest = '#EXT-X-PLAYLIST-TYPE:nonsense\n';
385 tokenizer.push(manifest);
386 ok(element, 'an event was triggered');
387 strictEqual(element.type, 'tag', 'the line type is tag');
388 strictEqual(element.tagType, 'playlist-type', 'the tag type is playlist-type');
389 strictEqual(element.playlistType, 'nonsense', 'the playlist type is parsed');
390 });
391
392 // #EXT-X-BYTERANGE
393 test('parses minimal #EXT-X-BYTERANGE tags', function() {
394 var
395 manifest = '#EXT-X-BYTERANGE\n',
396 element;
397 parser.on('data', function(elem) {
398 element = elem;
399 });
400 tokenizer.push(manifest);
401
402 ok(element, 'an event was triggered');
403 strictEqual(element.type, 'tag', 'the line type is tag');
404 strictEqual(element.tagType, 'byterange', 'the tag type is byterange');
405 ok(!('length' in element), 'no length is present');
406 ok(!('offset' in element), 'no offset is present');
407 });
408 test('parses #EXT-X-BYTERANGE with length and offset', function() {
409 var
410 manifest = '#EXT-X-BYTERANGE:45\n',
411 element;
412 parser.on('data', function(elem) {
413 element = elem;
414 });
415 tokenizer.push(manifest);
416
417 ok(element, 'an event was triggered');
418 strictEqual(element.type, 'tag', 'the line type is tag');
419 strictEqual(element.tagType, 'byterange', 'the tag type is byterange');
420 strictEqual(element.length, 45, 'length is parsed');
421 ok(!('offset' in element), 'no offset is present');
422
423 manifest = '#EXT-X-BYTERANGE:108@16\n';
424 tokenizer.push(manifest);
425 ok(element, 'an event was triggered');
426 strictEqual(element.type, 'tag', 'the line type is tag');
427 strictEqual(element.tagType, 'byterange', 'the tag type is byterange');
428 strictEqual(element.length, 108, 'length is parsed');
429 strictEqual(element.offset, 16, 'offset is parsed');
430 });
431
432 // #EXT-X-ALLOW-CACHE
433 test('parses minimal #EXT-X-ALLOW-CACHE tags', function() {
434 var
435 manifest = '#EXT-X-ALLOW-CACHE:\n',
436 element;
437 parser.on('data', function(elem) {
438 element = elem;
439 });
440 tokenizer.push(manifest);
441
442 ok(element, 'an event was triggered');
443 strictEqual(element.type, 'tag', 'the line type is tag');
444 strictEqual(element.tagType, 'allow-cache', 'the tag type is allow-cache');
445 ok(!('allowed' in element), 'no allowed is present');
446 });
447 test('parses valid #EXT-X-ALLOW-CACHE tags', function() {
448 var
449 manifest = '#EXT-X-ALLOW-CACHE:YES\n',
450 element;
451 parser.on('data', function(elem) {
452 element = elem;
453 });
454 tokenizer.push(manifest);
455
456 ok(element, 'an event was triggered');
457 strictEqual(element.type, 'tag', 'the line type is tag');
458 strictEqual(element.tagType, 'allow-cache', 'the tag type is allow-cache');
459 ok(element.allowed, 'allowed is parsed');
460
461 manifest = '#EXT-X-ALLOW-CACHE:NO\n';
462 tokenizer.push(manifest);
463
464 ok(element, 'an event was triggered');
465 strictEqual(element.type, 'tag', 'the line type is tag');
466 strictEqual(element.tagType, 'allow-cache', 'the tag type is allow-cache');
467 ok(!element.allowed, 'allowed is parsed');
468 });
469 // #EXT-X-STREAM-INF
470 test('parses minimal #EXT-X-STREAM-INF tags', function() {
471 var
472 manifest = '#EXT-X-STREAM-INF\n',
473 element;
474 parser.on('data', function(elem) {
475 element = elem;
476 });
477 tokenizer.push(manifest);
478
479 ok(element, 'an event was triggered');
480 strictEqual(element.type, 'tag', 'the line type is tag');
481 strictEqual(element.tagType, 'stream-inf', 'the tag type is stream-inf');
482 ok(!('attributes' in element), 'no attributes are present');
483 });
484 test('parses #EXT-X-STREAM-INF with common attributes', function() {
485 var
486 manifest = '#EXT-X-STREAM-INF:BANDWIDTH=14400\n',
487 element;
488 parser.on('data', function(elem) {
489 element = elem;
490 });
491 tokenizer.push(manifest);
492
493 ok(element, 'an event was triggered');
494 strictEqual(element.type, 'tag', 'the line type is tag');
495 strictEqual(element.tagType, 'stream-inf', 'the tag type is stream-inf');
496 strictEqual(element.attributes.BANDWIDTH, 14400, 'bandwidth is parsed');
497
498 manifest = '#EXT-X-STREAM-INF:PROGRAM-ID=7\n';
499 tokenizer.push(manifest);
500
501 ok(element, 'an event was triggered');
502 strictEqual(element.type, 'tag', 'the line type is tag');
503 strictEqual(element.tagType, 'stream-inf', 'the tag type is stream-inf');
504 strictEqual(element.attributes['PROGRAM-ID'], 7, 'program-id is parsed');
505
506 manifest = '#EXT-X-STREAM-INF:RESOLUTION=396x224\n';
507 tokenizer.push(manifest);
508
509 ok(element, 'an event was triggered');
510 strictEqual(element.type, 'tag', 'the line type is tag');
511 strictEqual(element.tagType, 'stream-inf', 'the tag type is stream-inf');
512 strictEqual(element.attributes.RESOLUTION.width, 396, 'width is parsed');
513 strictEqual(element.attributes.RESOLUTION.height, 224, 'heigth is parsed');
514 });
515 test('parses #EXT-X-STREAM-INF with arbitrary attributes', function() {
516 var
517 manifest = '#EXT-X-STREAM-INF:NUMERIC=24,ALPHA=Value,MIXED=123abc\n',
518 element;
519 parser.on('data', function(elem) {
520 element = elem;
521 });
522 tokenizer.push(manifest);
523
524 ok(element, 'an event was triggered');
525 strictEqual(element.type, 'tag', 'the line type is tag');
526 strictEqual(element.tagType, 'stream-inf', 'the tag type is stream-inf');
527 strictEqual(element.attributes.NUMERIC, '24', 'numeric attributes are parsed');
528 strictEqual(element.attributes.ALPHA, 'Value', 'alphabetic attributes are parsed');
529 strictEqual(element.attributes.MIXED, '123abc', 'mixed attributes are parsed');
530 });
531 // #EXT-X-ENDLIST
532 test('parses #EXT-X-ENDLIST tags', function() {
533 var
534 manifest = '#EXT-X-ENDLIST\n',
535 element;
536 parser.on('data', function(elem) {
537 element = elem;
538 });
539 tokenizer.push(manifest);
540
541 ok(element, 'an event was triggered');
542 strictEqual(element.type, 'tag', 'the line type is tag');
543 strictEqual(element.tagType, 'endlist', 'the tag type is stream-inf');
544 });
545
253 test('ignores empty lines', function() { 546 test('ignores empty lines', function() {
254 var 547 var
255 manifest = '\n', 548 manifest = '\n',
...@@ -290,15 +583,15 @@ ...@@ -290,15 +583,15 @@
290 }); 583 });
291 tokenizer.push(window.playlistData); 584 tokenizer.push(window.playlistData);
292 585
293 notEqual(data, null, 'data is not NULL'); 586 notStrictEqual(data, null, 'data is not NULL');
294 equal(data.openTag, true, 'data has valid EXTM3U'); 587 strictEqual(data.openTag, true, 'data has valid EXTM3U');
295 equal(data.targetDuration, 10, 'data has correct TARGET DURATION'); 588 strictEqual(data.targetDuration, 10, 'data has correct TARGET DURATION');
296 equal(data.allowCache, undefined, 'ALLOW-CACHE is not present in the manifest'); 589 strictEqual(data.allowCache, undefined, 'ALLOW-CACHE is not present in the manifest');
297 equal(data.playlistType, "VOD", 'acceptable PLAYLIST TYPE'); 590 strictEqual(data.playlistType, "VOD", 'acceptable PLAYLIST TYPE');
298 equal(data.segments.length, 17, 'there are 17 segments in the manifest'); 591 strictEqual(data.segments.length, 17, 'there are 17 segments in the manifest');
299 equal(data.mediaSequence, 0, 'MEDIA SEQUENCE is correct'); 592 strictEqual(data.mediaSequence, 0, 'MEDIA SEQUENCE is correct');
300 equal(data.totalDuration, undefined, "no total duration is specified"); 593 strictEqual(data.totalDuration, undefined, "no total duration is specified");
301 equal(data.closeTag, true, 'should have ENDLIST tag'); 594 strictEqual(data.closeTag, true, 'should have ENDLIST tag');
302 }); 595 });
303 596
304 /*3.4.7. EXT-X-PLAYLIST-TYPE 597 /*3.4.7. EXT-X-PLAYLIST-TYPE
...@@ -326,9 +619,9 @@ ...@@ -326,9 +619,9 @@
326 }); 619 });
327 tokenizer.push(window.playlistData); 620 tokenizer.push(window.playlistData);
328 621
329 notEqual(data, null, 'data is not NULL'); 622 notStrictEqual(data, null, 'data is not NULL');
330 //equal(data.invalidReasons.length, 0, 'Errors object should not be empty.'); 623 //strictEqual(data.invalidReasons.length, 0, 'Errors object should not be empty.');
331 equal(data.playlistType, "VOD", 'acceptable PLAYLIST TYPE'); 624 strictEqual(data.playlistType, "VOD", 'acceptable PLAYLIST TYPE');
332 }); 625 });
333 626
334 test('should have parsed EVENT playlist type', function() { 627 test('should have parsed EVENT playlist type', function() {
...@@ -342,9 +635,9 @@ ...@@ -342,9 +635,9 @@
342 }); 635 });
343 tokenizer.push(window.playlistData); 636 tokenizer.push(window.playlistData);
344 637
345 notEqual(data, null, 'data is not NULL'); 638 notStrictEqual(data, null, 'data is not NULL');
346 //equal(data.invalidReasons.length, 0, 'Errors object should not be empty.'); 639 //strictEqual(data.invalidReasons.length, 0, 'Errors object should not be empty.');
347 equal(data.playlistType, "EVENT", 'acceptable PLAYLIST TYPE'); 640 strictEqual(data.playlistType, "EVENT", 'acceptable PLAYLIST TYPE');
348 }); 641 });
349 642
350 test('handles a missing playlist type', function() { 643 test('handles a missing playlist type', function() {
...@@ -358,10 +651,10 @@ ...@@ -358,10 +651,10 @@
358 }); 651 });
359 tokenizer.push(window.playlistData); 652 tokenizer.push(window.playlistData);
360 653
361 notEqual(data, null, 'data is not NULL'); 654 notStrictEqual(data, null, 'data is not NULL');
362 //equal(data.invalidReasons.length, 0, 'Errors object should not be empty.'); 655 //strictEqual(data.invalidReasons.length, 0, 'Errors object should not be empty.');
363 //equal(data.warnings, 'EXT-X-PLAYLIST-TYPE was empty or missing. Assuming VOD'); 656 //strictEqual(data.warnings, 'EXT-X-PLAYLIST-TYPE was empty or missing. Assuming VOD');
364 equal(data.playlistType, undefined, 'no PLAYLIST TYPE present'); 657 strictEqual(data.playlistType, undefined, 'no PLAYLIST TYPE present');
365 }); 658 });
366 659
367 test('should have an invalid reason due to invalid playlist type', function() { 660 test('should have an invalid reason due to invalid playlist type', function() {
...@@ -370,9 +663,9 @@ ...@@ -370,9 +663,9 @@
370 testData = {playlistType: 'baklsdhfajsdf'}, 663 testData = {playlistType: 'baklsdhfajsdf'},
371 playlistData = playlistTemplate(testData), 664 playlistData = playlistTemplate(testData),
372 data = m3u8parser.parse(playlistData); 665 data = m3u8parser.parse(playlistData);
373 notEqual(data, null, 'data is not NULL'); 666 notStrictEqual(data, null, 'data is not NULL');
374 //equal(data.invalidReasons.length, 1, 'data has 1 invalid reasons'); 667 //strictEqual(data.invalidReasons.length, 1, 'data has 1 invalid reasons');
375 //equal(data.invalidReasons[0], 'Invalid Playlist Type Value: \'baklsdhfajsdf\''); 668 //strictEqual(data.invalidReasons[0], 'Invalid Playlist Type Value: \'baklsdhfajsdf\'');
376 }); 669 });
377 670
378 // test('handles an empty playlist type', function() { 671 // test('handles an empty playlist type', function() {
...@@ -381,10 +674,10 @@ ...@@ -381,10 +674,10 @@
381 // testData = {playlistType: ''}, 674 // testData = {playlistType: ''},
382 // playlistData = playlistTemplate(testData), 675 // playlistData = playlistTemplate(testData),
383 // data = m3u8parser.parse(playlistData); 676 // data = m3u8parser.parse(playlistData);
384 // notEqual(data, null, 'data is not NULL'); 677 // notStrictEqual(data, null, 'data is not NULL');
385 // //equal(data.invalidReasons.length, 0, 'Errors object should not be empty.'); 678 // //strictEqual(data.invalidReasons.length, 0, 'Errors object should not be empty.');
386 // //equal(data.warnings, 'EXT-X-PLAYLIST-TYPE was empty or missing. Assuming VOD'); 679 // //strictEqual(data.warnings, 'EXT-X-PLAYLIST-TYPE was empty or missing. Assuming VOD');
387 // equal(data.playlistType, '', 'PLAYLIST TYPE is the empty string'); 680 // strictEqual(data.playlistType, '', 'PLAYLIST TYPE is the empty string');
388 // }); 681 // });
389 682
390 /*3.4.2. EXT-X-TARGETDURATION 683 /*3.4.2. EXT-X-TARGETDURATION
...@@ -410,9 +703,9 @@ ...@@ -410,9 +703,9 @@
410 testData = {targetDuration: '10'}, 703 testData = {targetDuration: '10'},
411 playlistData = playlistTemplate(testData), 704 playlistData = playlistTemplate(testData),
412 data = m3u8parser.parse(playlistData); 705 data = m3u8parser.parse(playlistData);
413 notEqual(data, null, 'data is not NULL'); 706 notStrictEqual(data, null, 'data is not NULL');
414 equal(data.targetDuration, 10, 'data has correct TARGET DURATION'); 707 strictEqual(data.targetDuration, 10, 'data has correct TARGET DURATION');
415 //equal(data.invalidReasons.length, 0, 'data has 1 invalid reasons'); 708 //strictEqual(data.invalidReasons.length, 0, 'data has 1 invalid reasons');
416 }); 709 });
417 710
418 test('NaN target duration', function() { 711 test('NaN target duration', function() {
...@@ -423,10 +716,10 @@ ...@@ -423,10 +716,10 @@
423 data = m3u8parser.parse(playlistData); 716 data = m3u8parser.parse(playlistData);
424 console.log(playlistData); 717 console.log(playlistData);
425 console.log(data.targetDuration); 718 console.log(data.targetDuration);
426 notEqual(data, null, 'data is not NULL'); 719 notStrictEqual(data, null, 'data is not NULL');
427 // notEqual(data.invalidReasons, null, 'invalidReasons is not NULL'); 720 // notStrictEqual(data.invalidReasons, null, 'invalidReasons is not NULL');
428 // equal(data.invalidReasons.length, 1, 'data has 0 invalid reasons'); 721 // strictEqual(data.invalidReasons.length, 1, 'data has 0 invalid reasons');
429 // equal(data.invalidReasons[0], 'Invalid Target Duration Value: \'NaN\''); 722 // strictEqual(data.invalidReasons[0], 'Invalid Target Duration Value: \'NaN\'');
430 }); 723 });
431 724
432 test('empty target duration', function() { 725 test('empty target duration', function() {
...@@ -437,10 +730,10 @@ ...@@ -437,10 +730,10 @@
437 data = m3u8parser.parse(playlistData); 730 data = m3u8parser.parse(playlistData);
438 console.log(playlistData); 731 console.log(playlistData);
439 console.log(data.targetDuration); 732 console.log(data.targetDuration);
440 notEqual(data, null, 'data is not NULL'); 733 notStrictEqual(data, null, 'data is not NULL');
441 // notEqual(data.invalidReasons, null, 'invalidReasons is not NULL'); 734 // notStrictEqual(data.invalidReasons, null, 'invalidReasons is not NULL');
442 // equal(data.invalidReasons.length, 1, 'data has 1 invalid reasons'); 735 // strictEqual(data.invalidReasons.length, 1, 'data has 1 invalid reasons');
443 // equal(data.invalidReasons[0], 'Invalid Target Duration Value: \'NaN\''); 736 // strictEqual(data.invalidReasons[0], 'Invalid Target Duration Value: \'NaN\'');
444 }); 737 });
445 738
446 test('undefined target duration', function() { 739 test('undefined target duration', function() {
...@@ -451,10 +744,10 @@ ...@@ -451,10 +744,10 @@
451 data = m3u8parser.parse(playlistData); 744 data = m3u8parser.parse(playlistData);
452 console.log(playlistData); 745 console.log(playlistData);
453 console.log(data.targetDuration); 746 console.log(data.targetDuration);
454 notEqual(data, null, 'data is not NULL'); 747 notStrictEqual(data, null, 'data is not NULL');
455 // notEqual(data.invalidReasons, null, 'invalidReasons is not NULL'); 748 // notStrictEqual(data.invalidReasons, null, 'invalidReasons is not NULL');
456 // equal(data.invalidReasons.length, 1, 'data has 1 invalid reasons'); 749 // strictEqual(data.invalidReasons.length, 1, 'data has 1 invalid reasons');
457 // equal(data.invalidReasons[0], 'Invalid Target Duration Value: \'undefined\''); 750 // strictEqual(data.invalidReasons[0], 'Invalid Target Duration Value: \'undefined\'');
458 751
459 }); 752 });
460 753
...@@ -465,10 +758,10 @@ ...@@ -465,10 +758,10 @@
465 playlistData = playlistTemplate(testData), 758 playlistData = playlistTemplate(testData),
466 data = m3u8parser.parse(playlistData); 759 data = m3u8parser.parse(playlistData);
467 760
468 notEqual(data, null, 'data is not NULL'); 761 notStrictEqual(data, null, 'data is not NULL');
469 // notEqual(data.invalidReasons, null, 'invalidReasons is not NULL'); 762 // notStrictEqual(data.invalidReasons, null, 'invalidReasons is not NULL');
470 // equal(data.invalidReasons.length, 1, 'data has 1 invalid reasons'); 763 // strictEqual(data.invalidReasons.length, 1, 'data has 1 invalid reasons');
471 // equal(data.invalidReasons[0], 'Invalid Target Duration Value: 4 is lower than segments'); 764 // strictEqual(data.invalidReasons[0], 'Invalid Target Duration Value: 4 is lower than segments');
472 }); 765 });
473 766
474 /*3.4.3. EXT-X-MEDIA-SEQUENCE 767 /*3.4.3. EXT-X-MEDIA-SEQUENCE
...@@ -501,10 +794,10 @@ ...@@ -501,10 +794,10 @@
501 playlistData = playlistTemplate(testData), 794 playlistData = playlistTemplate(testData),
502 data = m3u8parser.parse(playlistData); 795 data = m3u8parser.parse(playlistData);
503 796
504 notEqual(data, null, 'data is not NULL'); 797 notStrictEqual(data, null, 'data is not NULL');
505 // notEqual(data.invalidReasons, null, 'invalidReasons is not NULL'); 798 // notStrictEqual(data.invalidReasons, null, 'invalidReasons is not NULL');
506 // equal(data.invalidReasons.length, 0, 'Errors object should not be empty.'); 799 // strictEqual(data.invalidReasons.length, 0, 'Errors object should not be empty.');
507 equal(data.mediaSequence, 0, 'MEDIA SEQUENCE is correct'); 800 strictEqual(data.mediaSequence, 0, 'MEDIA SEQUENCE is correct');
508 }); 801 });
509 802
510 test('media sequence is encountered twice in the playlist', function() { 803 test('media sequence is encountered twice in the playlist', function() {
...@@ -514,10 +807,10 @@ ...@@ -514,10 +807,10 @@
514 playlistData = playlistTemplate(testData), 807 playlistData = playlistTemplate(testData),
515 data = m3u8parser.parse(playlistData); 808 data = m3u8parser.parse(playlistData);
516 809
517 notEqual(data, null, 'data is not NULL'); 810 notStrictEqual(data, null, 'data is not NULL');
518 // notEqual(data.invalidReasons, null, 'invalidReasons is not NULL'); 811 // notStrictEqual(data.invalidReasons, null, 'invalidReasons is not NULL');
519 // equal(data.invalidReasons.length, 0, 'Errors object should not be empty.'); 812 // strictEqual(data.invalidReasons.length, 0, 'Errors object should not be empty.');
520 equal(data.mediaSequence, 0, 'MEDIA SEQUENCE tags after the first should be ignored'); 813 strictEqual(data.mediaSequence, 0, 'MEDIA SEQUENCE tags after the first should be ignored');
521 }); 814 });
522 815
523 test('media sequence is undefined in the playlist', function() { 816 test('media sequence is undefined in the playlist', function() {
...@@ -527,10 +820,10 @@ ...@@ -527,10 +820,10 @@
527 playlistData = playlistTemplate(testData), 820 playlistData = playlistTemplate(testData),
528 data = m3u8parser.parse(playlistData); 821 data = m3u8parser.parse(playlistData);
529 822
530 notEqual(data, null, 'data is not NULL'); 823 notStrictEqual(data, null, 'data is not NULL');
531 // notEqual(data.invalidReasons, null, 'invalidReasons is not NULL'); 824 // notStrictEqual(data.invalidReasons, null, 'invalidReasons is not NULL');
532 // equal(data.invalidReasons.length, 0, 'Errors object should not be empty.'); 825 // strictEqual(data.invalidReasons.length, 0, 'Errors object should not be empty.');
533 equal(data.mediaSequence, undefined, 'MEDIA SEQUENCE is undefined'); 826 strictEqual(data.mediaSequence, undefined, 'MEDIA SEQUENCE is undefined');
534 }); 827 });
535 828
536 // test('media sequence is empty in the playlist', function() { 829 // test('media sequence is empty in the playlist', function() {
...@@ -540,10 +833,10 @@ ...@@ -540,10 +833,10 @@
540 // playlistData = playlistTemplate(testData), 833 // playlistData = playlistTemplate(testData),
541 // data = m3u8parser.parse(playlistData); 834 // data = m3u8parser.parse(playlistData);
542 835
543 // notEqual(data, null, 'data is not NULL'); 836 // notStrictEqual(data, null, 'data is not NULL');
544 // // notEqual(data.invalidReasons, null, 'invalidReasons is not NULL'); 837 // // notStrictEqual(data.invalidReasons, null, 'invalidReasons is not NULL');
545 // // equal(data.invalidReasons.length, 1, 'data has 1 invalid reasons'); 838 // // strictEqual(data.invalidReasons.length, 1, 'data has 1 invalid reasons');
546 // equal(data.mediaSequence, '', 'media sequence is the empty string'); 839 // strictEqual(data.mediaSequence, '', 'media sequence is the empty string');
547 // }); 840 // });
548 841
549 test('media sequence is high (non-zero in first file) in the playlist', function() { 842 test('media sequence is high (non-zero in first file) in the playlist', function() {
...@@ -553,10 +846,10 @@ ...@@ -553,10 +846,10 @@
553 playlistData = playlistTemplate(testData), 846 playlistData = playlistTemplate(testData),
554 data = m3u8parser.parse(playlistData); 847 data = m3u8parser.parse(playlistData);
555 848
556 notEqual(data, null, 'data is not NULL'); 849 notStrictEqual(data, null, 'data is not NULL');
557 // notEqual(data.invalidReasons, null, 'invalidReasons is not NULL'); 850 // notStrictEqual(data.invalidReasons, null, 'invalidReasons is not NULL');
558 // equal(data.invalidReasons.length, 1, 'data has 1 invalid reasons'); 851 // strictEqual(data.invalidReasons.length, 1, 'data has 1 invalid reasons');
559 // equal(data.invalidReasons[0], 'Invalid Media Sequence Value: \'1\''); 852 // strictEqual(data.invalidReasons[0], 'Invalid Media Sequence Value: \'1\'');
560 }); 853 });
561 854
562 test('handles invalid media sequence numbers in the playlist', function() { 855 test('handles invalid media sequence numbers in the playlist', function() {
...@@ -566,11 +859,11 @@ ...@@ -566,11 +859,11 @@
566 playlistData = playlistTemplate(testData), 859 playlistData = playlistTemplate(testData),
567 data = m3u8parser.parse(playlistData); 860 data = m3u8parser.parse(playlistData);
568 861
569 notEqual(data, null, 'data is not NULL'); 862 notStrictEqual(data, null, 'data is not NULL');
570 // notEqual(data.invalidReasons, null, 'invalidReasons is not NULL'); 863 // notStrictEqual(data.invalidReasons, null, 'invalidReasons is not NULL');
571 // equal(data.invalidReasons.length, 1, 'data has 1 invalid reasons'); 864 // strictEqual(data.invalidReasons.length, 1, 'data has 1 invalid reasons');
572 // equal(data.invalidReasons[0], 'Invalid Media Sequence Value: \'-1\''); 865 // strictEqual(data.invalidReasons[0], 'Invalid Media Sequence Value: \'-1\'');
573 equal(data.mediaSequence, -1, 'negative media sequence numbers don\'t break parsing'); 866 strictEqual(data.mediaSequence, -1, 'negative media sequence numbers don\'t break parsing');
574 }); 867 });
575 868
576 test('media sequence invalid (string) in the playlist', function() { 869 test('media sequence invalid (string) in the playlist', function() {
...@@ -580,10 +873,10 @@ ...@@ -580,10 +873,10 @@
580 playlistData = playlistTemplate(testData), 873 playlistData = playlistTemplate(testData),
581 data = m3u8parser.parse(playlistData); 874 data = m3u8parser.parse(playlistData);
582 875
583 notEqual(data, null, 'data is not NULL'); 876 notStrictEqual(data, null, 'data is not NULL');
584 // notEqual(data.invalidReasons, null, 'invalidReasons is not NULL'); 877 // notStrictEqual(data.invalidReasons, null, 'invalidReasons is not NULL');
585 // equal(data.invalidReasons.length, 1, 'data has 1 invalid reasons'); 878 // strictEqual(data.invalidReasons.length, 1, 'data has 1 invalid reasons');
586 // equal(data.invalidReasons[0], 'Invalid Media Sequence Value: \'asdfkasdkfl\''); 879 // strictEqual(data.invalidReasons[0], 'Invalid Media Sequence Value: \'asdfkasdkfl\'');
587 }); 880 });
588 881
589 module('Representative Playlist', { 882 module('Representative Playlist', {
...@@ -596,13 +889,13 @@ ...@@ -596,13 +889,13 @@
596 var data = m3u8parser.parse(window.brightcove_playlist_data); 889 var data = m3u8parser.parse(window.brightcove_playlist_data);
597 890
598 ok(data); 891 ok(data);
599 equal(data.playlists.length, 4, 'has correct playlist count'); 892 strictEqual(data.playlists.length, 4, 'has correct playlist count');
600 equal(data.playlists[0].attributes.bandwidth, 240000, 'first rendition index bandwidth is correct'); 893 strictEqual(data.playlists[0].attributes.bandwidth, 240000, 'first rendition index bandwidth is correct');
601 equal(data.playlists[0].attributes.programId, 1, 'first rendition index program-id is correct'); 894 strictEqual(data.playlists[0].attributes.programId, 1, 'first rendition index program-id is correct');
602 equal(data.playlists[0].attributes.resolution.width, 895 strictEqual(data.playlists[0].attributes.resolution.width,
603 396, 896 396,
604 'first rendition index resolution width is correct'); 897 'first rendition index resolution width is correct');
605 equal(data.playlists[0].attributes.resolution.height, 898 strictEqual(data.playlists[0].attributes.resolution.height,
606 224, 899 224,
607 'first rendition index resolution height is correct'); 900 'first rendition index resolution height is correct');
608 901
...@@ -638,9 +931,9 @@ ...@@ -638,9 +931,9 @@
638 playlistData = playlistTemplate(testData), 931 playlistData = playlistTemplate(testData),
639 data = m3u8parser.parse(playlistData); 932 data = m3u8parser.parse(playlistData);
640 933
641 notEqual(data, null, 'data is not NULL'); 934 notStrictEqual(data, null, 'data is not NULL');
642 // notEqual(data.invalidReasons, null, 'invalidReasons is not NULL'); 935 // notStrictEqual(data.invalidReasons, null, 'invalidReasons is not NULL');
643 // equal(data.invalidReasons.length, 0, 'Errors object should not be empty.'); 936 // strictEqual(data.invalidReasons.length, 0, 'Errors object should not be empty.');
644 }); 937 });
645 938
646 test('test valid extinf without associated segment in playlist', function() { 939 test('test valid extinf without associated segment in playlist', function() {
...@@ -650,10 +943,10 @@ ...@@ -650,10 +943,10 @@
650 playlistData = playlistTemplate(testData), 943 playlistData = playlistTemplate(testData),
651 data = m3u8parser.parse(playlistData); 944 data = m3u8parser.parse(playlistData);
652 945
653 notEqual(data, null, 'data is not NULL'); 946 notStrictEqual(data, null, 'data is not NULL');
654 // notEqual(data.invalidReasons, null, 'invalidReasons is not NULL'); 947 // notStrictEqual(data.invalidReasons, null, 'invalidReasons is not NULL');
655 // equal(data.invalidReasons.length, 1, 'data has 1 invalid reasons'); 948 // strictEqual(data.invalidReasons.length, 1, 'data has 1 invalid reasons');
656 //equal(data.invalidReasons[0], 'Invalid Segment Data: \'#EXTINF missing segment\''); 949 //strictEqual(data.invalidReasons[0], 'Invalid Segment Data: \'#EXTINF missing segment\'');
657 }); 950 });
658 951
659 // 952 //
...@@ -664,9 +957,9 @@ ...@@ -664,9 +957,9 @@
664 playlistData = playlistTemplate(testData), 957 playlistData = playlistTemplate(testData),
665 data = m3u8parser.parse(playlistData); 958 data = m3u8parser.parse(playlistData);
666 959
667 notEqual(data, null, 'data is not NULL'); 960 notStrictEqual(data, null, 'data is not NULL');
668 // notEqual(data.invalidReasons, null, 'invalidReasons is not NULL'); 961 // notStrictEqual(data.invalidReasons, null, 'invalidReasons is not NULL');
669 // equal(data.invalidReasons.length, 1, 'data has 1 invalid reasons'); 962 // strictEqual(data.invalidReasons.length, 1, 'data has 1 invalid reasons');
670 }); 963 });
671 964
672 //its best practice that every extinf have the same value, but its not required 965 //its best practice that every extinf have the same value, but its not required
...@@ -677,9 +970,9 @@ ...@@ -677,9 +970,9 @@
677 playlistData = playlistTemplate(testData), 970 playlistData = playlistTemplate(testData),
678 data = m3u8parser.parse(playlistData); 971 data = m3u8parser.parse(playlistData);
679 972
680 notEqual(data, null, 'data is not NULL'); 973 notStrictEqual(data, null, 'data is not NULL');
681 // notEqual(data.invalidReasons, null, 'invalidReasons is not NULL'); 974 // notStrictEqual(data.invalidReasons, null, 'invalidReasons is not NULL');
682 // equal(data.invalidReasons.length, 0, 'Errors object should not be empty.'); 975 // strictEqual(data.invalidReasons.length, 0, 'Errors object should not be empty.');
683 }); 976 });
684 977
685 //extinf values must be below the target duration 978 //extinf values must be below the target duration
...@@ -690,10 +983,10 @@ ...@@ -690,10 +983,10 @@
690 playlistData = playlistTemplate(testData), 983 playlistData = playlistTemplate(testData),
691 data = m3u8parser.parse(playlistData); 984 data = m3u8parser.parse(playlistData);
692 985
693 notEqual(data, null, 'data is not NULL'); 986 notStrictEqual(data, null, 'data is not NULL');
694 // notEqual(data.invalidReasons, null, 'invalidReasons is not NULL'); 987 // notStrictEqual(data.invalidReasons, null, 'invalidReasons is not NULL');
695 // equal(data.invalidReasons.length, 1, 'data has 1 invalid reasons'); 988 // strictEqual(data.invalidReasons.length, 1, 'data has 1 invalid reasons');
696 // equal(data.invalidReasons[0], 'Invalid Segment Data: \'#EXTINF value higher than #TARGETDURATION\''); 989 // strictEqual(data.invalidReasons[0], 'Invalid Segment Data: \'#EXTINF value higher than #TARGETDURATION\'');
697 }); 990 });
698 991
699 //extinf values must be below the target duration 992 //extinf values must be below the target duration
...@@ -704,10 +997,10 @@ ...@@ -704,10 +997,10 @@
704 playlistData = playlistTemplate(testData), 997 playlistData = playlistTemplate(testData),
705 data = m3u8parser.parse(playlistData); 998 data = m3u8parser.parse(playlistData);
706 999
707 notEqual(data, null, 'data is not NULL'); 1000 notStrictEqual(data, null, 'data is not NULL');
708 // notEqual(data.invalidReasons, null, 'invalidReasons is not NULL'); 1001 // notStrictEqual(data.invalidReasons, null, 'invalidReasons is not NULL');
709 // equal(data.invalidReasons.length, 1, 'data has 1 invalid reasons'); 1002 // strictEqual(data.invalidReasons.length, 1, 'data has 1 invalid reasons');
710 // equal(data.invalidReasons[0], 'Invalid Segment Data: \'#EXTINF value not an integer\''); 1003 // strictEqual(data.invalidReasons[0], 'Invalid Segment Data: \'#EXTINF value not an integer\'');
711 }); 1004 });
712 1005
713 //extinf values must be below the target duration 1006 //extinf values must be below the target duration
...@@ -718,9 +1011,9 @@ ...@@ -718,9 +1011,9 @@
718 playlistData = playlistTemplate(testData), 1011 playlistData = playlistTemplate(testData),
719 data = m3u8parser.parse(playlistData); 1012 data = m3u8parser.parse(playlistData);
720 1013
721 notEqual(data, null, 'data is not NULL'); 1014 notStrictEqual(data, null, 'data is not NULL');
722 // notEqual(data.invalidReasons, null, 'invalidReasons is not NULL'); 1015 // notStrictEqual(data.invalidReasons, null, 'invalidReasons is not NULL');
723 // equal(data.invalidReasons.length, 0, 'Errors object should not be empty.'); 1016 // strictEqual(data.invalidReasons.length, 0, 'Errors object should not be empty.');
724 }); 1017 });
725 1018
726 //extinf values must be below the target duration 1019 //extinf values must be below the target duration
...@@ -731,10 +1024,10 @@ ...@@ -731,10 +1024,10 @@
731 playlistData = playlistTemplate(testData), 1024 playlistData = playlistTemplate(testData),
732 data = m3u8parser.parse(playlistData); 1025 data = m3u8parser.parse(playlistData);
733 1026
734 notEqual(data, null, 'data is not NULL'); 1027 notStrictEqual(data, null, 'data is not NULL');
735 // notEqual(data.invalidReasons, null, 'invalidReasons is not NULL'); 1028 // notStrictEqual(data.invalidReasons, null, 'invalidReasons is not NULL');
736 // equal(data.invalidReasons.length, 1, 'data has 1 invalid reasons'); 1029 // strictEqual(data.invalidReasons.length, 1, 'data has 1 invalid reasons');
737 // equal(data.invalidReasons[0], 'Invalid Segment Data: \'#EXTINF value empty\''); 1030 // strictEqual(data.invalidReasons[0], 'Invalid Segment Data: \'#EXTINF value empty\'');
738 }); 1031 });
739 1032
740 /* 1033 /*
...@@ -756,10 +1049,10 @@ ...@@ -756,10 +1049,10 @@
756 playlistData = playlistTemplate(testData), 1049 playlistData = playlistTemplate(testData),
757 data = m3u8parser.parse(playlistData); 1050 data = m3u8parser.parse(playlistData);
758 1051
759 notEqual(data, null, 'data is not NULL'); 1052 notStrictEqual(data, null, 'data is not NULL');
760 // notEqual(data.invalidReasons, null, 'invalidReasons is not NULL'); 1053 // notStrictEqual(data.invalidReasons, null, 'invalidReasons is not NULL');
761 // equal(data.invalidReasons.length, 0, 'Errors object should not be empty.'); 1054 // strictEqual(data.invalidReasons.length, 0, 'Errors object should not be empty.');
762 equal(data.allowCache, 'YES', 'EXT-X-ALLOW-CACHE should be YES'); 1055 strictEqual(data.allowCache, 'YES', 'EXT-X-ALLOW-CACHE should be YES');
763 }); 1056 });
764 1057
765 test('test EXT-X-ALLOW-CACHE NO', function() { 1058 test('test EXT-X-ALLOW-CACHE NO', function() {
...@@ -769,10 +1062,10 @@ ...@@ -769,10 +1062,10 @@
769 playlistData = playlistTemplate(testData), 1062 playlistData = playlistTemplate(testData),
770 data = m3u8parser.parse(playlistData); 1063 data = m3u8parser.parse(playlistData);
771 1064
772 notEqual(data, null, 'data is not NULL'); 1065 notStrictEqual(data, null, 'data is not NULL');
773 // notEqual(data.invalidReasons, null, 'invalidReasons is not NULL'); 1066 // notStrictEqual(data.invalidReasons, null, 'invalidReasons is not NULL');
774 // equal(data.invalidReasons.length, 0, 'Errors object should not be empty.'); 1067 // strictEqual(data.invalidReasons.length, 0, 'Errors object should not be empty.');
775 equal(data.allowCache, 'NO', 'EXT-X-ALLOW-CACHE should be NO'); 1068 strictEqual(data.allowCache, 'NO', 'EXT-X-ALLOW-CACHE should be NO');
776 }); 1069 });
777 1070
778 test('test EXT-X-ALLOW-CACHE invalid, default to YES', function() { 1071 test('test EXT-X-ALLOW-CACHE invalid, default to YES', function() {
...@@ -782,11 +1075,11 @@ ...@@ -782,11 +1075,11 @@
782 playlistData = playlistTemplate(testData), 1075 playlistData = playlistTemplate(testData),
783 data = m3u8parser.parse(playlistData); 1076 data = m3u8parser.parse(playlistData);
784 1077
785 notEqual(data, null, 'data is not NULL'); 1078 notStrictEqual(data, null, 'data is not NULL');
786 // notEqual(data.invalidReasons, null, 'invalidReasons is not NULL'); 1079 // notStrictEqual(data.invalidReasons, null, 'invalidReasons is not NULL');
787 // equal(data.invalidReasons.length, 1, 'data has 1 invalid reasons'); 1080 // strictEqual(data.invalidReasons.length, 1, 'data has 1 invalid reasons');
788 // equal(data.invalidReasons[0], 'Invalid EXT-X-ALLOW-CACHE value: \'YESTERDAYNO\''); 1081 // strictEqual(data.invalidReasons[0], 'Invalid EXT-X-ALLOW-CACHE value: \'YESTERDAYNO\'');
789 equal(data.allowCache, 'YES', 'EXT-X-ALLOW-CACHE should default to YES.'); 1082 strictEqual(data.allowCache, 'YES', 'EXT-X-ALLOW-CACHE should default to YES.');
790 }); 1083 });
791 1084
792 // test('test EXT-X-ALLOW-CACHE empty, default to YES', function() { 1085 // test('test EXT-X-ALLOW-CACHE empty, default to YES', function() {
...@@ -796,11 +1089,11 @@ ...@@ -796,11 +1089,11 @@
796 // playlistData = playlistTemplate(testData), 1089 // playlistData = playlistTemplate(testData),
797 // data = m3u8parser.parse(playlistData); 1090 // data = m3u8parser.parse(playlistData);
798 1091
799 // notEqual(data, null, 'data is not NULL'); 1092 // notStrictEqual(data, null, 'data is not NULL');
800 // // notEqual(data.invalidReasons, null, 'invalidReasons is not NULL'); 1093 // // notStrictEqual(data.invalidReasons, null, 'invalidReasons is not NULL');
801 // // equal(data.invalidReasons.length, 1, 'data has 1 invalid reasons'); 1094 // // strictEqual(data.invalidReasons.length, 1, 'data has 1 invalid reasons');
802 // // equal(data.invalidReasons[0], 'Invalid EXT-X-ALLOW-CACHE value: \'\''); 1095 // // strictEqual(data.invalidReasons[0], 'Invalid EXT-X-ALLOW-CACHE value: \'\'');
803 // equal(data.allowCache, 'YES', 'EXT-X-ALLOW-CACHE should default to YES.'); 1096 // strictEqual(data.allowCache, 'YES', 'EXT-X-ALLOW-CACHE should default to YES.');
804 // }); 1097 // });
805 1098
806 // test('test EXT-X-ALLOW-CACHE missing, default to YES', function() { 1099 // test('test EXT-X-ALLOW-CACHE missing, default to YES', function() {
...@@ -810,10 +1103,10 @@ ...@@ -810,10 +1103,10 @@
810 // playlistData = playlistTemplate(testData), 1103 // playlistData = playlistTemplate(testData),
811 // data = m3u8parser.parse(playlistData); 1104 // data = m3u8parser.parse(playlistData);
812 1105
813 // notEqual(data, null, 'data is not NULL'); 1106 // notStrictEqual(data, null, 'data is not NULL');
814 // // notEqual(data.invalidReasons, null, 'invalidReasons is not NULL'); 1107 // // notStrictEqual(data.invalidReasons, null, 'invalidReasons is not NULL');
815 // // equal(data.invalidReasons.length, 1, 'No EXT-X-ALLOW-CACHE specified. Default: YES.'); 1108 // // strictEqual(data.invalidReasons.length, 1, 'No EXT-X-ALLOW-CACHE specified. Default: YES.');
816 // equal(data.allowCache, 'YES', 'EXT-X-ALLOW-CACHE should default to YES'); 1109 // strictEqual(data.allowCache, 'YES', 'EXT-X-ALLOW-CACHE should default to YES');
817 // }); 1110 // });
818 1111
819 // test('test EXT-X-BYTERANGE valid', function() { 1112 // test('test EXT-X-BYTERANGE valid', function() {
...@@ -823,14 +1116,14 @@ ...@@ -823,14 +1116,14 @@
823 // playlistData = playlistTemplate(testData), 1116 // playlistData = playlistTemplate(testData),
824 // data = m3u8parser.parse(playlistData); 1117 // data = m3u8parser.parse(playlistData);
825 1118
826 // notEqual(data, null, 'data is not NULL'); 1119 // notStrictEqual(data, null, 'data is not NULL');
827 // //notEqual(data.invalidReasons, null, 'invalidReasons is not NULL'); 1120 // //notStrictEqual(data.invalidReasons, null, 'invalidReasons is not NULL');
828 // //equal(data.invalidReasons.length, 0, 'Errors object should be empty.'); 1121 // //strictEqual(data.invalidReasons.length, 0, 'Errors object should be empty.');
829 // //TODO: Validate the byteRange info 1122 // //TODO: Validate the byteRange info
830 // equal(data.segments.length, 16, '16 segments should have been parsed.'); 1123 // strictEqual(data.segments.length, 16, '16 segments should have been parsed.');
831 // equal(data.segments[0].byterange, testData.byteRange, 'byteRange incorrect.'); 1124 // strictEqual(data.segments[0].byterange, testData.byteRange, 'byteRange incorrect.');
832 // equal(data.segments[1].byterange, testData.byteRange1, 'byteRange1 incorrect.'); 1125 // strictEqual(data.segments[1].byterange, testData.byteRange1, 'byteRange1 incorrect.');
833 // equal(data.segments[15].byterange, testData.byteRange2, 'byteRange2 incorrect.'); 1126 // strictEqual(data.segments[15].byterange, testData.byteRange2, 'byteRange2 incorrect.');
834 // }); 1127 // });
835 1128
836 // test('test EXT-X-BYTERANGE used but version is < 4', function() { 1129 // test('test EXT-X-BYTERANGE used but version is < 4', function() {
...@@ -840,12 +1133,12 @@ ...@@ -840,12 +1133,12 @@
840 // playlistData = playlistTemplate(testData), 1133 // playlistData = playlistTemplate(testData),
841 // data = m3u8parser.parse(playlistData); 1134 // data = m3u8parser.parse(playlistData);
842 1135
843 // notEqual(data, null, 'data is not NULL'); 1136 // notStrictEqual(data, null, 'data is not NULL');
844 // equal(data.segments.length, 16, '16 segments should have been parsed.'); 1137 // strictEqual(data.segments.length, 16, '16 segments should have been parsed.');
845 // // notEqual(data.invalidReasons, null, 'there should be an error'); 1138 // // notStrictEqual(data.invalidReasons, null, 'there should be an error');
846 // // equal(data.invalidReasons.length, 1, 'there should be 1 error'); 1139 // // strictEqual(data.invalidReasons.length, 1, 'there should be 1 error');
847 // // //TODO: Validate the byteRange info 1140 // // //TODO: Validate the byteRange info
848 // // equal(data.invalidReasons[0], 'EXT-X-BYTERANGE used but version is < 4.');x 1141 // // strictEqual(data.invalidReasons[0], 'EXT-X-BYTERANGE used but version is < 4.');x
849 // }); 1142 // });
850 1143
851 })(window, window.console); 1144 })(window, window.console);
......