]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blob - server/tests/api/multiple-pods.js
Add like/dislike system for videos
[github/Chocobozzz/PeerTube.git] / server / tests / api / multiple-pods.js
1 /* eslint-disable no-unused-expressions */
2
3 'use strict'
4
5 const chai = require('chai')
6 const each = require('async/each')
7 const eachSeries = require('async/eachSeries')
8 const expect = chai.expect
9 const parallel = require('async/parallel')
10 const series = require('async/series')
11 const WebTorrent = require('webtorrent')
12 const webtorrent = new WebTorrent()
13
14 const loginUtils = require('../utils/login')
15 const miscsUtils = require('../utils/miscs')
16 const podsUtils = require('../utils/pods')
17 const serversUtils = require('../utils/servers')
18 const videosUtils = require('../utils/videos')
19
20 describe('Test multiple pods', function () {
21 let servers = []
22 const toRemove = []
23
24 before(function (done) {
25 this.timeout(30000)
26
27 series([
28 // Run servers
29 function (next) {
30 serversUtils.flushAndRunMultipleServers(3, function (serversRun) {
31 servers = serversRun
32 next()
33 })
34 },
35 // Get the access tokens
36 function (next) {
37 each(servers, function (server, callbackEach) {
38 loginUtils.loginAndGetAccessToken(server, function (err, accessToken) {
39 if (err) return callbackEach(err)
40
41 server.accessToken = accessToken
42 callbackEach()
43 })
44 }, next)
45 },
46 // The second pod make friend with the third
47 function (next) {
48 const server = servers[1]
49 podsUtils.makeFriends(server.url, server.accessToken, next)
50 },
51 // Wait for the request between pods
52 function (next) {
53 setTimeout(next, 10000)
54 },
55 // Pod 1 make friends too
56 function (next) {
57 const server = servers[0]
58 podsUtils.makeFriends(server.url, server.accessToken, next)
59 }
60 ], done)
61 })
62
63 it('Should not have videos for all pods', function (done) {
64 each(servers, function (server, callback) {
65 videosUtils.getVideosList(server.url, function (err, res) {
66 if (err) throw err
67
68 const videos = res.body.data
69 expect(videos).to.be.an('array')
70 expect(videos.length).to.equal(0)
71
72 callback()
73 })
74 }, done)
75 })
76
77 describe('Should upload the video and propagate on each pod', function () {
78 it('Should upload the video on pod 1 and propagate on each pod', function (done) {
79 this.timeout(15000)
80
81 series([
82 function (next) {
83 const name = 'my super name for pod 1'
84 const description = 'my super description for pod 1'
85 const tags = [ 'tag1p1', 'tag2p1' ]
86 const file = 'video_short1.webm'
87 videosUtils.uploadVideo(servers[0].url, servers[0].accessToken, name, description, tags, file, next)
88 },
89 function (next) {
90 setTimeout(next, 11000)
91 }],
92 // All pods should have this video
93 function (err) {
94 if (err) throw err
95
96 each(servers, function (server, callback) {
97 let baseMagnet = null
98
99 videosUtils.getVideosList(server.url, function (err, res) {
100 if (err) throw err
101
102 const videos = res.body.data
103 expect(videos).to.be.an('array')
104 expect(videos.length).to.equal(1)
105 const video = videos[0]
106 expect(video.name).to.equal('my super name for pod 1')
107 expect(video.description).to.equal('my super description for pod 1')
108 expect(video.podHost).to.equal('localhost:9001')
109 expect(video.magnetUri).to.exist
110 expect(video.duration).to.equal(10)
111 expect(video.tags).to.deep.equal([ 'tag1p1', 'tag2p1' ])
112 expect(miscsUtils.dateIsValid(video.createdAt)).to.be.true
113 expect(miscsUtils.dateIsValid(video.updatedAt)).to.be.true
114 expect(video.author).to.equal('root')
115
116 if (server.url !== 'http://localhost:9001') {
117 expect(video.isLocal).to.be.false
118 } else {
119 expect(video.isLocal).to.be.true
120 }
121
122 // All pods should have the same magnet Uri
123 if (baseMagnet === null) {
124 baseMagnet = video.magnetUri
125 } else {
126 expect(video.magnetUri).to.equal.magnetUri
127 }
128
129 videosUtils.testVideoImage(server.url, 'video_short1.webm', video.thumbnailPath, function (err, test) {
130 if (err) throw err
131 expect(test).to.equal(true)
132
133 callback()
134 })
135 })
136 }, done)
137 }
138 )
139 })
140
141 it('Should upload the video on pod 2 and propagate on each pod', function (done) {
142 this.timeout(15000)
143
144 series([
145 function (next) {
146 const name = 'my super name for pod 2'
147 const description = 'my super description for pod 2'
148 const tags = [ 'tag1p2', 'tag2p2', 'tag3p2' ]
149 const file = 'video_short2.webm'
150 videosUtils.uploadVideo(servers[1].url, servers[1].accessToken, name, description, tags, file, next)
151 },
152 function (next) {
153 setTimeout(next, 11000)
154 }],
155 // All pods should have this video
156 function (err) {
157 if (err) throw err
158
159 each(servers, function (server, callback) {
160 let baseMagnet = null
161
162 videosUtils.getVideosList(server.url, function (err, res) {
163 if (err) throw err
164
165 const videos = res.body.data
166 expect(videos).to.be.an('array')
167 expect(videos.length).to.equal(2)
168 const video = videos[1]
169 expect(video.name).to.equal('my super name for pod 2')
170 expect(video.description).to.equal('my super description for pod 2')
171 expect(video.podHost).to.equal('localhost:9002')
172 expect(video.magnetUri).to.exist
173 expect(video.duration).to.equal(5)
174 expect(video.tags).to.deep.equal([ 'tag1p2', 'tag2p2', 'tag3p2' ])
175 expect(miscsUtils.dateIsValid(video.createdAt)).to.be.true
176 expect(miscsUtils.dateIsValid(video.updatedAt)).to.be.true
177 expect(video.author).to.equal('root')
178
179 if (server.url !== 'http://localhost:9002') {
180 expect(video.isLocal).to.be.false
181 } else {
182 expect(video.isLocal).to.be.true
183 }
184
185 // All pods should have the same magnet Uri
186 if (baseMagnet === null) {
187 baseMagnet = video.magnetUri
188 } else {
189 expect(video.magnetUri).to.equal.magnetUri
190 }
191
192 videosUtils.testVideoImage(server.url, 'video_short2.webm', video.thumbnailPath, function (err, test) {
193 if (err) throw err
194 expect(test).to.equal(true)
195
196 callback()
197 })
198 })
199 }, done)
200 }
201 )
202 })
203
204 it('Should upload two videos on pod 3 and propagate on each pod', function (done) {
205 this.timeout(30000)
206
207 series([
208 function (next) {
209 const name = 'my super name for pod 3'
210 const description = 'my super description for pod 3'
211 const tags = [ 'tag1p3' ]
212 const file = 'video_short3.webm'
213 videosUtils.uploadVideo(servers[2].url, servers[2].accessToken, name, description, tags, file, next)
214 },
215 function (next) {
216 const name = 'my super name for pod 3-2'
217 const description = 'my super description for pod 3-2'
218 const tags = [ 'tag2p3', 'tag3p3', 'tag4p3' ]
219 const file = 'video_short.webm'
220 videosUtils.uploadVideo(servers[2].url, servers[2].accessToken, name, description, tags, file, next)
221 },
222 function (next) {
223 setTimeout(next, 22000)
224 }],
225 function (err) {
226 if (err) throw err
227
228 let baseMagnet = null
229 // All pods should have this video
230 each(servers, function (server, callback) {
231 videosUtils.getVideosList(server.url, function (err, res) {
232 if (err) throw err
233
234 const videos = res.body.data
235 expect(videos).to.be.an('array')
236 expect(videos.length).to.equal(4)
237
238 // We not sure about the order of the two last uploads
239 let video1 = null
240 let video2 = null
241 if (videos[2].name === 'my super name for pod 3') {
242 video1 = videos[2]
243 video2 = videos[3]
244 } else {
245 video1 = videos[3]
246 video2 = videos[2]
247 }
248
249 expect(video1.name).to.equal('my super name for pod 3')
250 expect(video1.description).to.equal('my super description for pod 3')
251 expect(video1.podHost).to.equal('localhost:9003')
252 expect(video1.magnetUri).to.exist
253 expect(video1.duration).to.equal(5)
254 expect(video1.tags).to.deep.equal([ 'tag1p3' ])
255 expect(video1.author).to.equal('root')
256 expect(miscsUtils.dateIsValid(video1.createdAt)).to.be.true
257 expect(miscsUtils.dateIsValid(video1.updatedAt)).to.be.true
258
259 expect(video2.name).to.equal('my super name for pod 3-2')
260 expect(video2.description).to.equal('my super description for pod 3-2')
261 expect(video2.podHost).to.equal('localhost:9003')
262 expect(video2.magnetUri).to.exist
263 expect(video2.duration).to.equal(5)
264 expect(video2.tags).to.deep.equal([ 'tag2p3', 'tag3p3', 'tag4p3' ])
265 expect(video2.author).to.equal('root')
266 expect(miscsUtils.dateIsValid(video2.createdAt)).to.be.true
267 expect(miscsUtils.dateIsValid(video2.updatedAt)).to.be.true
268
269 if (server.url !== 'http://localhost:9003') {
270 expect(video1.isLocal).to.be.false
271 expect(video2.isLocal).to.be.false
272 } else {
273 expect(video1.isLocal).to.be.true
274 expect(video2.isLocal).to.be.true
275 }
276
277 // All pods should have the same magnet Uri
278 if (baseMagnet === null) {
279 baseMagnet = video2.magnetUri
280 } else {
281 expect(video2.magnetUri).to.equal.magnetUri
282 }
283
284 videosUtils.testVideoImage(server.url, 'video_short3.webm', video1.thumbnailPath, function (err, test) {
285 if (err) throw err
286 expect(test).to.equal(true)
287
288 videosUtils.testVideoImage(server.url, 'video_short.webm', video2.thumbnailPath, function (err, test) {
289 if (err) throw err
290 expect(test).to.equal(true)
291
292 callback()
293 })
294 })
295 })
296 }, done)
297 }
298 )
299 })
300 })
301
302 describe('Should seed the uploaded video', function () {
303 it('Should add the file 1 by asking pod 3', function (done) {
304 // Yes, this could be long
305 this.timeout(200000)
306
307 videosUtils.getVideosList(servers[2].url, function (err, res) {
308 if (err) throw err
309
310 const video = res.body.data[0]
311 toRemove.push(res.body.data[2])
312 toRemove.push(res.body.data[3])
313
314 webtorrent.add(video.magnetUri, function (torrent) {
315 expect(torrent.files).to.exist
316 expect(torrent.files.length).to.equal(1)
317 expect(torrent.files[0].path).to.exist.and.to.not.equal('')
318
319 done()
320 })
321 })
322 })
323
324 it('Should add the file 2 by asking pod 1', function (done) {
325 // Yes, this could be long
326 this.timeout(200000)
327
328 videosUtils.getVideosList(servers[0].url, function (err, res) {
329 if (err) throw err
330
331 const video = res.body.data[1]
332
333 webtorrent.add(video.magnetUri, function (torrent) {
334 expect(torrent.files).to.exist
335 expect(torrent.files.length).to.equal(1)
336 expect(torrent.files[0].path).to.exist.and.to.not.equal('')
337
338 done()
339 })
340 })
341 })
342
343 it('Should add the file 3 by asking pod 2', function (done) {
344 // Yes, this could be long
345 this.timeout(200000)
346
347 videosUtils.getVideosList(servers[1].url, function (err, res) {
348 if (err) throw err
349
350 const video = res.body.data[2]
351
352 webtorrent.add(video.magnetUri, function (torrent) {
353 expect(torrent.files).to.exist
354 expect(torrent.files.length).to.equal(1)
355 expect(torrent.files[0].path).to.exist.and.to.not.equal('')
356
357 done()
358 })
359 })
360 })
361
362 it('Should add the file 3-2 by asking pod 1', function (done) {
363 // Yes, this could be long
364 this.timeout(200000)
365
366 videosUtils.getVideosList(servers[0].url, function (err, res) {
367 if (err) throw err
368
369 const video = res.body.data[3]
370
371 webtorrent.add(video.magnetUri, function (torrent) {
372 expect(torrent.files).to.exist
373 expect(torrent.files.length).to.equal(1)
374 expect(torrent.files[0].path).to.exist.and.to.not.equal('')
375
376 done()
377 })
378 })
379 })
380 })
381
382 describe('Should update video views, likes and dislikes', function () {
383 let localVideosPod3 = []
384 let remoteVideosPod1 = []
385 let remoteVideosPod2 = []
386 let remoteVideosPod3 = []
387
388 before(function (done) {
389 parallel([
390 function (callback) {
391 videosUtils.getVideosList(servers[0].url, function (err, res) {
392 if (err) throw err
393
394 remoteVideosPod1 = res.body.data.filter(video => video.isLocal === false).map(video => video.id)
395
396 callback()
397 })
398 },
399
400 function (callback) {
401 videosUtils.getVideosList(servers[1].url, function (err, res) {
402 if (err) throw err
403
404 remoteVideosPod2 = res.body.data.filter(video => video.isLocal === false).map(video => video.id)
405
406 callback()
407 })
408 },
409
410 function (callback) {
411 videosUtils.getVideosList(servers[2].url, function (err, res) {
412 if (err) throw err
413
414 localVideosPod3 = res.body.data.filter(video => video.isLocal === true).map(video => video.id)
415 remoteVideosPod3 = res.body.data.filter(video => video.isLocal === false).map(video => video.id)
416
417 callback()
418 })
419 }
420 ], done)
421 })
422
423 it('Should view multiple videos on owned servers', function (done) {
424 this.timeout(30000)
425
426 parallel([
427 function (callback) {
428 videosUtils.getVideo(servers[2].url, localVideosPod3[0], callback)
429 },
430
431 function (callback) {
432 videosUtils.getVideo(servers[2].url, localVideosPod3[0], callback)
433 },
434
435 function (callback) {
436 videosUtils.getVideo(servers[2].url, localVideosPod3[0], callback)
437 },
438
439 function (callback) {
440 videosUtils.getVideo(servers[2].url, localVideosPod3[1], callback)
441 },
442
443 function (callback) {
444 setTimeout(callback, 22000)
445 }
446 ], function (err) {
447 if (err) throw err
448
449 eachSeries(servers, function (server, callback) {
450 videosUtils.getVideosList(server.url, function (err, res) {
451 if (err) throw err
452
453 const videos = res.body.data
454 expect(videos.find(video => video.views === 3)).to.exist
455 expect(videos.find(video => video.views === 1)).to.exist
456
457 callback()
458 })
459 }, done)
460 })
461 })
462
463 it('Should view multiple videos on each servers', function (done) {
464 this.timeout(30000)
465
466 parallel([
467 function (callback) {
468 videosUtils.getVideo(servers[0].url, remoteVideosPod1[0], callback)
469 },
470
471 function (callback) {
472 videosUtils.getVideo(servers[1].url, remoteVideosPod2[0], callback)
473 },
474
475 function (callback) {
476 videosUtils.getVideo(servers[1].url, remoteVideosPod2[0], callback)
477 },
478
479 function (callback) {
480 videosUtils.getVideo(servers[2].url, remoteVideosPod3[0], callback)
481 },
482
483 function (callback) {
484 videosUtils.getVideo(servers[2].url, remoteVideosPod3[1], callback)
485 },
486
487 function (callback) {
488 videosUtils.getVideo(servers[2].url, remoteVideosPod3[1], callback)
489 },
490
491 function (callback) {
492 videosUtils.getVideo(servers[2].url, remoteVideosPod3[1], callback)
493 },
494
495 function (callback) {
496 videosUtils.getVideo(servers[2].url, localVideosPod3[1], callback)
497 },
498
499 function (callback) {
500 videosUtils.getVideo(servers[2].url, localVideosPod3[1], callback)
501 },
502
503 function (callback) {
504 videosUtils.getVideo(servers[2].url, localVideosPod3[1], callback)
505 },
506
507 function (callback) {
508 setTimeout(callback, 22000)
509 }
510 ], function (err) {
511 if (err) throw err
512
513 let baseVideos = null
514 eachSeries(servers, function (server, callback) {
515 videosUtils.getVideosList(server.url, function (err, res) {
516 if (err) throw err
517
518 const videos = res.body.data
519
520 // Initialize base videos for future comparisons
521 if (baseVideos === null) {
522 baseVideos = videos
523 return callback()
524 }
525
526 baseVideos.forEach(baseVideo => {
527 const sameVideo = videos.find(video => video.name === baseVideo.name)
528 expect(baseVideo.views).to.equal(sameVideo.views)
529 })
530
531 callback()
532 })
533 }, done)
534 })
535 })
536
537 it('Should like and dislikes videos on different services', function (done) {
538 this.timeout(30000)
539
540 parallel([
541 function (callback) {
542 videosUtils.rateVideo(servers[0].url, servers[0].accessToken, remoteVideosPod1[0], 'like', callback)
543 },
544
545 function (callback) {
546 videosUtils.rateVideo(servers[0].url, servers[0].accessToken, remoteVideosPod1[0], 'dislike', callback)
547 },
548
549 function (callback) {
550 videosUtils.rateVideo(servers[0].url, servers[0].accessToken, remoteVideosPod1[0], 'like', callback)
551 },
552
553 function (callback) {
554 videosUtils.rateVideo(servers[2].url, servers[2].accessToken, localVideosPod3[1], 'like', callback)
555 },
556
557 function (callback) {
558 videosUtils.rateVideo(servers[2].url, servers[2].accessToken, localVideosPod3[1], 'dislike', callback)
559 },
560
561 function (callback) {
562 videosUtils.rateVideo(servers[2].url, servers[2].accessToken, remoteVideosPod3[1], 'dislike', callback)
563 },
564
565 function (callback) {
566 videosUtils.rateVideo(servers[2].url, servers[2].accessToken, remoteVideosPod3[0], 'like', callback)
567 },
568
569 function (callback) {
570 setTimeout(callback, 22000)
571 }
572 ], function (err) {
573 if (err) throw err
574
575 let baseVideos = null
576 eachSeries(servers, function (server, callback) {
577 videosUtils.getVideosList(server.url, function (err, res) {
578 if (err) throw err
579
580 const videos = res.body.data
581
582 // Initialize base videos for future comparisons
583 if (baseVideos === null) {
584 baseVideos = videos
585 return callback()
586 }
587
588 baseVideos.forEach(baseVideo => {
589 const sameVideo = videos.find(video => video.name === baseVideo.name)
590 expect(baseVideo.likes).to.equal(sameVideo.likes)
591 expect(baseVideo.dislikes).to.equal(sameVideo.dislikes)
592 })
593
594 callback()
595 })
596 }, done)
597 })
598 })
599 })
600
601 describe('Should manipulate these videos', function () {
602 it('Should update the video 3 by asking pod 3', function (done) {
603 this.timeout(15000)
604
605 const name = 'my super video updated'
606 const description = 'my super description updated'
607 const tags = [ 'tagup1', 'tagup2' ]
608
609 videosUtils.updateVideo(servers[2].url, servers[2].accessToken, toRemove[0].id, name, description, tags, function (err) {
610 if (err) throw err
611
612 setTimeout(done, 11000)
613 })
614 })
615
616 it('Should have the video 3 updated on each pod', function (done) {
617 this.timeout(200000)
618
619 each(servers, function (server, callback) {
620 // Avoid "duplicate torrent" errors
621 const webtorrent = new WebTorrent()
622
623 videosUtils.getVideosList(server.url, function (err, res) {
624 if (err) throw err
625
626 const videos = res.body.data
627 const videoUpdated = videos.find(function (video) {
628 return video.name === 'my super video updated'
629 })
630
631 expect(!!videoUpdated).to.be.true
632 expect(videoUpdated.description).to.equal('my super description updated')
633 expect(videoUpdated.tags).to.deep.equal([ 'tagup1', 'tagup2' ])
634 expect(miscsUtils.dateIsValid(videoUpdated.updatedAt, 20000)).to.be.true
635
636 videosUtils.testVideoImage(server.url, 'video_short3.webm', videoUpdated.thumbnailPath, function (err, test) {
637 if (err) throw err
638 expect(test).to.equal(true)
639
640 webtorrent.add(videoUpdated.magnetUri, function (torrent) {
641 expect(torrent.files).to.exist
642 expect(torrent.files.length).to.equal(1)
643 expect(torrent.files[0].path).to.exist.and.to.not.equal('')
644
645 callback()
646 })
647 })
648 })
649 }, done)
650 })
651
652 it('Should remove the videos 3 and 3-2 by asking pod 3', function (done) {
653 this.timeout(15000)
654
655 series([
656 function (next) {
657 videosUtils.removeVideo(servers[2].url, servers[2].accessToken, toRemove[0].id, next)
658 },
659 function (next) {
660 videosUtils.removeVideo(servers[2].url, servers[2].accessToken, toRemove[1].id, next)
661 }],
662 function (err) {
663 if (err) throw err
664 setTimeout(done, 11000)
665 }
666 )
667 })
668
669 it('Should have videos 1 and 3 on each pod', function (done) {
670 each(servers, function (server, callback) {
671 videosUtils.getVideosList(server.url, function (err, res) {
672 if (err) throw err
673
674 const videos = res.body.data
675 expect(videos).to.be.an('array')
676 expect(videos.length).to.equal(2)
677 expect(videos[0].name).not.to.equal(videos[1].name)
678 expect(videos[0].name).not.to.equal(toRemove[0].name)
679 expect(videos[1].name).not.to.equal(toRemove[0].name)
680 expect(videos[0].name).not.to.equal(toRemove[1].name)
681 expect(videos[1].name).not.to.equal(toRemove[1].name)
682
683 callback()
684 })
685 }, done)
686 })
687 })
688
689 after(function (done) {
690 servers.forEach(function (server) {
691 process.kill(-server.app.pid)
692 })
693
694 // Keep the logs if the test failed
695 if (this.ok) {
696 serversUtils.flushTests(done)
697 } else {
698 done()
699 }
700 })
701 })