diff options
Diffstat (limited to 'server/tests/api')
-rw-r--r-- | server/tests/api/check-params/index.ts | 1 | ||||
-rw-r--r-- | server/tests/api/check-params/live.ts | 17 | ||||
-rw-r--r-- | server/tests/api/check-params/video-files.ts | 217 | ||||
-rw-r--r-- | server/tests/api/check-params/video-token.ts | 44 | ||||
-rw-r--r-- | server/tests/api/live/live-fast-restream.ts | 4 | ||||
-rw-r--r-- | server/tests/api/live/live.ts | 13 | ||||
-rw-r--r-- | server/tests/api/object-storage/live.ts | 2 | ||||
-rw-r--r-- | server/tests/api/object-storage/video-imports.ts | 6 | ||||
-rw-r--r-- | server/tests/api/object-storage/videos.ts | 20 | ||||
-rw-r--r-- | server/tests/api/redundancy/redundancy.ts | 2 | ||||
-rw-r--r-- | server/tests/api/server/open-telemetry.ts | 6 | ||||
-rw-r--r-- | server/tests/api/transcoding/create-transcoding.ts | 10 | ||||
-rw-r--r-- | server/tests/api/transcoding/hls.ts | 163 | ||||
-rw-r--r-- | server/tests/api/transcoding/index.ts | 1 | ||||
-rw-r--r-- | server/tests/api/transcoding/update-while-transcoding.ts | 151 | ||||
-rw-r--r-- | server/tests/api/videos/index.ts | 1 | ||||
-rw-r--r-- | server/tests/api/videos/video-files.ts | 2 | ||||
-rw-r--r-- | server/tests/api/videos/video-static-file-privacy.ts | 389 |
18 files changed, 787 insertions, 262 deletions
diff --git a/server/tests/api/check-params/index.ts b/server/tests/api/check-params/index.ts index 33dc8fb76..961093bb5 100644 --- a/server/tests/api/check-params/index.ts +++ b/server/tests/api/check-params/index.ts | |||
@@ -34,6 +34,7 @@ import './video-imports' | |||
34 | import './video-playlists' | 34 | import './video-playlists' |
35 | import './video-source' | 35 | import './video-source' |
36 | import './video-studio' | 36 | import './video-studio' |
37 | import './video-token' | ||
37 | import './videos-common-filters' | 38 | import './videos-common-filters' |
38 | import './videos-history' | 39 | import './videos-history' |
39 | import './videos-overviews' | 40 | import './videos-overviews' |
diff --git a/server/tests/api/check-params/live.ts b/server/tests/api/check-params/live.ts index 3f553c42b..2eff9414b 100644 --- a/server/tests/api/check-params/live.ts +++ b/server/tests/api/check-params/live.ts | |||
@@ -502,6 +502,23 @@ describe('Test video lives API validator', function () { | |||
502 | await stopFfmpeg(ffmpegCommand) | 502 | await stopFfmpeg(ffmpegCommand) |
503 | }) | 503 | }) |
504 | 504 | ||
505 | it('Should fail to change live privacy if it has already started', async function () { | ||
506 | this.timeout(40000) | ||
507 | |||
508 | const live = await command.get({ videoId: video.id }) | ||
509 | |||
510 | const ffmpegCommand = sendRTMPStream({ rtmpBaseUrl: live.rtmpUrl, streamKey: live.streamKey }) | ||
511 | |||
512 | await command.waitUntilPublished({ videoId: video.id }) | ||
513 | await server.videos.update({ | ||
514 | id: video.id, | ||
515 | attributes: { privacy: VideoPrivacy.PUBLIC }, | ||
516 | expectedStatus: HttpStatusCode.BAD_REQUEST_400 | ||
517 | }) | ||
518 | |||
519 | await stopFfmpeg(ffmpegCommand) | ||
520 | }) | ||
521 | |||
505 | it('Should fail to stream twice in the save live', async function () { | 522 | it('Should fail to stream twice in the save live', async function () { |
506 | this.timeout(40000) | 523 | this.timeout(40000) |
507 | 524 | ||
diff --git a/server/tests/api/check-params/video-files.ts b/server/tests/api/check-params/video-files.ts index aa4de2c83..9dc59a1b5 100644 --- a/server/tests/api/check-params/video-files.ts +++ b/server/tests/api/check-params/video-files.ts | |||
@@ -1,10 +1,12 @@ | |||
1 | /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */ | 1 | /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */ |
2 | 2 | ||
3 | import { HttpStatusCode, UserRole } from '@shared/models' | 3 | import { getAllFiles } from '@shared/core-utils' |
4 | import { HttpStatusCode, UserRole, VideoDetails, VideoPrivacy } from '@shared/models' | ||
4 | import { | 5 | import { |
5 | cleanupTests, | 6 | cleanupTests, |
6 | createMultipleServers, | 7 | createMultipleServers, |
7 | doubleFollow, | 8 | doubleFollow, |
9 | makeRawRequest, | ||
8 | PeerTubeServer, | 10 | PeerTubeServer, |
9 | setAccessTokensToServers, | 11 | setAccessTokensToServers, |
10 | waitJobs | 12 | waitJobs |
@@ -13,22 +15,9 @@ import { | |||
13 | describe('Test videos files', function () { | 15 | describe('Test videos files', function () { |
14 | let servers: PeerTubeServer[] | 16 | let servers: PeerTubeServer[] |
15 | 17 | ||
16 | let webtorrentId: string | ||
17 | let hlsId: string | ||
18 | let remoteId: string | ||
19 | |||
20 | let userToken: string | 18 | let userToken: string |
21 | let moderatorToken: string | 19 | let moderatorToken: string |
22 | 20 | ||
23 | let validId1: string | ||
24 | let validId2: string | ||
25 | |||
26 | let hlsFileId: number | ||
27 | let webtorrentFileId: number | ||
28 | |||
29 | let remoteHLSFileId: number | ||
30 | let remoteWebtorrentFileId: number | ||
31 | |||
32 | // --------------------------------------------------------------- | 21 | // --------------------------------------------------------------- |
33 | 22 | ||
34 | before(async function () { | 23 | before(async function () { |
@@ -41,117 +30,163 @@ describe('Test videos files', function () { | |||
41 | 30 | ||
42 | userToken = await servers[0].users.generateUserAndToken('user', UserRole.USER) | 31 | userToken = await servers[0].users.generateUserAndToken('user', UserRole.USER) |
43 | moderatorToken = await servers[0].users.generateUserAndToken('moderator', UserRole.MODERATOR) | 32 | moderatorToken = await servers[0].users.generateUserAndToken('moderator', UserRole.MODERATOR) |
33 | }) | ||
44 | 34 | ||
45 | { | 35 | describe('Getting metadata', function () { |
46 | const { uuid } = await servers[1].videos.quickUpload({ name: 'remote video' }) | 36 | let video: VideoDetails |
47 | await waitJobs(servers) | 37 | |
38 | before(async function () { | ||
39 | const { uuid } = await servers[0].videos.quickUpload({ name: 'video', privacy: VideoPrivacy.PRIVATE }) | ||
40 | video = await servers[0].videos.getWithToken({ id: uuid }) | ||
41 | }) | ||
42 | |||
43 | it('Should not get metadata of private video without token', async function () { | ||
44 | for (const file of getAllFiles(video)) { | ||
45 | await makeRawRequest({ url: file.metadataUrl, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 }) | ||
46 | } | ||
47 | }) | ||
48 | |||
49 | it('Should not get metadata of private video without the appropriate token', async function () { | ||
50 | for (const file of getAllFiles(video)) { | ||
51 | await makeRawRequest({ url: file.metadataUrl, token: userToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 }) | ||
52 | } | ||
53 | }) | ||
54 | |||
55 | it('Should get metadata of private video with the appropriate token', async function () { | ||
56 | for (const file of getAllFiles(video)) { | ||
57 | await makeRawRequest({ url: file.metadataUrl, token: servers[0].accessToken, expectedStatus: HttpStatusCode.OK_200 }) | ||
58 | } | ||
59 | }) | ||
60 | }) | ||
61 | |||
62 | describe('Deleting files', function () { | ||
63 | let webtorrentId: string | ||
64 | let hlsId: string | ||
65 | let remoteId: string | ||
66 | |||
67 | let validId1: string | ||
68 | let validId2: string | ||
48 | 69 | ||
49 | const video = await servers[1].videos.get({ id: uuid }) | 70 | let hlsFileId: number |
50 | remoteId = video.uuid | 71 | let webtorrentFileId: number |
51 | remoteHLSFileId = video.streamingPlaylists[0].files[0].id | ||
52 | remoteWebtorrentFileId = video.files[0].id | ||
53 | } | ||
54 | 72 | ||
55 | { | 73 | let remoteHLSFileId: number |
56 | await servers[0].config.enableTranscoding(true, true) | 74 | let remoteWebtorrentFileId: number |
75 | |||
76 | before(async function () { | ||
77 | this.timeout(300_000) | ||
57 | 78 | ||
58 | { | 79 | { |
59 | const { uuid } = await servers[0].videos.quickUpload({ name: 'both 1' }) | 80 | const { uuid } = await servers[1].videos.quickUpload({ name: 'remote video' }) |
60 | await waitJobs(servers) | 81 | await waitJobs(servers) |
61 | 82 | ||
62 | const video = await servers[0].videos.get({ id: uuid }) | 83 | const video = await servers[1].videos.get({ id: uuid }) |
63 | validId1 = video.uuid | 84 | remoteId = video.uuid |
64 | hlsFileId = video.streamingPlaylists[0].files[0].id | 85 | remoteHLSFileId = video.streamingPlaylists[0].files[0].id |
65 | webtorrentFileId = video.files[0].id | 86 | remoteWebtorrentFileId = video.files[0].id |
66 | } | 87 | } |
67 | 88 | ||
68 | { | 89 | { |
69 | const { uuid } = await servers[0].videos.quickUpload({ name: 'both 2' }) | 90 | await servers[0].config.enableTranscoding(true, true) |
70 | validId2 = uuid | 91 | |
92 | { | ||
93 | const { uuid } = await servers[0].videos.quickUpload({ name: 'both 1' }) | ||
94 | await waitJobs(servers) | ||
95 | |||
96 | const video = await servers[0].videos.get({ id: uuid }) | ||
97 | validId1 = video.uuid | ||
98 | hlsFileId = video.streamingPlaylists[0].files[0].id | ||
99 | webtorrentFileId = video.files[0].id | ||
100 | } | ||
101 | |||
102 | { | ||
103 | const { uuid } = await servers[0].videos.quickUpload({ name: 'both 2' }) | ||
104 | validId2 = uuid | ||
105 | } | ||
71 | } | 106 | } |
72 | } | ||
73 | 107 | ||
74 | await waitJobs(servers) | 108 | await waitJobs(servers) |
75 | 109 | ||
76 | { | 110 | { |
77 | await servers[0].config.enableTranscoding(false, true) | 111 | await servers[0].config.enableTranscoding(false, true) |
78 | const { uuid } = await servers[0].videos.quickUpload({ name: 'hls' }) | 112 | const { uuid } = await servers[0].videos.quickUpload({ name: 'hls' }) |
79 | hlsId = uuid | 113 | hlsId = uuid |
80 | } | 114 | } |
81 | 115 | ||
82 | await waitJobs(servers) | 116 | await waitJobs(servers) |
83 | 117 | ||
84 | { | 118 | { |
85 | await servers[0].config.enableTranscoding(false, true) | 119 | await servers[0].config.enableTranscoding(false, true) |
86 | const { uuid } = await servers[0].videos.quickUpload({ name: 'webtorrent' }) | 120 | const { uuid } = await servers[0].videos.quickUpload({ name: 'webtorrent' }) |
87 | webtorrentId = uuid | 121 | webtorrentId = uuid |
88 | } | 122 | } |
89 | 123 | ||
90 | await waitJobs(servers) | 124 | await waitJobs(servers) |
91 | }) | 125 | }) |
92 | 126 | ||
93 | it('Should not delete files of a unknown video', async function () { | 127 | it('Should not delete files of a unknown video', async function () { |
94 | const expectedStatus = HttpStatusCode.NOT_FOUND_404 | 128 | const expectedStatus = HttpStatusCode.NOT_FOUND_404 |
95 | 129 | ||
96 | await servers[0].videos.removeHLSPlaylist({ videoId: 404, expectedStatus }) | 130 | await servers[0].videos.removeHLSPlaylist({ videoId: 404, expectedStatus }) |
97 | await servers[0].videos.removeAllWebTorrentFiles({ videoId: 404, expectedStatus }) | 131 | await servers[0].videos.removeAllWebTorrentFiles({ videoId: 404, expectedStatus }) |
98 | 132 | ||
99 | await servers[0].videos.removeHLSFile({ videoId: 404, fileId: hlsFileId, expectedStatus }) | 133 | await servers[0].videos.removeHLSFile({ videoId: 404, fileId: hlsFileId, expectedStatus }) |
100 | await servers[0].videos.removeWebTorrentFile({ videoId: 404, fileId: webtorrentFileId, expectedStatus }) | 134 | await servers[0].videos.removeWebTorrentFile({ videoId: 404, fileId: webtorrentFileId, expectedStatus }) |
101 | }) | 135 | }) |
102 | 136 | ||
103 | it('Should not delete unknown files', async function () { | 137 | it('Should not delete unknown files', async function () { |
104 | const expectedStatus = HttpStatusCode.NOT_FOUND_404 | 138 | const expectedStatus = HttpStatusCode.NOT_FOUND_404 |
105 | 139 | ||
106 | await servers[0].videos.removeHLSFile({ videoId: validId1, fileId: webtorrentFileId, expectedStatus }) | 140 | await servers[0].videos.removeHLSFile({ videoId: validId1, fileId: webtorrentFileId, expectedStatus }) |
107 | await servers[0].videos.removeWebTorrentFile({ videoId: validId1, fileId: hlsFileId, expectedStatus }) | 141 | await servers[0].videos.removeWebTorrentFile({ videoId: validId1, fileId: hlsFileId, expectedStatus }) |
108 | }) | 142 | }) |
109 | 143 | ||
110 | it('Should not delete files of a remote video', async function () { | 144 | it('Should not delete files of a remote video', async function () { |
111 | const expectedStatus = HttpStatusCode.BAD_REQUEST_400 | 145 | const expectedStatus = HttpStatusCode.BAD_REQUEST_400 |
112 | 146 | ||
113 | await servers[0].videos.removeHLSPlaylist({ videoId: remoteId, expectedStatus }) | 147 | await servers[0].videos.removeHLSPlaylist({ videoId: remoteId, expectedStatus }) |
114 | await servers[0].videos.removeAllWebTorrentFiles({ videoId: remoteId, expectedStatus }) | 148 | await servers[0].videos.removeAllWebTorrentFiles({ videoId: remoteId, expectedStatus }) |
115 | 149 | ||
116 | await servers[0].videos.removeHLSFile({ videoId: remoteId, fileId: remoteHLSFileId, expectedStatus }) | 150 | await servers[0].videos.removeHLSFile({ videoId: remoteId, fileId: remoteHLSFileId, expectedStatus }) |
117 | await servers[0].videos.removeWebTorrentFile({ videoId: remoteId, fileId: remoteWebtorrentFileId, expectedStatus }) | 151 | await servers[0].videos.removeWebTorrentFile({ videoId: remoteId, fileId: remoteWebtorrentFileId, expectedStatus }) |
118 | }) | 152 | }) |
119 | 153 | ||
120 | it('Should not delete files by a non admin user', async function () { | 154 | it('Should not delete files by a non admin user', async function () { |
121 | const expectedStatus = HttpStatusCode.FORBIDDEN_403 | 155 | const expectedStatus = HttpStatusCode.FORBIDDEN_403 |
122 | 156 | ||
123 | await servers[0].videos.removeHLSPlaylist({ videoId: validId1, token: userToken, expectedStatus }) | 157 | await servers[0].videos.removeHLSPlaylist({ videoId: validId1, token: userToken, expectedStatus }) |
124 | await servers[0].videos.removeHLSPlaylist({ videoId: validId1, token: moderatorToken, expectedStatus }) | 158 | await servers[0].videos.removeHLSPlaylist({ videoId: validId1, token: moderatorToken, expectedStatus }) |
125 | 159 | ||
126 | await servers[0].videos.removeAllWebTorrentFiles({ videoId: validId1, token: userToken, expectedStatus }) | 160 | await servers[0].videos.removeAllWebTorrentFiles({ videoId: validId1, token: userToken, expectedStatus }) |
127 | await servers[0].videos.removeAllWebTorrentFiles({ videoId: validId1, token: moderatorToken, expectedStatus }) | 161 | await servers[0].videos.removeAllWebTorrentFiles({ videoId: validId1, token: moderatorToken, expectedStatus }) |
128 | 162 | ||
129 | await servers[0].videos.removeHLSFile({ videoId: validId1, fileId: hlsFileId, token: userToken, expectedStatus }) | 163 | await servers[0].videos.removeHLSFile({ videoId: validId1, fileId: hlsFileId, token: userToken, expectedStatus }) |
130 | await servers[0].videos.removeHLSFile({ videoId: validId1, fileId: hlsFileId, token: moderatorToken, expectedStatus }) | 164 | await servers[0].videos.removeHLSFile({ videoId: validId1, fileId: hlsFileId, token: moderatorToken, expectedStatus }) |
131 | 165 | ||
132 | await servers[0].videos.removeWebTorrentFile({ videoId: validId1, fileId: webtorrentFileId, token: userToken, expectedStatus }) | 166 | await servers[0].videos.removeWebTorrentFile({ videoId: validId1, fileId: webtorrentFileId, token: userToken, expectedStatus }) |
133 | await servers[0].videos.removeWebTorrentFile({ videoId: validId1, fileId: webtorrentFileId, token: moderatorToken, expectedStatus }) | 167 | await servers[0].videos.removeWebTorrentFile({ videoId: validId1, fileId: webtorrentFileId, token: moderatorToken, expectedStatus }) |
134 | }) | 168 | }) |
135 | 169 | ||
136 | it('Should not delete files if the files are not available', async function () { | 170 | it('Should not delete files if the files are not available', async function () { |
137 | await servers[0].videos.removeHLSPlaylist({ videoId: hlsId, expectedStatus: HttpStatusCode.BAD_REQUEST_400 }) | 171 | await servers[0].videos.removeHLSPlaylist({ videoId: hlsId, expectedStatus: HttpStatusCode.BAD_REQUEST_400 }) |
138 | await servers[0].videos.removeAllWebTorrentFiles({ videoId: webtorrentId, expectedStatus: HttpStatusCode.BAD_REQUEST_400 }) | 172 | await servers[0].videos.removeAllWebTorrentFiles({ videoId: webtorrentId, expectedStatus: HttpStatusCode.BAD_REQUEST_400 }) |
139 | 173 | ||
140 | await servers[0].videos.removeHLSFile({ videoId: hlsId, fileId: 404, expectedStatus: HttpStatusCode.NOT_FOUND_404 }) | 174 | await servers[0].videos.removeHLSFile({ videoId: hlsId, fileId: 404, expectedStatus: HttpStatusCode.NOT_FOUND_404 }) |
141 | await servers[0].videos.removeWebTorrentFile({ videoId: webtorrentId, fileId: 404, expectedStatus: HttpStatusCode.NOT_FOUND_404 }) | 175 | await servers[0].videos.removeWebTorrentFile({ videoId: webtorrentId, fileId: 404, expectedStatus: HttpStatusCode.NOT_FOUND_404 }) |
142 | }) | 176 | }) |
143 | 177 | ||
144 | it('Should not delete files if no both versions are available', async function () { | 178 | it('Should not delete files if no both versions are available', async function () { |
145 | await servers[0].videos.removeHLSPlaylist({ videoId: hlsId, expectedStatus: HttpStatusCode.BAD_REQUEST_400 }) | 179 | await servers[0].videos.removeHLSPlaylist({ videoId: hlsId, expectedStatus: HttpStatusCode.BAD_REQUEST_400 }) |
146 | await servers[0].videos.removeAllWebTorrentFiles({ videoId: webtorrentId, expectedStatus: HttpStatusCode.BAD_REQUEST_400 }) | 180 | await servers[0].videos.removeAllWebTorrentFiles({ videoId: webtorrentId, expectedStatus: HttpStatusCode.BAD_REQUEST_400 }) |
147 | }) | 181 | }) |
148 | 182 | ||
149 | it('Should delete files if both versions are available', async function () { | 183 | it('Should delete files if both versions are available', async function () { |
150 | await servers[0].videos.removeHLSFile({ videoId: validId1, fileId: hlsFileId }) | 184 | await servers[0].videos.removeHLSFile({ videoId: validId1, fileId: hlsFileId }) |
151 | await servers[0].videos.removeWebTorrentFile({ videoId: validId1, fileId: webtorrentFileId }) | 185 | await servers[0].videos.removeWebTorrentFile({ videoId: validId1, fileId: webtorrentFileId }) |
152 | 186 | ||
153 | await servers[0].videos.removeHLSPlaylist({ videoId: validId1 }) | 187 | await servers[0].videos.removeHLSPlaylist({ videoId: validId1 }) |
154 | await servers[0].videos.removeAllWebTorrentFiles({ videoId: validId2 }) | 188 | await servers[0].videos.removeAllWebTorrentFiles({ videoId: validId2 }) |
189 | }) | ||
155 | }) | 190 | }) |
156 | 191 | ||
157 | after(async function () { | 192 | after(async function () { |
diff --git a/server/tests/api/check-params/video-token.ts b/server/tests/api/check-params/video-token.ts new file mode 100644 index 000000000..7acb9d580 --- /dev/null +++ b/server/tests/api/check-params/video-token.ts | |||
@@ -0,0 +1,44 @@ | |||
1 | /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */ | ||
2 | |||
3 | import { HttpStatusCode, VideoPrivacy } from '@shared/models' | ||
4 | import { cleanupTests, createSingleServer, PeerTubeServer, setAccessTokensToServers } from '@shared/server-commands' | ||
5 | |||
6 | describe('Test video tokens', function () { | ||
7 | let server: PeerTubeServer | ||
8 | let videoId: string | ||
9 | let userToken: string | ||
10 | |||
11 | // --------------------------------------------------------------- | ||
12 | |||
13 | before(async function () { | ||
14 | this.timeout(300_000) | ||
15 | |||
16 | server = await createSingleServer(1) | ||
17 | await setAccessTokensToServers([ server ]) | ||
18 | |||
19 | const { uuid } = await server.videos.quickUpload({ name: 'video', privacy: VideoPrivacy.PRIVATE }) | ||
20 | videoId = uuid | ||
21 | |||
22 | userToken = await server.users.generateUserAndToken('user1') | ||
23 | }) | ||
24 | |||
25 | it('Should not generate tokens for unauthenticated user', async function () { | ||
26 | await server.videoToken.create({ videoId, token: null, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 }) | ||
27 | }) | ||
28 | |||
29 | it('Should not generate tokens of unknown video', async function () { | ||
30 | await server.videoToken.create({ videoId: 404, expectedStatus: HttpStatusCode.NOT_FOUND_404 }) | ||
31 | }) | ||
32 | |||
33 | it('Should not generate tokens of a non owned video', async function () { | ||
34 | await server.videoToken.create({ videoId, token: userToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 }) | ||
35 | }) | ||
36 | |||
37 | it('Should generate token', async function () { | ||
38 | await server.videoToken.create({ videoId }) | ||
39 | }) | ||
40 | |||
41 | after(async function () { | ||
42 | await cleanupTests([ server ]) | ||
43 | }) | ||
44 | }) | ||
diff --git a/server/tests/api/live/live-fast-restream.ts b/server/tests/api/live/live-fast-restream.ts index 772ea792d..971df1a61 100644 --- a/server/tests/api/live/live-fast-restream.ts +++ b/server/tests/api/live/live-fast-restream.ts | |||
@@ -79,8 +79,8 @@ describe('Fast restream in live', function () { | |||
79 | expect(video.streamingPlaylists).to.have.lengthOf(1) | 79 | expect(video.streamingPlaylists).to.have.lengthOf(1) |
80 | 80 | ||
81 | await server.live.getSegmentFile({ videoUUID: liveId, segment: 0, playlistNumber: 0 }) | 81 | await server.live.getSegmentFile({ videoUUID: liveId, segment: 0, playlistNumber: 0 }) |
82 | await makeRawRequest(video.streamingPlaylists[0].playlistUrl, HttpStatusCode.OK_200) | 82 | await makeRawRequest({ url: video.streamingPlaylists[0].playlistUrl, expectedStatus: HttpStatusCode.OK_200 }) |
83 | await makeRawRequest(video.streamingPlaylists[0].segmentsSha256Url, HttpStatusCode.OK_200) | 83 | await makeRawRequest({ url: video.streamingPlaylists[0].segmentsSha256Url, expectedStatus: HttpStatusCode.OK_200 }) |
84 | 84 | ||
85 | await wait(100) | 85 | await wait(100) |
86 | } | 86 | } |
diff --git a/server/tests/api/live/live.ts b/server/tests/api/live/live.ts index 3f2a304be..003cc934f 100644 --- a/server/tests/api/live/live.ts +++ b/server/tests/api/live/live.ts | |||
@@ -21,6 +21,7 @@ import { | |||
21 | doubleFollow, | 21 | doubleFollow, |
22 | killallServers, | 22 | killallServers, |
23 | LiveCommand, | 23 | LiveCommand, |
24 | makeGetRequest, | ||
24 | makeRawRequest, | 25 | makeRawRequest, |
25 | PeerTubeServer, | 26 | PeerTubeServer, |
26 | sendRTMPStream, | 27 | sendRTMPStream, |
@@ -157,8 +158,8 @@ describe('Test live', function () { | |||
157 | expect(video.privacy.id).to.equal(VideoPrivacy.UNLISTED) | 158 | expect(video.privacy.id).to.equal(VideoPrivacy.UNLISTED) |
158 | expect(video.nsfw).to.be.true | 159 | expect(video.nsfw).to.be.true |
159 | 160 | ||
160 | await makeRawRequest(server.url + video.thumbnailPath, HttpStatusCode.OK_200) | 161 | await makeGetRequest({ url: server.url, path: video.thumbnailPath, expectedStatus: HttpStatusCode.OK_200 }) |
161 | await makeRawRequest(server.url + video.previewPath, HttpStatusCode.OK_200) | 162 | await makeGetRequest({ url: server.url, path: video.previewPath, expectedStatus: HttpStatusCode.OK_200 }) |
162 | } | 163 | } |
163 | }) | 164 | }) |
164 | 165 | ||
@@ -532,8 +533,8 @@ describe('Test live', function () { | |||
532 | expect(video.files).to.have.lengthOf(0) | 533 | expect(video.files).to.have.lengthOf(0) |
533 | 534 | ||
534 | const hlsPlaylist = video.streamingPlaylists.find(s => s.type === VideoStreamingPlaylistType.HLS) | 535 | const hlsPlaylist = video.streamingPlaylists.find(s => s.type === VideoStreamingPlaylistType.HLS) |
535 | await makeRawRequest(hlsPlaylist.playlistUrl, HttpStatusCode.OK_200) | 536 | await makeRawRequest({ url: hlsPlaylist.playlistUrl, expectedStatus: HttpStatusCode.OK_200 }) |
536 | await makeRawRequest(hlsPlaylist.segmentsSha256Url, HttpStatusCode.OK_200) | 537 | await makeRawRequest({ url: hlsPlaylist.segmentsSha256Url, expectedStatus: HttpStatusCode.OK_200 }) |
537 | 538 | ||
538 | // We should have generated random filenames | 539 | // We should have generated random filenames |
539 | expect(basename(hlsPlaylist.playlistUrl)).to.not.equal('master.m3u8') | 540 | expect(basename(hlsPlaylist.playlistUrl)).to.not.equal('master.m3u8') |
@@ -564,8 +565,8 @@ describe('Test live', function () { | |||
564 | expect(probe.format.bit_rate).to.be.below(maxBitrateLimits[videoStream.height]) | 565 | expect(probe.format.bit_rate).to.be.below(maxBitrateLimits[videoStream.height]) |
565 | expect(probe.format.bit_rate).to.be.at.least(minBitrateLimits[videoStream.height]) | 566 | expect(probe.format.bit_rate).to.be.at.least(minBitrateLimits[videoStream.height]) |
566 | 567 | ||
567 | await makeRawRequest(file.torrentUrl, HttpStatusCode.OK_200) | 568 | await makeRawRequest({ url: file.torrentUrl, expectedStatus: HttpStatusCode.OK_200 }) |
568 | await makeRawRequest(file.fileUrl, HttpStatusCode.OK_200) | 569 | await makeRawRequest({ url: file.fileUrl, expectedStatus: HttpStatusCode.OK_200 }) |
569 | } | 570 | } |
570 | } | 571 | } |
571 | }) | 572 | }) |
diff --git a/server/tests/api/object-storage/live.ts b/server/tests/api/object-storage/live.ts index 7e16b4c89..77f3a8066 100644 --- a/server/tests/api/object-storage/live.ts +++ b/server/tests/api/object-storage/live.ts | |||
@@ -48,7 +48,7 @@ async function checkFilesExist (servers: PeerTubeServer[], videoUUID: string, nu | |||
48 | for (const file of files) { | 48 | for (const file of files) { |
49 | expectStartWith(file.fileUrl, ObjectStorageCommand.getPlaylistBaseUrl()) | 49 | expectStartWith(file.fileUrl, ObjectStorageCommand.getPlaylistBaseUrl()) |
50 | 50 | ||
51 | await makeRawRequest(file.fileUrl, HttpStatusCode.OK_200) | 51 | await makeRawRequest({ url: file.fileUrl, expectedStatus: HttpStatusCode.OK_200 }) |
52 | } | 52 | } |
53 | } | 53 | } |
54 | } | 54 | } |
diff --git a/server/tests/api/object-storage/video-imports.ts b/server/tests/api/object-storage/video-imports.ts index f688c7018..90988ea9a 100644 --- a/server/tests/api/object-storage/video-imports.ts +++ b/server/tests/api/object-storage/video-imports.ts | |||
@@ -66,7 +66,7 @@ describe('Object storage for video import', function () { | |||
66 | const fileUrl = video.files[0].fileUrl | 66 | const fileUrl = video.files[0].fileUrl |
67 | expectStartWith(fileUrl, ObjectStorageCommand.getWebTorrentBaseUrl()) | 67 | expectStartWith(fileUrl, ObjectStorageCommand.getWebTorrentBaseUrl()) |
68 | 68 | ||
69 | await makeRawRequest(fileUrl, HttpStatusCode.OK_200) | 69 | await makeRawRequest({ url: fileUrl, expectedStatus: HttpStatusCode.OK_200 }) |
70 | }) | 70 | }) |
71 | }) | 71 | }) |
72 | 72 | ||
@@ -91,13 +91,13 @@ describe('Object storage for video import', function () { | |||
91 | for (const file of video.files) { | 91 | for (const file of video.files) { |
92 | expectStartWith(file.fileUrl, ObjectStorageCommand.getWebTorrentBaseUrl()) | 92 | expectStartWith(file.fileUrl, ObjectStorageCommand.getWebTorrentBaseUrl()) |
93 | 93 | ||
94 | await makeRawRequest(file.fileUrl, HttpStatusCode.OK_200) | 94 | await makeRawRequest({ url: file.fileUrl, expectedStatus: HttpStatusCode.OK_200 }) |
95 | } | 95 | } |
96 | 96 | ||
97 | for (const file of video.streamingPlaylists[0].files) { | 97 | for (const file of video.streamingPlaylists[0].files) { |
98 | expectStartWith(file.fileUrl, ObjectStorageCommand.getPlaylistBaseUrl()) | 98 | expectStartWith(file.fileUrl, ObjectStorageCommand.getPlaylistBaseUrl()) |
99 | 99 | ||
100 | await makeRawRequest(file.fileUrl, HttpStatusCode.OK_200) | 100 | await makeRawRequest({ url: file.fileUrl, expectedStatus: HttpStatusCode.OK_200 }) |
101 | } | 101 | } |
102 | }) | 102 | }) |
103 | }) | 103 | }) |
diff --git a/server/tests/api/object-storage/videos.ts b/server/tests/api/object-storage/videos.ts index 3e65e1093..63f5179c7 100644 --- a/server/tests/api/object-storage/videos.ts +++ b/server/tests/api/object-storage/videos.ts | |||
@@ -59,11 +59,11 @@ async function checkFiles (options: { | |||
59 | 59 | ||
60 | expectStartWith(file.fileUrl, start) | 60 | expectStartWith(file.fileUrl, start) |
61 | 61 | ||
62 | const res = await makeRawRequest(file.fileDownloadUrl, HttpStatusCode.FOUND_302) | 62 | const res = await makeRawRequest({ url: file.fileDownloadUrl, expectedStatus: HttpStatusCode.FOUND_302 }) |
63 | const location = res.headers['location'] | 63 | const location = res.headers['location'] |
64 | expectStartWith(location, start) | 64 | expectStartWith(location, start) |
65 | 65 | ||
66 | await makeRawRequest(location, HttpStatusCode.OK_200) | 66 | await makeRawRequest({ url: location, expectedStatus: HttpStatusCode.OK_200 }) |
67 | } | 67 | } |
68 | 68 | ||
69 | const hls = video.streamingPlaylists[0] | 69 | const hls = video.streamingPlaylists[0] |
@@ -81,19 +81,19 @@ async function checkFiles (options: { | |||
81 | expectStartWith(hls.playlistUrl, start) | 81 | expectStartWith(hls.playlistUrl, start) |
82 | expectStartWith(hls.segmentsSha256Url, start) | 82 | expectStartWith(hls.segmentsSha256Url, start) |
83 | 83 | ||
84 | await makeRawRequest(hls.playlistUrl, HttpStatusCode.OK_200) | 84 | await makeRawRequest({ url: hls.playlistUrl, expectedStatus: HttpStatusCode.OK_200 }) |
85 | 85 | ||
86 | const resSha = await makeRawRequest(hls.segmentsSha256Url, HttpStatusCode.OK_200) | 86 | const resSha = await makeRawRequest({ url: hls.segmentsSha256Url, expectedStatus: HttpStatusCode.OK_200 }) |
87 | expect(JSON.stringify(resSha.body)).to.not.throw | 87 | expect(JSON.stringify(resSha.body)).to.not.throw |
88 | 88 | ||
89 | for (const file of hls.files) { | 89 | for (const file of hls.files) { |
90 | expectStartWith(file.fileUrl, start) | 90 | expectStartWith(file.fileUrl, start) |
91 | 91 | ||
92 | const res = await makeRawRequest(file.fileDownloadUrl, HttpStatusCode.FOUND_302) | 92 | const res = await makeRawRequest({ url: file.fileDownloadUrl, expectedStatus: HttpStatusCode.FOUND_302 }) |
93 | const location = res.headers['location'] | 93 | const location = res.headers['location'] |
94 | expectStartWith(location, start) | 94 | expectStartWith(location, start) |
95 | 95 | ||
96 | await makeRawRequest(location, HttpStatusCode.OK_200) | 96 | await makeRawRequest({ url: location, expectedStatus: HttpStatusCode.OK_200 }) |
97 | } | 97 | } |
98 | } | 98 | } |
99 | 99 | ||
@@ -104,7 +104,7 @@ async function checkFiles (options: { | |||
104 | expect(torrent.files.length).to.equal(1) | 104 | expect(torrent.files.length).to.equal(1) |
105 | expect(torrent.files[0].path).to.exist.and.to.not.equal('') | 105 | expect(torrent.files[0].path).to.exist.and.to.not.equal('') |
106 | 106 | ||
107 | const res = await makeRawRequest(file.fileUrl, HttpStatusCode.OK_200) | 107 | const res = await makeRawRequest({ url: file.fileUrl, expectedStatus: HttpStatusCode.OK_200 }) |
108 | expect(res.body).to.have.length.above(100) | 108 | expect(res.body).to.have.length.above(100) |
109 | } | 109 | } |
110 | 110 | ||
@@ -220,7 +220,7 @@ function runTestSuite (options: { | |||
220 | 220 | ||
221 | it('Should fetch correctly all the files', async function () { | 221 | it('Should fetch correctly all the files', async function () { |
222 | for (const url of deletedUrls.concat(keptUrls)) { | 222 | for (const url of deletedUrls.concat(keptUrls)) { |
223 | await makeRawRequest(url, HttpStatusCode.OK_200) | 223 | await makeRawRequest({ url, expectedStatus: HttpStatusCode.OK_200 }) |
224 | } | 224 | } |
225 | }) | 225 | }) |
226 | 226 | ||
@@ -231,13 +231,13 @@ function runTestSuite (options: { | |||
231 | await waitJobs(servers) | 231 | await waitJobs(servers) |
232 | 232 | ||
233 | for (const url of deletedUrls) { | 233 | for (const url of deletedUrls) { |
234 | await makeRawRequest(url, HttpStatusCode.NOT_FOUND_404) | 234 | await makeRawRequest({ url, expectedStatus: HttpStatusCode.NOT_FOUND_404 }) |
235 | } | 235 | } |
236 | }) | 236 | }) |
237 | 237 | ||
238 | it('Should have kept other files', async function () { | 238 | it('Should have kept other files', async function () { |
239 | for (const url of keptUrls) { | 239 | for (const url of keptUrls) { |
240 | await makeRawRequest(url, HttpStatusCode.OK_200) | 240 | await makeRawRequest({ url, expectedStatus: HttpStatusCode.OK_200 }) |
241 | } | 241 | } |
242 | }) | 242 | }) |
243 | 243 | ||
diff --git a/server/tests/api/redundancy/redundancy.ts b/server/tests/api/redundancy/redundancy.ts index f349a7a76..ba6b00e0b 100644 --- a/server/tests/api/redundancy/redundancy.ts +++ b/server/tests/api/redundancy/redundancy.ts | |||
@@ -39,7 +39,7 @@ async function checkMagnetWebseeds (file: VideoFile, baseWebseeds: string[], ser | |||
39 | expect(parsed.urlList).to.have.lengthOf(baseWebseeds.length) | 39 | expect(parsed.urlList).to.have.lengthOf(baseWebseeds.length) |
40 | 40 | ||
41 | for (const url of parsed.urlList) { | 41 | for (const url of parsed.urlList) { |
42 | await makeRawRequest(url, HttpStatusCode.OK_200) | 42 | await makeRawRequest({ url, expectedStatus: HttpStatusCode.OK_200 }) |
43 | } | 43 | } |
44 | } | 44 | } |
45 | 45 | ||
diff --git a/server/tests/api/server/open-telemetry.ts b/server/tests/api/server/open-telemetry.ts index 43a27cc32..7a294be82 100644 --- a/server/tests/api/server/open-telemetry.ts +++ b/server/tests/api/server/open-telemetry.ts | |||
@@ -18,7 +18,7 @@ describe('Open Telemetry', function () { | |||
18 | 18 | ||
19 | let hasError = false | 19 | let hasError = false |
20 | try { | 20 | try { |
21 | await makeRawRequest(metricsUrl, HttpStatusCode.NOT_FOUND_404) | 21 | await makeRawRequest({ url: metricsUrl, expectedStatus: HttpStatusCode.NOT_FOUND_404 }) |
22 | } catch (err) { | 22 | } catch (err) { |
23 | hasError = err.message.includes('ECONNREFUSED') | 23 | hasError = err.message.includes('ECONNREFUSED') |
24 | } | 24 | } |
@@ -37,7 +37,7 @@ describe('Open Telemetry', function () { | |||
37 | } | 37 | } |
38 | }) | 38 | }) |
39 | 39 | ||
40 | const res = await makeRawRequest(metricsUrl, HttpStatusCode.OK_200) | 40 | const res = await makeRawRequest({ url: metricsUrl, expectedStatus: HttpStatusCode.OK_200 }) |
41 | expect(res.text).to.contain('peertube_job_queue_total{') | 41 | expect(res.text).to.contain('peertube_job_queue_total{') |
42 | }) | 42 | }) |
43 | 43 | ||
@@ -60,7 +60,7 @@ describe('Open Telemetry', function () { | |||
60 | } | 60 | } |
61 | }) | 61 | }) |
62 | 62 | ||
63 | const res = await makeRawRequest(metricsUrl, HttpStatusCode.OK_200) | 63 | const res = await makeRawRequest({ url: metricsUrl, expectedStatus: HttpStatusCode.OK_200 }) |
64 | expect(res.text).to.contain('peertube_playback_http_downloaded_bytes_total{') | 64 | expect(res.text).to.contain('peertube_playback_http_downloaded_bytes_total{') |
65 | }) | 65 | }) |
66 | 66 | ||
diff --git a/server/tests/api/transcoding/create-transcoding.ts b/server/tests/api/transcoding/create-transcoding.ts index a50bf7654..372f5332a 100644 --- a/server/tests/api/transcoding/create-transcoding.ts +++ b/server/tests/api/transcoding/create-transcoding.ts | |||
@@ -20,7 +20,7 @@ import { | |||
20 | async function checkFilesInObjectStorage (video: VideoDetails) { | 20 | async function checkFilesInObjectStorage (video: VideoDetails) { |
21 | for (const file of video.files) { | 21 | for (const file of video.files) { |
22 | expectStartWith(file.fileUrl, ObjectStorageCommand.getWebTorrentBaseUrl()) | 22 | expectStartWith(file.fileUrl, ObjectStorageCommand.getWebTorrentBaseUrl()) |
23 | await makeRawRequest(file.fileUrl, HttpStatusCode.OK_200) | 23 | await makeRawRequest({ url: file.fileUrl, expectedStatus: HttpStatusCode.OK_200 }) |
24 | } | 24 | } |
25 | 25 | ||
26 | if (video.streamingPlaylists.length === 0) return | 26 | if (video.streamingPlaylists.length === 0) return |
@@ -28,14 +28,14 @@ async function checkFilesInObjectStorage (video: VideoDetails) { | |||
28 | const hlsPlaylist = video.streamingPlaylists[0] | 28 | const hlsPlaylist = video.streamingPlaylists[0] |
29 | for (const file of hlsPlaylist.files) { | 29 | for (const file of hlsPlaylist.files) { |
30 | expectStartWith(file.fileUrl, ObjectStorageCommand.getPlaylistBaseUrl()) | 30 | expectStartWith(file.fileUrl, ObjectStorageCommand.getPlaylistBaseUrl()) |
31 | await makeRawRequest(file.fileUrl, HttpStatusCode.OK_200) | 31 | await makeRawRequest({ url: file.fileUrl, expectedStatus: HttpStatusCode.OK_200 }) |
32 | } | 32 | } |
33 | 33 | ||
34 | expectStartWith(hlsPlaylist.playlistUrl, ObjectStorageCommand.getPlaylistBaseUrl()) | 34 | expectStartWith(hlsPlaylist.playlistUrl, ObjectStorageCommand.getPlaylistBaseUrl()) |
35 | await makeRawRequest(hlsPlaylist.playlistUrl, HttpStatusCode.OK_200) | 35 | await makeRawRequest({ url: hlsPlaylist.playlistUrl, expectedStatus: HttpStatusCode.OK_200 }) |
36 | 36 | ||
37 | expectStartWith(hlsPlaylist.segmentsSha256Url, ObjectStorageCommand.getPlaylistBaseUrl()) | 37 | expectStartWith(hlsPlaylist.segmentsSha256Url, ObjectStorageCommand.getPlaylistBaseUrl()) |
38 | await makeRawRequest(hlsPlaylist.segmentsSha256Url, HttpStatusCode.OK_200) | 38 | await makeRawRequest({ url: hlsPlaylist.segmentsSha256Url, expectedStatus: HttpStatusCode.OK_200 }) |
39 | } | 39 | } |
40 | 40 | ||
41 | function runTests (objectStorage: boolean) { | 41 | function runTests (objectStorage: boolean) { |
@@ -234,7 +234,7 @@ function runTests (objectStorage: boolean) { | |||
234 | 234 | ||
235 | it('Should have correctly deleted previous files', async function () { | 235 | it('Should have correctly deleted previous files', async function () { |
236 | for (const fileUrl of shouldBeDeleted) { | 236 | for (const fileUrl of shouldBeDeleted) { |
237 | await makeRawRequest(fileUrl, HttpStatusCode.NOT_FOUND_404) | 237 | await makeRawRequest({ url: fileUrl, expectedStatus: HttpStatusCode.NOT_FOUND_404 }) |
238 | } | 238 | } |
239 | }) | 239 | }) |
240 | 240 | ||
diff --git a/server/tests/api/transcoding/hls.ts b/server/tests/api/transcoding/hls.ts index 252422e5d..7b5492cd4 100644 --- a/server/tests/api/transcoding/hls.ts +++ b/server/tests/api/transcoding/hls.ts | |||
@@ -1,168 +1,48 @@ | |||
1 | /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */ | 1 | /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */ |
2 | 2 | ||
3 | import { expect } from 'chai' | 3 | import { join } from 'path' |
4 | import { basename, join } from 'path' | 4 | import { checkDirectoryIsEmpty, checkTmpIsEmpty, completeCheckHlsPlaylist } from '@server/tests/shared' |
5 | import { | 5 | import { areObjectStorageTestsDisabled } from '@shared/core-utils' |
6 | checkDirectoryIsEmpty, | 6 | import { HttpStatusCode } from '@shared/models' |
7 | checkResolutionsInMasterPlaylist, | ||
8 | checkSegmentHash, | ||
9 | checkTmpIsEmpty, | ||
10 | expectStartWith, | ||
11 | hlsInfohashExist | ||
12 | } from '@server/tests/shared' | ||
13 | import { areObjectStorageTestsDisabled, removeFragmentedMP4Ext, uuidRegex } from '@shared/core-utils' | ||
14 | import { HttpStatusCode, VideoStreamingPlaylistType } from '@shared/models' | ||
15 | import { | 7 | import { |
16 | cleanupTests, | 8 | cleanupTests, |
17 | createMultipleServers, | 9 | createMultipleServers, |
18 | doubleFollow, | 10 | doubleFollow, |
19 | makeRawRequest, | ||
20 | ObjectStorageCommand, | 11 | ObjectStorageCommand, |
21 | PeerTubeServer, | 12 | PeerTubeServer, |
22 | setAccessTokensToServers, | 13 | setAccessTokensToServers, |
23 | waitJobs, | 14 | waitJobs |
24 | webtorrentAdd | ||
25 | } from '@shared/server-commands' | 15 | } from '@shared/server-commands' |
26 | import { DEFAULT_AUDIO_RESOLUTION } from '../../../initializers/constants' | 16 | import { DEFAULT_AUDIO_RESOLUTION } from '../../../initializers/constants' |
27 | 17 | ||
28 | async function checkHlsPlaylist (options: { | ||
29 | servers: PeerTubeServer[] | ||
30 | videoUUID: string | ||
31 | hlsOnly: boolean | ||
32 | |||
33 | resolutions?: number[] | ||
34 | objectStorageBaseUrl: string | ||
35 | }) { | ||
36 | const { videoUUID, hlsOnly, objectStorageBaseUrl } = options | ||
37 | |||
38 | const resolutions = options.resolutions ?? [ 240, 360, 480, 720 ] | ||
39 | |||
40 | for (const server of options.servers) { | ||
41 | const videoDetails = await server.videos.get({ id: videoUUID }) | ||
42 | const baseUrl = `http://${videoDetails.account.host}` | ||
43 | |||
44 | expect(videoDetails.streamingPlaylists).to.have.lengthOf(1) | ||
45 | |||
46 | const hlsPlaylist = videoDetails.streamingPlaylists.find(p => p.type === VideoStreamingPlaylistType.HLS) | ||
47 | expect(hlsPlaylist).to.not.be.undefined | ||
48 | |||
49 | const hlsFiles = hlsPlaylist.files | ||
50 | expect(hlsFiles).to.have.lengthOf(resolutions.length) | ||
51 | |||
52 | if (hlsOnly) expect(videoDetails.files).to.have.lengthOf(0) | ||
53 | else expect(videoDetails.files).to.have.lengthOf(resolutions.length) | ||
54 | |||
55 | // Check JSON files | ||
56 | for (const resolution of resolutions) { | ||
57 | const file = hlsFiles.find(f => f.resolution.id === resolution) | ||
58 | expect(file).to.not.be.undefined | ||
59 | |||
60 | expect(file.magnetUri).to.have.lengthOf.above(2) | ||
61 | expect(file.torrentUrl).to.match( | ||
62 | new RegExp(`http://${server.host}/lazy-static/torrents/${uuidRegex}-${file.resolution.id}-hls.torrent`) | ||
63 | ) | ||
64 | |||
65 | if (objectStorageBaseUrl) { | ||
66 | expectStartWith(file.fileUrl, objectStorageBaseUrl) | ||
67 | } else { | ||
68 | expect(file.fileUrl).to.match( | ||
69 | new RegExp(`${baseUrl}/static/streaming-playlists/hls/${videoDetails.uuid}/${uuidRegex}-${file.resolution.id}-fragmented.mp4`) | ||
70 | ) | ||
71 | } | ||
72 | |||
73 | expect(file.resolution.label).to.equal(resolution + 'p') | ||
74 | |||
75 | await makeRawRequest(file.torrentUrl, HttpStatusCode.OK_200) | ||
76 | await makeRawRequest(file.fileUrl, HttpStatusCode.OK_200) | ||
77 | |||
78 | const torrent = await webtorrentAdd(file.magnetUri, true) | ||
79 | expect(torrent.files).to.be.an('array') | ||
80 | expect(torrent.files.length).to.equal(1) | ||
81 | expect(torrent.files[0].path).to.exist.and.to.not.equal('') | ||
82 | } | ||
83 | |||
84 | // Check master playlist | ||
85 | { | ||
86 | await checkResolutionsInMasterPlaylist({ server, playlistUrl: hlsPlaylist.playlistUrl, resolutions }) | ||
87 | |||
88 | const masterPlaylist = await server.streamingPlaylists.get({ url: hlsPlaylist.playlistUrl }) | ||
89 | |||
90 | let i = 0 | ||
91 | for (const resolution of resolutions) { | ||
92 | expect(masterPlaylist).to.contain(`${resolution}.m3u8`) | ||
93 | expect(masterPlaylist).to.contain(`${resolution}.m3u8`) | ||
94 | |||
95 | const url = 'http://' + videoDetails.account.host | ||
96 | await hlsInfohashExist(url, hlsPlaylist.playlistUrl, i) | ||
97 | |||
98 | i++ | ||
99 | } | ||
100 | } | ||
101 | |||
102 | // Check resolution playlists | ||
103 | { | ||
104 | for (const resolution of resolutions) { | ||
105 | const file = hlsFiles.find(f => f.resolution.id === resolution) | ||
106 | const playlistName = removeFragmentedMP4Ext(basename(file.fileUrl)) + '.m3u8' | ||
107 | |||
108 | const url = objectStorageBaseUrl | ||
109 | ? `${objectStorageBaseUrl}hls/${videoUUID}/${playlistName}` | ||
110 | : `${baseUrl}/static/streaming-playlists/hls/${videoUUID}/${playlistName}` | ||
111 | |||
112 | const subPlaylist = await server.streamingPlaylists.get({ url }) | ||
113 | |||
114 | expect(subPlaylist).to.match(new RegExp(`${uuidRegex}-${resolution}-fragmented.mp4`)) | ||
115 | expect(subPlaylist).to.contain(basename(file.fileUrl)) | ||
116 | } | ||
117 | } | ||
118 | |||
119 | { | ||
120 | const baseUrlAndPath = objectStorageBaseUrl | ||
121 | ? objectStorageBaseUrl + 'hls/' + videoUUID | ||
122 | : baseUrl + '/static/streaming-playlists/hls/' + videoUUID | ||
123 | |||
124 | for (const resolution of resolutions) { | ||
125 | await checkSegmentHash({ | ||
126 | server, | ||
127 | baseUrlPlaylist: baseUrlAndPath, | ||
128 | baseUrlSegment: baseUrlAndPath, | ||
129 | resolution, | ||
130 | hlsPlaylist | ||
131 | }) | ||
132 | } | ||
133 | } | ||
134 | } | ||
135 | } | ||
136 | |||
137 | describe('Test HLS videos', function () { | 18 | describe('Test HLS videos', function () { |
138 | let servers: PeerTubeServer[] = [] | 19 | let servers: PeerTubeServer[] = [] |
139 | let videoUUID = '' | ||
140 | let videoAudioUUID = '' | ||
141 | 20 | ||
142 | function runTestSuite (hlsOnly: boolean, objectStorageBaseUrl?: string) { | 21 | function runTestSuite (hlsOnly: boolean, objectStorageBaseUrl?: string) { |
22 | const videoUUIDs: string[] = [] | ||
143 | 23 | ||
144 | it('Should upload a video and transcode it to HLS', async function () { | 24 | it('Should upload a video and transcode it to HLS', async function () { |
145 | this.timeout(120000) | 25 | this.timeout(120000) |
146 | 26 | ||
147 | const { uuid } = await servers[0].videos.upload({ attributes: { name: 'video 1', fixture: 'video_short.webm' } }) | 27 | const { uuid } = await servers[0].videos.upload({ attributes: { name: 'video 1', fixture: 'video_short.webm' } }) |
148 | videoUUID = uuid | 28 | videoUUIDs.push(uuid) |
149 | 29 | ||
150 | await waitJobs(servers) | 30 | await waitJobs(servers) |
151 | 31 | ||
152 | await checkHlsPlaylist({ servers, videoUUID, hlsOnly, objectStorageBaseUrl }) | 32 | await completeCheckHlsPlaylist({ servers, videoUUID: uuid, hlsOnly, objectStorageBaseUrl }) |
153 | }) | 33 | }) |
154 | 34 | ||
155 | it('Should upload an audio file and transcode it to HLS', async function () { | 35 | it('Should upload an audio file and transcode it to HLS', async function () { |
156 | this.timeout(120000) | 36 | this.timeout(120000) |
157 | 37 | ||
158 | const { uuid } = await servers[0].videos.upload({ attributes: { name: 'video audio', fixture: 'sample.ogg' } }) | 38 | const { uuid } = await servers[0].videos.upload({ attributes: { name: 'video audio', fixture: 'sample.ogg' } }) |
159 | videoAudioUUID = uuid | 39 | videoUUIDs.push(uuid) |
160 | 40 | ||
161 | await waitJobs(servers) | 41 | await waitJobs(servers) |
162 | 42 | ||
163 | await checkHlsPlaylist({ | 43 | await completeCheckHlsPlaylist({ |
164 | servers, | 44 | servers, |
165 | videoUUID: videoAudioUUID, | 45 | videoUUID: uuid, |
166 | hlsOnly, | 46 | hlsOnly, |
167 | resolutions: [ DEFAULT_AUDIO_RESOLUTION, 360, 240 ], | 47 | resolutions: [ DEFAULT_AUDIO_RESOLUTION, 360, 240 ], |
168 | objectStorageBaseUrl | 48 | objectStorageBaseUrl |
@@ -172,31 +52,36 @@ describe('Test HLS videos', function () { | |||
172 | it('Should update the video', async function () { | 52 | it('Should update the video', async function () { |
173 | this.timeout(30000) | 53 | this.timeout(30000) |
174 | 54 | ||
175 | await servers[0].videos.update({ id: videoUUID, attributes: { name: 'video 1 updated' } }) | 55 | await servers[0].videos.update({ id: videoUUIDs[0], attributes: { name: 'video 1 updated' } }) |
176 | 56 | ||
177 | await waitJobs(servers) | 57 | await waitJobs(servers) |
178 | 58 | ||
179 | await checkHlsPlaylist({ servers, videoUUID, hlsOnly, objectStorageBaseUrl }) | 59 | await completeCheckHlsPlaylist({ servers, videoUUID: videoUUIDs[0], hlsOnly, objectStorageBaseUrl }) |
180 | }) | 60 | }) |
181 | 61 | ||
182 | it('Should delete videos', async function () { | 62 | it('Should delete videos', async function () { |
183 | this.timeout(10000) | 63 | this.timeout(10000) |
184 | 64 | ||
185 | await servers[0].videos.remove({ id: videoUUID }) | 65 | for (const uuid of videoUUIDs) { |
186 | await servers[0].videos.remove({ id: videoAudioUUID }) | 66 | await servers[0].videos.remove({ id: uuid }) |
67 | } | ||
187 | 68 | ||
188 | await waitJobs(servers) | 69 | await waitJobs(servers) |
189 | 70 | ||
190 | for (const server of servers) { | 71 | for (const server of servers) { |
191 | await server.videos.get({ id: videoUUID, expectedStatus: HttpStatusCode.NOT_FOUND_404 }) | 72 | for (const uuid of videoUUIDs) { |
192 | await server.videos.get({ id: videoAudioUUID, expectedStatus: HttpStatusCode.NOT_FOUND_404 }) | 73 | await server.videos.get({ id: uuid, expectedStatus: HttpStatusCode.NOT_FOUND_404 }) |
74 | } | ||
193 | } | 75 | } |
194 | }) | 76 | }) |
195 | 77 | ||
196 | it('Should have the playlists/segment deleted from the disk', async function () { | 78 | it('Should have the playlists/segment deleted from the disk', async function () { |
197 | for (const server of servers) { | 79 | for (const server of servers) { |
198 | await checkDirectoryIsEmpty(server, 'videos') | 80 | await checkDirectoryIsEmpty(server, 'videos', [ 'private' ]) |
199 | await checkDirectoryIsEmpty(server, join('streaming-playlists', 'hls')) | 81 | await checkDirectoryIsEmpty(server, join('videos', 'private')) |
82 | |||
83 | await checkDirectoryIsEmpty(server, join('streaming-playlists', 'hls'), [ 'private' ]) | ||
84 | await checkDirectoryIsEmpty(server, join('streaming-playlists', 'hls', 'private')) | ||
200 | } | 85 | } |
201 | }) | 86 | }) |
202 | 87 | ||
diff --git a/server/tests/api/transcoding/index.ts b/server/tests/api/transcoding/index.ts index 0cc28b4a4..9866418d6 100644 --- a/server/tests/api/transcoding/index.ts +++ b/server/tests/api/transcoding/index.ts | |||
@@ -2,4 +2,5 @@ export * from './audio-only' | |||
2 | export * from './create-transcoding' | 2 | export * from './create-transcoding' |
3 | export * from './hls' | 3 | export * from './hls' |
4 | export * from './transcoder' | 4 | export * from './transcoder' |
5 | export * from './update-while-transcoding' | ||
5 | export * from './video-studio' | 6 | export * from './video-studio' |
diff --git a/server/tests/api/transcoding/update-while-transcoding.ts b/server/tests/api/transcoding/update-while-transcoding.ts new file mode 100644 index 000000000..5ca923392 --- /dev/null +++ b/server/tests/api/transcoding/update-while-transcoding.ts | |||
@@ -0,0 +1,151 @@ | |||
1 | /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */ | ||
2 | |||
3 | import { completeCheckHlsPlaylist } from '@server/tests/shared' | ||
4 | import { areObjectStorageTestsDisabled, wait } from '@shared/core-utils' | ||
5 | import { VideoPrivacy } from '@shared/models' | ||
6 | import { | ||
7 | cleanupTests, | ||
8 | createMultipleServers, | ||
9 | doubleFollow, | ||
10 | ObjectStorageCommand, | ||
11 | PeerTubeServer, | ||
12 | setAccessTokensToServers, | ||
13 | waitJobs | ||
14 | } from '@shared/server-commands' | ||
15 | |||
16 | describe('Test update video privacy while transcoding', function () { | ||
17 | let servers: PeerTubeServer[] = [] | ||
18 | |||
19 | const videoUUIDs: string[] = [] | ||
20 | |||
21 | function runTestSuite (hlsOnly: boolean, objectStorageBaseUrl?: string) { | ||
22 | |||
23 | it('Should not have an error while quickly updating a private video to public after upload #1', async function () { | ||
24 | this.timeout(360_000) | ||
25 | |||
26 | const attributes = { | ||
27 | name: 'quick update', | ||
28 | privacy: VideoPrivacy.PRIVATE | ||
29 | } | ||
30 | |||
31 | const { uuid } = await servers[0].videos.upload({ attributes, waitTorrentGeneration: false }) | ||
32 | await servers[0].videos.update({ id: uuid, attributes: { privacy: VideoPrivacy.PUBLIC } }) | ||
33 | videoUUIDs.push(uuid) | ||
34 | |||
35 | await waitJobs(servers) | ||
36 | |||
37 | await completeCheckHlsPlaylist({ servers, videoUUID: uuid, hlsOnly, objectStorageBaseUrl }) | ||
38 | }) | ||
39 | |||
40 | it('Should not have an error while quickly updating a private video to public after upload #2', async function () { | ||
41 | |||
42 | { | ||
43 | const attributes = { | ||
44 | name: 'quick update 2', | ||
45 | privacy: VideoPrivacy.PRIVATE | ||
46 | } | ||
47 | |||
48 | const { uuid } = await servers[0].videos.upload({ attributes, waitTorrentGeneration: true }) | ||
49 | await servers[0].videos.update({ id: uuid, attributes: { privacy: VideoPrivacy.PUBLIC } }) | ||
50 | videoUUIDs.push(uuid) | ||
51 | |||
52 | await waitJobs(servers) | ||
53 | |||
54 | await completeCheckHlsPlaylist({ servers, videoUUID: uuid, hlsOnly, objectStorageBaseUrl }) | ||
55 | } | ||
56 | }) | ||
57 | |||
58 | it('Should not have an error while quickly updating a private video to public after upload #3', async function () { | ||
59 | const attributes = { | ||
60 | name: 'quick update 3', | ||
61 | privacy: VideoPrivacy.PRIVATE | ||
62 | } | ||
63 | |||
64 | const { uuid } = await servers[0].videos.upload({ attributes, waitTorrentGeneration: true }) | ||
65 | await wait(1000) | ||
66 | await servers[0].videos.update({ id: uuid, attributes: { privacy: VideoPrivacy.PUBLIC } }) | ||
67 | videoUUIDs.push(uuid) | ||
68 | |||
69 | await waitJobs(servers) | ||
70 | |||
71 | await completeCheckHlsPlaylist({ servers, videoUUID: uuid, hlsOnly, objectStorageBaseUrl }) | ||
72 | }) | ||
73 | } | ||
74 | |||
75 | before(async function () { | ||
76 | this.timeout(120000) | ||
77 | |||
78 | const configOverride = { | ||
79 | transcoding: { | ||
80 | enabled: true, | ||
81 | allow_audio_files: true, | ||
82 | hls: { | ||
83 | enabled: true | ||
84 | } | ||
85 | } | ||
86 | } | ||
87 | servers = await createMultipleServers(2, configOverride) | ||
88 | |||
89 | // Get the access tokens | ||
90 | await setAccessTokensToServers(servers) | ||
91 | |||
92 | // Server 1 and server 2 follow each other | ||
93 | await doubleFollow(servers[0], servers[1]) | ||
94 | }) | ||
95 | |||
96 | describe('With WebTorrent & HLS enabled', function () { | ||
97 | runTestSuite(false) | ||
98 | }) | ||
99 | |||
100 | describe('With only HLS enabled', function () { | ||
101 | |||
102 | before(async function () { | ||
103 | await servers[0].config.updateCustomSubConfig({ | ||
104 | newConfig: { | ||
105 | transcoding: { | ||
106 | enabled: true, | ||
107 | allowAudioFiles: true, | ||
108 | resolutions: { | ||
109 | '144p': false, | ||
110 | '240p': true, | ||
111 | '360p': true, | ||
112 | '480p': true, | ||
113 | '720p': true, | ||
114 | '1080p': true, | ||
115 | '1440p': true, | ||
116 | '2160p': true | ||
117 | }, | ||
118 | hls: { | ||
119 | enabled: true | ||
120 | }, | ||
121 | webtorrent: { | ||
122 | enabled: false | ||
123 | } | ||
124 | } | ||
125 | } | ||
126 | }) | ||
127 | }) | ||
128 | |||
129 | runTestSuite(true) | ||
130 | }) | ||
131 | |||
132 | describe('With object storage enabled', function () { | ||
133 | if (areObjectStorageTestsDisabled()) return | ||
134 | |||
135 | before(async function () { | ||
136 | this.timeout(120000) | ||
137 | |||
138 | const configOverride = ObjectStorageCommand.getDefaultConfig() | ||
139 | await ObjectStorageCommand.prepareDefaultBuckets() | ||
140 | |||
141 | await servers[0].kill() | ||
142 | await servers[0].run(configOverride) | ||
143 | }) | ||
144 | |||
145 | runTestSuite(true, ObjectStorageCommand.getPlaylistBaseUrl()) | ||
146 | }) | ||
147 | |||
148 | after(async function () { | ||
149 | await cleanupTests(servers) | ||
150 | }) | ||
151 | }) | ||
diff --git a/server/tests/api/videos/index.ts b/server/tests/api/videos/index.ts index 266155297..357c08199 100644 --- a/server/tests/api/videos/index.ts +++ b/server/tests/api/videos/index.ts | |||
@@ -19,3 +19,4 @@ import './videos-common-filters' | |||
19 | import './videos-history' | 19 | import './videos-history' |
20 | import './videos-overview' | 20 | import './videos-overview' |
21 | import './video-source' | 21 | import './video-source' |
22 | import './video-static-file-privacy' | ||
diff --git a/server/tests/api/videos/video-files.ts b/server/tests/api/videos/video-files.ts index c0b886aad..8c913bf31 100644 --- a/server/tests/api/videos/video-files.ts +++ b/server/tests/api/videos/video-files.ts | |||
@@ -153,7 +153,7 @@ describe('Test videos files', function () { | |||
153 | expect(video.streamingPlaylists[0].files).to.have.lengthOf(files.length - 1) | 153 | expect(video.streamingPlaylists[0].files).to.have.lengthOf(files.length - 1) |
154 | expect(video.streamingPlaylists[0].files.find(f => f.id === toDelete.id)).to.not.exist | 154 | expect(video.streamingPlaylists[0].files.find(f => f.id === toDelete.id)).to.not.exist |
155 | 155 | ||
156 | const { text } = await makeRawRequest(video.streamingPlaylists[0].playlistUrl) | 156 | const { text } = await makeRawRequest({ url: video.streamingPlaylists[0].playlistUrl, expectedStatus: HttpStatusCode.OK_200 }) |
157 | 157 | ||
158 | expect(text.includes(`-${toDelete.resolution.id}.m3u8`)).to.be.false | 158 | expect(text.includes(`-${toDelete.resolution.id}.m3u8`)).to.be.false |
159 | expect(text.includes(`-${video.streamingPlaylists[0].files[0].resolution.id}.m3u8`)).to.be.true | 159 | expect(text.includes(`-${video.streamingPlaylists[0].files[0].resolution.id}.m3u8`)).to.be.true |
diff --git a/server/tests/api/videos/video-static-file-privacy.ts b/server/tests/api/videos/video-static-file-privacy.ts new file mode 100644 index 000000000..e38fdec6e --- /dev/null +++ b/server/tests/api/videos/video-static-file-privacy.ts | |||
@@ -0,0 +1,389 @@ | |||
1 | /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */ | ||
2 | |||
3 | import { expect } from 'chai' | ||
4 | import { decode } from 'magnet-uri' | ||
5 | import { expectStartWith } from '@server/tests/shared' | ||
6 | import { getAllFiles, wait } from '@shared/core-utils' | ||
7 | import { HttpStatusCode, LiveVideo, VideoDetails, VideoPrivacy } from '@shared/models' | ||
8 | import { | ||
9 | cleanupTests, | ||
10 | createSingleServer, | ||
11 | findExternalSavedVideo, | ||
12 | makeRawRequest, | ||
13 | parseTorrentVideo, | ||
14 | PeerTubeServer, | ||
15 | sendRTMPStream, | ||
16 | setAccessTokensToServers, | ||
17 | setDefaultVideoChannel, | ||
18 | stopFfmpeg, | ||
19 | waitJobs | ||
20 | } from '@shared/server-commands' | ||
21 | |||
22 | describe('Test video static file privacy', function () { | ||
23 | let server: PeerTubeServer | ||
24 | let userToken: string | ||
25 | |||
26 | before(async function () { | ||
27 | this.timeout(50000) | ||
28 | |||
29 | server = await createSingleServer(1) | ||
30 | await setAccessTokensToServers([ server ]) | ||
31 | await setDefaultVideoChannel([ server ]) | ||
32 | |||
33 | userToken = await server.users.generateUserAndToken('user1') | ||
34 | }) | ||
35 | |||
36 | describe('VOD static file path', function () { | ||
37 | |||
38 | function runSuite () { | ||
39 | |||
40 | async function checkPrivateWebTorrentFiles (uuid: string) { | ||
41 | const video = await server.videos.getWithToken({ id: uuid }) | ||
42 | |||
43 | for (const file of video.files) { | ||
44 | expect(file.fileDownloadUrl).to.not.include('/private/') | ||
45 | expectStartWith(file.fileUrl, server.url + '/static/webseed/private/') | ||
46 | |||
47 | const torrent = await parseTorrentVideo(server, file) | ||
48 | expect(torrent.urlList).to.have.lengthOf(0) | ||
49 | |||
50 | const magnet = decode(file.magnetUri) | ||
51 | expect(magnet.urlList).to.have.lengthOf(0) | ||
52 | |||
53 | await makeRawRequest({ url: file.fileUrl, token: server.accessToken, expectedStatus: HttpStatusCode.OK_200 }) | ||
54 | } | ||
55 | |||
56 | const hls = video.streamingPlaylists[0] | ||
57 | if (hls) { | ||
58 | expectStartWith(hls.playlistUrl, server.url + '/static/streaming-playlists/hls/private/') | ||
59 | expectStartWith(hls.segmentsSha256Url, server.url + '/static/streaming-playlists/hls/private/') | ||
60 | |||
61 | await makeRawRequest({ url: hls.playlistUrl, token: server.accessToken, expectedStatus: HttpStatusCode.OK_200 }) | ||
62 | await makeRawRequest({ url: hls.segmentsSha256Url, token: server.accessToken, expectedStatus: HttpStatusCode.OK_200 }) | ||
63 | } | ||
64 | } | ||
65 | |||
66 | async function checkPublicWebTorrentFiles (uuid: string) { | ||
67 | const video = await server.videos.get({ id: uuid }) | ||
68 | |||
69 | for (const file of getAllFiles(video)) { | ||
70 | expect(file.fileDownloadUrl).to.not.include('/private/') | ||
71 | expect(file.fileUrl).to.not.include('/private/') | ||
72 | |||
73 | const torrent = await parseTorrentVideo(server, file) | ||
74 | expect(torrent.urlList[0]).to.not.include('private') | ||
75 | |||
76 | const magnet = decode(file.magnetUri) | ||
77 | expect(magnet.urlList[0]).to.not.include('private') | ||
78 | |||
79 | await makeRawRequest({ url: file.fileUrl, expectedStatus: HttpStatusCode.OK_200 }) | ||
80 | await makeRawRequest({ url: torrent.urlList[0], expectedStatus: HttpStatusCode.OK_200 }) | ||
81 | await makeRawRequest({ url: magnet.urlList[0], expectedStatus: HttpStatusCode.OK_200 }) | ||
82 | } | ||
83 | |||
84 | const hls = video.streamingPlaylists[0] | ||
85 | if (hls) { | ||
86 | expect(hls.playlistUrl).to.not.include('private') | ||
87 | expect(hls.segmentsSha256Url).to.not.include('private') | ||
88 | |||
89 | await makeRawRequest({ url: hls.playlistUrl, expectedStatus: HttpStatusCode.OK_200 }) | ||
90 | await makeRawRequest({ url: hls.segmentsSha256Url, expectedStatus: HttpStatusCode.OK_200 }) | ||
91 | } | ||
92 | } | ||
93 | |||
94 | it('Should upload a private/internal video and have a private static path', async function () { | ||
95 | this.timeout(120000) | ||
96 | |||
97 | for (const privacy of [ VideoPrivacy.PRIVATE, VideoPrivacy.INTERNAL ]) { | ||
98 | const { uuid } = await server.videos.quickUpload({ name: 'video', privacy }) | ||
99 | await waitJobs([ server ]) | ||
100 | |||
101 | await checkPrivateWebTorrentFiles(uuid) | ||
102 | } | ||
103 | }) | ||
104 | |||
105 | it('Should upload a public video and update it as private/internal to have a private static path', async function () { | ||
106 | this.timeout(120000) | ||
107 | |||
108 | for (const privacy of [ VideoPrivacy.PRIVATE, VideoPrivacy.INTERNAL ]) { | ||
109 | const { uuid } = await server.videos.quickUpload({ name: 'video', privacy: VideoPrivacy.PUBLIC }) | ||
110 | await waitJobs([ server ]) | ||
111 | |||
112 | await server.videos.update({ id: uuid, attributes: { privacy } }) | ||
113 | await waitJobs([ server ]) | ||
114 | |||
115 | await checkPrivateWebTorrentFiles(uuid) | ||
116 | } | ||
117 | }) | ||
118 | |||
119 | it('Should upload a private video and update it to unlisted to have a public static path', async function () { | ||
120 | this.timeout(120000) | ||
121 | |||
122 | const { uuid } = await server.videos.quickUpload({ name: 'video', privacy: VideoPrivacy.PRIVATE }) | ||
123 | await waitJobs([ server ]) | ||
124 | |||
125 | await server.videos.update({ id: uuid, attributes: { privacy: VideoPrivacy.UNLISTED } }) | ||
126 | await waitJobs([ server ]) | ||
127 | |||
128 | await checkPublicWebTorrentFiles(uuid) | ||
129 | }) | ||
130 | |||
131 | it('Should upload an internal video and update it to public to have a public static path', async function () { | ||
132 | this.timeout(120000) | ||
133 | |||
134 | const { uuid } = await server.videos.quickUpload({ name: 'video', privacy: VideoPrivacy.INTERNAL }) | ||
135 | await waitJobs([ server ]) | ||
136 | |||
137 | await server.videos.update({ id: uuid, attributes: { privacy: VideoPrivacy.PUBLIC } }) | ||
138 | await waitJobs([ server ]) | ||
139 | |||
140 | await checkPublicWebTorrentFiles(uuid) | ||
141 | }) | ||
142 | |||
143 | it('Should upload an internal video and schedule a public publish', async function () { | ||
144 | this.timeout(120000) | ||
145 | |||
146 | const attributes = { | ||
147 | name: 'video', | ||
148 | privacy: VideoPrivacy.PRIVATE, | ||
149 | scheduleUpdate: { | ||
150 | updateAt: new Date(Date.now() + 1000).toISOString(), | ||
151 | privacy: VideoPrivacy.PUBLIC as VideoPrivacy.PUBLIC | ||
152 | } | ||
153 | } | ||
154 | |||
155 | const { uuid } = await server.videos.upload({ attributes }) | ||
156 | |||
157 | await waitJobs([ server ]) | ||
158 | await wait(1000) | ||
159 | await server.debug.sendCommand({ body: { command: 'process-update-videos-scheduler' } }) | ||
160 | |||
161 | await waitJobs([ server ]) | ||
162 | |||
163 | await checkPublicWebTorrentFiles(uuid) | ||
164 | }) | ||
165 | } | ||
166 | |||
167 | describe('Without transcoding', function () { | ||
168 | runSuite() | ||
169 | }) | ||
170 | |||
171 | describe('With transcoding', function () { | ||
172 | |||
173 | before(async function () { | ||
174 | await server.config.enableMinimumTranscoding() | ||
175 | }) | ||
176 | |||
177 | runSuite() | ||
178 | }) | ||
179 | }) | ||
180 | |||
181 | describe('VOD static file right check', function () { | ||
182 | let unrelatedFileToken: string | ||
183 | |||
184 | async function checkVideoFiles (options: { | ||
185 | id: string | ||
186 | expectedStatus: HttpStatusCode | ||
187 | token: string | ||
188 | videoFileToken: string | ||
189 | }) { | ||
190 | const { id, expectedStatus, token, videoFileToken } = options | ||
191 | |||
192 | const video = await server.videos.getWithToken({ id }) | ||
193 | |||
194 | for (const file of getAllFiles(video)) { | ||
195 | await makeRawRequest({ url: file.fileUrl, token, expectedStatus }) | ||
196 | await makeRawRequest({ url: file.fileDownloadUrl, token, expectedStatus }) | ||
197 | |||
198 | await makeRawRequest({ url: file.fileUrl, query: { videoFileToken }, expectedStatus }) | ||
199 | await makeRawRequest({ url: file.fileDownloadUrl, query: { videoFileToken }, expectedStatus }) | ||
200 | } | ||
201 | |||
202 | const hls = video.streamingPlaylists[0] | ||
203 | await makeRawRequest({ url: hls.playlistUrl, token, expectedStatus }) | ||
204 | await makeRawRequest({ url: hls.segmentsSha256Url, token, expectedStatus }) | ||
205 | |||
206 | await makeRawRequest({ url: hls.playlistUrl, query: { videoFileToken }, expectedStatus }) | ||
207 | await makeRawRequest({ url: hls.segmentsSha256Url, query: { videoFileToken }, expectedStatus }) | ||
208 | } | ||
209 | |||
210 | before(async function () { | ||
211 | await server.config.enableMinimumTranscoding() | ||
212 | |||
213 | const { uuid } = await server.videos.quickUpload({ name: 'another video' }) | ||
214 | unrelatedFileToken = await server.videoToken.getVideoFileToken({ videoId: uuid }) | ||
215 | }) | ||
216 | |||
217 | it('Should not be able to access a private video files without OAuth token and file token', async function () { | ||
218 | this.timeout(120000) | ||
219 | |||
220 | const { uuid } = await server.videos.quickUpload({ name: 'video', privacy: VideoPrivacy.INTERNAL }) | ||
221 | await waitJobs([ server ]) | ||
222 | |||
223 | await checkVideoFiles({ id: uuid, expectedStatus: HttpStatusCode.FORBIDDEN_403, token: null, videoFileToken: null }) | ||
224 | }) | ||
225 | |||
226 | it('Should not be able to access an internal video files without appropriate OAuth token and file token', async function () { | ||
227 | this.timeout(120000) | ||
228 | |||
229 | const { uuid } = await server.videos.quickUpload({ name: 'video', privacy: VideoPrivacy.PRIVATE }) | ||
230 | await waitJobs([ server ]) | ||
231 | |||
232 | await checkVideoFiles({ | ||
233 | id: uuid, | ||
234 | expectedStatus: HttpStatusCode.FORBIDDEN_403, | ||
235 | token: userToken, | ||
236 | videoFileToken: unrelatedFileToken | ||
237 | }) | ||
238 | }) | ||
239 | |||
240 | it('Should be able to access a private video files with appropriate OAuth token or file token', async function () { | ||
241 | this.timeout(120000) | ||
242 | |||
243 | const { uuid } = await server.videos.quickUpload({ name: 'video', privacy: VideoPrivacy.PRIVATE }) | ||
244 | const videoFileToken = await server.videoToken.getVideoFileToken({ videoId: uuid }) | ||
245 | |||
246 | await waitJobs([ server ]) | ||
247 | |||
248 | await checkVideoFiles({ id: uuid, expectedStatus: HttpStatusCode.OK_200, token: server.accessToken, videoFileToken }) | ||
249 | }) | ||
250 | |||
251 | it('Should be able to access a private video of another user with an admin OAuth token or file token', async function () { | ||
252 | this.timeout(120000) | ||
253 | |||
254 | const { uuid } = await server.videos.quickUpload({ name: 'video', token: userToken, privacy: VideoPrivacy.PRIVATE }) | ||
255 | const videoFileToken = await server.videoToken.getVideoFileToken({ videoId: uuid }) | ||
256 | |||
257 | await waitJobs([ server ]) | ||
258 | |||
259 | await checkVideoFiles({ id: uuid, expectedStatus: HttpStatusCode.OK_200, token: server.accessToken, videoFileToken }) | ||
260 | }) | ||
261 | }) | ||
262 | |||
263 | describe('Live static file path and check', function () { | ||
264 | let normalLiveId: string | ||
265 | let normalLive: LiveVideo | ||
266 | |||
267 | let permanentLiveId: string | ||
268 | let permanentLive: LiveVideo | ||
269 | |||
270 | let unrelatedFileToken: string | ||
271 | |||
272 | async function checkLiveFiles (live: LiveVideo, liveId: string) { | ||
273 | const ffmpegCommand = sendRTMPStream({ rtmpBaseUrl: live.rtmpUrl, streamKey: live.streamKey }) | ||
274 | await server.live.waitUntilPublished({ videoId: liveId }) | ||
275 | |||
276 | const video = await server.videos.getWithToken({ id: liveId }) | ||
277 | const fileToken = await server.videoToken.getVideoFileToken({ videoId: video.uuid }) | ||
278 | |||
279 | const hls = video.streamingPlaylists[0] | ||
280 | |||
281 | for (const url of [ hls.playlistUrl, hls.segmentsSha256Url ]) { | ||
282 | expectStartWith(url, server.url + '/static/streaming-playlists/hls/private/') | ||
283 | |||
284 | await makeRawRequest({ url, token: server.accessToken, expectedStatus: HttpStatusCode.OK_200 }) | ||
285 | await makeRawRequest({ url, query: { videoFileToken: fileToken }, expectedStatus: HttpStatusCode.OK_200 }) | ||
286 | |||
287 | await makeRawRequest({ url, token: userToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 }) | ||
288 | await makeRawRequest({ url, expectedStatus: HttpStatusCode.FORBIDDEN_403 }) | ||
289 | await makeRawRequest({ url, query: { videoFileToken: unrelatedFileToken }, expectedStatus: HttpStatusCode.FORBIDDEN_403 }) | ||
290 | } | ||
291 | |||
292 | await stopFfmpeg(ffmpegCommand) | ||
293 | } | ||
294 | |||
295 | async function checkReplay (replay: VideoDetails) { | ||
296 | const fileToken = await server.videoToken.getVideoFileToken({ videoId: replay.uuid }) | ||
297 | |||
298 | const hls = replay.streamingPlaylists[0] | ||
299 | expect(hls.files).to.not.have.lengthOf(0) | ||
300 | |||
301 | for (const file of hls.files) { | ||
302 | await makeRawRequest({ url: file.fileUrl, token: server.accessToken, expectedStatus: HttpStatusCode.OK_200 }) | ||
303 | await makeRawRequest({ url: file.fileUrl, query: { videoFileToken: fileToken }, expectedStatus: HttpStatusCode.OK_200 }) | ||
304 | |||
305 | await makeRawRequest({ url: file.fileUrl, token: userToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 }) | ||
306 | await makeRawRequest({ url: file.fileUrl, expectedStatus: HttpStatusCode.FORBIDDEN_403 }) | ||
307 | await makeRawRequest({ | ||
308 | url: file.fileUrl, | ||
309 | query: { videoFileToken: unrelatedFileToken }, | ||
310 | expectedStatus: HttpStatusCode.FORBIDDEN_403 | ||
311 | }) | ||
312 | } | ||
313 | |||
314 | for (const url of [ hls.playlistUrl, hls.segmentsSha256Url ]) { | ||
315 | expectStartWith(url, server.url + '/static/streaming-playlists/hls/private/') | ||
316 | |||
317 | await makeRawRequest({ url, token: server.accessToken, expectedStatus: HttpStatusCode.OK_200 }) | ||
318 | await makeRawRequest({ url, query: { videoFileToken: fileToken }, expectedStatus: HttpStatusCode.OK_200 }) | ||
319 | |||
320 | await makeRawRequest({ url, token: userToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 }) | ||
321 | await makeRawRequest({ url, expectedStatus: HttpStatusCode.FORBIDDEN_403 }) | ||
322 | await makeRawRequest({ url, query: { videoFileToken: unrelatedFileToken }, expectedStatus: HttpStatusCode.FORBIDDEN_403 }) | ||
323 | } | ||
324 | } | ||
325 | |||
326 | before(async function () { | ||
327 | await server.config.enableMinimumTranscoding() | ||
328 | |||
329 | const { uuid } = await server.videos.quickUpload({ name: 'another video' }) | ||
330 | unrelatedFileToken = await server.videoToken.getVideoFileToken({ videoId: uuid }) | ||
331 | |||
332 | await server.config.enableLive({ | ||
333 | allowReplay: true, | ||
334 | transcoding: true, | ||
335 | resolutions: 'min' | ||
336 | }) | ||
337 | |||
338 | { | ||
339 | const { video, live } = await server.live.quickCreate({ saveReplay: true, permanentLive: false, privacy: VideoPrivacy.PRIVATE }) | ||
340 | normalLiveId = video.uuid | ||
341 | normalLive = live | ||
342 | } | ||
343 | |||
344 | { | ||
345 | const { video, live } = await server.live.quickCreate({ saveReplay: true, permanentLive: true, privacy: VideoPrivacy.PRIVATE }) | ||
346 | permanentLiveId = video.uuid | ||
347 | permanentLive = live | ||
348 | } | ||
349 | }) | ||
350 | |||
351 | it('Should create a private normal live and have a private static path', async function () { | ||
352 | this.timeout(240000) | ||
353 | |||
354 | await checkLiveFiles(normalLive, normalLiveId) | ||
355 | }) | ||
356 | |||
357 | it('Should create a private permanent live and have a private static path', async function () { | ||
358 | this.timeout(240000) | ||
359 | |||
360 | await checkLiveFiles(permanentLive, permanentLiveId) | ||
361 | }) | ||
362 | |||
363 | it('Should have created a replay of the normal live with a private static path', async function () { | ||
364 | this.timeout(240000) | ||
365 | |||
366 | await server.live.waitUntilReplacedByReplay({ videoId: normalLiveId }) | ||
367 | |||
368 | const replay = await server.videos.getWithToken({ id: normalLiveId }) | ||
369 | await checkReplay(replay) | ||
370 | }) | ||
371 | |||
372 | it('Should have created a replay of the permanent live with a private static path', async function () { | ||
373 | this.timeout(240000) | ||
374 | |||
375 | await server.live.waitUntilWaiting({ videoId: permanentLiveId }) | ||
376 | await waitJobs([ server ]) | ||
377 | |||
378 | const live = await server.videos.getWithToken({ id: permanentLiveId }) | ||
379 | const replayFromList = await findExternalSavedVideo(server, live) | ||
380 | const replay = await server.videos.getWithToken({ id: replayFromList.id }) | ||
381 | |||
382 | await checkReplay(replay) | ||
383 | }) | ||
384 | }) | ||
385 | |||
386 | after(async function () { | ||
387 | await cleanupTests([ server ]) | ||
388 | }) | ||
389 | }) | ||