]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame - server/tests/api/server/handle-down.ts
Fix CI using 127.0.0.1 for tests
[github/Chocobozzz/PeerTube.git] / server / tests / api / server / handle-down.ts
CommitLineData
a1587156 1/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
2ccaeeb3 2
86347717 3import { expect } from 'chai'
c55e3d72
C
4import { completeVideoCheck } from '@server/tests/shared'
5import { wait } from '@shared/core-utils'
6import { HttpStatusCode, JobState, VideoCreateResult, VideoPrivacy } from '@shared/models'
2ccaeeb3 7import {
7c3b7976 8 cleanupTests,
12edc149 9 CommentsCommand,
254d3579 10 createMultipleServers,
94831479 11 killallServers,
254d3579 12 PeerTubeServer,
94831479 13 setAccessTokensToServers,
c3d29f69 14 waitJobs
bf54587a 15} from '@shared/server-commands'
2ccaeeb3 16
2ccaeeb3 17describe('Test handle downs', function () {
254d3579 18 let servers: PeerTubeServer[] = []
7bc29171
C
19 let threadIdServer1: number
20 let threadIdServer2: number
21 let commentIdServer1: number
22 let commentIdServer2: number
d23dd9fb
C
23 let missedVideo1: VideoCreateResult
24 let missedVideo2: VideoCreateResult
25 let unlistedVideo: VideoCreateResult
2ccaeeb3 26
d4a8e7a6 27 const videoIdsServer1: string[] = []
6b9c966f 28
2ccaeeb3
C
29 const videoAttributes = {
30 name: 'my super name for server 1',
31 category: 5,
32 licence: 4,
9d3ef9fe 33 language: 'ja',
2ccaeeb3 34 nsfw: true,
7bc29171 35 privacy: VideoPrivacy.PUBLIC,
2ccaeeb3 36 description: 'my super description for server 1',
2422c46b 37 support: 'my super support text for server 1',
2ccaeeb3
C
38 tags: [ 'tag1p1', 'tag2p1' ],
39 fixture: 'video_short1.webm'
40 }
41
6c5065a0 42 const unlistedVideoAttributes = { ...videoAttributes, privacy: VideoPrivacy.UNLISTED }
7bc29171 43
48f07b4a
C
44 let checkAttributes: any
45 let unlistedCheckAttributes: any
7bc29171 46
12edc149
C
47 let commentCommands: CommentsCommand[]
48
2ccaeeb3 49 before(async function () {
10a72a7e 50 this.timeout(120000)
2ccaeeb3 51
254d3579 52 servers = await createMultipleServers(3)
89d241a7 53 commentCommands = servers.map(s => s.comments)
2ccaeeb3 54
48f07b4a
C
55 checkAttributes = {
56 name: 'my super name for server 1',
57 category: 5,
58 licence: 4,
59 language: 'ja',
60 nsfw: true,
61 description: 'my super description for server 1',
62 support: 'my super support text for server 1',
63 account: {
64 name: 'root',
2732eeff 65 host: servers[0].host
48f07b4a
C
66 },
67 isLocal: false,
68 duration: 10,
69 tags: [ 'tag1p1', 'tag2p1' ],
70 privacy: VideoPrivacy.PUBLIC,
71 commentsEnabled: true,
72 downloadEnabled: true,
73 channel: {
74 name: 'root_channel',
75 displayName: 'Main root channel',
76 description: '',
77 isLocal: false
78 },
79 fixture: 'video_short1.webm',
80 files: [
81 {
82 resolution: 720,
83 size: 572456
84 }
85 ]
86 }
6c5065a0 87 unlistedCheckAttributes = { ...checkAttributes, privacy: VideoPrivacy.UNLISTED }
48f07b4a 88
2ccaeeb3
C
89 // Get the access tokens
90 await setAccessTokensToServers(servers)
91 })
92
93 it('Should remove followers that are often down', async function () {
2284f202 94 this.timeout(240000)
2ccaeeb3 95
cc6373e6 96 // Server 2 and 3 follow server 1
4d029ef8
C
97 await servers[1].follows.follow({ hosts: [ servers[0].url ] })
98 await servers[2].follows.follow({ hosts: [ servers[0].url ] })
2ccaeeb3 99
3cd0734f 100 await waitJobs(servers)
2ccaeeb3 101
cc6373e6 102 // Upload a video to server 1
89d241a7 103 await servers[0].videos.upload({ attributes: videoAttributes })
2ccaeeb3 104
3cd0734f 105 await waitJobs(servers)
2ccaeeb3 106
cc6373e6 107 // And check all servers have this video
2ccaeeb3 108 for (const server of servers) {
89d241a7 109 const { data } = await server.videos.list()
d23dd9fb
C
110 expect(data).to.be.an('array')
111 expect(data).to.have.lengthOf(1)
2ccaeeb3
C
112 }
113
cc6373e6 114 // Kill server 2
9293139f 115 await killallServers([ servers[1] ])
2ccaeeb3
C
116
117 // Remove server 2 follower
118 for (let i = 0; i < 10; i++) {
89d241a7 119 await servers[0].videos.upload({ attributes: videoAttributes })
7bc29171
C
120 }
121
f67d1dca 122 await waitJobs([ servers[0], servers[2] ])
6502c3d4 123
cc6373e6 124 // Kill server 3
9293139f 125 await killallServers([ servers[2] ])
cc6373e6 126
89d241a7 127 missedVideo1 = await servers[0].videos.upload({ attributes: videoAttributes })
cc6373e6 128
89d241a7 129 missedVideo2 = await servers[0].videos.upload({ attributes: videoAttributes })
cc6373e6
C
130
131 // Unlisted video
89d241a7 132 unlistedVideo = await servers[0].videos.upload({ attributes: unlistedVideoAttributes })
6502c3d4 133
7bc29171
C
134 // Add comments to video 2
135 {
136 const text = 'thread 1'
12edc149 137 let comment = await commentCommands[0].createThread({ videoId: missedVideo2.uuid, text })
7bc29171
C
138 threadIdServer1 = comment.id
139
12edc149 140 comment = await commentCommands[0].addReply({ videoId: missedVideo2.uuid, toCommentId: comment.id, text: 'comment 1-1' })
7bc29171 141
12edc149
C
142 const created = await commentCommands[0].addReply({ videoId: missedVideo2.uuid, toCommentId: comment.id, text: 'comment 1-2' })
143 commentIdServer1 = created.id
2ccaeeb3
C
144 }
145
3cd0734f
C
146 await waitJobs(servers[0])
147 // Wait scheduler
9a4a9b6c 148 await wait(11000)
2ccaeeb3 149
cc6373e6 150 // Only server 3 is still a follower of server 1
89d241a7 151 const body = await servers[0].follows.getFollowers({ start: 0, count: 2, sort: 'createdAt' })
c3d29f69
C
152 expect(body.data).to.be.an('array')
153 expect(body.data).to.have.lengthOf(1)
2732eeff 154 expect(body.data[0].follower.host).to.equal(servers[2].host)
2ccaeeb3
C
155 })
156
157 it('Should not have pending/processing jobs anymore', async function () {
94831479 158 const states: JobState[] = [ 'waiting', 'active' ]
2ccaeeb3 159
94a5ff8a 160 for (const state of states) {
851675c5 161 const body = await servers[0].jobs.list({
ba2684ce 162 state,
1061c73f
C
163 start: 0,
164 count: 50,
165 sort: '-createdAt'
166 })
9c6327f8 167 expect(body.data).to.have.length(0)
2ccaeeb3
C
168 }
169 })
170
cc6373e6 171 it('Should re-follow server 1', async function () {
87c0f718 172 this.timeout(70000)
7bc29171 173
254d3579
C
174 await servers[1].run()
175 await servers[2].run()
cc6373e6 176
89d241a7 177 await servers[1].follows.unfollow({ target: servers[0] })
cc6373e6 178 await waitJobs(servers)
2ccaeeb3 179
4d029ef8 180 await servers[1].follows.follow({ hosts: [ servers[0].url ] })
2ccaeeb3 181
3cd0734f 182 await waitJobs(servers)
2ccaeeb3 183
89d241a7 184 const body = await servers[0].follows.getFollowers({ start: 0, count: 2, sort: 'createdAt' })
c3d29f69
C
185 expect(body.data).to.be.an('array')
186 expect(body.data).to.have.lengthOf(2)
2ccaeeb3
C
187 })
188
8cf99873 189 it('Should send an update to server 3, and automatically fetch the video', async function () {
7bc29171 190 this.timeout(15000)
2ccaeeb3 191
d23dd9fb 192 {
89d241a7 193 const { data } = await servers[2].videos.list()
d23dd9fb
C
194 expect(data).to.be.an('array')
195 expect(data).to.have.lengthOf(11)
196 }
cc6373e6 197
89d241a7
C
198 await servers[0].videos.update({ id: missedVideo1.uuid })
199 await servers[0].videos.update({ id: unlistedVideo.uuid })
2ccaeeb3 200
3cd0734f 201 await waitJobs(servers)
2ccaeeb3 202
d23dd9fb 203 {
89d241a7 204 const { data } = await servers[2].videos.list()
d23dd9fb
C
205 expect(data).to.be.an('array')
206 // 1 video is unlisted
207 expect(data).to.have.lengthOf(12)
208 }
7bc29171 209
cc6373e6 210 // Check unlisted video
89d241a7 211 const video = await servers[2].videos.get({ id: unlistedVideo.uuid })
d23dd9fb 212 await completeVideoCheck(servers[2], video, unlistedCheckAttributes)
7bc29171
C
213 })
214
cc6373e6 215 it('Should send comments on a video to server 3, and automatically fetch the video', async function () {
7bc29171 216 this.timeout(25000)
2ccaeeb3 217
12edc149 218 await commentCommands[0].addReply({ videoId: missedVideo2.uuid, toCommentId: commentIdServer1, text: 'comment 1-3' })
7bc29171 219
3cd0734f 220 await waitJobs(servers)
7bc29171 221
89d241a7 222 await servers[2].videos.get({ id: missedVideo2.uuid })
7bc29171 223
7bc29171 224 {
89d241a7 225 const { data } = await servers[2].comments.listThreads({ videoId: missedVideo2.uuid })
12edc149
C
226 expect(data).to.be.an('array')
227 expect(data).to.have.lengthOf(1)
7bc29171 228
12edc149 229 threadIdServer2 = data[0].id
7bc29171 230
89d241a7 231 const tree = await servers[2].comments.getThread({ videoId: missedVideo2.uuid, threadId: threadIdServer2 })
7bc29171
C
232 expect(tree.comment.text).equal('thread 1')
233 expect(tree.children).to.have.lengthOf(1)
234
235 const firstChild = tree.children[0]
236 expect(firstChild.comment.text).to.equal('comment 1-1')
237 expect(firstChild.children).to.have.lengthOf(1)
238
239 const childOfFirstChild = firstChild.children[0]
240 expect(childOfFirstChild.comment.text).to.equal('comment 1-2')
241 expect(childOfFirstChild.children).to.have.lengthOf(1)
242
243 const childOfChildFirstChild = childOfFirstChild.children[0]
244 expect(childOfChildFirstChild.comment.text).to.equal('comment 1-3')
245 expect(childOfChildFirstChild.children).to.have.lengthOf(0)
246
247 commentIdServer2 = childOfChildFirstChild.comment.id
248 }
249 })
250
251 it('Should correctly reply to the comment', async function () {
252 this.timeout(15000)
253
89d241a7 254 await servers[2].comments.addReply({ videoId: missedVideo2.uuid, toCommentId: commentIdServer2, text: 'comment 1-4' })
7bc29171 255
3cd0734f 256 await waitJobs(servers)
7bc29171 257
12edc149 258 const tree = await commentCommands[0].getThread({ videoId: missedVideo2.uuid, threadId: threadIdServer1 })
7bc29171 259
12edc149
C
260 expect(tree.comment.text).equal('thread 1')
261 expect(tree.children).to.have.lengthOf(1)
7bc29171 262
12edc149
C
263 const firstChild = tree.children[0]
264 expect(firstChild.comment.text).to.equal('comment 1-1')
265 expect(firstChild.children).to.have.lengthOf(1)
7bc29171 266
12edc149
C
267 const childOfFirstChild = firstChild.children[0]
268 expect(childOfFirstChild.comment.text).to.equal('comment 1-2')
269 expect(childOfFirstChild.children).to.have.lengthOf(1)
7bc29171 270
12edc149
C
271 const childOfChildFirstChild = childOfFirstChild.children[0]
272 expect(childOfChildFirstChild.comment.text).to.equal('comment 1-3')
273 expect(childOfChildFirstChild.children).to.have.lengthOf(1)
7bc29171 274
12edc149
C
275 const childOfChildOfChildOfFirstChild = childOfChildFirstChild.children[0]
276 expect(childOfChildOfChildOfFirstChild.comment.text).to.equal('comment 1-4')
277 expect(childOfChildOfChildOfFirstChild.children).to.have.lengthOf(0)
2ccaeeb3
C
278 })
279
6b9c966f
C
280 it('Should upload many videos on server 1', async function () {
281 this.timeout(120000)
282
283 for (let i = 0; i < 10; i++) {
89d241a7 284 const uuid = (await servers[0].videos.quickUpload({ name: 'video ' + i })).uuid
6b9c966f
C
285 videoIdsServer1.push(uuid)
286 }
287
288 await waitJobs(servers)
289
290 for (const id of videoIdsServer1) {
89d241a7 291 await servers[1].videos.get({ id })
6b9c966f
C
292 }
293
294 await waitJobs(servers)
89d241a7 295 await servers[1].sql.setActorFollowScores(20)
6b9c966f
C
296
297 // Wait video expiration
298 await wait(11000)
299
300 // Refresh video -> score + 10 = 30
89d241a7 301 await servers[1].videos.get({ id: videoIdsServer1[0] })
6b9c966f
C
302
303 await waitJobs(servers)
304 })
305
306 it('Should remove followings that are down', async function () {
307 this.timeout(120000)
308
9293139f 309 await killallServers([ servers[0] ])
6b9c966f
C
310
311 // Wait video expiration
312 await wait(11000)
313
a3c997b3
C
314 for (let i = 0; i < 5; i++) {
315 try {
89d241a7 316 await servers[1].videos.get({ id: videoIdsServer1[i] })
a3c997b3
C
317 await waitJobs([ servers[1] ])
318 await wait(1500)
319 } catch {}
6b9c966f
C
320 }
321
322 for (const id of videoIdsServer1) {
89d241a7 323 await servers[1].videos.get({ id, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
6b9c966f
C
324 }
325 })
326
7c3b7976
C
327 after(async function () {
328 await cleanupTests(servers)
2ccaeeb3
C
329 })
330})