aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/tests/peertube-runner
diff options
context:
space:
mode:
Diffstat (limited to 'server/tests/peertube-runner')
-rw-r--r--server/tests/peertube-runner/client-cli.ts71
-rw-r--r--server/tests/peertube-runner/index.ts3
-rw-r--r--server/tests/peertube-runner/live-transcoding.ts178
-rw-r--r--server/tests/peertube-runner/vod-transcoding.ts330
4 files changed, 582 insertions, 0 deletions
diff --git a/server/tests/peertube-runner/client-cli.ts b/server/tests/peertube-runner/client-cli.ts
new file mode 100644
index 000000000..90bf73ef7
--- /dev/null
+++ b/server/tests/peertube-runner/client-cli.ts
@@ -0,0 +1,71 @@
1/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
2
3import { expect } from 'chai'
4import { PeerTubeRunnerProcess } from '@server/tests/shared'
5import { cleanupTests, createSingleServer, PeerTubeServer, setAccessTokensToServers, setDefaultVideoChannel } from '@shared/server-commands'
6
7describe('Test peertube-runner program client CLI', function () {
8 let server: PeerTubeServer
9 let peertubeRunner: PeerTubeRunnerProcess
10
11 before(async function () {
12 this.timeout(120_000)
13
14 server = await createSingleServer(1)
15
16 await setAccessTokensToServers([ server ])
17 await setDefaultVideoChannel([ server ])
18
19 await server.config.enableRemoteTranscoding()
20
21 peertubeRunner = new PeerTubeRunnerProcess()
22 await peertubeRunner.runServer()
23 })
24
25 it('Should not have PeerTube instance listed', async function () {
26 const data = await peertubeRunner.listRegisteredPeerTubeInstances()
27
28 expect(data).to.not.contain(server.url)
29 })
30
31 it('Should register a new PeerTube instance', async function () {
32 const registrationToken = await server.runnerRegistrationTokens.getFirstRegistrationToken()
33
34 await peertubeRunner.registerPeerTubeInstance({
35 server,
36 registrationToken,
37 runnerName: 'my super runner',
38 runnerDescription: 'super description'
39 })
40 })
41
42 it('Should list this new PeerTube instance', async function () {
43 const data = await peertubeRunner.listRegisteredPeerTubeInstances()
44
45 expect(data).to.contain(server.url)
46 expect(data).to.contain('my super runner')
47 expect(data).to.contain('super description')
48 })
49
50 it('Should still have the configuration after a restart', async function () {
51 peertubeRunner.kill()
52
53 await peertubeRunner.runServer()
54 })
55
56 it('Should unregister the PeerTube instance', async function () {
57 await peertubeRunner.unregisterPeerTubeInstance({ server })
58 })
59
60 it('Should not have PeerTube instance listed', async function () {
61 const data = await peertubeRunner.listRegisteredPeerTubeInstances()
62
63 expect(data).to.not.contain(server.url)
64 })
65
66 after(async function () {
67 await cleanupTests([ server ])
68
69 peertubeRunner.kill()
70 })
71})
diff --git a/server/tests/peertube-runner/index.ts b/server/tests/peertube-runner/index.ts
new file mode 100644
index 000000000..6258d6eb2
--- /dev/null
+++ b/server/tests/peertube-runner/index.ts
@@ -0,0 +1,3 @@
1export * from './client-cli'
2export * from './live-transcoding'
3export * from './vod-transcoding'
diff --git a/server/tests/peertube-runner/live-transcoding.ts b/server/tests/peertube-runner/live-transcoding.ts
new file mode 100644
index 000000000..f58e920ba
--- /dev/null
+++ b/server/tests/peertube-runner/live-transcoding.ts
@@ -0,0 +1,178 @@
1import { expect } from 'chai'
2/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
3import { expectStartWith, PeerTubeRunnerProcess, SQLCommand, testLiveVideoResolutions } from '@server/tests/shared'
4import { areMockObjectStorageTestsDisabled, wait } from '@shared/core-utils'
5import { HttpStatusCode, VideoPrivacy } from '@shared/models'
6import {
7 cleanupTests,
8 createMultipleServers,
9 doubleFollow,
10 findExternalSavedVideo,
11 makeRawRequest,
12 ObjectStorageCommand,
13 PeerTubeServer,
14 setAccessTokensToServers,
15 setDefaultVideoChannel,
16 stopFfmpeg,
17 waitJobs,
18 waitUntilLivePublishedOnAllServers,
19 waitUntilLiveWaitingOnAllServers
20} from '@shared/server-commands'
21
22describe('Test Live transcoding in peertube-runner program', function () {
23 let servers: PeerTubeServer[] = []
24 let peertubeRunner: PeerTubeRunnerProcess
25 let sqlCommandServer1: SQLCommand
26
27 function runSuite (options: {
28 objectStorage: boolean
29 }) {
30 const { objectStorage } = options
31
32 it('Should enable transcoding without additional resolutions', async function () {
33 this.timeout(120000)
34
35 const { video } = await servers[0].live.quickCreate({ permanentLive: true, saveReplay: false, privacy: VideoPrivacy.PUBLIC })
36
37 const ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ videoId: video.uuid })
38 await waitUntilLivePublishedOnAllServers(servers, video.uuid)
39 await waitJobs(servers)
40
41 await testLiveVideoResolutions({
42 originServer: servers[0],
43 sqlCommand: sqlCommandServer1,
44 servers,
45 liveVideoId: video.uuid,
46 resolutions: [ 720, 480, 360, 240, 144 ],
47 objectStorage,
48 transcoded: true
49 })
50
51 await stopFfmpeg(ffmpegCommand)
52
53 await waitUntilLiveWaitingOnAllServers(servers, video.uuid)
54 await servers[0].videos.remove({ id: video.id })
55 })
56
57 it('Should transcode audio only RTMP stream', async function () {
58 this.timeout(120000)
59
60 const { video } = await servers[0].live.quickCreate({ permanentLive: true, saveReplay: false, privacy: VideoPrivacy.UNLISTED })
61
62 const ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ videoId: video.uuid, fixtureName: 'video_short_no_audio.mp4' })
63 await waitUntilLivePublishedOnAllServers(servers, video.uuid)
64 await waitJobs(servers)
65
66 await stopFfmpeg(ffmpegCommand)
67
68 await waitUntilLiveWaitingOnAllServers(servers, video.uuid)
69 await servers[0].videos.remove({ id: video.id })
70 })
71
72 it('Should save a replay', async function () {
73 this.timeout(120000)
74
75 const { video } = await servers[0].live.quickCreate({ permanentLive: true, saveReplay: true })
76
77 const ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ videoId: video.uuid })
78 await waitUntilLivePublishedOnAllServers(servers, video.uuid)
79
80 await testLiveVideoResolutions({
81 originServer: servers[0],
82 sqlCommand: sqlCommandServer1,
83 servers,
84 liveVideoId: video.uuid,
85 resolutions: [ 720, 480, 360, 240, 144 ],
86 objectStorage,
87 transcoded: true
88 })
89
90 await stopFfmpeg(ffmpegCommand)
91
92 await waitUntilLiveWaitingOnAllServers(servers, video.uuid)
93 await waitJobs(servers)
94
95 const session = await servers[0].live.findLatestSession({ videoId: video.uuid })
96 expect(session.endingProcessed).to.be.true
97 expect(session.endDate).to.exist
98 expect(session.saveReplay).to.be.true
99
100 const videoLiveDetails = await servers[0].videos.get({ id: video.uuid })
101 const replay = await findExternalSavedVideo(servers[0], videoLiveDetails)
102
103 for (const server of servers) {
104 const video = await server.videos.get({ id: replay.uuid })
105
106 expect(video.files).to.have.lengthOf(0)
107 expect(video.streamingPlaylists).to.have.lengthOf(1)
108
109 const files = video.streamingPlaylists[0].files
110 expect(files).to.have.lengthOf(5)
111
112 for (const file of files) {
113 if (objectStorage) {
114 expectStartWith(file.fileUrl, ObjectStorageCommand.getMockPlaylistBaseUrl())
115 }
116
117 await makeRawRequest({ url: file.fileUrl, expectedStatus: HttpStatusCode.OK_200 })
118 }
119 }
120 })
121 }
122
123 before(async function () {
124 this.timeout(120_000)
125
126 servers = await createMultipleServers(2)
127
128 await setAccessTokensToServers(servers)
129 await setDefaultVideoChannel(servers)
130
131 await doubleFollow(servers[0], servers[1])
132
133 sqlCommandServer1 = new SQLCommand(servers[0])
134
135 await servers[0].config.enableRemoteTranscoding()
136 await servers[0].config.enableTranscoding(true, true, true)
137 await servers[0].config.enableLive({ allowReplay: true, resolutions: 'max', transcoding: true })
138
139 const registrationToken = await servers[0].runnerRegistrationTokens.getFirstRegistrationToken()
140
141 peertubeRunner = new PeerTubeRunnerProcess()
142 await peertubeRunner.runServer({ hideLogs: false })
143 await peertubeRunner.registerPeerTubeInstance({ server: servers[0], registrationToken, runnerName: 'runner' })
144 })
145
146 describe('With lives on local filesystem storage', function () {
147
148 before(async function () {
149 await servers[0].config.enableTranscoding(true, false, true)
150 })
151
152 runSuite({ objectStorage: false })
153 })
154
155 describe('With lives on object storage', function () {
156 if (areMockObjectStorageTestsDisabled()) return
157
158 before(async function () {
159 await ObjectStorageCommand.prepareDefaultMockBuckets()
160
161 await servers[0].kill()
162
163 await servers[0].run(ObjectStorageCommand.getDefaultMockConfig())
164
165 // Wait for peertube runner socket reconnection
166 await wait(1500)
167 })
168
169 runSuite({ objectStorage: true })
170 })
171
172 after(async function () {
173 await peertubeRunner.unregisterPeerTubeInstance({ server: servers[0] })
174 peertubeRunner.kill()
175
176 await cleanupTests(servers)
177 })
178})
diff --git a/server/tests/peertube-runner/vod-transcoding.ts b/server/tests/peertube-runner/vod-transcoding.ts
new file mode 100644
index 000000000..bdf798379
--- /dev/null
+++ b/server/tests/peertube-runner/vod-transcoding.ts
@@ -0,0 +1,330 @@
1/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
2import { expect } from 'chai'
3import { completeCheckHlsPlaylist, completeWebVideoFilesCheck, PeerTubeRunnerProcess } from '@server/tests/shared'
4import { areMockObjectStorageTestsDisabled, getAllFiles, wait } from '@shared/core-utils'
5import { VideoPrivacy } from '@shared/models'
6import {
7 cleanupTests,
8 createMultipleServers,
9 doubleFollow,
10 ObjectStorageCommand,
11 PeerTubeServer,
12 setAccessTokensToServers,
13 setDefaultVideoChannel,
14 waitJobs
15} from '@shared/server-commands'
16
17describe('Test VOD transcoding in peertube-runner program', function () {
18 let servers: PeerTubeServer[] = []
19 let peertubeRunner: PeerTubeRunnerProcess
20
21 function runSuite (options: {
22 webtorrentEnabled: boolean
23 hlsEnabled: boolean
24 objectStorage: boolean
25 }) {
26 const { webtorrentEnabled, hlsEnabled, objectStorage } = options
27
28 const objectStorageBaseUrlWebTorrent = objectStorage
29 ? ObjectStorageCommand.getMockWebTorrentBaseUrl()
30 : undefined
31
32 const objectStorageBaseUrlHLS = objectStorage
33 ? ObjectStorageCommand.getMockPlaylistBaseUrl()
34 : undefined
35
36 it('Should upload a classic video mp4 and transcode it', async function () {
37 this.timeout(120000)
38
39 const { uuid } = await servers[0].videos.quickUpload({ name: 'mp4', fixture: 'video_short.mp4' })
40
41 await waitJobs(servers, { runnerJobs: true })
42
43 for (const server of servers) {
44 if (webtorrentEnabled) {
45 await completeWebVideoFilesCheck({
46 server,
47 originServer: servers[0],
48 fixture: 'video_short.mp4',
49 videoUUID: uuid,
50 objectStorageBaseUrl: objectStorageBaseUrlWebTorrent,
51 files: [
52 { resolution: 0 },
53 { resolution: 144 },
54 { resolution: 240 },
55 { resolution: 360 },
56 { resolution: 480 },
57 { resolution: 720 }
58 ]
59 })
60 }
61
62 if (hlsEnabled) {
63 await completeCheckHlsPlaylist({
64 hlsOnly: !webtorrentEnabled,
65 servers,
66 videoUUID: uuid,
67 objectStorageBaseUrl: objectStorageBaseUrlHLS,
68 resolutions: [ 720, 480, 360, 240, 144, 0 ]
69 })
70 }
71 }
72 })
73
74 it('Should upload a webm video and transcode it', async function () {
75 this.timeout(120000)
76
77 const { uuid } = await servers[0].videos.quickUpload({ name: 'mp4', fixture: 'video_short.webm' })
78
79 await waitJobs(servers, { runnerJobs: true })
80
81 for (const server of servers) {
82 if (webtorrentEnabled) {
83 await completeWebVideoFilesCheck({
84 server,
85 originServer: servers[0],
86 fixture: 'video_short.webm',
87 videoUUID: uuid,
88 objectStorageBaseUrl: objectStorageBaseUrlWebTorrent,
89 files: [
90 { resolution: 0 },
91 { resolution: 144 },
92 { resolution: 240 },
93 { resolution: 360 },
94 { resolution: 480 },
95 { resolution: 720 }
96 ]
97 })
98 }
99
100 if (hlsEnabled) {
101 await completeCheckHlsPlaylist({
102 hlsOnly: !webtorrentEnabled,
103 servers,
104 videoUUID: uuid,
105 objectStorageBaseUrl: objectStorageBaseUrlHLS,
106 resolutions: [ 720, 480, 360, 240, 144, 0 ]
107 })
108 }
109 }
110 })
111
112 it('Should upload an audio only video and transcode it', async function () {
113 this.timeout(120000)
114
115 const attributes = { name: 'audio_without_preview', fixture: 'sample.ogg' }
116 const { uuid } = await servers[0].videos.upload({ attributes, mode: 'resumable' })
117
118 await waitJobs(servers, { runnerJobs: true })
119
120 for (const server of servers) {
121 if (webtorrentEnabled) {
122 await completeWebVideoFilesCheck({
123 server,
124 originServer: servers[0],
125 fixture: 'sample.ogg',
126 videoUUID: uuid,
127 objectStorageBaseUrl: objectStorageBaseUrlWebTorrent,
128 files: [
129 { resolution: 0 },
130 { resolution: 144 },
131 { resolution: 240 },
132 { resolution: 360 },
133 { resolution: 480 }
134 ]
135 })
136 }
137
138 if (hlsEnabled) {
139 await completeCheckHlsPlaylist({
140 hlsOnly: !webtorrentEnabled,
141 servers,
142 videoUUID: uuid,
143 objectStorageBaseUrl: objectStorageBaseUrlHLS,
144 resolutions: [ 480, 360, 240, 144, 0 ]
145 })
146 }
147 }
148 })
149
150 it('Should upload a private video and transcode it', async function () {
151 this.timeout(120000)
152
153 const { uuid } = await servers[0].videos.quickUpload({ name: 'mp4', fixture: 'video_short.mp4', privacy: VideoPrivacy.PRIVATE })
154
155 await waitJobs(servers, { runnerJobs: true })
156
157 if (webtorrentEnabled) {
158 await completeWebVideoFilesCheck({
159 server: servers[0],
160 originServer: servers[0],
161 fixture: 'video_short.mp4',
162 videoUUID: uuid,
163 objectStorageBaseUrl: objectStorageBaseUrlWebTorrent,
164 files: [
165 { resolution: 0 },
166 { resolution: 144 },
167 { resolution: 240 },
168 { resolution: 360 },
169 { resolution: 480 },
170 { resolution: 720 }
171 ]
172 })
173 }
174
175 if (hlsEnabled) {
176 await completeCheckHlsPlaylist({
177 hlsOnly: !webtorrentEnabled,
178 servers: [ servers[0] ],
179 videoUUID: uuid,
180 objectStorageBaseUrl: objectStorageBaseUrlHLS,
181 resolutions: [ 720, 480, 360, 240, 144, 0 ]
182 })
183 }
184 })
185
186 it('Should transcode videos on manual run', async function () {
187 this.timeout(120000)
188
189 await servers[0].config.disableTranscoding()
190
191 const { uuid } = await servers[0].videos.quickUpload({ name: 'manual transcoding', fixture: 'video_short.mp4' })
192 await waitJobs(servers, { runnerJobs: true })
193
194 {
195 const video = await servers[0].videos.get({ id: uuid })
196 expect(getAllFiles(video)).to.have.lengthOf(1)
197 }
198
199 await servers[0].config.enableTranscoding(true, true, true)
200
201 await servers[0].videos.runTranscoding({ transcodingType: 'webtorrent', videoId: uuid })
202 await waitJobs(servers, { runnerJobs: true })
203
204 await completeWebVideoFilesCheck({
205 server: servers[0],
206 originServer: servers[0],
207 fixture: 'video_short.mp4',
208 videoUUID: uuid,
209 objectStorageBaseUrl: objectStorageBaseUrlWebTorrent,
210 files: [
211 { resolution: 0 },
212 { resolution: 144 },
213 { resolution: 240 },
214 { resolution: 360 },
215 { resolution: 480 },
216 { resolution: 720 }
217 ]
218 })
219
220 await servers[0].videos.runTranscoding({ transcodingType: 'hls', videoId: uuid })
221 await waitJobs(servers, { runnerJobs: true })
222
223 await completeCheckHlsPlaylist({
224 hlsOnly: false,
225 servers: [ servers[0] ],
226 videoUUID: uuid,
227 objectStorageBaseUrl: objectStorageBaseUrlHLS,
228 resolutions: [ 720, 480, 360, 240, 144, 0 ]
229 })
230 })
231 }
232
233 before(async function () {
234 this.timeout(120_000)
235
236 servers = await createMultipleServers(2)
237
238 await setAccessTokensToServers(servers)
239 await setDefaultVideoChannel(servers)
240
241 await doubleFollow(servers[0], servers[1])
242
243 await servers[0].config.enableRemoteTranscoding()
244
245 const registrationToken = await servers[0].runnerRegistrationTokens.getFirstRegistrationToken()
246
247 peertubeRunner = new PeerTubeRunnerProcess()
248 await peertubeRunner.runServer()
249 await peertubeRunner.registerPeerTubeInstance({ server: servers[0], registrationToken, runnerName: 'runner' })
250 })
251
252 describe('With videos on local filesystem storage', function () {
253
254 describe('Web video only enabled', function () {
255
256 before(async function () {
257 await servers[0].config.enableTranscoding(true, false, true)
258 })
259
260 runSuite({ webtorrentEnabled: true, hlsEnabled: false, objectStorage: false })
261 })
262
263 describe('HLS videos only enabled', function () {
264
265 before(async function () {
266 await servers[0].config.enableTranscoding(false, true, true)
267 })
268
269 runSuite({ webtorrentEnabled: false, hlsEnabled: true, objectStorage: false })
270 })
271
272 describe('Web video & HLS enabled', function () {
273
274 before(async function () {
275 await servers[0].config.enableTranscoding(true, true, true)
276 })
277
278 runSuite({ webtorrentEnabled: true, hlsEnabled: true, objectStorage: false })
279 })
280 })
281
282 describe('With videos on object storage', function () {
283 if (areMockObjectStorageTestsDisabled()) return
284
285 before(async function () {
286 await ObjectStorageCommand.prepareDefaultMockBuckets()
287
288 await servers[0].kill()
289
290 await servers[0].run(ObjectStorageCommand.getDefaultMockConfig())
291
292 // Wait for peertube runner socket reconnection
293 await wait(1500)
294 })
295
296 describe('Web video only enabled', function () {
297
298 before(async function () {
299 await servers[0].config.enableTranscoding(true, false, true)
300 })
301
302 runSuite({ webtorrentEnabled: true, hlsEnabled: false, objectStorage: true })
303 })
304
305 describe('HLS videos only enabled', function () {
306
307 before(async function () {
308 await servers[0].config.enableTranscoding(false, true, true)
309 })
310
311 runSuite({ webtorrentEnabled: false, hlsEnabled: true, objectStorage: true })
312 })
313
314 describe('Web video & HLS enabled', function () {
315
316 before(async function () {
317 await servers[0].config.enableTranscoding(true, true, true)
318 })
319
320 runSuite({ webtorrentEnabled: true, hlsEnabled: true, objectStorage: true })
321 })
322 })
323
324 after(async function () {
325 await peertubeRunner.unregisterPeerTubeInstance({ server: servers[0] })
326 peertubeRunner.kill()
327
328 await cleanupTests(servers)
329 })
330})