]>
Commit | Line | Data |
---|---|---|
1 | /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */ | |
2 | import { checkBadCountPagination, checkBadSortPagination, checkBadStartPagination } from '@server/tests/shared' | |
3 | import { HttpStatusCode, RunnerJob, RunnerJobState, RunnerJobSuccessPayload, RunnerJobUpdatePayload, VideoPrivacy } from '@shared/models' | |
4 | import { | |
5 | cleanupTests, | |
6 | createSingleServer, | |
7 | makePostBodyRequest, | |
8 | PeerTubeServer, | |
9 | sendRTMPStream, | |
10 | setAccessTokensToServers, | |
11 | setDefaultVideoChannel, | |
12 | stopFfmpeg, | |
13 | waitJobs | |
14 | } from '@shared/server-commands' | |
15 | ||
16 | const badUUID = '910ec12a-d9e6-458b-a274-0abb655f9464' | |
17 | ||
18 | describe('Test managing runners', function () { | |
19 | let server: PeerTubeServer | |
20 | ||
21 | let userToken: string | |
22 | ||
23 | let registrationTokenId: number | |
24 | let registrationToken: string | |
25 | ||
26 | let runnerToken: string | |
27 | let runnerToken2: string | |
28 | ||
29 | let completedJobToken: string | |
30 | let completedJobUUID: string | |
31 | ||
32 | let cancelledJobUUID: string | |
33 | ||
34 | before(async function () { | |
35 | this.timeout(120000) | |
36 | ||
37 | const config = { | |
38 | rates_limit: { | |
39 | api: { | |
40 | max: 5000 | |
41 | } | |
42 | } | |
43 | } | |
44 | ||
45 | server = await createSingleServer(1, config) | |
46 | await setAccessTokensToServers([ server ]) | |
47 | await setDefaultVideoChannel([ server ]) | |
48 | ||
49 | userToken = await server.users.generateUserAndToken('user1') | |
50 | ||
51 | const { data } = await server.runnerRegistrationTokens.list() | |
52 | registrationToken = data[0].registrationToken | |
53 | registrationTokenId = data[0].id | |
54 | ||
55 | await server.config.enableTranscoding(true, true) | |
56 | await server.config.enableRemoteTranscoding() | |
57 | runnerToken = await server.runners.autoRegisterRunner() | |
58 | runnerToken2 = await server.runners.autoRegisterRunner() | |
59 | ||
60 | { | |
61 | await server.videos.quickUpload({ name: 'video 1' }) | |
62 | await server.videos.quickUpload({ name: 'video 2' }) | |
63 | ||
64 | await waitJobs([ server ]) | |
65 | ||
66 | { | |
67 | const job = await server.runnerJobs.autoProcessWebVideoJob(runnerToken) | |
68 | completedJobToken = job.jobToken | |
69 | completedJobUUID = job.uuid | |
70 | } | |
71 | ||
72 | { | |
73 | const { job } = await server.runnerJobs.autoAccept({ runnerToken }) | |
74 | cancelledJobUUID = job.uuid | |
75 | await server.runnerJobs.cancelByAdmin({ jobUUID: cancelledJobUUID }) | |
76 | } | |
77 | } | |
78 | }) | |
79 | ||
80 | describe('Managing runner registration tokens', function () { | |
81 | ||
82 | describe('Common', function () { | |
83 | ||
84 | it('Should fail to generate, list or delete runner registration token without oauth token', async function () { | |
85 | const expectedStatus = HttpStatusCode.UNAUTHORIZED_401 | |
86 | ||
87 | await server.runnerRegistrationTokens.generate({ token: null, expectedStatus }) | |
88 | await server.runnerRegistrationTokens.list({ token: null, expectedStatus }) | |
89 | await server.runnerRegistrationTokens.delete({ token: null, id: registrationTokenId, expectedStatus }) | |
90 | }) | |
91 | ||
92 | it('Should fail to generate, list or delete runner registration token without admin rights', async function () { | |
93 | const expectedStatus = HttpStatusCode.FORBIDDEN_403 | |
94 | ||
95 | await server.runnerRegistrationTokens.generate({ token: userToken, expectedStatus }) | |
96 | await server.runnerRegistrationTokens.list({ token: userToken, expectedStatus }) | |
97 | await server.runnerRegistrationTokens.delete({ token: userToken, id: registrationTokenId, expectedStatus }) | |
98 | }) | |
99 | }) | |
100 | ||
101 | describe('Delete', function () { | |
102 | ||
103 | it('Should fail to delete with a bad id', async function () { | |
104 | await server.runnerRegistrationTokens.delete({ id: 404, expectedStatus: HttpStatusCode.NOT_FOUND_404 }) | |
105 | }) | |
106 | }) | |
107 | ||
108 | describe('List', function () { | |
109 | const path = '/api/v1/runners/registration-tokens' | |
110 | ||
111 | it('Should fail to list with a bad start pagination', async function () { | |
112 | await checkBadStartPagination(server.url, path, server.accessToken) | |
113 | }) | |
114 | ||
115 | it('Should fail to list with a bad count pagination', async function () { | |
116 | await checkBadCountPagination(server.url, path, server.accessToken) | |
117 | }) | |
118 | ||
119 | it('Should fail to list with an incorrect sort', async function () { | |
120 | await checkBadSortPagination(server.url, path, server.accessToken) | |
121 | }) | |
122 | ||
123 | it('Should succeed to list with the correct params', async function () { | |
124 | await server.runnerRegistrationTokens.list({ start: 0, count: 5, sort: '-createdAt' }) | |
125 | }) | |
126 | }) | |
127 | }) | |
128 | ||
129 | describe('Managing runners', function () { | |
130 | let toDeleteId: number | |
131 | ||
132 | describe('Register', function () { | |
133 | const name = 'runner name' | |
134 | ||
135 | it('Should fail with a bad registration token', async function () { | |
136 | const expectedStatus = HttpStatusCode.BAD_REQUEST_400 | |
137 | ||
138 | await server.runners.register({ name, registrationToken: 'a'.repeat(4000), expectedStatus }) | |
139 | await server.runners.register({ name, registrationToken: null, expectedStatus }) | |
140 | }) | |
141 | ||
142 | it('Should fail with an unknown registration token', async function () { | |
143 | await server.runners.register({ name, registrationToken: 'aaa', expectedStatus: HttpStatusCode.NOT_FOUND_404 }) | |
144 | }) | |
145 | ||
146 | it('Should fail with a bad name', async function () { | |
147 | const expectedStatus = HttpStatusCode.BAD_REQUEST_400 | |
148 | ||
149 | await server.runners.register({ name: '', registrationToken, expectedStatus }) | |
150 | await server.runners.register({ name: 'a'.repeat(200), registrationToken, expectedStatus }) | |
151 | }) | |
152 | ||
153 | it('Should fail with an invalid description', async function () { | |
154 | const expectedStatus = HttpStatusCode.BAD_REQUEST_400 | |
155 | ||
156 | await server.runners.register({ name, description: '', registrationToken, expectedStatus }) | |
157 | await server.runners.register({ name, description: 'a'.repeat(5000), registrationToken, expectedStatus }) | |
158 | }) | |
159 | ||
160 | it('Should succeed with the correct params', async function () { | |
161 | const { id } = await server.runners.register({ name, description: 'super description', registrationToken }) | |
162 | ||
163 | toDeleteId = id | |
164 | }) | |
165 | }) | |
166 | ||
167 | describe('Delete', function () { | |
168 | ||
169 | it('Should fail without oauth token', async function () { | |
170 | await server.runners.delete({ token: null, id: toDeleteId, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 }) | |
171 | }) | |
172 | ||
173 | it('Should fail without admin rights', async function () { | |
174 | await server.runners.delete({ token: userToken, id: toDeleteId, expectedStatus: HttpStatusCode.FORBIDDEN_403 }) | |
175 | }) | |
176 | ||
177 | it('Should fail with a bad id', async function () { | |
178 | await server.runners.delete({ id: 'hi' as any, expectedStatus: HttpStatusCode.BAD_REQUEST_400 }) | |
179 | }) | |
180 | ||
181 | it('Should fail with an unknown id', async function () { | |
182 | await server.runners.delete({ id: 404, expectedStatus: HttpStatusCode.NOT_FOUND_404 }) | |
183 | }) | |
184 | ||
185 | it('Should succeed with the correct params', async function () { | |
186 | await server.runners.delete({ id: toDeleteId }) | |
187 | }) | |
188 | }) | |
189 | ||
190 | describe('List', function () { | |
191 | const path = '/api/v1/runners' | |
192 | ||
193 | it('Should fail without oauth token', async function () { | |
194 | await server.runners.list({ token: null, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 }) | |
195 | }) | |
196 | ||
197 | it('Should fail without admin rights', async function () { | |
198 | await server.runners.list({ token: userToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 }) | |
199 | }) | |
200 | ||
201 | it('Should fail to list with a bad start pagination', async function () { | |
202 | await checkBadStartPagination(server.url, path, server.accessToken) | |
203 | }) | |
204 | ||
205 | it('Should fail to list with a bad count pagination', async function () { | |
206 | await checkBadCountPagination(server.url, path, server.accessToken) | |
207 | }) | |
208 | ||
209 | it('Should fail to list with an incorrect sort', async function () { | |
210 | await checkBadSortPagination(server.url, path, server.accessToken) | |
211 | }) | |
212 | ||
213 | it('Should succeed to list with the correct params', async function () { | |
214 | await server.runners.list({ start: 0, count: 5, sort: '-createdAt' }) | |
215 | }) | |
216 | }) | |
217 | ||
218 | }) | |
219 | ||
220 | describe('Runner jobs by admin', function () { | |
221 | ||
222 | describe('Cancel', function () { | |
223 | let jobUUID: string | |
224 | ||
225 | before(async function () { | |
226 | this.timeout(60000) | |
227 | ||
228 | await server.videos.quickUpload({ name: 'video' }) | |
229 | await waitJobs([ server ]) | |
230 | ||
231 | const { availableJobs } = await server.runnerJobs.request({ runnerToken }) | |
232 | jobUUID = availableJobs[0].uuid | |
233 | }) | |
234 | ||
235 | it('Should fail without oauth token', async function () { | |
236 | await server.runnerJobs.cancelByAdmin({ token: null, jobUUID, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 }) | |
237 | }) | |
238 | ||
239 | it('Should fail without admin rights', async function () { | |
240 | await server.runnerJobs.cancelByAdmin({ token: userToken, jobUUID, expectedStatus: HttpStatusCode.FORBIDDEN_403 }) | |
241 | }) | |
242 | ||
243 | it('Should fail with a bad job uuid', async function () { | |
244 | await server.runnerJobs.cancelByAdmin({ jobUUID: 'hello', expectedStatus: HttpStatusCode.BAD_REQUEST_400 }) | |
245 | }) | |
246 | ||
247 | it('Should fail with an unknown job uuid', async function () { | |
248 | const jobUUID = badUUID | |
249 | await server.runnerJobs.cancelByAdmin({ jobUUID, expectedStatus: HttpStatusCode.NOT_FOUND_404 }) | |
250 | }) | |
251 | ||
252 | it('Should succeed with the correct params', async function () { | |
253 | await server.runnerJobs.cancelByAdmin({ jobUUID }) | |
254 | }) | |
255 | }) | |
256 | ||
257 | describe('List', function () { | |
258 | const path = '/api/v1/runners/jobs' | |
259 | ||
260 | it('Should fail without oauth token', async function () { | |
261 | await server.runnerJobs.list({ token: null, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 }) | |
262 | }) | |
263 | ||
264 | it('Should fail without admin rights', async function () { | |
265 | await server.runnerJobs.list({ token: userToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 }) | |
266 | }) | |
267 | ||
268 | it('Should fail to list with a bad start pagination', async function () { | |
269 | await checkBadStartPagination(server.url, path, server.accessToken) | |
270 | }) | |
271 | ||
272 | it('Should fail to list with a bad count pagination', async function () { | |
273 | await checkBadCountPagination(server.url, path, server.accessToken) | |
274 | }) | |
275 | ||
276 | it('Should fail to list with an incorrect sort', async function () { | |
277 | await checkBadSortPagination(server.url, path, server.accessToken) | |
278 | }) | |
279 | ||
280 | it('Should succeed to list with the correct params', async function () { | |
281 | await server.runnerJobs.list({ start: 0, count: 5, sort: '-createdAt' }) | |
282 | }) | |
283 | }) | |
284 | ||
285 | }) | |
286 | ||
287 | describe('Runner jobs by runners', function () { | |
288 | let jobUUID: string | |
289 | let jobToken: string | |
290 | let videoUUID: string | |
291 | ||
292 | let jobUUID2: string | |
293 | let jobToken2: string | |
294 | ||
295 | let videoUUID2: string | |
296 | ||
297 | let pendingUUID: string | |
298 | ||
299 | let liveAcceptedJob: RunnerJob & { jobToken: string } | |
300 | ||
301 | async function fetchFiles (options: { | |
302 | jobUUID: string | |
303 | videoUUID: string | |
304 | runnerToken: string | |
305 | jobToken: string | |
306 | expectedStatus: HttpStatusCode | |
307 | }) { | |
308 | const { jobUUID, expectedStatus, videoUUID, runnerToken, jobToken } = options | |
309 | ||
310 | const basePath = '/api/v1/runners/jobs/' + jobUUID + '/files/videos/' + videoUUID | |
311 | const paths = [ `${basePath}/max-quality`, `${basePath}/previews/max-quality` ] | |
312 | ||
313 | for (const path of paths) { | |
314 | await makePostBodyRequest({ url: server.url, path, fields: { runnerToken, jobToken }, expectedStatus }) | |
315 | } | |
316 | } | |
317 | ||
318 | before(async function () { | |
319 | this.timeout(120000) | |
320 | ||
321 | { | |
322 | await server.runnerJobs.cancelAllJobs({ state: RunnerJobState.PENDING }) | |
323 | } | |
324 | ||
325 | { | |
326 | const { uuid } = await server.videos.quickUpload({ name: 'video' }) | |
327 | videoUUID = uuid | |
328 | ||
329 | await waitJobs([ server ]) | |
330 | ||
331 | const { job } = await server.runnerJobs.autoAccept({ runnerToken }) | |
332 | jobUUID = job.uuid | |
333 | jobToken = job.jobToken | |
334 | } | |
335 | ||
336 | { | |
337 | const { uuid } = await server.videos.quickUpload({ name: 'video' }) | |
338 | videoUUID2 = uuid | |
339 | ||
340 | await waitJobs([ server ]) | |
341 | ||
342 | const { job } = await server.runnerJobs.autoAccept({ runnerToken: runnerToken2 }) | |
343 | jobUUID2 = job.uuid | |
344 | jobToken2 = job.jobToken | |
345 | } | |
346 | ||
347 | { | |
348 | await server.videos.quickUpload({ name: 'video' }) | |
349 | await waitJobs([ server ]) | |
350 | ||
351 | const { availableJobs } = await server.runnerJobs.request({ runnerToken }) | |
352 | pendingUUID = availableJobs[0].uuid | |
353 | } | |
354 | ||
355 | { | |
356 | await server.config.enableLive({ | |
357 | allowReplay: false, | |
358 | resolutions: 'max', | |
359 | transcoding: true | |
360 | }) | |
361 | ||
362 | const { live } = await server.live.quickCreate({ permanentLive: true, saveReplay: false, privacy: VideoPrivacy.PUBLIC }) | |
363 | ||
364 | const ffmpegCommand = sendRTMPStream({ rtmpBaseUrl: live.rtmpUrl, streamKey: live.streamKey }) | |
365 | await waitJobs([ server ]) | |
366 | ||
367 | await server.runnerJobs.requestLiveJob(runnerToken) | |
368 | ||
369 | const { job } = await server.runnerJobs.autoAccept({ runnerToken, type: 'live-rtmp-hls-transcoding' }) | |
370 | liveAcceptedJob = job | |
371 | ||
372 | await stopFfmpeg(ffmpegCommand) | |
373 | } | |
374 | }) | |
375 | ||
376 | describe('Common runner tokens validations', function () { | |
377 | ||
378 | async function testEndpoints (options: { | |
379 | jobUUID: string | |
380 | runnerToken: string | |
381 | jobToken: string | |
382 | expectedStatus: HttpStatusCode | |
383 | }) { | |
384 | await fetchFiles({ ...options, videoUUID }) | |
385 | ||
386 | await server.runnerJobs.abort({ ...options, reason: 'reason' }) | |
387 | await server.runnerJobs.update({ ...options }) | |
388 | await server.runnerJobs.error({ ...options, message: 'message' }) | |
389 | await server.runnerJobs.success({ ...options, payload: { videoFile: 'video_short.mp4' } }) | |
390 | } | |
391 | ||
392 | it('Should fail with an invalid job uuid', async function () { | |
393 | await testEndpoints({ jobUUID: 'a', runnerToken, jobToken, expectedStatus: HttpStatusCode.BAD_REQUEST_400 }) | |
394 | }) | |
395 | ||
396 | it('Should fail with an unknown job uuid', async function () { | |
397 | const jobUUID = badUUID | |
398 | await testEndpoints({ jobUUID, runnerToken, jobToken, expectedStatus: HttpStatusCode.NOT_FOUND_404 }) | |
399 | }) | |
400 | ||
401 | it('Should fail with an invalid runner token', async function () { | |
402 | await testEndpoints({ jobUUID, runnerToken: '', jobToken, expectedStatus: HttpStatusCode.BAD_REQUEST_400 }) | |
403 | }) | |
404 | ||
405 | it('Should fail with an unknown runner token', async function () { | |
406 | const runnerToken = badUUID | |
407 | await testEndpoints({ jobUUID, runnerToken, jobToken, expectedStatus: HttpStatusCode.NOT_FOUND_404 }) | |
408 | }) | |
409 | ||
410 | it('Should fail with an invalid job token job uuid', async function () { | |
411 | await testEndpoints({ jobUUID, runnerToken, jobToken: '', expectedStatus: HttpStatusCode.BAD_REQUEST_400 }) | |
412 | }) | |
413 | ||
414 | it('Should fail with an unknown job token job uuid', async function () { | |
415 | const jobToken = badUUID | |
416 | await testEndpoints({ jobUUID, runnerToken, jobToken, expectedStatus: HttpStatusCode.NOT_FOUND_404 }) | |
417 | }) | |
418 | ||
419 | it('Should fail with a runner token not associated to this job', async function () { | |
420 | await testEndpoints({ jobUUID, runnerToken: runnerToken2, jobToken, expectedStatus: HttpStatusCode.NOT_FOUND_404 }) | |
421 | }) | |
422 | ||
423 | it('Should fail with a job uuid not associated to the job token', async function () { | |
424 | await testEndpoints({ jobUUID: jobUUID2, runnerToken, jobToken, expectedStatus: HttpStatusCode.NOT_FOUND_404 }) | |
425 | await testEndpoints({ jobUUID, runnerToken, jobToken: jobToken2, expectedStatus: HttpStatusCode.NOT_FOUND_404 }) | |
426 | }) | |
427 | }) | |
428 | ||
429 | describe('Unregister', function () { | |
430 | ||
431 | it('Should fail without a runner token', async function () { | |
432 | await server.runners.unregister({ runnerToken: null, expectedStatus: HttpStatusCode.BAD_REQUEST_400 }) | |
433 | }) | |
434 | ||
435 | it('Should fail with a bad a runner token', async function () { | |
436 | await server.runners.unregister({ runnerToken: '', expectedStatus: HttpStatusCode.BAD_REQUEST_400 }) | |
437 | }) | |
438 | ||
439 | it('Should fail with an unknown runner token', async function () { | |
440 | await server.runners.unregister({ runnerToken: badUUID, expectedStatus: HttpStatusCode.NOT_FOUND_404 }) | |
441 | }) | |
442 | }) | |
443 | ||
444 | describe('Request', function () { | |
445 | ||
446 | it('Should fail without a runner token', async function () { | |
447 | await server.runnerJobs.request({ runnerToken: null, expectedStatus: HttpStatusCode.BAD_REQUEST_400 }) | |
448 | }) | |
449 | ||
450 | it('Should fail with a bad a runner token', async function () { | |
451 | await server.runnerJobs.request({ runnerToken: '', expectedStatus: HttpStatusCode.BAD_REQUEST_400 }) | |
452 | }) | |
453 | ||
454 | it('Should fail with an unknown runner token', async function () { | |
455 | await server.runnerJobs.request({ runnerToken: badUUID, expectedStatus: HttpStatusCode.NOT_FOUND_404 }) | |
456 | }) | |
457 | }) | |
458 | ||
459 | describe('Accept', function () { | |
460 | ||
461 | it('Should fail with a bad a job uuid', async function () { | |
462 | await server.runnerJobs.accept({ jobUUID: '', runnerToken, expectedStatus: HttpStatusCode.BAD_REQUEST_400 }) | |
463 | }) | |
464 | ||
465 | it('Should fail with an unknown job uuid', async function () { | |
466 | await server.runnerJobs.accept({ jobUUID: badUUID, runnerToken, expectedStatus: HttpStatusCode.NOT_FOUND_404 }) | |
467 | }) | |
468 | ||
469 | it('Should fail with a job not in pending state', async function () { | |
470 | await server.runnerJobs.accept({ jobUUID: completedJobUUID, runnerToken, expectedStatus: HttpStatusCode.BAD_REQUEST_400 }) | |
471 | await server.runnerJobs.accept({ jobUUID: cancelledJobUUID, runnerToken, expectedStatus: HttpStatusCode.BAD_REQUEST_400 }) | |
472 | }) | |
473 | ||
474 | it('Should fail without a runner token', async function () { | |
475 | await server.runnerJobs.accept({ jobUUID: pendingUUID, runnerToken: null, expectedStatus: HttpStatusCode.BAD_REQUEST_400 }) | |
476 | }) | |
477 | ||
478 | it('Should fail with a bad a runner token', async function () { | |
479 | await server.runnerJobs.accept({ jobUUID: pendingUUID, runnerToken: '', expectedStatus: HttpStatusCode.BAD_REQUEST_400 }) | |
480 | }) | |
481 | ||
482 | it('Should fail with an unknown runner token', async function () { | |
483 | await server.runnerJobs.accept({ jobUUID: pendingUUID, runnerToken: badUUID, expectedStatus: HttpStatusCode.NOT_FOUND_404 }) | |
484 | }) | |
485 | }) | |
486 | ||
487 | describe('Abort', function () { | |
488 | ||
489 | it('Should fail without a reason', async function () { | |
490 | await server.runnerJobs.abort({ jobUUID, jobToken, runnerToken, reason: null, expectedStatus: HttpStatusCode.BAD_REQUEST_400 }) | |
491 | }) | |
492 | ||
493 | it('Should fail with a bad reason', async function () { | |
494 | const reason = 'reason'.repeat(5000) | |
495 | await server.runnerJobs.abort({ jobUUID, jobToken, runnerToken, reason, expectedStatus: HttpStatusCode.BAD_REQUEST_400 }) | |
496 | }) | |
497 | ||
498 | it('Should fail with a job not in processing state', async function () { | |
499 | await server.runnerJobs.abort({ | |
500 | jobUUID: completedJobUUID, | |
501 | jobToken: completedJobToken, | |
502 | runnerToken, | |
503 | reason: 'reason', | |
504 | expectedStatus: HttpStatusCode.BAD_REQUEST_400 | |
505 | }) | |
506 | }) | |
507 | }) | |
508 | ||
509 | describe('Update', function () { | |
510 | ||
511 | describe('Common', function () { | |
512 | ||
513 | it('Should fail with an invalid progress', async function () { | |
514 | await server.runnerJobs.update({ jobUUID, jobToken, runnerToken, progress: 101, expectedStatus: HttpStatusCode.BAD_REQUEST_400 }) | |
515 | }) | |
516 | ||
517 | it('Should fail with a job not in processing state', async function () { | |
518 | await server.runnerJobs.update({ | |
519 | jobUUID: completedJobUUID, | |
520 | jobToken: completedJobToken, | |
521 | runnerToken, | |
522 | expectedStatus: HttpStatusCode.BAD_REQUEST_400 | |
523 | }) | |
524 | }) | |
525 | }) | |
526 | ||
527 | describe('Live RTMP to HLS', function () { | |
528 | const base: RunnerJobUpdatePayload = { | |
529 | masterPlaylistFile: 'live/master.m3u8', | |
530 | resolutionPlaylistFilename: '0.m3u8', | |
531 | resolutionPlaylistFile: 'live/1.m3u8', | |
532 | type: 'add-chunk', | |
533 | videoChunkFile: 'live/1-000069.ts', | |
534 | videoChunkFilename: '1-000068.ts' | |
535 | } | |
536 | ||
537 | function testUpdate (payload: RunnerJobUpdatePayload) { | |
538 | return server.runnerJobs.update({ | |
539 | jobUUID: liveAcceptedJob.uuid, | |
540 | jobToken: liveAcceptedJob.jobToken, | |
541 | payload, | |
542 | runnerToken, | |
543 | expectedStatus: HttpStatusCode.BAD_REQUEST_400 | |
544 | }) | |
545 | } | |
546 | ||
547 | it('Should fail with an invalid resolutionPlaylistFilename', async function () { | |
548 | await testUpdate({ ...base, resolutionPlaylistFilename: undefined }) | |
549 | await testUpdate({ ...base, resolutionPlaylistFilename: 'coucou/hello' }) | |
550 | await testUpdate({ ...base, resolutionPlaylistFilename: 'hello' }) | |
551 | }) | |
552 | ||
553 | it('Should fail with an invalid videoChunkFilename', async function () { | |
554 | await testUpdate({ ...base, resolutionPlaylistFilename: undefined }) | |
555 | await testUpdate({ ...base, resolutionPlaylistFilename: 'coucou/hello' }) | |
556 | await testUpdate({ ...base, resolutionPlaylistFilename: 'hello' }) | |
557 | }) | |
558 | ||
559 | it('Should fail with an invalid type', async function () { | |
560 | await testUpdate({ ...base, type: undefined }) | |
561 | await testUpdate({ ...base, type: 'toto' as any }) | |
562 | }) | |
563 | ||
564 | it('Should succeed with the correct params', async function () { | |
565 | await server.runnerJobs.update({ | |
566 | jobUUID: liveAcceptedJob.uuid, | |
567 | jobToken: liveAcceptedJob.jobToken, | |
568 | payload: base, | |
569 | runnerToken | |
570 | }) | |
571 | ||
572 | await server.runnerJobs.update({ | |
573 | jobUUID: liveAcceptedJob.uuid, | |
574 | jobToken: liveAcceptedJob.jobToken, | |
575 | payload: { ...base, masterPlaylistFile: undefined }, | |
576 | runnerToken | |
577 | }) | |
578 | }) | |
579 | }) | |
580 | }) | |
581 | ||
582 | describe('Error', function () { | |
583 | ||
584 | it('Should fail with a missing error message', async function () { | |
585 | await server.runnerJobs.error({ jobUUID, jobToken, runnerToken, message: null, expectedStatus: HttpStatusCode.BAD_REQUEST_400 }) | |
586 | }) | |
587 | ||
588 | it('Should fail with an invalid error messgae', async function () { | |
589 | const message = 'a'.repeat(6000) | |
590 | await server.runnerJobs.error({ jobUUID, jobToken, runnerToken, message, expectedStatus: HttpStatusCode.BAD_REQUEST_400 }) | |
591 | }) | |
592 | ||
593 | it('Should fail with a job not in processing state', async function () { | |
594 | await server.runnerJobs.error({ | |
595 | jobUUID: completedJobUUID, | |
596 | jobToken: completedJobToken, | |
597 | message: 'my message', | |
598 | runnerToken, | |
599 | expectedStatus: HttpStatusCode.BAD_REQUEST_400 | |
600 | }) | |
601 | }) | |
602 | }) | |
603 | ||
604 | describe('Success', function () { | |
605 | let vodJobUUID: string | |
606 | let vodJobToken: string | |
607 | ||
608 | describe('Common', function () { | |
609 | ||
610 | it('Should fail with a job not in processing state', async function () { | |
611 | await server.runnerJobs.success({ | |
612 | jobUUID: completedJobUUID, | |
613 | jobToken: completedJobToken, | |
614 | payload: { videoFile: 'video_short.mp4' }, | |
615 | runnerToken, | |
616 | expectedStatus: HttpStatusCode.BAD_REQUEST_400 | |
617 | }) | |
618 | }) | |
619 | }) | |
620 | ||
621 | describe('VOD', function () { | |
622 | ||
623 | it('Should fail with an invalid vod web video payload', async function () { | |
624 | const { job } = await server.runnerJobs.autoAccept({ runnerToken, type: 'vod-web-video-transcoding' }) | |
625 | ||
626 | await server.runnerJobs.success({ | |
627 | jobUUID: job.uuid, | |
628 | jobToken: job.jobToken, | |
629 | payload: { hello: 'video_short.mp4' } as any, | |
630 | runnerToken, | |
631 | expectedStatus: HttpStatusCode.BAD_REQUEST_400 | |
632 | }) | |
633 | ||
634 | vodJobUUID = job.uuid | |
635 | vodJobToken = job.jobToken | |
636 | }) | |
637 | ||
638 | it('Should fail with an invalid vod hls payload', async function () { | |
639 | // To create HLS jobs | |
640 | const payload: RunnerJobSuccessPayload = { videoFile: 'video_short.mp4' } | |
641 | await server.runnerJobs.success({ runnerToken, jobUUID: vodJobUUID, jobToken: vodJobToken, payload }) | |
642 | ||
643 | await waitJobs([ server ]) | |
644 | ||
645 | const { job } = await server.runnerJobs.autoAccept({ runnerToken, type: 'vod-hls-transcoding' }) | |
646 | ||
647 | await server.runnerJobs.success({ | |
648 | jobUUID: job.uuid, | |
649 | jobToken: job.jobToken, | |
650 | payload: { videoFile: 'video_short.mp4' } as any, | |
651 | runnerToken, | |
652 | expectedStatus: HttpStatusCode.BAD_REQUEST_400 | |
653 | }) | |
654 | }) | |
655 | ||
656 | it('Should fail with an invalid vod audio merge payload', async function () { | |
657 | const attributes = { name: 'audio_with_preview', previewfile: 'preview.jpg', fixture: 'sample.ogg' } | |
658 | await server.videos.upload({ attributes, mode: 'legacy' }) | |
659 | ||
660 | await waitJobs([ server ]) | |
661 | ||
662 | const { job } = await server.runnerJobs.autoAccept({ runnerToken, type: 'vod-audio-merge-transcoding' }) | |
663 | ||
664 | await server.runnerJobs.success({ | |
665 | jobUUID: job.uuid, | |
666 | jobToken: job.jobToken, | |
667 | payload: { hello: 'video_short.mp4' } as any, | |
668 | runnerToken, | |
669 | expectedStatus: HttpStatusCode.BAD_REQUEST_400 | |
670 | }) | |
671 | }) | |
672 | }) | |
673 | }) | |
674 | ||
675 | describe('Job files', function () { | |
676 | ||
677 | describe('Video files', function () { | |
678 | ||
679 | it('Should fail with an invalid video id', async function () { | |
680 | await fetchFiles({ videoUUID: 'a', jobUUID, runnerToken, jobToken, expectedStatus: HttpStatusCode.BAD_REQUEST_400 }) | |
681 | }) | |
682 | ||
683 | it('Should fail with an unknown video id', async function () { | |
684 | const videoUUID = '910ec12a-d9e6-458b-a274-0abb655f9464' | |
685 | await fetchFiles({ videoUUID, jobUUID, runnerToken, jobToken, expectedStatus: HttpStatusCode.NOT_FOUND_404 }) | |
686 | }) | |
687 | ||
688 | it('Should fail with a video id not associated to this job', async function () { | |
689 | await fetchFiles({ videoUUID: videoUUID2, jobUUID, runnerToken, jobToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 }) | |
690 | }) | |
691 | ||
692 | it('Should succeed with the correct params', async function () { | |
693 | await fetchFiles({ videoUUID, jobUUID, runnerToken, jobToken, expectedStatus: HttpStatusCode.OK_200 }) | |
694 | }) | |
695 | }) | |
696 | }) | |
697 | }) | |
698 | ||
699 | after(async function () { | |
700 | await cleanupTests([ server ]) | |
701 | }) | |
702 | }) |