3 const each = require('async/each')
4 const isEqual = require('lodash/isEqual')
5 const differenceWith = require('lodash/differenceWith')
6 const program = require('commander')
7 const series = require('async/series')
9 process.env.NODE_ENV = 'test'
10 const constants = require('../../initializers/constants')
12 const loginUtils = require('../utils/login')
13 const podsUtils = require('../utils/pods')
14 const serversUtils = require('../utils/servers')
15 const videosUtils = require('../utils/videos')
16 const requestStatsUtils = require('../utils/requests-stats')
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')
32 const createWeight = program.create !== undefined ? parseInt(program.create) : 5
33 const removeWeight = program.remove !== undefined ? parseInt(program.remove) : 4
34 const updateWeight = program.update !== undefined ? parseInt(program.update) : 4
35 const viewWeight = program.view !== undefined ? parseInt(program.view) : 4
36 const likeWeight = program.like !== undefined ? parseInt(program.like) : 4
37 const dislikeWeight = program.dislike !== undefined ? parseInt(program.dislike) : 4
38 const flushAtExit = program.flush || false
39 const actionInterval = program.action !== undefined ? parseInt(program.action) : 500
40 const integrityInterval = program.integrity !== undefined ? parseInt(program.integrity) : 60000
41 const displayDiffOnFail = program.integrity || false
43 const numberOfPods = 6
45 console.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)
47 console.log('Program will flush data on exit.')
49 console.log('Program will not flush data on exit.')
51 if (displayDiffOnFail) {
52 console.log('Program will display diff on failure.')
54 console.log('Program will not display diff on failure')
56 console.log('Interval in ms for each action: %d.', actionInterval)
57 console.log('Interval in ms for each integrity check: %d.', integrityInterval)
59 console.log('Run servers...')
60 runServers(numberOfPods, function (err, servers) {
63 process.on('exit', function () {
64 exitServers(servers, flushAtExit)
66 process.on('SIGINT', goodbye)
67 process.on('SIGTERM', goodbye)
69 console.log('Servers runned')
70 initializeRequestsPerServer(servers)
74 setInterval(function () {
75 if (checking === true) return
77 const rand = getRandomInt(0, createWeight + updateWeight + removeWeight + viewWeight + likeWeight + dislikeWeight)
79 const numServer = getRandomNumServer(servers)
80 servers[numServer].requestsNumber++
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)
93 dislike(servers, numServer)
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
101 console.log('Checking integrity...')
104 const waitingInterval = setInterval(function () {
105 isThereAwaitingRequests(servers, function (res) {
107 console.log('A server has awaiting requests, waiting...')
111 checkIntegrity(servers, function () {
112 initializeRequestsPerServer(servers)
114 clearInterval(waitingInterval)
117 }, constants.REQUESTS_INTERVAL)
118 }, integrityInterval)
121 // ----------------------------------------------------------------------------
123 function initializeRequestsPerServer (servers) {
124 servers.forEach(function (server) {
125 server.requestsNumber = 0
129 function getRandomInt (min, max) {
130 return Math.floor(Math.random() * (max - min)) + min
133 function getRandomNumServer (servers) {
134 return getRandomInt(0, servers.length)
137 function runServers (numberOfPods, callback) {
143 serversUtils.flushAndRunMultipleServers(numberOfPods, function (serversRun) {
148 // Get the access tokens
150 each(servers, function (server, callbackEach) {
151 loginUtils.loginAndGetAccessToken(server, function (err, accessToken) {
152 if (err) return callbackEach(err)
154 server.accessToken = accessToken
160 const server = servers[1]
161 podsUtils.makeFriends(server.url, server.accessToken, next)
164 const server = servers[0]
165 podsUtils.makeFriends(server.url, server.accessToken, next)
168 setTimeout(next, 1000)
171 const server = servers[3]
172 podsUtils.makeFriends(server.url, server.accessToken, next)
175 const server = servers[5]
176 podsUtils.makeFriends(server.url, server.accessToken, next)
179 const server = servers[4]
180 podsUtils.makeFriends(server.url, server.accessToken, next)
183 setTimeout(next, 1000)
186 return callback(err, servers)
190 function exitServers (servers, callback) {
191 if (!callback) callback = function () {}
193 servers.forEach(function (server) {
194 if (server.app) process.kill(-server.app.pid)
197 if (flushAtExit) serversUtils.flushTests(callback)
200 function upload (servers, numServer, callback) {
201 if (!callback) callback = function () {}
203 console.log('Uploading video to server ' + numServer)
205 const videoAttributes = {
206 name: Date.now() + ' name',
211 description: Date.now() + ' description',
212 tags: [ Date.now().toString().substring(0, 5) + 't1', Date.now().toString().substring(0, 5) + 't2' ],
213 fixture: 'video_short1.webm'
215 videosUtils.uploadVideo(servers[numServer].url, servers[numServer].accessToken, videoAttributes, callback)
218 function update (servers, numServer, callback) {
219 if (!callback) callback = function () {}
221 videosUtils.getVideosList(servers[numServer].url, function (err, res) {
224 const videos = res.body.data.filter(function (video) { return video.isLocal })
225 if (videos.length === 0) return callback()
227 const toUpdate = videos[getRandomInt(0, videos.length)].id
229 name: Date.now() + ' name',
230 description: Date.now() + ' description',
231 tags: [ Date.now().toString().substring(0, 5) + 't1', Date.now().toString().substring(0, 5) + 't2' ]
234 console.log('Updating video of server ' + numServer)
236 videosUtils.updateVideo(servers[numServer].url, servers[numServer].accessToken, toUpdate, attributes, callback)
240 function remove (servers, numServer, callback) {
241 if (!callback) callback = function () {}
243 videosUtils.getVideosList(servers[numServer].url, function (err, res) {
246 const videos = res.body.data
247 if (videos.length === 0) return callback()
249 const toRemove = videos[getRandomInt(0, videos.length)].id
251 console.log('Removing video from server ' + numServer)
252 videosUtils.removeVideo(servers[numServer].url, servers[numServer].accessToken, toRemove, callback)
256 function view (servers, numServer, callback) {
257 if (!callback) callback = function () {}
259 videosUtils.getVideosList(servers[numServer].url, function (err, res) {
262 const videos = res.body.data
263 if (videos.length === 0) return callback()
265 const toView = videos[getRandomInt(0, videos.length)].id
267 console.log('Viewing video from server ' + numServer)
268 videosUtils.getVideo(servers[numServer].url, toView, callback)
272 function like (servers, numServer, callback) {
273 rate(servers, numServer, 'like', callback)
276 function dislike (servers, numServer, callback) {
277 rate(servers, numServer, 'dislike', callback)
280 function rate (servers, numServer, rating, callback) {
281 if (!callback) callback = function () {}
283 videosUtils.getVideosList(servers[numServer].url, function (err, res) {
286 const videos = res.body.data
287 if (videos.length === 0) return callback()
289 const toRate = videos[getRandomInt(0, videos.length)].id
291 console.log('Rating (%s) video from server %d', rating, numServer)
292 videosUtils.getVideo(servers[numServer].url, toRate, callback)
296 function checkIntegrity (servers, callback) {
298 each(servers, function (server, callback) {
299 videosUtils.getAllVideosListBy(server.url, function (err, res) {
301 const serverVideos = res.body.data
302 for (const serverVideo of serverVideos) {
303 delete serverVideo.id
304 delete serverVideo.isLocal
305 delete serverVideo.thumbnailPath
306 delete serverVideo.updatedAt
307 delete serverVideo.views
310 videos.push(serverVideos)
316 for (const video of videos) {
317 if (!isEqual(video, videos[0])) {
318 console.error('Integrity not ok with server %d!', i + 1)
320 if (displayDiffOnFail) {
321 console.log(differenceWith(videos[0], video, isEqual))
322 console.log(differenceWith(video, videos[0], isEqual))
331 console.log('Integrity ok.')
336 function goodbye () {
337 return process.exit(-1)
340 function isThereAwaitingRequests (servers, callback) {
341 let noRequests = true
343 // Check is each server has awaiting requestq
344 each(servers, function (server, callbackEach) {
345 requestStatsUtils.getRequestsStats(server, server.accessToken, function (err, res) {
348 const stats = res.body
351 stats.requestScheduler.totalRequests !== 0 ||
352 stats.requestVideoEventScheduler.totalRequests !== 0 ||
353 stats.requestVideoQaduScheduler.totalRequests !== 0
363 return callback(noRequests === false)