]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame - server/tests/api/redundancy/redundancy.ts
Fix tests
[github/Chocobozzz/PeerTube.git] / server / tests / api / redundancy / redundancy.ts
CommitLineData
a1587156 1/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
26370ce4 2
26370ce4 3import 'mocha'
6949a1a1
C
4import * as chai from 'chai'
5import { readdir } from 'fs-extra'
41fb13c3 6import magnetUtil from 'magnet-uri'
83903cb6 7import { basename, join } from 'path'
26370ce4 8import {
07b1a18a 9 checkSegmentHash,
b764380a
C
10 checkVideoFilesWereRemoved,
11 cleanupTests,
254d3579 12 createMultipleServers,
4c7e60bc 13 doubleFollow,
07b1a18a 14 killallServers,
83903cb6 15 makeRawRequest,
254d3579 16 PeerTubeServer,
4c7e60bc 17 root,
83903cb6 18 saveVideoInServers,
07b1a18a 19 setAccessTokensToServers,
26370ce4 20 wait,
6c5065a0 21 waitJobs
dab04709 22} from '@shared/extra-utils'
83903cb6
C
23import {
24 HttpStatusCode,
25 VideoDetails,
26 VideoFile,
27 VideoPrivacy,
28 VideoRedundancyStrategy,
29 VideoRedundancyStrategyWithManual
30} from '@shared/models'
26370ce4
C
31
32const expect = chai.expect
33
254d3579 34let servers: PeerTubeServer[] = []
83903cb6 35let video1Server2: VideoDetails
26370ce4 36
83903cb6 37async function checkMagnetWebseeds (file: VideoFile, baseWebseeds: string[], server: PeerTubeServer) {
26370ce4
C
38 const parsed = magnetUtil.decode(file.magnetUri)
39
40 for (const ws of baseWebseeds) {
83903cb6 41 const found = parsed.urlList.find(url => url === `${ws}${basename(file.fileUrl)}`)
26370ce4
C
42 expect(found, `Webseed ${ws} not found in ${file.magnetUri} on server ${server.url}`).to.not.be.undefined
43 }
44
45 expect(parsed.urlList).to.have.lengthOf(baseWebseeds.length)
83903cb6
C
46
47 for (const url of parsed.urlList) {
48 await makeRawRequest(url, HttpStatusCode.OK_200)
49 }
26370ce4
C
50}
51
7b6cf83e 52async function createServers (strategy: VideoRedundancyStrategy | null, additionalParams: any = {}, withWebtorrent = true) {
b764380a
C
53 const strategies: any[] = []
54
55 if (strategy !== null) {
56 strategies.push(
6c5065a0 57 {
b764380a
C
58 min_lifetime: '1 hour',
59 strategy: strategy,
6c5065a0
C
60 size: '400KB',
61
62 ...additionalParams
63 }
b764380a
C
64 )
65 }
66
26370ce4 67 const config = {
09209296 68 transcoding: {
7448551f
C
69 webtorrent: {
70 enabled: withWebtorrent
71 },
09209296
C
72 hls: {
73 enabled: true
74 }
75 },
26370ce4
C
76 redundancy: {
77 videos: {
78 check_interval: '5 seconds',
b764380a 79 strategies
26370ce4
C
80 }
81 }
82 }
b764380a 83
254d3579 84 servers = await createMultipleServers(3, config)
26370ce4
C
85
86 // Get the access tokens
87 await setAccessTokensToServers(servers)
88
89 {
83903cb6
C
90 const { id } = await servers[1].videos.upload({ attributes: { name: 'video 1 server 2' } })
91 video1Server2 = await servers[1].videos.get({ id })
26370ce4 92
83903cb6 93 await servers[1].videos.view({ id })
26370ce4
C
94 }
95
96 await waitJobs(servers)
97
98 // Server 1 and server 2 follow each other
a1587156 99 await doubleFollow(servers[0], servers[1])
26370ce4 100 // Server 1 and server 3 follow each other
a1587156 101 await doubleFollow(servers[0], servers[2])
26370ce4 102 // Server 2 and server 3 follow each other
a1587156 103 await doubleFollow(servers[1], servers[2])
26370ce4
C
104
105 await waitJobs(servers)
106}
107
83903cb6
C
108async function ensureSameFilenames (videoUUID: string) {
109 let webtorrentFilenames: string[]
110 let hlsFilenames: string[]
111
112 for (const server of servers) {
113 const video = await server.videos.getWithToken({ id: videoUUID })
114
115 // Ensure we use the same filenames that the origin
116
117 const localWebtorrentFilenames = video.files.map(f => basename(f.fileUrl)).sort()
118 const localHLSFilenames = video.streamingPlaylists[0].files.map(f => basename(f.fileUrl)).sort()
119
120 if (webtorrentFilenames) expect(webtorrentFilenames).to.deep.equal(localWebtorrentFilenames)
121 else webtorrentFilenames = localWebtorrentFilenames
122
123 if (hlsFilenames) expect(hlsFilenames).to.deep.equal(localHLSFilenames)
124 else hlsFilenames = localHLSFilenames
125 }
126
127 return { webtorrentFilenames, hlsFilenames }
128}
129
09209296 130async function check1WebSeed (videoUUID?: string) {
83903cb6 131 if (!videoUUID) videoUUID = video1Server2.uuid
26370ce4
C
132
133 const webseeds = [
83903cb6 134 `http://localhost:${servers[1].port}/static/webseed/`
26370ce4
C
135 ]
136
137 for (const server of servers) {
09209296 138 // With token to avoid issues with video follow constraints
89d241a7 139 const video = await server.videos.getWithToken({ id: videoUUID })
26370ce4 140
09209296 141 for (const f of video.files) {
83903cb6 142 await checkMagnetWebseeds(f, webseeds, server)
26370ce4
C
143 }
144 }
83903cb6
C
145
146 await ensureSameFilenames(videoUUID)
26370ce4
C
147}
148
09209296 149async function check2Webseeds (videoUUID?: string) {
83903cb6 150 if (!videoUUID) videoUUID = video1Server2.uuid
26370ce4
C
151
152 const webseeds = [
83903cb6
C
153 `http://localhost:${servers[0].port}/static/redundancy/`,
154 `http://localhost:${servers[1].port}/static/webseed/`
26370ce4
C
155 ]
156
157 for (const server of servers) {
89d241a7 158 const video = await server.videos.get({ id: videoUUID })
26370ce4
C
159
160 for (const file of video.files) {
83903cb6 161 await checkMagnetWebseeds(file, webseeds, server)
26370ce4
C
162 }
163 }
164
83903cb6
C
165 const { webtorrentFilenames } = await ensureSameFilenames(videoUUID)
166
7243f84d
C
167 const directories = [
168 'test' + servers[0].internalServerNumber + '/redundancy',
169 'test' + servers[1].internalServerNumber + '/videos'
170 ]
171
172 for (const directory of directories) {
b9fffa29 173 const files = await readdir(join(root(), directory))
26370ce4
C
174 expect(files).to.have.length.at.least(4)
175
83903cb6
C
176 // Ensure we files exist on disk
177 expect(files.find(f => webtorrentFilenames.includes(f))).to.exist
26370ce4
C
178 }
179}
180
09209296 181async function check0PlaylistRedundancies (videoUUID?: string) {
83903cb6 182 if (!videoUUID) videoUUID = video1Server2.uuid
09209296
C
183
184 for (const server of servers) {
185 // With token to avoid issues with video follow constraints
89d241a7 186 const video = await server.videos.getWithToken({ id: videoUUID })
09209296
C
187
188 expect(video.streamingPlaylists).to.be.an('array')
189 expect(video.streamingPlaylists).to.have.lengthOf(1)
190 expect(video.streamingPlaylists[0].redundancies).to.have.lengthOf(0)
191 }
83903cb6
C
192
193 await ensureSameFilenames(videoUUID)
09209296
C
194}
195
196async function check1PlaylistRedundancies (videoUUID?: string) {
83903cb6 197 if (!videoUUID) videoUUID = video1Server2.uuid
09209296
C
198
199 for (const server of servers) {
89d241a7 200 const video = await server.videos.get({ id: videoUUID })
09209296
C
201
202 expect(video.streamingPlaylists).to.have.lengthOf(1)
203 expect(video.streamingPlaylists[0].redundancies).to.have.lengthOf(1)
204
205 const redundancy = video.streamingPlaylists[0].redundancies[0]
206
207 expect(redundancy.baseUrl).to.equal(servers[0].url + '/static/redundancy/hls/' + videoUUID)
208 }
209
0305db28
JB
210 const baseUrlPlaylist = servers[1].url + '/static/streaming-playlists/hls/' + videoUUID
211 const baseUrlSegment = servers[0].url + '/static/redundancy/hls/' + videoUUID
4c280004 212
89d241a7 213 const video = await servers[0].videos.get({ id: videoUUID })
d23dd9fb 214 const hlsPlaylist = video.streamingPlaylists[0]
4c280004
C
215
216 for (const resolution of [ 240, 360, 480, 720 ]) {
0305db28 217 await checkSegmentHash({ server: servers[1], baseUrlPlaylist, baseUrlSegment, resolution, hlsPlaylist })
4c280004 218 }
09209296 219
83903cb6
C
220 const { hlsFilenames } = await ensureSameFilenames(videoUUID)
221
7243f84d
C
222 const directories = [
223 'test' + servers[0].internalServerNumber + '/redundancy/hls',
224 'test' + servers[1].internalServerNumber + '/streaming-playlists/hls'
225 ]
226
227 for (const directory of directories) {
09209296
C
228 const files = await readdir(join(root(), directory, videoUUID))
229 expect(files).to.have.length.at.least(4)
230
83903cb6
C
231 // Ensure we files exist on disk
232 expect(files.find(f => hlsFilenames.includes(f))).to.exist
09209296
C
233 }
234}
235
b764380a
C
236async function checkStatsGlobal (strategy: VideoRedundancyStrategyWithManual) {
237 let totalSize: number = null
238 let statsLength = 1
239
240 if (strategy !== 'manual') {
241 totalSize = 409600
242 statsLength = 2
243 }
244
89d241a7 245 const data = await servers[0].stats.get()
b764380a 246 expect(data.videosRedundancy).to.have.lengthOf(statsLength)
09209296 247
b764380a 248 const stat = data.videosRedundancy[0]
09209296 249 expect(stat.strategy).to.equal(strategy)
b764380a
C
250 expect(stat.totalSize).to.equal(totalSize)
251
252 return stat
253}
254
6949a1a1 255async function checkStatsWith1Redundancy (strategy: VideoRedundancyStrategyWithManual, onlyHls = false) {
b764380a
C
256 const stat = await checkStatsGlobal(strategy)
257
9e3e3617 258 expect(stat.totalUsed).to.be.at.least(1).and.below(409601)
6949a1a1 259 expect(stat.totalVideoFiles).to.equal(onlyHls ? 4 : 8)
09209296
C
260 expect(stat.totalVideos).to.equal(1)
261}
262
7448551f 263async function checkStatsWithoutRedundancy (strategy: VideoRedundancyStrategyWithManual) {
b764380a 264 const stat = await checkStatsGlobal(strategy)
09209296 265
09209296
C
266 expect(stat.totalUsed).to.equal(0)
267 expect(stat.totalVideoFiles).to.equal(0)
268 expect(stat.totalVideos).to.equal(0)
269}
270
c3d29f69 271async function findServerFollows () {
89d241a7 272 const body = await servers[0].follows.getFollowings({ start: 0, count: 5, sort: '-createdAt' })
c3d29f69
C
273 const follows = body.data
274 const server2 = follows.find(f => f.following.host === `localhost:${servers[1].port}`)
275 const server3 = follows.find(f => f.following.host === `localhost:${servers[2].port}`)
276
277 return { server2, server3 }
278}
279
26370ce4 280async function enableRedundancyOnServer1 () {
89d241a7 281 await servers[0].redundancy.updateRedundancy({ host: servers[1].host, redundancyAllowed: true })
26370ce4 282
c3d29f69 283 const { server2, server3 } = await findServerFollows()
26370ce4
C
284
285 expect(server3).to.not.be.undefined
286 expect(server3.following.hostRedundancyAllowed).to.be.false
287
288 expect(server2).to.not.be.undefined
289 expect(server2.following.hostRedundancyAllowed).to.be.true
290}
291
292async function disableRedundancyOnServer1 () {
89d241a7 293 await servers[0].redundancy.updateRedundancy({ host: servers[1].host, redundancyAllowed: false })
26370ce4 294
c3d29f69 295 const { server2, server3 } = await findServerFollows()
26370ce4
C
296
297 expect(server3).to.not.be.undefined
298 expect(server3.following.hostRedundancyAllowed).to.be.false
299
300 expect(server2).to.not.be.undefined
301 expect(server2.following.hostRedundancyAllowed).to.be.false
302}
303
26370ce4
C
304describe('Test videos redundancy', function () {
305
306 describe('With most-views strategy', function () {
307 const strategy = 'most-views'
308
309 before(function () {
310 this.timeout(120000)
311
7b6cf83e 312 return createServers(strategy)
26370ce4
C
313 })
314
315 it('Should have 1 webseed on the first video', async function () {
09209296
C
316 await check1WebSeed()
317 await check0PlaylistRedundancies()
7448551f 318 await checkStatsWithoutRedundancy(strategy)
26370ce4
C
319 })
320
321 it('Should enable redundancy on server 1', function () {
322 return enableRedundancyOnServer1()
323 })
324
6cb3482c 325 it('Should have 2 webseeds on the first video', async function () {
09209296 326 this.timeout(80000)
26370ce4
C
327
328 await waitJobs(servers)
89d241a7 329 await servers[0].servers.waitUntilLog('Duplicated ', 5)
26370ce4
C
330 await waitJobs(servers)
331
09209296
C
332 await check2Webseeds()
333 await check1PlaylistRedundancies()
7448551f 334 await checkStatsWith1Redundancy(strategy)
26370ce4
C
335 })
336
337 it('Should undo redundancy on server 1 and remove duplicated videos', async function () {
09209296 338 this.timeout(80000)
26370ce4
C
339
340 await disableRedundancyOnServer1()
341
342 await waitJobs(servers)
343 await wait(5000)
344
09209296
C
345 await check1WebSeed()
346 await check0PlaylistRedundancies()
26370ce4 347
83903cb6 348 await checkVideoFilesWereRemoved({ server: servers[0], video: video1Server2, onlyVideoFiles: true })
26370ce4
C
349 })
350
7c3b7976
C
351 after(async function () {
352 return cleanupTests(servers)
26370ce4
C
353 })
354 })
355
356 describe('With trending strategy', function () {
357 const strategy = 'trending'
358
359 before(function () {
360 this.timeout(120000)
361
7b6cf83e 362 return createServers(strategy)
26370ce4
C
363 })
364
365 it('Should have 1 webseed on the first video', async function () {
09209296
C
366 await check1WebSeed()
367 await check0PlaylistRedundancies()
7448551f 368 await checkStatsWithoutRedundancy(strategy)
26370ce4
C
369 })
370
371 it('Should enable redundancy on server 1', function () {
372 return enableRedundancyOnServer1()
373 })
374
6cb3482c 375 it('Should have 2 webseeds on the first video', async function () {
09209296 376 this.timeout(80000)
26370ce4
C
377
378 await waitJobs(servers)
89d241a7 379 await servers[0].servers.waitUntilLog('Duplicated ', 5)
26370ce4
C
380 await waitJobs(servers)
381
09209296
C
382 await check2Webseeds()
383 await check1PlaylistRedundancies()
7448551f 384 await checkStatsWith1Redundancy(strategy)
26370ce4
C
385 })
386
7b6cf83e
C
387 it('Should unfollow server 3 and keep duplicated videos', async function () {
388 this.timeout(80000)
389
390 await servers[0].follows.unfollow({ target: servers[2] })
391
392 await waitJobs(servers)
393 await wait(5000)
394
395 await check2Webseeds()
396 await check1PlaylistRedundancies()
397 await checkStatsWith1Redundancy(strategy)
398 })
399
400 it('Should unfollow server 2 and remove duplicated videos', async function () {
09209296 401 this.timeout(80000)
26370ce4 402
89d241a7 403 await servers[0].follows.unfollow({ target: servers[1] })
26370ce4
C
404
405 await waitJobs(servers)
406 await wait(5000)
407
09209296
C
408 await check1WebSeed()
409 await check0PlaylistRedundancies()
26370ce4 410
83903cb6 411 await checkVideoFilesWereRemoved({ server: servers[0], video: video1Server2, onlyVideoFiles: true })
26370ce4
C
412 })
413
7c3b7976
C
414 after(async function () {
415 await cleanupTests(servers)
26370ce4
C
416 })
417 })
418
419 describe('With recently added strategy', function () {
420 const strategy = 'recently-added'
421
422 before(function () {
423 this.timeout(120000)
424
7b6cf83e 425 return createServers(strategy, { min_views: 3 })
26370ce4
C
426 })
427
428 it('Should have 1 webseed on the first video', async function () {
09209296
C
429 await check1WebSeed()
430 await check0PlaylistRedundancies()
7448551f 431 await checkStatsWithoutRedundancy(strategy)
26370ce4
C
432 })
433
434 it('Should enable redundancy on server 1', function () {
435 return enableRedundancyOnServer1()
436 })
437
438 it('Should still have 1 webseed on the first video', async function () {
09209296 439 this.timeout(80000)
26370ce4
C
440
441 await waitJobs(servers)
442 await wait(15000)
443 await waitJobs(servers)
444
09209296
C
445 await check1WebSeed()
446 await check0PlaylistRedundancies()
7448551f 447 await checkStatsWithoutRedundancy(strategy)
26370ce4
C
448 })
449
450 it('Should view 2 times the first video to have > min_views config', async function () {
09209296 451 this.timeout(80000)
26370ce4 452
83903cb6
C
453 await servers[0].videos.view({ id: video1Server2.uuid })
454 await servers[2].videos.view({ id: video1Server2.uuid })
26370ce4
C
455
456 await wait(10000)
457 await waitJobs(servers)
458 })
459
6cb3482c 460 it('Should have 2 webseeds on the first video', async function () {
09209296 461 this.timeout(80000)
26370ce4
C
462
463 await waitJobs(servers)
89d241a7 464 await servers[0].servers.waitUntilLog('Duplicated ', 5)
26370ce4
C
465 await waitJobs(servers)
466
09209296
C
467 await check2Webseeds()
468 await check1PlaylistRedundancies()
7448551f 469 await checkStatsWith1Redundancy(strategy)
26370ce4
C
470 })
471
472 it('Should remove the video and the redundancy files', async function () {
473 this.timeout(20000)
474
83903cb6
C
475 await saveVideoInServers(servers, video1Server2.uuid)
476 await servers[1].videos.remove({ id: video1Server2.uuid })
26370ce4
C
477
478 await waitJobs(servers)
479
480 for (const server of servers) {
83903cb6 481 await checkVideoFilesWereRemoved({ server, video: server.store.videoDetails })
26370ce4
C
482 }
483 })
484
7c3b7976
C
485 after(async function () {
486 await cleanupTests(servers)
26370ce4
C
487 })
488 })
489
7448551f
C
490 describe('With only HLS files', function () {
491 const strategy = 'recently-added'
492
493 before(async function () {
494 this.timeout(120000)
495
7b6cf83e 496 await createServers(strategy, { min_views: 3 }, false)
7448551f
C
497 })
498
499 it('Should have 0 playlist redundancy on the first video', async function () {
500 await check1WebSeed()
501 await check0PlaylistRedundancies()
502 })
503
504 it('Should enable redundancy on server 1', function () {
505 return enableRedundancyOnServer1()
506 })
507
508 it('Should still have 0 redundancy on the first video', async function () {
509 this.timeout(80000)
510
511 await waitJobs(servers)
512 await wait(15000)
513 await waitJobs(servers)
514
515 await check0PlaylistRedundancies()
516 await checkStatsWithoutRedundancy(strategy)
517 })
518
519 it('Should have 1 redundancy on the first video', async function () {
520 this.timeout(160000)
521
83903cb6
C
522 await servers[0].videos.view({ id: video1Server2.uuid })
523 await servers[2].videos.view({ id: video1Server2.uuid })
7448551f
C
524
525 await wait(10000)
526 await waitJobs(servers)
527
528 await waitJobs(servers)
89d241a7 529 await servers[0].servers.waitUntilLog('Duplicated ', 1)
7448551f
C
530 await waitJobs(servers)
531
532 await check1PlaylistRedundancies()
6949a1a1 533 await checkStatsWith1Redundancy(strategy, true)
7448551f
C
534 })
535
536 it('Should remove the video and the redundancy files', async function () {
537 this.timeout(20000)
538
83903cb6
C
539 await saveVideoInServers(servers, video1Server2.uuid)
540 await servers[1].videos.remove({ id: video1Server2.uuid })
7448551f
C
541
542 await waitJobs(servers)
543
544 for (const server of servers) {
83903cb6 545 await checkVideoFilesWereRemoved({ server, video: server.store.videoDetails })
7448551f
C
546 }
547 })
6949a1a1
C
548
549 after(async function () {
550 await cleanupTests(servers)
551 })
7448551f
C
552 })
553
b764380a
C
554 describe('With manual strategy', function () {
555 before(function () {
556 this.timeout(120000)
557
7b6cf83e 558 return createServers(null)
b764380a
C
559 })
560
561 it('Should have 1 webseed on the first video', async function () {
562 await check1WebSeed()
563 await check0PlaylistRedundancies()
7448551f 564 await checkStatsWithoutRedundancy('manual')
b764380a
C
565 })
566
567 it('Should create a redundancy on first video', async function () {
83903cb6 568 await servers[0].redundancy.addVideo({ videoId: video1Server2.id })
b764380a
C
569 })
570
571 it('Should have 2 webseeds on the first video', async function () {
572 this.timeout(80000)
573
574 await waitJobs(servers)
89d241a7 575 await servers[0].servers.waitUntilLog('Duplicated ', 5)
b764380a
C
576 await waitJobs(servers)
577
578 await check2Webseeds()
579 await check1PlaylistRedundancies()
7448551f 580 await checkStatsWith1Redundancy('manual')
b764380a
C
581 })
582
583 it('Should manually remove redundancies on server 1 and remove duplicated videos', async function () {
584 this.timeout(80000)
585
89d241a7 586 const body = await servers[0].redundancy.listVideos({ target: 'remote-videos' })
b764380a 587
dab04709 588 const videos = body.data
b764380a
C
589 expect(videos).to.have.lengthOf(1)
590
591 const video = videos[0]
dab04709 592
b764380a 593 for (const r of video.redundancies.files.concat(video.redundancies.streamingPlaylists)) {
89d241a7 594 await servers[0].redundancy.removeVideo({ redundancyId: r.id })
b764380a
C
595 }
596
597 await waitJobs(servers)
598 await wait(5000)
599
600 await check1WebSeed()
601 await check0PlaylistRedundancies()
602
83903cb6 603 await checkVideoFilesWereRemoved({ server: servers[0], video: video1Server2, onlyVideoFiles: true })
b764380a
C
604 })
605
606 after(async function () {
607 await cleanupTests(servers)
608 })
609 })
610
26370ce4
C
611 describe('Test expiration', function () {
612 const strategy = 'recently-added'
613
254d3579 614 async function checkContains (servers: PeerTubeServer[], str: string) {
26370ce4 615 for (const server of servers) {
83903cb6 616 const video = await server.videos.get({ id: video1Server2.uuid })
26370ce4
C
617
618 for (const f of video.files) {
619 expect(f.magnetUri).to.contain(str)
620 }
621 }
622 }
623
254d3579 624 async function checkNotContains (servers: PeerTubeServer[], str: string) {
26370ce4 625 for (const server of servers) {
83903cb6 626 const video = await server.videos.get({ id: video1Server2.uuid })
26370ce4
C
627
628 for (const f of video.files) {
629 expect(f.magnetUri).to.not.contain(str)
630 }
631 }
632 }
633
634 before(async function () {
635 this.timeout(120000)
636
7b6cf83e 637 await createServers(strategy, { min_lifetime: '7 seconds', min_views: 0 })
26370ce4
C
638
639 await enableRedundancyOnServer1()
640 })
641
642 it('Should still have 2 webseeds after 10 seconds', async function () {
09209296 643 this.timeout(80000)
26370ce4
C
644
645 await wait(10000)
646
647 try {
7243f84d 648 await checkContains(servers, 'http%3A%2F%2Flocalhost%3A' + servers[0].port)
26370ce4
C
649 } catch {
650 // Maybe a server deleted a redundancy in the scheduler
651 await wait(2000)
652
7243f84d 653 await checkContains(servers, 'http%3A%2F%2Flocalhost%3A' + servers[0].port)
26370ce4
C
654 }
655 })
656
657 it('Should stop server 1 and expire video redundancy', async function () {
09209296 658 this.timeout(80000)
26370ce4 659
9293139f 660 await killallServers([ servers[0] ])
26370ce4 661
6cb3482c 662 await wait(15000)
26370ce4 663
7243f84d 664 await checkNotContains([ servers[1], servers[2] ], 'http%3A%2F%2Flocalhost%3A' + servers[0].port)
26370ce4
C
665 })
666
7c3b7976
C
667 after(async function () {
668 await cleanupTests(servers)
26370ce4
C
669 })
670 })
671
672 describe('Test file replacement', function () {
673 let video2Server2UUID: string
674 const strategy = 'recently-added'
675
676 before(async function () {
677 this.timeout(120000)
678
7b6cf83e 679 await createServers(strategy, { min_lifetime: '7 seconds', min_views: 0 })
26370ce4
C
680
681 await enableRedundancyOnServer1()
682
683 await waitJobs(servers)
89d241a7 684 await servers[0].servers.waitUntilLog('Duplicated ', 5)
26370ce4
C
685 await waitJobs(servers)
686
83903cb6
C
687 await check2Webseeds()
688 await check1PlaylistRedundancies()
7448551f 689 await checkStatsWith1Redundancy(strategy)
26370ce4 690
89d241a7 691 const { uuid } = await servers[1].videos.upload({ attributes: { name: 'video 2 server 2', privacy: VideoPrivacy.PRIVATE } })
d23dd9fb 692 video2Server2UUID = uuid
5e8dd6e0
C
693
694 // Wait transcoding before federation
695 await waitJobs(servers)
696
89d241a7 697 await servers[1].videos.update({ id: video2Server2UUID, attributes: { privacy: VideoPrivacy.PUBLIC } })
26370ce4
C
698 })
699
6cb3482c
C
700 it('Should cache video 2 webseeds on the first video', async function () {
701 this.timeout(120000)
26370ce4
C
702
703 await waitJobs(servers)
704
6cb3482c 705 let checked = false
26370ce4 706
6cb3482c
C
707 while (checked === false) {
708 await wait(1000)
26370ce4
C
709
710 try {
83903cb6
C
711 await check1WebSeed()
712 await check0PlaylistRedundancies()
5e8dd6e0 713
09209296
C
714 await check2Webseeds(video2Server2UUID)
715 await check1PlaylistRedundancies(video2Server2UUID)
26370ce4 716
6cb3482c
C
717 checked = true
718 } catch {
719 checked = false
26370ce4
C
720 }
721 }
722 })
723
09209296
C
724 it('Should disable strategy and remove redundancies', async function () {
725 this.timeout(80000)
726
727 await waitJobs(servers)
728
9293139f 729 await killallServers([ servers[0] ])
254d3579 730 await servers[0].run({
09209296
C
731 redundancy: {
732 videos: {
733 check_interval: '1 second',
734 strategies: []
735 }
736 }
737 })
738
739 await waitJobs(servers)
740
83903cb6 741 await checkVideoFilesWereRemoved({ server: servers[0], video: video1Server2, onlyVideoFiles: true })
09209296
C
742 })
743
7c3b7976
C
744 after(async function () {
745 await cleanupTests(servers)
26370ce4
C
746 })
747 })
748})