diff options
Diffstat (limited to 'server/tests/api')
-rw-r--r-- | server/tests/api/server/redundancy.ts | 264 |
1 files changed, 191 insertions, 73 deletions
diff --git a/server/tests/api/server/redundancy.ts b/server/tests/api/server/redundancy.ts index 6ce4b9dd1..a773e3de4 100644 --- a/server/tests/api/server/redundancy.ts +++ b/server/tests/api/server/redundancy.ts | |||
@@ -31,14 +31,13 @@ const expect = chai.expect | |||
31 | 31 | ||
32 | let servers: ServerInfo[] = [] | 32 | let servers: ServerInfo[] = [] |
33 | let video1Server2UUID: string | 33 | let video1Server2UUID: string |
34 | let video2Server2UUID: string | ||
35 | 34 | ||
36 | function checkMagnetWebseeds (file: { magnetUri: string, resolution: { id: number } }, baseWebseeds: string[]) { | 35 | function checkMagnetWebseeds (file: { magnetUri: string, resolution: { id: number } }, baseWebseeds: string[], server: ServerInfo) { |
37 | const parsed = magnetUtil.decode(file.magnetUri) | 36 | const parsed = magnetUtil.decode(file.magnetUri) |
38 | 37 | ||
39 | for (const ws of baseWebseeds) { | 38 | for (const ws of baseWebseeds) { |
40 | const found = parsed.urlList.find(url => url === `${ws}-${file.resolution.id}.mp4`) | 39 | const found = parsed.urlList.find(url => url === `${ws}-${file.resolution.id}.mp4`) |
41 | expect(found, `Webseed ${ws} not found in ${file.magnetUri}`).to.not.be.undefined | 40 | expect(found, `Webseed ${ws} not found in ${file.magnetUri} on server ${server.url}`).to.not.be.undefined |
42 | } | 41 | } |
43 | } | 42 | } |
44 | 43 | ||
@@ -49,6 +48,7 @@ async function runServers (strategy: VideoRedundancyStrategy, additionalParams: | |||
49 | check_interval: '5 seconds', | 48 | check_interval: '5 seconds', |
50 | strategies: [ | 49 | strategies: [ |
51 | immutableAssign({ | 50 | immutableAssign({ |
51 | min_lifetime: '1 hour', | ||
52 | strategy: strategy, | 52 | strategy: strategy, |
53 | size: '100KB' | 53 | size: '100KB' |
54 | }, additionalParams) | 54 | }, additionalParams) |
@@ -68,11 +68,6 @@ async function runServers (strategy: VideoRedundancyStrategy, additionalParams: | |||
68 | await viewVideo(servers[ 1 ].url, video1Server2UUID) | 68 | await viewVideo(servers[ 1 ].url, video1Server2UUID) |
69 | } | 69 | } |
70 | 70 | ||
71 | { | ||
72 | const res = await uploadVideo(servers[ 1 ].url, servers[ 1 ].accessToken, { name: 'video 2 server 2' }) | ||
73 | video2Server2UUID = res.body.video.uuid | ||
74 | } | ||
75 | |||
76 | await waitJobs(servers) | 71 | await waitJobs(servers) |
77 | 72 | ||
78 | // Server 1 and server 2 follow each other | 73 | // Server 1 and server 2 follow each other |
@@ -85,68 +80,69 @@ async function runServers (strategy: VideoRedundancyStrategy, additionalParams: | |||
85 | await waitJobs(servers) | 80 | await waitJobs(servers) |
86 | } | 81 | } |
87 | 82 | ||
88 | async function check1WebSeed (strategy: VideoRedundancyStrategy) { | 83 | async function check1WebSeed (strategy: VideoRedundancyStrategy, videoUUID?: string) { |
84 | if (!videoUUID) videoUUID = video1Server2UUID | ||
85 | |||
89 | const webseeds = [ | 86 | const webseeds = [ |
90 | 'http://localhost:9002/static/webseed/' + video1Server2UUID | 87 | 'http://localhost:9002/static/webseed/' + videoUUID |
91 | ] | 88 | ] |
92 | 89 | ||
93 | for (const server of servers) { | 90 | for (const server of servers) { |
94 | { | 91 | { |
95 | const res = await getVideo(server.url, video1Server2UUID) | 92 | const res = await getVideo(server.url, videoUUID) |
96 | 93 | ||
97 | const video: VideoDetails = res.body | 94 | const video: VideoDetails = res.body |
98 | video.files.forEach(f => checkMagnetWebseeds(f, webseeds)) | 95 | for (const f of video.files) { |
96 | checkMagnetWebseeds(f, webseeds, server) | ||
97 | } | ||
99 | } | 98 | } |
99 | } | ||
100 | } | ||
100 | 101 | ||
101 | { | 102 | async function checkStatsWith2Webseed (strategy: VideoRedundancyStrategy) { |
102 | const res = await getStats(server.url) | 103 | const res = await getStats(servers[0].url) |
103 | const data: ServerStats = res.body | 104 | const data: ServerStats = res.body |
104 | 105 | ||
105 | expect(data.videosRedundancy).to.have.lengthOf(1) | 106 | expect(data.videosRedundancy).to.have.lengthOf(1) |
107 | const stat = data.videosRedundancy[0] | ||
106 | 108 | ||
107 | const stat = data.videosRedundancy[0] | 109 | expect(stat.strategy).to.equal(strategy) |
108 | expect(stat.strategy).to.equal(strategy) | 110 | expect(stat.totalSize).to.equal(102400) |
109 | expect(stat.totalSize).to.equal(102400) | 111 | expect(stat.totalUsed).to.be.at.least(1).and.below(102401) |
110 | expect(stat.totalUsed).to.equal(0) | 112 | expect(stat.totalVideoFiles).to.equal(4) |
111 | expect(stat.totalVideoFiles).to.equal(0) | 113 | expect(stat.totalVideos).to.equal(1) |
112 | expect(stat.totalVideos).to.equal(0) | ||
113 | } | ||
114 | } | ||
115 | } | 114 | } |
116 | 115 | ||
117 | async function enableRedundancy () { | 116 | async function checkStatsWith1Webseed (strategy: VideoRedundancyStrategy) { |
118 | await updateRedundancy(servers[ 0 ].url, servers[ 0 ].accessToken, servers[ 1 ].host, true) | 117 | const res = await getStats(servers[0].url) |
118 | const data: ServerStats = res.body | ||
119 | 119 | ||
120 | const res = await getFollowingListPaginationAndSort(servers[ 0 ].url, 0, 5, '-createdAt') | 120 | expect(data.videosRedundancy).to.have.lengthOf(1) |
121 | const follows: ActorFollow[] = res.body.data | ||
122 | const server2 = follows.find(f => f.following.host === 'localhost:9002') | ||
123 | const server3 = follows.find(f => f.following.host === 'localhost:9003') | ||
124 | |||
125 | expect(server3).to.not.be.undefined | ||
126 | expect(server3.following.hostRedundancyAllowed).to.be.false | ||
127 | 121 | ||
128 | expect(server2).to.not.be.undefined | 122 | const stat = data.videosRedundancy[0] |
129 | expect(server2.following.hostRedundancyAllowed).to.be.true | 123 | expect(stat.strategy).to.equal(strategy) |
124 | expect(stat.totalSize).to.equal(102400) | ||
125 | expect(stat.totalUsed).to.equal(0) | ||
126 | expect(stat.totalVideoFiles).to.equal(0) | ||
127 | expect(stat.totalVideos).to.equal(0) | ||
130 | } | 128 | } |
131 | 129 | ||
132 | async function check2Webseeds (strategy: VideoRedundancyStrategy) { | 130 | async function check2Webseeds (strategy: VideoRedundancyStrategy, videoUUID?: string) { |
133 | await waitJobs(servers) | 131 | if (!videoUUID) videoUUID = video1Server2UUID |
134 | await wait(15000) | ||
135 | await waitJobs(servers) | ||
136 | 132 | ||
137 | const webseeds = [ | 133 | const webseeds = [ |
138 | 'http://localhost:9001/static/webseed/' + video1Server2UUID, | 134 | 'http://localhost:9001/static/webseed/' + videoUUID, |
139 | 'http://localhost:9002/static/webseed/' + video1Server2UUID | 135 | 'http://localhost:9002/static/webseed/' + videoUUID |
140 | ] | 136 | ] |
141 | 137 | ||
142 | for (const server of servers) { | 138 | for (const server of servers) { |
143 | { | 139 | { |
144 | const res = await getVideo(server.url, video1Server2UUID) | 140 | const res = await getVideo(server.url, videoUUID) |
145 | 141 | ||
146 | const video: VideoDetails = res.body | 142 | const video: VideoDetails = res.body |
147 | 143 | ||
148 | for (const file of video.files) { | 144 | for (const file of video.files) { |
149 | checkMagnetWebseeds(file, webseeds) | 145 | checkMagnetWebseeds(file, webseeds, server) |
150 | } | 146 | } |
151 | } | 147 | } |
152 | } | 148 | } |
@@ -155,22 +151,23 @@ async function check2Webseeds (strategy: VideoRedundancyStrategy) { | |||
155 | expect(files).to.have.lengthOf(4) | 151 | expect(files).to.have.lengthOf(4) |
156 | 152 | ||
157 | for (const resolution of [ 240, 360, 480, 720 ]) { | 153 | for (const resolution of [ 240, 360, 480, 720 ]) { |
158 | expect(files.find(f => f === `${video1Server2UUID}-${resolution}.mp4`)).to.not.be.undefined | 154 | expect(files.find(f => f === `${videoUUID}-${resolution}.mp4`)).to.not.be.undefined |
159 | } | 155 | } |
156 | } | ||
160 | 157 | ||
161 | { | 158 | async function enableRedundancyOnServer1 () { |
162 | const res = await getStats(servers[0].url) | 159 | await updateRedundancy(servers[ 0 ].url, servers[ 0 ].accessToken, servers[ 1 ].host, true) |
163 | const data: ServerStats = res.body | ||
164 | 160 | ||
165 | expect(data.videosRedundancy).to.have.lengthOf(1) | 161 | const res = await getFollowingListPaginationAndSort(servers[ 0 ].url, 0, 5, '-createdAt') |
166 | const stat = data.videosRedundancy[0] | 162 | const follows: ActorFollow[] = res.body.data |
163 | const server2 = follows.find(f => f.following.host === 'localhost:9002') | ||
164 | const server3 = follows.find(f => f.following.host === 'localhost:9003') | ||
167 | 165 | ||
168 | expect(stat.strategy).to.equal(strategy) | 166 | expect(server3).to.not.be.undefined |
169 | expect(stat.totalSize).to.equal(102400) | 167 | expect(server3.following.hostRedundancyAllowed).to.be.false |
170 | expect(stat.totalUsed).to.be.at.least(1).and.below(102401) | 168 | |
171 | expect(stat.totalVideoFiles).to.equal(4) | 169 | expect(server2).to.not.be.undefined |
172 | expect(stat.totalVideos).to.equal(1) | 170 | expect(server2.following.hostRedundancyAllowed).to.be.true |
173 | } | ||
174 | } | 171 | } |
175 | 172 | ||
176 | async function cleanServers () { | 173 | async function cleanServers () { |
@@ -188,18 +185,24 @@ describe('Test videos redundancy', function () { | |||
188 | return runServers(strategy) | 185 | return runServers(strategy) |
189 | }) | 186 | }) |
190 | 187 | ||
191 | it('Should have 1 webseed on the first video', function () { | 188 | it('Should have 1 webseed on the first video', async function () { |
192 | return check1WebSeed(strategy) | 189 | await check1WebSeed(strategy) |
190 | await checkStatsWith1Webseed(strategy) | ||
193 | }) | 191 | }) |
194 | 192 | ||
195 | it('Should enable redundancy on server 1', function () { | 193 | it('Should enable redundancy on server 1', function () { |
196 | return enableRedundancy() | 194 | return enableRedundancyOnServer1() |
197 | }) | 195 | }) |
198 | 196 | ||
199 | it('Should have 2 webseed on the first video', function () { | 197 | it('Should have 2 webseed on the first video', async function () { |
200 | this.timeout(40000) | 198 | this.timeout(40000) |
201 | 199 | ||
202 | return check2Webseeds(strategy) | 200 | await waitJobs(servers) |
201 | await wait(15000) | ||
202 | await waitJobs(servers) | ||
203 | |||
204 | await check2Webseeds(strategy) | ||
205 | await checkStatsWith2Webseed(strategy) | ||
203 | }) | 206 | }) |
204 | 207 | ||
205 | after(function () { | 208 | after(function () { |
@@ -216,18 +219,24 @@ describe('Test videos redundancy', function () { | |||
216 | return runServers(strategy) | 219 | return runServers(strategy) |
217 | }) | 220 | }) |
218 | 221 | ||
219 | it('Should have 1 webseed on the first video', function () { | 222 | it('Should have 1 webseed on the first video', async function () { |
220 | return check1WebSeed(strategy) | 223 | await check1WebSeed(strategy) |
224 | await checkStatsWith1Webseed(strategy) | ||
221 | }) | 225 | }) |
222 | 226 | ||
223 | it('Should enable redundancy on server 1', function () { | 227 | it('Should enable redundancy on server 1', function () { |
224 | return enableRedundancy() | 228 | return enableRedundancyOnServer1() |
225 | }) | 229 | }) |
226 | 230 | ||
227 | it('Should have 2 webseed on the first video', function () { | 231 | it('Should have 2 webseed on the first video', async function () { |
228 | this.timeout(40000) | 232 | this.timeout(40000) |
229 | 233 | ||
230 | return check2Webseeds(strategy) | 234 | await waitJobs(servers) |
235 | await wait(15000) | ||
236 | await waitJobs(servers) | ||
237 | |||
238 | await check2Webseeds(strategy) | ||
239 | await checkStatsWith2Webseed(strategy) | ||
231 | }) | 240 | }) |
232 | 241 | ||
233 | after(function () { | 242 | after(function () { |
@@ -241,15 +250,16 @@ describe('Test videos redundancy', function () { | |||
241 | before(function () { | 250 | before(function () { |
242 | this.timeout(120000) | 251 | this.timeout(120000) |
243 | 252 | ||
244 | return runServers(strategy, { minViews: 3 }) | 253 | return runServers(strategy, { min_views: 3 }) |
245 | }) | 254 | }) |
246 | 255 | ||
247 | it('Should have 1 webseed on the first video', function () { | 256 | it('Should have 1 webseed on the first video', async function () { |
248 | return check1WebSeed(strategy) | 257 | await check1WebSeed(strategy) |
258 | await checkStatsWith1Webseed(strategy) | ||
249 | }) | 259 | }) |
250 | 260 | ||
251 | it('Should enable redundancy on server 1', function () { | 261 | it('Should enable redundancy on server 1', function () { |
252 | return enableRedundancy() | 262 | return enableRedundancyOnServer1() |
253 | }) | 263 | }) |
254 | 264 | ||
255 | it('Should still have 1 webseed on the first video', async function () { | 265 | it('Should still have 1 webseed on the first video', async function () { |
@@ -259,10 +269,11 @@ describe('Test videos redundancy', function () { | |||
259 | await wait(15000) | 269 | await wait(15000) |
260 | await waitJobs(servers) | 270 | await waitJobs(servers) |
261 | 271 | ||
262 | return check1WebSeed(strategy) | 272 | await check1WebSeed(strategy) |
273 | await checkStatsWith1Webseed(strategy) | ||
263 | }) | 274 | }) |
264 | 275 | ||
265 | it('Should view 2 times the first video', async function () { | 276 | it('Should view 2 times the first video to have > min_views config', async function () { |
266 | this.timeout(40000) | 277 | this.timeout(40000) |
267 | 278 | ||
268 | await viewVideo(servers[ 0 ].url, video1Server2UUID) | 279 | await viewVideo(servers[ 0 ].url, video1Server2UUID) |
@@ -272,10 +283,117 @@ describe('Test videos redundancy', function () { | |||
272 | await waitJobs(servers) | 283 | await waitJobs(servers) |
273 | }) | 284 | }) |
274 | 285 | ||
275 | it('Should have 2 webseed on the first video', function () { | 286 | it('Should have 2 webseed on the first video', async function () { |
276 | this.timeout(40000) | 287 | this.timeout(40000) |
277 | 288 | ||
278 | return check2Webseeds(strategy) | 289 | await waitJobs(servers) |
290 | await wait(15000) | ||
291 | await waitJobs(servers) | ||
292 | |||
293 | await check2Webseeds(strategy) | ||
294 | await checkStatsWith2Webseed(strategy) | ||
295 | }) | ||
296 | |||
297 | after(function () { | ||
298 | return cleanServers() | ||
299 | }) | ||
300 | }) | ||
301 | |||
302 | describe('Test expiration', function () { | ||
303 | const strategy = 'recently-added' | ||
304 | |||
305 | async function checkContains (servers: ServerInfo[], str: string) { | ||
306 | for (const server of servers) { | ||
307 | const res = await getVideo(server.url, video1Server2UUID) | ||
308 | const video: VideoDetails = res.body | ||
309 | |||
310 | for (const f of video.files) { | ||
311 | expect(f.magnetUri).to.contain(str) | ||
312 | } | ||
313 | } | ||
314 | } | ||
315 | |||
316 | async function checkNotContains (servers: ServerInfo[], str: string) { | ||
317 | for (const server of servers) { | ||
318 | const res = await getVideo(server.url, video1Server2UUID) | ||
319 | const video: VideoDetails = res.body | ||
320 | |||
321 | for (const f of video.files) { | ||
322 | expect(f.magnetUri).to.not.contain(str) | ||
323 | } | ||
324 | } | ||
325 | } | ||
326 | |||
327 | before(async function () { | ||
328 | this.timeout(120000) | ||
329 | |||
330 | await runServers(strategy, { min_lifetime: '7 seconds', min_views: 0 }) | ||
331 | |||
332 | await enableRedundancyOnServer1() | ||
333 | }) | ||
334 | |||
335 | it('Should still have 2 webseeds after 10 seconds', async function () { | ||
336 | this.timeout(40000) | ||
337 | |||
338 | await wait(10000) | ||
339 | |||
340 | try { | ||
341 | await checkContains(servers, 'http%3A%2F%2Flocalhost%3A9001') | ||
342 | } catch { | ||
343 | // Maybe a server deleted a redundancy in the scheduler | ||
344 | await wait(2000) | ||
345 | |||
346 | await checkContains(servers, 'http%3A%2F%2Flocalhost%3A9001') | ||
347 | } | ||
348 | }) | ||
349 | |||
350 | it('Should stop server 1 and expire video redundancy', async function () { | ||
351 | this.timeout(40000) | ||
352 | |||
353 | killallServers([ servers[0] ]) | ||
354 | |||
355 | await wait(10000) | ||
356 | |||
357 | await checkNotContains([ servers[1], servers[2] ], 'http%3A%2F%2Flocalhost%3A9001') | ||
358 | }) | ||
359 | |||
360 | after(function () { | ||
361 | return killallServers([ servers[1], servers[2] ]) | ||
362 | }) | ||
363 | }) | ||
364 | |||
365 | describe('Test file replacement', function () { | ||
366 | let video2Server2UUID: string | ||
367 | const strategy = 'recently-added' | ||
368 | |||
369 | before(async function () { | ||
370 | this.timeout(120000) | ||
371 | |||
372 | await runServers(strategy, { min_lifetime: '7 seconds', min_views: 0 }) | ||
373 | |||
374 | await enableRedundancyOnServer1() | ||
375 | |||
376 | await waitJobs(servers) | ||
377 | await wait(5000) | ||
378 | await waitJobs(servers) | ||
379 | |||
380 | await check2Webseeds(strategy) | ||
381 | await checkStatsWith2Webseed(strategy) | ||
382 | |||
383 | const res = await uploadVideo(servers[ 1 ].url, servers[ 1 ].accessToken, { name: 'video 2 server 2' }) | ||
384 | video2Server2UUID = res.body.video.uuid | ||
385 | }) | ||
386 | |||
387 | it('Should cache video 2 webseed on the first video', async function () { | ||
388 | this.timeout(40000) | ||
389 | this.retries(3) | ||
390 | |||
391 | await waitJobs(servers) | ||
392 | |||
393 | await wait(7000) | ||
394 | |||
395 | await check1WebSeed(strategy, video1Server2UUID) | ||
396 | await check2Webseeds(strategy, video2Server2UUID) | ||
279 | }) | 397 | }) |
280 | 398 | ||
281 | after(function () { | 399 | after(function () { |