1 /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
3 import { expect } from 'chai'
4 import { SQLCommand } from '@server/tests/shared'
5 import { wait } from '@shared/core-utils'
11 setAccessTokensToServers,
13 } from '@shared/server-commands'
15 describe('Test AP cleaner', function () {
16 let servers: PeerTubeServer[] = []
17 const sqlCommands: SQLCommand[] = []
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' })
63 sqlCommands.push(new SQLCommand(server))
66 await waitJobs(servers)
69 it('Should have the correct likes', async function () {
70 for (const server of servers) {
71 for (const uuid of videoUUIDs) {
72 const video = await server.videos.get({ id: uuid })
74 expect(video.likes).to.equal(3)
75 expect(video.dislikes).to.equal(0)
80 it('Should destroy server 3 internal likes and correctly clean them', async function () {
83 await sqlCommands[2].deleteAll('accountVideoRate')
84 for (const uuid of videoUUIDs) {
85 await sqlCommands[2].setVideoField(uuid, 'likes', '0')
89 await waitJobs(servers)
91 // Updated rates of my video
93 const video = await servers[0].videos.get({ id: videoUUID1 })
94 expect(video.likes).to.equal(2)
95 expect(video.dislikes).to.equal(0)
98 // Did not update rates of a remote video
100 const video = await servers[0].videos.get({ id: videoUUID2 })
101 expect(video.likes).to.equal(3)
102 expect(video.dislikes).to.equal(0)
106 it('Should update rates to dislikes', async function () {
109 for (const server of servers) {
110 for (const uuid of videoUUIDs) {
111 await server.videos.rate({ id: uuid, rating: 'dislike' })
115 await waitJobs(servers)
117 for (const server of servers) {
118 for (const uuid of videoUUIDs) {
119 const video = await server.videos.get({ id: uuid })
120 expect(video.likes).to.equal(0)
121 expect(video.dislikes).to.equal(3)
126 it('Should destroy server 3 internal dislikes and correctly clean them', async function () {
129 await sqlCommands[2].deleteAll('accountVideoRate')
131 for (const uuid of videoUUIDs) {
132 await sqlCommands[2].setVideoField(uuid, 'dislikes', '0')
136 await waitJobs(servers)
138 // Updated rates of my video
140 const video = await servers[0].videos.get({ id: videoUUID1 })
141 expect(video.likes).to.equal(0)
142 expect(video.dislikes).to.equal(2)
145 // Did not update rates of a remote video
147 const video = await servers[0].videos.get({ id: videoUUID2 })
148 expect(video.likes).to.equal(0)
149 expect(video.dislikes).to.equal(3)
153 it('Should destroy server 3 internal shares and correctly clean them', async function () {
156 const preCount = await sqlCommands[0].getVideoShareCount()
157 expect(preCount).to.equal(6)
159 await sqlCommands[2].deleteAll('videoShare')
161 await waitJobs(servers)
163 // Still 6 because we don't have remote shares on local videos
164 const postCount = await sqlCommands[0].getVideoShareCount()
165 expect(postCount).to.equal(6)
168 it('Should destroy server 3 internal comments and correctly clean them', async function () {
172 const { total } = await servers[0].comments.listThreads({ videoId: videoUUID1 })
173 expect(total).to.equal(3)
176 await sqlCommands[2].deleteAll('videoComment')
179 await waitJobs(servers)
182 const { total } = await servers[0].comments.listThreads({ videoId: videoUUID1 })
183 expect(total).to.equal(2)
187 it('Should correctly update rate URLs', async function () {
190 async function check (like: string, ofServerUrl: string, urlSuffix: string, remote: 'true' | 'false') {
191 const query = `SELECT "videoId", "accountVideoRate".url FROM "accountVideoRate" ` +
192 `INNER JOIN video ON "accountVideoRate"."videoId" = video.id AND remote IS ${remote} WHERE "accountVideoRate"."url" LIKE '${like}'`
193 const res = await sqlCommands[0].selectQuery<{ url: string }>(query)
195 for (const rate of res) {
196 const matcher = new RegExp(`^${ofServerUrl}/accounts/root/dislikes/\\d+${urlSuffix}$`)
197 expect(rate.url).to.match(matcher)
201 async function checkLocal () {
202 const startsWith = 'http://' + servers[0].host + '%'
204 await check(startsWith, servers[0].url, '', 'false')
206 await check(startsWith, servers[0].url, '', 'true')
209 async function checkRemote (suffix: string) {
210 const startsWith = 'http://' + servers[1].host + '%'
212 await check(startsWith, servers[1].url, suffix, 'false')
213 // On remote videos, we should not update URLs so no suffix
214 await check(startsWith, servers[1].url, '', 'true')
218 await checkRemote('')
221 const query = `UPDATE "accountVideoRate" SET url = url || 'stan'`
222 await sqlCommands[1].updateQuery(query)
225 await waitJobs(servers)
229 await checkRemote('stan')
232 it('Should correctly update comment URLs', async function () {
235 async function check (like: string, ofServerUrl: string, urlSuffix: string, remote: 'true' | 'false') {
236 const query = `SELECT "videoId", "videoComment".url, uuid as "videoUUID" FROM "videoComment" ` +
237 `INNER JOIN video ON "videoComment"."videoId" = video.id AND remote IS ${remote} WHERE "videoComment"."url" LIKE '${like}'`
239 const res = await sqlCommands[0].selectQuery<{ url: string, videoUUID: string }>(query)
241 for (const comment of res) {
242 const matcher = new RegExp(`${ofServerUrl}/videos/watch/${comment.videoUUID}/comments/\\d+${urlSuffix}`)
243 expect(comment.url).to.match(matcher)
247 async function checkLocal () {
248 const startsWith = 'http://' + servers[0].host + '%'
250 await check(startsWith, servers[0].url, '', 'false')
252 await check(startsWith, servers[0].url, '', 'true')
255 async function checkRemote (suffix: string) {
256 const startsWith = 'http://' + servers[1].host + '%'
258 await check(startsWith, servers[1].url, suffix, 'false')
259 // On remote videos, we should not update URLs so no suffix
260 await check(startsWith, servers[1].url, '', 'true')
264 const query = `UPDATE "videoComment" SET url = url || 'kyle'`
265 await sqlCommands[1].updateQuery(query)
268 await waitJobs(servers)
272 await checkRemote('kyle')
275 it('Should remove unavailable remote resources', async function () {
278 async function expectNotDeleted () {
280 const video = await servers[0].videos.get({ id: uuid })
282 expect(video.likes).to.equal(3)
283 expect(video.dislikes).to.equal(0)
287 const { total } = await servers[0].comments.listThreads({ videoId: uuid })
288 expect(total).to.equal(3)
292 async function expectDeleted () {
294 const video = await servers[0].videos.get({ id: uuid })
296 expect(video.likes).to.equal(2)
297 expect(video.dislikes).to.equal(0)
301 const { total } = await servers[0].comments.listThreads({ videoId: uuid })
302 expect(total).to.equal(2)
306 const uuid = (await servers[0].videos.quickUpload({ name: 'server 1 video 2' })).uuid
308 await waitJobs(servers)
310 for (const server of servers) {
311 await server.videos.rate({ id: uuid, rating: 'like' })
312 await server.comments.createThread({ videoId: uuid, text: 'comment' })
315 await waitJobs(servers)
317 await expectNotDeleted()
319 await servers[1].kill()
322 await expectNotDeleted()
324 let continueWhile = true
328 await expectDeleted()
329 continueWhile = false
332 } while (continueWhile)
335 after(async function () {
336 for (const sql of sqlCommands) {
340 await cleanupTests(servers)