diff options
author | Chocobozzz <me@florianbigard.com> | 2023-07-31 14:34:36 +0200 |
---|---|---|
committer | Chocobozzz <me@florianbigard.com> | 2023-08-11 15:02:33 +0200 |
commit | 3a4992633ee62d5edfbb484d9c6bcb3cf158489d (patch) | |
tree | e4510b39bdac9c318fdb4b47018d08f15368b8f0 /packages/tests/src/api/live/live-save-replay.ts | |
parent | 04d1da5621d25d59bd5fa1543b725c497bf5d9a8 (diff) | |
download | PeerTube-3a4992633ee62d5edfbb484d9c6bcb3cf158489d.tar.gz PeerTube-3a4992633ee62d5edfbb484d9c6bcb3cf158489d.tar.zst PeerTube-3a4992633ee62d5edfbb484d9c6bcb3cf158489d.zip |
Migrate server to ESM
Sorry for the very big commit that may lead to git log issues and merge
conflicts, but it's a major step forward:
* Server can be faster at startup because imports() are async and we can
easily lazy import big modules
* Angular doesn't seem to support ES import (with .js extension), so we
had to correctly organize peertube into a monorepo:
* Use yarn workspace feature
* Use typescript reference projects for dependencies
* Shared projects have been moved into "packages", each one is now a
node module (with a dedicated package.json/tsconfig.json)
* server/tools have been moved into apps/ and is now a dedicated app
bundled and published on NPM so users don't have to build peertube
cli tools manually
* server/tests have been moved into packages/ so we don't compile
them every time we want to run the server
* Use isolatedModule option:
* Had to move from const enum to const
(https://www.typescriptlang.org/docs/handbook/enums.html#objects-vs-enums)
* Had to explictely specify "type" imports when used in decorators
* Prefer tsx (that uses esbuild under the hood) instead of ts-node to
load typescript files (tests with mocha or scripts):
* To reduce test complexity as esbuild doesn't support decorator
metadata, we only test server files that do not import server
models
* We still build tests files into js files for a faster CI
* Remove unmaintained peertube CLI import script
* Removed some barrels to speed up execution (less imports)
Diffstat (limited to 'packages/tests/src/api/live/live-save-replay.ts')
-rw-r--r-- | packages/tests/src/api/live/live-save-replay.ts | 583 |
1 files changed, 583 insertions, 0 deletions
diff --git a/packages/tests/src/api/live/live-save-replay.ts b/packages/tests/src/api/live/live-save-replay.ts new file mode 100644 index 000000000..84135365b --- /dev/null +++ b/packages/tests/src/api/live/live-save-replay.ts | |||
@@ -0,0 +1,583 @@ | |||
1 | /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */ | ||
2 | |||
3 | import { expect } from 'chai' | ||
4 | import { FfmpegCommand } from 'fluent-ffmpeg' | ||
5 | import { wait } from '@peertube/peertube-core-utils' | ||
6 | import { | ||
7 | HttpStatusCode, | ||
8 | HttpStatusCodeType, | ||
9 | LiveVideoCreate, | ||
10 | LiveVideoError, | ||
11 | VideoPrivacy, | ||
12 | VideoPrivacyType, | ||
13 | VideoState, | ||
14 | VideoStateType | ||
15 | } from '@peertube/peertube-models' | ||
16 | import { checkLiveCleanup } from '@tests/shared/live.js' | ||
17 | import { | ||
18 | cleanupTests, | ||
19 | ConfigCommand, | ||
20 | createMultipleServers, | ||
21 | doubleFollow, | ||
22 | findExternalSavedVideo, | ||
23 | PeerTubeServer, | ||
24 | setAccessTokensToServers, | ||
25 | setDefaultVideoChannel, | ||
26 | stopFfmpeg, | ||
27 | testFfmpegStreamError, | ||
28 | waitJobs, | ||
29 | waitUntilLivePublishedOnAllServers, | ||
30 | waitUntilLiveReplacedByReplayOnAllServers, | ||
31 | waitUntilLiveWaitingOnAllServers | ||
32 | } from '@peertube/peertube-server-commands' | ||
33 | |||
34 | describe('Save replay setting', function () { | ||
35 | let servers: PeerTubeServer[] = [] | ||
36 | let liveVideoUUID: string | ||
37 | let ffmpegCommand: FfmpegCommand | ||
38 | |||
39 | async function createLiveWrapper (options: { permanent: boolean, replay: boolean, replaySettings?: { privacy: VideoPrivacyType } }) { | ||
40 | if (liveVideoUUID) { | ||
41 | try { | ||
42 | await servers[0].videos.remove({ id: liveVideoUUID }) | ||
43 | await waitJobs(servers) | ||
44 | } catch {} | ||
45 | } | ||
46 | |||
47 | const attributes: LiveVideoCreate = { | ||
48 | channelId: servers[0].store.channel.id, | ||
49 | privacy: VideoPrivacy.PUBLIC, | ||
50 | name: 'live'.repeat(30), | ||
51 | saveReplay: options.replay, | ||
52 | replaySettings: options.replaySettings, | ||
53 | permanentLive: options.permanent | ||
54 | } | ||
55 | |||
56 | const { uuid } = await servers[0].live.create({ fields: attributes }) | ||
57 | return uuid | ||
58 | } | ||
59 | |||
60 | async function publishLive (options: { permanent: boolean, replay: boolean, replaySettings?: { privacy: VideoPrivacyType } }) { | ||
61 | liveVideoUUID = await createLiveWrapper(options) | ||
62 | |||
63 | const ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ videoId: liveVideoUUID }) | ||
64 | await waitUntilLivePublishedOnAllServers(servers, liveVideoUUID) | ||
65 | |||
66 | const liveDetails = await servers[0].videos.get({ id: liveVideoUUID }) | ||
67 | |||
68 | await waitJobs(servers) | ||
69 | await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200) | ||
70 | |||
71 | return { ffmpegCommand, liveDetails } | ||
72 | } | ||
73 | |||
74 | async function publishLiveAndDelete (options: { permanent: boolean, replay: boolean, replaySettings?: { privacy: VideoPrivacyType } }) { | ||
75 | const { ffmpegCommand, liveDetails } = await publishLive(options) | ||
76 | |||
77 | await Promise.all([ | ||
78 | servers[0].videos.remove({ id: liveVideoUUID }), | ||
79 | testFfmpegStreamError(ffmpegCommand, true) | ||
80 | ]) | ||
81 | |||
82 | await waitJobs(servers) | ||
83 | await wait(5000) | ||
84 | await waitJobs(servers) | ||
85 | |||
86 | return { liveDetails } | ||
87 | } | ||
88 | |||
89 | async function publishLiveAndBlacklist (options: { | ||
90 | permanent: boolean | ||
91 | replay: boolean | ||
92 | replaySettings?: { privacy: VideoPrivacyType } | ||
93 | }) { | ||
94 | const { ffmpegCommand, liveDetails } = await publishLive(options) | ||
95 | |||
96 | await Promise.all([ | ||
97 | servers[0].blacklist.add({ videoId: liveVideoUUID, reason: 'bad live', unfederate: true }), | ||
98 | testFfmpegStreamError(ffmpegCommand, true) | ||
99 | ]) | ||
100 | |||
101 | await waitJobs(servers) | ||
102 | await wait(5000) | ||
103 | await waitJobs(servers) | ||
104 | |||
105 | return { liveDetails } | ||
106 | } | ||
107 | |||
108 | async function checkVideosExist (videoId: string, existsInList: boolean, expectedStatus?: HttpStatusCodeType) { | ||
109 | for (const server of servers) { | ||
110 | const length = existsInList ? 1 : 0 | ||
111 | |||
112 | const { data, total } = await server.videos.list() | ||
113 | expect(data).to.have.lengthOf(length) | ||
114 | expect(total).to.equal(length) | ||
115 | |||
116 | if (expectedStatus) { | ||
117 | await server.videos.get({ id: videoId, expectedStatus }) | ||
118 | } | ||
119 | } | ||
120 | } | ||
121 | |||
122 | async function checkVideoState (videoId: string, state: VideoStateType) { | ||
123 | for (const server of servers) { | ||
124 | const video = await server.videos.get({ id: videoId }) | ||
125 | expect(video.state.id).to.equal(state) | ||
126 | } | ||
127 | } | ||
128 | |||
129 | async function checkVideoPrivacy (videoId: string, privacy: VideoPrivacyType) { | ||
130 | for (const server of servers) { | ||
131 | const video = await server.videos.get({ id: videoId }) | ||
132 | expect(video.privacy.id).to.equal(privacy) | ||
133 | } | ||
134 | } | ||
135 | |||
136 | before(async function () { | ||
137 | this.timeout(120000) | ||
138 | |||
139 | servers = await createMultipleServers(2) | ||
140 | |||
141 | // Get the access tokens | ||
142 | await setAccessTokensToServers(servers) | ||
143 | await setDefaultVideoChannel(servers) | ||
144 | |||
145 | // Server 1 and server 2 follow each other | ||
146 | await doubleFollow(servers[0], servers[1]) | ||
147 | |||
148 | await servers[0].config.updateCustomSubConfig({ | ||
149 | newConfig: { | ||
150 | live: { | ||
151 | enabled: true, | ||
152 | allowReplay: true, | ||
153 | maxDuration: -1, | ||
154 | transcoding: { | ||
155 | enabled: false, | ||
156 | resolutions: ConfigCommand.getCustomConfigResolutions(true) | ||
157 | } | ||
158 | } | ||
159 | } | ||
160 | }) | ||
161 | }) | ||
162 | |||
163 | describe('With save replay disabled', function () { | ||
164 | let sessionStartDateMin: Date | ||
165 | let sessionStartDateMax: Date | ||
166 | let sessionEndDateMin: Date | ||
167 | |||
168 | it('Should correctly create and federate the "waiting for stream" live', async function () { | ||
169 | this.timeout(40000) | ||
170 | |||
171 | liveVideoUUID = await createLiveWrapper({ permanent: false, replay: false }) | ||
172 | |||
173 | await waitJobs(servers) | ||
174 | |||
175 | await checkVideosExist(liveVideoUUID, false, HttpStatusCode.OK_200) | ||
176 | await checkVideoState(liveVideoUUID, VideoState.WAITING_FOR_LIVE) | ||
177 | }) | ||
178 | |||
179 | it('Should correctly have updated the live and federated it when streaming in the live', async function () { | ||
180 | this.timeout(120000) | ||
181 | |||
182 | ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ videoId: liveVideoUUID }) | ||
183 | |||
184 | sessionStartDateMin = new Date() | ||
185 | await waitUntilLivePublishedOnAllServers(servers, liveVideoUUID) | ||
186 | sessionStartDateMax = new Date() | ||
187 | |||
188 | await waitJobs(servers) | ||
189 | |||
190 | await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200) | ||
191 | await checkVideoState(liveVideoUUID, VideoState.PUBLISHED) | ||
192 | }) | ||
193 | |||
194 | it('Should correctly delete the video files after the stream ended', async function () { | ||
195 | this.timeout(120000) | ||
196 | |||
197 | sessionEndDateMin = new Date() | ||
198 | await stopFfmpeg(ffmpegCommand) | ||
199 | |||
200 | for (const server of servers) { | ||
201 | await server.live.waitUntilEnded({ videoId: liveVideoUUID }) | ||
202 | } | ||
203 | await waitJobs(servers) | ||
204 | |||
205 | // Live still exist, but cannot be played anymore | ||
206 | await checkVideosExist(liveVideoUUID, false, HttpStatusCode.OK_200) | ||
207 | await checkVideoState(liveVideoUUID, VideoState.LIVE_ENDED) | ||
208 | |||
209 | // No resolutions saved since we did not save replay | ||
210 | await checkLiveCleanup({ server: servers[0], videoUUID: liveVideoUUID, permanent: false }) | ||
211 | }) | ||
212 | |||
213 | it('Should have appropriate ended session', async function () { | ||
214 | const { data, total } = await servers[0].live.listSessions({ videoId: liveVideoUUID }) | ||
215 | expect(total).to.equal(1) | ||
216 | expect(data).to.have.lengthOf(1) | ||
217 | |||
218 | const session = data[0] | ||
219 | |||
220 | const startDate = new Date(session.startDate) | ||
221 | expect(startDate).to.be.above(sessionStartDateMin) | ||
222 | expect(startDate).to.be.below(sessionStartDateMax) | ||
223 | |||
224 | expect(session.endDate).to.exist | ||
225 | expect(new Date(session.endDate)).to.be.above(sessionEndDateMin) | ||
226 | |||
227 | expect(session.saveReplay).to.be.false | ||
228 | expect(session.error).to.not.exist | ||
229 | expect(session.replayVideo).to.not.exist | ||
230 | }) | ||
231 | |||
232 | it('Should correctly terminate the stream on blacklist and delete the live', async function () { | ||
233 | this.timeout(120000) | ||
234 | |||
235 | await publishLiveAndBlacklist({ permanent: false, replay: false }) | ||
236 | |||
237 | await checkVideosExist(liveVideoUUID, false) | ||
238 | |||
239 | await servers[0].videos.get({ id: liveVideoUUID, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 }) | ||
240 | await servers[1].videos.get({ id: liveVideoUUID, expectedStatus: HttpStatusCode.NOT_FOUND_404 }) | ||
241 | |||
242 | await wait(5000) | ||
243 | await waitJobs(servers) | ||
244 | await checkLiveCleanup({ server: servers[0], videoUUID: liveVideoUUID, permanent: false }) | ||
245 | }) | ||
246 | |||
247 | it('Should have blacklisted session error', async function () { | ||
248 | const session = await servers[0].live.findLatestSession({ videoId: liveVideoUUID }) | ||
249 | expect(session.startDate).to.exist | ||
250 | expect(session.endDate).to.exist | ||
251 | |||
252 | expect(session.error).to.equal(LiveVideoError.BLACKLISTED) | ||
253 | expect(session.replayVideo).to.not.exist | ||
254 | }) | ||
255 | |||
256 | it('Should correctly terminate the stream on delete and delete the video', async function () { | ||
257 | this.timeout(120000) | ||
258 | |||
259 | await publishLiveAndDelete({ permanent: false, replay: false }) | ||
260 | |||
261 | await checkVideosExist(liveVideoUUID, false, HttpStatusCode.NOT_FOUND_404) | ||
262 | await checkLiveCleanup({ server: servers[0], videoUUID: liveVideoUUID, permanent: false }) | ||
263 | }) | ||
264 | }) | ||
265 | |||
266 | describe('With save replay enabled on non permanent live', function () { | ||
267 | |||
268 | it('Should correctly create and federate the "waiting for stream" live', async function () { | ||
269 | this.timeout(120000) | ||
270 | |||
271 | liveVideoUUID = await createLiveWrapper({ permanent: false, replay: true, replaySettings: { privacy: VideoPrivacy.UNLISTED } }) | ||
272 | |||
273 | await waitJobs(servers) | ||
274 | |||
275 | await checkVideosExist(liveVideoUUID, false, HttpStatusCode.OK_200) | ||
276 | await checkVideoState(liveVideoUUID, VideoState.WAITING_FOR_LIVE) | ||
277 | await checkVideoPrivacy(liveVideoUUID, VideoPrivacy.PUBLIC) | ||
278 | }) | ||
279 | |||
280 | it('Should correctly have updated the live and federated it when streaming in the live', async function () { | ||
281 | this.timeout(120000) | ||
282 | |||
283 | ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ videoId: liveVideoUUID }) | ||
284 | await waitUntilLivePublishedOnAllServers(servers, liveVideoUUID) | ||
285 | |||
286 | await waitJobs(servers) | ||
287 | |||
288 | await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200) | ||
289 | await checkVideoState(liveVideoUUID, VideoState.PUBLISHED) | ||
290 | await checkVideoPrivacy(liveVideoUUID, VideoPrivacy.PUBLIC) | ||
291 | }) | ||
292 | |||
293 | it('Should correctly have saved the live and federated it after the streaming', async function () { | ||
294 | this.timeout(120000) | ||
295 | |||
296 | const session = await servers[0].live.findLatestSession({ videoId: liveVideoUUID }) | ||
297 | expect(session.endDate).to.not.exist | ||
298 | expect(session.endingProcessed).to.be.false | ||
299 | expect(session.saveReplay).to.be.true | ||
300 | expect(session.replaySettings).to.exist | ||
301 | expect(session.replaySettings.privacy).to.equal(VideoPrivacy.UNLISTED) | ||
302 | |||
303 | await stopFfmpeg(ffmpegCommand) | ||
304 | |||
305 | await waitUntilLiveReplacedByReplayOnAllServers(servers, liveVideoUUID) | ||
306 | await waitJobs(servers) | ||
307 | |||
308 | // Live has been transcoded | ||
309 | await checkVideosExist(liveVideoUUID, false, HttpStatusCode.OK_200) | ||
310 | await checkVideoState(liveVideoUUID, VideoState.PUBLISHED) | ||
311 | await checkVideoPrivacy(liveVideoUUID, VideoPrivacy.UNLISTED) | ||
312 | }) | ||
313 | |||
314 | it('Should find the replay live session', async function () { | ||
315 | const session = await servers[0].live.getReplaySession({ videoId: liveVideoUUID }) | ||
316 | |||
317 | expect(session).to.exist | ||
318 | |||
319 | expect(session.startDate).to.exist | ||
320 | expect(session.endDate).to.exist | ||
321 | |||
322 | expect(session.error).to.not.exist | ||
323 | expect(session.saveReplay).to.be.true | ||
324 | expect(session.endingProcessed).to.be.true | ||
325 | expect(session.replaySettings).to.exist | ||
326 | expect(session.replaySettings.privacy).to.equal(VideoPrivacy.UNLISTED) | ||
327 | |||
328 | expect(session.replayVideo).to.exist | ||
329 | expect(session.replayVideo.id).to.exist | ||
330 | expect(session.replayVideo.shortUUID).to.exist | ||
331 | expect(session.replayVideo.uuid).to.equal(liveVideoUUID) | ||
332 | }) | ||
333 | |||
334 | it('Should update the saved live and correctly federate the updated attributes', async function () { | ||
335 | this.timeout(120000) | ||
336 | |||
337 | await servers[0].videos.update({ id: liveVideoUUID, attributes: { name: 'video updated', privacy: VideoPrivacy.PUBLIC } }) | ||
338 | await waitJobs(servers) | ||
339 | |||
340 | for (const server of servers) { | ||
341 | const video = await server.videos.get({ id: liveVideoUUID }) | ||
342 | expect(video.name).to.equal('video updated') | ||
343 | expect(video.isLive).to.be.false | ||
344 | expect(video.privacy.id).to.equal(VideoPrivacy.PUBLIC) | ||
345 | } | ||
346 | }) | ||
347 | |||
348 | it('Should have cleaned up the live files', async function () { | ||
349 | await checkLiveCleanup({ server: servers[0], videoUUID: liveVideoUUID, permanent: false, savedResolutions: [ 720 ] }) | ||
350 | }) | ||
351 | |||
352 | it('Should correctly terminate the stream on blacklist and blacklist the saved replay video', async function () { | ||
353 | this.timeout(120000) | ||
354 | |||
355 | await publishLiveAndBlacklist({ permanent: false, replay: true, replaySettings: { privacy: VideoPrivacy.PUBLIC } }) | ||
356 | |||
357 | await checkVideosExist(liveVideoUUID, false) | ||
358 | |||
359 | await servers[0].videos.get({ id: liveVideoUUID, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 }) | ||
360 | await servers[1].videos.get({ id: liveVideoUUID, expectedStatus: HttpStatusCode.NOT_FOUND_404 }) | ||
361 | |||
362 | await wait(5000) | ||
363 | await waitJobs(servers) | ||
364 | await checkLiveCleanup({ server: servers[0], videoUUID: liveVideoUUID, permanent: false, savedResolutions: [ 720 ] }) | ||
365 | }) | ||
366 | |||
367 | it('Should correctly terminate the stream on delete and delete the video', async function () { | ||
368 | this.timeout(120000) | ||
369 | |||
370 | await publishLiveAndDelete({ permanent: false, replay: true, replaySettings: { privacy: VideoPrivacy.PUBLIC } }) | ||
371 | |||
372 | await checkVideosExist(liveVideoUUID, false, HttpStatusCode.NOT_FOUND_404) | ||
373 | await checkLiveCleanup({ server: servers[0], videoUUID: liveVideoUUID, permanent: false }) | ||
374 | }) | ||
375 | }) | ||
376 | |||
377 | describe('With save replay enabled on permanent live', function () { | ||
378 | let lastReplayUUID: string | ||
379 | |||
380 | describe('With a first live and its replay', function () { | ||
381 | |||
382 | it('Should correctly create and federate the "waiting for stream" live', async function () { | ||
383 | this.timeout(120000) | ||
384 | |||
385 | liveVideoUUID = await createLiveWrapper({ permanent: true, replay: true, replaySettings: { privacy: VideoPrivacy.UNLISTED } }) | ||
386 | |||
387 | await waitJobs(servers) | ||
388 | |||
389 | await checkVideosExist(liveVideoUUID, false, HttpStatusCode.OK_200) | ||
390 | await checkVideoState(liveVideoUUID, VideoState.WAITING_FOR_LIVE) | ||
391 | await checkVideoPrivacy(liveVideoUUID, VideoPrivacy.PUBLIC) | ||
392 | }) | ||
393 | |||
394 | it('Should correctly have updated the live and federated it when streaming in the live', async function () { | ||
395 | this.timeout(120000) | ||
396 | |||
397 | ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ videoId: liveVideoUUID }) | ||
398 | await waitUntilLivePublishedOnAllServers(servers, liveVideoUUID) | ||
399 | |||
400 | await waitJobs(servers) | ||
401 | |||
402 | await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200) | ||
403 | await checkVideoState(liveVideoUUID, VideoState.PUBLISHED) | ||
404 | await checkVideoPrivacy(liveVideoUUID, VideoPrivacy.PUBLIC) | ||
405 | }) | ||
406 | |||
407 | it('Should correctly have saved the live and federated it after the streaming', async function () { | ||
408 | this.timeout(120000) | ||
409 | |||
410 | const liveDetails = await servers[0].videos.get({ id: liveVideoUUID }) | ||
411 | |||
412 | await stopFfmpeg(ffmpegCommand) | ||
413 | |||
414 | await waitUntilLiveWaitingOnAllServers(servers, liveVideoUUID) | ||
415 | await waitJobs(servers) | ||
416 | |||
417 | const video = await findExternalSavedVideo(servers[0], liveDetails) | ||
418 | expect(video).to.exist | ||
419 | |||
420 | for (const server of servers) { | ||
421 | await server.videos.get({ id: video.uuid }) | ||
422 | } | ||
423 | |||
424 | lastReplayUUID = video.uuid | ||
425 | }) | ||
426 | |||
427 | it('Should have appropriate ended session and replay live session', async function () { | ||
428 | const { data, total } = await servers[0].live.listSessions({ videoId: liveVideoUUID }) | ||
429 | expect(total).to.equal(1) | ||
430 | expect(data).to.have.lengthOf(1) | ||
431 | |||
432 | const sessionFromLive = data[0] | ||
433 | const sessionFromReplay = await servers[0].live.getReplaySession({ videoId: lastReplayUUID }) | ||
434 | |||
435 | for (const session of [ sessionFromLive, sessionFromReplay ]) { | ||
436 | expect(session.startDate).to.exist | ||
437 | expect(session.endDate).to.exist | ||
438 | |||
439 | expect(session.replaySettings).to.exist | ||
440 | expect(session.replaySettings.privacy).to.equal(VideoPrivacy.UNLISTED) | ||
441 | |||
442 | expect(session.error).to.not.exist | ||
443 | |||
444 | expect(session.replayVideo).to.exist | ||
445 | expect(session.replayVideo.id).to.exist | ||
446 | expect(session.replayVideo.shortUUID).to.exist | ||
447 | expect(session.replayVideo.uuid).to.equal(lastReplayUUID) | ||
448 | } | ||
449 | }) | ||
450 | |||
451 | it('Should have the first live replay with correct settings', async function () { | ||
452 | await checkVideosExist(lastReplayUUID, false, HttpStatusCode.OK_200) | ||
453 | await checkVideoState(lastReplayUUID, VideoState.PUBLISHED) | ||
454 | await checkVideoPrivacy(lastReplayUUID, VideoPrivacy.UNLISTED) | ||
455 | }) | ||
456 | }) | ||
457 | |||
458 | describe('With a second live and its replay', function () { | ||
459 | |||
460 | it('Should update the replay settings', async function () { | ||
461 | await servers[0].live.update({ videoId: liveVideoUUID, fields: { replaySettings: { privacy: VideoPrivacy.PUBLIC } } }) | ||
462 | await waitJobs(servers) | ||
463 | |||
464 | const live = await servers[0].live.get({ videoId: liveVideoUUID }) | ||
465 | |||
466 | expect(live.saveReplay).to.be.true | ||
467 | expect(live.replaySettings).to.exist | ||
468 | expect(live.replaySettings.privacy).to.equal(VideoPrivacy.PUBLIC) | ||
469 | |||
470 | }) | ||
471 | |||
472 | it('Should correctly have updated the live and federated it when streaming in the live', async function () { | ||
473 | this.timeout(120000) | ||
474 | |||
475 | ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ videoId: liveVideoUUID }) | ||
476 | await waitUntilLivePublishedOnAllServers(servers, liveVideoUUID) | ||
477 | |||
478 | await waitJobs(servers) | ||
479 | |||
480 | await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200) | ||
481 | await checkVideoState(liveVideoUUID, VideoState.PUBLISHED) | ||
482 | await checkVideoPrivacy(liveVideoUUID, VideoPrivacy.PUBLIC) | ||
483 | }) | ||
484 | |||
485 | it('Should correctly have saved the live and federated it after the streaming', async function () { | ||
486 | this.timeout(120000) | ||
487 | |||
488 | const liveDetails = await servers[0].videos.get({ id: liveVideoUUID }) | ||
489 | |||
490 | await stopFfmpeg(ffmpegCommand) | ||
491 | |||
492 | await waitUntilLiveWaitingOnAllServers(servers, liveVideoUUID) | ||
493 | await waitJobs(servers) | ||
494 | |||
495 | const video = await findExternalSavedVideo(servers[0], liveDetails) | ||
496 | expect(video).to.exist | ||
497 | |||
498 | for (const server of servers) { | ||
499 | await server.videos.get({ id: video.uuid }) | ||
500 | } | ||
501 | |||
502 | lastReplayUUID = video.uuid | ||
503 | }) | ||
504 | |||
505 | it('Should have appropriate ended session and replay live session', async function () { | ||
506 | const { data, total } = await servers[0].live.listSessions({ videoId: liveVideoUUID }) | ||
507 | expect(total).to.equal(2) | ||
508 | expect(data).to.have.lengthOf(2) | ||
509 | |||
510 | const sessionFromLive = data[1] | ||
511 | const sessionFromReplay = await servers[0].live.getReplaySession({ videoId: lastReplayUUID }) | ||
512 | |||
513 | for (const session of [ sessionFromLive, sessionFromReplay ]) { | ||
514 | expect(session.startDate).to.exist | ||
515 | expect(session.endDate).to.exist | ||
516 | |||
517 | expect(session.replaySettings).to.exist | ||
518 | expect(session.replaySettings.privacy).to.equal(VideoPrivacy.PUBLIC) | ||
519 | |||
520 | expect(session.error).to.not.exist | ||
521 | |||
522 | expect(session.replayVideo).to.exist | ||
523 | expect(session.replayVideo.id).to.exist | ||
524 | expect(session.replayVideo.shortUUID).to.exist | ||
525 | expect(session.replayVideo.uuid).to.equal(lastReplayUUID) | ||
526 | } | ||
527 | }) | ||
528 | |||
529 | it('Should have the first live replay with correct settings', async function () { | ||
530 | await checkVideosExist(lastReplayUUID, true, HttpStatusCode.OK_200) | ||
531 | await checkVideoState(lastReplayUUID, VideoState.PUBLISHED) | ||
532 | await checkVideoPrivacy(lastReplayUUID, VideoPrivacy.PUBLIC) | ||
533 | }) | ||
534 | |||
535 | it('Should have cleaned up the live files', async function () { | ||
536 | await checkLiveCleanup({ server: servers[0], videoUUID: liveVideoUUID, permanent: false }) | ||
537 | }) | ||
538 | |||
539 | it('Should correctly terminate the stream on blacklist and blacklist the saved replay video', async function () { | ||
540 | this.timeout(120000) | ||
541 | |||
542 | await servers[0].videos.remove({ id: lastReplayUUID }) | ||
543 | const { liveDetails } = await publishLiveAndBlacklist({ | ||
544 | permanent: true, | ||
545 | replay: true, | ||
546 | replaySettings: { privacy: VideoPrivacy.PUBLIC } | ||
547 | }) | ||
548 | |||
549 | const replay = await findExternalSavedVideo(servers[0], liveDetails) | ||
550 | expect(replay).to.exist | ||
551 | |||
552 | for (const videoId of [ liveVideoUUID, replay.uuid ]) { | ||
553 | await checkVideosExist(videoId, false) | ||
554 | |||
555 | await servers[0].videos.get({ id: videoId, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 }) | ||
556 | await servers[1].videos.get({ id: videoId, expectedStatus: HttpStatusCode.NOT_FOUND_404 }) | ||
557 | } | ||
558 | |||
559 | await checkLiveCleanup({ server: servers[0], videoUUID: liveVideoUUID, permanent: false }) | ||
560 | }) | ||
561 | |||
562 | it('Should correctly terminate the stream on delete and not save the video', async function () { | ||
563 | this.timeout(120000) | ||
564 | |||
565 | const { liveDetails } = await publishLiveAndDelete({ | ||
566 | permanent: true, | ||
567 | replay: true, | ||
568 | replaySettings: { privacy: VideoPrivacy.PUBLIC } | ||
569 | }) | ||
570 | |||
571 | const replay = await findExternalSavedVideo(servers[0], liveDetails) | ||
572 | expect(replay).to.not.exist | ||
573 | |||
574 | await checkVideosExist(liveVideoUUID, false, HttpStatusCode.NOT_FOUND_404) | ||
575 | await checkLiveCleanup({ server: servers[0], videoUUID: liveVideoUUID, permanent: false }) | ||
576 | }) | ||
577 | }) | ||
578 | }) | ||
579 | |||
580 | after(async function () { | ||
581 | await cleanupTests(servers) | ||
582 | }) | ||
583 | }) | ||