]>
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, | |
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' |
20 | import { waitJobs } from '../../utils/server/jobs' | |
21 | import * as magnetUtil from 'magnet-uri' | |
22 | import { updateRedundancy } from '../../utils/server/redundancy' | |
23 | import { ActorFollow } from '../../../../shared/models/actors' | |
24 | import { readdir } from 'fs-extra' | |
25 | import { join } from 'path' | |
b36f41ca | 26 | import { VideoRedundancyStrategy } from '../../../../shared/models/redundancy' |
4b5384f6 C |
27 | import { getStats } from '../../utils/server/stats' |
28 | import { ServerStats } from '../../../../shared/models/server/server-stats.model' | |
c48e82b5 C |
29 | |
30 | const expect = chai.expect | |
31 | ||
b36f41ca C |
32 | let servers: ServerInfo[] = [] |
33 | let video1Server2UUID: string | |
34 | let video2Server2UUID: string | |
35 | ||
c48e82b5 C |
36 | function 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 | 45 | async 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 | 88 | async 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 | ||
117 | async 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 | 132 | async 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 |
176 | async function cleanServers () { |
177 | killallServers(servers) | |
178 | } | |
c48e82b5 | 179 | |
b36f41ca | 180 | describe('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 | }) |