diff options
author | Chocobozzz <me@florianbigard.com> | 2023-07-31 14:34:36 +0200 |
---|---|---|
committer | Chocobozzz <me@florianbigard.com> | 2023-08-11 15:02:33 +0200 |
commit | 3a4992633ee62d5edfbb484d9c6bcb3cf158489d (patch) | |
tree | e4510b39bdac9c318fdb4b47018d08f15368b8f0 /server/tests/api/activitypub/cleaner.ts | |
parent | 04d1da5621d25d59bd5fa1543b725c497bf5d9a8 (diff) | |
download | PeerTube-3a4992633ee62d5edfbb484d9c6bcb3cf158489d.tar.gz PeerTube-3a4992633ee62d5edfbb484d9c6bcb3cf158489d.tar.zst PeerTube-3a4992633ee62d5edfbb484d9c6bcb3cf158489d.zip |
Migrate server to ESM
Sorry for the very big commit that may lead to git log issues and merge
conflicts, but it's a major step forward:
* Server can be faster at startup because imports() are async and we can
easily lazy import big modules
* Angular doesn't seem to support ES import (with .js extension), so we
had to correctly organize peertube into a monorepo:
* Use yarn workspace feature
* Use typescript reference projects for dependencies
* Shared projects have been moved into "packages", each one is now a
node module (with a dedicated package.json/tsconfig.json)
* server/tools have been moved into apps/ and is now a dedicated app
bundled and published on NPM so users don't have to build peertube
cli tools manually
* server/tests have been moved into packages/ so we don't compile
them every time we want to run the server
* Use isolatedModule option:
* Had to move from const enum to const
(https://www.typescriptlang.org/docs/handbook/enums.html#objects-vs-enums)
* Had to explictely specify "type" imports when used in decorators
* Prefer tsx (that uses esbuild under the hood) instead of ts-node to
load typescript files (tests with mocha or scripts):
* To reduce test complexity as esbuild doesn't support decorator
metadata, we only test server files that do not import server
models
* We still build tests files into js files for a faster CI
* Remove unmaintained peertube CLI import script
* Removed some barrels to speed up execution (less imports)
Diffstat (limited to 'server/tests/api/activitypub/cleaner.ts')
-rw-r--r-- | server/tests/api/activitypub/cleaner.ts | 342 |
1 files changed, 0 insertions, 342 deletions
diff --git a/server/tests/api/activitypub/cleaner.ts b/server/tests/api/activitypub/cleaner.ts deleted file mode 100644 index d67175e20..000000000 --- a/server/tests/api/activitypub/cleaner.ts +++ /dev/null | |||
@@ -1,342 +0,0 @@ | |||
1 | /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */ | ||
2 | |||
3 | import { expect } from 'chai' | ||
4 | import { SQLCommand } from '@server/tests/shared' | ||
5 | import { wait } from '@shared/core-utils' | ||
6 | import { | ||
7 | cleanupTests, | ||
8 | createMultipleServers, | ||
9 | doubleFollow, | ||
10 | PeerTubeServer, | ||
11 | setAccessTokensToServers, | ||
12 | waitJobs | ||
13 | } from '@shared/server-commands' | ||
14 | |||
15 | describe('Test AP cleaner', function () { | ||
16 | let servers: PeerTubeServer[] = [] | ||
17 | const sqlCommands: SQLCommand[] = [] | ||
18 | |||
19 | let videoUUID1: string | ||
20 | let videoUUID2: string | ||
21 | let videoUUID3: string | ||
22 | |||
23 | let videoUUIDs: string[] | ||
24 | |||
25 | before(async function () { | ||
26 | this.timeout(120000) | ||
27 | |||
28 | const config = { | ||
29 | federation: { | ||
30 | videos: { cleanup_remote_interactions: true } | ||
31 | } | ||
32 | } | ||
33 | servers = await createMultipleServers(3, config) | ||
34 | |||
35 | // Get the access tokens | ||
36 | await setAccessTokensToServers(servers) | ||
37 | |||
38 | await Promise.all([ | ||
39 | doubleFollow(servers[0], servers[1]), | ||
40 | doubleFollow(servers[1], servers[2]), | ||
41 | doubleFollow(servers[0], servers[2]) | ||
42 | ]) | ||
43 | |||
44 | // Update 1 local share, check 6 shares | ||
45 | |||
46 | // Create 1 comment per video | ||
47 | // Update 1 remote URL and 1 local URL on | ||
48 | |||
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 | ||
52 | |||
53 | videoUUIDs = [ videoUUID1, videoUUID2, videoUUID3 ] | ||
54 | |||
55 | await waitJobs(servers) | ||
56 | |||
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' }) | ||
61 | } | ||
62 | |||
63 | sqlCommands.push(new SQLCommand(server)) | ||
64 | } | ||
65 | |||
66 | await waitJobs(servers) | ||
67 | }) | ||
68 | |||
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 }) | ||
73 | |||
74 | expect(video.likes).to.equal(3) | ||
75 | expect(video.dislikes).to.equal(0) | ||
76 | } | ||
77 | } | ||
78 | }) | ||
79 | |||
80 | it('Should destroy server 3 internal likes and correctly clean them', async function () { | ||
81 | this.timeout(20000) | ||
82 | |||
83 | await sqlCommands[2].deleteAll('accountVideoRate') | ||
84 | for (const uuid of videoUUIDs) { | ||
85 | await sqlCommands[2].setVideoField(uuid, 'likes', '0') | ||
86 | } | ||
87 | |||
88 | await wait(5000) | ||
89 | await waitJobs(servers) | ||
90 | |||
91 | // Updated rates of my video | ||
92 | { | ||
93 | const video = await servers[0].videos.get({ id: videoUUID1 }) | ||
94 | expect(video.likes).to.equal(2) | ||
95 | expect(video.dislikes).to.equal(0) | ||
96 | } | ||
97 | |||
98 | // Did not update rates of a remote video | ||
99 | { | ||
100 | const video = await servers[0].videos.get({ id: videoUUID2 }) | ||
101 | expect(video.likes).to.equal(3) | ||
102 | expect(video.dislikes).to.equal(0) | ||
103 | } | ||
104 | }) | ||
105 | |||
106 | it('Should update rates to dislikes', async function () { | ||
107 | this.timeout(20000) | ||
108 | |||
109 | for (const server of servers) { | ||
110 | for (const uuid of videoUUIDs) { | ||
111 | await server.videos.rate({ id: uuid, rating: 'dislike' }) | ||
112 | } | ||
113 | } | ||
114 | |||
115 | await waitJobs(servers) | ||
116 | |||
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) | ||
122 | } | ||
123 | } | ||
124 | }) | ||
125 | |||
126 | it('Should destroy server 3 internal dislikes and correctly clean them', async function () { | ||
127 | this.timeout(20000) | ||
128 | |||
129 | await sqlCommands[2].deleteAll('accountVideoRate') | ||
130 | |||
131 | for (const uuid of videoUUIDs) { | ||
132 | await sqlCommands[2].setVideoField(uuid, 'dislikes', '0') | ||
133 | } | ||
134 | |||
135 | await wait(5000) | ||
136 | await waitJobs(servers) | ||
137 | |||
138 | // Updated rates of my video | ||
139 | { | ||
140 | const video = await servers[0].videos.get({ id: videoUUID1 }) | ||
141 | expect(video.likes).to.equal(0) | ||
142 | expect(video.dislikes).to.equal(2) | ||
143 | } | ||
144 | |||
145 | // Did not update rates of a remote video | ||
146 | { | ||
147 | const video = await servers[0].videos.get({ id: videoUUID2 }) | ||
148 | expect(video.likes).to.equal(0) | ||
149 | expect(video.dislikes).to.equal(3) | ||
150 | } | ||
151 | }) | ||
152 | |||
153 | it('Should destroy server 3 internal shares and correctly clean them', async function () { | ||
154 | this.timeout(20000) | ||
155 | |||
156 | const preCount = await sqlCommands[0].getVideoShareCount() | ||
157 | expect(preCount).to.equal(6) | ||
158 | |||
159 | await sqlCommands[2].deleteAll('videoShare') | ||
160 | await wait(5000) | ||
161 | await waitJobs(servers) | ||
162 | |||
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) | ||
166 | }) | ||
167 | |||
168 | it('Should destroy server 3 internal comments and correctly clean them', async function () { | ||
169 | this.timeout(20000) | ||
170 | |||
171 | { | ||
172 | const { total } = await servers[0].comments.listThreads({ videoId: videoUUID1 }) | ||
173 | expect(total).to.equal(3) | ||
174 | } | ||
175 | |||
176 | await sqlCommands[2].deleteAll('videoComment') | ||
177 | |||
178 | await wait(5000) | ||
179 | await waitJobs(servers) | ||
180 | |||
181 | { | ||
182 | const { total } = await servers[0].comments.listThreads({ videoId: videoUUID1 }) | ||
183 | expect(total).to.equal(2) | ||
184 | } | ||
185 | }) | ||
186 | |||
187 | it('Should correctly update rate URLs', async function () { | ||
188 | this.timeout(30000) | ||
189 | |||
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) | ||
194 | |||
195 | for (const rate of res) { | ||
196 | const matcher = new RegExp(`^${ofServerUrl}/accounts/root/dislikes/\\d+${urlSuffix}$`) | ||
197 | expect(rate.url).to.match(matcher) | ||
198 | } | ||
199 | } | ||
200 | |||
201 | async function checkLocal () { | ||
202 | const startsWith = 'http://' + servers[0].host + '%' | ||
203 | // On local videos | ||
204 | await check(startsWith, servers[0].url, '', 'false') | ||
205 | // On remote videos | ||
206 | await check(startsWith, servers[0].url, '', 'true') | ||
207 | } | ||
208 | |||
209 | async function checkRemote (suffix: string) { | ||
210 | const startsWith = 'http://' + servers[1].host + '%' | ||
211 | // On local videos | ||
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') | ||
215 | } | ||
216 | |||
217 | await checkLocal() | ||
218 | await checkRemote('') | ||
219 | |||
220 | { | ||
221 | const query = `UPDATE "accountVideoRate" SET url = url || 'stan'` | ||
222 | await sqlCommands[1].updateQuery(query) | ||
223 | |||
224 | await wait(5000) | ||
225 | await waitJobs(servers) | ||
226 | } | ||
227 | |||
228 | await checkLocal() | ||
229 | await checkRemote('stan') | ||
230 | }) | ||
231 | |||
232 | it('Should correctly update comment URLs', async function () { | ||
233 | this.timeout(30000) | ||
234 | |||
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}'` | ||
238 | |||
239 | const res = await sqlCommands[0].selectQuery<{ url: string, videoUUID: string }>(query) | ||
240 | |||
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) | ||
244 | } | ||
245 | } | ||
246 | |||
247 | async function checkLocal () { | ||
248 | const startsWith = 'http://' + servers[0].host + '%' | ||
249 | // On local videos | ||
250 | await check(startsWith, servers[0].url, '', 'false') | ||
251 | // On remote videos | ||
252 | await check(startsWith, servers[0].url, '', 'true') | ||
253 | } | ||
254 | |||
255 | async function checkRemote (suffix: string) { | ||
256 | const startsWith = 'http://' + servers[1].host + '%' | ||
257 | // On local videos | ||
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') | ||
261 | } | ||
262 | |||
263 | { | ||
264 | const query = `UPDATE "videoComment" SET url = url || 'kyle'` | ||
265 | await sqlCommands[1].updateQuery(query) | ||
266 | |||
267 | await wait(5000) | ||
268 | await waitJobs(servers) | ||
269 | } | ||
270 | |||
271 | await checkLocal() | ||
272 | await checkRemote('kyle') | ||
273 | }) | ||
274 | |||
275 | it('Should remove unavailable remote resources', async function () { | ||
276 | this.timeout(240000) | ||
277 | |||
278 | async function expectNotDeleted () { | ||
279 | { | ||
280 | const video = await servers[0].videos.get({ id: uuid }) | ||
281 | |||
282 | expect(video.likes).to.equal(3) | ||
283 | expect(video.dislikes).to.equal(0) | ||
284 | } | ||
285 | |||
286 | { | ||
287 | const { total } = await servers[0].comments.listThreads({ videoId: uuid }) | ||
288 | expect(total).to.equal(3) | ||
289 | } | ||
290 | } | ||
291 | |||
292 | async function expectDeleted () { | ||
293 | { | ||
294 | const video = await servers[0].videos.get({ id: uuid }) | ||
295 | |||
296 | expect(video.likes).to.equal(2) | ||
297 | expect(video.dislikes).to.equal(0) | ||
298 | } | ||
299 | |||
300 | { | ||
301 | const { total } = await servers[0].comments.listThreads({ videoId: uuid }) | ||
302 | expect(total).to.equal(2) | ||
303 | } | ||
304 | } | ||
305 | |||
306 | const uuid = (await servers[0].videos.quickUpload({ name: 'server 1 video 2' })).uuid | ||
307 | |||
308 | await waitJobs(servers) | ||
309 | |||
310 | for (const server of servers) { | ||
311 | await server.videos.rate({ id: uuid, rating: 'like' }) | ||
312 | await server.comments.createThread({ videoId: uuid, text: 'comment' }) | ||
313 | } | ||
314 | |||
315 | await waitJobs(servers) | ||
316 | |||
317 | await expectNotDeleted() | ||
318 | |||
319 | await servers[1].kill() | ||
320 | |||
321 | await wait(5000) | ||
322 | await expectNotDeleted() | ||
323 | |||
324 | let continueWhile = true | ||
325 | |||
326 | do { | ||
327 | try { | ||
328 | await expectDeleted() | ||
329 | continueWhile = false | ||
330 | } catch { | ||
331 | } | ||
332 | } while (continueWhile) | ||
333 | }) | ||
334 | |||
335 | after(async function () { | ||
336 | for (const sql of sqlCommands) { | ||
337 | await sql.cleanup() | ||
338 | } | ||
339 | |||
340 | await cleanupTests(servers) | ||
341 | }) | ||
342 | }) | ||