aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorChocobozzz <me@florianbigard.com>2021-07-22 14:28:03 +0200
committerChocobozzz <chocobozzz@cpy.re>2021-07-26 11:29:31 +0200
commit83903cb65d531a6b6b91715387493ba8312b264d (patch)
treefd172e26a483331e74f15a062743a9d40d4016d3
parentc4fa01f7c45b66b112ebd08abce744b7c4041feb (diff)
downloadPeerTube-83903cb65d531a6b6b91715387493ba8312b264d.tar.gz
PeerTube-83903cb65d531a6b6b91715387493ba8312b264d.tar.zst
PeerTube-83903cb65d531a6b6b91715387493ba8312b264d.zip
Generate random uuid for video files
-rw-r--r--server/controllers/api/videos/upload.ts4
-rw-r--r--server/lib/hls.ts6
-rw-r--r--server/lib/job-queue/handlers/video-file-import.ts4
-rw-r--r--server/lib/job-queue/handlers/video-import.ts4
-rw-r--r--server/lib/transcoding/video-transcoding.ts12
-rw-r--r--server/lib/video-paths.ts35
-rw-r--r--server/tests/api/check-params/abuses.ts20
-rw-r--r--server/tests/api/check-params/services.ts16
-rw-r--r--server/tests/api/check-params/video-blacklist.ts42
-rw-r--r--server/tests/api/moderation/abuses.ts54
-rw-r--r--server/tests/api/redundancy/redundancy.ts145
-rw-r--r--server/tests/api/users/users-multiple-servers.ts20
-rw-r--r--server/tests/api/videos/audio-only.ts12
-rw-r--r--server/tests/api/videos/multiple-servers.ts21
-rw-r--r--server/tests/api/videos/resumable-upload.ts8
-rw-r--r--server/tests/api/videos/single-server.ts3
-rw-r--r--server/tests/api/videos/video-captions.ts5
-rw-r--r--server/tests/api/videos/video-change-ownership.ts16
-rw-r--r--server/tests/api/videos/video-hls.ts17
-rw-r--r--server/tests/api/videos/video-transcoder.ts60
-rw-r--r--server/tests/plugins/plugin-helpers.ts4
-rw-r--r--shared/core-utils/miscs/index.ts1
-rw-r--r--shared/core-utils/miscs/regexp.ts1
-rw-r--r--shared/extra-utils/server/server.ts18
-rw-r--r--shared/extra-utils/server/servers-command.ts9
-rw-r--r--shared/extra-utils/videos/streaming-playlists.ts4
-rw-r--r--shared/extra-utils/videos/videos.ts89
27 files changed, 364 insertions, 266 deletions
diff --git a/server/controllers/api/videos/upload.ts b/server/controllers/api/videos/upload.ts
index 1603ef127..7792ae3fc 100644
--- a/server/controllers/api/videos/upload.ts
+++ b/server/controllers/api/videos/upload.ts
@@ -6,7 +6,7 @@ import { uuidToShort } from '@server/helpers/uuid'
6import { createTorrentAndSetInfoHash } from '@server/helpers/webtorrent' 6import { createTorrentAndSetInfoHash } from '@server/helpers/webtorrent'
7import { getLocalVideoActivityPubUrl } from '@server/lib/activitypub/url' 7import { getLocalVideoActivityPubUrl } from '@server/lib/activitypub/url'
8import { addOptimizeOrMergeAudioJob, buildLocalVideoFromReq, buildVideoThumbnailsFromReq, setVideoTags } from '@server/lib/video' 8import { addOptimizeOrMergeAudioJob, buildLocalVideoFromReq, buildVideoThumbnailsFromReq, setVideoTags } from '@server/lib/video'
9import { generateVideoFilename, getVideoFilePath } from '@server/lib/video-paths' 9import { generateWebTorrentVideoFilename, getVideoFilePath } from '@server/lib/video-paths'
10import { openapiOperationDoc } from '@server/middlewares/doc' 10import { openapiOperationDoc } from '@server/middlewares/doc'
11import { MVideo, MVideoFile, MVideoFullLight } from '@server/types/models' 11import { MVideo, MVideoFile, MVideoFullLight } from '@server/types/models'
12import { uploadx } from '@uploadx/core' 12import { uploadx } from '@uploadx/core'
@@ -240,7 +240,7 @@ async function buildNewFile (video: MVideo, videoPhysicalFile: express.VideoUplo
240 videoFile.resolution = (await getVideoFileResolution(videoPhysicalFile.path)).videoFileResolution 240 videoFile.resolution = (await getVideoFileResolution(videoPhysicalFile.path)).videoFileResolution
241 } 241 }
242 242
243 videoFile.filename = generateVideoFilename(video, false, videoFile.resolution, videoFile.extname) 243 videoFile.filename = generateWebTorrentVideoFilename(videoFile.resolution, videoFile.extname)
244 244
245 return videoFile 245 return videoFile
246} 246}
diff --git a/server/lib/hls.ts b/server/lib/hls.ts
index 05be403f3..212bd095b 100644
--- a/server/lib/hls.ts
+++ b/server/lib/hls.ts
@@ -36,8 +36,10 @@ async function updateMasterHLSPlaylist (video: MVideoWithFile) {
36 const streamingPlaylist = video.getHLSPlaylist() 36 const streamingPlaylist = video.getHLSPlaylist()
37 37
38 for (const file of streamingPlaylist.VideoFiles) { 38 for (const file of streamingPlaylist.VideoFiles) {
39 const playlistFilename = VideoStreamingPlaylistModel.getHlsPlaylistFilename(file.resolution)
40
39 // If we did not generated a playlist for this resolution, skip 41 // If we did not generated a playlist for this resolution, skip
40 const filePlaylistPath = join(directory, VideoStreamingPlaylistModel.getHlsPlaylistFilename(file.resolution)) 42 const filePlaylistPath = join(directory, playlistFilename)
41 if (await pathExists(filePlaylistPath) === false) continue 43 if (await pathExists(filePlaylistPath) === false) continue
42 44
43 const videoFilePath = getVideoFilePath(streamingPlaylist, file) 45 const videoFilePath = getVideoFilePath(streamingPlaylist, file)
@@ -58,7 +60,7 @@ async function updateMasterHLSPlaylist (video: MVideoWithFile) {
58 line += `,CODECS="${codecs.filter(c => !!c).join(',')}"` 60 line += `,CODECS="${codecs.filter(c => !!c).join(',')}"`
59 61
60 masterPlaylists.push(line) 62 masterPlaylists.push(line)
61 masterPlaylists.push(VideoStreamingPlaylistModel.getHlsPlaylistFilename(file.resolution)) 63 masterPlaylists.push(playlistFilename)
62 } 64 }
63 65
64 await writeFile(masterPlaylistPath, masterPlaylists.join('\n') + '\n') 66 await writeFile(masterPlaylistPath, masterPlaylists.join('\n') + '\n')
diff --git a/server/lib/job-queue/handlers/video-file-import.ts b/server/lib/job-queue/handlers/video-file-import.ts
index 187cb652e..1783f206a 100644
--- a/server/lib/job-queue/handlers/video-file-import.ts
+++ b/server/lib/job-queue/handlers/video-file-import.ts
@@ -2,7 +2,7 @@ import * as Bull from 'bull'
2import { copy, stat } from 'fs-extra' 2import { copy, stat } from 'fs-extra'
3import { getLowercaseExtension } from '@server/helpers/core-utils' 3import { getLowercaseExtension } from '@server/helpers/core-utils'
4import { createTorrentAndSetInfoHash } from '@server/helpers/webtorrent' 4import { createTorrentAndSetInfoHash } from '@server/helpers/webtorrent'
5import { generateVideoFilename, getVideoFilePath } from '@server/lib/video-paths' 5import { generateWebTorrentVideoFilename, getVideoFilePath } from '@server/lib/video-paths'
6import { UserModel } from '@server/models/user/user' 6import { UserModel } from '@server/models/user/user'
7import { MVideoFullLight } from '@server/types/models' 7import { MVideoFullLight } from '@server/types/models'
8import { VideoFileImportPayload } from '@shared/models' 8import { VideoFileImportPayload } from '@shared/models'
@@ -72,7 +72,7 @@ async function updateVideoFile (video: MVideoFullLight, inputFilePath: string) {
72 const newVideoFile = new VideoFileModel({ 72 const newVideoFile = new VideoFileModel({
73 resolution: videoFileResolution, 73 resolution: videoFileResolution,
74 extname: fileExt, 74 extname: fileExt,
75 filename: generateVideoFilename(video, false, videoFileResolution, fileExt), 75 filename: generateWebTorrentVideoFilename(videoFileResolution, fileExt),
76 size, 76 size,
77 fps, 77 fps,
78 videoId: video.id 78 videoId: video.id
diff --git a/server/lib/job-queue/handlers/video-import.ts b/server/lib/job-queue/handlers/video-import.ts
index 55498003d..6e425d09c 100644
--- a/server/lib/job-queue/handlers/video-import.ts
+++ b/server/lib/job-queue/handlers/video-import.ts
@@ -8,7 +8,7 @@ import { Hooks } from '@server/lib/plugins/hooks'
8import { ServerConfigManager } from '@server/lib/server-config-manager' 8import { ServerConfigManager } from '@server/lib/server-config-manager'
9import { isAbleToUploadVideo } from '@server/lib/user' 9import { isAbleToUploadVideo } from '@server/lib/user'
10import { addOptimizeOrMergeAudioJob } from '@server/lib/video' 10import { addOptimizeOrMergeAudioJob } from '@server/lib/video'
11import { generateVideoFilename, getVideoFilePath } from '@server/lib/video-paths' 11import { generateWebTorrentVideoFilename, getVideoFilePath } from '@server/lib/video-paths'
12import { ThumbnailModel } from '@server/models/video/thumbnail' 12import { ThumbnailModel } from '@server/models/video/thumbnail'
13import { MVideoImportDefault, MVideoImportDefaultFiles, MVideoImportVideo } from '@server/types/models/video/video-import' 13import { MVideoImportDefault, MVideoImportDefaultFiles, MVideoImportVideo } from '@server/types/models/video/video-import'
14import { 14import {
@@ -124,7 +124,7 @@ async function processFile (downloader: () => Promise<string>, videoImport: MVid
124 extname: fileExt, 124 extname: fileExt,
125 resolution: videoFileResolution, 125 resolution: videoFileResolution,
126 size: stats.size, 126 size: stats.size,
127 filename: generateVideoFilename(videoImport.Video, false, videoFileResolution, fileExt), 127 filename: generateWebTorrentVideoFilename(videoFileResolution, fileExt),
128 fps, 128 fps,
129 videoId: videoImport.videoId 129 videoId: videoImport.videoId
130 } 130 }
diff --git a/server/lib/transcoding/video-transcoding.ts b/server/lib/transcoding/video-transcoding.ts
index 1ad63baf3..d70f7f474 100644
--- a/server/lib/transcoding/video-transcoding.ts
+++ b/server/lib/transcoding/video-transcoding.ts
@@ -14,7 +14,7 @@ import { HLS_STREAMING_PLAYLIST_DIRECTORY, P2P_MEDIA_LOADER_PEER_VERSION, WEBSER
14import { VideoFileModel } from '../../models/video/video-file' 14import { VideoFileModel } from '../../models/video/video-file'
15import { VideoStreamingPlaylistModel } from '../../models/video/video-streaming-playlist' 15import { VideoStreamingPlaylistModel } from '../../models/video/video-streaming-playlist'
16import { updateMasterHLSPlaylist, updateSha256VODSegments } from '../hls' 16import { updateMasterHLSPlaylist, updateSha256VODSegments } from '../hls'
17import { generateVideoFilename, generateVideoStreamingPlaylistName, getVideoFilePath } from '../video-paths' 17import { generateHLSVideoFilename, generateWebTorrentVideoFilename, getVideoFilePath } from '../video-paths'
18import { VideoTranscodingProfilesManager } from './video-transcoding-profiles' 18import { VideoTranscodingProfilesManager } from './video-transcoding-profiles'
19 19
20/** 20/**
@@ -60,7 +60,7 @@ async function optimizeOriginalVideofile (video: MVideoFullLight, inputVideoFile
60 60
61 // Important to do this before getVideoFilename() to take in account the new filename 61 // Important to do this before getVideoFilename() to take in account the new filename
62 inputVideoFile.extname = newExtname 62 inputVideoFile.extname = newExtname
63 inputVideoFile.filename = generateVideoFilename(video, false, resolution, newExtname) 63 inputVideoFile.filename = generateWebTorrentVideoFilename(resolution, newExtname)
64 64
65 const videoOutputPath = getVideoFilePath(video, inputVideoFile) 65 const videoOutputPath = getVideoFilePath(video, inputVideoFile)
66 66
@@ -86,7 +86,7 @@ async function transcodeNewWebTorrentResolution (video: MVideoFullLight, resolut
86 const newVideoFile = new VideoFileModel({ 86 const newVideoFile = new VideoFileModel({
87 resolution, 87 resolution,
88 extname, 88 extname,
89 filename: generateVideoFilename(video, false, resolution, extname), 89 filename: generateWebTorrentVideoFilename(resolution, extname),
90 size: 0, 90 size: 0,
91 videoId: video.id 91 videoId: video.id
92 }) 92 })
@@ -169,7 +169,7 @@ async function mergeAudioVideofile (video: MVideoFullLight, resolution: VideoRes
169 169
170 // Important to do this before getVideoFilename() to take in account the new file extension 170 // Important to do this before getVideoFilename() to take in account the new file extension
171 inputVideoFile.extname = newExtname 171 inputVideoFile.extname = newExtname
172 inputVideoFile.filename = generateVideoFilename(video, false, inputVideoFile.resolution, newExtname) 172 inputVideoFile.filename = generateWebTorrentVideoFilename(inputVideoFile.resolution, newExtname)
173 173
174 const videoOutputPath = getVideoFilePath(video, inputVideoFile) 174 const videoOutputPath = getVideoFilePath(video, inputVideoFile)
175 // ffmpeg generated a new video file, so update the video duration 175 // ffmpeg generated a new video file, so update the video duration
@@ -271,7 +271,7 @@ async function generateHlsPlaylistCommon (options: {
271 const videoTranscodedBasePath = join(transcodeDirectory, type) 271 const videoTranscodedBasePath = join(transcodeDirectory, type)
272 await ensureDir(videoTranscodedBasePath) 272 await ensureDir(videoTranscodedBasePath)
273 273
274 const videoFilename = generateVideoStreamingPlaylistName(video.uuid, resolution) 274 const videoFilename = generateHLSVideoFilename(resolution)
275 const playlistFilename = VideoStreamingPlaylistModel.getHlsPlaylistFilename(resolution) 275 const playlistFilename = VideoStreamingPlaylistModel.getHlsPlaylistFilename(resolution)
276 const playlistFileTranscodePath = join(videoTranscodedBasePath, playlistFilename) 276 const playlistFileTranscodePath = join(videoTranscodedBasePath, playlistFilename)
277 277
@@ -319,7 +319,7 @@ async function generateHlsPlaylistCommon (options: {
319 resolution, 319 resolution,
320 extname, 320 extname,
321 size: 0, 321 size: 0,
322 filename: generateVideoFilename(video, true, resolution, extname), 322 filename: videoFilename,
323 fps: -1, 323 fps: -1,
324 videoStreamingPlaylistId: videoStreamingPlaylist.id 324 videoStreamingPlaylistId: videoStreamingPlaylist.id
325 }) 325 })
diff --git a/server/lib/video-paths.ts b/server/lib/video-paths.ts
index 1708c479a..b7068190c 100644
--- a/server/lib/video-paths.ts
+++ b/server/lib/video-paths.ts
@@ -3,29 +3,20 @@ import { extractVideo } from '@server/helpers/video'
3import { CONFIG } from '@server/initializers/config' 3import { CONFIG } from '@server/initializers/config'
4import { HLS_REDUNDANCY_DIRECTORY, HLS_STREAMING_PLAYLIST_DIRECTORY, STATIC_PATHS, WEBSERVER } from '@server/initializers/constants' 4import { HLS_REDUNDANCY_DIRECTORY, HLS_STREAMING_PLAYLIST_DIRECTORY, STATIC_PATHS, WEBSERVER } from '@server/initializers/constants'
5import { isStreamingPlaylist, MStreamingPlaylist, MStreamingPlaylistVideo, MVideo, MVideoFile, MVideoUUID } from '@server/types/models' 5import { isStreamingPlaylist, MStreamingPlaylist, MStreamingPlaylistVideo, MVideo, MVideoFile, MVideoUUID } from '@server/types/models'
6import { buildUUID } from '@server/helpers/uuid'
6 7
7// ################## Video file name ################## 8// ################## Video file name ##################
8 9
9function generateVideoFilename (videoOrPlaylist: MVideo | MStreamingPlaylistVideo, isHls: boolean, resolution: number, extname: string) { 10function generateWebTorrentVideoFilename (resolution: number, extname: string) {
10 const video = extractVideo(videoOrPlaylist) 11 const uuid = buildUUID()
11 12
12 // FIXME: use a generated uuid instead, that will break compatibility with PeerTube < 3.1 13 return uuid + '-' + resolution + extname
13 // const uuid = uuidv4()
14 const uuid = video.uuid
15
16 if (isHls) {
17 return generateVideoStreamingPlaylistName(uuid, resolution)
18 }
19
20 return generateWebTorrentVideoName(uuid, resolution, extname)
21} 14}
22 15
23function generateVideoStreamingPlaylistName (uuid: string, resolution: number) { 16function generateHLSVideoFilename (resolution: number) {
24 return `${uuid}-${resolution}-fragmented.mp4` 17 const uuid = buildUUID()
25}
26 18
27function generateWebTorrentVideoName (uuid: string, resolution: number, extname: string) { 19 return `${uuid}-${resolution}-fragmented.mp4`
28 return uuid + '-' + resolution + extname
29} 20}
30 21
31function getVideoFilePath (videoOrPlaylist: MVideo | MStreamingPlaylistVideo, videoFile: MVideoFile, isRedundancy = false) { 22function getVideoFilePath (videoOrPlaylist: MVideo | MStreamingPlaylistVideo, videoFile: MVideoFile, isRedundancy = false) {
@@ -66,12 +57,8 @@ function getHLSDirectory (video: MVideoUUID, isRedundancy = false) {
66// ################## Torrents ################## 57// ################## Torrents ##################
67 58
68function generateTorrentFileName (videoOrPlaylist: MVideo | MStreamingPlaylistVideo, resolution: number) { 59function generateTorrentFileName (videoOrPlaylist: MVideo | MStreamingPlaylistVideo, resolution: number) {
69 const video = extractVideo(videoOrPlaylist)
70 const extension = '.torrent' 60 const extension = '.torrent'
71 61 const uuid = buildUUID()
72 // FIXME: use a generated uuid instead, that will break compatibility with PeerTube < 3.1
73 // const uuid = uuidv4()
74 const uuid = video.uuid
75 62
76 if (isStreamingPlaylist(videoOrPlaylist)) { 63 if (isStreamingPlaylist(videoOrPlaylist)) {
77 return `${uuid}-${resolution}-${videoOrPlaylist.getStringType()}${extension}` 64 return `${uuid}-${resolution}-${videoOrPlaylist.getStringType()}${extension}`
@@ -95,9 +82,9 @@ function getLocalVideoFileMetadataUrl (video: MVideoUUID, videoFile: MVideoFile)
95// --------------------------------------------------------------------------- 82// ---------------------------------------------------------------------------
96 83
97export { 84export {
98 generateVideoStreamingPlaylistName, 85 generateHLSVideoFilename,
99 generateWebTorrentVideoName, 86 generateWebTorrentVideoFilename,
100 generateVideoFilename, 87
101 getVideoFilePath, 88 getVideoFilePath,
102 89
103 generateTorrentFileName, 90 generateTorrentFileName,
diff --git a/server/tests/api/check-params/abuses.ts b/server/tests/api/check-params/abuses.ts
index 72f2cbd8f..fb9a5fd8b 100644
--- a/server/tests/api/check-params/abuses.ts
+++ b/server/tests/api/check-params/abuses.ts
@@ -41,7 +41,7 @@ describe('Test abuses API validators', function () {
41 userToken = await server.users.generateUserAndToken('user_1') 41 userToken = await server.users.generateUserAndToken('user_1')
42 userToken2 = await server.users.generateUserAndToken('user_2') 42 userToken2 = await server.users.generateUserAndToken('user_2')
43 43
44 server.store.video = await server.videos.upload() 44 server.store.videoCreated = await server.videos.upload()
45 45
46 command = server.abuses 46 command = server.abuses
47 }) 47 })
@@ -223,25 +223,25 @@ describe('Test abuses API validators', function () {
223 }) 223 })
224 224
225 it('Should fail with a non authenticated user', async function () { 225 it('Should fail with a non authenticated user', async function () {
226 const fields = { video: { id: server.store.video.id }, reason: 'my super reason' } 226 const fields = { video: { id: server.store.videoCreated.id }, reason: 'my super reason' }
227 227
228 await makePostBodyRequest({ url: server.url, path, token: 'hello', fields, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 }) 228 await makePostBodyRequest({ url: server.url, path, token: 'hello', fields, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
229 }) 229 })
230 230
231 it('Should fail with a reason too short', async function () { 231 it('Should fail with a reason too short', async function () {
232 const fields = { video: { id: server.store.video.id }, reason: 'h' } 232 const fields = { video: { id: server.store.videoCreated.id }, reason: 'h' }
233 233
234 await makePostBodyRequest({ url: server.url, path, token: userToken, fields }) 234 await makePostBodyRequest({ url: server.url, path, token: userToken, fields })
235 }) 235 })
236 236
237 it('Should fail with a too big reason', async function () { 237 it('Should fail with a too big reason', async function () {
238 const fields = { video: { id: server.store.video.id }, reason: 'super'.repeat(605) } 238 const fields = { video: { id: server.store.videoCreated.id }, reason: 'super'.repeat(605) }
239 239
240 await makePostBodyRequest({ url: server.url, path, token: userToken, fields }) 240 await makePostBodyRequest({ url: server.url, path, token: userToken, fields })
241 }) 241 })
242 242
243 it('Should succeed with the correct parameters (basic)', async function () { 243 it('Should succeed with the correct parameters (basic)', async function () {
244 const fields: AbuseCreate = { video: { id: server.store.video.shortUUID }, reason: 'my super reason' } 244 const fields: AbuseCreate = { video: { id: server.store.videoCreated.shortUUID }, reason: 'my super reason' }
245 245
246 const res = await makePostBodyRequest({ 246 const res = await makePostBodyRequest({
247 url: server.url, 247 url: server.url,
@@ -254,19 +254,19 @@ describe('Test abuses API validators', function () {
254 }) 254 })
255 255
256 it('Should fail with a wrong predefined reason', async function () { 256 it('Should fail with a wrong predefined reason', async function () {
257 const fields = { video: { id: server.store.video.id }, reason: 'my super reason', predefinedReasons: [ 'wrongPredefinedReason' ] } 257 const fields = { video: server.store.videoCreated, reason: 'my super reason', predefinedReasons: [ 'wrongPredefinedReason' ] }
258 258
259 await makePostBodyRequest({ url: server.url, path, token: userToken, fields }) 259 await makePostBodyRequest({ url: server.url, path, token: userToken, fields })
260 }) 260 })
261 261
262 it('Should fail with negative timestamps', async function () { 262 it('Should fail with negative timestamps', async function () {
263 const fields = { video: { id: server.store.video.id, startAt: -1 }, reason: 'my super reason' } 263 const fields = { video: { id: server.store.videoCreated.id, startAt: -1 }, reason: 'my super reason' }
264 264
265 await makePostBodyRequest({ url: server.url, path, token: userToken, fields }) 265 await makePostBodyRequest({ url: server.url, path, token: userToken, fields })
266 }) 266 })
267 267
268 it('Should fail mith misordered startAt/endAt', async function () { 268 it('Should fail mith misordered startAt/endAt', async function () {
269 const fields = { video: { id: server.store.video.id, startAt: 5, endAt: 1 }, reason: 'my super reason' } 269 const fields = { video: { id: server.store.videoCreated.id, startAt: 5, endAt: 1 }, reason: 'my super reason' }
270 270
271 await makePostBodyRequest({ url: server.url, path, token: userToken, fields }) 271 await makePostBodyRequest({ url: server.url, path, token: userToken, fields })
272 }) 272 })
@@ -274,7 +274,7 @@ describe('Test abuses API validators', function () {
274 it('Should succeed with the corret parameters (advanced)', async function () { 274 it('Should succeed with the corret parameters (advanced)', async function () {
275 const fields: AbuseCreate = { 275 const fields: AbuseCreate = {
276 video: { 276 video: {
277 id: server.store.video.id, 277 id: server.store.videoCreated.id,
278 startAt: 1, 278 startAt: 1,
279 endAt: 5 279 endAt: 5
280 }, 280 },
@@ -413,7 +413,7 @@ describe('Test abuses API validators', function () {
413 413
414 await doubleFollow(anotherServer, server) 414 await doubleFollow(anotherServer, server)
415 415
416 const server2VideoId = await anotherServer.videos.getId({ uuid: server.store.video.uuid }) 416 const server2VideoId = await anotherServer.videos.getId({ uuid: server.store.videoCreated.uuid })
417 await anotherServer.abuses.report({ reason: 'remote server', videoId: server2VideoId }) 417 await anotherServer.abuses.report({ reason: 'remote server', videoId: server2VideoId })
418 418
419 await waitJobs([ server, anotherServer ]) 419 await waitJobs([ server, anotherServer ])
diff --git a/server/tests/api/check-params/services.ts b/server/tests/api/check-params/services.ts
index 4c4a5cade..8d795fabc 100644
--- a/server/tests/api/check-params/services.ts
+++ b/server/tests/api/check-params/services.ts
@@ -24,7 +24,7 @@ describe('Test services API validators', function () {
24 await setAccessTokensToServers([ server ]) 24 await setAccessTokensToServers([ server ])
25 await setDefaultVideoChannel([ server ]) 25 await setDefaultVideoChannel([ server ])
26 26
27 server.store.video = await server.videos.upload({ attributes: { name: 'my super name' } }) 27 server.store.videoCreated = await server.videos.upload({ attributes: { name: 'my super name' } })
28 28
29 { 29 {
30 const created = await server.playlists.create({ 30 const created = await server.playlists.create({
@@ -47,7 +47,7 @@ describe('Test services API validators', function () {
47 }) 47 })
48 48
49 it('Should fail with an invalid host', async function () { 49 it('Should fail with an invalid host', async function () {
50 const embedUrl = 'http://hello.com/videos/watch/' + server.store.video.uuid 50 const embedUrl = 'http://hello.com/videos/watch/' + server.store.videoCreated.uuid
51 await checkParamEmbed(server, embedUrl) 51 await checkParamEmbed(server, embedUrl)
52 }) 52 })
53 53
@@ -62,37 +62,37 @@ describe('Test services API validators', function () {
62 }) 62 })
63 63
64 it('Should fail with an invalid path', async function () { 64 it('Should fail with an invalid path', async function () {
65 const embedUrl = `http://localhost:${server.port}/videos/watchs/${server.store.video.uuid}` 65 const embedUrl = `http://localhost:${server.port}/videos/watchs/${server.store.videoCreated.uuid}`
66 66
67 await checkParamEmbed(server, embedUrl) 67 await checkParamEmbed(server, embedUrl)
68 }) 68 })
69 69
70 it('Should fail with an invalid max height', async function () { 70 it('Should fail with an invalid max height', async function () {
71 const embedUrl = `http://localhost:${server.port}/videos/watch/${server.store.video.uuid}` 71 const embedUrl = `http://localhost:${server.port}/videos/watch/${server.store.videoCreated.uuid}`
72 72
73 await checkParamEmbed(server, embedUrl, HttpStatusCode.BAD_REQUEST_400, { maxheight: 'hello' }) 73 await checkParamEmbed(server, embedUrl, HttpStatusCode.BAD_REQUEST_400, { maxheight: 'hello' })
74 }) 74 })
75 75
76 it('Should fail with an invalid max width', async function () { 76 it('Should fail with an invalid max width', async function () {
77 const embedUrl = `http://localhost:${server.port}/videos/watch/${server.store.video.uuid}` 77 const embedUrl = `http://localhost:${server.port}/videos/watch/${server.store.videoCreated.uuid}`
78 78
79 await checkParamEmbed(server, embedUrl, HttpStatusCode.BAD_REQUEST_400, { maxwidth: 'hello' }) 79 await checkParamEmbed(server, embedUrl, HttpStatusCode.BAD_REQUEST_400, { maxwidth: 'hello' })
80 }) 80 })
81 81
82 it('Should fail with an invalid format', async function () { 82 it('Should fail with an invalid format', async function () {
83 const embedUrl = `http://localhost:${server.port}/videos/watch/${server.store.video.uuid}` 83 const embedUrl = `http://localhost:${server.port}/videos/watch/${server.store.videoCreated.uuid}`
84 84
85 await checkParamEmbed(server, embedUrl, HttpStatusCode.BAD_REQUEST_400, { format: 'blabla' }) 85 await checkParamEmbed(server, embedUrl, HttpStatusCode.BAD_REQUEST_400, { format: 'blabla' })
86 }) 86 })
87 87
88 it('Should fail with a non supported format', async function () { 88 it('Should fail with a non supported format', async function () {
89 const embedUrl = `http://localhost:${server.port}/videos/watch/${server.store.video.uuid}` 89 const embedUrl = `http://localhost:${server.port}/videos/watch/${server.store.videoCreated.uuid}`
90 90
91 await checkParamEmbed(server, embedUrl, HttpStatusCode.NOT_IMPLEMENTED_501, { format: 'xml' }) 91 await checkParamEmbed(server, embedUrl, HttpStatusCode.NOT_IMPLEMENTED_501, { format: 'xml' })
92 }) 92 })
93 93
94 it('Should succeed with the correct params with a video', async function () { 94 it('Should succeed with the correct params with a video', async function () {
95 const embedUrl = `http://localhost:${server.port}/videos/watch/${server.store.video.uuid}` 95 const embedUrl = `http://localhost:${server.port}/videos/watch/${server.store.videoCreated.uuid}`
96 const query = { 96 const query = {
97 format: 'json', 97 format: 'json',
98 maxheight: 400, 98 maxheight: 400,
diff --git a/server/tests/api/check-params/video-blacklist.ts b/server/tests/api/check-params/video-blacklist.ts
index d28c6a952..1f926d227 100644
--- a/server/tests/api/check-params/video-blacklist.ts
+++ b/server/tests/api/check-params/video-blacklist.ts
@@ -51,7 +51,7 @@ describe('Test video blacklist API validators', function () {
51 } 51 }
52 52
53 { 53 {
54 servers[0].store.video = await servers[0].videos.upload({ token: userAccessToken1 }) 54 servers[0].store.videoCreated = await servers[0].videos.upload({ token: userAccessToken1 })
55 } 55 }
56 56
57 { 57 {
@@ -73,7 +73,7 @@ describe('Test video blacklist API validators', function () {
73 const basePath = '/api/v1/videos/' 73 const basePath = '/api/v1/videos/'
74 74
75 it('Should fail with nothing', async function () { 75 it('Should fail with nothing', async function () {
76 const path = basePath + servers[0].store.video + '/blacklist' 76 const path = basePath + servers[0].store.videoCreated + '/blacklist'
77 const fields = {} 77 const fields = {}
78 await makePostBodyRequest({ url: servers[0].url, path, token: servers[0].accessToken, fields }) 78 await makePostBodyRequest({ url: servers[0].url, path, token: servers[0].accessToken, fields })
79 }) 79 })
@@ -85,13 +85,13 @@ describe('Test video blacklist API validators', function () {
85 }) 85 })
86 86
87 it('Should fail with a non authenticated user', async function () { 87 it('Should fail with a non authenticated user', async function () {
88 const path = basePath + servers[0].store.video + '/blacklist' 88 const path = basePath + servers[0].store.videoCreated + '/blacklist'
89 const fields = {} 89 const fields = {}
90 await makePostBodyRequest({ url: servers[0].url, path, token: 'hello', fields, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 }) 90 await makePostBodyRequest({ url: servers[0].url, path, token: 'hello', fields, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
91 }) 91 })
92 92
93 it('Should fail with a non admin user', async function () { 93 it('Should fail with a non admin user', async function () {
94 const path = basePath + servers[0].store.video + '/blacklist' 94 const path = basePath + servers[0].store.videoCreated + '/blacklist'
95 const fields = {} 95 const fields = {}
96 await makePostBodyRequest({ 96 await makePostBodyRequest({
97 url: servers[0].url, 97 url: servers[0].url,
@@ -103,7 +103,7 @@ describe('Test video blacklist API validators', function () {
103 }) 103 })
104 104
105 it('Should fail with an invalid reason', async function () { 105 it('Should fail with an invalid reason', async function () {
106 const path = basePath + servers[0].store.video.uuid + '/blacklist' 106 const path = basePath + servers[0].store.videoCreated.uuid + '/blacklist'
107 const fields = { reason: 'a'.repeat(305) } 107 const fields = { reason: 'a'.repeat(305) }
108 108
109 await makePostBodyRequest({ url: servers[0].url, path, token: servers[0].accessToken, fields }) 109 await makePostBodyRequest({ url: servers[0].url, path, token: servers[0].accessToken, fields })
@@ -123,7 +123,7 @@ describe('Test video blacklist API validators', function () {
123 }) 123 })
124 124
125 it('Should succeed with the correct params', async function () { 125 it('Should succeed with the correct params', async function () {
126 const path = basePath + servers[0].store.video.uuid + '/blacklist' 126 const path = basePath + servers[0].store.videoCreated.uuid + '/blacklist'
127 const fields = {} 127 const fields = {}
128 128
129 await makePostBodyRequest({ 129 await makePostBodyRequest({
@@ -158,13 +158,13 @@ describe('Test video blacklist API validators', function () {
158 }) 158 })
159 159
160 it('Should fail with a non authenticated user', async function () { 160 it('Should fail with a non authenticated user', async function () {
161 const path = basePath + servers[0].store.video + '/blacklist' 161 const path = basePath + servers[0].store.videoCreated + '/blacklist'
162 const fields = {} 162 const fields = {}
163 await makePutBodyRequest({ url: servers[0].url, path, token: 'hello', fields, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 }) 163 await makePutBodyRequest({ url: servers[0].url, path, token: 'hello', fields, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
164 }) 164 })
165 165
166 it('Should fail with a non admin user', async function () { 166 it('Should fail with a non admin user', async function () {
167 const path = basePath + servers[0].store.video + '/blacklist' 167 const path = basePath + servers[0].store.videoCreated + '/blacklist'
168 const fields = {} 168 const fields = {}
169 await makePutBodyRequest({ 169 await makePutBodyRequest({
170 url: servers[0].url, 170 url: servers[0].url,
@@ -176,14 +176,14 @@ describe('Test video blacklist API validators', function () {
176 }) 176 })
177 177
178 it('Should fail with an invalid reason', async function () { 178 it('Should fail with an invalid reason', async function () {
179 const path = basePath + servers[0].store.video.uuid + '/blacklist' 179 const path = basePath + servers[0].store.videoCreated.uuid + '/blacklist'
180 const fields = { reason: 'a'.repeat(305) } 180 const fields = { reason: 'a'.repeat(305) }
181 181
182 await makePutBodyRequest({ url: servers[0].url, path, token: servers[0].accessToken, fields }) 182 await makePutBodyRequest({ url: servers[0].url, path, token: servers[0].accessToken, fields })
183 }) 183 })
184 184
185 it('Should succeed with the correct params', async function () { 185 it('Should succeed with the correct params', async function () {
186 const path = basePath + servers[0].store.video.shortUUID + '/blacklist' 186 const path = basePath + servers[0].store.videoCreated.shortUUID + '/blacklist'
187 const fields = { reason: 'hello' } 187 const fields = { reason: 'hello' }
188 188
189 await makePutBodyRequest({ 189 await makePutBodyRequest({
@@ -199,24 +199,24 @@ describe('Test video blacklist API validators', function () {
199 describe('When getting blacklisted video', function () { 199 describe('When getting blacklisted video', function () {
200 200
201 it('Should fail with a non authenticated user', async function () { 201 it('Should fail with a non authenticated user', async function () {
202 await servers[0].videos.get({ id: servers[0].store.video.uuid, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 }) 202 await servers[0].videos.get({ id: servers[0].store.videoCreated.uuid, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
203 }) 203 })
204 204
205 it('Should fail with another user', async function () { 205 it('Should fail with another user', async function () {
206 await servers[0].videos.getWithToken({ 206 await servers[0].videos.getWithToken({
207 token: userAccessToken2, 207 token: userAccessToken2,
208 id: servers[0].store.video.uuid, 208 id: servers[0].store.videoCreated.uuid,
209 expectedStatus: HttpStatusCode.FORBIDDEN_403 209 expectedStatus: HttpStatusCode.FORBIDDEN_403
210 }) 210 })
211 }) 211 })
212 212
213 it('Should succeed with the owner authenticated user', async function () { 213 it('Should succeed with the owner authenticated user', async function () {
214 const video = await servers[0].videos.getWithToken({ token: userAccessToken1, id: servers[0].store.video.uuid }) 214 const video = await servers[0].videos.getWithToken({ token: userAccessToken1, id: servers[0].store.videoCreated.uuid })
215 expect(video.blacklisted).to.be.true 215 expect(video.blacklisted).to.be.true
216 }) 216 })
217 217
218 it('Should succeed with an admin', async function () { 218 it('Should succeed with an admin', async function () {
219 const video = servers[0].store.video 219 const video = servers[0].store.videoCreated
220 220
221 for (const id of [ video.id, video.uuid, video.shortUUID ]) { 221 for (const id of [ video.id, video.uuid, video.shortUUID ]) {
222 const video = await servers[0].videos.getWithToken({ id, expectedStatus: HttpStatusCode.OK_200 }) 222 const video = await servers[0].videos.getWithToken({ id, expectedStatus: HttpStatusCode.OK_200 })
@@ -228,11 +228,19 @@ describe('Test video blacklist API validators', function () {
228 describe('When removing a video in blacklist', function () { 228 describe('When removing a video in blacklist', function () {
229 229
230 it('Should fail with a non authenticated user', async function () { 230 it('Should fail with a non authenticated user', async function () {
231 await command.remove({ token: 'fake token', videoId: servers[0].store.video.uuid, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 }) 231 await command.remove({
232 token: 'fake token',
233 videoId: servers[0].store.videoCreated.uuid,
234 expectedStatus: HttpStatusCode.UNAUTHORIZED_401
235 })
232 }) 236 })
233 237
234 it('Should fail with a non admin user', async function () { 238 it('Should fail with a non admin user', async function () {
235 await command.remove({ token: userAccessToken2, videoId: servers[0].store.video.uuid, expectedStatus: HttpStatusCode.FORBIDDEN_403 }) 239 await command.remove({
240 token: userAccessToken2,
241 videoId: servers[0].store.videoCreated.uuid,
242 expectedStatus: HttpStatusCode.FORBIDDEN_403
243 })
236 }) 244 })
237 245
238 it('Should fail with an incorrect id', async function () { 246 it('Should fail with an incorrect id', async function () {
@@ -245,7 +253,7 @@ describe('Test video blacklist API validators', function () {
245 }) 253 })
246 254
247 it('Should succeed with the correct params', async function () { 255 it('Should succeed with the correct params', async function () {
248 await command.remove({ videoId: servers[0].store.video.uuid, expectedStatus: HttpStatusCode.NO_CONTENT_204 }) 256 await command.remove({ videoId: servers[0].store.videoCreated.uuid, expectedStatus: HttpStatusCode.NO_CONTENT_204 })
249 }) 257 })
250 }) 258 })
251 259
diff --git a/server/tests/api/moderation/abuses.ts b/server/tests/api/moderation/abuses.ts
index 8d6360eb3..c258414ce 100644
--- a/server/tests/api/moderation/abuses.ts
+++ b/server/tests/api/moderation/abuses.ts
@@ -64,8 +64,8 @@ describe('Test abuses', function () {
64 const { data } = await servers[0].videos.list() 64 const { data } = await servers[0].videos.list()
65 expect(data.length).to.equal(2) 65 expect(data.length).to.equal(2)
66 66
67 servers[0].store.video = data.find(video => video.name === 'my super name for server 1') 67 servers[0].store.videoCreated = data.find(video => video.name === 'my super name for server 1')
68 servers[1].store.video = data.find(video => video.name === 'my super name for server 2') 68 servers[1].store.videoCreated = data.find(video => video.name === 'my super name for server 2')
69 }) 69 })
70 70
71 it('Should not have abuses', async function () { 71 it('Should not have abuses', async function () {
@@ -80,7 +80,7 @@ describe('Test abuses', function () {
80 this.timeout(15000) 80 this.timeout(15000)
81 81
82 const reason = 'my super bad reason' 82 const reason = 'my super bad reason'
83 await commands[0].report({ videoId: servers[0].store.video.id, reason }) 83 await commands[0].report({ videoId: servers[0].store.videoCreated.id, reason })
84 84
85 // We wait requests propagation, even if the server 1 is not supposed to make a request to server 2 85 // We wait requests propagation, even if the server 1 is not supposed to make a request to server 2
86 await waitJobs(servers) 86 await waitJobs(servers)
@@ -100,7 +100,7 @@ describe('Test abuses', function () {
100 expect(abuse.reporterAccount.name).to.equal('root') 100 expect(abuse.reporterAccount.name).to.equal('root')
101 expect(abuse.reporterAccount.host).to.equal(servers[0].host) 101 expect(abuse.reporterAccount.host).to.equal(servers[0].host)
102 102
103 expect(abuse.video.id).to.equal(servers[0].store.video.id) 103 expect(abuse.video.id).to.equal(servers[0].store.videoCreated.id)
104 expect(abuse.video.channel).to.exist 104 expect(abuse.video.channel).to.exist
105 105
106 expect(abuse.comment).to.be.null 106 expect(abuse.comment).to.be.null
@@ -127,7 +127,7 @@ describe('Test abuses', function () {
127 this.timeout(10000) 127 this.timeout(10000)
128 128
129 const reason = 'my super bad reason 2' 129 const reason = 'my super bad reason 2'
130 const videoId = await servers[0].videos.getId({ uuid: servers[1].store.video.uuid }) 130 const videoId = await servers[0].videos.getId({ uuid: servers[1].store.videoCreated.uuid })
131 await commands[0].report({ videoId, reason }) 131 await commands[0].report({ videoId, reason })
132 132
133 // We wait requests propagation 133 // We wait requests propagation
@@ -146,7 +146,7 @@ describe('Test abuses', function () {
146 expect(abuse1.reporterAccount.name).to.equal('root') 146 expect(abuse1.reporterAccount.name).to.equal('root')
147 expect(abuse1.reporterAccount.host).to.equal(servers[0].host) 147 expect(abuse1.reporterAccount.host).to.equal(servers[0].host)
148 148
149 expect(abuse1.video.id).to.equal(servers[0].store.video.id) 149 expect(abuse1.video.id).to.equal(servers[0].store.videoCreated.id)
150 expect(abuse1.video.countReports).to.equal(1) 150 expect(abuse1.video.countReports).to.equal(1)
151 expect(abuse1.video.nthReport).to.equal(1) 151 expect(abuse1.video.nthReport).to.equal(1)
152 152
@@ -165,7 +165,7 @@ describe('Test abuses', function () {
165 expect(abuse2.reporterAccount.name).to.equal('root') 165 expect(abuse2.reporterAccount.name).to.equal('root')
166 expect(abuse2.reporterAccount.host).to.equal(servers[0].host) 166 expect(abuse2.reporterAccount.host).to.equal(servers[0].host)
167 167
168 expect(abuse2.video.id).to.equal(servers[1].store.video.id) 168 expect(abuse2.video.id).to.equal(servers[1].store.videoCreated.id)
169 169
170 expect(abuse2.comment).to.be.null 170 expect(abuse2.comment).to.be.null
171 171
@@ -200,7 +200,7 @@ describe('Test abuses', function () {
200 this.timeout(10000) 200 this.timeout(10000)
201 201
202 { 202 {
203 const videoId = await servers[1].videos.getId({ uuid: servers[0].store.video.uuid }) 203 const videoId = await servers[1].videos.getId({ uuid: servers[0].store.videoCreated.uuid })
204 await commands[1].report({ videoId, reason: 'will mute this' }) 204 await commands[1].report({ videoId, reason: 'will mute this' })
205 await waitJobs(servers) 205 await waitJobs(servers)
206 206
@@ -288,7 +288,7 @@ describe('Test abuses', function () {
288 await commands[0].report({ videoId: video3Id, reason: reason3 }) 288 await commands[0].report({ videoId: video3Id, reason: reason3 })
289 289
290 const reason4 = 'my super bad reason 4' 290 const reason4 = 'my super bad reason 4'
291 await commands[0].report({ token: userAccessToken, videoId: servers[0].store.video.id, reason: reason4 }) 291 await commands[0].report({ token: userAccessToken, videoId: servers[0].store.videoCreated.id, reason: reason4 })
292 292
293 { 293 {
294 const body = await commands[0].getAdminList() 294 const body = await commands[0].getAdminList()
@@ -301,7 +301,7 @@ describe('Test abuses', function () {
301 expect(abuseVideo3.countReportsForReportee).to.equal(1, "wrong reports count for reporter on video 3 abuse") 301 expect(abuseVideo3.countReportsForReportee).to.equal(1, "wrong reports count for reporter on video 3 abuse")
302 expect(abuseVideo3.countReportsForReporter).to.equal(3, "wrong reports count for reportee on video 3 abuse") 302 expect(abuseVideo3.countReportsForReporter).to.equal(3, "wrong reports count for reportee on video 3 abuse")
303 303
304 const abuseServer1 = abuses.find(a => a.video.id === servers[0].store.video.id) 304 const abuseServer1 = abuses.find(a => a.video.id === servers[0].store.videoCreated.id)
305 expect(abuseServer1.countReportsForReportee).to.equal(3, "wrong reports count for reporter on video 1 abuse") 305 expect(abuseServer1.countReportsForReportee).to.equal(3, "wrong reports count for reporter on video 1 abuse")
306 } 306 }
307 }) 307 })
@@ -312,7 +312,7 @@ describe('Test abuses', function () {
312 const reason5 = 'my super bad reason 5' 312 const reason5 = 'my super bad reason 5'
313 const predefinedReasons5: AbusePredefinedReasonsString[] = [ 'violentOrRepulsive', 'captions' ] 313 const predefinedReasons5: AbusePredefinedReasonsString[] = [ 'violentOrRepulsive', 'captions' ]
314 const createRes = await commands[0].report({ 314 const createRes = await commands[0].report({
315 videoId: servers[0].store.video.id, 315 videoId: servers[0].store.videoCreated.id,
316 reason: reason5, 316 reason: reason5,
317 predefinedReasons: predefinedReasons5, 317 predefinedReasons: predefinedReasons5,
318 startAt: 1, 318 startAt: 1,
@@ -402,11 +402,11 @@ describe('Test abuses', function () {
402 before(async function () { 402 before(async function () {
403 this.timeout(50000) 403 this.timeout(50000)
404 404
405 servers[0].store.video = await servers[0].videos.quickUpload({ name: 'server 1' }) 405 servers[0].store.videoCreated = await servers[0].videos.quickUpload({ name: 'server 1' })
406 servers[1].store.video = await servers[1].videos.quickUpload({ name: 'server 2' }) 406 servers[1].store.videoCreated = await servers[1].videos.quickUpload({ name: 'server 2' })
407 407
408 await servers[0].comments.createThread({ videoId: servers[0].store.video.id, text: 'comment server 1' }) 408 await servers[0].comments.createThread({ videoId: servers[0].store.videoCreated.id, text: 'comment server 1' })
409 await servers[1].comments.createThread({ videoId: servers[1].store.video.id, text: 'comment server 2' }) 409 await servers[1].comments.createThread({ videoId: servers[1].store.videoCreated.id, text: 'comment server 2' })
410 410
411 await waitJobs(servers) 411 await waitJobs(servers)
412 }) 412 })
@@ -414,7 +414,7 @@ describe('Test abuses', function () {
414 it('Should report abuse on a comment', async function () { 414 it('Should report abuse on a comment', async function () {
415 this.timeout(15000) 415 this.timeout(15000)
416 416
417 const comment = await getComment(servers[0], servers[0].store.video.id) 417 const comment = await getComment(servers[0], servers[0].store.videoCreated.id)
418 418
419 const reason = 'it is a bad comment' 419 const reason = 'it is a bad comment'
420 await commands[0].report({ commentId: comment.id, reason }) 420 await commands[0].report({ commentId: comment.id, reason })
@@ -424,7 +424,7 @@ describe('Test abuses', function () {
424 424
425 it('Should have 1 comment abuse on server 1 and 0 on server 2', async function () { 425 it('Should have 1 comment abuse on server 1 and 0 on server 2', async function () {
426 { 426 {
427 const comment = await getComment(servers[0], servers[0].store.video.id) 427 const comment = await getComment(servers[0], servers[0].store.videoCreated.id)
428 const body = await commands[0].getAdminList({ filter: 'comment' }) 428 const body = await commands[0].getAdminList({ filter: 'comment' })
429 429
430 expect(body.total).to.equal(1) 430 expect(body.total).to.equal(1)
@@ -442,8 +442,8 @@ describe('Test abuses', function () {
442 expect(abuse.comment.id).to.equal(comment.id) 442 expect(abuse.comment.id).to.equal(comment.id)
443 expect(abuse.comment.text).to.equal(comment.text) 443 expect(abuse.comment.text).to.equal(comment.text)
444 expect(abuse.comment.video.name).to.equal('server 1') 444 expect(abuse.comment.video.name).to.equal('server 1')
445 expect(abuse.comment.video.id).to.equal(servers[0].store.video.id) 445 expect(abuse.comment.video.id).to.equal(servers[0].store.videoCreated.id)
446 expect(abuse.comment.video.uuid).to.equal(servers[0].store.video.uuid) 446 expect(abuse.comment.video.uuid).to.equal(servers[0].store.videoCreated.uuid)
447 447
448 expect(abuse.countReportsForReporter).to.equal(5) 448 expect(abuse.countReportsForReporter).to.equal(5)
449 expect(abuse.countReportsForReportee).to.equal(5) 449 expect(abuse.countReportsForReportee).to.equal(5)
@@ -459,7 +459,7 @@ describe('Test abuses', function () {
459 it('Should report abuse on a remote comment', async function () { 459 it('Should report abuse on a remote comment', async function () {
460 this.timeout(10000) 460 this.timeout(10000)
461 461
462 const comment = await getComment(servers[0], servers[1].store.video.uuid) 462 const comment = await getComment(servers[0], servers[1].store.videoCreated.uuid)
463 463
464 const reason = 'it is a really bad comment' 464 const reason = 'it is a really bad comment'
465 await commands[0].report({ commentId: comment.id, reason }) 465 await commands[0].report({ commentId: comment.id, reason })
@@ -468,7 +468,7 @@ describe('Test abuses', function () {
468 }) 468 })
469 469
470 it('Should have 2 comment abuses on server 1 and 1 on server 2', async function () { 470 it('Should have 2 comment abuses on server 1 and 1 on server 2', async function () {
471 const commentServer2 = await getComment(servers[0], servers[1].store.video.id) 471 const commentServer2 = await getComment(servers[0], servers[1].store.videoCreated.id)
472 472
473 { 473 {
474 const body = await commands[0].getAdminList({ filter: 'comment' }) 474 const body = await commands[0].getAdminList({ filter: 'comment' })
@@ -493,7 +493,7 @@ describe('Test abuses', function () {
493 expect(abuse2.comment.id).to.equal(commentServer2.id) 493 expect(abuse2.comment.id).to.equal(commentServer2.id)
494 expect(abuse2.comment.text).to.equal(commentServer2.text) 494 expect(abuse2.comment.text).to.equal(commentServer2.text)
495 expect(abuse2.comment.video.name).to.equal('server 2') 495 expect(abuse2.comment.video.name).to.equal('server 2')
496 expect(abuse2.comment.video.uuid).to.equal(servers[1].store.video.uuid) 496 expect(abuse2.comment.video.uuid).to.equal(servers[1].store.videoCreated.uuid)
497 497
498 expect(abuse2.state.id).to.equal(AbuseState.PENDING) 498 expect(abuse2.state.id).to.equal(AbuseState.PENDING)
499 expect(abuse2.state.label).to.equal('Pending') 499 expect(abuse2.state.label).to.equal('Pending')
@@ -527,9 +527,9 @@ describe('Test abuses', function () {
527 it('Should keep the comment abuse when deleting the comment', async function () { 527 it('Should keep the comment abuse when deleting the comment', async function () {
528 this.timeout(10000) 528 this.timeout(10000)
529 529
530 const commentServer2 = await getComment(servers[0], servers[1].store.video.id) 530 const commentServer2 = await getComment(servers[0], servers[1].store.videoCreated.id)
531 531
532 await servers[0].comments.delete({ videoId: servers[1].store.video.uuid, commentId: commentServer2.id }) 532 await servers[0].comments.delete({ videoId: servers[1].store.videoCreated.uuid, commentId: commentServer2.id })
533 533
534 await waitJobs(servers) 534 await waitJobs(servers)
535 535
@@ -761,9 +761,9 @@ describe('Test abuses', function () {
761 before(async function () { 761 before(async function () {
762 userAccessToken = await servers[0].users.generateUserAndToken('user_42') 762 userAccessToken = await servers[0].users.generateUserAndToken('user_42')
763 763
764 await commands[0].report({ token: userAccessToken, videoId: servers[0].store.video.id, reason: 'user reason 1' }) 764 await commands[0].report({ token: userAccessToken, videoId: servers[0].store.videoCreated.id, reason: 'user reason 1' })
765 765
766 const videoId = await servers[0].videos.getId({ uuid: servers[1].store.video.uuid }) 766 const videoId = await servers[0].videos.getId({ uuid: servers[1].store.videoCreated.uuid })
767 await commands[0].report({ token: userAccessToken, videoId, reason: 'user reason 2' }) 767 await commands[0].report({ token: userAccessToken, videoId, reason: 'user reason 2' })
768 }) 768 })
769 769
@@ -832,7 +832,7 @@ describe('Test abuses', function () {
832 before(async function () { 832 before(async function () {
833 userToken = await servers[0].users.generateUserAndToken('user_43') 833 userToken = await servers[0].users.generateUserAndToken('user_43')
834 834
835 const body = await commands[0].report({ token: userToken, videoId: servers[0].store.video.id, reason: 'user 43 reason 1' }) 835 const body = await commands[0].report({ token: userToken, videoId: servers[0].store.videoCreated.id, reason: 'user 43 reason 1' })
836 abuseId = body.abuse.id 836 abuseId = body.abuse.id
837 }) 837 })
838 838
diff --git a/server/tests/api/redundancy/redundancy.ts b/server/tests/api/redundancy/redundancy.ts
index a6559d304..e1a12f5f8 100644
--- a/server/tests/api/redundancy/redundancy.ts
+++ b/server/tests/api/redundancy/redundancy.ts
@@ -4,7 +4,7 @@ import 'mocha'
4import * as chai from 'chai' 4import * as chai from 'chai'
5import { readdir } from 'fs-extra' 5import { readdir } from 'fs-extra'
6import * as magnetUtil from 'magnet-uri' 6import * as magnetUtil from 'magnet-uri'
7import { join } from 'path' 7import { basename, join } from 'path'
8import { 8import {
9 checkSegmentHash, 9 checkSegmentHash,
10 checkVideoFilesWereRemoved, 10 checkVideoFilesWereRemoved,
@@ -12,30 +12,41 @@ import {
12 createMultipleServers, 12 createMultipleServers,
13 doubleFollow, 13 doubleFollow,
14 killallServers, 14 killallServers,
15 makeGetRequest, 15 makeRawRequest,
16 PeerTubeServer, 16 PeerTubeServer,
17 root, 17 root,
18 saveVideoInServers,
18 setAccessTokensToServers, 19 setAccessTokensToServers,
19 wait, 20 wait,
20 waitJobs 21 waitJobs
21} from '@shared/extra-utils' 22} from '@shared/extra-utils'
22import { HttpStatusCode, VideoPrivacy, VideoRedundancyStrategy, VideoRedundancyStrategyWithManual } from '@shared/models' 23import {
24 HttpStatusCode,
25 VideoDetails,
26 VideoFile,
27 VideoPrivacy,
28 VideoRedundancyStrategy,
29 VideoRedundancyStrategyWithManual
30} from '@shared/models'
23 31
24const expect = chai.expect 32const expect = chai.expect
25 33
26let servers: PeerTubeServer[] = [] 34let servers: PeerTubeServer[] = []
27let video1Server2UUID: string 35let video1Server2: VideoDetails
28let video1Server2Id: number
29 36
30function checkMagnetWebseeds (file: { magnetUri: string, resolution: { id: number } }, baseWebseeds: string[], server: PeerTubeServer) { 37async function checkMagnetWebseeds (file: VideoFile, baseWebseeds: string[], server: PeerTubeServer) {
31 const parsed = magnetUtil.decode(file.magnetUri) 38 const parsed = magnetUtil.decode(file.magnetUri)
32 39
33 for (const ws of baseWebseeds) { 40 for (const ws of baseWebseeds) {
34 const found = parsed.urlList.find(url => url === `${ws}-${file.resolution.id}.mp4`) 41 const found = parsed.urlList.find(url => url === `${ws}${basename(file.fileUrl)}`)
35 expect(found, `Webseed ${ws} not found in ${file.magnetUri} on server ${server.url}`).to.not.be.undefined 42 expect(found, `Webseed ${ws} not found in ${file.magnetUri} on server ${server.url}`).to.not.be.undefined
36 } 43 }
37 44
38 expect(parsed.urlList).to.have.lengthOf(baseWebseeds.length) 45 expect(parsed.urlList).to.have.lengthOf(baseWebseeds.length)
46
47 for (const url of parsed.urlList) {
48 await makeRawRequest(url, HttpStatusCode.OK_200)
49 }
39} 50}
40 51
41async function createSingleServers (strategy: VideoRedundancyStrategy | null, additionalParams: any = {}, withWebtorrent = true) { 52async function createSingleServers (strategy: VideoRedundancyStrategy | null, additionalParams: any = {}, withWebtorrent = true) {
@@ -76,11 +87,10 @@ async function createSingleServers (strategy: VideoRedundancyStrategy | null, ad
76 await setAccessTokensToServers(servers) 87 await setAccessTokensToServers(servers)
77 88
78 { 89 {
79 const { uuid, id } = await servers[1].videos.upload({ attributes: { name: 'video 1 server 2' } }) 90 const { id } = await servers[1].videos.upload({ attributes: { name: 'video 1 server 2' } })
80 video1Server2UUID = uuid 91 video1Server2 = await servers[1].videos.get({ id })
81 video1Server2Id = id
82 92
83 await servers[1].videos.view({ id: video1Server2UUID }) 93 await servers[1].videos.view({ id })
84 } 94 }
85 95
86 await waitJobs(servers) 96 await waitJobs(servers)
@@ -95,11 +105,33 @@ async function createSingleServers (strategy: VideoRedundancyStrategy | null, ad
95 await waitJobs(servers) 105 await waitJobs(servers)
96} 106}
97 107
108async function ensureSameFilenames (videoUUID: string) {
109 let webtorrentFilenames: string[]
110 let hlsFilenames: string[]
111
112 for (const server of servers) {
113 const video = await server.videos.getWithToken({ id: videoUUID })
114
115 // Ensure we use the same filenames that the origin
116
117 const localWebtorrentFilenames = video.files.map(f => basename(f.fileUrl)).sort()
118 const localHLSFilenames = video.streamingPlaylists[0].files.map(f => basename(f.fileUrl)).sort()
119
120 if (webtorrentFilenames) expect(webtorrentFilenames).to.deep.equal(localWebtorrentFilenames)
121 else webtorrentFilenames = localWebtorrentFilenames
122
123 if (hlsFilenames) expect(hlsFilenames).to.deep.equal(localHLSFilenames)
124 else hlsFilenames = localHLSFilenames
125 }
126
127 return { webtorrentFilenames, hlsFilenames }
128}
129
98async function check1WebSeed (videoUUID?: string) { 130async function check1WebSeed (videoUUID?: string) {
99 if (!videoUUID) videoUUID = video1Server2UUID 131 if (!videoUUID) videoUUID = video1Server2.uuid
100 132
101 const webseeds = [ 133 const webseeds = [
102 `http://localhost:${servers[1].port}/static/webseed/${videoUUID}` 134 `http://localhost:${servers[1].port}/static/webseed/`
103 ] 135 ]
104 136
105 for (const server of servers) { 137 for (const server of servers) {
@@ -107,40 +139,31 @@ async function check1WebSeed (videoUUID?: string) {
107 const video = await server.videos.getWithToken({ id: videoUUID }) 139 const video = await server.videos.getWithToken({ id: videoUUID })
108 140
109 for (const f of video.files) { 141 for (const f of video.files) {
110 checkMagnetWebseeds(f, webseeds, server) 142 await checkMagnetWebseeds(f, webseeds, server)
111 } 143 }
112 } 144 }
145
146 await ensureSameFilenames(videoUUID)
113} 147}
114 148
115async function check2Webseeds (videoUUID?: string) { 149async function check2Webseeds (videoUUID?: string) {
116 if (!videoUUID) videoUUID = video1Server2UUID 150 if (!videoUUID) videoUUID = video1Server2.uuid
117 151
118 const webseeds = [ 152 const webseeds = [
119 `http://localhost:${servers[0].port}/static/redundancy/${videoUUID}`, 153 `http://localhost:${servers[0].port}/static/redundancy/`,
120 `http://localhost:${servers[1].port}/static/webseed/${videoUUID}` 154 `http://localhost:${servers[1].port}/static/webseed/`
121 ] 155 ]
122 156
123 for (const server of servers) { 157 for (const server of servers) {
124 const video = await server.videos.get({ id: videoUUID }) 158 const video = await server.videos.get({ id: videoUUID })
125 159
126 for (const file of video.files) { 160 for (const file of video.files) {
127 checkMagnetWebseeds(file, webseeds, server) 161 await checkMagnetWebseeds(file, webseeds, server)
128
129 await makeGetRequest({
130 url: servers[0].url,
131 expectedStatus: HttpStatusCode.OK_200,
132 path: '/static/redundancy/' + `${videoUUID}-${file.resolution.id}.mp4`,
133 contentType: null
134 })
135 await makeGetRequest({
136 url: servers[1].url,
137 expectedStatus: HttpStatusCode.OK_200,
138 path: `/static/webseed/${videoUUID}-${file.resolution.id}.mp4`,
139 contentType: null
140 })
141 } 162 }
142 } 163 }
143 164
165 const { webtorrentFilenames } = await ensureSameFilenames(videoUUID)
166
144 const directories = [ 167 const directories = [
145 'test' + servers[0].internalServerNumber + '/redundancy', 168 'test' + servers[0].internalServerNumber + '/redundancy',
146 'test' + servers[1].internalServerNumber + '/videos' 169 'test' + servers[1].internalServerNumber + '/videos'
@@ -150,14 +173,13 @@ async function check2Webseeds (videoUUID?: string) {
150 const files = await readdir(join(root(), directory)) 173 const files = await readdir(join(root(), directory))
151 expect(files).to.have.length.at.least(4) 174 expect(files).to.have.length.at.least(4)
152 175
153 for (const resolution of [ 240, 360, 480, 720 ]) { 176 // Ensure we files exist on disk
154 expect(files.find(f => f === `${videoUUID}-${resolution}.mp4`)).to.not.be.undefined 177 expect(files.find(f => webtorrentFilenames.includes(f))).to.exist
155 }
156 } 178 }
157} 179}
158 180
159async function check0PlaylistRedundancies (videoUUID?: string) { 181async function check0PlaylistRedundancies (videoUUID?: string) {
160 if (!videoUUID) videoUUID = video1Server2UUID 182 if (!videoUUID) videoUUID = video1Server2.uuid
161 183
162 for (const server of servers) { 184 for (const server of servers) {
163 // With token to avoid issues with video follow constraints 185 // With token to avoid issues with video follow constraints
@@ -167,10 +189,12 @@ async function check0PlaylistRedundancies (videoUUID?: string) {
167 expect(video.streamingPlaylists).to.have.lengthOf(1) 189 expect(video.streamingPlaylists).to.have.lengthOf(1)
168 expect(video.streamingPlaylists[0].redundancies).to.have.lengthOf(0) 190 expect(video.streamingPlaylists[0].redundancies).to.have.lengthOf(0)
169 } 191 }
192
193 await ensureSameFilenames(videoUUID)
170} 194}
171 195
172async function check1PlaylistRedundancies (videoUUID?: string) { 196async function check1PlaylistRedundancies (videoUUID?: string) {
173 if (!videoUUID) videoUUID = video1Server2UUID 197 if (!videoUUID) videoUUID = video1Server2.uuid
174 198
175 for (const server of servers) { 199 for (const server of servers) {
176 const video = await server.videos.get({ id: videoUUID }) 200 const video = await server.videos.get({ id: videoUUID })
@@ -193,6 +217,8 @@ async function check1PlaylistRedundancies (videoUUID?: string) {
193 await checkSegmentHash({ server: servers[1], baseUrlPlaylist, baseUrlSegment, videoUUID, resolution, hlsPlaylist }) 217 await checkSegmentHash({ server: servers[1], baseUrlPlaylist, baseUrlSegment, videoUUID, resolution, hlsPlaylist })
194 } 218 }
195 219
220 const { hlsFilenames } = await ensureSameFilenames(videoUUID)
221
196 const directories = [ 222 const directories = [
197 'test' + servers[0].internalServerNumber + '/redundancy/hls', 223 'test' + servers[0].internalServerNumber + '/redundancy/hls',
198 'test' + servers[1].internalServerNumber + '/streaming-playlists/hls' 224 'test' + servers[1].internalServerNumber + '/streaming-playlists/hls'
@@ -202,11 +228,8 @@ async function check1PlaylistRedundancies (videoUUID?: string) {
202 const files = await readdir(join(root(), directory, videoUUID)) 228 const files = await readdir(join(root(), directory, videoUUID))
203 expect(files).to.have.length.at.least(4) 229 expect(files).to.have.length.at.least(4)
204 230
205 for (const resolution of [ 240, 360, 480, 720 ]) { 231 // Ensure we files exist on disk
206 const filename = `${videoUUID}-${resolution}-fragmented.mp4` 232 expect(files.find(f => hlsFilenames.includes(f))).to.exist
207
208 expect(files.find(f => f === filename)).to.not.be.undefined
209 }
210 } 233 }
211} 234}
212 235
@@ -322,7 +345,7 @@ describe('Test videos redundancy', function () {
322 await check1WebSeed() 345 await check1WebSeed()
323 await check0PlaylistRedundancies() 346 await check0PlaylistRedundancies()
324 347
325 await checkVideoFilesWereRemoved(video1Server2UUID, servers[0], [ 'videos', join('playlists', 'hls') ]) 348 await checkVideoFilesWereRemoved({ server: servers[0], video: video1Server2, onlyVideoFiles: true })
326 }) 349 })
327 350
328 after(async function () { 351 after(async function () {
@@ -372,7 +395,7 @@ describe('Test videos redundancy', function () {
372 await check1WebSeed() 395 await check1WebSeed()
373 await check0PlaylistRedundancies() 396 await check0PlaylistRedundancies()
374 397
375 await checkVideoFilesWereRemoved(video1Server2UUID, servers[0], [ 'videos' ]) 398 await checkVideoFilesWereRemoved({ server: servers[0], video: video1Server2, onlyVideoFiles: true })
376 }) 399 })
377 400
378 after(async function () { 401 after(async function () {
@@ -414,8 +437,8 @@ describe('Test videos redundancy', function () {
414 it('Should view 2 times the first video to have > min_views config', async function () { 437 it('Should view 2 times the first video to have > min_views config', async function () {
415 this.timeout(80000) 438 this.timeout(80000)
416 439
417 await servers[0].videos.view({ id: video1Server2UUID }) 440 await servers[0].videos.view({ id: video1Server2.uuid })
418 await servers[2].videos.view({ id: video1Server2UUID }) 441 await servers[2].videos.view({ id: video1Server2.uuid })
419 442
420 await wait(10000) 443 await wait(10000)
421 await waitJobs(servers) 444 await waitJobs(servers)
@@ -436,12 +459,13 @@ describe('Test videos redundancy', function () {
436 it('Should remove the video and the redundancy files', async function () { 459 it('Should remove the video and the redundancy files', async function () {
437 this.timeout(20000) 460 this.timeout(20000)
438 461
439 await servers[1].videos.remove({ id: video1Server2UUID }) 462 await saveVideoInServers(servers, video1Server2.uuid)
463 await servers[1].videos.remove({ id: video1Server2.uuid })
440 464
441 await waitJobs(servers) 465 await waitJobs(servers)
442 466
443 for (const server of servers) { 467 for (const server of servers) {
444 await checkVideoFilesWereRemoved(video1Server2UUID, server) 468 await checkVideoFilesWereRemoved({ server, video: server.store.videoDetails })
445 } 469 }
446 }) 470 })
447 471
@@ -482,8 +506,8 @@ describe('Test videos redundancy', function () {
482 it('Should have 1 redundancy on the first video', async function () { 506 it('Should have 1 redundancy on the first video', async function () {
483 this.timeout(160000) 507 this.timeout(160000)
484 508
485 await servers[0].videos.view({ id: video1Server2UUID }) 509 await servers[0].videos.view({ id: video1Server2.uuid })
486 await servers[2].videos.view({ id: video1Server2UUID }) 510 await servers[2].videos.view({ id: video1Server2.uuid })
487 511
488 await wait(10000) 512 await wait(10000)
489 await waitJobs(servers) 513 await waitJobs(servers)
@@ -499,12 +523,13 @@ describe('Test videos redundancy', function () {
499 it('Should remove the video and the redundancy files', async function () { 523 it('Should remove the video and the redundancy files', async function () {
500 this.timeout(20000) 524 this.timeout(20000)
501 525
502 await servers[1].videos.remove({ id: video1Server2UUID }) 526 await saveVideoInServers(servers, video1Server2.uuid)
527 await servers[1].videos.remove({ id: video1Server2.uuid })
503 528
504 await waitJobs(servers) 529 await waitJobs(servers)
505 530
506 for (const server of servers) { 531 for (const server of servers) {
507 await checkVideoFilesWereRemoved(video1Server2UUID, server) 532 await checkVideoFilesWereRemoved({ server, video: server.store.videoDetails })
508 } 533 }
509 }) 534 })
510 535
@@ -527,7 +552,7 @@ describe('Test videos redundancy', function () {
527 }) 552 })
528 553
529 it('Should create a redundancy on first video', async function () { 554 it('Should create a redundancy on first video', async function () {
530 await servers[0].redundancy.addVideo({ videoId: video1Server2Id }) 555 await servers[0].redundancy.addVideo({ videoId: video1Server2.id })
531 }) 556 })
532 557
533 it('Should have 2 webseeds on the first video', async function () { 558 it('Should have 2 webseeds on the first video', async function () {
@@ -562,7 +587,7 @@ describe('Test videos redundancy', function () {
562 await check1WebSeed() 587 await check1WebSeed()
563 await check0PlaylistRedundancies() 588 await check0PlaylistRedundancies()
564 589
565 await checkVideoFilesWereRemoved(video1Server2UUID, servers[0], [ 'videos' ]) 590 await checkVideoFilesWereRemoved({ server: servers[0], video: video1Server2, onlyVideoFiles: true })
566 }) 591 })
567 592
568 after(async function () { 593 after(async function () {
@@ -575,7 +600,7 @@ describe('Test videos redundancy', function () {
575 600
576 async function checkContains (servers: PeerTubeServer[], str: string) { 601 async function checkContains (servers: PeerTubeServer[], str: string) {
577 for (const server of servers) { 602 for (const server of servers) {
578 const video = await server.videos.get({ id: video1Server2UUID }) 603 const video = await server.videos.get({ id: video1Server2.uuid })
579 604
580 for (const f of video.files) { 605 for (const f of video.files) {
581 expect(f.magnetUri).to.contain(str) 606 expect(f.magnetUri).to.contain(str)
@@ -585,7 +610,7 @@ describe('Test videos redundancy', function () {
585 610
586 async function checkNotContains (servers: PeerTubeServer[], str: string) { 611 async function checkNotContains (servers: PeerTubeServer[], str: string) {
587 for (const server of servers) { 612 for (const server of servers) {
588 const video = await server.videos.get({ id: video1Server2UUID }) 613 const video = await server.videos.get({ id: video1Server2.uuid })
589 614
590 for (const f of video.files) { 615 for (const f of video.files) {
591 expect(f.magnetUri).to.not.contain(str) 616 expect(f.magnetUri).to.not.contain(str)
@@ -646,8 +671,8 @@ describe('Test videos redundancy', function () {
646 await servers[0].servers.waitUntilLog('Duplicated ', 5) 671 await servers[0].servers.waitUntilLog('Duplicated ', 5)
647 await waitJobs(servers) 672 await waitJobs(servers)
648 673
649 await check2Webseeds(video1Server2UUID) 674 await check2Webseeds()
650 await check1PlaylistRedundancies(video1Server2UUID) 675 await check1PlaylistRedundancies()
651 await checkStatsWith1Redundancy(strategy) 676 await checkStatsWith1Redundancy(strategy)
652 677
653 const { uuid } = await servers[1].videos.upload({ attributes: { name: 'video 2 server 2', privacy: VideoPrivacy.PRIVATE } }) 678 const { uuid } = await servers[1].videos.upload({ attributes: { name: 'video 2 server 2', privacy: VideoPrivacy.PRIVATE } })
@@ -670,8 +695,8 @@ describe('Test videos redundancy', function () {
670 await wait(1000) 695 await wait(1000)
671 696
672 try { 697 try {
673 await check1WebSeed(video1Server2UUID) 698 await check1WebSeed()
674 await check0PlaylistRedundancies(video1Server2UUID) 699 await check0PlaylistRedundancies()
675 700
676 await check2Webseeds(video2Server2UUID) 701 await check2Webseeds(video2Server2UUID)
677 await check1PlaylistRedundancies(video2Server2UUID) 702 await check1PlaylistRedundancies(video2Server2UUID)
@@ -700,7 +725,7 @@ describe('Test videos redundancy', function () {
700 725
701 await waitJobs(servers) 726 await waitJobs(servers)
702 727
703 await checkVideoFilesWereRemoved(video1Server2UUID, servers[0], [ join('redundancy', 'hls') ]) 728 await checkVideoFilesWereRemoved({ server: servers[0], video: video1Server2, onlyVideoFiles: true })
704 }) 729 })
705 730
706 after(async function () { 731 after(async function () {
diff --git a/server/tests/api/users/users-multiple-servers.ts b/server/tests/api/users/users-multiple-servers.ts
index 225145957..16372b039 100644
--- a/server/tests/api/users/users-multiple-servers.ts
+++ b/server/tests/api/users/users-multiple-servers.ts
@@ -10,18 +10,21 @@ import {
10 createMultipleServers, 10 createMultipleServers,
11 doubleFollow, 11 doubleFollow,
12 PeerTubeServer, 12 PeerTubeServer,
13 saveVideoInServers,
13 setAccessTokensToServers, 14 setAccessTokensToServers,
14 testImage, 15 testImage,
15 waitJobs 16 waitJobs
16} from '@shared/extra-utils' 17} from '@shared/extra-utils'
17import { User } from '@shared/models' 18import { MyUser } from '@shared/models'
18 19
19const expect = chai.expect 20const expect = chai.expect
20 21
21describe('Test users with multiple servers', function () { 22describe('Test users with multiple servers', function () {
22 let servers: PeerTubeServer[] = [] 23 let servers: PeerTubeServer[] = []
23 let user: User 24
25 let user: MyUser
24 let userId: number 26 let userId: number
27
25 let videoUUID: string 28 let videoUUID: string
26 let userAccessToken: string 29 let userAccessToken: string
27 let userAvatarFilename: string 30 let userAvatarFilename: string
@@ -45,18 +48,17 @@ describe('Test users with multiple servers', function () {
45 await servers[0].videos.upload() 48 await servers[0].videos.upload()
46 49
47 { 50 {
48 const user = { 51 const username = 'user1'
49 username: 'user1', 52 const created = await servers[0].users.create({ username })
50 password: 'password'
51 }
52 const created = await servers[0].users.create(user)
53 userId = created.id 53 userId = created.id
54 userAccessToken = await servers[0].login.getAccessToken(user) 54 userAccessToken = await servers[0].login.getAccessToken(username)
55 } 55 }
56 56
57 { 57 {
58 const { uuid } = await servers[0].videos.upload({ token: userAccessToken }) 58 const { uuid } = await servers[0].videos.upload({ token: userAccessToken })
59 videoUUID = uuid 59 videoUUID = uuid
60
61 await saveVideoInServers(servers, videoUUID)
60 } 62 }
61 63
62 await waitJobs(servers) 64 await waitJobs(servers)
@@ -195,7 +197,7 @@ describe('Test users with multiple servers', function () {
195 197
196 it('Should not have video files', async () => { 198 it('Should not have video files', async () => {
197 for (const server of servers) { 199 for (const server of servers) {
198 await checkVideoFilesWereRemoved(videoUUID, server) 200 await checkVideoFilesWereRemoved({ server, video: server.store.videoDetails })
199 } 201 }
200 }) 202 })
201 203
diff --git a/server/tests/api/videos/audio-only.ts b/server/tests/api/videos/audio-only.ts
index 15c3ae6d6..7fac6e738 100644
--- a/server/tests/api/videos/audio-only.ts
+++ b/server/tests/api/videos/audio-only.ts
@@ -2,7 +2,6 @@
2 2
3import 'mocha' 3import 'mocha'
4import * as chai from 'chai' 4import * as chai from 'chai'
5import { join } from 'path'
6import { getAudioStream, getVideoStreamSize } from '@server/helpers/ffprobe-utils' 5import { getAudioStream, getVideoStreamSize } from '@server/helpers/ffprobe-utils'
7import { cleanupTests, createMultipleServers, doubleFollow, PeerTubeServer, setAccessTokensToServers, waitJobs } from '@shared/extra-utils' 6import { cleanupTests, createMultipleServers, doubleFollow, PeerTubeServer, setAccessTokensToServers, waitJobs } from '@shared/extra-utils'
8 7
@@ -11,6 +10,8 @@ const expect = chai.expect
11describe('Test audio only video transcoding', function () { 10describe('Test audio only video transcoding', function () {
12 let servers: PeerTubeServer[] = [] 11 let servers: PeerTubeServer[] = []
13 let videoUUID: string 12 let videoUUID: string
13 let webtorrentAudioFileUrl: string
14 let fragmentedAudioFileUrl: string
14 15
15 before(async function () { 16 before(async function () {
16 this.timeout(120000) 17 this.timeout(120000)
@@ -63,13 +64,18 @@ describe('Test audio only video transcoding', function () {
63 expect(files[1].resolution.id).to.equal(240) 64 expect(files[1].resolution.id).to.equal(240)
64 expect(files[2].resolution.id).to.equal(0) 65 expect(files[2].resolution.id).to.equal(0)
65 } 66 }
67
68 if (server.serverNumber === 1) {
69 webtorrentAudioFileUrl = video.files[2].fileUrl
70 fragmentedAudioFileUrl = video.streamingPlaylists[0].files[2].fileUrl
71 }
66 } 72 }
67 }) 73 })
68 74
69 it('0p transcoded video should not have video', async function () { 75 it('0p transcoded video should not have video', async function () {
70 const paths = [ 76 const paths = [
71 servers[0].servers.buildDirectory(join('videos', videoUUID + '-0.mp4')), 77 servers[0].servers.buildWebTorrentFilePath(webtorrentAudioFileUrl),
72 servers[0].servers.buildDirectory(join('streaming-playlists', 'hls', videoUUID, videoUUID + '-0-fragmented.mp4')) 78 servers[0].servers.buildFragmentedFilePath(videoUUID, fragmentedAudioFileUrl)
73 ] 79 ]
74 80
75 for (const path of paths) { 81 for (const path of paths) {
diff --git a/server/tests/api/videos/multiple-servers.ts b/server/tests/api/videos/multiple-servers.ts
index d916abb09..f9220e4b3 100644
--- a/server/tests/api/videos/multiple-servers.ts
+++ b/server/tests/api/videos/multiple-servers.ts
@@ -13,6 +13,7 @@ import {
13 dateIsValid, 13 dateIsValid,
14 doubleFollow, 14 doubleFollow,
15 PeerTubeServer, 15 PeerTubeServer,
16 saveVideoInServers,
16 setAccessTokensToServers, 17 setAccessTokensToServers,
17 testImage, 18 testImage,
18 wait, 19 wait,
@@ -661,19 +662,19 @@ describe('Test multiple servers', function () {
661 } 662 }
662 }) 663 })
663 664
664 it('Should remove the videos 3 and 3-2 by asking server 3', async function () { 665 it('Should remove the videos 3 and 3-2 by asking server 3 and correctly delete files', async function () {
665 this.timeout(10000) 666 this.timeout(30000)
666 667
667 await servers[2].videos.remove({ id: toRemove[0].id }) 668 for (const id of [ toRemove[0].id, toRemove[1].id ]) {
668 await servers[2].videos.remove({ id: toRemove[1].id }) 669 await saveVideoInServers(servers, id)
669 670
670 await waitJobs(servers) 671 await servers[2].videos.remove({ id })
671 })
672 672
673 it('Should not have files of videos 3 and 3-2 on each server', async function () { 673 await waitJobs(servers)
674 for (const server of servers) { 674
675 await checkVideoFilesWereRemoved(toRemove[0].uuid, server) 675 for (const server of servers) {
676 await checkVideoFilesWereRemoved(toRemove[1].uuid, server) 676 await checkVideoFilesWereRemoved({ server, video: server.store.videoDetails })
677 }
677 } 678 }
678 }) 679 })
679 680
diff --git a/server/tests/api/videos/resumable-upload.ts b/server/tests/api/videos/resumable-upload.ts
index a2d60eeec..c94d92cf2 100644
--- a/server/tests/api/videos/resumable-upload.ts
+++ b/server/tests/api/videos/resumable-upload.ts
@@ -99,8 +99,8 @@ describe('Test resumable upload', function () {
99 this.timeout(30000) 99 this.timeout(30000)
100 100
101 server = await createSingleServer(1) 101 server = await createSingleServer(1)
102 await setAccessTokensToServers([server]) 102 await setAccessTokensToServers([ server ])
103 await setDefaultVideoChannel([server]) 103 await setDefaultVideoChannel([ server ])
104 104
105 const body = await server.users.getMyInfo() 105 const body = await server.users.getMyInfo()
106 rootId = body.id 106 rootId = body.id
@@ -170,13 +170,13 @@ describe('Test resumable upload', function () {
170 170
171 const size = 1000 171 const size = 1000
172 172
173 const contentRangeBuilder = start => `bytes ${start}-${start + size - 1}/${size}` 173 const contentRangeBuilder = (start: number) => `bytes ${start}-${start + size - 1}/${size}`
174 await sendChunks({ pathUploadId: uploadId, expectedStatus: HttpStatusCode.CONFLICT_409, contentRangeBuilder, contentLength: size }) 174 await sendChunks({ pathUploadId: uploadId, expectedStatus: HttpStatusCode.CONFLICT_409, contentRangeBuilder, contentLength: size })
175 await checkFileSize(uploadId, 0) 175 await checkFileSize(uploadId, 0)
176 }) 176 })
177 }) 177 })
178 178
179 after(async function () { 179 after(async function () {
180 await cleanupTests([server]) 180 await cleanupTests([ server ])
181 }) 181 })
182}) 182})
diff --git a/server/tests/api/videos/single-server.ts b/server/tests/api/videos/single-server.ts
index c0535be09..29dac6ec1 100644
--- a/server/tests/api/videos/single-server.ts
+++ b/server/tests/api/videos/single-server.ts
@@ -199,9 +199,10 @@ describe('Test a single server', function () {
199 }) 199 })
200 200
201 it('Should remove the video', async function () { 201 it('Should remove the video', async function () {
202 const video = await server.videos.get({ id: videoId })
202 await server.videos.remove({ id: videoId }) 203 await server.videos.remove({ id: videoId })
203 204
204 await checkVideoFilesWereRemoved(videoUUID, server) 205 await checkVideoFilesWereRemoved({ video, server })
205 }) 206 })
206 207
207 it('Should not have videos', async function () { 208 it('Should not have videos', async function () {
diff --git a/server/tests/api/videos/video-captions.ts b/server/tests/api/videos/video-captions.ts
index 4c8e28adf..3bb0d131c 100644
--- a/server/tests/api/videos/video-captions.ts
+++ b/server/tests/api/videos/video-captions.ts
@@ -178,9 +178,12 @@ describe('Test video captions', function () {
178 }) 178 })
179 179
180 it('Should remove the video, and thus all video captions', async function () { 180 it('Should remove the video, and thus all video captions', async function () {
181 const video = await servers[0].videos.get({ id: videoUUID })
182 const { data: captions } = await servers[0].captions.list({ videoId: videoUUID })
183
181 await servers[0].videos.remove({ id: videoUUID }) 184 await servers[0].videos.remove({ id: videoUUID })
182 185
183 await checkVideoFilesWereRemoved(videoUUID, servers[0]) 186 await checkVideoFilesWereRemoved({ server: servers[0], video, captions })
184 }) 187 })
185 188
186 after(async function () { 189 after(async function () {
diff --git a/server/tests/api/videos/video-change-ownership.ts b/server/tests/api/videos/video-change-ownership.ts
index 6ae6d3004..d6665fe4e 100644
--- a/server/tests/api/videos/video-change-ownership.ts
+++ b/server/tests/api/videos/video-change-ownership.ts
@@ -73,7 +73,7 @@ describe('Test video change ownership - nominal', function () {
73 } 73 }
74 const { id } = await servers[0].videos.upload({ token: firstUserToken, attributes }) 74 const { id } = await servers[0].videos.upload({ token: firstUserToken, attributes })
75 75
76 servers[0].store.video = await servers[0].videos.get({ id }) 76 servers[0].store.videoCreated = await servers[0].videos.get({ id })
77 } 77 }
78 78
79 { 79 {
@@ -109,7 +109,7 @@ describe('Test video change ownership - nominal', function () {
109 it('Should send a request to change ownership of a video', async function () { 109 it('Should send a request to change ownership of a video', async function () {
110 this.timeout(15000) 110 this.timeout(15000)
111 111
112 await command.create({ token: firstUserToken, videoId: servers[0].store.video.id, username: secondUser }) 112 await command.create({ token: firstUserToken, videoId: servers[0].store.videoCreated.id, username: secondUser })
113 }) 113 })
114 114
115 it('Should only return a request to change ownership for the second user', async function () { 115 it('Should only return a request to change ownership for the second user', async function () {
@@ -135,7 +135,7 @@ describe('Test video change ownership - nominal', function () {
135 it('Should accept the same change ownership request without crashing', async function () { 135 it('Should accept the same change ownership request without crashing', async function () {
136 this.timeout(10000) 136 this.timeout(10000)
137 137
138 await command.create({ token: firstUserToken, videoId: servers[0].store.video.id, username: secondUser }) 138 await command.create({ token: firstUserToken, videoId: servers[0].store.videoCreated.id, username: secondUser })
139 }) 139 })
140 140
141 it('Should not create multiple change ownership requests while one is waiting', async function () { 141 it('Should not create multiple change ownership requests while one is waiting', async function () {
@@ -163,7 +163,7 @@ describe('Test video change ownership - nominal', function () {
163 it('Should send a new request to change ownership of a video', async function () { 163 it('Should send a new request to change ownership of a video', async function () {
164 this.timeout(15000) 164 this.timeout(15000)
165 165
166 await command.create({ token: firstUserToken, videoId: servers[0].store.video.id, username: secondUser }) 166 await command.create({ token: firstUserToken, videoId: servers[0].store.videoCreated.id, username: secondUser })
167 }) 167 })
168 168
169 it('Should return two requests to change ownership for the second user', async function () { 169 it('Should return two requests to change ownership for the second user', async function () {
@@ -207,7 +207,7 @@ describe('Test video change ownership - nominal', function () {
207 207
208 it('Should have the channel of the video updated', async function () { 208 it('Should have the channel of the video updated', async function () {
209 for (const server of servers) { 209 for (const server of servers) {
210 const video = await server.videos.get({ id: servers[0].store.video.uuid }) 210 const video = await server.videos.get({ id: servers[0].store.videoCreated.uuid })
211 211
212 expect(video.name).to.equal('my super name') 212 expect(video.name).to.equal('my super name')
213 expect(video.channel.displayName).to.equal('Main second channel') 213 expect(video.channel.displayName).to.equal('Main second channel')
@@ -236,7 +236,7 @@ describe('Test video change ownership - nominal', function () {
236 await waitJobs(servers) 236 await waitJobs(servers)
237 237
238 for (const server of servers) { 238 for (const server of servers) {
239 const video = await server.videos.get({ id: servers[0].store.video.uuid }) 239 const video = await server.videos.get({ id: servers[0].store.videoCreated.uuid })
240 240
241 expect(video.name).to.equal('my super name') 241 expect(video.name).to.equal('my super name')
242 expect(video.channel.displayName).to.equal('Main second channel') 242 expect(video.channel.displayName).to.equal('Main second channel')
@@ -282,13 +282,13 @@ describe('Test video change ownership - quota too small', function () {
282 const { data } = await server.videos.list() 282 const { data } = await server.videos.list()
283 expect(data.length).to.equal(1) 283 expect(data.length).to.equal(1)
284 284
285 server.store.video = data.find(video => video.name === 'my super name') 285 server.store.videoCreated = data.find(video => video.name === 'my super name')
286 }) 286 })
287 287
288 it('Should send a request to change ownership of a video', async function () { 288 it('Should send a request to change ownership of a video', async function () {
289 this.timeout(15000) 289 this.timeout(15000)
290 290
291 await server.changeOwnership.create({ token: firstUserToken, videoId: server.store.video.id, username: secondUser }) 291 await server.changeOwnership.create({ token: firstUserToken, videoId: server.store.videoCreated.id, username: secondUser })
292 }) 292 })
293 293
294 it('Should only return a request to change ownership for the second user', async function () { 294 it('Should only return a request to change ownership for the second user', async function () {
diff --git a/server/tests/api/videos/video-hls.ts b/server/tests/api/videos/video-hls.ts
index 7845f7334..921d7ce64 100644
--- a/server/tests/api/videos/video-hls.ts
+++ b/server/tests/api/videos/video-hls.ts
@@ -19,6 +19,8 @@ import {
19} from '@shared/extra-utils' 19} from '@shared/extra-utils'
20import { HttpStatusCode, VideoStreamingPlaylistType } from '@shared/models' 20import { HttpStatusCode, VideoStreamingPlaylistType } from '@shared/models'
21import { DEFAULT_AUDIO_RESOLUTION } from '../../../initializers/constants' 21import { DEFAULT_AUDIO_RESOLUTION } from '../../../initializers/constants'
22import { uuidRegex } from '@shared/core-utils'
23import { basename } from 'path/posix'
22 24
23const expect = chai.expect 25const expect = chai.expect
24 26
@@ -38,14 +40,17 @@ async function checkHlsPlaylist (servers: PeerTubeServer[], videoUUID: string, h
38 if (hlsOnly) expect(videoDetails.files).to.have.lengthOf(0) 40 if (hlsOnly) expect(videoDetails.files).to.have.lengthOf(0)
39 else expect(videoDetails.files).to.have.lengthOf(resolutions.length) 41 else expect(videoDetails.files).to.have.lengthOf(resolutions.length)
40 42
43 // Check JSON files
41 for (const resolution of resolutions) { 44 for (const resolution of resolutions) {
42 const file = hlsFiles.find(f => f.resolution.id === resolution) 45 const file = hlsFiles.find(f => f.resolution.id === resolution)
43 expect(file).to.not.be.undefined 46 expect(file).to.not.be.undefined
44 47
45 expect(file.magnetUri).to.have.lengthOf.above(2) 48 expect(file.magnetUri).to.have.lengthOf.above(2)
46 expect(file.torrentUrl).to.equal(`http://${server.host}/lazy-static/torrents/${videoDetails.uuid}-${file.resolution.id}-hls.torrent`) 49 expect(file.torrentUrl).to.match(
47 expect(file.fileUrl).to.equal( 50 new RegExp(`http://${server.host}/lazy-static/torrents/${uuidRegex}-${file.resolution.id}-hls.torrent`)
48 `${baseUrl}/static/streaming-playlists/hls/${videoDetails.uuid}/${videoDetails.uuid}-${file.resolution.id}-fragmented.mp4` 51 )
52 expect(file.fileUrl).to.match(
53 new RegExp(`${baseUrl}/static/streaming-playlists/hls/${videoDetails.uuid}/${uuidRegex}-${file.resolution.id}-fragmented.mp4`)
49 ) 54 )
50 expect(file.resolution.label).to.equal(resolution + 'p') 55 expect(file.resolution.label).to.equal(resolution + 'p')
51 56
@@ -58,6 +63,7 @@ async function checkHlsPlaylist (servers: PeerTubeServer[], videoUUID: string, h
58 expect(torrent.files[0].path).to.exist.and.to.not.equal('') 63 expect(torrent.files[0].path).to.exist.and.to.not.equal('')
59 } 64 }
60 65
66 // Check master playlist
61 { 67 {
62 await checkResolutionsInMasterPlaylist({ server, playlistUrl: hlsPlaylist.playlistUrl, resolutions }) 68 await checkResolutionsInMasterPlaylist({ server, playlistUrl: hlsPlaylist.playlistUrl, resolutions })
63 69
@@ -69,13 +75,16 @@ async function checkHlsPlaylist (servers: PeerTubeServer[], videoUUID: string, h
69 } 75 }
70 } 76 }
71 77
78 // Check resolution playlists
72 { 79 {
73 for (const resolution of resolutions) { 80 for (const resolution of resolutions) {
74 const subPlaylist = await server.streamingPlaylists.get({ 81 const subPlaylist = await server.streamingPlaylists.get({
75 url: `${baseUrl}/static/streaming-playlists/hls/${videoUUID}/${resolution}.m3u8` 82 url: `${baseUrl}/static/streaming-playlists/hls/${videoUUID}/${resolution}.m3u8`
76 }) 83 })
77 84
78 expect(subPlaylist).to.contain(`${videoUUID}-${resolution}-fragmented.mp4`) 85 const file = hlsFiles.find(f => f.resolution.id === resolution)
86 expect(subPlaylist).to.match(new RegExp(`${uuidRegex}-${resolution}-fragmented.mp4`))
87 expect(subPlaylist).to.contain(basename(file.fileUrl))
79 } 88 }
80 } 89 }
81 90
diff --git a/server/tests/api/videos/video-transcoder.ts b/server/tests/api/videos/video-transcoder.ts
index e4892bb24..2a09e95bf 100644
--- a/server/tests/api/videos/video-transcoder.ts
+++ b/server/tests/api/videos/video-transcoder.ts
@@ -3,7 +3,6 @@
3import 'mocha' 3import 'mocha'
4import * as chai from 'chai' 4import * as chai from 'chai'
5import { omit } from 'lodash' 5import { omit } from 'lodash'
6import { join } from 'path'
7import { 6import {
8 buildAbsoluteFixturePath, 7 buildAbsoluteFixturePath,
9 cleanupTests, 8 cleanupTests,
@@ -11,6 +10,7 @@ import {
11 doubleFollow, 10 doubleFollow,
12 generateHighBitrateVideo, 11 generateHighBitrateVideo,
13 generateVideoWithFramerate, 12 generateVideoWithFramerate,
13 getFileSize,
14 makeGetRequest, 14 makeGetRequest,
15 PeerTubeServer, 15 PeerTubeServer,
16 setAccessTokensToServers, 16 setAccessTokensToServers,
@@ -271,7 +271,8 @@ describe('Test video transcoding', function () {
271 271
272 expect(videoDetails.files).to.have.lengthOf(4) 272 expect(videoDetails.files).to.have.lengthOf(4)
273 273
274 const path = servers[1].servers.buildDirectory(join('videos', video.uuid + '-240.mp4')) 274 const file = videoDetails.files.find(f => f.resolution.id === 240)
275 const path = servers[1].servers.buildWebTorrentFilePath(file.fileUrl)
275 const probe = await getAudioStream(path) 276 const probe = await getAudioStream(path)
276 277
277 if (probe.audioStream) { 278 if (probe.audioStream) {
@@ -300,8 +301,9 @@ describe('Test video transcoding', function () {
300 const video = data.find(v => v.name === attributes.name) 301 const video = data.find(v => v.name === attributes.name)
301 const videoDetails = await server.videos.get({ id: video.id }) 302 const videoDetails = await server.videos.get({ id: video.id })
302 303
303 expect(videoDetails.files).to.have.lengthOf(4) 304 const file = videoDetails.files.find(f => f.resolution.id === 240)
304 const path = servers[1].servers.buildDirectory(join('videos', video.uuid + '-240.mp4')) 305 const path = servers[1].servers.buildWebTorrentFilePath(file.fileUrl)
306
305 const probe = await getAudioStream(path) 307 const probe = await getAudioStream(path)
306 expect(probe).to.not.have.property('audioStream') 308 expect(probe).to.not.have.property('audioStream')
307 } 309 }
@@ -328,7 +330,9 @@ describe('Test video transcoding', function () {
328 330
329 const fixturePath = buildAbsoluteFixturePath(attributes.fixture) 331 const fixturePath = buildAbsoluteFixturePath(attributes.fixture)
330 const fixtureVideoProbe = await getAudioStream(fixturePath) 332 const fixtureVideoProbe = await getAudioStream(fixturePath)
331 const path = servers[1].servers.buildDirectory(join('videos', video.uuid + '-240.mp4')) 333
334 const file = videoDetails.files.find(f => f.resolution.id === 240)
335 const path = servers[1].servers.buildWebTorrentFilePath(file.fileUrl)
332 336
333 const videoProbe = await getAudioStream(path) 337 const videoProbe = await getAudioStream(path)
334 338
@@ -485,14 +489,16 @@ describe('Test video transcoding', function () {
485 expect(videoDetails.files[2].fps).to.be.below(31) 489 expect(videoDetails.files[2].fps).to.be.below(31)
486 expect(videoDetails.files[3].fps).to.be.below(31) 490 expect(videoDetails.files[3].fps).to.be.below(31)
487 491
488 for (const resolution of [ '240', '360', '480' ]) { 492 for (const resolution of [ 240, 360, 480 ]) {
489 const path = servers[1].servers.buildDirectory(join('videos', video.uuid + '-' + resolution + '.mp4')) 493 const file = videoDetails.files.find(f => f.resolution.id === resolution)
494 const path = servers[1].servers.buildWebTorrentFilePath(file.fileUrl)
490 const fps = await getVideoFileFPS(path) 495 const fps = await getVideoFileFPS(path)
491 496
492 expect(fps).to.be.below(31) 497 expect(fps).to.be.below(31)
493 } 498 }
494 499
495 const path = servers[1].servers.buildDirectory(join('videos', video.uuid + '-720.mp4')) 500 const file = videoDetails.files.find(f => f.resolution.id === 720)
501 const path = servers[1].servers.buildWebTorrentFilePath(file.fileUrl)
496 const fps = await getVideoFileFPS(path) 502 const fps = await getVideoFileFPS(path)
497 503
498 expect(fps).to.be.above(58).and.below(62) 504 expect(fps).to.be.above(58).and.below(62)
@@ -524,16 +530,19 @@ describe('Test video transcoding', function () {
524 for (const server of servers) { 530 for (const server of servers) {
525 const { data } = await server.videos.list() 531 const { data } = await server.videos.list()
526 532
527 const video = data.find(v => v.name === attributes.name) 533 const { id } = data.find(v => v.name === attributes.name)
534 const video = await server.videos.get({ id })
528 535
529 { 536 {
530 const path = servers[1].servers.buildDirectory(join('videos', video.uuid + '-240.mp4')) 537 const file = video.files.find(f => f.resolution.id === 240)
538 const path = servers[1].servers.buildWebTorrentFilePath(file.fileUrl)
531 const fps = await getVideoFileFPS(path) 539 const fps = await getVideoFileFPS(path)
532 expect(fps).to.be.equal(25) 540 expect(fps).to.be.equal(25)
533 } 541 }
534 542
535 { 543 {
536 const path = servers[1].servers.buildDirectory(join('videos', video.uuid + '-720.mp4')) 544 const file = video.files.find(f => f.resolution.id === 720)
545 const path = servers[1].servers.buildWebTorrentFilePath(file.fileUrl)
537 const fps = await getVideoFileFPS(path) 546 const fps = await getVideoFileFPS(path)
538 expect(fps).to.be.equal(59) 547 expect(fps).to.be.equal(59)
539 } 548 }
@@ -542,6 +551,7 @@ describe('Test video transcoding', function () {
542 }) 551 })
543 552
544 describe('Bitrate control', function () { 553 describe('Bitrate control', function () {
554
545 it('Should respect maximum bitrate values', async function () { 555 it('Should respect maximum bitrate values', async function () {
546 this.timeout(160_000) 556 this.timeout(160_000)
547 557
@@ -567,17 +577,19 @@ describe('Test video transcoding', function () {
567 for (const server of servers) { 577 for (const server of servers) {
568 const { data } = await server.videos.list() 578 const { data } = await server.videos.list()
569 579
570 const video = data.find(v => v.name === attributes.name) 580 const { id } = data.find(v => v.name === attributes.name)
581 const video = await server.videos.get({ id })
571 582
572 for (const resolution of [ '240', '360', '480', '720', '1080' ]) { 583 for (const resolution of [ 240, 360, 480, 720, 1080 ]) {
573 const path = servers[1].servers.buildDirectory(join('videos', video.uuid + '-' + resolution + '.mp4')) 584 const file = video.files.find(f => f.resolution.id === resolution)
585 const path = servers[1].servers.buildWebTorrentFilePath(file.fileUrl)
574 586
575 const bitrate = await getVideoFileBitrate(path) 587 const bitrate = await getVideoFileBitrate(path)
576 const fps = await getVideoFileFPS(path) 588 const fps = await getVideoFileFPS(path)
577 const resolution2 = await getVideoFileResolution(path) 589 const { videoFileResolution } = await getVideoFileResolution(path)
578 590
579 expect(resolution2.videoFileResolution.toString()).to.equal(resolution) 591 expect(videoFileResolution).to.equal(resolution)
580 expect(bitrate).to.be.below(getMaxBitrate(resolution2.videoFileResolution, fps, VIDEO_TRANSCODING_FPS)) 592 expect(bitrate).to.be.below(getMaxBitrate(videoFileResolution, fps, VIDEO_TRANSCODING_FPS))
581 } 593 }
582 } 594 }
583 }) 595 })
@@ -608,14 +620,18 @@ describe('Test video transcoding', function () {
608 fixture: 'low-bitrate.mp4' 620 fixture: 'low-bitrate.mp4'
609 } 621 }
610 622
611 const { uuid } = await servers[1].videos.upload({ attributes }) 623 const { id } = await servers[1].videos.upload({ attributes })
612 624
613 await waitJobs(servers) 625 await waitJobs(servers)
614 626
627 const video = await servers[1].videos.get({ id })
628
615 const resolutions = [ 240, 360, 480, 720, 1080 ] 629 const resolutions = [ 240, 360, 480, 720, 1080 ]
616 for (const r of resolutions) { 630 for (const r of resolutions) {
617 const path = `videos/${uuid}-${r}.mp4` 631 const file = video.files.find(f => f.resolution.id === r)
618 const size = await servers[1].servers.getServerFileSize(path) 632
633 const path = servers[1].servers.buildWebTorrentFilePath(file.fileUrl)
634 const size = await getFileSize(path)
619 expect(size, `${path} not below ${60_000}`).to.be.below(60_000) 635 expect(size, `${path} not below ${60_000}`).to.be.below(60_000)
620 } 636 }
621 }) 637 })
@@ -630,7 +646,9 @@ describe('Test video transcoding', function () {
630 await waitJobs(servers) 646 await waitJobs(servers)
631 647
632 { 648 {
633 const path = servers[1].servers.buildDirectory(join('videos', videoUUID + '-240.mp4')) 649 const video = await servers[1].videos.get({ id: videoUUID })
650 const file = video.files.find(f => f.resolution.id === 240)
651 const path = servers[1].servers.buildWebTorrentFilePath(file.fileUrl)
634 const metadata = await getMetadataFromFile(path) 652 const metadata = await getMetadataFromFile(path)
635 653
636 // expected format properties 654 // expected format properties
diff --git a/server/tests/plugins/plugin-helpers.ts b/server/tests/plugins/plugin-helpers.ts
index 242994273..5d16b28a4 100644
--- a/server/tests/plugins/plugin-helpers.ts
+++ b/server/tests/plugins/plugin-helpers.ts
@@ -232,7 +232,7 @@ describe('Test plugin helpers', function () {
232 this.timeout(40000) 232 this.timeout(40000)
233 233
234 // Should not throw -> video exists 234 // Should not throw -> video exists
235 await servers[0].videos.get({ id: videoUUID }) 235 const video = await servers[0].videos.get({ id: videoUUID })
236 // Should delete the video 236 // Should delete the video
237 await servers[0].videos.view({ id: videoUUID }) 237 await servers[0].videos.view({ id: videoUUID })
238 238
@@ -246,7 +246,7 @@ describe('Test plugin helpers', function () {
246 if (err.message.includes('exists')) throw err 246 if (err.message.includes('exists')) throw err
247 } 247 }
248 248
249 await checkVideoFilesWereRemoved(videoUUID, servers[0]) 249 await checkVideoFilesWereRemoved({ server: servers[0], video })
250 }) 250 })
251 251
252 it('Should have fetched the video by URL', async function () { 252 it('Should have fetched the video by URL', async function () {
diff --git a/shared/core-utils/miscs/index.ts b/shared/core-utils/miscs/index.ts
index afd147f24..7764e69ad 100644
--- a/shared/core-utils/miscs/index.ts
+++ b/shared/core-utils/miscs/index.ts
@@ -1,3 +1,4 @@
1export * from './date' 1export * from './date'
2export * from './miscs' 2export * from './miscs'
3export * from './types' 3export * from './types'
4export * from './regexp'
diff --git a/shared/core-utils/miscs/regexp.ts b/shared/core-utils/miscs/regexp.ts
new file mode 100644
index 000000000..862b8e00f
--- /dev/null
+++ b/shared/core-utils/miscs/regexp.ts
@@ -0,0 +1 @@
export const uuidRegex = '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}'
diff --git a/shared/extra-utils/server/server.ts b/shared/extra-utils/server/server.ts
index 5bdcbac52..d37a7f39c 100644
--- a/shared/extra-utils/server/server.ts
+++ b/shared/extra-utils/server/server.ts
@@ -3,7 +3,7 @@ import { copy } from 'fs-extra'
3import { join } from 'path' 3import { join } from 'path'
4import { root } from '@server/helpers/core-utils' 4import { root } from '@server/helpers/core-utils'
5import { randomInt } from '../../core-utils/miscs/miscs' 5import { randomInt } from '../../core-utils/miscs/miscs'
6import { VideoChannel } from '../../models/videos' 6import { Video, VideoChannel, VideoCreateResult, VideoDetails } from '../../models/videos'
7import { BulkCommand } from '../bulk' 7import { BulkCommand } from '../bulk'
8import { CLICommand } from '../cli' 8import { CLICommand } from '../cli'
9import { CustomPagesCommand } from '../custom-pages' 9import { CustomPagesCommand } from '../custom-pages'
@@ -75,19 +75,9 @@ export class PeerTubeServer {
75 75
76 channel?: VideoChannel 76 channel?: VideoChannel
77 77
78 video?: { 78 video?: Video
79 id: number 79 videoCreated?: VideoCreateResult
80 uuid: string 80 videoDetails?: VideoDetails
81 shortUUID: string
82 name?: string
83 url?: string
84
85 account?: {
86 name: string
87 }
88
89 embedPath?: string
90 }
91 81
92 videos?: { id: number, uuid: string }[] 82 videos?: { id: number, uuid: string }[]
93 } 83 }
diff --git a/shared/extra-utils/server/servers-command.ts b/shared/extra-utils/server/servers-command.ts
index a78921f2a..441c728c1 100644
--- a/shared/extra-utils/server/servers-command.ts
+++ b/shared/extra-utils/server/servers-command.ts
@@ -1,6 +1,7 @@
1import { exec } from 'child_process' 1import { exec } from 'child_process'
2import { copy, ensureDir, readFile, remove } from 'fs-extra' 2import { copy, ensureDir, readFile, remove } from 'fs-extra'
3import { join } from 'path' 3import { join } from 'path'
4import { basename } from 'path/posix'
4import { root } from '@server/helpers/core-utils' 5import { root } from '@server/helpers/core-utils'
5import { HttpStatusCode } from '@shared/models' 6import { HttpStatusCode } from '@shared/models'
6import { getFileSize, isGithubCI, wait } from '../miscs' 7import { getFileSize, isGithubCI, wait } from '../miscs'
@@ -72,6 +73,14 @@ export class ServersCommand extends AbstractCommand {
72 return join(root(), 'test' + this.server.internalServerNumber, directory) 73 return join(root(), 'test' + this.server.internalServerNumber, directory)
73 } 74 }
74 75
76 buildWebTorrentFilePath (fileUrl: string) {
77 return this.buildDirectory(join('videos', basename(fileUrl)))
78 }
79
80 buildFragmentedFilePath (videoUUID: string, fileUrl: string) {
81 return this.buildDirectory(join('streaming-playlists', 'hls', videoUUID, basename(fileUrl)))
82 }
83
75 async getServerFileSize (subPath: string) { 84 async getServerFileSize (subPath: string) {
76 const path = this.server.servers.buildDirectory(subPath) 85 const path = this.server.servers.buildDirectory(subPath)
77 86
diff --git a/shared/extra-utils/videos/streaming-playlists.ts b/shared/extra-utils/videos/streaming-playlists.ts
index 1ae3fefc1..db40c27be 100644
--- a/shared/extra-utils/videos/streaming-playlists.ts
+++ b/shared/extra-utils/videos/streaming-playlists.ts
@@ -1,4 +1,5 @@
1import { expect } from 'chai' 1import { expect } from 'chai'
2import { basename } from 'path'
2import { sha256 } from '@server/helpers/core-utils' 3import { sha256 } from '@server/helpers/core-utils'
3import { HttpStatusCode, VideoStreamingPlaylist } from '@shared/models' 4import { HttpStatusCode, VideoStreamingPlaylist } from '@shared/models'
4import { PeerTubeServer } from '../server' 5import { PeerTubeServer } from '../server'
@@ -16,7 +17,8 @@ async function checkSegmentHash (options: {
16 17
17 const playlist = await command.get({ url: `${baseUrlPlaylist}/${videoUUID}/${resolution}.m3u8` }) 18 const playlist = await command.get({ url: `${baseUrlPlaylist}/${videoUUID}/${resolution}.m3u8` })
18 19
19 const videoName = `${videoUUID}-${resolution}-fragmented.mp4` 20 const file = hlsPlaylist.files.find(f => f.resolution.id === resolution)
21 const videoName = basename(file.fileUrl)
20 22
21 const matches = /#EXT-X-BYTERANGE:(\d+)@(\d+)/.exec(playlist) 23 const matches = /#EXT-X-BYTERANGE:(\d+)@(\d+)/.exec(playlist)
22 24
diff --git a/shared/extra-utils/videos/videos.ts b/shared/extra-utils/videos/videos.ts
index 9a9bfb3cf..a1d2ba0fc 100644
--- a/shared/extra-utils/videos/videos.ts
+++ b/shared/extra-utils/videos/videos.ts
@@ -2,9 +2,10 @@
2 2
3import { expect } from 'chai' 3import { expect } from 'chai'
4import { pathExists, readdir } from 'fs-extra' 4import { pathExists, readdir } from 'fs-extra'
5import { join } from 'path' 5import { basename, join } from 'path'
6import { getLowercaseExtension } from '@server/helpers/core-utils' 6import { getLowercaseExtension } from '@server/helpers/core-utils'
7import { HttpStatusCode } from '@shared/models' 7import { uuidRegex } from '@shared/core-utils'
8import { HttpStatusCode, VideoCaption, VideoDetails } from '@shared/models'
8import { VIDEO_CATEGORIES, VIDEO_LANGUAGES, VIDEO_LICENCES, VIDEO_PRIVACIES } from '../../../server/initializers/constants' 9import { VIDEO_CATEGORIES, VIDEO_LANGUAGES, VIDEO_LICENCES, VIDEO_PRIVACIES } from '../../../server/initializers/constants'
9import { dateIsValid, testImage, webtorrentAdd } from '../miscs' 10import { dateIsValid, testImage, webtorrentAdd } from '../miscs'
10import { makeRawRequest } from '../requests/requests' 11import { makeRawRequest } from '../requests/requests'
@@ -12,33 +13,66 @@ import { waitJobs } from '../server'
12import { PeerTubeServer } from '../server/server' 13import { PeerTubeServer } from '../server/server'
13import { VideoEdit } from './videos-command' 14import { VideoEdit } from './videos-command'
14 15
15async function checkVideoFilesWereRemoved ( 16async function checkVideoFilesWereRemoved (options: {
16 videoUUID: string, 17 server: PeerTubeServer
17 server: PeerTubeServer, 18 video: VideoDetails
18 directories = [ 19 captions?: VideoCaption[]
19 'redundancy', 20 onlyVideoFiles?: boolean // default false
20 'videos', 21}) {
21 'thumbnails', 22 const { video, server, captions = [], onlyVideoFiles = false } = options
22 'torrents', 23
23 'previews', 24 const webtorrentFiles = video.files || []
24 'captions', 25 const hlsFiles = video.streamingPlaylists[0]?.files || []
25 join('playlists', 'hls'), 26
26 join('redundancy', 'hls') 27 const thumbnailName = basename(video.thumbnailPath)
27 ] 28 const previewName = basename(video.previewPath)
28) { 29
29 for (const directory of directories) { 30 const torrentNames = webtorrentFiles.concat(hlsFiles).map(f => basename(f.torrentUrl))
31
32 const captionNames = captions.map(c => basename(c.captionPath))
33
34 const webtorrentFilenames = webtorrentFiles.map(f => basename(f.fileUrl))
35 const hlsFilenames = hlsFiles.map(f => basename(f.fileUrl))
36
37 let directories: { [ directory: string ]: string[] } = {
38 videos: webtorrentFilenames,
39 redundancy: webtorrentFilenames,
40 [join('playlists', 'hls')]: hlsFilenames,
41 [join('redundancy', 'hls')]: hlsFilenames
42 }
43
44 if (onlyVideoFiles !== true) {
45 directories = {
46 ...directories,
47
48 thumbnails: [ thumbnailName ],
49 previews: [ previewName ],
50 torrents: torrentNames,
51 captions: captionNames
52 }
53 }
54
55 for (const directory of Object.keys(directories)) {
30 const directoryPath = server.servers.buildDirectory(directory) 56 const directoryPath = server.servers.buildDirectory(directory)
31 57
32 const directoryExists = await pathExists(directoryPath) 58 const directoryExists = await pathExists(directoryPath)
33 if (directoryExists === false) continue 59 if (directoryExists === false) continue
34 60
35 const files = await readdir(directoryPath) 61 const existingFiles = await readdir(directoryPath)
36 for (const file of files) { 62 for (const existingFile of existingFiles) {
37 expect(file, `File ${file} should not exist in ${directoryPath}`).to.not.contain(videoUUID) 63 for (const shouldNotExist of directories[directory]) {
64 expect(existingFile, `File ${existingFile} should not exist in ${directoryPath}`).to.not.contain(shouldNotExist)
65 }
38 } 66 }
39 } 67 }
40} 68}
41 69
70async function saveVideoInServers (servers: PeerTubeServer[], uuid: string) {
71 for (const server of servers) {
72 server.store.videoDetails = await server.videos.get({ id: uuid })
73 }
74}
75
42function checkUploadVideoParam ( 76function checkUploadVideoParam (
43 server: PeerTubeServer, 77 server: PeerTubeServer,
44 token: string, 78 token: string,
@@ -156,18 +190,16 @@ async function completeVideoCheck (
156 190
157 expect(file.magnetUri).to.have.lengthOf.above(2) 191 expect(file.magnetUri).to.have.lengthOf.above(2)
158 192
159 expect(file.torrentDownloadUrl).to.equal(`http://${host}/download/torrents/${videoDetails.uuid}-${file.resolution.id}.torrent`) 193 expect(file.torrentDownloadUrl).to.match(new RegExp(`http://${host}/download/torrents/${uuidRegex}-${file.resolution.id}.torrent`))
160 expect(file.torrentUrl).to.equal(`http://${host}/lazy-static/torrents/${videoDetails.uuid}-${file.resolution.id}.torrent`) 194 expect(file.torrentUrl).to.match(new RegExp(`http://${host}/lazy-static/torrents/${uuidRegex}-${file.resolution.id}.torrent`))
161 195
162 expect(file.fileUrl).to.equal(`http://${originHost}/static/webseed/${videoDetails.uuid}-${file.resolution.id}${extension}`) 196 expect(file.fileUrl).to.match(new RegExp(`http://${originHost}/static/webseed/${uuidRegex}-${file.resolution.id}${extension}`))
163 expect(file.fileDownloadUrl).to.equal(`http://${originHost}/download/videos/${videoDetails.uuid}-${file.resolution.id}${extension}`) 197 expect(file.fileDownloadUrl).to.match(new RegExp(`http://${originHost}/download/videos/${uuidRegex}-${file.resolution.id}${extension}`))
164 198
165 await Promise.all([ 199 await Promise.all([
166 makeRawRequest(file.torrentUrl, 200), 200 makeRawRequest(file.torrentUrl, 200),
167 makeRawRequest(file.torrentDownloadUrl, 200), 201 makeRawRequest(file.torrentDownloadUrl, 200),
168 makeRawRequest(file.metadataUrl, 200), 202 makeRawRequest(file.metadataUrl, 200)
169 // Backward compatibility
170 makeRawRequest(`http://${originHost}/static/torrents/${videoDetails.uuid}-${file.resolution.id}.torrent`, 200)
171 ]) 203 ])
172 204
173 expect(file.resolution.id).to.equal(attributeFile.resolution) 205 expect(file.resolution.id).to.equal(attributeFile.resolution)
@@ -215,5 +247,6 @@ export {
215 checkUploadVideoParam, 247 checkUploadVideoParam,
216 completeVideoCheck, 248 completeVideoCheck,
217 uploadRandomVideoOnServers, 249 uploadRandomVideoOnServers,
218 checkVideoFilesWereRemoved 250 checkVideoFilesWereRemoved,
251 saveVideoInServers
219} 252}