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