]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame - server/tests/api/object-storage/live.ts
Fix live quota tests
[github/Chocobozzz/PeerTube.git] / server / tests / api / object-storage / live.ts
CommitLineData
0305db28
JB
1/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
2
86347717 3import { expect } from 'chai'
d102de1b 4import { expectStartWith, MockObjectStorageProxy, SQLCommand, testLiveVideoResolutions } from '@server/tests/shared'
9ab330b9 5import { areMockObjectStorageTestsDisabled } from '@shared/core-utils'
cfd57d2c 6import { HttpStatusCode, LiveVideoCreate, VideoPrivacy } from '@shared/models'
0305db28 7import {
644391be 8 cleanupTests,
0305db28
JB
9 createMultipleServers,
10 doubleFollow,
4ec52d04 11 findExternalSavedVideo,
0305db28
JB
12 makeRawRequest,
13 ObjectStorageCommand,
14 PeerTubeServer,
15 setAccessTokensToServers,
16 setDefaultVideoChannel,
17 stopFfmpeg,
18 waitJobs,
19 waitUntilLivePublishedOnAllServers,
4ec52d04
C
20 waitUntilLiveReplacedByReplayOnAllServers,
21 waitUntilLiveWaitingOnAllServers
bf54587a 22} from '@shared/server-commands'
0305db28 23
4ec52d04 24async function createLive (server: PeerTubeServer, permanent: boolean) {
0305db28
JB
25 const attributes: LiveVideoCreate = {
26 channelId: server.store.channel.id,
27 privacy: VideoPrivacy.PUBLIC,
28 name: 'my super live',
4ec52d04 29 saveReplay: true,
05a60d85 30 replaySettings: { privacy: VideoPrivacy.PUBLIC },
4ec52d04 31 permanentLive: permanent
0305db28
JB
32 }
33
34 const { uuid } = await server.live.create({ fields: attributes })
35
36 return uuid
37}
38
cfd57d2c
C
39async function checkFilesExist (servers: PeerTubeServer[], videoUUID: string, numberOfFiles: number) {
40 for (const server of servers) {
41 const video = await server.videos.get({ id: videoUUID })
0305db28 42
cfd57d2c
C
43 expect(video.files).to.have.lengthOf(0)
44 expect(video.streamingPlaylists).to.have.lengthOf(1)
0305db28 45
cfd57d2c
C
46 const files = video.streamingPlaylists[0].files
47 expect(files).to.have.lengthOf(numberOfFiles)
4ec52d04 48
cfd57d2c 49 for (const file of files) {
9ab330b9 50 expectStartWith(file.fileUrl, ObjectStorageCommand.getMockPlaylistBaseUrl())
4ec52d04 51
3545e72c 52 await makeRawRequest({ url: file.fileUrl, expectedStatus: HttpStatusCode.OK_200 })
cfd57d2c
C
53 }
54 }
4ec52d04
C
55}
56
cfd57d2c
C
57async function checkFilesCleanup (server: PeerTubeServer, videoUUID: string, resolutions: number[]) {
58 const resolutionFiles = resolutions.map((_value, i) => `${i}.m3u8`)
4ec52d04 59
cfd57d2c
C
60 for (const playlistName of [ 'master.m3u8' ].concat(resolutionFiles)) {
61 await server.live.getPlaylistFile({
62 videoUUID,
63 playlistName,
64 expectedStatus: HttpStatusCode.NOT_FOUND_404,
65 objectStorage: true
66 })
4ec52d04
C
67 }
68
cfd57d2c
C
69 await server.live.getSegmentFile({
70 videoUUID,
71 playlistNumber: 0,
72 segment: 0,
73 objectStorage: true,
74 expectedStatus: HttpStatusCode.NOT_FOUND_404
75 })
4ec52d04
C
76}
77
0305db28 78describe('Object storage for lives', function () {
9ab330b9 79 if (areMockObjectStorageTestsDisabled()) return
0305db28 80
0305db28 81 let servers: PeerTubeServer[]
d102de1b 82 let sqlCommandServer1: SQLCommand
0305db28
JB
83
84 before(async function () {
85 this.timeout(120000)
86
9ab330b9 87 await ObjectStorageCommand.prepareDefaultMockBuckets()
0305db28 88
9ab330b9 89 servers = await createMultipleServers(2, ObjectStorageCommand.getDefaultMockConfig())
0305db28
JB
90
91 await setAccessTokensToServers(servers)
92 await setDefaultVideoChannel(servers)
93 await doubleFollow(servers[0], servers[1])
94
95 await servers[0].config.enableTranscoding()
d102de1b
C
96
97 sqlCommandServer1 = new SQLCommand(servers[0])
0305db28
JB
98 })
99
8059e050 100 describe('Without live transcoding', function () {
4ec52d04 101 let videoUUID: string
0305db28
JB
102
103 before(async function () {
104 await servers[0].config.enableLive({ transcoding: false })
105
4ec52d04 106 videoUUID = await createLive(servers[0], false)
0305db28
JB
107 })
108
cfd57d2c
C
109 it('Should create a live and publish it on object storage', async function () {
110 this.timeout(220000)
111
112 const ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ videoId: videoUUID })
113 await waitUntilLivePublishedOnAllServers(servers, videoUUID)
114
d102de1b 115 await testLiveVideoResolutions({
cfd57d2c 116 originServer: servers[0],
d102de1b 117 sqlCommand: sqlCommandServer1,
cfd57d2c
C
118 servers,
119 liveVideoId: videoUUID,
120 resolutions: [ 720 ],
121 transcoded: false,
122 objectStorage: true
123 })
124
125 await stopFfmpeg(ffmpegCommand)
126 })
127
128 it('Should have saved the replay on object storage', async function () {
0305db28
JB
129 this.timeout(220000)
130
cfd57d2c
C
131 await waitUntilLiveReplacedByReplayOnAllServers(servers, videoUUID)
132 await waitJobs(servers)
0305db28 133
cfd57d2c
C
134 await checkFilesExist(servers, videoUUID, 1)
135 })
0305db28 136
cfd57d2c
C
137 it('Should have cleaned up live files from object storage', async function () {
138 await checkFilesCleanup(servers[0], videoUUID, [ 720 ])
0305db28
JB
139 })
140 })
141
8059e050 142 describe('With live transcoding', function () {
cfd57d2c 143 const resolutions = [ 720, 480, 360, 240, 144 ]
0305db28
JB
144
145 before(async function () {
146 await servers[0].config.enableLive({ transcoding: true })
0305db28
JB
147 })
148
cfd57d2c
C
149 describe('Normal replay', function () {
150 let videoUUIDNonPermanent: string
151
152 before(async function () {
153 videoUUIDNonPermanent = await createLive(servers[0], false)
154 })
155
156 it('Should create a live and publish it on object storage', async function () {
157 this.timeout(240000)
158
159 const ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ videoId: videoUUIDNonPermanent })
160 await waitUntilLivePublishedOnAllServers(servers, videoUUIDNonPermanent)
161
d102de1b 162 await testLiveVideoResolutions({
cfd57d2c 163 originServer: servers[0],
d102de1b 164 sqlCommand: sqlCommandServer1,
cfd57d2c
C
165 servers,
166 liveVideoId: videoUUIDNonPermanent,
167 resolutions,
168 transcoded: true,
169 objectStorage: true
170 })
171
172 await stopFfmpeg(ffmpegCommand)
173 })
0305db28 174
cfd57d2c
C
175 it('Should have saved the replay on object storage', async function () {
176 this.timeout(220000)
0305db28 177
cfd57d2c
C
178 await waitUntilLiveReplacedByReplayOnAllServers(servers, videoUUIDNonPermanent)
179 await waitJobs(servers)
0305db28 180
cfd57d2c
C
181 await checkFilesExist(servers, videoUUIDNonPermanent, 5)
182 })
183
184 it('Should have cleaned up live files from object storage', async function () {
185 await checkFilesCleanup(servers[0], videoUUIDNonPermanent, resolutions)
186 })
4ec52d04 187 })
0305db28 188
cfd57d2c
C
189 describe('Permanent replay', function () {
190 let videoUUIDPermanent: string
191
192 before(async function () {
193 videoUUIDPermanent = await createLive(servers[0], true)
194 })
195
196 it('Should create a live and publish it on object storage', async function () {
197 this.timeout(240000)
198
199 const ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ videoId: videoUUIDPermanent })
200 await waitUntilLivePublishedOnAllServers(servers, videoUUIDPermanent)
201
d102de1b 202 await testLiveVideoResolutions({
cfd57d2c 203 originServer: servers[0],
d102de1b 204 sqlCommand: sqlCommandServer1,
cfd57d2c
C
205 servers,
206 liveVideoId: videoUUIDPermanent,
207 resolutions,
208 transcoded: true,
209 objectStorage: true
210 })
211
212 await stopFfmpeg(ffmpegCommand)
213 })
214
215 it('Should have saved the replay on object storage', async function () {
216 this.timeout(220000)
4ec52d04 217
cfd57d2c
C
218 await waitUntilLiveWaitingOnAllServers(servers, videoUUIDPermanent)
219 await waitJobs(servers)
0305db28 220
cfd57d2c
C
221 const videoLiveDetails = await servers[0].videos.get({ id: videoUUIDPermanent })
222 const replay = await findExternalSavedVideo(servers[0], videoLiveDetails)
0305db28 223
cfd57d2c
C
224 await checkFilesExist(servers, replay.uuid, 5)
225 })
0305db28 226
cfd57d2c
C
227 it('Should have cleaned up live files from object storage', async function () {
228 await checkFilesCleanup(servers[0], videoUUIDPermanent, resolutions)
229 })
0305db28
JB
230 })
231 })
232
8059e050
C
233 describe('With object storage base url', function () {
234 const mockObjectStorageProxy = new MockObjectStorageProxy()
235 let baseMockUrl: string
236
237 before(async function () {
238 this.timeout(120000)
239
240 const port = await mockObjectStorageProxy.initialize()
241 baseMockUrl = `http://127.0.0.1:${port}/streaming-playlists`
242
243 await ObjectStorageCommand.createMockBucket('streaming-playlists')
244
245 const config = {
246 object_storage: {
247 enabled: true,
248 endpoint: 'http://' + ObjectStorageCommand.getMockEndpointHost(),
249 region: ObjectStorageCommand.getMockRegion(),
250
251 credentials: ObjectStorageCommand.getMockCredentialsConfig(),
252
253 streaming_playlists: {
254 bucket_name: 'streaming-playlists',
255 prefix: '',
256 base_url: baseMockUrl
257 }
258 }
259 }
260
261 await servers[0].kill()
262 await servers[0].run(config)
263
264 await servers[0].config.enableLive({ transcoding: true, resolutions: 'min' })
265 })
266
267 it('Should publish a live and replace the base url', async function () {
268 this.timeout(240000)
269
270 const videoUUIDPermanent = await createLive(servers[0], true)
271
272 const ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ videoId: videoUUIDPermanent })
273 await waitUntilLivePublishedOnAllServers(servers, videoUUIDPermanent)
274
d102de1b 275 await testLiveVideoResolutions({
8059e050 276 originServer: servers[0],
d102de1b 277 sqlCommand: sqlCommandServer1,
8059e050
C
278 servers,
279 liveVideoId: videoUUIDPermanent,
280 resolutions: [ 720 ],
281 transcoded: true,
282 objectStorage: true,
283 objectStorageBaseUrl: baseMockUrl
284 })
285
286 await stopFfmpeg(ffmpegCommand)
287 })
288 })
289
0305db28 290 after(async function () {
d102de1b
C
291 await sqlCommandServer1.cleanup()
292
644391be 293 await cleanupTests(servers)
0305db28
JB
294 })
295})