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