aboutsummaryrefslogtreecommitdiffhomepage
path: root/packages/tests/src/api/videos/video-source.ts
diff options
context:
space:
mode:
Diffstat (limited to 'packages/tests/src/api/videos/video-source.ts')
-rw-r--r--packages/tests/src/api/videos/video-source.ts448
1 files changed, 448 insertions, 0 deletions
diff --git a/packages/tests/src/api/videos/video-source.ts b/packages/tests/src/api/videos/video-source.ts
new file mode 100644
index 000000000..efe8c3802
--- /dev/null
+++ b/packages/tests/src/api/videos/video-source.ts
@@ -0,0 +1,448 @@
1/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
2import { expect } from 'chai'
3import { getAllFiles } from '@peertube/peertube-core-utils'
4import { HttpStatusCode } from '@peertube/peertube-models'
5import { expectStartWith } from '@tests/shared/checks.js'
6import { areMockObjectStorageTestsDisabled } from '@peertube/peertube-node-utils'
7import {
8 cleanupTests,
9 createMultipleServers,
10 doubleFollow,
11 makeGetRequest,
12 makeRawRequest,
13 ObjectStorageCommand,
14 PeerTubeServer,
15 setAccessTokensToServers,
16 setDefaultAccountAvatar,
17 setDefaultVideoChannel,
18 waitJobs
19} from '@peertube/peertube-server-commands'
20
21describe('Test a video file replacement', function () {
22 let servers: PeerTubeServer[] = []
23
24 let replaceDate: Date
25 let userToken: string
26 let uuid: string
27
28 before(async function () {
29 this.timeout(50000)
30
31 servers = await createMultipleServers(2)
32
33 // Get the access tokens
34 await setAccessTokensToServers(servers)
35 await setDefaultVideoChannel(servers)
36 await setDefaultAccountAvatar(servers)
37
38 await servers[0].config.enableFileUpdate()
39
40 userToken = await servers[0].users.generateUserAndToken('user1')
41
42 // Server 1 and server 2 follow each other
43 await doubleFollow(servers[0], servers[1])
44 })
45
46 describe('Getting latest video source', () => {
47 const fixture = 'video_short.webm'
48 const uuids: string[] = []
49
50 it('Should get the source filename with legacy upload', async function () {
51 this.timeout(30000)
52
53 const { uuid } = await servers[0].videos.upload({ attributes: { name: 'my video', fixture }, mode: 'legacy' })
54 uuids.push(uuid)
55
56 const source = await servers[0].videos.getSource({ id: uuid })
57 expect(source.filename).to.equal(fixture)
58 })
59
60 it('Should get the source filename with resumable upload', async function () {
61 this.timeout(30000)
62
63 const { uuid } = await servers[0].videos.upload({ attributes: { name: 'my video', fixture }, mode: 'resumable' })
64 uuids.push(uuid)
65
66 const source = await servers[0].videos.getSource({ id: uuid })
67 expect(source.filename).to.equal(fixture)
68 })
69
70 after(async function () {
71 this.timeout(60000)
72
73 for (const uuid of uuids) {
74 await servers[0].videos.remove({ id: uuid })
75 }
76
77 await waitJobs(servers)
78 })
79 })
80
81 describe('Updating video source', function () {
82
83 describe('Filesystem', function () {
84
85 it('Should replace a video file with transcoding disabled', async function () {
86 this.timeout(120000)
87
88 await servers[0].config.disableTranscoding()
89
90 const { uuid } = await servers[0].videos.quickUpload({ name: 'fs without transcoding', fixture: 'video_short_720p.mp4' })
91 await waitJobs(servers)
92
93 for (const server of servers) {
94 const video = await server.videos.get({ id: uuid })
95
96 const files = getAllFiles(video)
97 expect(files).to.have.lengthOf(1)
98 expect(files[0].resolution.id).to.equal(720)
99 }
100
101 await servers[0].videos.replaceSourceFile({ videoId: uuid, fixture: 'video_short_360p.mp4' })
102 await waitJobs(servers)
103
104 for (const server of servers) {
105 const video = await server.videos.get({ id: uuid })
106
107 const files = getAllFiles(video)
108 expect(files).to.have.lengthOf(1)
109 expect(files[0].resolution.id).to.equal(360)
110 }
111 })
112
113 it('Should replace a video file with transcoding enabled', async function () {
114 this.timeout(120000)
115
116 const previousPaths: string[] = []
117
118 await servers[0].config.enableTranscoding({ hls: true, webVideo: true, with0p: true })
119
120 const { uuid: videoUUID } = await servers[0].videos.quickUpload({ name: 'fs with transcoding', fixture: 'video_short_720p.mp4' })
121 uuid = videoUUID
122
123 await waitJobs(servers)
124
125 for (const server of servers) {
126 const video = await server.videos.get({ id: uuid })
127 expect(video.inputFileUpdatedAt).to.be.null
128
129 const files = getAllFiles(video)
130 expect(files).to.have.lengthOf(6 * 2)
131
132 // Grab old paths to ensure we'll regenerate
133
134 previousPaths.push(video.previewPath)
135 previousPaths.push(video.thumbnailPath)
136
137 for (const file of files) {
138 previousPaths.push(file.fileUrl)
139 previousPaths.push(file.torrentUrl)
140 previousPaths.push(file.metadataUrl)
141
142 const metadata = await server.videos.getFileMetadata({ url: file.metadataUrl })
143 previousPaths.push(JSON.stringify(metadata))
144 }
145
146 const { storyboards } = await server.storyboard.list({ id: uuid })
147 for (const s of storyboards) {
148 previousPaths.push(s.storyboardPath)
149 }
150 }
151
152 replaceDate = new Date()
153
154 await servers[0].videos.replaceSourceFile({ videoId: uuid, fixture: 'video_short_360p.mp4' })
155 await waitJobs(servers)
156
157 for (const server of servers) {
158 const video = await server.videos.get({ id: uuid })
159
160 expect(video.inputFileUpdatedAt).to.not.be.null
161 expect(new Date(video.inputFileUpdatedAt)).to.be.above(replaceDate)
162
163 const files = getAllFiles(video)
164 expect(files).to.have.lengthOf(4 * 2)
165
166 expect(previousPaths).to.not.include(video.previewPath)
167 expect(previousPaths).to.not.include(video.thumbnailPath)
168
169 await makeGetRequest({ url: server.url, path: video.previewPath, expectedStatus: HttpStatusCode.OK_200 })
170 await makeGetRequest({ url: server.url, path: video.thumbnailPath, expectedStatus: HttpStatusCode.OK_200 })
171
172 for (const file of files) {
173 expect(previousPaths).to.not.include(file.fileUrl)
174 expect(previousPaths).to.not.include(file.torrentUrl)
175 expect(previousPaths).to.not.include(file.metadataUrl)
176
177 await makeRawRequest({ url: file.fileUrl, expectedStatus: HttpStatusCode.OK_200 })
178 await makeRawRequest({ url: file.torrentUrl, expectedStatus: HttpStatusCode.OK_200 })
179
180 const metadata = await server.videos.getFileMetadata({ url: file.metadataUrl })
181 expect(previousPaths).to.not.include(JSON.stringify(metadata))
182 }
183
184 const { storyboards } = await server.storyboard.list({ id: uuid })
185 for (const s of storyboards) {
186 expect(previousPaths).to.not.include(s.storyboardPath)
187
188 await makeGetRequest({ url: server.url, path: s.storyboardPath, expectedStatus: HttpStatusCode.OK_200 })
189 }
190 }
191
192 await servers[0].config.enableMinimumTranscoding()
193 })
194
195 it('Should have cleaned up old files', async function () {
196 {
197 const count = await servers[0].servers.countFiles('storyboards')
198 expect(count).to.equal(2)
199 }
200
201 {
202 const count = await servers[0].servers.countFiles('web-videos')
203 expect(count).to.equal(5 + 1) // +1 for private directory
204 }
205
206 {
207 const count = await servers[0].servers.countFiles('streaming-playlists/hls')
208 expect(count).to.equal(1 + 1) // +1 for private directory
209 }
210
211 {
212 const count = await servers[0].servers.countFiles('torrents')
213 expect(count).to.equal(9)
214 }
215 })
216
217 it('Should have the correct source input', async function () {
218 const source = await servers[0].videos.getSource({ id: uuid })
219
220 expect(source.filename).to.equal('video_short_360p.mp4')
221 expect(new Date(source.createdAt)).to.be.above(replaceDate)
222 })
223
224 it('Should not have regenerated miniatures that were previously uploaded', async function () {
225 this.timeout(120000)
226
227 const { uuid } = await servers[0].videos.upload({
228 attributes: {
229 name: 'custom miniatures',
230 thumbnailfile: 'custom-thumbnail.jpg',
231 previewfile: 'custom-preview.jpg'
232 }
233 })
234
235 await waitJobs(servers)
236
237 const previousPaths: string[] = []
238
239 for (const server of servers) {
240 const video = await server.videos.get({ id: uuid })
241
242 previousPaths.push(video.previewPath)
243 previousPaths.push(video.thumbnailPath)
244
245 await makeGetRequest({ url: server.url, path: video.previewPath, expectedStatus: HttpStatusCode.OK_200 })
246 await makeGetRequest({ url: server.url, path: video.thumbnailPath, expectedStatus: HttpStatusCode.OK_200 })
247 }
248
249 await servers[0].videos.replaceSourceFile({ videoId: uuid, fixture: 'video_short_360p.mp4' })
250 await waitJobs(servers)
251
252 for (const server of servers) {
253 const video = await server.videos.get({ id: uuid })
254
255 expect(previousPaths).to.include(video.previewPath)
256 expect(previousPaths).to.include(video.thumbnailPath)
257
258 await makeGetRequest({ url: server.url, path: video.previewPath, expectedStatus: HttpStatusCode.OK_200 })
259 await makeGetRequest({ url: server.url, path: video.thumbnailPath, expectedStatus: HttpStatusCode.OK_200 })
260 }
261 })
262 })
263
264 describe('Autoblacklist', function () {
265
266 function updateAutoBlacklist (enabled: boolean) {
267 return servers[0].config.updateExistingSubConfig({
268 newConfig: {
269 autoBlacklist: {
270 videos: {
271 ofUsers: {
272 enabled
273 }
274 }
275 }
276 }
277 })
278 }
279
280 async function expectBlacklist (uuid: string, value: boolean) {
281 const video = await servers[0].videos.getWithToken({ id: uuid })
282
283 expect(video.blacklisted).to.equal(value)
284 }
285
286 before(async function () {
287 await updateAutoBlacklist(true)
288 })
289
290 it('Should auto blacklist an unblacklisted video after file replacement', async function () {
291 this.timeout(120000)
292
293 const { uuid } = await servers[0].videos.quickUpload({ token: userToken, name: 'user video' })
294 await waitJobs(servers)
295 await expectBlacklist(uuid, true)
296
297 await servers[0].blacklist.remove({ videoId: uuid })
298 await expectBlacklist(uuid, false)
299
300 await servers[0].videos.replaceSourceFile({ videoId: uuid, token: userToken, fixture: 'video_short_360p.mp4' })
301 await waitJobs(servers)
302
303 await expectBlacklist(uuid, true)
304 })
305
306 it('Should auto blacklist an already blacklisted video after file replacement', async function () {
307 this.timeout(120000)
308
309 const { uuid } = await servers[0].videos.quickUpload({ token: userToken, name: 'user video' })
310 await waitJobs(servers)
311 await expectBlacklist(uuid, true)
312
313 await servers[0].videos.replaceSourceFile({ videoId: uuid, token: userToken, fixture: 'video_short_360p.mp4' })
314 await waitJobs(servers)
315
316 await expectBlacklist(uuid, true)
317 })
318
319 it('Should not auto blacklist if auto blacklist has been disabled between the upload and the replacement', async function () {
320 this.timeout(120000)
321
322 const { uuid } = await servers[0].videos.quickUpload({ token: userToken, name: 'user video' })
323 await waitJobs(servers)
324 await expectBlacklist(uuid, true)
325
326 await servers[0].blacklist.remove({ videoId: uuid })
327 await expectBlacklist(uuid, false)
328
329 await updateAutoBlacklist(false)
330
331 await servers[0].videos.replaceSourceFile({ videoId: uuid, token: userToken, fixture: 'video_short1.webm' })
332 await waitJobs(servers)
333
334 await expectBlacklist(uuid, false)
335 })
336 })
337
338 describe('With object storage enabled', function () {
339 if (areMockObjectStorageTestsDisabled()) return
340
341 const objectStorage = new ObjectStorageCommand()
342
343 before(async function () {
344 this.timeout(120000)
345
346 const configOverride = objectStorage.getDefaultMockConfig()
347 await objectStorage.prepareDefaultMockBuckets()
348
349 await servers[0].kill()
350 await servers[0].run(configOverride)
351 })
352
353 it('Should replace a video file with transcoding disabled', async function () {
354 this.timeout(120000)
355
356 await servers[0].config.disableTranscoding()
357
358 const { uuid } = await servers[0].videos.quickUpload({
359 name: 'object storage without transcoding',
360 fixture: 'video_short_720p.mp4'
361 })
362 await waitJobs(servers)
363
364 for (const server of servers) {
365 const video = await server.videos.get({ id: uuid })
366
367 const files = getAllFiles(video)
368 expect(files).to.have.lengthOf(1)
369 expect(files[0].resolution.id).to.equal(720)
370 expectStartWith(files[0].fileUrl, objectStorage.getMockWebVideosBaseUrl())
371 }
372
373 await servers[0].videos.replaceSourceFile({ videoId: uuid, fixture: 'video_short_360p.mp4' })
374 await waitJobs(servers)
375
376 for (const server of servers) {
377 const video = await server.videos.get({ id: uuid })
378
379 const files = getAllFiles(video)
380 expect(files).to.have.lengthOf(1)
381 expect(files[0].resolution.id).to.equal(360)
382 expectStartWith(files[0].fileUrl, objectStorage.getMockWebVideosBaseUrl())
383 }
384 })
385
386 it('Should replace a video file with transcoding enabled', async function () {
387 this.timeout(120000)
388
389 const previousPaths: string[] = []
390
391 await servers[0].config.enableTranscoding({ hls: true, webVideo: true, with0p: true })
392
393 const { uuid: videoUUID } = await servers[0].videos.quickUpload({
394 name: 'object storage with transcoding',
395 fixture: 'video_short_360p.mp4'
396 })
397 uuid = videoUUID
398
399 await waitJobs(servers)
400
401 for (const server of servers) {
402 const video = await server.videos.get({ id: uuid })
403
404 const files = getAllFiles(video)
405 expect(files).to.have.lengthOf(4 * 2)
406
407 for (const file of files) {
408 previousPaths.push(file.fileUrl)
409 }
410
411 for (const file of video.files) {
412 expectStartWith(file.fileUrl, objectStorage.getMockWebVideosBaseUrl())
413 }
414
415 for (const file of video.streamingPlaylists[0].files) {
416 expectStartWith(file.fileUrl, objectStorage.getMockPlaylistBaseUrl())
417 }
418 }
419
420 await servers[0].videos.replaceSourceFile({ videoId: uuid, fixture: 'video_short_240p.mp4' })
421 await waitJobs(servers)
422
423 for (const server of servers) {
424 const video = await server.videos.get({ id: uuid })
425
426 const files = getAllFiles(video)
427 expect(files).to.have.lengthOf(3 * 2)
428
429 for (const file of files) {
430 expect(previousPaths).to.not.include(file.fileUrl)
431 }
432
433 for (const file of video.files) {
434 expectStartWith(file.fileUrl, objectStorage.getMockWebVideosBaseUrl())
435 }
436
437 for (const file of video.streamingPlaylists[0].files) {
438 expectStartWith(file.fileUrl, objectStorage.getMockPlaylistBaseUrl())
439 }
440 }
441 })
442 })
443 })
444
445 after(async function () {
446 await cleanupTests(servers)
447 })
448})