mirror of
https://github.com/ajayyy/SponsorBlockServer.git
synced 2025-12-08 04:27:09 +03:00
test fixes
test fixes - fix timeout in redis (by @ajayyy) - allow "errors" in tempVIP test - remove duplicate warning in postSkipSegments - remove duplicate VIP in tempVIP - run tests against different user once tempVIP removed - fix typo in getHashCache fetching syntax and wording - use standard syntax in redisTest - fix spacing in getLockReason - typo in npm script name test cases - add getHashCache test case - add more tests to redisTest configuration - update config to use redis timeout - update docker-compose to use newest pinned version Co-Authored-By: Ajay Ramachandran <dev@ajay.app>
This commit is contained in:
4
ci.json
4
ci.json
@@ -17,10 +17,12 @@
|
|||||||
"port": 5432
|
"port": 5432
|
||||||
},
|
},
|
||||||
"redis": {
|
"redis": {
|
||||||
|
"enabled": true,
|
||||||
"socket": {
|
"socket": {
|
||||||
"host": "localhost",
|
"host": "localhost",
|
||||||
"port": 6379
|
"port": 6379
|
||||||
}
|
},
|
||||||
|
"expiryTime": 86400
|
||||||
},
|
},
|
||||||
"createDatabaseIfNotExist": true,
|
"createDatabaseIfNotExist": true,
|
||||||
"schemaFolder": "./databases",
|
"schemaFolder": "./databases",
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ version: '3'
|
|||||||
services:
|
services:
|
||||||
database:
|
database:
|
||||||
container_name: database
|
container_name: database
|
||||||
image: postgres:13
|
image: postgres:14
|
||||||
env_file:
|
env_file:
|
||||||
- database.env
|
- database.env
|
||||||
volumes:
|
volumes:
|
||||||
@@ -12,7 +12,7 @@ services:
|
|||||||
restart: always
|
restart: always
|
||||||
redis:
|
redis:
|
||||||
container_name: redis
|
container_name: redis
|
||||||
image: redis:6.0
|
image: redis:7.0
|
||||||
command: /usr/local/etc/redis/redis.conf
|
command: /usr/local/etc/redis/redis.conf
|
||||||
volumes:
|
volumes:
|
||||||
- ./redis/redis.conf:/usr/local/etc/redis/redis.conf
|
- ./redis/redis.conf:/usr/local/etc/redis/redis.conf
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "npm run tsc && ts-node test/test.ts",
|
"test": "npm run tsc && ts-node test/test.ts",
|
||||||
"test:coverate": "nyc npm run test",
|
"test:coverage": "nyc npm run test",
|
||||||
"dev": "nodemon",
|
"dev": "nodemon",
|
||||||
"dev:bash": "nodemon -x 'npm test ; npm start'",
|
"dev:bash": "nodemon -x 'npm test ; npm start'",
|
||||||
"postgres:docker": "docker run --rm -p 5432:5432 -e POSTGRES_USER=ci_db_user -e POSTGRES_PASSWORD=ci_db_pass postgres:alpine",
|
"postgres:docker": "docker run --rm -p 5432:5432 -e POSTGRES_USER=ci_db_user -e POSTGRES_PASSWORD=ci_db_pass postgres:alpine",
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { config } from "../config";
|
|||||||
import util from "util";
|
import util from "util";
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
import { ChildProcess, exec, ExecOptions, spawn } from "child_process";
|
import { exec, ExecOptions } from "child_process";
|
||||||
const unlink = util.promisify(fs.unlink);
|
const unlink = util.promisify(fs.unlink);
|
||||||
|
|
||||||
const ONE_MINUTE = 1000 * 60;
|
const ONE_MINUTE = 1000 * 60;
|
||||||
@@ -44,7 +44,7 @@ const credentials: ExecOptions = {
|
|||||||
PGPASSWORD: String(config.postgres.password),
|
PGPASSWORD: String(config.postgres.password),
|
||||||
PGDATABASE: "sponsorTimes",
|
PGDATABASE: "sponsorTimes",
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
interface TableDumpList {
|
interface TableDumpList {
|
||||||
fileName: string;
|
fileName: string;
|
||||||
@@ -232,7 +232,7 @@ async function queueDump(): Promise<void> {
|
|||||||
|
|
||||||
resolve(error ? stderr : stdout);
|
resolve(error ? stderr : stdout);
|
||||||
});
|
});
|
||||||
})
|
});
|
||||||
|
|
||||||
dumpFiles.push({
|
dumpFiles.push({
|
||||||
fileName,
|
fileName,
|
||||||
|
|||||||
@@ -26,11 +26,13 @@ async function getFromRedis<T extends string>(key: HashedValue): Promise<T & Has
|
|||||||
Logger.debug(`Got data from redis: ${reply}`);
|
Logger.debug(`Got data from redis: ${reply}`);
|
||||||
return reply as T & HashedValue;
|
return reply as T & HashedValue;
|
||||||
}
|
}
|
||||||
} catch (e) {} // eslint-disable-line no-empty
|
} catch (err) {
|
||||||
|
Logger.error(err as string);
|
||||||
|
}
|
||||||
|
|
||||||
// Otherwise, calculate it
|
// Otherwise, calculate it
|
||||||
const data = getHash(key, cachedHashTimes);
|
const data = getHash(key, cachedHashTimes);
|
||||||
redis.set(key, data).catch((err) => Logger.error(err));
|
redis.set(redisKey, data).catch((err) => Logger.error(err));
|
||||||
|
|
||||||
return data as T & HashedValue;
|
return data as T & HashedValue;
|
||||||
}
|
}
|
||||||
@@ -33,7 +33,7 @@ if (config.redis?.enabled) {
|
|||||||
|
|
||||||
const get = client.get.bind(client);
|
const get = client.get.bind(client);
|
||||||
exportClient.get = (key) => new Promise((resolve, reject) => {
|
exportClient.get = (key) => new Promise((resolve, reject) => {
|
||||||
const timeout = setTimeout(() => reject(), config.redis.getTimeout);
|
const timeout = config.redis.getTimeout ? setTimeout(() => reject(), config.redis.getTimeout) : null;
|
||||||
get(key).then((reply) => {
|
get(key).then((reply) => {
|
||||||
clearTimeout(timeout);
|
clearTimeout(timeout);
|
||||||
resolve(reply);
|
resolve(reply);
|
||||||
@@ -48,7 +48,10 @@ if (config.redis?.enabled) {
|
|||||||
.catch((err) => reject(err))
|
.catch((err) => reject(err))
|
||||||
);
|
);
|
||||||
client.on("error", function(error) {
|
client.on("error", function(error) {
|
||||||
Logger.error(error);
|
Logger.error(`Redis Error: ${error}`);
|
||||||
|
});
|
||||||
|
client.on("reconnect", () => {
|
||||||
|
Logger.info("Redis: trying to reconnect");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
31
test/cases/getHashCache.ts
Normal file
31
test/cases/getHashCache.ts
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
import { config } from "../../src/config";
|
||||||
|
import { getHashCache } from "../../src/utils/getHashCache";
|
||||||
|
import { shaHashKey } from "../../src/utils/redisKeys";
|
||||||
|
import { getHash } from "../../src/utils/getHash";
|
||||||
|
import redis from "../../src/utils/redis";
|
||||||
|
import crypto from "crypto";
|
||||||
|
import assert from "assert";
|
||||||
|
import { setTimeout } from "timers/promises";
|
||||||
|
|
||||||
|
const genRandom = (bytes=8) => crypto.pseudoRandomBytes(bytes).toString("hex");
|
||||||
|
|
||||||
|
const rand1Hash = genRandom(24);
|
||||||
|
const rand1Hash_Key = getHash(rand1Hash, 1);
|
||||||
|
const rand1Hash_Result = getHash(rand1Hash);
|
||||||
|
|
||||||
|
describe("getHashCache test", function() {
|
||||||
|
before(function() {
|
||||||
|
if (!config.redis?.enabled) this.skip();
|
||||||
|
});
|
||||||
|
it("Should set hashKey and be able to retreive", (done) => {
|
||||||
|
const redisKey = shaHashKey(rand1Hash_Key);
|
||||||
|
getHashCache(rand1Hash)
|
||||||
|
.then(() => setTimeout(50)) // add timeout for redis to complete async
|
||||||
|
.then(() => redis.get(redisKey))
|
||||||
|
.then(result => {
|
||||||
|
assert.strictEqual(result, rand1Hash_Result);
|
||||||
|
done();
|
||||||
|
})
|
||||||
|
.catch(err => done(err === undefined ? "no set value" : err));
|
||||||
|
}).timeout(5000);
|
||||||
|
});
|
||||||
@@ -31,7 +31,7 @@ describe("getLockReason", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
after(async () => {
|
after(async () => {
|
||||||
const deleteUserNameQuery = 'DELETE FROM "userNames" WHERE "userID" = ? AND "userName" = ? LIMIT 1';
|
const deleteUserNameQuery = 'DELETE FROM "userNames" WHERE "userID" = ? AND "userName" = ?';
|
||||||
await db.prepare("run", deleteUserNameQuery, [vipUserID1, vipUserName1]);
|
await db.prepare("run", deleteUserNameQuery, [vipUserID1, vipUserName1]);
|
||||||
await db.prepare("run", deleteUserNameQuery, [vipUserID2, vipUserName2]);
|
await db.prepare("run", deleteUserNameQuery, [vipUserID2, vipUserName2]);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -93,7 +93,6 @@ describe("postSkipSegments", () => {
|
|||||||
db.prepare("run", insertWarningQuery, [warnUser01Hash, warnVip01Hash, 1, reason01, (now - 3601000)]);
|
db.prepare("run", insertWarningQuery, [warnUser01Hash, warnVip01Hash, 1, reason01, (now - 3601000)]);
|
||||||
// User 2
|
// User 2
|
||||||
db.prepare("run", insertWarningQuery, [warnUser02Hash, warnVip01Hash, 1, reason02, now]);
|
db.prepare("run", insertWarningQuery, [warnUser02Hash, warnVip01Hash, 1, reason02, now]);
|
||||||
db.prepare("run", insertWarningQuery, [warnUser02Hash, warnVip01Hash, 1, reason02, now]);
|
|
||||||
db.prepare("run", insertWarningQuery, [warnUser02Hash, warnVip01Hash, 1, reason02, (now - (warningExpireTime + 1000))]);
|
db.prepare("run", insertWarningQuery, [warnUser02Hash, warnVip01Hash, 1, reason02, (now - (warningExpireTime + 1000))]);
|
||||||
db.prepare("run", insertWarningQuery, [warnUser02Hash, warnVip01Hash, 1, reason02, (now - (warningExpireTime + 2000))]);
|
db.prepare("run", insertWarningQuery, [warnUser02Hash, warnVip01Hash, 1, reason02, (now - (warningExpireTime + 2000))]);
|
||||||
// User 3
|
// User 3
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ const genRandom = (bytes=8) => crypto.pseudoRandomBytes(bytes).toString("hex");
|
|||||||
const randKey1 = genRandom();
|
const randKey1 = genRandom();
|
||||||
const randValue1 = genRandom();
|
const randValue1 = genRandom();
|
||||||
const randKey2 = genRandom(16);
|
const randKey2 = genRandom(16);
|
||||||
|
const randKey3 = genRandom();
|
||||||
|
const randValue3 = genRandom();
|
||||||
|
|
||||||
describe("redis test", function() {
|
describe("redis test", function() {
|
||||||
before(async function() {
|
before(async function() {
|
||||||
@@ -19,13 +21,41 @@ describe("redis test", function() {
|
|||||||
.then(res => {
|
.then(res => {
|
||||||
assert.strictEqual(res, randValue1);
|
assert.strictEqual(res, randValue1);
|
||||||
done();
|
done();
|
||||||
}).catch(err => assert.fail(err));
|
}).catch(err => done(err));
|
||||||
});
|
});
|
||||||
it("Should not be able to get not stored value", (done) => {
|
it("Should not be able to get not stored value", (done) => {
|
||||||
redis.get(randKey2)
|
redis.get(randKey2)
|
||||||
.then(res => {
|
.then(res => {
|
||||||
if (res) assert.fail("Value should not be found");
|
if (res) done("Value should not be found");
|
||||||
|
done();
|
||||||
|
}).catch(err => done(err));
|
||||||
|
});
|
||||||
|
it("Should be able to delete stored value", (done) => {
|
||||||
|
redis.del(randKey1)
|
||||||
|
.then(() => {
|
||||||
|
redis.get(randKey1)
|
||||||
|
.then(res => {
|
||||||
|
assert.strictEqual(res, null);
|
||||||
|
done();
|
||||||
|
}).catch(err => done(err));
|
||||||
|
}).catch(err => done(err));
|
||||||
|
});
|
||||||
|
it("Should be able to set expiring value", (done) => {
|
||||||
|
redis.setEx(randKey3, 8400, randValue3)
|
||||||
|
.then(() => {
|
||||||
|
redis.get(randKey3)
|
||||||
|
.then(res => {
|
||||||
|
assert.strictEqual(res, randValue3);
|
||||||
|
done();
|
||||||
|
}).catch(err => done(err));
|
||||||
|
}).catch(err => done(err));
|
||||||
|
});
|
||||||
|
it("Should continue when undefined value is fetched", (done) => {
|
||||||
|
const undefkey = `undefined.${genRandom()}`;
|
||||||
|
redis.get(undefkey)
|
||||||
|
.then(result => {
|
||||||
|
assert.ok(!result); // result should be falsy
|
||||||
done();
|
done();
|
||||||
}).catch(err => assert.fail(err));
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -6,14 +6,13 @@ import { client } from "../utils/httpClient";
|
|||||||
import { db, privateDB } from "../../src/databases/databases";
|
import { db, privateDB } from "../../src/databases/databases";
|
||||||
import redis from "../../src/utils/redis";
|
import redis from "../../src/utils/redis";
|
||||||
import assert from "assert";
|
import assert from "assert";
|
||||||
import { Logger } from "../../src/utils/logger";
|
|
||||||
|
|
||||||
// helpers
|
// helpers
|
||||||
const getSegment = (UUID: string) => db.prepare("get", `SELECT "votes", "locked", "category" FROM "sponsorTimes" WHERE "UUID" = ?`, [UUID]);
|
const getSegment = (UUID: string) => db.prepare("get", `SELECT "votes", "locked", "category" FROM "sponsorTimes" WHERE "UUID" = ?`, [UUID]);
|
||||||
|
|
||||||
const permVIP1 = "tempVipPermOne";
|
const permVIP1 = "tempVip_permaVIPOne";
|
||||||
const publicPermVIP1 = getHash(permVIP1) as HashedUserID;
|
const publicPermVIP1 = getHash(permVIP1) as HashedUserID;
|
||||||
const permVIP2 = "tempVipPermOne";
|
const permVIP2 = "tempVip_permaVIPTwo";
|
||||||
const publicPermVIP2 = getHash(permVIP2) as HashedUserID;
|
const publicPermVIP2 = getHash(permVIP2) as HashedUserID;
|
||||||
|
|
||||||
const tempVIPOne = "tempVipTempOne";
|
const tempVIPOne = "tempVipTempOne";
|
||||||
@@ -51,15 +50,8 @@ const postVoteCategory = (userID: string, UUID: string, category: string) => cli
|
|||||||
category
|
category
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
const checkUserVIP = async (publicID: HashedUserID) => {
|
const checkUserVIP = async (publicID: HashedUserID): Promise<string> =>
|
||||||
try {
|
await redis.get(tempVIPKey(publicID));
|
||||||
const reply = await redis.get(tempVIPKey(publicID));
|
|
||||||
return reply;
|
|
||||||
} catch (e) {
|
|
||||||
Logger.error(e as string);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
describe("tempVIP test", function() {
|
describe("tempVIP test", function() {
|
||||||
before(async function() {
|
before(async function() {
|
||||||
@@ -152,7 +144,7 @@ describe("tempVIP test", function() {
|
|||||||
.catch(err => done(err));
|
.catch(err => done(err));
|
||||||
});
|
});
|
||||||
it("Should be able to remove tempVIP prematurely", (done) => {
|
it("Should be able to remove tempVIP prematurely", (done) => {
|
||||||
addTempVIP("false", permVIP1, publicTempVIPOne, null)
|
addTempVIP("false", permVIP1, publicTempVIPOne)
|
||||||
.then(async res => {
|
.then(async res => {
|
||||||
assert.strictEqual(res.status, 200);
|
assert.strictEqual(res.status, 200);
|
||||||
const vip = await checkUserVIP(publicTempVIPOne);
|
const vip = await checkUserVIP(publicTempVIPOne);
|
||||||
|
|||||||
@@ -78,7 +78,6 @@ describe("voteOnSponsorTime", () => {
|
|||||||
await db.prepare("run", insertWarningQuery, [warnUser01Hash, (now - 2000), warnVip01Hash, 1]);
|
await db.prepare("run", insertWarningQuery, [warnUser01Hash, (now - 2000), warnVip01Hash, 1]);
|
||||||
await db.prepare("run", insertWarningQuery, [warnUser01Hash, (now - 3601000), warnVip01Hash, 1]);
|
await db.prepare("run", insertWarningQuery, [warnUser01Hash, (now - 3601000), warnVip01Hash, 1]);
|
||||||
await db.prepare("run", insertWarningQuery, [warnUser02Hash, now, warnVip01Hash, 1]);
|
await db.prepare("run", insertWarningQuery, [warnUser02Hash, now, warnVip01Hash, 1]);
|
||||||
await db.prepare("run", insertWarningQuery, [warnUser02Hash, now, warnVip01Hash, 1]);
|
|
||||||
await db.prepare("run", insertWarningQuery, [warnUser02Hash, (now - (warningExpireTime + 1000)), warnVip01Hash, 1]);
|
await db.prepare("run", insertWarningQuery, [warnUser02Hash, (now - (warningExpireTime + 1000)), warnVip01Hash, 1]);
|
||||||
await db.prepare("run", insertWarningQuery, [warnUser02Hash, (now - (warningExpireTime + 2000)), warnVip01Hash, 1]);
|
await db.prepare("run", insertWarningQuery, [warnUser02Hash, (now - (warningExpireTime + 2000)), warnVip01Hash, 1]);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user