From 9293139fde7091e9badcafa9b570b83cea9a10ad Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Fri, 9 Jul 2021 15:37:43 +0200 Subject: Introduce sql command --- scripts/benchmark.ts | 2 +- server/tests/api/activitypub/cleaner.ts | 32 ++-- server/tests/api/activitypub/fetch.ts | 12 +- server/tests/api/activitypub/refresher.ts | 16 +- server/tests/api/activitypub/security.ts | 14 +- server/tests/api/check-params/contact-form.ts | 4 +- server/tests/api/check-params/users.ts | 2 +- server/tests/api/live/live.ts | 2 +- server/tests/api/moderation/video-blacklist.ts | 2 +- .../tests/api/notifications/admin-notifications.ts | 10 +- .../tests/api/redundancy/redundancy-constraints.ts | 4 +- server/tests/api/redundancy/redundancy.ts | 4 +- server/tests/api/server/config.ts | 4 +- server/tests/api/server/handle-down.ts | 12 +- server/tests/api/server/homepage.ts | 2 +- server/tests/api/server/logs.ts | 2 +- server/tests/api/server/plugins.ts | 9 +- server/tests/api/server/tracker.ts | 6 +- server/tests/api/users/users.ts | 13 +- server/tests/api/videos/video-channels.ts | 5 +- server/tests/api/videos/videos-history.ts | 4 +- server/tests/api/videos/videos-views-cleaner.ts | 20 +-- server/tests/cli/plugins.ts | 4 +- server/tests/cli/prune-storage.ts | 2 +- server/tests/cli/update-host.ts | 2 +- server/tests/external-plugins/auto-block-videos.ts | 2 +- server/tests/external-plugins/auto-mute.ts | 2 +- server/tests/plugins/action-hooks.ts | 2 +- server/tools/test-live.ts | 2 +- shared/extra-utils/miscs/index.ts | 2 +- shared/extra-utils/miscs/sql-command.ts | 142 ++++++++++++++++++ shared/extra-utils/miscs/sql.ts | 161 --------------------- shared/extra-utils/miscs/stubs.ts | 7 - shared/extra-utils/server/servers.ts | 10 +- shared/extra-utils/shared/abstract-command.ts | 2 +- 35 files changed, 229 insertions(+), 292 deletions(-) create mode 100644 shared/extra-utils/miscs/sql-command.ts delete mode 100644 shared/extra-utils/miscs/sql.ts diff --git a/scripts/benchmark.ts b/scripts/benchmark.ts index 321b07c94..272f9e8b1 100644 --- a/scripts/benchmark.ts +++ b/scripts/benchmark.ts @@ -15,7 +15,7 @@ const outfile = process.argv[2] run() .catch(err => console.error(err)) .finally(() => { - if (server) killallServers([ server ]) + if (server) return killallServers([ server ]) }) function buildAuthorizationHeader () { diff --git a/server/tests/api/activitypub/cleaner.ts b/server/tests/api/activitypub/cleaner.ts index 27f17b4d6..5b08880bf 100644 --- a/server/tests/api/activitypub/cleaner.ts +++ b/server/tests/api/activitypub/cleaner.ts @@ -4,18 +4,12 @@ import 'mocha' import * as chai from 'chai' import { cleanupTests, - closeAllSequelize, - deleteAll, doubleFollow, flushAndRunMultipleServers, - getCount, getVideo, rateVideo, - selectQuery, ServerInfo, setAccessTokensToServers, - setVideoField, - updateQuery, uploadVideoAndGetId, wait, waitJobs @@ -86,9 +80,9 @@ describe('Test AP cleaner', function () { it('Should destroy server 3 internal likes and correctly clean them', async function () { this.timeout(20000) - await deleteAll(servers[2].internalServerNumber, 'accountVideoRate') + await servers[2].sqlCommand.deleteAll('accountVideoRate') for (const uuid of videoUUIDs) { - await setVideoField(servers[2].internalServerNumber, uuid, 'likes', '0') + await servers[2].sqlCommand.setVideoField(uuid, 'likes', '0') } await wait(5000) @@ -132,10 +126,10 @@ describe('Test AP cleaner', function () { it('Should destroy server 3 internal dislikes and correctly clean them', async function () { this.timeout(20000) - await deleteAll(servers[2].internalServerNumber, 'accountVideoRate') + await servers[2].sqlCommand.deleteAll('accountVideoRate') for (const uuid of videoUUIDs) { - await setVideoField(servers[2].internalServerNumber, uuid, 'dislikes', '0') + await servers[2].sqlCommand.setVideoField(uuid, 'dislikes', '0') } await wait(5000) @@ -159,15 +153,15 @@ describe('Test AP cleaner', function () { it('Should destroy server 3 internal shares and correctly clean them', async function () { this.timeout(20000) - const preCount = await getCount(servers[0].internalServerNumber, 'videoShare') + const preCount = await servers[0].sqlCommand.getCount('videoShare') expect(preCount).to.equal(6) - await deleteAll(servers[2].internalServerNumber, 'videoShare') + await servers[2].sqlCommand.deleteAll('videoShare') await wait(5000) await waitJobs(servers) // Still 6 because we don't have remote shares on local videos - const postCount = await getCount(servers[0].internalServerNumber, 'videoShare') + const postCount = await servers[0].sqlCommand.getCount('videoShare') expect(postCount).to.equal(6) }) @@ -179,7 +173,7 @@ describe('Test AP cleaner', function () { expect(total).to.equal(3) } - await deleteAll(servers[2].internalServerNumber, 'videoComment') + await servers[2].sqlCommand.deleteAll('videoComment') await wait(5000) await waitJobs(servers) @@ -196,7 +190,7 @@ describe('Test AP cleaner', function () { async function check (like: string, ofServerUrl: string, urlSuffix: string, remote: 'true' | 'false') { const query = `SELECT "videoId", "accountVideoRate".url FROM "accountVideoRate" ` + `INNER JOIN video ON "accountVideoRate"."videoId" = video.id AND remote IS ${remote} WHERE "accountVideoRate"."url" LIKE '${like}'` - const res = await selectQuery(servers[0].internalServerNumber, query) + const res = await servers[0].sqlCommand.selectQuery(query) for (const rate of res) { const matcher = new RegExp(`^${ofServerUrl}/accounts/root/dislikes/\\d+${urlSuffix}$`) @@ -225,7 +219,7 @@ describe('Test AP cleaner', function () { { const query = `UPDATE "accountVideoRate" SET url = url || 'stan'` - await updateQuery(servers[1].internalServerNumber, query) + await servers[1].sqlCommand.updateQuery(query) await wait(5000) await waitJobs(servers) @@ -242,7 +236,7 @@ describe('Test AP cleaner', function () { const query = `SELECT "videoId", "videoComment".url, uuid as "videoUUID" FROM "videoComment" ` + `INNER JOIN video ON "videoComment"."videoId" = video.id AND remote IS ${remote} WHERE "videoComment"."url" LIKE '${like}'` - const res = await selectQuery(servers[0].internalServerNumber, query) + const res = await servers[0].sqlCommand.selectQuery(query) for (const comment of res) { const matcher = new RegExp(`${ofServerUrl}/videos/watch/${comment.videoUUID}/comments/\\d+${urlSuffix}`) @@ -268,7 +262,7 @@ describe('Test AP cleaner', function () { { const query = `UPDATE "videoComment" SET url = url || 'kyle'` - await updateQuery(servers[1].internalServerNumber, query) + await servers[1].sqlCommand.updateQuery(query) await wait(5000) await waitJobs(servers) @@ -280,7 +274,5 @@ describe('Test AP cleaner', function () { after(async function () { await cleanupTests(servers) - - await closeAllSequelize(servers) }) }) diff --git a/server/tests/api/activitypub/fetch.ts b/server/tests/api/activitypub/fetch.ts index 35fd94eed..d5e21404c 100644 --- a/server/tests/api/activitypub/fetch.ts +++ b/server/tests/api/activitypub/fetch.ts @@ -1,23 +1,19 @@ /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */ import 'mocha' - +import * as chai from 'chai' import { cleanupTests, - closeAllSequelize, createUser, doubleFollow, flushAndRunMultipleServers, getVideosListSort, ServerInfo, setAccessTokensToServers, - setActorField, - setVideoField, uploadVideo, userLogin, waitJobs } from '../../../../shared/extra-utils' -import * as chai from 'chai' import { Video } from '../../../../shared/models/videos' const expect = chai.expect @@ -50,12 +46,12 @@ describe('Test ActivityPub fetcher', function () { { const to = 'http://localhost:' + servers[0].port + '/accounts/user1' const value = 'http://localhost:' + servers[1].port + '/accounts/user1' - await setActorField(servers[0].internalServerNumber, to, 'url', value) + await servers[0].sqlCommand.setActorField(to, 'url', value) } { const value = 'http://localhost:' + servers[2].port + '/videos/watch/' + badVideoUUID - await setVideoField(servers[0].internalServerNumber, badVideoUUID, 'url', value) + await servers[0].sqlCommand.setVideoField(badVideoUUID, 'url', value) } }) @@ -88,7 +84,5 @@ describe('Test ActivityPub fetcher', function () { this.timeout(20000) await cleanupTests(servers) - - await closeAllSequelize(servers) }) }) diff --git a/server/tests/api/activitypub/refresher.ts b/server/tests/api/activitypub/refresher.ts index f295dfab7..af919f2f3 100644 --- a/server/tests/api/activitypub/refresher.ts +++ b/server/tests/api/activitypub/refresher.ts @@ -4,7 +4,6 @@ import 'mocha' import { HttpStatusCode } from '@shared/core-utils' import { cleanupTests, - closeAllSequelize, doubleFollow, flushAndRunMultipleServers, generateUserAccessToken, @@ -13,10 +12,7 @@ import { reRunServer, ServerInfo, setAccessTokensToServers, - setActorField, setDefaultVideoChannel, - setPlaylistField, - setVideoField, uploadVideo, uploadVideoAndGetId, wait, @@ -78,7 +74,7 @@ describe('Test AP refresher', function () { await wait(10000) // Change UUID so the remote server returns a 404 - await setVideoField(servers[1].internalServerNumber, videoUUID1, 'uuid', '304afe4f-39f9-4d49-8ed7-ac57b86b174f') + await servers[1].sqlCommand.setVideoField(videoUUID1, 'uuid', '304afe4f-39f9-4d49-8ed7-ac57b86b174f') await getVideo(servers[0].url, videoUUID1) await getVideo(servers[0].url, videoUUID2) @@ -92,9 +88,9 @@ describe('Test AP refresher', function () { it('Should not update a remote video if the remote instance is down', async function () { this.timeout(70000) - killallServers([ servers[1] ]) + await killallServers([ servers[1] ]) - await setVideoField(servers[1].internalServerNumber, videoUUID3, 'uuid', '304afe4f-39f9-4d49-8ed7-ac57b86b174e') + await servers[1].sqlCommand.setVideoField(videoUUID3, 'uuid', '304afe4f-39f9-4d49-8ed7-ac57b86b174e') // Video will need a refresh await wait(10000) @@ -120,7 +116,7 @@ describe('Test AP refresher', function () { // Change actor name so the remote server returns a 404 const to = 'http://localhost:' + servers[1].port + '/accounts/user2' - await setActorField(servers[1].internalServerNumber, to, 'preferredUsername', 'toto') + await servers[1].sqlCommand.setActorField(to, 'preferredUsername', 'toto') await command.get({ accountName: 'user1@localhost:' + servers[1].port }) await command.get({ accountName: 'user2@localhost:' + servers[1].port }) @@ -140,7 +136,7 @@ describe('Test AP refresher', function () { await wait(10000) // Change UUID so the remote server returns a 404 - await setPlaylistField(servers[1].internalServerNumber, playlistUUID2, 'uuid', '304afe4f-39f9-4d49-8ed7-ac57b86b178e') + await servers[1].sqlCommand.setPlaylistField(playlistUUID2, 'uuid', '304afe4f-39f9-4d49-8ed7-ac57b86b178e') await servers[0].playlistsCommand.get({ playlistId: playlistUUID1 }) await servers[0].playlistsCommand.get({ playlistId: playlistUUID2 }) @@ -156,7 +152,5 @@ describe('Test AP refresher', function () { this.timeout(10000) await cleanupTests(servers) - - await closeAllSequelize(servers) }) }) diff --git a/server/tests/api/activitypub/security.ts b/server/tests/api/activitypub/security.ts index 61db272f6..c32940070 100644 --- a/server/tests/api/activitypub/security.ts +++ b/server/tests/api/activitypub/security.ts @@ -7,12 +7,10 @@ import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-c import { buildAbsoluteFixturePath, cleanupTests, - closeAllSequelize, flushAndRunMultipleServers, killallServers, reRunServer, ServerInfo, - setActorField, wait } from '../../../../shared/extra-utils' import { makeFollowRequest, makePOSTAPRequest } from '../../../../shared/extra-utils/requests/activitypub' @@ -26,8 +24,8 @@ function setKeysOfServer (onServer: ServerInfo, ofServer: ServerInfo, publicKey: const url = 'http://localhost:' + ofServer.port + '/accounts/peertube' return Promise.all([ - setActorField(onServer.internalServerNumber, url, 'publicKey', publicKey), - setActorField(onServer.internalServerNumber, url, 'privateKey', privateKey) + onServer.sqlCommand.setActorField(url, 'publicKey', publicKey), + onServer.sqlCommand.setActorField(url, 'privateKey', privateKey) ]) } @@ -35,8 +33,8 @@ function setUpdatedAtOfServer (onServer: ServerInfo, ofServer: ServerInfo, updat const url = 'http://localhost:' + ofServer.port + '/accounts/peertube' return Promise.all([ - setActorField(onServer.internalServerNumber, url, 'createdAt', updatedAt), - setActorField(onServer.internalServerNumber, url, 'updatedAt', updatedAt) + onServer.sqlCommand.setActorField(url, 'createdAt', updatedAt), + onServer.sqlCommand.setActorField(url, 'updatedAt', updatedAt) ]) } @@ -173,7 +171,7 @@ describe('Test ActivityPub security', function () { await setUpdatedAtOfServer(servers[0], servers[1], '2015-07-17 22:00:00+00') // Invalid peertube actor cache - killallServers([ servers[1] ]) + await killallServers([ servers[1] ]) await reRunServer(servers[1]) const body = activityPubContextify(getAnnounceWithoutContext(servers[1])) @@ -294,7 +292,5 @@ describe('Test ActivityPub security', function () { this.timeout(10000) await cleanupTests(servers) - - await closeAllSequelize(servers) }) }) diff --git a/server/tests/api/check-params/contact-form.ts b/server/tests/api/check-params/contact-form.ts index fb30766d9..5539266b8 100644 --- a/server/tests/api/check-params/contact-form.ts +++ b/server/tests/api/check-params/contact-form.ts @@ -36,7 +36,7 @@ describe('Test contact form API validators', function () { it('Should not accept a contact form if it is disabled in the configuration', async function () { this.timeout(10000) - killallServers([ server ]) + await killallServers([ server ]) // Contact form is disabled await reRunServer(server, { smtp: { hostname: 'localhost', port: emailPort }, contact_form: { enabled: false } }) @@ -46,7 +46,7 @@ describe('Test contact form API validators', function () { it('Should not accept a contact form if from email is invalid', async function () { this.timeout(10000) - killallServers([ server ]) + await killallServers([ server ]) // Email & contact form enabled await reRunServer(server, { smtp: { hostname: 'localhost', port: emailPort } }) diff --git a/server/tests/api/check-params/users.ts b/server/tests/api/check-params/users.ts index 88fc8e8b1..bffe29bce 100644 --- a/server/tests/api/check-params/users.ts +++ b/server/tests/api/check-params/users.ts @@ -237,7 +237,7 @@ describe('Test users API validators', function () { it('Should succeed with no password on a server with smtp enabled', async function () { this.timeout(20000) - killallServers([ server ]) + await killallServers([ server ]) const config = immutableAssign(overrideConfig, { smtp: { diff --git a/server/tests/api/live/live.ts b/server/tests/api/live/live.ts index 0b06df44c..f9a162df6 100644 --- a/server/tests/api/live/live.ts +++ b/server/tests/api/live/live.ts @@ -587,7 +587,7 @@ describe('Test live', function () { await commands[0].waitUntilSegmentGeneration({ videoUUID: liveVideoId, resolution: 0, segment: 2 }) await commands[0].waitUntilSegmentGeneration({ videoUUID: liveVideoReplayId, resolution: 0, segment: 2 }) - killallServers([ servers[0] ]) + await killallServers([ servers[0] ]) await reRunServer(servers[0]) await wait(5000) diff --git a/server/tests/api/moderation/video-blacklist.ts b/server/tests/api/moderation/video-blacklist.ts index c72ebc16b..8b4723a2b 100644 --- a/server/tests/api/moderation/video-blacklist.ts +++ b/server/tests/api/moderation/video-blacklist.ts @@ -342,7 +342,7 @@ describe('Test video blacklist', function () { before(async function () { this.timeout(20000) - killallServers([ servers[0] ]) + await killallServers([ servers[0] ]) const config = { auto_blacklist: { diff --git a/server/tests/api/notifications/admin-notifications.ts b/server/tests/api/notifications/admin-notifications.ts index da9767b74..03fbe0b70 100644 --- a/server/tests/api/notifications/admin-notifications.ts +++ b/server/tests/api/notifications/admin-notifications.ts @@ -11,8 +11,6 @@ import { MockSmtpServer, prepareNotificationsTest, ServerInfo, - setPluginLatestVersion, - setPluginVersion, wait } from '@shared/extra-utils' import { PluginType, UserNotification, UserNotificationType } from '@shared/models' @@ -120,8 +118,8 @@ describe('Test admin notifications', function () { it('Should send a notification to admins on new plugin version', async function () { this.timeout(30000) - await setPluginVersion(server.internalServerNumber, 'hello-world', '0.0.1') - await setPluginLatestVersion(server.internalServerNumber, 'hello-world', '0.0.1') + await server.sqlCommand.setPluginVersion('hello-world', '0.0.1') + await server.sqlCommand.setPluginLatestVersion('hello-world', '0.0.1') await wait(6000) await checkNewPluginVersion(baseParams, PluginType.PLUGIN, 'hello-world', 'presence') @@ -142,8 +140,8 @@ describe('Test admin notifications', function () { it('Should send a new notification after a new plugin release', async function () { this.timeout(30000) - await setPluginVersion(server.internalServerNumber, 'hello-world', '0.0.1') - await setPluginLatestVersion(server.internalServerNumber, 'hello-world', '0.0.1') + await server.sqlCommand.setPluginVersion('hello-world', '0.0.1') + await server.sqlCommand.setPluginLatestVersion('hello-world', '0.0.1') await wait(6000) expect(adminNotifications.filter(n => n.type === UserNotificationType.NEW_PEERTUBE_VERSION)).to.have.lengthOf(2) diff --git a/server/tests/api/redundancy/redundancy-constraints.ts b/server/tests/api/redundancy/redundancy-constraints.ts index 500b96747..82d952471 100644 --- a/server/tests/api/redundancy/redundancy-constraints.ts +++ b/server/tests/api/redundancy/redundancy-constraints.ts @@ -121,7 +121,7 @@ describe('Test redundancy constraints', function () { } } } - await killallServers([ localServer ]) + await await killallServers([ localServer ]) await reRunServer(localServer, config) await uploadWrapper('video 2 server 2') @@ -150,7 +150,7 @@ describe('Test redundancy constraints', function () { } } } - killallServers([ localServer ]) + await killallServers([ localServer ]) await reRunServer(localServer, config) await uploadWrapper('video 3 server 2') diff --git a/server/tests/api/redundancy/redundancy.ts b/server/tests/api/redundancy/redundancy.ts index d20cb80f1..56a2af395 100644 --- a/server/tests/api/redundancy/redundancy.ts +++ b/server/tests/api/redundancy/redundancy.ts @@ -634,7 +634,7 @@ describe('Test videos redundancy', function () { it('Should stop server 1 and expire video redundancy', async function () { this.timeout(80000) - killallServers([ servers[0] ]) + await killallServers([ servers[0] ]) await wait(15000) @@ -703,7 +703,7 @@ describe('Test videos redundancy', function () { await waitJobs(servers) - killallServers([ servers[0] ]) + await killallServers([ servers[0] ]) await reRunServer(servers[0], { redundancy: { videos: { diff --git a/server/tests/api/server/config.ts b/server/tests/api/server/config.ts index 037628c9d..55cf2a1b8 100644 --- a/server/tests/api/server/config.ts +++ b/server/tests/api/server/config.ts @@ -456,7 +456,7 @@ describe('Test config', function () { it('Should have the configuration updated after a restart', async function () { this.timeout(10000) - killallServers([ server ]) + await killallServers([ server ]) await reRunServer(server) @@ -507,7 +507,7 @@ describe('Test config', function () { expect(res.headers['x-frame-options']).to.exist } - killallServers([ server ]) + await killallServers([ server ]) const config = { security: { diff --git a/server/tests/api/server/handle-down.ts b/server/tests/api/server/handle-down.ts index 94496a159..dd06acb5e 100644 --- a/server/tests/api/server/handle-down.ts +++ b/server/tests/api/server/handle-down.ts @@ -5,7 +5,6 @@ import * as chai from 'chai' import { HttpStatusCode } from '@shared/core-utils' import { cleanupTests, - closeAllSequelize, CommentsCommand, completeVideoCheck, flushAndRunMultipleServers, @@ -16,7 +15,6 @@ import { reRunServer, ServerInfo, setAccessTokensToServers, - setActorFollowScores, updateVideo, uploadVideo, uploadVideoAndGetId, @@ -129,7 +127,7 @@ describe('Test handle downs', function () { } // Kill server 2 - killallServers([ servers[1] ]) + await killallServers([ servers[1] ]) // Remove server 2 follower for (let i = 0; i < 10; i++) { @@ -139,7 +137,7 @@ describe('Test handle downs', function () { await waitJobs([ servers[0], servers[2] ]) // Kill server 3 - killallServers([ servers[2] ]) + await killallServers([ servers[2] ]) const resLastVideo1 = await uploadVideo(servers[0].url, servers[0].accessToken, videoAttributes) missedVideo1 = resLastVideo1.body.video @@ -311,7 +309,7 @@ describe('Test handle downs', function () { } await waitJobs(servers) - await setActorFollowScores(servers[1].internalServerNumber, 20) + await servers[1].sqlCommand.setActorFollowScores(20) // Wait video expiration await wait(11000) @@ -325,7 +323,7 @@ describe('Test handle downs', function () { it('Should remove followings that are down', async function () { this.timeout(120000) - killallServers([ servers[0] ]) + await killallServers([ servers[0] ]) // Wait video expiration await wait(11000) @@ -344,8 +342,6 @@ describe('Test handle downs', function () { }) after(async function () { - await closeAllSequelize([ servers[1] ]) - await cleanupTests(servers) }) }) diff --git a/server/tests/api/server/homepage.ts b/server/tests/api/server/homepage.ts index c08067f3c..18b9edc31 100644 --- a/server/tests/api/server/homepage.ts +++ b/server/tests/api/server/homepage.ts @@ -54,7 +54,7 @@ describe('Test instance homepage actions', function () { it('Should have the same homepage after a restart', async function () { this.timeout(30000) - killallServers([ server ]) + await killallServers([ server ]) await reRunServer(server) diff --git a/server/tests/api/server/logs.ts b/server/tests/api/server/logs.ts index ab83a329f..365f6cc2b 100644 --- a/server/tests/api/server/logs.ts +++ b/server/tests/api/server/logs.ts @@ -113,7 +113,7 @@ describe('Test logs', function () { it('Should not log ping requests', async function () { this.timeout(30000) - killallServers([ server ]) + await killallServers([ server ]) await reRunServer(server, { log: { log_ping_requests: false } }) diff --git a/server/tests/api/server/plugins.ts b/server/tests/api/server/plugins.ts index e22ecfad9..655cf00fa 100644 --- a/server/tests/api/server/plugins.ts +++ b/server/tests/api/server/plugins.ts @@ -5,7 +5,6 @@ import * as chai from 'chai' import { HttpStatusCode } from '@shared/core-utils' import { cleanupTests, - closeAllSequelize, flushAndRunServer, getMyUserInformation, killallServers, @@ -13,7 +12,6 @@ import { reRunServer, ServerInfo, setAccessTokensToServers, - setPluginVersion, testHelloWorldRegisteredSettings, updateMyUser, wait, @@ -244,7 +242,7 @@ describe('Test plugins', function () { await wait(6000) // Fake update our plugin version - await setPluginVersion(server.internalServerNumber, 'hello-world', '0.0.1') + await server.sqlCommand.setPluginVersion('hello-world', '0.0.1') // Fake update package.json const packageJSON = await command.getPackageJSON('peertube-plugin-hello-world') @@ -254,7 +252,7 @@ describe('Test plugins', function () { await command.updatePackageJSON('peertube-plugin-hello-world', packageJSON) // Restart the server to take into account this change - killallServers([ server ]) + await killallServers([ server ]) await reRunServer(server) { @@ -335,14 +333,13 @@ describe('Test plugins', function () { await check() - killallServers([ server ]) + await killallServers([ server ]) await reRunServer(server) await check() }) after(async function () { - await closeAllSequelize([ server ]) await cleanupTests([ server ]) }) }) diff --git a/server/tests/api/server/tracker.ts b/server/tests/api/server/tracker.ts index 4b86e0b90..868dc8977 100644 --- a/server/tests/api/server/tracker.ts +++ b/server/tests/api/server/tracker.ts @@ -61,8 +61,7 @@ describe('Test tracker', function () { const errCb = () => done(new Error('Tracker is enabled')) killallServers([ server ]) - - reRunServer(server, { tracker: { enabled: false } }) + .then(() => reRunServer(server, { tracker: { enabled: false } })) .then(() => { const webtorrent = new WebTorrent() @@ -86,8 +85,7 @@ describe('Test tracker', function () { this.timeout(20000) killallServers([ server ]) - - reRunServer(server) + .then(() => reRunServer(server)) .then(() => { const webtorrent = new WebTorrent() diff --git a/server/tests/api/users/users.ts b/server/tests/api/users/users.ts index 4d255f340..69a8dba34 100644 --- a/server/tests/api/users/users.ts +++ b/server/tests/api/users/users.ts @@ -6,7 +6,6 @@ import { HttpStatusCode } from '@shared/core-utils' import { blockUser, cleanupTests, - closeAllSequelize, createUser, deleteMe, flushAndRunServer, @@ -30,7 +29,6 @@ import { reRunServer, ServerInfo, setAccessTokensToServers, - setTokenField, testImage, unblockUser, updateMyAvatar, @@ -264,10 +262,10 @@ describe('Test users', function () { it('Should have an expired access token', async function () { this.timeout(15000) - await setTokenField(server.internalServerNumber, server.accessToken, 'accessTokenExpiresAt', new Date().toISOString()) - await setTokenField(server.internalServerNumber, server.accessToken, 'refreshTokenExpiresAt', new Date().toISOString()) + await server.sqlCommand.setTokenField(server.accessToken, 'accessTokenExpiresAt', new Date().toISOString()) + await server.sqlCommand.setTokenField(server.accessToken, 'refreshTokenExpiresAt', new Date().toISOString()) - killallServers([ server ]) + await killallServers([ server ]) await reRunServer(server) await getMyUserInformation(server.url, server.accessToken, 401) @@ -281,9 +279,9 @@ describe('Test users', function () { this.timeout(15000) const futureDate = new Date(new Date().getTime() + 1000 * 60).toISOString() - await setTokenField(server.internalServerNumber, server.accessToken, 'refreshTokenExpiresAt', futureDate) + await server.sqlCommand.setTokenField(server.accessToken, 'refreshTokenExpiresAt', futureDate) - killallServers([ server ]) + await killallServers([ server ]) await reRunServer(server) const res = await refreshToken(server, server.refreshToken) @@ -1013,7 +1011,6 @@ describe('Test users', function () { }) after(async function () { - await closeAllSequelize([ server ]) await cleanupTests([ server ]) }) }) diff --git a/server/tests/api/videos/video-channels.ts b/server/tests/api/videos/video-channels.ts index daf066eb1..e441ebbd4 100644 --- a/server/tests/api/videos/video-channels.ts +++ b/server/tests/api/videos/video-channels.ts @@ -9,7 +9,6 @@ import { createUser, doubleFollow, flushAndRunMultipleServers, - getActorImage, getVideo, getVideoChannelVideos, setDefaultVideoChannel, @@ -268,7 +267,7 @@ describe('Test video channels', function () { await testImage(server.url, 'avatar-resized', avatarPaths[server.port], '.png') await testFileExistsOrNot(server, 'avatars', basename(avatarPaths[server.port]), true) - const row = await getActorImage(server.internalServerNumber, basename(avatarPaths[server.port])) + const row = await server.sqlCommand.getActorImage(basename(avatarPaths[server.port])) expect(row.height).to.equal(ACTOR_IMAGES_SIZE.AVATARS.height) expect(row.width).to.equal(ACTOR_IMAGES_SIZE.AVATARS.width) } @@ -294,7 +293,7 @@ describe('Test video channels', function () { await testImage(server.url, 'banner-resized', bannerPaths[server.port]) await testFileExistsOrNot(server, 'avatars', basename(bannerPaths[server.port]), true) - const row = await getActorImage(server.internalServerNumber, basename(bannerPaths[server.port])) + const row = await server.sqlCommand.getActorImage(basename(bannerPaths[server.port])) expect(row.height).to.equal(ACTOR_IMAGES_SIZE.BANNERS.height) expect(row.width).to.equal(ACTOR_IMAGES_SIZE.BANNERS.width) } diff --git a/server/tests/api/videos/videos-history.ts b/server/tests/api/videos/videos-history.ts index 731447135..9a7635c35 100644 --- a/server/tests/api/videos/videos-history.ts +++ b/server/tests/api/videos/videos-history.ts @@ -204,7 +204,7 @@ describe('Test videos history', function () { it('Should not clean old history', async function () { this.timeout(50000) - killallServers([ server ]) + await killallServers([ server ]) await reRunServer(server, { history: { videos: { max_age: '10 days' } } }) @@ -219,7 +219,7 @@ describe('Test videos history', function () { it('Should clean old history', async function () { this.timeout(50000) - killallServers([ server ]) + await killallServers([ server ]) await reRunServer(server, { history: { videos: { max_age: '5 seconds' } } }) diff --git a/server/tests/api/videos/videos-views-cleaner.ts b/server/tests/api/videos/videos-views-cleaner.ts index b89f33217..b6cde6b50 100644 --- a/server/tests/api/videos/videos-views-cleaner.ts +++ b/server/tests/api/videos/videos-views-cleaner.ts @@ -1,11 +1,9 @@ /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */ -import * as chai from 'chai' import 'mocha' +import * as chai from 'chai' import { cleanupTests, - closeAllSequelize, - countVideoViewsOf, doubleFollow, flushAndRunMultipleServers, killallServers, @@ -50,7 +48,7 @@ describe('Test video views cleaner', function () { it('Should not clean old video views', async function () { this.timeout(50000) - killallServers([ servers[0] ]) + await killallServers([ servers[0] ]) await reRunServer(servers[0], { views: { videos: { remote: { max_age: '10 days' } } } }) @@ -60,14 +58,14 @@ describe('Test video views cleaner', function () { { for (const server of servers) { - const total = await countVideoViewsOf(server.internalServerNumber, videoIdServer1) + const total = await server.sqlCommand.countVideoViewsOf(videoIdServer1) expect(total).to.equal(2, 'Server ' + server.serverNumber + ' does not have the correct amount of views') } } { for (const server of servers) { - const total = await countVideoViewsOf(server.internalServerNumber, videoIdServer2) + const total = await server.sqlCommand.countVideoViewsOf(videoIdServer2) expect(total).to.equal(2, 'Server ' + server.serverNumber + ' does not have the correct amount of views') } } @@ -76,7 +74,7 @@ describe('Test video views cleaner', function () { it('Should clean old video views', async function () { this.timeout(50000) - killallServers([ servers[0] ]) + await killallServers([ servers[0] ]) await reRunServer(servers[0], { views: { videos: { remote: { max_age: '5 seconds' } } } }) @@ -86,23 +84,21 @@ describe('Test video views cleaner', function () { { for (const server of servers) { - const total = await countVideoViewsOf(server.internalServerNumber, videoIdServer1) + const total = await server.sqlCommand.countVideoViewsOf(videoIdServer1) expect(total).to.equal(2) } } { - const totalServer1 = await countVideoViewsOf(servers[0].internalServerNumber, videoIdServer2) + const totalServer1 = await servers[0].sqlCommand.countVideoViewsOf(videoIdServer2) expect(totalServer1).to.equal(0) - const totalServer2 = await countVideoViewsOf(servers[1].internalServerNumber, videoIdServer2) + const totalServer2 = await servers[1].sqlCommand.countVideoViewsOf(videoIdServer2) expect(totalServer2).to.equal(2) } }) after(async function () { - await closeAllSequelize(servers) - await cleanupTests(servers) }) }) diff --git a/server/tests/cli/plugins.ts b/server/tests/cli/plugins.ts index e5efae36b..5344bfc96 100644 --- a/server/tests/cli/plugins.ts +++ b/server/tests/cli/plugins.ts @@ -39,7 +39,7 @@ describe('Test plugin scripts', function () { it('Should have the theme and the plugin registered when we restart peertube', async function () { this.timeout(30000) - killallServers([ server ]) + await killallServers([ server ]) await reRunServer(server) const config = await server.configCommand.getConfig() @@ -62,7 +62,7 @@ describe('Test plugin scripts', function () { it('Should have removed the plugin on another peertube restart', async function () { this.timeout(30000) - killallServers([ server ]) + await killallServers([ server ]) await reRunServer(server) const config = await server.configCommand.getConfig() diff --git a/server/tests/cli/prune-storage.ts b/server/tests/cli/prune-storage.ts index fa1df65a9..d4dbee682 100644 --- a/server/tests/cli/prune-storage.ts +++ b/server/tests/cli/prune-storage.ts @@ -110,7 +110,7 @@ describe('Test prune storage scripts', function () { await wait(1000) await waitJobs(servers) - killallServers(servers) + await killallServers(servers) await wait(1000) }) diff --git a/server/tests/cli/update-host.ts b/server/tests/cli/update-host.ts index d3a1520cf..e986a04f2 100644 --- a/server/tests/cli/update-host.ts +++ b/server/tests/cli/update-host.ts @@ -61,7 +61,7 @@ describe('Test update host scripts', function () { it('Should run update host', async function () { this.timeout(30000) - killallServers([ server ]) + await killallServers([ server ]) // Run server with standard configuration await reRunServer(server) diff --git a/server/tests/external-plugins/auto-block-videos.ts b/server/tests/external-plugins/auto-block-videos.ts index 6659b6f39..f4b55522a 100644 --- a/server/tests/external-plugins/auto-block-videos.ts +++ b/server/tests/external-plugins/auto-block-videos.ts @@ -164,7 +164,7 @@ describe('Official plugin auto-block videos', function () { await check(servers[0], video.uuid, true) - killallServers([ servers[0] ]) + await killallServers([ servers[0] ]) await reRunServer(servers[0]) await wait(2000) diff --git a/server/tests/external-plugins/auto-mute.ts b/server/tests/external-plugins/auto-mute.ts index f86c83808..844023b83 100644 --- a/server/tests/external-plugins/auto-mute.ts +++ b/server/tests/external-plugins/auto-mute.ts @@ -151,7 +151,7 @@ describe('Official plugin auto-mute', function () { expect(res.body.total).to.equal(2) } - killallServers([ servers[0] ]) + await killallServers([ servers[0] ]) await reRunServer(servers[0]) await wait(2000) diff --git a/server/tests/plugins/action-hooks.ts b/server/tests/plugins/action-hooks.ts index 6975ca4bb..bcf773854 100644 --- a/server/tests/plugins/action-hooks.ts +++ b/server/tests/plugins/action-hooks.ts @@ -44,7 +44,7 @@ describe('Test plugin action hooks', function () { await servers[0].pluginsCommand.install({ path: PluginsCommand.getPluginTestPath() }) - killallServers([ servers[0] ]) + await killallServers([ servers[0] ]) await reRunServer(servers[0], { live: { diff --git a/server/tools/test-live.ts b/server/tools/test-live.ts index 76fd69435..3c6a67cf7 100644 --- a/server/tools/test-live.ts +++ b/server/tools/test-live.ts @@ -40,7 +40,7 @@ async function run () { const cleanup = () => { console.log('Killing server') - killallServers([ server ]) + await killallServers([ server ]) } process.on('exit', cleanup) diff --git a/shared/extra-utils/miscs/index.ts b/shared/extra-utils/miscs/index.ts index ccacd4c79..7e236c329 100644 --- a/shared/extra-utils/miscs/index.ts +++ b/shared/extra-utils/miscs/index.ts @@ -1,3 +1,3 @@ export * from './miscs' -export * from './sql' +export * from './sql-command' export * from './stubs' diff --git a/shared/extra-utils/miscs/sql-command.ts b/shared/extra-utils/miscs/sql-command.ts new file mode 100644 index 000000000..2a3e9e607 --- /dev/null +++ b/shared/extra-utils/miscs/sql-command.ts @@ -0,0 +1,142 @@ +import { QueryTypes, Sequelize } from 'sequelize' +import { AbstractCommand } from '../shared' + +export class SQLCommand extends AbstractCommand { + private sequelize: Sequelize + + deleteAll (table: string) { + const seq = this.getSequelize() + + const options = { type: QueryTypes.DELETE } + + return seq.query(`DELETE FROM "${table}"`, options) + } + + async getCount (table: string) { + const seq = this.getSequelize() + + const options = { type: QueryTypes.SELECT as QueryTypes.SELECT } + + const [ { total } ] = await seq.query<{ total: string }>(`SELECT COUNT(*) as total FROM "${table}"`, options) + if (total === null) return 0 + + return parseInt(total, 10) + } + + setActorField (to: string, field: string, value: string) { + const seq = this.getSequelize() + + const options = { type: QueryTypes.UPDATE } + + return seq.query(`UPDATE actor SET "${field}" = '${value}' WHERE url = '${to}'`, options) + } + + setVideoField (uuid: string, field: string, value: string) { + const seq = this.getSequelize() + + const options = { type: QueryTypes.UPDATE } + + return seq.query(`UPDATE video SET "${field}" = '${value}' WHERE uuid = '${uuid}'`, options) + } + + setPlaylistField (uuid: string, field: string, value: string) { + const seq = this.getSequelize() + + const options = { type: QueryTypes.UPDATE } + + return seq.query(`UPDATE "videoPlaylist" SET "${field}" = '${value}' WHERE uuid = '${uuid}'`, options) + } + + async countVideoViewsOf (uuid: string) { + const seq = this.getSequelize() + + // tslint:disable + const query = 'SELECT SUM("videoView"."views") AS "total" FROM "videoView" ' + + `INNER JOIN "video" ON "video"."id" = "videoView"."videoId" WHERE "video"."uuid" = '${uuid}'` + + const options = { type: QueryTypes.SELECT as QueryTypes.SELECT } + const [ { total } ] = await seq.query<{ total: number }>(query, options) + + if (!total) return 0 + + return parseInt(total + '', 10) + } + + getActorImage (filename: string) { + return this.selectQuery(`SELECT * FROM "actorImage" WHERE filename = '${filename}'`) + .then(rows => rows[0]) + } + + selectQuery (query: string) { + const seq = this.getSequelize() + const options = { type: QueryTypes.SELECT as QueryTypes.SELECT } + + return seq.query(query, options) + } + + updateQuery (query: string) { + const seq = this.getSequelize() + const options = { type: QueryTypes.UPDATE as QueryTypes.UPDATE } + + return seq.query(query, options) + } + + setPluginField (pluginName: string, field: string, value: string) { + const seq = this.getSequelize() + + const options = { type: QueryTypes.UPDATE } + + return seq.query(`UPDATE "plugin" SET "${field}" = '${value}' WHERE "name" = '${pluginName}'`, options) + } + + setPluginVersion (pluginName: string, newVersion: string) { + return this.setPluginField(pluginName, 'version', newVersion) + } + + setPluginLatestVersion (pluginName: string, newVersion: string) { + return this.setPluginField(pluginName, 'latestVersion', newVersion) + } + + setActorFollowScores (newScore: number) { + const seq = this.getSequelize() + + const options = { type: QueryTypes.UPDATE } + + return seq.query(`UPDATE "actorFollow" SET "score" = ${newScore}`, options) + } + + setTokenField (accessToken: string, field: string, value: string) { + const seq = this.getSequelize() + + const options = { type: QueryTypes.UPDATE } + + return seq.query(`UPDATE "oAuthToken" SET "${field}" = '${value}' WHERE "accessToken" = '${accessToken}'`, options) + } + + async cleanup () { + if (!this.sequelize) return + + await this.sequelize.close() + this.sequelize = undefined + } + + private getSequelize () { + if (this.sequelize) return this.sequelize + + const dbname = 'peertube_test' + this.server.internalServerNumber + const username = 'peertube' + const password = 'peertube' + const host = 'localhost' + const port = 5432 + + this.sequelize = new Sequelize(dbname, username, password, { + dialect: 'postgres', + host, + port, + logging: false + }) + + return this.sequelize + } + +} diff --git a/shared/extra-utils/miscs/sql.ts b/shared/extra-utils/miscs/sql.ts deleted file mode 100644 index 65a0aa5fe..000000000 --- a/shared/extra-utils/miscs/sql.ts +++ /dev/null @@ -1,161 +0,0 @@ -import { QueryTypes, Sequelize } from 'sequelize' -import { ServerInfo } from '../server/servers' - -const sequelizes: { [ id: number ]: Sequelize } = {} - -function getSequelize (internalServerNumber: number) { - if (sequelizes[internalServerNumber]) return sequelizes[internalServerNumber] - - const dbname = 'peertube_test' + internalServerNumber - const username = 'peertube' - const password = 'peertube' - const host = 'localhost' - const port = 5432 - - const seq = new Sequelize(dbname, username, password, { - dialect: 'postgres', - host, - port, - logging: false - }) - - sequelizes[internalServerNumber] = seq - - return seq -} - -function deleteAll (internalServerNumber: number, table: string) { - const seq = getSequelize(internalServerNumber) - - const options = { type: QueryTypes.DELETE } - - return seq.query(`DELETE FROM "${table}"`, options) -} - -async function getCount (internalServerNumber: number, table: string) { - const seq = getSequelize(internalServerNumber) - - const options = { type: QueryTypes.SELECT as QueryTypes.SELECT } - - const [ { total } ] = await seq.query<{ total: string }>(`SELECT COUNT(*) as total FROM "${table}"`, options) - if (total === null) return 0 - - return parseInt(total, 10) -} - -function setActorField (internalServerNumber: number, to: string, field: string, value: string) { - const seq = getSequelize(internalServerNumber) - - const options = { type: QueryTypes.UPDATE } - - return seq.query(`UPDATE actor SET "${field}" = '${value}' WHERE url = '${to}'`, options) -} - -function setVideoField (internalServerNumber: number, uuid: string, field: string, value: string) { - const seq = getSequelize(internalServerNumber) - - const options = { type: QueryTypes.UPDATE } - - return seq.query(`UPDATE video SET "${field}" = '${value}' WHERE uuid = '${uuid}'`, options) -} - -function setPlaylistField (internalServerNumber: number, uuid: string, field: string, value: string) { - const seq = getSequelize(internalServerNumber) - - const options = { type: QueryTypes.UPDATE } - - return seq.query(`UPDATE "videoPlaylist" SET "${field}" = '${value}' WHERE uuid = '${uuid}'`, options) -} - -async function countVideoViewsOf (internalServerNumber: number, uuid: string) { - const seq = getSequelize(internalServerNumber) - - // tslint:disable - const query = 'SELECT SUM("videoView"."views") AS "total" FROM "videoView" ' + - `INNER JOIN "video" ON "video"."id" = "videoView"."videoId" WHERE "video"."uuid" = '${uuid}'` - - const options = { type: QueryTypes.SELECT as QueryTypes.SELECT } - const [ { total } ] = await seq.query<{ total: number }>(query, options) - - if (!total) return 0 - - return parseInt(total + '', 10) -} - -function getActorImage (internalServerNumber: number, filename: string) { - return selectQuery(internalServerNumber, `SELECT * FROM "actorImage" WHERE filename = '${filename}'`) - .then(rows => rows[0]) -} - -function selectQuery (internalServerNumber: number, query: string) { - const seq = getSequelize(internalServerNumber) - const options = { type: QueryTypes.SELECT as QueryTypes.SELECT } - - return seq.query(query, options) -} - -function updateQuery (internalServerNumber: number, query: string) { - const seq = getSequelize(internalServerNumber) - const options = { type: QueryTypes.UPDATE as QueryTypes.UPDATE } - - return seq.query(query, options) -} - -async function closeAllSequelize (servers: ServerInfo[]) { - for (const server of servers) { - if (sequelizes[server.internalServerNumber]) { - await sequelizes[server.internalServerNumber].close() - // eslint-disable-next-line - delete sequelizes[server.internalServerNumber] - } - } -} - -function setPluginField (internalServerNumber: number, pluginName: string, field: string, value: string) { - const seq = getSequelize(internalServerNumber) - - const options = { type: QueryTypes.UPDATE } - - return seq.query(`UPDATE "plugin" SET "${field}" = '${value}' WHERE "name" = '${pluginName}'`, options) -} - -function setPluginVersion (internalServerNumber: number, pluginName: string, newVersion: string) { - return setPluginField(internalServerNumber, pluginName, 'version', newVersion) -} - -function setPluginLatestVersion (internalServerNumber: number, pluginName: string, newVersion: string) { - return setPluginField(internalServerNumber, pluginName, 'latestVersion', newVersion) -} - -function setActorFollowScores (internalServerNumber: number, newScore: number) { - const seq = getSequelize(internalServerNumber) - - const options = { type: QueryTypes.UPDATE } - - return seq.query(`UPDATE "actorFollow" SET "score" = ${newScore}`, options) -} - -function setTokenField (internalServerNumber: number, accessToken: string, field: string, value: string) { - const seq = getSequelize(internalServerNumber) - - const options = { type: QueryTypes.UPDATE } - - return seq.query(`UPDATE "oAuthToken" SET "${field}" = '${value}' WHERE "accessToken" = '${accessToken}'`, options) -} - -export { - setVideoField, - setPlaylistField, - setActorField, - countVideoViewsOf, - setPluginVersion, - setPluginLatestVersion, - selectQuery, - getActorImage, - deleteAll, - setTokenField, - updateQuery, - setActorFollowScores, - closeAllSequelize, - getCount -} diff --git a/shared/extra-utils/miscs/stubs.ts b/shared/extra-utils/miscs/stubs.ts index d1eb0e3b2..940e4bf29 100644 --- a/shared/extra-utils/miscs/stubs.ts +++ b/shared/extra-utils/miscs/stubs.ts @@ -2,13 +2,6 @@ function buildRequestStub (): any { return { } } -function buildResponseStub (): any { - return { - locals: {} - } -} - export { - buildResponseStub, buildRequestStub } diff --git a/shared/extra-utils/server/servers.ts b/shared/extra-utils/server/servers.ts index 41b48a8ee..bd3be8373 100644 --- a/shared/extra-utils/server/servers.ts +++ b/shared/extra-utils/server/servers.ts @@ -30,6 +30,7 @@ import { ServicesCommand, StreamingPlaylistsCommand } from '../videos' +import { SQLCommand } from '../miscs' import { CommentsCommand } from '../videos/comments-command' import { ConfigCommand } from './config-command' import { ContactFormCommand } from './contact-form-command' @@ -123,6 +124,7 @@ interface ServerInfo { streamingPlaylistsCommand?: StreamingPlaylistsCommand channelsCommand?: ChannelsCommand commentsCommand?: CommentsCommand + sqlCommand?: SQLCommand } function parallelTests () { @@ -367,6 +369,7 @@ function assignCommands (server: ServerInfo) { server.streamingPlaylistsCommand = new StreamingPlaylistsCommand(server) server.channelsCommand = new ChannelsCommand(server) server.commentsCommand = new CommentsCommand(server) + server.sqlCommand = new SQLCommand(server) } async function reRunServer (server: ServerInfo, configOverride?: any) { @@ -398,17 +401,20 @@ async function checkDirectoryIsEmpty (server: ServerInfo, directory: string, exc expect(filtered).to.have.lengthOf(0) } -function killallServers (servers: ServerInfo[]) { +async function killallServers (servers: ServerInfo[]) { for (const server of servers) { if (!server.app) continue + await server.sqlCommand.cleanup() + process.kill(-server.app.pid) + server.app = null } } async function cleanupTests (servers: ServerInfo[]) { - killallServers(servers) + await killallServers(servers) if (isGithubCI()) { await ensureDir('artifacts') diff --git a/shared/extra-utils/shared/abstract-command.ts b/shared/extra-utils/shared/abstract-command.ts index 6a9ab1348..200db90d4 100644 --- a/shared/extra-utils/shared/abstract-command.ts +++ b/shared/extra-utils/shared/abstract-command.ts @@ -1,6 +1,6 @@ import { isAbsolute, join } from 'path' import { HttpStatusCode } from '@shared/core-utils' -import { root } from '../miscs' +import { root } from '../miscs/miscs' import { makeDeleteRequest, makeGetRequest, -- cgit v1.2.3