aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/tests/api
diff options
context:
space:
mode:
authorChocobozzz <me@florianbigard.com>2021-02-26 16:26:27 +0100
committerChocobozzz <me@florianbigard.com>2021-03-03 10:08:08 +0100
commit74d249bc1346c7cfaac7ee49bebbebcf2a01f82a (patch)
treed47bd163ae57ed8f15b445296634cc04f4f67b6f /server/tests/api
parent095e2258043fcff8a79ab082d11edfbd8f13a8e2 (diff)
downloadPeerTube-74d249bc1346c7cfaac7ee49bebbebcf2a01f82a.tar.gz
PeerTube-74d249bc1346c7cfaac7ee49bebbebcf2a01f82a.tar.zst
PeerTube-74d249bc1346c7cfaac7ee49bebbebcf2a01f82a.zip
Add ability to cleanup remote AP interactions
Diffstat (limited to 'server/tests/api')
-rw-r--r--server/tests/api/activitypub/cleaner.ts283
-rw-r--r--server/tests/api/activitypub/index.ts1
2 files changed, 284 insertions, 0 deletions
diff --git a/server/tests/api/activitypub/cleaner.ts b/server/tests/api/activitypub/cleaner.ts
new file mode 100644
index 000000000..75ef56ce3
--- /dev/null
+++ b/server/tests/api/activitypub/cleaner.ts
@@ -0,0 +1,283 @@
1/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
2
3import 'mocha'
4import * as chai from 'chai'
5import {
6 cleanupTests,
7 closeAllSequelize,
8 deleteAll,
9 doubleFollow,
10 getCount,
11 selectQuery,
12 setVideoField,
13 updateQuery,
14 wait
15} from '../../../../shared/extra-utils'
16import { flushAndRunMultipleServers, ServerInfo, setAccessTokensToServers } from '../../../../shared/extra-utils/index'
17import { waitJobs } from '../../../../shared/extra-utils/server/jobs'
18import { addVideoCommentThread, getVideoCommentThreads } from '../../../../shared/extra-utils/videos/video-comments'
19import { getVideo, rateVideo, uploadVideoAndGetId } from '../../../../shared/extra-utils/videos/videos'
20
21const expect = chai.expect
22
23describe('Test AP cleaner', function () {
24 let servers: ServerInfo[] = []
25 let videoUUID1: string
26 let videoUUID2: string
27 let videoUUID3: string
28
29 let videoUUIDs: string[]
30
31 before(async function () {
32 this.timeout(120000)
33
34 const config = {
35 federation: {
36 videos: { cleanup_remote_interactions: true }
37 }
38 }
39 servers = await flushAndRunMultipleServers(3, config)
40
41 // Get the access tokens
42 await setAccessTokensToServers(servers)
43
44 await Promise.all([
45 doubleFollow(servers[0], servers[1]),
46 doubleFollow(servers[1], servers[2]),
47 doubleFollow(servers[0], servers[2])
48 ])
49
50 // Update 1 local share, check 6 shares
51
52 // Create 1 comment per video
53 // Update 1 remote URL and 1 local URL on
54
55 videoUUID1 = (await uploadVideoAndGetId({ server: servers[0], videoName: 'server 1' })).uuid
56 videoUUID2 = (await uploadVideoAndGetId({ server: servers[1], videoName: 'server 2' })).uuid
57 videoUUID3 = (await uploadVideoAndGetId({ server: servers[2], videoName: 'server 3' })).uuid
58
59 videoUUIDs = [ videoUUID1, videoUUID2, videoUUID3 ]
60
61 await waitJobs(servers)
62
63 for (const server of servers) {
64 for (const uuid of videoUUIDs) {
65 await rateVideo(server.url, server.accessToken, uuid, 'like')
66 await addVideoCommentThread(server.url, server.accessToken, uuid, 'comment')
67 }
68 }
69
70 await waitJobs(servers)
71 })
72
73 it('Should have the correct likes', async function () {
74 for (const server of servers) {
75 for (const uuid of videoUUIDs) {
76 const res = await getVideo(server.url, uuid)
77 expect(res.body.likes).to.equal(3)
78 expect(res.body.dislikes).to.equal(0)
79 }
80 }
81 })
82
83 it('Should destroy server 3 internal likes and correctly clean them', async function () {
84 this.timeout(20000)
85
86 await deleteAll(servers[2].internalServerNumber, 'accountVideoRate')
87 for (const uuid of videoUUIDs) {
88 await setVideoField(servers[2].internalServerNumber, uuid, 'likes', '0')
89 }
90
91 await wait(5000)
92 await waitJobs(servers)
93
94 // Updated rates of my video
95 {
96 const res = await getVideo(servers[0].url, videoUUID1)
97 expect(res.body.likes).to.equal(2)
98 expect(res.body.dislikes).to.equal(0)
99 }
100
101 // Did not update rates of a remote video
102 {
103 const res = await getVideo(servers[0].url, videoUUID2)
104 expect(res.body.likes).to.equal(3)
105 expect(res.body.dislikes).to.equal(0)
106 }
107 })
108
109 it('Should update rates to dislikes', async function () {
110 this.timeout(20000)
111
112 for (const server of servers) {
113 for (const uuid of videoUUIDs) {
114 await rateVideo(server.url, server.accessToken, uuid, 'dislike')
115 }
116 }
117
118 await waitJobs(servers)
119
120 for (const server of servers) {
121 for (const uuid of videoUUIDs) {
122 const res = await getVideo(server.url, uuid)
123 expect(res.body.likes).to.equal(0)
124 expect(res.body.dislikes).to.equal(3)
125 }
126 }
127 })
128
129 it('Should destroy server 3 internal dislikes and correctly clean them', async function () {
130 this.timeout(20000)
131
132 await deleteAll(servers[2].internalServerNumber, 'accountVideoRate')
133
134 for (const uuid of videoUUIDs) {
135 await setVideoField(servers[2].internalServerNumber, uuid, 'dislikes', '0')
136 }
137
138 await wait(5000)
139 await waitJobs(servers)
140
141 // Updated rates of my video
142 {
143 const res = await getVideo(servers[0].url, videoUUID1)
144 expect(res.body.likes).to.equal(0)
145 expect(res.body.dislikes).to.equal(2)
146 }
147
148 // Did not update rates of a remote video
149 {
150 const res = await getVideo(servers[0].url, videoUUID2)
151 expect(res.body.likes).to.equal(0)
152 expect(res.body.dislikes).to.equal(3)
153 }
154 })
155
156 it('Should destroy server 3 internal shares and correctly clean them', async function () {
157 this.timeout(20000)
158
159 const preCount = await getCount(servers[0].internalServerNumber, 'videoShare')
160 expect(preCount).to.equal(6)
161
162 await deleteAll(servers[2].internalServerNumber, 'videoShare')
163 await wait(5000)
164 await waitJobs(servers)
165
166 // Still 6 because we don't have remote shares on local videos
167 const postCount = await getCount(servers[0].internalServerNumber, 'videoShare')
168 expect(postCount).to.equal(6)
169 })
170
171 it('Should destroy server 3 internal comments and correctly clean them', async function () {
172 this.timeout(20000)
173
174 {
175 const res = await getVideoCommentThreads(servers[0].url, videoUUID1, 0, 5)
176 expect(res.body.total).to.equal(3)
177 }
178
179 await deleteAll(servers[2].internalServerNumber, 'videoComment')
180
181 await wait(5000)
182 await waitJobs(servers)
183
184 {
185 const res = await getVideoCommentThreads(servers[0].url, videoUUID1, 0, 5)
186 expect(res.body.total).to.equal(2)
187 }
188 })
189
190 it('Should correctly update rate URLs', async function () {
191 this.timeout(30000)
192
193 async function check (like: string, ofServerUrl: string, urlSuffix: string, remote: 'true' | 'false') {
194 const query = `SELECT "videoId", "accountVideoRate".url FROM "accountVideoRate" ` +
195 `INNER JOIN video ON "accountVideoRate"."videoId" = video.id AND remote IS ${remote} WHERE "accountVideoRate"."url" LIKE '${like}'`
196 const res = await selectQuery(servers[0].internalServerNumber, query)
197
198 for (const rate of res) {
199 const matcher = new RegExp(`^${ofServerUrl}/accounts/root/dislikes/\\d+${urlSuffix}$`)
200 expect(rate.url).to.match(matcher)
201 }
202 }
203
204 async function checkLocal () {
205 const startsWith = 'http://' + servers[0].host + '%'
206 // On local videos
207 await check(startsWith, servers[0].url, '', 'false')
208 // On remote videos
209 await check(startsWith, servers[0].url, '', 'true')
210 }
211
212 async function checkRemote (suffix: string) {
213 const startsWith = 'http://' + servers[1].host + '%'
214 // On local videos
215 await check(startsWith, servers[1].url, suffix, 'false')
216 // On remote videos, we should not update URLs so no suffix
217 await check(startsWith, servers[1].url, '', 'true')
218 }
219
220 await checkLocal()
221 await checkRemote('')
222
223 {
224 const query = `UPDATE "accountVideoRate" SET url = url || 'stan'`
225 await updateQuery(servers[1].internalServerNumber, query)
226
227 await wait(5000)
228 await waitJobs(servers)
229 }
230
231 await checkLocal()
232 await checkRemote('stan')
233 })
234
235 it('Should correctly update comment URLs', async function () {
236 this.timeout(30000)
237
238 async function check (like: string, ofServerUrl: string, urlSuffix: string, remote: 'true' | 'false') {
239 const query = `SELECT "videoId", "videoComment".url, uuid as "videoUUID" FROM "videoComment" ` +
240 `INNER JOIN video ON "videoComment"."videoId" = video.id AND remote IS ${remote} WHERE "videoComment"."url" LIKE '${like}'`
241
242 const res = await selectQuery(servers[0].internalServerNumber, query)
243
244 for (const comment of res) {
245 const matcher = new RegExp(`${ofServerUrl}/videos/watch/${comment.videoUUID}/comments/\\d+${urlSuffix}`)
246 expect(comment.url).to.match(matcher)
247 }
248 }
249
250 async function checkLocal () {
251 const startsWith = 'http://' + servers[0].host + '%'
252 // On local videos
253 await check(startsWith, servers[0].url, '', 'false')
254 // On remote videos
255 await check(startsWith, servers[0].url, '', 'true')
256 }
257
258 async function checkRemote (suffix: string) {
259 const startsWith = 'http://' + servers[1].host + '%'
260 // On local videos
261 await check(startsWith, servers[1].url, suffix, 'false')
262 // On remote videos, we should not update URLs so no suffix
263 await check(startsWith, servers[1].url, '', 'true')
264 }
265
266 {
267 const query = `UPDATE "videoComment" SET url = url || 'kyle'`
268 await updateQuery(servers[1].internalServerNumber, query)
269
270 await wait(5000)
271 await waitJobs(servers)
272 }
273
274 await checkLocal()
275 await checkRemote('kyle')
276 })
277
278 after(async function () {
279 await cleanupTests(servers)
280
281 await closeAllSequelize(servers)
282 })
283})
diff --git a/server/tests/api/activitypub/index.ts b/server/tests/api/activitypub/index.ts
index 92bd6f660..324b444e4 100644
--- a/server/tests/api/activitypub/index.ts
+++ b/server/tests/api/activitypub/index.ts
@@ -1,3 +1,4 @@
1import './cleaner'
1import './client' 2import './client'
2import './fetch' 3import './fetch'
3import './refresher' 4import './refresher'