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