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.
Showing
2 changed files
with
639 additions
and
215 deletions
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 |
... | @@ -314,9 +607,9 @@ | ... | @@ -314,9 +607,9 @@ |
314 | 607 | ||
315 | The EXT-X-PLAYLIST-TYPE tag MUST NOT appear in a Master Playlist. | 608 | The EXT-X-PLAYLIST-TYPE tag MUST NOT appear in a Master Playlist. |
316 | */ | 609 | */ |
317 | 610 | ||
318 | test('should have parsed VOD playlist type', function() { | 611 | test('should have parsed VOD playlist type', function() { |
319 | var | 612 | var |
320 | playlistTemplate = Handlebars.compile(window.playlist_type_template), | 613 | playlistTemplate = Handlebars.compile(window.playlist_type_template), |
321 | testData = {playlistType: 'VOD'}, | 614 | testData = {playlistType: 'VOD'}, |
322 | playlistData = playlistTemplate(testData), | 615 | playlistData = playlistTemplate(testData), |
... | @@ -326,13 +619,13 @@ | ... | @@ -326,13 +619,13 @@ |
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() { |
335 | var | 628 | var |
336 | playlistTemplate = Handlebars.compile(window.playlist_type_template), | 629 | playlistTemplate = Handlebars.compile(window.playlist_type_template), |
337 | testData = {playlistType: 'EVENT'}, | 630 | testData = {playlistType: 'EVENT'}, |
338 | playlistData = playlistTemplate(testData), | 631 | playlistData = playlistTemplate(testData), |
... | @@ -342,13 +635,13 @@ | ... | @@ -342,13 +635,13 @@ |
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() { |
351 | var | 644 | var |
352 | playlistTemplate = Handlebars.compile(window.playlist_type_template), | 645 | playlistTemplate = Handlebars.compile(window.playlist_type_template), |
353 | testData = {}, | 646 | testData = {}, |
354 | playlistData = playlistTemplate(testData), | 647 | playlistData = playlistTemplate(testData), |
... | @@ -358,21 +651,21 @@ | ... | @@ -358,21 +651,21 @@ |
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() { |
368 | var | 661 | var |
369 | playlistTemplate = Handlebars.compile(window.playlist_type_template), | 662 | playlistTemplate = Handlebars.compile(window.playlist_type_template), |
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 |
... | @@ -405,72 +698,72 @@ | ... | @@ -405,72 +698,72 @@ |
405 | */ | 698 | */ |
406 | 699 | ||
407 | test('valid target duration', function() { | 700 | test('valid target duration', function() { |
408 | var | 701 | var |
409 | playlistTemplate = Handlebars.compile(window.playlist_target_duration_template), | 702 | playlistTemplate = Handlebars.compile(window.playlist_target_duration_template), |
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() { |
419 | var | 712 | var |
420 | playlistTemplate = Handlebars.compile(window.playlist_target_duration_template), | 713 | playlistTemplate = Handlebars.compile(window.playlist_target_duration_template), |
421 | testData = {targetDuration: 'string'}, | 714 | testData = {targetDuration: 'string'}, |
422 | playlistData = playlistTemplate(testData), | 715 | playlistData = playlistTemplate(testData), |
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() { |
433 | var | 726 | var |
434 | playlistTemplate = Handlebars.compile(window.playlist_target_duration_template), | 727 | playlistTemplate = Handlebars.compile(window.playlist_target_duration_template), |
435 | testData = {targetDuration: '\'\''}, | 728 | testData = {targetDuration: '\'\''}, |
436 | playlistData = playlistTemplate(testData), | 729 | playlistData = playlistTemplate(testData), |
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() { |
447 | var | 740 | var |
448 | playlistTemplate = Handlebars.compile(window.playlist_target_duration_template), | 741 | playlistTemplate = Handlebars.compile(window.playlist_target_duration_template), |
449 | testData = {}, | 742 | testData = {}, |
450 | playlistData = playlistTemplate(testData), | 743 | playlistData = playlistTemplate(testData), |
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 | ||
461 | test('target duration lower than segment', function() { | 754 | test('target duration lower than segment', function() { |
462 | var | 755 | var |
463 | playlistTemplate = Handlebars.compile(window.playlist_target_duration_template), | 756 | playlistTemplate = Handlebars.compile(window.playlist_target_duration_template), |
464 | testData = {targetDuration: '4'}, | 757 | testData = {targetDuration: '4'}, |
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 |
475 | 768 | ||
476 | Each media segment in a Playlist has a unique integer sequence | 769 | Each media segment in a Playlist has a unique integer sequence |
... | @@ -489,48 +782,48 @@ | ... | @@ -489,48 +782,48 @@ |
489 | MEDIA-SEQUENCE tag then the sequence number of the first segment in | 782 | MEDIA-SEQUENCE tag then the sequence number of the first segment in |
490 | the playlist SHALL be considered to be 0. A client MUST NOT assume | 783 | the playlist SHALL be considered to be 0. A client MUST NOT assume |
491 | that segments with the same sequence number in different Media | 784 | that segments with the same sequence number in different Media |
492 | Playlists contain matching content. | 785 | Playlists contain matching content. |
493 | 786 | ||
494 | A media URI is not required to contain its sequence number. | 787 | A media URI is not required to contain its sequence number. |
495 | */ | 788 | */ |
496 | 789 | ||
497 | test('media sequence is valid in the playlist', function() { | 790 | test('media sequence is valid in the playlist', function() { |
498 | var | 791 | var |
499 | playlistTemplate = Handlebars.compile(window.playlist_media_sequence_template), | 792 | playlistTemplate = Handlebars.compile(window.playlist_media_sequence_template), |
500 | testData = {mediaSequence: '0'}, | 793 | testData = {mediaSequence: '0'}, |
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() { |
511 | var | 804 | var |
512 | playlistTemplate = Handlebars.compile(window.playlist_media_sequence_template), | 805 | playlistTemplate = Handlebars.compile(window.playlist_media_sequence_template), |
513 | testData = {mediaSequence: '0', mediaSequence1: '1'}, | 806 | testData = {mediaSequence: '0', mediaSequence1: '1'}, |
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() { |
524 | var | 817 | var |
525 | playlistTemplate = Handlebars.compile(window.playlist_media_sequence_template), | 818 | playlistTemplate = Handlebars.compile(window.playlist_media_sequence_template), |
526 | testData = {mediaSequence: ''}, | 819 | testData = {mediaSequence: ''}, |
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,50 +833,50 @@ | ... | @@ -540,50 +833,50 @@ |
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() { |
550 | var | 843 | var |
551 | playlistTemplate = Handlebars.compile(window.playlist_media_sequence_template), | 844 | playlistTemplate = Handlebars.compile(window.playlist_media_sequence_template), |
552 | testData = {mediaSequence: '1'}, | 845 | testData = {mediaSequence: '1'}, |
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() { |
563 | var | 856 | var |
564 | playlistTemplate = Handlebars.compile(window.playlist_media_sequence_template), | 857 | playlistTemplate = Handlebars.compile(window.playlist_media_sequence_template), |
565 | testData = {mediaSequence: '-1'}, | 858 | testData = {mediaSequence: '-1'}, |
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() { |
577 | var | 870 | var |
578 | playlistTemplate = Handlebars.compile(window.playlist_media_sequence_template), | 871 | playlistTemplate = Handlebars.compile(window.playlist_media_sequence_template), |
579 | testData = {mediaSequence: 'asdfkasdkfl'}, | 872 | testData = {mediaSequence: 'asdfkasdkfl'}, |
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 | ||
... | @@ -630,111 +923,111 @@ | ... | @@ -630,111 +923,111 @@ |
630 | file, when rounded to the nearest integer, MUST be less than or equal | 923 | file, when rounded to the nearest integer, MUST be less than or equal |
631 | to the target duration. | 924 | to the target duration. |
632 | */ | 925 | */ |
633 | 926 | ||
634 | test('test valid extinf values in playlist', function() { | 927 | test('test valid extinf values in playlist', function() { |
635 | var | 928 | var |
636 | playlistTemplate = Handlebars.compile(window.playlist_extinf_template), | 929 | playlistTemplate = Handlebars.compile(window.playlist_extinf_template), |
637 | testData = {version: 4, extInf: '10', extInf1: '10', extInf2: '10', segment: 'hls_450k_video.ts'}, | 930 | testData = {version: 4, extInf: '10', extInf1: '10', extInf2: '10', segment: 'hls_450k_video.ts'}, |
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() { |
647 | var | 940 | var |
648 | playlistTemplate = Handlebars.compile(window.playlist_extinf_template), | 941 | playlistTemplate = Handlebars.compile(window.playlist_extinf_template), |
649 | testData = {version: 4, extInf: '10', extInf1: '10', extInf2: '10'}, | 942 | testData = {version: 4, extInf: '10', extInf1: '10', extInf2: '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 | // |
660 | test('test invalid extinf values in playlist', function() { | 953 | test('test invalid extinf values in playlist', function() { |
661 | var | 954 | var |
662 | playlistTemplate = Handlebars.compile(window.playlist_extinf_template), | 955 | playlistTemplate = Handlebars.compile(window.playlist_extinf_template), |
663 | testData = {version: 4, extInf: 'asdf', extInf1: '10', extInf2: '10', segment: 'hls_450k_video.ts'}, | 956 | testData = {version: 4, extInf: 'asdf', extInf1: '10', extInf2: '10', segment: 'hls_450k_video.ts'}, |
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 |
673 | test('test inconsistent extinf values in playlist below target duration', function() { | 966 | test('test inconsistent extinf values in playlist below target duration', function() { |
674 | var | 967 | var |
675 | playlistTemplate = Handlebars.compile(window.playlist_extinf_template), | 968 | playlistTemplate = Handlebars.compile(window.playlist_extinf_template), |
676 | testData = {version: 4, extInf: '10', extInf1: '7', extInf2: '10', segment: 'hls_450k_video.ts'}, | 969 | testData = {version: 4, extInf: '10', extInf1: '7', extInf2: '10', segment: 'hls_450k_video.ts'}, |
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 |
686 | test('test inconsistent extinf values in playlist above target duration', function() { | 979 | test('test inconsistent extinf values in playlist above target duration', function() { |
687 | var | 980 | var |
688 | playlistTemplate = Handlebars.compile(window.playlist_extinf_template), | 981 | playlistTemplate = Handlebars.compile(window.playlist_extinf_template), |
689 | testData = {version: 4, extInf: '10', extInf1: '7', extInf2: '10', segment: 'hls_450k_video.ts'}, | 982 | testData = {version: 4, extInf: '10', extInf1: '7', extInf2: '10', segment: 'hls_450k_video.ts'}, |
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 |
700 | test('test floating-point values not accepted with version 3', function() { | 993 | test('test floating-point values not accepted with version 3', function() { |
701 | var | 994 | var |
702 | playlistTemplate = Handlebars.compile(window.playlist_extinf_template), | 995 | playlistTemplate = Handlebars.compile(window.playlist_extinf_template), |
703 | testData = {version: 3, extInf: '10.5', extInf1: '10.5', extInf2: '10.5', segment: 'hls_450k_video.ts'}, | 996 | testData = {version: 3, extInf: '10.5', extInf1: '10.5', extInf2: '10.5', segment: 'hls_450k_video.ts'}, |
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 |
714 | test('test floating-point values accepted with version 4', function() { | 1007 | test('test floating-point values accepted with version 4', function() { |
715 | var | 1008 | var |
716 | playlistTemplate = Handlebars.compile(window.playlist_extinf_template), | 1009 | playlistTemplate = Handlebars.compile(window.playlist_extinf_template), |
717 | testData = {version: 4, extInf: '10.5', extInf1: '10.5', extInf2: '10.5', segment: 'hls_450k_video.ts'}, | 1010 | testData = {version: 4, extInf: '10.5', extInf1: '10.5', extInf2: '10.5', segment: 'hls_450k_video.ts'}, |
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 |
727 | test('test empty EXTINF values', function() { | 1020 | test('test empty EXTINF values', function() { |
728 | var | 1021 | var |
729 | playlistTemplate = Handlebars.compile(window.playlist_extinf_template), | 1022 | playlistTemplate = Handlebars.compile(window.playlist_extinf_template), |
730 | testData = {version: 4, extInf: '', extInf1: '10.5', extInf2: '10.5', segment: 'hls_450k_video.ts'}, | 1023 | testData = {version: 4, extInf: '', extInf1: '10.5', extInf2: '10.5', segment: 'hls_450k_video.ts'}, |
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 | /* |
... | @@ -748,45 +1041,45 @@ | ... | @@ -748,45 +1041,45 @@ |
748 | 1041 | ||
749 | #EXT-X-ALLOW-CACHE:<YES|NO> | 1042 | #EXT-X-ALLOW-CACHE:<YES|NO> |
750 | */ | 1043 | */ |
751 | 1044 | ||
752 | test('test EXT-X-ALLOW-CACHE YES', function() { | 1045 | test('test EXT-X-ALLOW-CACHE YES', function() { |
753 | var | 1046 | var |
754 | playlistTemplate = Handlebars.compile(window.playlist_allow_cache), | 1047 | playlistTemplate = Handlebars.compile(window.playlist_allow_cache), |
755 | testData = {version: 4, allowCache: 'YES'}, | 1048 | testData = {version: 4, allowCache: 'YES'}, |
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() { |
766 | var | 1059 | var |
767 | playlistTemplate = Handlebars.compile(window.playlist_allow_cache), | 1060 | playlistTemplate = Handlebars.compile(window.playlist_allow_cache), |
768 | testData = {version: 4, allowCache: 'NO'}, | 1061 | testData = {version: 4, allowCache: 'NO'}, |
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() { |
779 | var | 1072 | var |
780 | playlistTemplate = Handlebars.compile(window.playlist_allow_cache), | 1073 | playlistTemplate = Handlebars.compile(window.playlist_allow_cache), |
781 | testData = {version: 4, allowCache: 'YESTERDAYNO'}, | 1074 | testData = {version: 4, allowCache: 'YESTERDAYNO'}, |
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,26 +1089,26 @@ | ... | @@ -796,26 +1089,26 @@ |
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() { |
807 | // var | 1100 | // var |
808 | // playlistTemplate = Handlebars.compile(window.playlist_allow_cache), | 1101 | // playlistTemplate = Handlebars.compile(window.playlist_allow_cache), |
809 | // testData = {version: 4}, | 1102 | // testData = {version: 4}, |
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() { |
820 | // var | 1113 | // var |
821 | // playlistTemplate = Handlebars.compile(window.playlist_byte_range), | 1114 | // playlistTemplate = Handlebars.compile(window.playlist_byte_range), |
... | @@ -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); | ... | ... |
-
Please register or sign in to post a comment