]>
Commit | Line | Data |
---|---|---|
a1587156 | 1 | /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */ |
0c948c16 | 2 | |
86347717 | 3 | import { expect } from 'chai' |
9ab330b9 | 4 | import { areMockObjectStorageTestsDisabled } from '@shared/core-utils' |
0305db28 | 5 | import { HttpStatusCode, VideoFile } from '@shared/models' |
0c948c16 | 6 | import { |
7c3b7976 | 7 | cleanupTests, |
254d3579 | 8 | createMultipleServers, |
4c7e60bc | 9 | doubleFollow, |
0305db28 JB |
10 | makeRawRequest, |
11 | ObjectStorageCommand, | |
254d3579 | 12 | PeerTubeServer, |
a1587156 | 13 | setAccessTokensToServers, |
d23dd9fb | 14 | waitJobs |
c55e3d72 | 15 | } from '@shared/server-commands' |
a2caee9f | 16 | import { checkResolutionsInMasterPlaylist, expectStartWith } from '../shared' |
3cd0734f | 17 | |
0305db28 JB |
18 | async function checkFilesInObjectStorage (files: VideoFile[], type: 'webtorrent' | 'playlist') { |
19 | for (const file of files) { | |
20 | const shouldStartWith = type === 'webtorrent' | |
9ab330b9 C |
21 | ? ObjectStorageCommand.getMockWebTorrentBaseUrl() |
22 | : ObjectStorageCommand.getMockPlaylistBaseUrl() | |
dee6fe1e | 23 | |
0305db28 JB |
24 | expectStartWith(file.fileUrl, shouldStartWith) |
25 | ||
3545e72c | 26 | await makeRawRequest({ url: file.fileUrl, expectedStatus: HttpStatusCode.OK_200 }) |
dee6fe1e | 27 | } |
0305db28 JB |
28 | } |
29 | ||
30 | function runTests (objectStorage: boolean) { | |
31 | let servers: PeerTubeServer[] = [] | |
32 | const videosUUID: string[] = [] | |
9db2330e | 33 | const publishedAt: string[] = [] |
0c948c16 C |
34 | |
35 | before(async function () { | |
9db2330e | 36 | this.timeout(120000) |
0c948c16 | 37 | |
0305db28 | 38 | const config = objectStorage |
9ab330b9 | 39 | ? ObjectStorageCommand.getDefaultMockConfig() |
0305db28 JB |
40 | : {} |
41 | ||
0c948c16 | 42 | // Run server 2 to have transcoding enabled |
0305db28 | 43 | servers = await createMultipleServers(2, config) |
0c948c16 C |
44 | await setAccessTokensToServers(servers) |
45 | ||
0305db28 | 46 | await servers[0].config.disableTranscoding() |
dee6fe1e | 47 | |
0c948c16 C |
48 | await doubleFollow(servers[0], servers[1]) |
49 | ||
9ab330b9 | 50 | if (objectStorage) await ObjectStorageCommand.prepareDefaultMockBuckets() |
0305db28 | 51 | |
dee6fe1e | 52 | for (let i = 1; i <= 5; i++) { |
c186a67f C |
53 | const { uuid, shortUUID } = await servers[0].videos.upload({ attributes: { name: 'video' + i } }) |
54 | ||
9db2330e C |
55 | await waitJobs(servers) |
56 | ||
57 | const video = await servers[0].videos.get({ id: uuid }) | |
58 | publishedAt.push(video.publishedAt as string) | |
59 | ||
c186a67f C |
60 | if (i > 2) { |
61 | videosUUID.push(uuid) | |
62 | } else { | |
63 | videosUUID.push(shortUUID) | |
64 | } | |
dee6fe1e | 65 | } |
0c948c16 | 66 | |
3cd0734f | 67 | await waitJobs(servers) |
0c948c16 C |
68 | }) |
69 | ||
70 | it('Should have two video files on each server', async function () { | |
71 | this.timeout(30000) | |
72 | ||
73 | for (const server of servers) { | |
89d241a7 | 74 | const { data } = await server.videos.list() |
d23dd9fb | 75 | expect(data).to.have.lengthOf(videosUUID.length) |
0c948c16 | 76 | |
d23dd9fb | 77 | for (const video of data) { |
89d241a7 | 78 | const videoDetail = await server.videos.get({ id: video.uuid }) |
0c948c16 | 79 | expect(videoDetail.files).to.have.lengthOf(1) |
dee6fe1e | 80 | expect(videoDetail.streamingPlaylists).to.have.lengthOf(0) |
0c948c16 C |
81 | } |
82 | } | |
83 | }) | |
84 | ||
85 | it('Should run a transcoding job on video 2', async function () { | |
86 | this.timeout(60000) | |
87 | ||
89d241a7 | 88 | await servers[0].cli.execWithEnv(`npm run create-transcoding-job -- -v ${videosUUID[1]}`) |
3cd0734f | 89 | await waitJobs(servers) |
0c948c16 C |
90 | |
91 | for (const server of servers) { | |
89d241a7 | 92 | const { data } = await server.videos.list() |
0c948c16 | 93 | |
a1587156 | 94 | let infoHashes: { [id: number]: string } |
04bf312c | 95 | |
d23dd9fb | 96 | for (const video of data) { |
0305db28 | 97 | const videoDetails = await server.videos.get({ id: video.uuid }) |
0c948c16 | 98 | |
c186a67f | 99 | if (video.shortUUID === videosUUID[1] || video.uuid === videosUUID[1]) { |
0305db28 JB |
100 | expect(videoDetails.files).to.have.lengthOf(4) |
101 | expect(videoDetails.streamingPlaylists).to.have.lengthOf(0) | |
102 | ||
103 | if (objectStorage) await checkFilesInObjectStorage(videoDetails.files, 'webtorrent') | |
04bf312c C |
104 | |
105 | if (!infoHashes) { | |
106 | infoHashes = {} | |
107 | ||
0305db28 | 108 | for (const file of videoDetails.files) { |
04bf312c C |
109 | infoHashes[file.resolution.id.toString()] = file.magnetUri |
110 | } | |
111 | } else { | |
112 | for (const resolution of Object.keys(infoHashes)) { | |
0305db28 | 113 | const file = videoDetails.files.find(f => f.resolution.id.toString() === resolution) |
04bf312c C |
114 | expect(file.magnetUri).to.equal(infoHashes[resolution]) |
115 | } | |
116 | } | |
0c948c16 | 117 | } else { |
0305db28 JB |
118 | expect(videoDetails.files).to.have.lengthOf(1) |
119 | expect(videoDetails.streamingPlaylists).to.have.lengthOf(0) | |
0c948c16 C |
120 | } |
121 | } | |
122 | } | |
123 | }) | |
124 | ||
05623b90 F |
125 | it('Should run a transcoding job on video 1 with resolution', async function () { |
126 | this.timeout(60000) | |
127 | ||
89d241a7 | 128 | await servers[0].cli.execWithEnv(`npm run create-transcoding-job -- -v ${videosUUID[0]} -r 480`) |
05623b90 F |
129 | |
130 | await waitJobs(servers) | |
131 | ||
132 | for (const server of servers) { | |
89d241a7 | 133 | const { data } = await server.videos.list() |
d23dd9fb | 134 | expect(data).to.have.lengthOf(videosUUID.length) |
05623b90 | 135 | |
89d241a7 | 136 | const videoDetails = await server.videos.get({ id: videosUUID[0] }) |
05623b90 | 137 | |
d23dd9fb C |
138 | expect(videoDetails.files).to.have.lengthOf(2) |
139 | expect(videoDetails.files[0].resolution.id).to.equal(720) | |
140 | expect(videoDetails.files[1].resolution.id).to.equal(480) | |
dee6fe1e | 141 | |
d23dd9fb | 142 | expect(videoDetails.streamingPlaylists).to.have.lengthOf(0) |
0305db28 JB |
143 | |
144 | if (objectStorage) await checkFilesInObjectStorage(videoDetails.files, 'webtorrent') | |
dee6fe1e C |
145 | } |
146 | }) | |
147 | ||
148 | it('Should generate an HLS resolution', async function () { | |
149 | this.timeout(120000) | |
150 | ||
89d241a7 | 151 | await servers[0].cli.execWithEnv(`npm run create-transcoding-job -- -v ${videosUUID[2]} --generate-hls -r 480`) |
dee6fe1e C |
152 | |
153 | await waitJobs(servers) | |
154 | ||
155 | for (const server of servers) { | |
89d241a7 | 156 | const videoDetails = await server.videos.get({ id: videosUUID[2] }) |
dee6fe1e | 157 | |
d23dd9fb | 158 | expect(videoDetails.files).to.have.lengthOf(1) |
0305db28 JB |
159 | if (objectStorage) await checkFilesInObjectStorage(videoDetails.files, 'webtorrent') |
160 | ||
d23dd9fb | 161 | expect(videoDetails.streamingPlaylists).to.have.lengthOf(1) |
dee6fe1e | 162 | |
a2caee9f C |
163 | const hlsPlaylist = videoDetails.streamingPlaylists[0] |
164 | ||
165 | const files = hlsPlaylist.files | |
dee6fe1e C |
166 | expect(files).to.have.lengthOf(1) |
167 | expect(files[0].resolution.id).to.equal(480) | |
0305db28 | 168 | |
a2caee9f C |
169 | if (objectStorage) { |
170 | await checkFilesInObjectStorage(files, 'playlist') | |
171 | ||
172 | const resolutions = files.map(f => f.resolution.id) | |
173 | await checkResolutionsInMasterPlaylist({ server, playlistUrl: hlsPlaylist.playlistUrl, resolutions }) | |
174 | } | |
dee6fe1e C |
175 | } |
176 | }) | |
177 | ||
178 | it('Should not duplicate an HLS resolution', async function () { | |
179 | this.timeout(120000) | |
180 | ||
89d241a7 | 181 | await servers[0].cli.execWithEnv(`npm run create-transcoding-job -- -v ${videosUUID[2]} --generate-hls -r 480`) |
dee6fe1e C |
182 | |
183 | await waitJobs(servers) | |
184 | ||
185 | for (const server of servers) { | |
89d241a7 | 186 | const videoDetails = await server.videos.get({ id: videosUUID[2] }) |
dee6fe1e | 187 | |
d23dd9fb | 188 | const files = videoDetails.streamingPlaylists[0].files |
dee6fe1e C |
189 | expect(files).to.have.lengthOf(1) |
190 | expect(files[0].resolution.id).to.equal(480) | |
0305db28 JB |
191 | |
192 | if (objectStorage) await checkFilesInObjectStorage(files, 'playlist') | |
dee6fe1e C |
193 | } |
194 | }) | |
195 | ||
196 | it('Should generate all HLS resolutions', async function () { | |
197 | this.timeout(120000) | |
198 | ||
89d241a7 | 199 | await servers[0].cli.execWithEnv(`npm run create-transcoding-job -- -v ${videosUUID[3]} --generate-hls`) |
dee6fe1e C |
200 | |
201 | await waitJobs(servers) | |
202 | ||
203 | for (const server of servers) { | |
89d241a7 | 204 | const videoDetails = await server.videos.get({ id: videosUUID[3] }) |
dee6fe1e | 205 | |
d23dd9fb C |
206 | expect(videoDetails.files).to.have.lengthOf(1) |
207 | expect(videoDetails.streamingPlaylists).to.have.lengthOf(1) | |
dee6fe1e | 208 | |
d23dd9fb | 209 | const files = videoDetails.streamingPlaylists[0].files |
dee6fe1e | 210 | expect(files).to.have.lengthOf(4) |
0305db28 JB |
211 | |
212 | if (objectStorage) await checkFilesInObjectStorage(files, 'playlist') | |
dee6fe1e C |
213 | } |
214 | }) | |
215 | ||
216 | it('Should optimize the video file and generate HLS videos if enabled in config', async function () { | |
217 | this.timeout(120000) | |
218 | ||
0305db28 | 219 | await servers[0].config.enableTranscoding() |
89d241a7 | 220 | await servers[0].cli.execWithEnv(`npm run create-transcoding-job -- -v ${videosUUID[4]}`) |
dee6fe1e C |
221 | |
222 | await waitJobs(servers) | |
223 | ||
224 | for (const server of servers) { | |
89d241a7 | 225 | const videoDetails = await server.videos.get({ id: videosUUID[4] }) |
dee6fe1e | 226 | |
8dd754c7 | 227 | expect(videoDetails.files).to.have.lengthOf(5) |
d23dd9fb | 228 | expect(videoDetails.streamingPlaylists).to.have.lengthOf(1) |
8dd754c7 | 229 | expect(videoDetails.streamingPlaylists[0].files).to.have.lengthOf(5) |
0305db28 JB |
230 | |
231 | if (objectStorage) { | |
232 | await checkFilesInObjectStorage(videoDetails.files, 'webtorrent') | |
233 | await checkFilesInObjectStorage(videoDetails.streamingPlaylists[0].files, 'playlist') | |
234 | } | |
05623b90 F |
235 | } |
236 | }) | |
237 | ||
9db2330e C |
238 | it('Should not have updated published at attributes', async function () { |
239 | for (const id of videosUUID) { | |
240 | const video = await servers[0].videos.get({ id }) | |
241 | ||
242 | expect(publishedAt.some(p => video.publishedAt === p)).to.be.true | |
243 | } | |
244 | }) | |
245 | ||
7c3b7976 C |
246 | after(async function () { |
247 | await cleanupTests(servers) | |
0c948c16 | 248 | }) |
0305db28 JB |
249 | } |
250 | ||
251 | describe('Test create transcoding jobs', function () { | |
252 | ||
253 | describe('On filesystem', function () { | |
254 | runTests(false) | |
255 | }) | |
256 | ||
257 | describe('On object storage', function () { | |
9ab330b9 | 258 | if (areMockObjectStorageTestsDisabled()) return |
0305db28 JB |
259 | |
260 | runTests(true) | |
261 | }) | |
0c948c16 | 262 | }) |