diff options
author | Chocobozzz <me@florianbigard.com> | 2023-01-03 14:23:42 +0100 |
---|---|---|
committer | Chocobozzz <me@florianbigard.com> | 2023-01-03 14:23:42 +0100 |
commit | 25691c99307997b80075c817a801fe3049cd8987 (patch) | |
tree | 1ed054356f629884e2ef46409bbccfa5ba310085 | |
parent | 66b73484c719659d213cab225ae3b63a3aae5228 (diff) | |
download | PeerTube-25691c99307997b80075c817a801fe3049cd8987.tar.gz PeerTube-25691c99307997b80075c817a801fe3049cd8987.tar.zst PeerTube-25691c99307997b80075c817a801fe3049cd8987.zip |
Prefer using sequelize replacements even for tests
-rw-r--r-- | server/tests/api/activitypub/cleaner.ts | 8 | ||||
-rw-r--r-- | server/tests/api/live/live-fast-restream.ts | 2 | ||||
-rw-r--r-- | shared/server-commands/miscs/sql-command.ts | 102 |
3 files changed, 49 insertions, 63 deletions
diff --git a/server/tests/api/activitypub/cleaner.ts b/server/tests/api/activitypub/cleaner.ts index eb6779123..1c1495022 100644 --- a/server/tests/api/activitypub/cleaner.ts +++ b/server/tests/api/activitypub/cleaner.ts | |||
@@ -148,7 +148,7 @@ describe('Test AP cleaner', function () { | |||
148 | it('Should destroy server 3 internal shares and correctly clean them', async function () { | 148 | it('Should destroy server 3 internal shares and correctly clean them', async function () { |
149 | this.timeout(20000) | 149 | this.timeout(20000) |
150 | 150 | ||
151 | const preCount = await servers[0].sql.getCount('videoShare') | 151 | const preCount = await servers[0].sql.getVideoShareCount() |
152 | expect(preCount).to.equal(6) | 152 | expect(preCount).to.equal(6) |
153 | 153 | ||
154 | await servers[2].sql.deleteAll('videoShare') | 154 | await servers[2].sql.deleteAll('videoShare') |
@@ -156,7 +156,7 @@ describe('Test AP cleaner', function () { | |||
156 | await waitJobs(servers) | 156 | await waitJobs(servers) |
157 | 157 | ||
158 | // Still 6 because we don't have remote shares on local videos | 158 | // Still 6 because we don't have remote shares on local videos |
159 | const postCount = await servers[0].sql.getCount('videoShare') | 159 | const postCount = await servers[0].sql.getVideoShareCount() |
160 | expect(postCount).to.equal(6) | 160 | expect(postCount).to.equal(6) |
161 | }) | 161 | }) |
162 | 162 | ||
@@ -185,7 +185,7 @@ describe('Test AP cleaner', function () { | |||
185 | async function check (like: string, ofServerUrl: string, urlSuffix: string, remote: 'true' | 'false') { | 185 | async function check (like: string, ofServerUrl: string, urlSuffix: string, remote: 'true' | 'false') { |
186 | const query = `SELECT "videoId", "accountVideoRate".url FROM "accountVideoRate" ` + | 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}'` | 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) | 188 | const res = await servers[0].sql.selectQuery<{ url: string }>(query) |
189 | 189 | ||
190 | for (const rate of res) { | 190 | for (const rate of res) { |
191 | const matcher = new RegExp(`^${ofServerUrl}/accounts/root/dislikes/\\d+${urlSuffix}$`) | 191 | const matcher = new RegExp(`^${ofServerUrl}/accounts/root/dislikes/\\d+${urlSuffix}$`) |
@@ -231,7 +231,7 @@ describe('Test AP cleaner', function () { | |||
231 | const query = `SELECT "videoId", "videoComment".url, uuid as "videoUUID" FROM "videoComment" ` + | 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}'` | 232 | `INNER JOIN video ON "videoComment"."videoId" = video.id AND remote IS ${remote} WHERE "videoComment"."url" LIKE '${like}'` |
233 | 233 | ||
234 | const res = await servers[0].sql.selectQuery(query) | 234 | const res = await servers[0].sql.selectQuery<{ url: string, videoUUID: string }>(query) |
235 | 235 | ||
236 | for (const comment of res) { | 236 | for (const comment of res) { |
237 | const matcher = new RegExp(`${ofServerUrl}/videos/watch/${comment.videoUUID}/comments/\\d+${urlSuffix}`) | 237 | const matcher = new RegExp(`${ofServerUrl}/videos/watch/${comment.videoUUID}/comments/\\d+${urlSuffix}`) |
diff --git a/server/tests/api/live/live-fast-restream.ts b/server/tests/api/live/live-fast-restream.ts index c0bb8d529..63a69e591 100644 --- a/server/tests/api/live/live-fast-restream.ts +++ b/server/tests/api/live/live-fast-restream.ts | |||
@@ -129,7 +129,7 @@ describe('Fast restream in live', function () { | |||
129 | await server.config.enableLive({ allowReplay: true, transcoding: true, resolutions: 'min' }) | 129 | await server.config.enableLive({ allowReplay: true, transcoding: true, resolutions: 'min' }) |
130 | }) | 130 | }) |
131 | 131 | ||
132 | it('Should correctly fast reastream in a permanent live with and without save replay', async function () { | 132 | it('Should correctly fast restream in a permanent live with and without save replay', async function () { |
133 | this.timeout(480000) | 133 | this.timeout(480000) |
134 | 134 | ||
135 | // A test can take a long time, so prefer to run them in parallel | 135 | // A test can take a long time, so prefer to run them in parallel |
diff --git a/shared/server-commands/miscs/sql-command.ts b/shared/server-commands/miscs/sql-command.ts index 823fc9e38..35cc2253f 100644 --- a/shared/server-commands/miscs/sql-command.ts +++ b/shared/server-commands/miscs/sql-command.ts | |||
@@ -13,101 +13,87 @@ export class SQLCommand extends AbstractCommand { | |||
13 | return seq.query(`DELETE FROM "${table}"`, options) | 13 | return seq.query(`DELETE FROM "${table}"`, options) |
14 | } | 14 | } |
15 | 15 | ||
16 | async getCount (table: string) { | 16 | async getVideoShareCount () { |
17 | const seq = this.getSequelize() | 17 | const [ { total } ] = await this.selectQuery<{ total: string }>(`SELECT COUNT(*) as total FROM "videoShare"`) |
18 | |||
19 | const options = { type: QueryTypes.SELECT as QueryTypes.SELECT } | ||
20 | |||
21 | const [ { total } ] = await seq.query<{ total: string }>(`SELECT COUNT(*) as total FROM "${table}"`, options) | ||
22 | if (total === null) return 0 | 18 | if (total === null) return 0 |
23 | 19 | ||
24 | return parseInt(total, 10) | 20 | return parseInt(total, 10) |
25 | } | 21 | } |
26 | 22 | ||
27 | async getInternalFileUrl (fileId: number) { | 23 | async getInternalFileUrl (fileId: number) { |
28 | return this.selectQuery(`SELECT "fileUrl" FROM "videoFile" WHERE id = ${fileId}`) | 24 | return this.selectQuery<{ fileUrl: string }>(`SELECT "fileUrl" FROM "videoFile" WHERE id = :fileId`, { fileId }) |
29 | .then(rows => rows[0].fileUrl as string) | 25 | .then(rows => rows[0].fileUrl) |
30 | } | 26 | } |
31 | 27 | ||
32 | setActorField (to: string, field: string, value: string) { | 28 | setActorField (to: string, field: string, value: string) { |
33 | const seq = this.getSequelize() | 29 | return this.updateQuery(`UPDATE actor SET ${this.escapeColumnName(field)} = :value WHERE url = :to`, { value, to }) |
34 | |||
35 | const options = { type: QueryTypes.UPDATE } | ||
36 | |||
37 | return seq.query(`UPDATE actor SET "${field}" = '${value}' WHERE url = '${to}'`, options) | ||
38 | } | 30 | } |
39 | 31 | ||
40 | setVideoField (uuid: string, field: string, value: string) { | 32 | setVideoField (uuid: string, field: string, value: string) { |
41 | const seq = this.getSequelize() | 33 | return this.updateQuery(`UPDATE video SET ${this.escapeColumnName(field)} = :value WHERE uuid = :uuid`, { value, uuid }) |
42 | |||
43 | const options = { type: QueryTypes.UPDATE } | ||
44 | |||
45 | return seq.query(`UPDATE video SET "${field}" = '${value}' WHERE uuid = '${uuid}'`, options) | ||
46 | } | 34 | } |
47 | 35 | ||
48 | setPlaylistField (uuid: string, field: string, value: string) { | 36 | setPlaylistField (uuid: string, field: string, value: string) { |
49 | const seq = this.getSequelize() | 37 | return this.updateQuery(`UPDATE "videoPlaylist" SET ${this.escapeColumnName(field)} = :value WHERE uuid = :uuid`, { value, uuid }) |
50 | |||
51 | const options = { type: QueryTypes.UPDATE } | ||
52 | |||
53 | return seq.query(`UPDATE "videoPlaylist" SET "${field}" = '${value}' WHERE uuid = '${uuid}'`, options) | ||
54 | } | 38 | } |
55 | 39 | ||
56 | async countVideoViewsOf (uuid: string) { | 40 | async countVideoViewsOf (uuid: string) { |
57 | const seq = this.getSequelize() | ||
58 | |||
59 | const query = 'SELECT SUM("videoView"."views") AS "total" FROM "videoView" ' + | 41 | const query = 'SELECT SUM("videoView"."views") AS "total" FROM "videoView" ' + |
60 | `INNER JOIN "video" ON "video"."id" = "videoView"."videoId" WHERE "video"."uuid" = '${uuid}'` | 42 | `INNER JOIN "video" ON "video"."id" = "videoView"."videoId" WHERE "video"."uuid" = :uuid` |
61 | |||
62 | const options = { type: QueryTypes.SELECT as QueryTypes.SELECT } | ||
63 | const [ { total } ] = await seq.query<{ total: number }>(query, options) | ||
64 | 43 | ||
44 | const [ { total } ] = await this.selectQuery<{ total: number }>(query, { uuid }) | ||
65 | if (!total) return 0 | 45 | if (!total) return 0 |
66 | 46 | ||
67 | return forceNumber(total) | 47 | return forceNumber(total) |
68 | } | 48 | } |
69 | 49 | ||
70 | getActorImage (filename: string) { | 50 | getActorImage (filename: string) { |
71 | return this.selectQuery(`SELECT * FROM "actorImage" WHERE filename = '${filename}'`) | 51 | return this.selectQuery<{ width: number, height: number }>(`SELECT * FROM "actorImage" WHERE filename = :filename`, { filename }) |
72 | .then(rows => rows[0]) | 52 | .then(rows => rows[0]) |
73 | } | 53 | } |
74 | 54 | ||
75 | selectQuery (query: string) { | 55 | // --------------------------------------------------------------------------- |
76 | const seq = this.getSequelize() | ||
77 | const options = { type: QueryTypes.SELECT as QueryTypes.SELECT } | ||
78 | 56 | ||
79 | return seq.query<any>(query, options) | 57 | setPluginVersion (pluginName: string, newVersion: string) { |
58 | return this.setPluginField(pluginName, 'version', newVersion) | ||
80 | } | 59 | } |
81 | 60 | ||
82 | updateQuery (query: string) { | 61 | setPluginLatestVersion (pluginName: string, newVersion: string) { |
83 | const seq = this.getSequelize() | 62 | return this.setPluginField(pluginName, 'latestVersion', newVersion) |
84 | const options = { type: QueryTypes.UPDATE as QueryTypes.UPDATE } | 63 | } |
85 | 64 | ||
86 | return seq.query(query, options) | 65 | setPluginField (pluginName: string, field: string, value: string) { |
66 | return this.updateQuery( | ||
67 | `UPDATE "plugin" SET ${this.escapeColumnName(field)} = :value WHERE "name" = :pluginName`, | ||
68 | { pluginName, value } | ||
69 | ) | ||
87 | } | 70 | } |
88 | 71 | ||
89 | // --------------------------------------------------------------------------- | 72 | // --------------------------------------------------------------------------- |
90 | 73 | ||
91 | setPluginField (pluginName: string, field: string, value: string) { | 74 | selectQuery <T extends object> (query: string, replacements: { [id: string]: string | number } = {}) { |
92 | const seq = this.getSequelize() | 75 | const seq = this.getSequelize() |
76 | const options = { | ||
77 | type: QueryTypes.SELECT as QueryTypes.SELECT, | ||
78 | replacements | ||
79 | } | ||
93 | 80 | ||
94 | const options = { type: QueryTypes.UPDATE } | 81 | return seq.query<T>(query, options) |
95 | |||
96 | return seq.query(`UPDATE "plugin" SET "${field}" = '${value}' WHERE "name" = '${pluginName}'`, options) | ||
97 | } | 82 | } |
98 | 83 | ||
99 | setPluginVersion (pluginName: string, newVersion: string) { | 84 | updateQuery (query: string, replacements: { [id: string]: string | number } = {}) { |
100 | return this.setPluginField(pluginName, 'version', newVersion) | 85 | const seq = this.getSequelize() |
101 | } | 86 | const options = { type: QueryTypes.UPDATE as QueryTypes.UPDATE, replacements } |
102 | 87 | ||
103 | setPluginLatestVersion (pluginName: string, newVersion: string) { | 88 | return seq.query(query, options) |
104 | return this.setPluginField(pluginName, 'latestVersion', newVersion) | ||
105 | } | 89 | } |
106 | 90 | ||
107 | // --------------------------------------------------------------------------- | 91 | // --------------------------------------------------------------------------- |
108 | 92 | ||
109 | async getPlaylistInfohash (playlistId: number) { | 93 | async getPlaylistInfohash (playlistId: number) { |
110 | const result = await this.selectQuery('SELECT "p2pMediaLoaderInfohashes" FROM "videoStreamingPlaylist" WHERE id = ' + playlistId) | 94 | const query = 'SELECT "p2pMediaLoaderInfohashes" FROM "videoStreamingPlaylist" WHERE id = :playlistId' |
95 | |||
96 | const result = await this.selectQuery<{ p2pMediaLoaderInfohashes: string }>(query, { playlistId }) | ||
111 | if (!result || result.length === 0) return [] | 97 | if (!result || result.length === 0) return [] |
112 | 98 | ||
113 | return result[0].p2pMediaLoaderInfohashes | 99 | return result[0].p2pMediaLoaderInfohashes |
@@ -116,19 +102,14 @@ export class SQLCommand extends AbstractCommand { | |||
116 | // --------------------------------------------------------------------------- | 102 | // --------------------------------------------------------------------------- |
117 | 103 | ||
118 | setActorFollowScores (newScore: number) { | 104 | setActorFollowScores (newScore: number) { |
119 | const seq = this.getSequelize() | 105 | return this.updateQuery(`UPDATE "actorFollow" SET "score" = :newScore`, { newScore }) |
120 | |||
121 | const options = { type: QueryTypes.UPDATE } | ||
122 | |||
123 | return seq.query(`UPDATE "actorFollow" SET "score" = ${newScore}`, options) | ||
124 | } | 106 | } |
125 | 107 | ||
126 | setTokenField (accessToken: string, field: string, value: string) { | 108 | setTokenField (accessToken: string, field: string, value: string) { |
127 | const seq = this.getSequelize() | 109 | return this.updateQuery( |
128 | 110 | `UPDATE "oAuthToken" SET ${this.escapeColumnName(field)} = :value WHERE "accessToken" = :accessToken`, | |
129 | const options = { type: QueryTypes.UPDATE } | 111 | { value, accessToken } |
130 | 112 | ) | |
131 | return seq.query(`UPDATE "oAuthToken" SET "${field}" = '${value}' WHERE "accessToken" = '${accessToken}'`, options) | ||
132 | } | 113 | } |
133 | 114 | ||
134 | async cleanup () { | 115 | async cleanup () { |
@@ -157,4 +138,9 @@ export class SQLCommand extends AbstractCommand { | |||
157 | return this.sequelize | 138 | return this.sequelize |
158 | } | 139 | } |
159 | 140 | ||
141 | private escapeColumnName (columnName: string) { | ||
142 | return this.getSequelize().escape(columnName) | ||
143 | .replace(/^'/, '"') | ||
144 | .replace(/'$/, '"') | ||
145 | } | ||
160 | } | 146 | } |