]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blob - server/tests/api/activitypub/cleaner.ts
Also retry when fetching master m3u8 playlist
[github/Chocobozzz/PeerTube.git] / server / tests / api / activitypub / cleaner.ts
1 /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
2
3 import { expect } from 'chai'
4 import { wait } from '@shared/core-utils'
5 import {
6 cleanupTests,
7 createMultipleServers,
8 doubleFollow,
9 PeerTubeServer,
10 setAccessTokensToServers,
11 waitJobs
12 } from '@shared/server-commands'
13
14 describe('Test AP cleaner', function () {
15 let servers: PeerTubeServer[] = []
16 let videoUUID1: string
17 let videoUUID2: string
18 let videoUUID3: string
19
20 let videoUUIDs: string[]
21
22 before(async function () {
23 this.timeout(120000)
24
25 const config = {
26 federation: {
27 videos: { cleanup_remote_interactions: true }
28 }
29 }
30 servers = await createMultipleServers(3, config)
31
32 // Get the access tokens
33 await setAccessTokensToServers(servers)
34
35 await Promise.all([
36 doubleFollow(servers[0], servers[1]),
37 doubleFollow(servers[1], servers[2]),
38 doubleFollow(servers[0], servers[2])
39 ])
40
41 // Update 1 local share, check 6 shares
42
43 // Create 1 comment per video
44 // Update 1 remote URL and 1 local URL on
45
46 videoUUID1 = (await servers[0].videos.quickUpload({ name: 'server 1' })).uuid
47 videoUUID2 = (await servers[1].videos.quickUpload({ name: 'server 2' })).uuid
48 videoUUID3 = (await servers[2].videos.quickUpload({ name: 'server 3' })).uuid
49
50 videoUUIDs = [ videoUUID1, videoUUID2, videoUUID3 ]
51
52 await waitJobs(servers)
53
54 for (const server of servers) {
55 for (const uuid of videoUUIDs) {
56 await server.videos.rate({ id: uuid, rating: 'like' })
57 await server.comments.createThread({ videoId: uuid, text: 'comment' })
58 }
59 }
60
61 await waitJobs(servers)
62 })
63
64 it('Should have the correct likes', async function () {
65 for (const server of servers) {
66 for (const uuid of videoUUIDs) {
67 const video = await server.videos.get({ id: uuid })
68
69 expect(video.likes).to.equal(3)
70 expect(video.dislikes).to.equal(0)
71 }
72 }
73 })
74
75 it('Should destroy server 3 internal likes and correctly clean them', async function () {
76 this.timeout(20000)
77
78 await servers[2].sql.deleteAll('accountVideoRate')
79 for (const uuid of videoUUIDs) {
80 await servers[2].sql.setVideoField(uuid, 'likes', '0')
81 }
82
83 await wait(5000)
84 await waitJobs(servers)
85
86 // Updated rates of my video
87 {
88 const video = await servers[0].videos.get({ id: videoUUID1 })
89 expect(video.likes).to.equal(2)
90 expect(video.dislikes).to.equal(0)
91 }
92
93 // Did not update rates of a remote video
94 {
95 const video = await servers[0].videos.get({ id: videoUUID2 })
96 expect(video.likes).to.equal(3)
97 expect(video.dislikes).to.equal(0)
98 }
99 })
100
101 it('Should update rates to dislikes', async function () {
102 this.timeout(20000)
103
104 for (const server of servers) {
105 for (const uuid of videoUUIDs) {
106 await server.videos.rate({ id: uuid, rating: 'dislike' })
107 }
108 }
109
110 await waitJobs(servers)
111
112 for (const server of servers) {
113 for (const uuid of videoUUIDs) {
114 const video = await server.videos.get({ id: uuid })
115 expect(video.likes).to.equal(0)
116 expect(video.dislikes).to.equal(3)
117 }
118 }
119 })
120
121 it('Should destroy server 3 internal dislikes and correctly clean them', async function () {
122 this.timeout(20000)
123
124 await servers[2].sql.deleteAll('accountVideoRate')
125
126 for (const uuid of videoUUIDs) {
127 await servers[2].sql.setVideoField(uuid, 'dislikes', '0')
128 }
129
130 await wait(5000)
131 await waitJobs(servers)
132
133 // Updated rates of my video
134 {
135 const video = await servers[0].videos.get({ id: videoUUID1 })
136 expect(video.likes).to.equal(0)
137 expect(video.dislikes).to.equal(2)
138 }
139
140 // Did not update rates of a remote video
141 {
142 const video = await servers[0].videos.get({ id: videoUUID2 })
143 expect(video.likes).to.equal(0)
144 expect(video.dislikes).to.equal(3)
145 }
146 })
147
148 it('Should destroy server 3 internal shares and correctly clean them', async function () {
149 this.timeout(20000)
150
151 const preCount = await servers[0].sql.getCount('videoShare')
152 expect(preCount).to.equal(6)
153
154 await servers[2].sql.deleteAll('videoShare')
155 await wait(5000)
156 await waitJobs(servers)
157
158 // Still 6 because we don't have remote shares on local videos
159 const postCount = await servers[0].sql.getCount('videoShare')
160 expect(postCount).to.equal(6)
161 })
162
163 it('Should destroy server 3 internal comments and correctly clean them', async function () {
164 this.timeout(20000)
165
166 {
167 const { total } = await servers[0].comments.listThreads({ videoId: videoUUID1 })
168 expect(total).to.equal(3)
169 }
170
171 await servers[2].sql.deleteAll('videoComment')
172
173 await wait(5000)
174 await waitJobs(servers)
175
176 {
177 const { total } = await servers[0].comments.listThreads({ videoId: videoUUID1 })
178 expect(total).to.equal(2)
179 }
180 })
181
182 it('Should correctly update rate URLs', async function () {
183 this.timeout(30000)
184
185 async function check (like: string, ofServerUrl: string, urlSuffix: string, remote: 'true' | 'false') {
186 const query = `SELECT "videoId", "accountVideoRate".url FROM "accountVideoRate" ` +
187 `INNER JOIN video ON "accountVideoRate"."videoId" = video.id AND remote IS ${remote} WHERE "accountVideoRate"."url" LIKE '${like}'`
188 const res = await servers[0].sql.selectQuery(query)
189
190 for (const rate of res) {
191 const matcher = new RegExp(`^${ofServerUrl}/accounts/root/dislikes/\\d+${urlSuffix}$`)
192 expect(rate.url).to.match(matcher)
193 }
194 }
195
196 async function checkLocal () {
197 const startsWith = 'http://' + servers[0].host + '%'
198 // On local videos
199 await check(startsWith, servers[0].url, '', 'false')
200 // On remote videos
201 await check(startsWith, servers[0].url, '', 'true')
202 }
203
204 async function checkRemote (suffix: string) {
205 const startsWith = 'http://' + servers[1].host + '%'
206 // On local videos
207 await check(startsWith, servers[1].url, suffix, 'false')
208 // On remote videos, we should not update URLs so no suffix
209 await check(startsWith, servers[1].url, '', 'true')
210 }
211
212 await checkLocal()
213 await checkRemote('')
214
215 {
216 const query = `UPDATE "accountVideoRate" SET url = url || 'stan'`
217 await servers[1].sql.updateQuery(query)
218
219 await wait(5000)
220 await waitJobs(servers)
221 }
222
223 await checkLocal()
224 await checkRemote('stan')
225 })
226
227 it('Should correctly update comment URLs', async function () {
228 this.timeout(30000)
229
230 async function check (like: string, ofServerUrl: string, urlSuffix: string, remote: 'true' | 'false') {
231 const query = `SELECT "videoId", "videoComment".url, uuid as "videoUUID" FROM "videoComment" ` +
232 `INNER JOIN video ON "videoComment"."videoId" = video.id AND remote IS ${remote} WHERE "videoComment"."url" LIKE '${like}'`
233
234 const res = await servers[0].sql.selectQuery(query)
235
236 for (const comment of res) {
237 const matcher = new RegExp(`${ofServerUrl}/videos/watch/${comment.videoUUID}/comments/\\d+${urlSuffix}`)
238 expect(comment.url).to.match(matcher)
239 }
240 }
241
242 async function checkLocal () {
243 const startsWith = 'http://' + servers[0].host + '%'
244 // On local videos
245 await check(startsWith, servers[0].url, '', 'false')
246 // On remote videos
247 await check(startsWith, servers[0].url, '', 'true')
248 }
249
250 async function checkRemote (suffix: string) {
251 const startsWith = 'http://' + servers[1].host + '%'
252 // On local videos
253 await check(startsWith, servers[1].url, suffix, 'false')
254 // On remote videos, we should not update URLs so no suffix
255 await check(startsWith, servers[1].url, '', 'true')
256 }
257
258 {
259 const query = `UPDATE "videoComment" SET url = url || 'kyle'`
260 await servers[1].sql.updateQuery(query)
261
262 await wait(5000)
263 await waitJobs(servers)
264 }
265
266 await checkLocal()
267 await checkRemote('kyle')
268 })
269
270 it('Should remove unavailable remote resources', async function () {
271 this.timeout(240000)
272
273 async function expectNotDeleted () {
274 {
275 const video = await servers[0].videos.get({ id: uuid })
276
277 expect(video.likes).to.equal(3)
278 expect(video.dislikes).to.equal(0)
279 }
280
281 {
282 const { total } = await servers[0].comments.listThreads({ videoId: uuid })
283 expect(total).to.equal(3)
284 }
285 }
286
287 async function expectDeleted () {
288 {
289 const video = await servers[0].videos.get({ id: uuid })
290
291 expect(video.likes).to.equal(2)
292 expect(video.dislikes).to.equal(0)
293 }
294
295 {
296 const { total } = await servers[0].comments.listThreads({ videoId: uuid })
297 expect(total).to.equal(2)
298 }
299 }
300
301 const uuid = (await servers[0].videos.quickUpload({ name: 'server 1 video 2' })).uuid
302
303 await waitJobs(servers)
304
305 for (const server of servers) {
306 await server.videos.rate({ id: uuid, rating: 'like' })
307 await server.comments.createThread({ videoId: uuid, text: 'comment' })
308 }
309
310 await waitJobs(servers)
311
312 await expectNotDeleted()
313
314 await servers[1].kill()
315
316 await wait(5000)
317 await expectNotDeleted()
318
319 let continueWhile = true
320
321 do {
322 try {
323 await expectDeleted()
324 continueWhile = false
325 } catch {
326 }
327 } while (continueWhile)
328 })
329
330 after(async function () {
331 await cleanupTests(servers)
332 })
333 })