X-Git-Url: https://git.immae.eu/?a=blobdiff_plain;f=server%2Ftests%2Fapi%2Fredundancy%2Fredundancy.ts;h=6f2c5907661635e81b6da076cd7dd4533b069d79;hb=bec4ea343987c69252b84d02f444c0f033d4a3f9;hp=1960854b654136e5d5b40818c7aa5490a40f95a7;hpb=6d8c8ea73a774c3568e6d28a4cbebcf7979d5c2a;p=github%2FChocobozzz%2FPeerTube.git diff --git a/server/tests/api/redundancy/redundancy.ts b/server/tests/api/redundancy/redundancy.ts index 1960854b6..6f2c59076 100644 --- a/server/tests/api/redundancy/redundancy.ts +++ b/server/tests/api/redundancy/redundancy.ts @@ -4,29 +4,36 @@ import * as chai from 'chai' import 'mocha' import { VideoDetails } from '../../../../shared/models/videos' import { + checkSegmentHash, + checkVideoFilesWereRemoved, cleanupTests, doubleFollow, flushAndRunMultipleServers, getFollowingListPaginationAndSort, getVideo, + getVideoWithToken, immutableAssign, - killallServers, makeGetRequest, + killallServers, + makeGetRequest, + removeVideo, + reRunServer, root, ServerInfo, - setAccessTokensToServers, unfollow, + setAccessTokensToServers, + unfollow, uploadVideo, viewVideo, wait, - waitUntilLog, - checkVideoFilesWereRemoved, removeVideo -} from '../../utils' -import { waitJobs } from '../../utils/server/jobs' + waitUntilLog +} from '../../../../shared/extra-utils' +import { waitJobs } from '../../../../shared/extra-utils/server/jobs' + import * as magnetUtil from 'magnet-uri' -import { updateRedundancy } from '../../utils/server/redundancy' +import { updateRedundancy } from '../../../../shared/extra-utils/server/redundancy' import { ActorFollow } from '../../../../shared/models/actors' import { readdir } from 'fs-extra' import { join } from 'path' import { VideoRedundancyStrategy } from '../../../../shared/models/redundancy' -import { getStats } from '../../utils/server/stats' +import { getStats } from '../../../../shared/extra-utils/server/stats' import { ServerStats } from '../../../../shared/models/server/server-stats.model' const expect = chai.expect @@ -45,8 +52,13 @@ function checkMagnetWebseeds (file: { magnetUri: string, resolution: { id: numbe expect(parsed.urlList).to.have.lengthOf(baseWebseeds.length) } -async function runServers (strategy: VideoRedundancyStrategy, additionalParams: any = {}) { +async function flushAndRunServers (strategy: VideoRedundancyStrategy, additionalParams: any = {}) { const config = { + transcoding: { + hls: { + enabled: true + } + }, redundancy: { videos: { check_interval: '5 seconds', @@ -54,7 +66,7 @@ async function runServers (strategy: VideoRedundancyStrategy, additionalParams: immutableAssign({ min_lifetime: '1 hour', strategy: strategy, - size: '100KB' + size: '200KB' }, additionalParams) ] } @@ -84,21 +96,122 @@ async function runServers (strategy: VideoRedundancyStrategy, additionalParams: await waitJobs(servers) } -async function check1WebSeed (strategy: VideoRedundancyStrategy, videoUUID?: string) { +async function check1WebSeed (videoUUID?: string) { if (!videoUUID) videoUUID = video1Server2UUID const webseeds = [ - 'http://localhost:9002/static/webseed/' + videoUUID + `http://localhost:${servers[ 1 ].port}/static/webseed/${videoUUID}` ] for (const server of servers) { - { - const res = await getVideo(server.url, videoUUID) + // With token to avoid issues with video follow constraints + const res = await getVideoWithToken(server.url, server.accessToken, videoUUID) - const video: VideoDetails = res.body - for (const f of video.files) { - checkMagnetWebseeds(f, webseeds, server) - } + const video: VideoDetails = res.body + for (const f of video.files) { + checkMagnetWebseeds(f, webseeds, server) + } + } +} + +async function check2Webseeds (videoUUID?: string) { + if (!videoUUID) videoUUID = video1Server2UUID + + const webseeds = [ + `http://localhost:${servers[ 0 ].port}/static/redundancy/${videoUUID}`, + `http://localhost:${servers[ 1 ].port}/static/webseed/${videoUUID}` + ] + + for (const server of servers) { + const res = await getVideo(server.url, videoUUID) + + const video: VideoDetails = res.body + + for (const file of video.files) { + checkMagnetWebseeds(file, webseeds, server) + + await makeGetRequest({ + url: servers[0].url, + statusCodeExpected: 200, + path: '/static/redundancy/' + `${videoUUID}-${file.resolution.id}.mp4`, + contentType: null + }) + await makeGetRequest({ + url: servers[1].url, + statusCodeExpected: 200, + path: `/static/webseed/${videoUUID}-${file.resolution.id}.mp4`, + contentType: null + }) + } + } + + const directories = [ + 'test' + servers[0].internalServerNumber + '/redundancy', + 'test' + servers[1].internalServerNumber + '/videos' + ] + + for (const directory of directories) { + const files = await readdir(join(root(), directory)) + expect(files).to.have.length.at.least(4) + + for (const resolution of [ 240, 360, 480, 720 ]) { + expect(files.find(f => f === `${videoUUID}-${resolution}.mp4`)).to.not.be.undefined + } + } +} + +async function check0PlaylistRedundancies (videoUUID?: string) { + if (!videoUUID) videoUUID = video1Server2UUID + + for (const server of servers) { + // With token to avoid issues with video follow constraints + const res = await getVideoWithToken(server.url, server.accessToken, videoUUID) + const video: VideoDetails = res.body + + expect(video.streamingPlaylists).to.be.an('array') + expect(video.streamingPlaylists).to.have.lengthOf(1) + expect(video.streamingPlaylists[0].redundancies).to.have.lengthOf(0) + } +} + +async function check1PlaylistRedundancies (videoUUID?: string) { + if (!videoUUID) videoUUID = video1Server2UUID + + for (const server of servers) { + const res = await getVideo(server.url, videoUUID) + const video: VideoDetails = res.body + + expect(video.streamingPlaylists).to.have.lengthOf(1) + expect(video.streamingPlaylists[0].redundancies).to.have.lengthOf(1) + + const redundancy = video.streamingPlaylists[0].redundancies[0] + + expect(redundancy.baseUrl).to.equal(servers[0].url + '/static/redundancy/hls/' + videoUUID) + } + + const baseUrlPlaylist = servers[1].url + '/static/streaming-playlists/hls' + const baseUrlSegment = servers[0].url + '/static/redundancy/hls' + + const res = await getVideo(servers[0].url, videoUUID) + const hlsPlaylist = (res.body as VideoDetails).streamingPlaylists[0] + + for (const resolution of [ 240, 360, 480, 720 ]) { + await checkSegmentHash(baseUrlPlaylist, baseUrlSegment, videoUUID, resolution, hlsPlaylist) + } + + const directories = [ + 'test' + servers[0].internalServerNumber + '/redundancy/hls', + 'test' + servers[1].internalServerNumber + '/streaming-playlists/hls' + ] + + for (const directory of directories) { + const files = await readdir(join(root(), directory, videoUUID)) + expect(files).to.have.length.at.least(4) + + for (const resolution of [ 240, 360, 480, 720 ]) { + const filename = `${videoUUID}-${resolution}-fragmented.mp4` + + expect(files.find(f => f === filename)).to.not.be.undefined } } } @@ -111,8 +224,8 @@ async function checkStatsWith2Webseed (strategy: VideoRedundancyStrategy) { const stat = data.videosRedundancy[0] expect(stat.strategy).to.equal(strategy) - expect(stat.totalSize).to.equal(102400) - expect(stat.totalUsed).to.be.at.least(1).and.below(102401) + expect(stat.totalSize).to.equal(204800) + expect(stat.totalUsed).to.be.at.least(1).and.below(204801) expect(stat.totalVideoFiles).to.equal(4) expect(stat.totalVideos).to.equal(1) } @@ -125,57 +238,19 @@ async function checkStatsWith1Webseed (strategy: VideoRedundancyStrategy) { const stat = data.videosRedundancy[0] expect(stat.strategy).to.equal(strategy) - expect(stat.totalSize).to.equal(102400) + expect(stat.totalSize).to.equal(204800) expect(stat.totalUsed).to.equal(0) expect(stat.totalVideoFiles).to.equal(0) expect(stat.totalVideos).to.equal(0) } -async function check2Webseeds (strategy: VideoRedundancyStrategy, videoUUID?: string) { - if (!videoUUID) videoUUID = video1Server2UUID - - const webseeds = [ - 'http://localhost:9001/static/webseed/' + videoUUID, - 'http://localhost:9002/static/webseed/' + videoUUID - ] - - for (const server of servers) { - const res = await getVideo(server.url, videoUUID) - - const video: VideoDetails = res.body - - for (const file of video.files) { - checkMagnetWebseeds(file, webseeds, server) - - // Only servers 1 and 2 have the video - if (server.serverNumber !== 3) { - await makeGetRequest({ - url: server.url, - statusCodeExpected: 200, - path: '/static/webseed/' + `${videoUUID}-${file.resolution.id}.mp4`, - contentType: null - }) - } - } - } - - for (const directory of [ 'test1', 'test2' ]) { - const files = await readdir(join(root(), directory, 'videos')) - expect(files).to.have.length.at.least(4) - - for (const resolution of [ 240, 360, 480, 720 ]) { - expect(files.find(f => f === `${videoUUID}-${resolution}.mp4`)).to.not.be.undefined - } - } -} - async function enableRedundancyOnServer1 () { await updateRedundancy(servers[ 0 ].url, servers[ 0 ].accessToken, servers[ 1 ].host, true) const res = await getFollowingListPaginationAndSort(servers[ 0 ].url, 0, 5, '-createdAt') const follows: ActorFollow[] = res.body.data - const server2 = follows.find(f => f.following.host === 'localhost:9002') - const server3 = follows.find(f => f.following.host === 'localhost:9003') + const server2 = follows.find(f => f.following.host === `localhost:${servers[ 1 ].port}`) + const server3 = follows.find(f => f.following.host === `localhost:${servers[ 2 ].port}`) expect(server3).to.not.be.undefined expect(server3.following.hostRedundancyAllowed).to.be.false @@ -189,8 +264,8 @@ async function disableRedundancyOnServer1 () { const res = await getFollowingListPaginationAndSort(servers[ 0 ].url, 0, 5, '-createdAt') const follows: ActorFollow[] = res.body.data - const server2 = follows.find(f => f.following.host === 'localhost:9002') - const server3 = follows.find(f => f.following.host === 'localhost:9003') + const server2 = follows.find(f => f.following.host === `localhost:${servers[ 1 ].port}`) + const server3 = follows.find(f => f.following.host === `localhost:${servers[ 2 ].port}`) expect(server3).to.not.be.undefined expect(server3.following.hostRedundancyAllowed).to.be.false @@ -199,10 +274,6 @@ async function disableRedundancyOnServer1 () { expect(server2.following.hostRedundancyAllowed).to.be.false } -async function cleanServers () { - killallServers(servers) -} - describe('Test videos redundancy', function () { describe('With most-views strategy', function () { @@ -211,11 +282,12 @@ describe('Test videos redundancy', function () { before(function () { this.timeout(120000) - return runServers(strategy) + return flushAndRunServers(strategy) }) it('Should have 1 webseed on the first video', async function () { - await check1WebSeed(strategy) + await check1WebSeed() + await check0PlaylistRedundancies() await checkStatsWith1Webseed(strategy) }) @@ -223,32 +295,34 @@ describe('Test videos redundancy', function () { return enableRedundancyOnServer1() }) - it('Should have 2 webseed on the first video', async function () { - this.timeout(40000) + it('Should have 2 webseeds on the first video', async function () { + this.timeout(80000) await waitJobs(servers) - await waitUntilLog(servers[0], 'Duplicated ', 4) + await waitUntilLog(servers[0], 'Duplicated ', 5) await waitJobs(servers) - await check2Webseeds(strategy) + await check2Webseeds() + await check1PlaylistRedundancies() await checkStatsWith2Webseed(strategy) }) it('Should undo redundancy on server 1 and remove duplicated videos', async function () { - this.timeout(40000) + this.timeout(80000) await disableRedundancyOnServer1() await waitJobs(servers) await wait(5000) - await check1WebSeed(strategy) + await check1WebSeed() + await check0PlaylistRedundancies() - await checkVideoFilesWereRemoved(video1Server2UUID, servers[0].serverNumber, [ 'videos' ]) + await checkVideoFilesWereRemoved(video1Server2UUID, servers[0].serverNumber, [ 'videos', join('playlists', 'hls') ]) }) - after(function () { - return cleanServers() + after(async function () { + return cleanupTests(servers) }) }) @@ -258,11 +332,12 @@ describe('Test videos redundancy', function () { before(function () { this.timeout(120000) - return runServers(strategy) + return flushAndRunServers(strategy) }) it('Should have 1 webseed on the first video', async function () { - await check1WebSeed(strategy) + await check1WebSeed() + await check0PlaylistRedundancies() await checkStatsWith1Webseed(strategy) }) @@ -270,32 +345,34 @@ describe('Test videos redundancy', function () { return enableRedundancyOnServer1() }) - it('Should have 2 webseed on the first video', async function () { - this.timeout(40000) + it('Should have 2 webseeds on the first video', async function () { + this.timeout(80000) await waitJobs(servers) - await waitUntilLog(servers[0], 'Duplicated ', 4) + await waitUntilLog(servers[0], 'Duplicated ', 5) await waitJobs(servers) - await check2Webseeds(strategy) + await check2Webseeds() + await check1PlaylistRedundancies() await checkStatsWith2Webseed(strategy) }) it('Should unfollow on server 1 and remove duplicated videos', async function () { - this.timeout(40000) + this.timeout(80000) await unfollow(servers[0].url, servers[0].accessToken, servers[1]) await waitJobs(servers) await wait(5000) - await check1WebSeed(strategy) + await check1WebSeed() + await check0PlaylistRedundancies() await checkVideoFilesWereRemoved(video1Server2UUID, servers[0].serverNumber, [ 'videos' ]) }) - after(function () { - return cleanServers() + after(async function () { + await cleanupTests(servers) }) }) @@ -305,11 +382,12 @@ describe('Test videos redundancy', function () { before(function () { this.timeout(120000) - return runServers(strategy, { min_views: 3 }) + return flushAndRunServers(strategy, { min_views: 3 }) }) it('Should have 1 webseed on the first video', async function () { - await check1WebSeed(strategy) + await check1WebSeed() + await check0PlaylistRedundancies() await checkStatsWith1Webseed(strategy) }) @@ -318,18 +396,19 @@ describe('Test videos redundancy', function () { }) it('Should still have 1 webseed on the first video', async function () { - this.timeout(40000) + this.timeout(80000) await waitJobs(servers) await wait(15000) await waitJobs(servers) - await check1WebSeed(strategy) + await check1WebSeed() + await check0PlaylistRedundancies() await checkStatsWith1Webseed(strategy) }) it('Should view 2 times the first video to have > min_views config', async function () { - this.timeout(40000) + this.timeout(80000) await viewVideo(servers[ 0 ].url, video1Server2UUID) await viewVideo(servers[ 2 ].url, video1Server2UUID) @@ -338,14 +417,15 @@ describe('Test videos redundancy', function () { await waitJobs(servers) }) - it('Should have 2 webseed on the first video', async function () { - this.timeout(40000) + it('Should have 2 webseeds on the first video', async function () { + this.timeout(80000) await waitJobs(servers) - await waitUntilLog(servers[0], 'Duplicated ', 4) + await waitUntilLog(servers[0], 'Duplicated ', 5) await waitJobs(servers) - await check2Webseeds(strategy) + await check2Webseeds() + await check1PlaylistRedundancies() await checkStatsWith2Webseed(strategy) }) @@ -361,8 +441,8 @@ describe('Test videos redundancy', function () { } }) - after(function () { - return cleanServers() + after(async function () { + await cleanupTests(servers) }) }) @@ -394,38 +474,38 @@ describe('Test videos redundancy', function () { before(async function () { this.timeout(120000) - await runServers(strategy, { min_lifetime: '7 seconds', min_views: 0 }) + await flushAndRunServers(strategy, { min_lifetime: '7 seconds', min_views: 0 }) await enableRedundancyOnServer1() }) it('Should still have 2 webseeds after 10 seconds', async function () { - this.timeout(40000) + this.timeout(80000) await wait(10000) try { - await checkContains(servers, 'http%3A%2F%2Flocalhost%3A9001') + await checkContains(servers, 'http%3A%2F%2Flocalhost%3A' + servers[0].port) } catch { // Maybe a server deleted a redundancy in the scheduler await wait(2000) - await checkContains(servers, 'http%3A%2F%2Flocalhost%3A9001') + await checkContains(servers, 'http%3A%2F%2Flocalhost%3A' + servers[0].port) } }) it('Should stop server 1 and expire video redundancy', async function () { - this.timeout(40000) + this.timeout(80000) killallServers([ servers[0] ]) - await wait(10000) + await wait(15000) - await checkNotContains([ servers[1], servers[2] ], 'http%3A%2F%2Flocalhost%3A9001') + await checkNotContains([ servers[1], servers[2] ], 'http%3A%2F%2Flocalhost%3A' + servers[0].port) }) - after(function () { - return killallServers([ servers[1], servers[2] ]) + after(async function () { + await cleanupTests(servers) }) }) @@ -436,48 +516,67 @@ describe('Test videos redundancy', function () { before(async function () { this.timeout(120000) - await runServers(strategy, { min_lifetime: '7 seconds', min_views: 0 }) + await flushAndRunServers(strategy, { min_lifetime: '7 seconds', min_views: 0 }) await enableRedundancyOnServer1() await waitJobs(servers) - await waitUntilLog(servers[0], 'Duplicated ', 4) + await waitUntilLog(servers[0], 'Duplicated ', 5) await waitJobs(servers) - await check2Webseeds(strategy) + await check2Webseeds() + await check1PlaylistRedundancies() await checkStatsWith2Webseed(strategy) const res = await uploadVideo(servers[ 1 ].url, servers[ 1 ].accessToken, { name: 'video 2 server 2' }) video2Server2UUID = res.body.video.uuid }) - it('Should cache video 2 webseed on the first video', async function () { - this.timeout(50000) + it('Should cache video 2 webseeds on the first video', async function () { + this.timeout(120000) await waitJobs(servers) - await wait(7000) + let checked = false - try { - await check1WebSeed(strategy, video1Server2UUID) - await check2Webseeds(strategy, video2Server2UUID) - } catch { - await wait(3000) + while (checked === false) { + await wait(1000) try { - await check1WebSeed(strategy, video1Server2UUID) - await check2Webseeds(strategy, video2Server2UUID) - } catch { - await wait(5000) + await check1WebSeed(video1Server2UUID) + await check0PlaylistRedundancies(video1Server2UUID) + await check2Webseeds(video2Server2UUID) + await check1PlaylistRedundancies(video2Server2UUID) - await check1WebSeed(strategy, video1Server2UUID) - await check2Webseeds(strategy, video2Server2UUID) + checked = true + } catch { + checked = false } } }) - after(function () { - return cleanServers() + it('Should disable strategy and remove redundancies', async function () { + this.timeout(80000) + + await waitJobs(servers) + + killallServers([ servers[ 0 ] ]) + await reRunServer(servers[ 0 ], { + redundancy: { + videos: { + check_interval: '1 second', + strategies: [] + } + } + }) + + await waitJobs(servers) + + await checkVideoFilesWereRemoved(video1Server2UUID, servers[0].serverNumber, [ join('redundancy', 'hls') ]) + }) + + after(async function () { + await cleanupTests(servers) }) }) })