1 /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
4 import * as chai from 'chai'
5 import { wait } from '@shared/core-utils'
11 setAccessTokensToServers,
13 } from '@shared/server-commands'
15 const expect = chai.expect
17 describe('Test AP cleaner', function () {
18 let servers: PeerTubeServer[] = []
19 let videoUUID1: string
20 let videoUUID2: string
21 let videoUUID3: string
23 let videoUUIDs: string[]
25 before(async function () {
30 videos: { cleanup_remote_interactions: true }
33 servers = await createMultipleServers(3, config)
35 // Get the access tokens
36 await setAccessTokensToServers(servers)
39 doubleFollow(servers[0], servers[1]),
40 doubleFollow(servers[1], servers[2]),
41 doubleFollow(servers[0], servers[2])
44 // Update 1 local share, check 6 shares
46 // Create 1 comment per video
47 // Update 1 remote URL and 1 local URL on
49 videoUUID1 = (await servers[0].videos.quickUpload({ name: 'server 1' })).uuid
50 videoUUID2 = (await servers[1].videos.quickUpload({ name: 'server 2' })).uuid
51 videoUUID3 = (await servers[2].videos.quickUpload({ name: 'server 3' })).uuid
53 videoUUIDs = [ videoUUID1, videoUUID2, videoUUID3 ]
55 await waitJobs(servers)
57 for (const server of servers) {
58 for (const uuid of videoUUIDs) {
59 await server.videos.rate({ id: uuid, rating: 'like' })
60 await server.comments.createThread({ videoId: uuid, text: 'comment' })
64 await waitJobs(servers)
67 it('Should have the correct likes', async function () {
68 for (const server of servers) {
69 for (const uuid of videoUUIDs) {
70 const video = await server.videos.get({ id: uuid })
72 expect(video.likes).to.equal(3)
73 expect(video.dislikes).to.equal(0)
78 it('Should destroy server 3 internal likes and correctly clean them', async function () {
81 await servers[2].sql.deleteAll('accountVideoRate')
82 for (const uuid of videoUUIDs) {
83 await servers[2].sql.setVideoField(uuid, 'likes', '0')
87 await waitJobs(servers)
89 // Updated rates of my video
91 const video = await servers[0].videos.get({ id: videoUUID1 })
92 expect(video.likes).to.equal(2)
93 expect(video.dislikes).to.equal(0)
96 // Did not update rates of a remote video
98 const video = await servers[0].videos.get({ id: videoUUID2 })
99 expect(video.likes).to.equal(3)
100 expect(video.dislikes).to.equal(0)
104 it('Should update rates to dislikes', async function () {
107 for (const server of servers) {
108 for (const uuid of videoUUIDs) {
109 await server.videos.rate({ id: uuid, rating: 'dislike' })
113 await waitJobs(servers)
115 for (const server of servers) {
116 for (const uuid of videoUUIDs) {
117 const video = await server.videos.get({ id: uuid })
118 expect(video.likes).to.equal(0)
119 expect(video.dislikes).to.equal(3)
124 it('Should destroy server 3 internal dislikes and correctly clean them', async function () {
127 await servers[2].sql.deleteAll('accountVideoRate')
129 for (const uuid of videoUUIDs) {
130 await servers[2].sql.setVideoField(uuid, 'dislikes', '0')
134 await waitJobs(servers)
136 // Updated rates of my video
138 const video = await servers[0].videos.get({ id: videoUUID1 })
139 expect(video.likes).to.equal(0)
140 expect(video.dislikes).to.equal(2)
143 // Did not update rates of a remote video
145 const video = await servers[0].videos.get({ id: videoUUID2 })
146 expect(video.likes).to.equal(0)
147 expect(video.dislikes).to.equal(3)
151 it('Should destroy server 3 internal shares and correctly clean them', async function () {
154 const preCount = await servers[0].sql.getCount('videoShare')
155 expect(preCount).to.equal(6)
157 await servers[2].sql.deleteAll('videoShare')
159 await waitJobs(servers)
161 // Still 6 because we don't have remote shares on local videos
162 const postCount = await servers[0].sql.getCount('videoShare')
163 expect(postCount).to.equal(6)
166 it('Should destroy server 3 internal comments and correctly clean them', async function () {
170 const { total } = await servers[0].comments.listThreads({ videoId: videoUUID1 })
171 expect(total).to.equal(3)
174 await servers[2].sql.deleteAll('videoComment')
177 await waitJobs(servers)
180 const { total } = await servers[0].comments.listThreads({ videoId: videoUUID1 })
181 expect(total).to.equal(2)
185 it('Should correctly update rate URLs', async function () {
188 async function check (like: string, ofServerUrl: string, urlSuffix: string, remote: 'true' | 'false') {
189 const query = `SELECT "videoId", "accountVideoRate".url FROM "accountVideoRate" ` +
190 `INNER JOIN video ON "accountVideoRate"."videoId" = video.id AND remote IS ${remote} WHERE "accountVideoRate"."url" LIKE '${like}'`
191 const res = await servers[0].sql.selectQuery(query)
193 for (const rate of res) {
194 const matcher = new RegExp(`^${ofServerUrl}/accounts/root/dislikes/\\d+${urlSuffix}$`)
195 expect(rate.url).to.match(matcher)
199 async function checkLocal () {
200 const startsWith = 'http://' + servers[0].host + '%'
202 await check(startsWith, servers[0].url, '', 'false')
204 await check(startsWith, servers[0].url, '', 'true')
207 async function checkRemote (suffix: string) {
208 const startsWith = 'http://' + servers[1].host + '%'
210 await check(startsWith, servers[1].url, suffix, 'false')
211 // On remote videos, we should not update URLs so no suffix
212 await check(startsWith, servers[1].url, '', 'true')
216 await checkRemote('')
219 const query = `UPDATE "accountVideoRate" SET url = url || 'stan'`
220 await servers[1].sql.updateQuery(query)
223 await waitJobs(servers)
227 await checkRemote('stan')
230 it('Should correctly update comment URLs', async function () {
233 async function check (like: string, ofServerUrl: string, urlSuffix: string, remote: 'true' | 'false') {
234 const query = `SELECT "videoId", "videoComment".url, uuid as "videoUUID" FROM "videoComment" ` +
235 `INNER JOIN video ON "videoComment"."videoId" = video.id AND remote IS ${remote} WHERE "videoComment"."url" LIKE '${like}'`
237 const res = await servers[0].sql.selectQuery(query)
239 for (const comment of res) {
240 const matcher = new RegExp(`${ofServerUrl}/videos/watch/${comment.videoUUID}/comments/\\d+${urlSuffix}`)
241 expect(comment.url).to.match(matcher)
245 async function checkLocal () {
246 const startsWith = 'http://' + servers[0].host + '%'
248 await check(startsWith, servers[0].url, '', 'false')
250 await check(startsWith, servers[0].url, '', 'true')
253 async function checkRemote (suffix: string) {
254 const startsWith = 'http://' + servers[1].host + '%'
256 await check(startsWith, servers[1].url, suffix, 'false')
257 // On remote videos, we should not update URLs so no suffix
258 await check(startsWith, servers[1].url, '', 'true')
262 const query = `UPDATE "videoComment" SET url = url || 'kyle'`
263 await servers[1].sql.updateQuery(query)
266 await waitJobs(servers)
270 await checkRemote('kyle')
273 it('Should remove unavailable remote resources', async function () {
276 async function expectNotDeleted () {
278 const video = await servers[0].videos.get({ id: uuid })
280 expect(video.likes).to.equal(3)
281 expect(video.dislikes).to.equal(0)
285 const { total } = await servers[0].comments.listThreads({ videoId: uuid })
286 expect(total).to.equal(3)
290 async function expectDeleted () {
292 const video = await servers[0].videos.get({ id: uuid })
294 expect(video.likes).to.equal(2)
295 expect(video.dislikes).to.equal(0)
299 const { total } = await servers[0].comments.listThreads({ videoId: uuid })
300 expect(total).to.equal(2)
304 const uuid = (await servers[0].videos.quickUpload({ name: 'server 1 video 2' })).uuid
306 await waitJobs(servers)
308 for (const server of servers) {
309 await server.videos.rate({ id: uuid, rating: 'like' })
310 await server.comments.createThread({ videoId: uuid, text: 'comment' })
313 await waitJobs(servers)
315 await expectNotDeleted()
317 await servers[1].kill()
320 await expectNotDeleted()
322 let continueWhile = true
326 await expectDeleted()
327 continueWhile = false
330 } while (continueWhile)
333 after(async function () {
334 await cleanupTests(servers)