]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame - server/tests/api/server/redundancy.ts
Refractor audit user identifier
[github/Chocobozzz/PeerTube.git] / server / tests / api / server / redundancy.ts
CommitLineData
c48e82b5
C
1/* tslint:disable:no-unused-expression */
2
3import * as chai from 'chai'
4import 'mocha'
5import { VideoDetails } from '../../../../shared/models/videos'
6import {
7 doubleFollow,
8 flushAndRunMultipleServers,
c48e82b5
C
9 getFollowingListPaginationAndSort,
10 getVideo,
993cef4b 11 immutableAssign,
c48e82b5 12 killallServers,
993cef4b 13 root,
c48e82b5
C
14 ServerInfo,
15 setAccessTokensToServers,
16 uploadVideo,
993cef4b
C
17 viewVideo,
18 wait
c48e82b5
C
19} from '../../utils'
20import { waitJobs } from '../../utils/server/jobs'
21import * as magnetUtil from 'magnet-uri'
22import { updateRedundancy } from '../../utils/server/redundancy'
23import { ActorFollow } from '../../../../shared/models/actors'
24import { readdir } from 'fs-extra'
25import { join } from 'path'
b36f41ca 26import { VideoRedundancyStrategy } from '../../../../shared/models/redundancy'
4b5384f6
C
27import { getStats } from '../../utils/server/stats'
28import { ServerStats } from '../../../../shared/models/server/server-stats.model'
c48e82b5
C
29
30const expect = chai.expect
31
b36f41ca
C
32let servers: ServerInfo[] = []
33let video1Server2UUID: string
34let video2Server2UUID: string
35
c48e82b5
C
36function checkMagnetWebseeds (file: { magnetUri: string, resolution: { id: number } }, baseWebseeds: string[]) {
37 const parsed = magnetUtil.decode(file.magnetUri)
38
39 for (const ws of baseWebseeds) {
40 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
42 }
43}
44
3f6b6a56 45async function runServers (strategy: VideoRedundancyStrategy, additionalParams: any = {}) {
b36f41ca
C
46 const config = {
47 redundancy: {
993cef4b
C
48 videos: {
49 check_interval: '5 seconds',
50 strategies: [
51 immutableAssign({
52 strategy: strategy,
53 size: '100KB'
54 }, additionalParams)
55 ]
56 }
b36f41ca
C
57 }
58 }
59 servers = await flushAndRunMultipleServers(3, config)
c48e82b5 60
b36f41ca
C
61 // Get the access tokens
62 await setAccessTokensToServers(servers)
c48e82b5 63
b36f41ca
C
64 {
65 const res = await uploadVideo(servers[ 1 ].url, servers[ 1 ].accessToken, { name: 'video 1 server 2' })
66 video1Server2UUID = res.body.video.uuid
c48e82b5 67
b36f41ca
C
68 await viewVideo(servers[ 1 ].url, video1Server2UUID)
69 }
c48e82b5 70
b36f41ca
C
71 {
72 const res = await uploadVideo(servers[ 1 ].url, servers[ 1 ].accessToken, { name: 'video 2 server 2' })
73 video2Server2UUID = res.body.video.uuid
74 }
c48e82b5 75
b36f41ca 76 await waitJobs(servers)
c48e82b5 77
b36f41ca
C
78 // Server 1 and server 2 follow each other
79 await doubleFollow(servers[ 0 ], servers[ 1 ])
80 // Server 1 and server 3 follow each other
81 await doubleFollow(servers[ 0 ], servers[ 2 ])
82 // Server 2 and server 3 follow each other
83 await doubleFollow(servers[ 1 ], servers[ 2 ])
84
85 await waitJobs(servers)
86}
c48e82b5 87
4b5384f6 88async function check1WebSeed (strategy: VideoRedundancyStrategy) {
b36f41ca
C
89 const webseeds = [
90 'http://localhost:9002/static/webseed/' + video1Server2UUID
91 ]
c48e82b5 92
b36f41ca 93 for (const server of servers) {
4b5384f6
C
94 {
95 const res = await getVideo(server.url, video1Server2UUID)
c48e82b5 96
4b5384f6
C
97 const video: VideoDetails = res.body
98 video.files.forEach(f => checkMagnetWebseeds(f, webseeds))
99 }
100
101 {
102 const res = await getStats(server.url)
103 const data: ServerStats = res.body
104
105 expect(data.videosRedundancy).to.have.lengthOf(1)
106
107 const stat = data.videosRedundancy[0]
108 expect(stat.strategy).to.equal(strategy)
109 expect(stat.totalSize).to.equal(102400)
110 expect(stat.totalUsed).to.equal(0)
111 expect(stat.totalVideoFiles).to.equal(0)
112 expect(stat.totalVideos).to.equal(0)
113 }
b36f41ca
C
114 }
115}
116
117async function enableRedundancy () {
118 await updateRedundancy(servers[ 0 ].url, servers[ 0 ].accessToken, servers[ 1 ].host, true)
119
120 const res = await getFollowingListPaginationAndSort(servers[ 0 ].url, 0, 5, '-createdAt')
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
128 expect(server2).to.not.be.undefined
129 expect(server2.following.hostRedundancyAllowed).to.be.true
130}
c48e82b5 131
4b5384f6 132async function check2Webseeds (strategy: VideoRedundancyStrategy) {
b36f41ca
C
133 await waitJobs(servers)
134 await wait(15000)
135 await waitJobs(servers)
c48e82b5 136
b36f41ca
C
137 const webseeds = [
138 'http://localhost:9001/static/webseed/' + video1Server2UUID,
139 'http://localhost:9002/static/webseed/' + video1Server2UUID
140 ]
c48e82b5 141
b36f41ca 142 for (const server of servers) {
4b5384f6
C
143 {
144 const res = await getVideo(server.url, video1Server2UUID)
b36f41ca 145
4b5384f6 146 const video: VideoDetails = res.body
b36f41ca 147
4b5384f6
C
148 for (const file of video.files) {
149 checkMagnetWebseeds(file, webseeds)
150 }
c48e82b5 151 }
b36f41ca 152 }
c48e82b5 153
b36f41ca
C
154 const files = await readdir(join(root(), 'test1', 'videos'))
155 expect(files).to.have.lengthOf(4)
c48e82b5 156
b36f41ca
C
157 for (const resolution of [ 240, 360, 480, 720 ]) {
158 expect(files.find(f => f === `${video1Server2UUID}-${resolution}.mp4`)).to.not.be.undefined
159 }
4b5384f6
C
160
161 {
162 const res = await getStats(servers[0].url)
163 const data: ServerStats = res.body
164
165 expect(data.videosRedundancy).to.have.lengthOf(1)
166 const stat = data.videosRedundancy[0]
167
168 expect(stat.strategy).to.equal(strategy)
169 expect(stat.totalSize).to.equal(102400)
170 expect(stat.totalUsed).to.be.at.least(1).and.below(102401)
171 expect(stat.totalVideoFiles).to.equal(4)
172 expect(stat.totalVideos).to.equal(1)
173 }
b36f41ca 174}
c48e82b5 175
b36f41ca
C
176async function cleanServers () {
177 killallServers(servers)
178}
c48e82b5 179
b36f41ca 180describe('Test videos redundancy', function () {
c48e82b5 181
b36f41ca 182 describe('With most-views strategy', function () {
4b5384f6 183 const strategy = 'most-views'
c48e82b5 184
b36f41ca
C
185 before(function () {
186 this.timeout(120000)
c48e82b5 187
4b5384f6 188 return runServers(strategy)
b36f41ca 189 })
c48e82b5 190
b36f41ca 191 it('Should have 1 webseed on the first video', function () {
4b5384f6 192 return check1WebSeed(strategy)
b36f41ca 193 })
c48e82b5 194
3f6b6a56 195 it('Should enable redundancy on server 1', function () {
b36f41ca
C
196 return enableRedundancy()
197 })
c48e82b5 198
3f6b6a56 199 it('Should have 2 webseed on the first video', function () {
b36f41ca 200 this.timeout(40000)
c48e82b5 201
4b5384f6 202 return check2Webseeds(strategy)
b36f41ca 203 })
c48e82b5 204
b36f41ca
C
205 after(function () {
206 return cleanServers()
207 })
c48e82b5
C
208 })
209
b36f41ca 210 describe('With trending strategy', function () {
4b5384f6 211 const strategy = 'trending'
c48e82b5 212
b36f41ca
C
213 before(function () {
214 this.timeout(120000)
215
4b5384f6 216 return runServers(strategy)
b36f41ca
C
217 })
218
219 it('Should have 1 webseed on the first video', function () {
4b5384f6 220 return check1WebSeed(strategy)
b36f41ca
C
221 })
222
3f6b6a56 223 it('Should enable redundancy on server 1', function () {
b36f41ca
C
224 return enableRedundancy()
225 })
226
3f6b6a56
C
227 it('Should have 2 webseed on the first video', function () {
228 this.timeout(40000)
229
4b5384f6 230 return check2Webseeds(strategy)
3f6b6a56
C
231 })
232
233 after(function () {
234 return cleanServers()
235 })
236 })
237
238 describe('With recently added strategy', function () {
4b5384f6 239 const strategy = 'recently-added'
3f6b6a56
C
240
241 before(function () {
242 this.timeout(120000)
243
4b5384f6 244 return runServers(strategy, { minViews: 3 })
3f6b6a56
C
245 })
246
247 it('Should have 1 webseed on the first video', function () {
4b5384f6 248 return check1WebSeed(strategy)
3f6b6a56
C
249 })
250
251 it('Should enable redundancy on server 1', function () {
252 return enableRedundancy()
253 })
254
255 it('Should still have 1 webseed on the first video', async function () {
256 this.timeout(40000)
257
258 await waitJobs(servers)
259 await wait(15000)
260 await waitJobs(servers)
261
4b5384f6 262 return check1WebSeed(strategy)
3f6b6a56
C
263 })
264
265 it('Should view 2 times the first video', async function () {
266 this.timeout(40000)
267
268 await viewVideo(servers[ 0 ].url, video1Server2UUID)
269 await viewVideo(servers[ 2 ].url, video1Server2UUID)
270
271 await wait(10000)
272 await waitJobs(servers)
273 })
274
275 it('Should have 2 webseed on the first video', function () {
b36f41ca
C
276 this.timeout(40000)
277
4b5384f6 278 return check2Webseeds(strategy)
b36f41ca
C
279 })
280
281 after(function () {
282 return cleanServers()
283 })
c48e82b5
C
284 })
285})