aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/tests/real-world
diff options
context:
space:
mode:
Diffstat (limited to 'server/tests/real-world')
-rw-r--r--server/tests/real-world/real-world.js367
-rw-r--r--server/tests/real-world/real-world.ts327
2 files changed, 327 insertions, 367 deletions
diff --git a/server/tests/real-world/real-world.js b/server/tests/real-world/real-world.js
deleted file mode 100644
index ea189c5f2..000000000
--- a/server/tests/real-world/real-world.js
+++ /dev/null
@@ -1,367 +0,0 @@
1'use strict'
2
3const each = require('async/each')
4const isEqual = require('lodash/isEqual')
5const differenceWith = require('lodash/differenceWith')
6const program = require('commander')
7const series = require('async/series')
8
9process.env.NODE_ENV = 'test'
10const constants = require('../../initializers/constants')
11
12const loginUtils = require('../utils/login')
13const podsUtils = require('../utils/pods')
14const serversUtils = require('../utils/servers')
15const videosUtils = require('../utils/videos')
16const requestSchedulersUtils = require('../utils/request-schedulers')
17
18program
19 .option('-c, --create [weight]', 'Weight for creating videos')
20 .option('-r, --remove [weight]', 'Weight for removing videos')
21 .option('-u, --update [weight]', 'Weight for updating videos')
22 .option('-v, --view [weight]', 'Weight for viewing videos')
23 .option('-l, --like [weight]', 'Weight for liking videos')
24 .option('-s, --dislike [weight]', 'Weight for disliking videos')
25 .option('-p, --pods [n]', 'Number of pods to run (3 or 6)', /^3|6$/, 3)
26 .option('-a, --action [interval]', 'Interval in ms for an action')
27 .option('-i, --integrity [interval]', 'Interval in ms for an integrity check')
28 .option('-f, --flush', 'Flush datas on exit')
29 .option('-d, --difference', 'Display difference if integrity is not okay')
30 .parse(process.argv)
31
32const createWeight = program.create !== undefined ? parseInt(program.create) : 5
33const removeWeight = program.remove !== undefined ? parseInt(program.remove) : 4
34const updateWeight = program.update !== undefined ? parseInt(program.update) : 4
35const viewWeight = program.view !== undefined ? parseInt(program.view) : 4
36const likeWeight = program.like !== undefined ? parseInt(program.like) : 4
37const dislikeWeight = program.dislike !== undefined ? parseInt(program.dislike) : 4
38const flushAtExit = program.flush || false
39const actionInterval = program.action !== undefined ? parseInt(program.action) : 500
40const integrityInterval = program.integrity !== undefined ? parseInt(program.integrity) : 60000
41const displayDiffOnFail = program.integrity || false
42
43const numberOfPods = 6
44
45console.log('Create weight: %d, update weight: %d, remove weight: %d, view weight: %d, like weight: %d, dislike weight: %d.', createWeight, updateWeight, removeWeight, viewWeight, likeWeight, dislikeWeight)
46if (flushAtExit) {
47 console.log('Program will flush data on exit.')
48} else {
49 console.log('Program will not flush data on exit.')
50}
51if (displayDiffOnFail) {
52 console.log('Program will display diff on failure.')
53} else {
54 console.log('Program will not display diff on failure')
55}
56console.log('Interval in ms for each action: %d.', actionInterval)
57console.log('Interval in ms for each integrity check: %d.', integrityInterval)
58
59console.log('Run servers...')
60runServers(numberOfPods, function (err, servers) {
61 if (err) throw err
62
63 process.on('exit', function () {
64 exitServers(servers, flushAtExit)
65 })
66 process.on('SIGINT', goodbye)
67 process.on('SIGTERM', goodbye)
68
69 console.log('Servers runned')
70 initializeRequestsPerServer(servers)
71
72 let checking = false
73
74 setInterval(function () {
75 if (checking === true) return
76
77 const rand = getRandomInt(0, createWeight + updateWeight + removeWeight + viewWeight + likeWeight + dislikeWeight)
78
79 const numServer = getRandomNumServer(servers)
80 servers[numServer].requestsNumber++
81
82 if (rand < createWeight) {
83 upload(servers, numServer)
84 } else if (rand < createWeight + updateWeight) {
85 update(servers, numServer)
86 } else if (rand < createWeight + updateWeight + removeWeight) {
87 remove(servers, numServer)
88 } else if (rand < createWeight + updateWeight + removeWeight + viewWeight) {
89 view(servers, numServer)
90 } else if (rand < createWeight + updateWeight + removeWeight + viewWeight + likeWeight) {
91 like(servers, numServer)
92 } else {
93 dislike(servers, numServer)
94 }
95 }, actionInterval)
96
97 // The function will check the consistency between servers (should have the same videos with same attributes...)
98 setInterval(function () {
99 if (checking === true) return
100
101 console.log('Checking integrity...')
102 checking = true
103
104 const waitingInterval = setInterval(function () {
105 isThereAwaitingRequests(servers, function (err, res) {
106 if (err) throw err
107
108 if (res === true) {
109 console.log('A server has awaiting requests, waiting...')
110 return
111 }
112
113 checkIntegrity(servers, function () {
114 initializeRequestsPerServer(servers)
115 checking = false
116 clearInterval(waitingInterval)
117 })
118 })
119 }, constants.REQUESTS_INTERVAL)
120 }, integrityInterval)
121})
122
123// ----------------------------------------------------------------------------
124
125function initializeRequestsPerServer (servers) {
126 servers.forEach(function (server) {
127 server.requestsNumber = 0
128 })
129}
130
131function getRandomInt (min, max) {
132 return Math.floor(Math.random() * (max - min)) + min
133}
134
135function getRandomNumServer (servers) {
136 return getRandomInt(0, servers.length)
137}
138
139function runServers (numberOfPods, callback) {
140 let servers = null
141
142 series([
143 // Run servers
144 function (next) {
145 serversUtils.flushAndRunMultipleServers(numberOfPods, function (serversRun) {
146 servers = serversRun
147 next()
148 })
149 },
150 // Get the access tokens
151 function (next) {
152 each(servers, function (server, callbackEach) {
153 loginUtils.loginAndGetAccessToken(server, function (err, accessToken) {
154 if (err) return callbackEach(err)
155
156 server.accessToken = accessToken
157 callbackEach()
158 })
159 }, next)
160 },
161 function (next) {
162 const server = servers[1]
163 podsUtils.makeFriends(server.url, server.accessToken, next)
164 },
165 function (next) {
166 const server = servers[0]
167 podsUtils.makeFriends(server.url, server.accessToken, next)
168 },
169 function (next) {
170 setTimeout(next, 1000)
171 },
172 function (next) {
173 const server = servers[3]
174 podsUtils.makeFriends(server.url, server.accessToken, next)
175 },
176 function (next) {
177 const server = servers[5]
178 podsUtils.makeFriends(server.url, server.accessToken, next)
179 },
180 function (next) {
181 const server = servers[4]
182 podsUtils.makeFriends(server.url, server.accessToken, next)
183 },
184 function (next) {
185 setTimeout(next, 1000)
186 }
187 ], function (err) {
188 return callback(err, servers)
189 })
190}
191
192function exitServers (servers, callback) {
193 if (!callback) callback = function () {}
194
195 servers.forEach(function (server) {
196 if (server.app) process.kill(-server.app.pid)
197 })
198
199 if (flushAtExit) serversUtils.flushTests(callback)
200}
201
202function upload (servers, numServer, callback) {
203 if (!callback) callback = function () {}
204
205 console.log('Uploading video to server ' + numServer)
206
207 const videoAttributes = {
208 name: Date.now() + ' name',
209 category: 4,
210 nsfw: false,
211 licence: 2,
212 language: 1,
213 description: Date.now() + ' description',
214 tags: [ Date.now().toString().substring(0, 5) + 't1', Date.now().toString().substring(0, 5) + 't2' ],
215 fixture: 'video_short1.webm'
216 }
217 videosUtils.uploadVideo(servers[numServer].url, servers[numServer].accessToken, videoAttributes, callback)
218}
219
220function update (servers, numServer, callback) {
221 if (!callback) callback = function () {}
222
223 videosUtils.getVideosList(servers[numServer].url, function (err, res) {
224 if (err) throw err
225
226 const videos = res.body.data.filter(function (video) { return video.isLocal })
227 if (videos.length === 0) return callback()
228
229 const toUpdate = videos[getRandomInt(0, videos.length)].id
230 const attributes = {
231 name: Date.now() + ' name',
232 description: Date.now() + ' description',
233 tags: [ Date.now().toString().substring(0, 5) + 't1', Date.now().toString().substring(0, 5) + 't2' ]
234 }
235
236 console.log('Updating video of server ' + numServer)
237
238 videosUtils.updateVideo(servers[numServer].url, servers[numServer].accessToken, toUpdate, attributes, callback)
239 })
240}
241
242function remove (servers, numServer, callback) {
243 if (!callback) callback = function () {}
244
245 videosUtils.getVideosList(servers[numServer].url, function (err, res) {
246 if (err) throw err
247
248 const videos = res.body.data
249 if (videos.length === 0) return callback()
250
251 const toRemove = videos[getRandomInt(0, videos.length)].id
252
253 console.log('Removing video from server ' + numServer)
254 videosUtils.removeVideo(servers[numServer].url, servers[numServer].accessToken, toRemove, callback)
255 })
256}
257
258function view (servers, numServer, callback) {
259 if (!callback) callback = function () {}
260
261 videosUtils.getVideosList(servers[numServer].url, function (err, res) {
262 if (err) throw err
263
264 const videos = res.body.data
265 if (videos.length === 0) return callback()
266
267 const toView = videos[getRandomInt(0, videos.length)].id
268
269 console.log('Viewing video from server ' + numServer)
270 videosUtils.getVideo(servers[numServer].url, toView, callback)
271 })
272}
273
274function like (servers, numServer, callback) {
275 rate(servers, numServer, 'like', callback)
276}
277
278function dislike (servers, numServer, callback) {
279 rate(servers, numServer, 'dislike', callback)
280}
281
282function rate (servers, numServer, rating, callback) {
283 if (!callback) callback = function () {}
284
285 videosUtils.getVideosList(servers[numServer].url, function (err, res) {
286 if (err) throw err
287
288 const videos = res.body.data
289 if (videos.length === 0) return callback()
290
291 const toRate = videos[getRandomInt(0, videos.length)].id
292
293 console.log('Rating (%s) video from server %d', rating, numServer)
294 videosUtils.getVideo(servers[numServer].url, toRate, callback)
295 })
296}
297
298function checkIntegrity (servers, callback) {
299 const videos = []
300 each(servers, function (server, callback) {
301 videosUtils.getAllVideosListBy(server.url, function (err, res) {
302 if (err) throw err
303 const serverVideos = res.body.data
304 for (const serverVideo of serverVideos) {
305 delete serverVideo.id
306 delete serverVideo.isLocal
307 delete serverVideo.thumbnailPath
308 delete serverVideo.updatedAt
309 delete serverVideo.views
310 }
311
312 videos.push(serverVideos)
313 callback()
314 })
315 }, function () {
316 let i = 0
317
318 for (const video of videos) {
319 if (!isEqual(video, videos[0])) {
320 console.error('Integrity not ok with server %d!', i + 1)
321
322 if (displayDiffOnFail) {
323 console.log(differenceWith(videos[0], video, isEqual))
324 console.log(differenceWith(video, videos[0], isEqual))
325 }
326
327 process.exit(-1)
328 }
329
330 i++
331 }
332
333 console.log('Integrity ok.')
334 return callback()
335 })
336}
337
338function goodbye () {
339 return process.exit(-1)
340}
341
342function isThereAwaitingRequests (servers, callback) {
343 let noRequests = true
344
345 // Check is each server has awaiting requestq
346 each(servers, function (server, callbackEach) {
347 requestSchedulersUtils.getRequestsStats(server, server.accessToken, function (err, res) {
348 if (err) throw err
349
350 const stats = res.body
351
352 if (
353 stats.requestScheduler.totalRequests !== 0 ||
354 stats.requestVideoEventScheduler.totalRequests !== 0 ||
355 stats.requestVideoQaduScheduler.totalRequests !== 0
356 ) {
357 noRequests = false
358 }
359
360 callbackEach()
361 })
362 }, function (err) {
363 if (err) throw err
364
365 return callback(null, noRequests === false)
366 })
367}
diff --git a/server/tests/real-world/real-world.ts b/server/tests/real-world/real-world.ts
new file mode 100644
index 000000000..a200bd02d
--- /dev/null
+++ b/server/tests/real-world/real-world.ts
@@ -0,0 +1,327 @@
1import * as program from 'commander'
2import { isEqual, differenceWith } from 'lodash'
3
4// /!\ Before imports /!\
5process.env.NODE_ENV = 'test'
6
7import { REQUESTS_INTERVAL } from '../../initializers/constants'
8import { Video, VideoRateType } from '../../../shared'
9import {
10 ServerInfo as DefaultServerInfo,
11 flushAndRunMultipleServers,
12 setAccessTokensToServers,
13 makeFriends,
14 wait,
15 killallServers,
16 flushTests,
17 uploadVideo,
18 getVideosList,
19 updateVideo,
20 removeVideo,
21 getVideo,
22 getAllVideosListBy,
23 getRequestsStats
24} from '../utils'
25
26interface ServerInfo extends DefaultServerInfo {
27 requestsNumber: number
28}
29
30program
31 .option('-c, --create [weight]', 'Weight for creating videos')
32 .option('-r, --remove [weight]', 'Weight for removing videos')
33 .option('-u, --update [weight]', 'Weight for updating videos')
34 .option('-v, --view [weight]', 'Weight for viewing videos')
35 .option('-l, --like [weight]', 'Weight for liking videos')
36 .option('-s, --dislike [weight]', 'Weight for disliking videos')
37 .option('-p, --pods [n]', 'Number of pods to run (3 or 6)', /^3|6$/, 3)
38 .option('-i, --interval-action [interval]', 'Interval in ms for an action')
39 .option('-I, --interval-integrity [interval]', 'Interval in ms for an integrity check')
40 .option('-f, --flush', 'Flush datas on exit')
41 .option('-d, --difference', 'Display difference if integrity is not okay')
42 .parse(process.argv)
43
44const createWeight = program['create'] !== undefined ? parseInt(program['create'], 10) : 5
45const removeWeight = program['remove'] !== undefined ? parseInt(program['remove'], 10) : 4
46const updateWeight = program['update'] !== undefined ? parseInt(program['update'], 10) : 4
47const viewWeight = program['view'] !== undefined ? parseInt(program['view'], 10) : 4
48const likeWeight = program['like'] !== undefined ? parseInt(program['like'], 10) : 4
49const dislikeWeight = program['dislike'] !== undefined ? parseInt(program['dislike'], 10) : 4
50const flushAtExit = program['flush'] || false
51const actionInterval = program['intervalAction'] !== undefined ? parseInt(program['intervalAction'], 10) : 500
52const integrityInterval = program['intervalIntegrity'] !== undefined ? parseInt(program['intervalIntegrity'], 10) : 60000
53const displayDiffOnFail = program['difference'] || false
54
55const numberOfPods = 6
56
57console.log(
58 'Create weight: %d, update weight: %d, remove weight: %d, view weight: %d, like weight: %d, dislike weight: %d.',
59 createWeight, updateWeight, removeWeight, viewWeight, likeWeight, dislikeWeight
60)
61
62if (flushAtExit) {
63 console.log('Program will flush data on exit.')
64} else {
65 console.log('Program will not flush data on exit.')
66}
67if (displayDiffOnFail) {
68 console.log('Program will display diff on failure.')
69} else {
70 console.log('Program will not display diff on failure')
71}
72console.log('Interval in ms for each action: %d.', actionInterval)
73console.log('Interval in ms for each integrity check: %d.', integrityInterval)
74
75console.log('Run servers...')
76
77start()
78
79// ----------------------------------------------------------------------------
80
81async function start () {
82 const servers = await runServers(numberOfPods)
83
84 process.on('exit', async () => await exitServers(servers, flushAtExit))
85 process.on('SIGINT', goodbye)
86 process.on('SIGTERM', goodbye)
87
88 console.log('Servers runned')
89 initializeRequestsPerServer(servers)
90
91 let checking = false
92
93 setInterval(async () => {
94 if (checking === true) return
95
96 const rand = getRandomInt(0, createWeight + updateWeight + removeWeight + viewWeight + likeWeight + dislikeWeight)
97
98 const numServer = getRandomNumServer(servers)
99 servers[numServer].requestsNumber++
100
101 if (rand < createWeight) {
102 await upload(servers, numServer)
103 } else if (rand < createWeight + updateWeight) {
104 await update(servers, numServer)
105 } else if (rand < createWeight + updateWeight + removeWeight) {
106 await remove(servers, numServer)
107 } else if (rand < createWeight + updateWeight + removeWeight + viewWeight) {
108 await view(servers, numServer)
109 } else if (rand < createWeight + updateWeight + removeWeight + viewWeight + likeWeight) {
110 await like(servers, numServer)
111 } else {
112 await dislike(servers, numServer)
113 }
114 }, actionInterval)
115
116 // The function will check the consistency between servers (should have the same videos with same attributes...)
117 setInterval(function () {
118 if (checking === true) return
119
120 console.log('Checking integrity...')
121 checking = true
122
123 const waitingInterval = setInterval(async () => {
124 const awaitingRequests = await isThereAwaitingRequests(servers)
125 if (awaitingRequests === true) {
126 console.log('A server has awaiting requests, waiting...')
127 return
128 }
129
130 await checkIntegrity(servers)
131
132 initializeRequestsPerServer(servers)
133 checking = false
134 clearInterval(waitingInterval)
135 }, REQUESTS_INTERVAL)
136 }, integrityInterval)
137}
138
139function initializeRequestsPerServer (servers: ServerInfo[]) {
140 servers.forEach(server => server.requestsNumber = 0)
141}
142
143function getRandomInt (min, max) {
144 return Math.floor(Math.random() * (max - min)) + min
145}
146
147function getRandomNumServer (servers) {
148 return getRandomInt(0, servers.length)
149}
150
151async function runServers (numberOfPods: number) {
152 let servers = null
153
154 // Run servers
155 servers = await flushAndRunMultipleServers(numberOfPods)
156
157 // Get the access tokens
158 await setAccessTokensToServers(servers)
159
160 await makeFriends(servers[1].url, servers[1].accessToken)
161 await makeFriends(servers[0].url, servers[0].accessToken)
162 await wait(1000)
163
164 await makeFriends(servers[3].url, servers[3].accessToken)
165 await makeFriends(servers[5].url, servers[5].accessToken)
166 await makeFriends(servers[4].url, servers[4].accessToken)
167
168 await wait(1000)
169
170 return servers
171}
172
173async function exitServers (servers: ServerInfo[], flushAtExit: boolean) {
174 killallServers(servers)
175
176 if (flushAtExit) await flushTests()
177}
178
179function upload (servers: ServerInfo[], numServer: number) {
180 console.log('Uploading video to server ' + numServer)
181
182 const videoAttributes = {
183 name: Date.now() + ' name',
184 category: 4,
185 nsfw: false,
186 licence: 2,
187 language: 1,
188 description: Date.now() + ' description',
189 tags: [ Date.now().toString().substring(0, 5) + 't1', Date.now().toString().substring(0, 5) + 't2' ],
190 fixture: 'video_short1.webm'
191 }
192 return uploadVideo(servers[numServer].url, servers[numServer].accessToken, videoAttributes)
193}
194
195async function update (servers: ServerInfo[], numServer: number) {
196 const res = await getVideosList(servers[numServer].url)
197
198 const videos = res.body.data.filter(video => video.isLocal === true)
199 if (videos.length === 0) return undefined
200
201 const toUpdate = videos[getRandomInt(0, videos.length)].id
202 const attributes = {
203 name: Date.now() + ' name',
204 description: Date.now() + ' description',
205 tags: [ Date.now().toString().substring(0, 5) + 't1', Date.now().toString().substring(0, 5) + 't2' ]
206 }
207
208 console.log('Updating video of server ' + numServer)
209
210 return updateVideo(servers[numServer].url, servers[numServer].accessToken, toUpdate, attributes)
211}
212
213async function remove (servers: ServerInfo[], numServer: number) {
214 const res = await getVideosList(servers[numServer].url)
215 const videos = res.body.data
216 if (videos.length === 0) return undefined
217
218 const toRemove = videos[getRandomInt(0, videos.length)].id
219
220 console.log('Removing video from server ' + numServer)
221 return removeVideo(servers[numServer].url, servers[numServer].accessToken, toRemove)
222}
223
224async function view (servers: ServerInfo[], numServer: number) {
225 const res = await getVideosList(servers[numServer].url)
226
227 const videos = res.body.data
228 if (videos.length === 0) return undefined
229
230 const toView = videos[getRandomInt(0, videos.length)].id
231
232 console.log('Viewing video from server ' + numServer)
233 return getVideo(servers[numServer].url, toView)
234}
235
236function like (servers: ServerInfo[], numServer: number) {
237 return rate(servers, numServer, 'like')
238}
239
240function dislike (servers: ServerInfo[], numServer: number) {
241 return rate(servers, numServer, 'dislike')
242}
243
244async function rate (servers: ServerInfo[], numServer: number, rating: VideoRateType) {
245 const res = await getVideosList(servers[numServer].url)
246
247 const videos = res.body.data
248 if (videos.length === 0) return undefined
249
250 const toRate = videos[getRandomInt(0, videos.length)].id
251
252 console.log('Rating (%s) video from server %d', rating, numServer)
253 return getVideo(servers[numServer].url, toRate)
254}
255
256async function checkIntegrity (servers: ServerInfo[]) {
257 const videos: Video[][] = []
258 const tasks: Promise<any>[] = []
259
260 // Fetch all videos and remove some fields that can differ between pods
261 for (const server of servers) {
262 const p = getAllVideosListBy(server.url).then(res => {
263 const serverVideos = res.body.data
264 for (const serverVideo of serverVideos) {
265 delete serverVideo.id
266 delete serverVideo.isLocal
267 delete serverVideo.thumbnailPath
268 delete serverVideo.updatedAt
269 delete serverVideo.views
270 }
271
272 videos.push(serverVideos)
273 })
274
275 tasks.push(p)
276 }
277
278 await Promise.all(tasks)
279
280 let i = 0
281 for (const video of videos) {
282 if (!isEqual(video, videos[0])) {
283 console.error('Integrity not ok with server %d!', i + 1)
284
285 if (displayDiffOnFail) {
286 console.log(differenceWith(videos[0], video, isEqual))
287 console.log(differenceWith(video, videos[0], isEqual))
288 }
289
290 process.exit(-1)
291 }
292
293 i++
294 }
295
296 console.log('Integrity ok.')
297}
298
299function goodbye () {
300 return process.exit(-1)
301}
302
303async function isThereAwaitingRequests (servers: ServerInfo[]) {
304 const tasks: Promise<any>[] = []
305 let awaitingRequests = false
306
307 // Check if each server has awaiting request
308 for (const server of servers) {
309 const p = getRequestsStats(server).then(res => {
310 const stats = res.body
311
312 if (
313 stats.requestScheduler.totalRequests !== 0 ||
314 stats.requestVideoEventScheduler.totalRequests !== 0 ||
315 stats.requestVideoQaduScheduler.totalRequests !== 0
316 ) {
317 awaitingRequests = true
318 }
319 })
320
321 tasks.push(p)
322 }
323
324 await Promise.all(tasks)
325
326 return awaitingRequests
327}