/* tslint:disable:no-unused-expression */
import * as chai from 'chai'
import 'mocha'
import {
cleanupTests,
doubleFollow,
flushAndRunMultipleServers,
getLocalIdByUUID,
ServerInfo,
setAccessTokensToServers,
uploadVideo,
uploadVideoAndGetId,
waitUntilLog
} from '../../../../shared/extra-utils'
import { waitJobs } from '../../../../shared/extra-utils/server/jobs'
import { addVideoRedundancy, listVideoRedundancies, removeVideoRedundancy, updateRedundancy } from '@shared/extra-utils/server/redundancy'
import { VideoPrivacy, VideoRedundanciesTarget, VideoRedundancy } from '@shared/models'
const expect = chai.expect
describe('Test manage videos redundancy', function () {
const targets: VideoRedundanciesTarget[] = [ 'my-videos', 'remote-videos' ]
let servers: ServerInfo[]
let video1Server2UUID: string
let video2Server2UUID: string
let redundanciesToRemove: number[] = []
before(async function () {
this.timeout(120000)
const config = {
transcoding: {
hls: {
enabled: true
}
},
redundancy: {
videos: {
check_interval: '1 second',
strategies: [
{
strategy: 'recently-added',
min_lifetime: '1 hour',
size: '10MB',
min_views: 0
}
]
}
}
}
servers = await flushAndRunMultipleServers(3, config)
// Get the access tokens
await setAccessTokensToServers(servers)
{
const res = await uploadVideo(servers[ 1 ].url, servers[ 1 ].accessToken, { name: 'video 1 server 2' })
video1Server2UUID = res.body.video.uuid
}
{
const res = await uploadVideo(servers[ 1 ].url, servers[ 1 ].accessToken, { name: 'video 2 server 2' })
video2Server2UUID = res.body.video.uuid
}
await waitJobs(servers)
// Server 1 and server 2 follow each other
await doubleFollow(servers[ 0 ], servers[ 1 ])
await updateRedundancy(servers[ 0 ].url, servers[ 0 ].accessToken, servers[ 1 ].host, true)
await waitJobs(servers)
})
it('Should not have redundancies on server 3', async function () {
for (const target of targets) {
const res = await listVideoRedundancies({
url: servers[2].url,
accessToken: servers[2].accessToken,
target
})
expect(res.body.total).to.equal(0)
expect(res.body.data).to.have.lengthOf(0)
}
})
it('Should not have "remote-videos" redundancies on server 2', async function () {
this.timeout(120000)
await waitJobs(servers)
await waitUntilLog(servers[0], 'Duplicated ', 10)
await waitJobs(servers)
const res = await listVideoRedundancies({
url: servers[1].url,
accessToken: servers[1].accessToken,
target: 'remote-videos'
})
expect(res.body.total).to.equal(0)
expect(res.body.data).to.have.lengthOf(0)
})
it('Should have "my-videos" redundancies on server 2', async function () {
this.timeout(120000)
const res = await listVideoRedundancies({
url: servers[1].url,
accessToken: servers[1].accessToken,
target: 'my-videos'
})
expect(res.body.total).to.equal(2)
const videos = res.body.data as VideoRedundancy[]
expect(videos).to.have.lengthOf(2)
const videos1 = videos.find(v => v.uuid === video1Server2UUID)
const videos2 = videos.find(v => v.uuid === video2Server2UUID)
expect(videos1.name).to.equal('video 1 server 2')
expect(videos2.name).to.equal('video 2 server 2')
expect(videos1.redundancies.files).to.have.lengthOf(4)
expect(videos1.redundancies.streamingPlaylists).to.have.lengthOf(1)
const redundancies = videos1.redundancies.files.concat(videos1.redundancies.streamingPlaylists)
for (const r of redundancies) {
expect(r.strategy).to.be.null
expect(r.fileUrl).to.exist
expect(r.createdAt).to.exist
expect(r.updatedAt).to.exist
expect(r.expiresOn).to.exist
}
})
it('Should not have "my-videos" redundancies on server 1', async function () {
const res = await listVideoRedundancies({
url: servers[0].url,
accessToken: servers[0].accessToken,
target: 'my-videos'
})
expect(res.body.total).to.equal(0)
expect(res.body.data).to.have.lengthOf(0)
})
it('Should have "remote-videos" redundancies on server 1', async function () {
this.timeout(120000)
const res = await listVideoRedundancies({
url: servers[0].url,
accessToken: servers[0].accessToken,
target: 'remote-videos'
})
expect(res.body.total).to.equal(2)
const videos = res.body.data as VideoRedundancy[]
expect(videos).to.have.lengthOf(2)
const videos1 = videos.find(v => v.uuid === video1Server2UUID)
const videos2 = videos.find(v => v.uuid === video2Server2UUID)
expect(videos1.name).to.equal('video 1 server 2')
expect(videos2.name).to.equal('video 2 server 2')
expect(videos1.redundancies.files).to.have.lengthOf(4)
expect(videos1.redundancies.streamingPlaylists).to.have.lengthOf(1)
const redundancies = videos1.redundancies.files.concat(videos1.redundancies.streamingPlaylists)
for (const r of redundancies) {
expect(r.strategy).to.equal('recently-added')
expect(r.fileUrl).to.exist
expect(r.createdAt).to.exist
expect(r.updatedAt).to.exist
expect(r.expiresOn).to.exist
}
})
it('Should correctly paginate and sort results', async function () {
{
const res = await listVideoRedundancies({
url: servers[0].url,
accessToken: servers[0].accessToken,
target: 'remote-videos',
sort: 'name',
start: 0,
count: 2
})
const videos = res.body.data
expect(videos[ 0 ].name).to.equal('video 1 server 2')
expect(videos[ 1 ].name).to.equal('video 2 server 2')
}
{
const res = await listVideoRedundancies({
url: servers[0].url,
accessToken: servers[0].accessToken,
target: 'remote-videos',
sort: '-name',
start: 0,
count: 2
})
const videos = res.body.data
expect(videos[ 0 ].name).to.equal('video 2 server 2')
expect(videos[ 1 ].name).to.equal('video 1 server 2')
}
{
const res = await listVideoRedundancies({
url: servers[0].url,
accessToken: servers[0].accessToken,
target: 'remote-videos',
sort: '-name',
start: 1,
count: 1
})
const videos = res.body.data
expect(videos[ 0 ].name).to.equal('video 1 server 2')
}
})
it('Should manually add a redundancy and list it', async function () {
this.timeout(120000)
const uuid = (await uploadVideoAndGetId({ server: servers[ 1 ], videoName: 'video 3 server 2', privacy: VideoPrivacy.UNLISTED })).uuid
await waitJobs(servers)
const videoId = await getLocalIdByUUID(servers[0].url, uuid)
await addVideoRedundancy({
url: servers[0].url,
accessToken: servers[0].accessToken,
videoId
})
await waitJobs(servers)
await waitUntilLog(servers[0], 'Duplicated ', 15)
await waitJobs(servers)
{
const res = await listVideoRedundancies({
url: servers[0].url,
accessToken: servers[0].accessToken,
target: 'remote-videos',
sort: '-name',
start: 0,
count: 5
})
const videos = res.body.data
expect(videos[ 0 ].name).to.equal('video 3 server 2')
const video = videos[ 0 ]
expect(video.redundancies.files).to.have.lengthOf(4)
expect(video.redundancies.streamingPlaylists).to.have.lengthOf(1)
const redundancies = video.redundancies.files.concat(video.redundancies.streamingPlaylists)
for (const r of redundancies) {
redundanciesToRemove.push(r.id)
expect(r.strategy).to.equal('manual')
expect(r.fileUrl).to.exist
expect(r.createdAt).to.exist
expect(r.updatedAt).to.exist
expect(r.expiresOn).to.be.null
}
}
const res = await listVideoRedundancies({
url: servers[1].url,
accessToken: servers[1].accessToken,
target: 'my-videos',
sort: '-name',
start: 0,
count: 5
})
const videos = res.body.data
expect(videos[ 0 ].name).to.equal('video 3 server 2')
const video = videos[ 0 ]
expect(video.redundancies.files).to.have.lengthOf(4)
expect(video.redundancies.streamingPlaylists).to.have.lengthOf(1)
const redundancies = video.redundancies.files.concat(video.redundancies.streamingPlaylists)
for (const r of redundancies) {
expect(r.strategy).to.be.null
expect(r.fileUrl).to.exist
expect(r.createdAt).to.exist
expect(r.updatedAt).to.exist
expect(r.expiresOn).to.be.null
}
})
it('Should manually remove a redundancy and remove it from the list', async function () {
this.timeout(120000)
for (const redundancyId of redundanciesToRemove) {
await removeVideoRedundancy({
url: servers[ 0 ].url,
accessToken: servers[ 0 ].accessToken,
redundancyId
})
}
{
const res = await listVideoRedundancies({
url: servers[0].url,
accessToken: servers[0].accessToken,
target: 'remote-videos',
sort: '-name',
start: 0,
count: 5
})
const videos = res.body.data
expect(videos).to.have.lengthOf(2)
expect(videos[ 0 ].name).to.equal('video 2 server 2')
redundanciesToRemove = []
const video = videos[ 0 ]
expect(video.redundancies.files).to.have.lengthOf(4)
expect(video.redundancies.streamingPlaylists).to.have.lengthOf(1)
const redundancies = video.redundancies.files.concat(video.redundancies.streamingPlaylists)
for (const r of redundancies) {
redundanciesToRemove.push(r.id)
}
}
})
it('Should remove another (auto) redundancy', async function () {
{
for (const redundancyId of redundanciesToRemove) {
await removeVideoRedundancy({
url: servers[ 0 ].url,
accessToken: servers[ 0 ].accessToken,
redundancyId
})
}
const res = await listVideoRedundancies({
url: servers[0].url,
accessToken: servers[0].accessToken,
target: 'remote-videos',
sort: '-name',
start: 0,
count: 5
})
const videos = res.body.data
expect(videos[ 0 ].name).to.equal('video 1 server 2')
expect(videos).to.have.lengthOf(1)
}
})
after(async function () {
await cleanupTests(servers)
})
})