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