add genUser frameworks, start fixing tests

transformative:
- getUserID
- redisTest
- reputation

mocha test reconfig:
- etag
- getIP
- userCounter
- validateVideoIDs
This commit is contained in:
Michael C 2023-09-27 20:18:35 -04:00
parent 1275afa25b
commit 4438ce7db6
No known key found for this signature in database
GPG key ID: FFB04FB3B878B7B4
9 changed files with 320 additions and 481 deletions

View file

@ -16,14 +16,10 @@ describe("eTag", () => {
});
const endpoint = "/etag";
it("Should reject weak etag", (done) => {
it("Should reject weak etag", () => {
const etagKey = `W/test-etag-${genRandom()}`;
client.get(endpoint, { headers: { "If-None-Match": etagKey } })
.then(res => {
assert.strictEqual(res.status, 404);
done();
})
.catch(err => done(err));
return client.get(endpoint, { headers: { "If-None-Match": etagKey } })
.then(res => assert.strictEqual(res.status, 404));
});
});
@ -34,32 +30,29 @@ describe("304 etag validation", () => {
const endpoint = "/etag";
for (const hashType of ["skipSegments", "skipSegmentsHash", "videoLabel", "videoLabelHash"]) {
it(`${hashType} etag should return 304`, (done) => {
it(`${hashType} etag should return 304`, () => {
const etagKey = `${hashType};${genRandom};YouTube;${Date.now()}`;
redis.setEx(etagKey, 8400, "test").then(() =>
return redis.setEx(etagKey, 8400, "test").then(() =>
client.get(endpoint, { headers: { "If-None-Match": etagKey } }).then(res => {
assert.strictEqual(res.status, 304);
const etag = res.headers?.etag ?? "";
assert.ok(validateEtag(etagKey, etag));
done();
}).catch(err => done(err))
})
);
});
}
it(`other etag type should not return 304`, (done) => {
it(`other etag type should not return 304`, () => {
const etagKey = `invalidHashType;${genRandom};YouTube;${Date.now()}`;
client.get(endpoint, { headers: { "If-None-Match": etagKey } }).then(res => {
return client.get(endpoint, { headers: { "If-None-Match": etagKey } }).then(res => {
assert.strictEqual(res.status, 404);
done();
}).catch(err => done(err));
});
});
it(`outdated etag type should not return 304`, (done) => {
it(`outdated etag type should not return 304`, () => {
const etagKey = `skipSegments;${genRandom};YouTube;5000`;
client.get(endpoint, { headers: { "If-None-Match": etagKey } }).then(res => {
return client.get(endpoint, { headers: { "If-None-Match": etagKey } }).then(res => {
assert.strictEqual(res.status, 404);
done();
}).catch(err => done(err));
});
});
});

View file

@ -50,9 +50,8 @@ describe("getIP stubs", () => {
before(() => stub = sinon.stub(config, "mode").value(mode));
after(() => stub.restore());
it("Should return production mode if stub worked", (done) => {
it("Should return production mode if stub worked", () => {
assert.strictEqual(config.mode, mode);
done();
});
});
@ -64,22 +63,20 @@ describe("getIP array tests", () => {
});
for (const [key, value] of Object.entries(expectedIP4)) {
it(`Should return correct IPv4 from ${key}`, (done) => {
it(`Should return correct IPv4 from ${key}`, () => {
stub2 = sinon.stub(config, "behindProxy").value(key);
const ip = getIP(v4MockRequest);
assert.strictEqual(config.behindProxy, key);
assert.strictEqual(ip, value);
done();
});
}
for (const [key, value] of Object.entries(expectedIP6)) {
it(`Should return correct IPv6 from ${key}`, (done) => {
it(`Should return correct IPv6 from ${key}`, () => {
stub2 = sinon.stub(config, "behindProxy").value(key);
const ip = getIP(v6MockRequest);
assert.strictEqual(config.behindProxy, key);
assert.strictEqual(ip, value);
done();
});
}
});
@ -91,19 +88,17 @@ describe("getIP true tests", () => {
stub2.restore();
});
it(`Should return correct IPv4 from with bool true`, (done) => {
it(`Should return correct IPv4 from with bool true`, () => {
stub2 = sinon.stub(config, "behindProxy").value(true);
const ip = getIP(v4MockRequest);
assert.strictEqual(config.behindProxy, "X-Forwarded-For");
assert.strictEqual(ip, expectedIP4["X-Forwarded-For"]);
done();
});
it(`Should return correct IPv4 from with string true`, (done) => {
it(`Should return correct IPv4 from with string true`, () => {
stub2 = sinon.stub(config, "behindProxy").value("true");
const ip = getIP(v4MockRequest);
assert.strictEqual(config.behindProxy, "X-Forwarded-For");
assert.strictEqual(ip, expectedIP4["X-Forwarded-For"]);
done();
});
});

View file

@ -1,315 +1,141 @@
import { db } from "../../src/databases/databases";
import { getHash } from "../../src/utils/getHash";
import assert from "assert";
import { client } from "../utils/httpClient";
import { AxiosResponse } from "axios";
import { UsernameUser, genUser, genUsersUsername } from "../utils/genUser";
import { insertUsernameBulk } from "../utils/queryGen";
const endpoint = "/api/userID";
const getUserName = (username: string): Promise<AxiosResponse> => client.get(endpoint, { params: { username } });
const getUserName = (username: string, exact: any = false): Promise<AxiosResponse> => client.get(endpoint, { params: { username, exact } });
const validateSearch = (query: string, users: UsernameUser[], exact: number | boolean = false): Promise<void> =>
getUserName(query, exact)
.then(res => {
assert.strictEqual(res.status, 200);
const expected = users.map(user => ({
userName: user.username,
userID: user.pubID
}));
assert.deepStrictEqual(res.data, expected);
});
const validateSearchWithUser = (user: UsernameUser, exact = false) =>
validateSearch(user.username, [user], exact);
const cases = new Map([
["fuzzy_1", "fuzzy user 01"],
["fuzzy_2", "fuzzy user 02"],
["specific_1", "specific user 03"],
["repeating_1", "repeating"],
["repeating_2", "repeating"],
["redos_1", "0redis0"],
["redos_2", "%redos%"],
["redos_3", "_redos_"],
["redos_4", "redos\\%"],
["redos_5", "\\\\\\"],
["exact_1", "a"],
]);
const userPublicOne = genUser("getUserID", "public_1");
const users = genUsersUsername("getUserID", cases);
users["public_1"] = { ...userPublicOne, username: userPublicOne.pubID };
describe("getUserID", () => {
before(async () => {
const insertUserNameQuery = 'INSERT INTO "userNames" ("userID", "userName") VALUES(?, ?)';
await db.prepare("run", insertUserNameQuery, [getHash("getuserid_user_01"), "fuzzy user 01"]);
await db.prepare("run", insertUserNameQuery, [getHash("getuserid_user_02"), "fuzzy user 02"]);
await db.prepare("run", insertUserNameQuery, [getHash("getuserid_user_03"), "specific user 03"]);
await db.prepare("run", insertUserNameQuery, [getHash("getuserid_user_04"), "repeating"]);
await db.prepare("run", insertUserNameQuery, [getHash("getuserid_user_05"), "repeating"]);
await db.prepare("run", insertUserNameQuery, [getHash("getuserid_user_06"), getHash("getuserid_user_06")]);
await db.prepare("run", insertUserNameQuery, [getHash("getuserid_user_07"), "0redos0"]);
await db.prepare("run", insertUserNameQuery, [getHash("getuserid_user_08"), "%redos%"]);
await db.prepare("run", insertUserNameQuery, [getHash("getuserid_user_09"), "_redos_"]);
await db.prepare("run", insertUserNameQuery, [getHash("getuserid_user_10"), "redos\\%"]);
await db.prepare("run", insertUserNameQuery, [getHash("getuserid_user_11"), "\\\\\\"]);
await db.prepare("run", insertUserNameQuery, [getHash("getuserid_user_12"), "a"]);
await insertUsernameBulk(db, users);
});
it("Should be able to get a 200", (done) => {
// status tests
it("Should be able to get a 200", () =>
getUserName("fuzzy user 01")
.then(res => {
assert.strictEqual(res.status, 200);
done();
})
.catch(err => done(err));
.then(res => assert.strictEqual(res.status, 200))
);
it("Should be able to get a 200 (username is public id)", () =>
getUserName(users["public_1"].username)
.then(res => assert.strictEqual(res.status, 200))
);
// individual user tests
it("Should be able to get single username", () => validateSearchWithUser(users["fuzzy_1"]));
it("Should be able to get with public ID", () => validateSearchWithUser(users["public_1"]));
// individual user ReDOS
it("should avoid ReDOS with _", () => validateSearchWithUser(users["redos_3"]));
it("should avoid ReDOS with %", () => validateSearchWithUser(users["redos_2"]));
it("should return user if just backslashes", () => validateSearchWithUser(users["redos_5"]));
it("should allow exact match", () => validateSearchWithUser(users["exact_1"], true));
// fuzzy tests
it("Should be able to get multiple fuzzy user info from start", () =>
validateSearch("fuzzy user",
[users["fuzzy_1"], users["fuzzy_2"]]
)
);
it("Should be able to get multiple fuzzy user info from middle", () => {
validateSearch("user",
[users["fuzzy_1"], users["fuzzy_2"], users["specific_1"]]
);
});
it("Should be able to get a 400 (No username parameter)", (done) => {
client.get(endpoint)
.then(res => {
assert.strictEqual(res.status, 400);
done();
})
.catch(err => done(err));
it("Should be able to get with fuzzy public ID", () => {
const userID = users["public_1"].pubID.substring(0,60);
return validateSearch(userID,
[users["public_1"]]
);
});
it("Should be able to get a 200 (username is public id)", (done) => {
client.get(endpoint, { params: { username: getHash("getuserid_user_06") } })
.then(res => {
assert.strictEqual(res.status, 200);
done();
})
.catch(err => done(err));
});
it("Should be able to get repeating username", () =>
validateSearch("repeating", [users["repeating_1"], users["repeating_2"]])
);
it("Should be able to get a 400 (username longer than 64 chars)", (done) => {
client.get(endpoint, { params: { username: `${getHash("getuserid_user_06")}0` } })
.then(res => {
assert.strictEqual(res.status, 400);
done();
})
.catch(err => done(err));
});
it("Should be able to get repeating fuzzy username", () =>
validateSearch("peat", [users["repeating_1"], users["repeating_2"]])
);
it("Should be able to get single username", (done) => {
client.get(endpoint, { params: { username: "fuzzy user 01" } })
.then(res => {
assert.strictEqual(res.status, 200);
const expected = [{
userName: "fuzzy user 01",
userID: getHash("getuserid_user_01")
}];
assert.deepStrictEqual(res.data, expected);
done();
})
.catch(err => done(err));
});
it("Should be able to get repeating username with exact username", () =>
validateSearch("repeating", [users["repeating_1"], users["repeating_2"]], true)
);
it("Should be able to get multiple fuzzy user info from start", (done) => {
getUserName("fuzzy user")
.then(res => {
assert.strictEqual(res.status, 200);
const expected = [{
userName: "fuzzy user 01",
userID: getHash("getuserid_user_01")
}, {
userName: "fuzzy user 02",
userID: getHash("getuserid_user_02")
}];
assert.deepStrictEqual(res.data, expected);
done();
})
.catch(err => done(err));
});
it("Should be able to get multiple fuzzy user info from middle", (done) => {
getUserName("user")
.then(res => {
assert.strictEqual(res.status, 200);
const expected = [{
userName: "fuzzy user 01",
userID: getHash("getuserid_user_01")
}, {
userName: "fuzzy user 02",
userID: getHash("getuserid_user_02")
}, {
userName: "specific user 03",
userID: getHash("getuserid_user_03")
}];
assert.deepStrictEqual(res.data, expected);
done();
})
.catch(err => done(err));
});
it("Should be able to get with public ID", (done) => {
const userID = getHash("getuserid_user_06");
getUserName(userID)
.then(res => {
assert.strictEqual(res.status, 200);
const expected = [{
userName: userID,
userID
}];
assert.deepStrictEqual(res.data, expected);
done();
})
.catch(err => done(err));
});
it("Should be able to get with fuzzy public ID", (done) => {
const userID = getHash("getuserid_user_06");
getUserName(userID.substr(10,60))
.then(res => {
assert.strictEqual(res.status, 200);
const expected = [{
userName: userID,
userID
}];
assert.deepStrictEqual(res.data, expected);
done();
})
.catch(err => done(err));
});
it("Should be able to get repeating username", (done) => {
getUserName("repeating")
.then(res => {
assert.strictEqual(res.status, 200);
const expected = [{
userName: "repeating",
userID: getHash("getuserid_user_04")
}, {
userName: "repeating",
userID: getHash("getuserid_user_05")
}];
assert.deepStrictEqual(res.data, expected);
done();
})
.catch(err => done(err));
});
it("Should be able to get repeating fuzzy username", (done) => {
getUserName("peat")
.then(res => {
assert.strictEqual(res.status, 200);
const expected = [{
userName: "repeating",
userID: getHash("getuserid_user_04")
}, {
userName: "repeating",
userID: getHash("getuserid_user_05")
}];
assert.deepStrictEqual(res.data, expected);
done();
})
.catch(err => done(err));
});
it("should avoid ReDOS with _", (done) => {
getUserName("_redos_")
.then(res => {
assert.strictEqual(res.status, 200);
const expected = [{
userName: "_redos_",
userID: getHash("getuserid_user_09")
}];
assert.deepStrictEqual(res.data, expected);
done();
})
.catch(err => done(err));
});
it("should avoid ReDOS with %", (done) => {
getUserName("%redos%")
.then(res => {
assert.strictEqual(res.status, 200);
const expected = [{
userName: "%redos%",
userID: getHash("getuserid_user_08")
}];
assert.deepStrictEqual(res.data, expected);
done();
})
.catch(err => done(err));
});
it("should return 404 if escaped backslashes present", (done) => {
getUserName("%redos\\\\_")
.then(res => {
assert.strictEqual(res.status, 404);
done();
})
.catch(err => done(err));
});
it("should return 404 if backslashes present", (done) => {
getUserName(`\\%redos\\_`)
.then(res => {
assert.strictEqual(res.status, 404);
done();
})
.catch(err => done(err));
});
it("should return user if just backslashes", (done) => {
getUserName(`\\\\\\`)
.then(res => {
assert.strictEqual(res.status, 200);
const expected = [{
userName: "\\\\\\",
userID: getHash("getuserid_user_11")
}];
assert.deepStrictEqual(res.data, expected);
done();
})
.catch(err => done(err));
});
it("should not allow usernames more than 64 characters", (done) => {
getUserName("0".repeat(65))
.then(res => {
assert.strictEqual(res.status, 400);
done();
})
.catch(err => done(err));
});
it("should not allow usernames less than 3 characters", (done) => {
getUserName("aa")
.then(res => {
assert.strictEqual(res.status, 400);
done();
})
.catch(err => done(err));
});
it("should allow exact match", (done) => {
client.get(endpoint, { params: { username: "a", exact: true } })
.then(res => {
assert.strictEqual(res.status, 200);
const expected = [{
userName: "a",
userID: getHash("getuserid_user_12")
}];
assert.deepStrictEqual(res.data, expected);
done();
})
.catch(err => done(err));
});
it("Should be able to get repeating username with exact username", (done) => {
client.get(endpoint, { params: { username: "repeating", exact: true } })
.then(res => {
assert.strictEqual(res.status, 200);
const expected = [{
userName: "repeating",
userID: getHash("getuserid_user_04")
}, {
userName: "repeating",
userID: getHash("getuserid_user_05")
}];
assert.deepStrictEqual(res.data, expected);
done();
})
.catch(err => done(err));
});
it("Should not get exact unless explicitly set to true", (done) => {
client.get(endpoint, { params: { username: "user", exact: 1 } })
.then(res => {
assert.strictEqual(res.status, 200);
const expected = [{
userName: "fuzzy user 01",
userID: getHash("getuserid_user_01")
}, {
userName: "fuzzy user 02",
userID: getHash("getuserid_user_02")
}, {
userName: "specific user 03",
userID: getHash("getuserid_user_03")
}];
assert.deepStrictEqual(res.data, expected);
done();
})
.catch(err => done(err));
});
it("should return 400 if no username parameter specified", (done) => {
client.get(endpoint)
.then(res => {
assert.strictEqual(res.status, 400);
done();
})
.catch(() => ("couldn't call endpoint"));
});
it("Should not get exact unless explicitly set to true", () =>
validateSearch("user", [users["fuzzy_1"], users["fuzzy_2"], users["specific_1"]], 1)
);
});
describe("getUserID 400/ 404", () => {
it("Should be able to get a 400 (No username parameter)", () =>
client.get(endpoint)
.then(res => assert.strictEqual(res.status, 400))
);
it("Should return 400 if no username parameter specified", () =>
client.get(endpoint)
.then(res => assert.strictEqual(res.status, 400))
);
it("Should not allow usernames more than 64 characters", () =>
getUserName("0".repeat(65))
.then(res => assert.strictEqual(res.status, 400))
);
it("Should not allow usernames less than 3 characters", () =>
getUserName("aa")
.then(res => assert.strictEqual(res.status, 400))
);
it("Should return 400 (username longer than 64 chars)", () =>
getUserName(users["public_1"].username+0)
.then(res => assert.strictEqual(res.status, 400))
);
it("Should return 404 if escaped backslashes present", () =>
getUserName("%redos\\\\_")
.then(res => assert.strictEqual(res.status, 404))
);
it("Should return 404 if backslashes present", () =>
getUserName(`\\%redos\\_`)
.then(res => assert.strictEqual(res.status, 404))
);
});

View file

@ -9,17 +9,20 @@ const randKey2 = genRandom(16);
const randKey3 = genRandom();
const randValue3 = genRandom();
const redisGetCheck = (key: string, expected: string | null, done: Mocha.Done): Promise<void> =>
redis.get(key)
.then(res => {
assert.strictEqual(res, expected);
done();
}).catch(err => done(err));
describe("redis test", function() {
before(async function() {
if (!config.redis?.enabled) this.skip();
await redis.set(randKey1, randValue1);
});
it("Should get stored value", (done) => {
redis.get(randKey1)
.then(res => {
assert.strictEqual(res, randValue1);
done();
}).catch(err => done(err));
redisGetCheck(randKey1, randValue1, done);
});
it("Should not be able to get not stored value", (done) => {
redis.get(randKey2)
@ -30,23 +33,13 @@ describe("redis test", function() {
});
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));
.catch(err => done(err))
.then(() => redisGetCheck(randKey1, null, done));
});
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));
.catch(err => done(err))
.then(() => redisGetCheck(randKey3, randValue3, done));
});
it("Should continue when undefined value is fetched", (done) => {
const undefkey = `undefined.${genRandom()}`;

View file

@ -1,31 +1,24 @@
import assert from "assert";
import { db } from "../../src/databases/databases";
import { UserID } from "../../src/types/user.model";
import { getHash } from "../../src/utils/getHash";
import { getReputation, calculateReputationFromMetrics } from "../../src/utils/reputation";
import { genUsers } from "../utils/genUser";
describe("reputation", () => {
// constants
const userIDLowSubmissions = "reputation-lowsubmissions" as UserID;
const userHashLowSubmissions = getHash(userIDLowSubmissions);
const userIDHighDownvotes = "reputation-highdownvotes" as UserID;
const userHashHighDownvotes = getHash(userIDHighDownvotes);
const userIDLowNonSelfDownvotes = "reputation-lownonselfdownvotes" as UserID;
const userHashLowNonSelfDownvotes = getHash(userIDLowNonSelfDownvotes);
const userIDHighNonSelfDownvotes = "reputation-highnonselfdownvotes" as UserID;
const userHashHighNonSelfDownvotes = getHash(userIDHighNonSelfDownvotes);
const userIDNewSubmissions = "reputation-newsubmissions" as UserID;
const userHashNewSubmissions = getHash(userIDNewSubmissions);
const userIDLowSum = "reputation-lowsum" as UserID;
const userHashLowSum = getHash(userIDLowSum);
const userIDHighRepBeforeManualVote = "reputation-oldhighrep" as UserID;
const userHashHighRepBeforeManualVote = getHash(userIDHighRepBeforeManualVote);
const userIDHighRep = "reputation-highrep" as UserID;
const userHashHighRep = getHash(userIDHighRep);
const userIDHighRepAndLocked = "reputation-highlockedrep" as UserID;
const userHashHighAndLocked = getHash(userIDHighRepAndLocked);
const userIDHaveMostUpvotedInLockedVideo = "reputation-mostupvotedaslocked" as UserID;
const userHashHaveMostUpvotedInLockedVideo = getHash(userIDHaveMostUpvotedInLockedVideo);
// user definitions
const cases = [
"locking-vip",
"low-submissions",
"high-downvotes",
"low-non-self-downvotes",
"high-non-self-downvotes",
"new-submissions",
"low-sum",
"high-rep-before-manual-vote",
"high-rep",
"high-rep-locked",
"have-most-upvoted-in-locked-video"
];
const users = genUsers("reputation", cases);
before(async function() {
this.timeout(5000); // this preparation takes longer then usual
@ -33,113 +26,113 @@ describe("reputation", () => {
const videoID2 = "reputation-videoID-2";
const sponsorTimesInsertQuery = 'INSERT INTO "sponsorTimes" ("videoID", "startTime", "endTime", "votes", "locked", "UUID", "userID", "timeSubmitted", "views", "category", "hidden", "shadowHidden") VALUES(?,?,?,?,?,?,?,?,?,?,?,?)';
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 2, 0, "reputation-0-uuid-0", userHashLowSubmissions, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 2, 0, "reputation-0-uuid-1", userHashLowSubmissions, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 100, 0, "reputation-0-uuid-2", userHashLowSubmissions, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 2, 0, "reputation-0-uuid-0", users["low-submissions"].pubID, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 2, 0, "reputation-0-uuid-1", users["low-submissions"].pubID, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 100, 0, "reputation-0-uuid-2", users["low-submissions"].pubID, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 2, 0, "reputation-1-uuid-0", userHashHighDownvotes, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, -2, 0, "reputation-1-uuid-1", userHashHighDownvotes, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, -2, 0, "reputation-1-uuid-2", userHashHighDownvotes, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, -2, 0, "reputation-1-uuid-3", userHashHighDownvotes, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, -2, 0, "reputation-1-uuid-4", userHashHighDownvotes, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, -1, 0, "reputation-1-uuid-5", userHashHighDownvotes, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 0, 0, "reputation-1-uuid-6", userHashHighDownvotes, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 0, 0, "reputation-1-uuid-7", userHashHighDownvotes, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 2, 0, "reputation-1-uuid-0", users["high-downvotes"].pubID, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, -2, 0, "reputation-1-uuid-1", users["high-downvotes"].pubID, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, -2, 0, "reputation-1-uuid-2", users["high-downvotes"].pubID, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, -2, 0, "reputation-1-uuid-3", users["high-downvotes"].pubID, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, -2, 0, "reputation-1-uuid-4", users["high-downvotes"].pubID, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, -1, 0, "reputation-1-uuid-5", users["high-downvotes"].pubID, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 0, 0, "reputation-1-uuid-6", users["high-downvotes"].pubID, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 0, 0, "reputation-1-uuid-7", users["high-downvotes"].pubID, 1606240000000, 50, "sponsor", 0, 0]);
// First video is considered a normal downvote, second is considered a self-downvote (ie. they didn't resubmit to fix their downvote)
await db.prepare("run", sponsorTimesInsertQuery, [`${videoID}A`, 1, 11, 2, 0, "reputation-1-1-uuid-0", userHashLowNonSelfDownvotes, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [`${videoID}A`, 1, 11, 2, 0, "reputation-1-1-uuid-0", users["low-non-self-downvotes"].pubID, 1606240000000, 50, "sponsor", 0, 0]);
// Different category, same video
await db.prepare("run", sponsorTimesInsertQuery, [`${videoID}A`, 1, 11, -2, 0, "reputation-1-1-uuid-1", userHashLowNonSelfDownvotes, 1606240000000, 50, "intro", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 0, 0, "reputation-1-1-uuid-2", userHashLowNonSelfDownvotes, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 0, 0, "reputation-1-1-uuid-3", userHashLowNonSelfDownvotes, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 0, 0, "reputation-1-1-uuid-4", userHashLowNonSelfDownvotes, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, -1, 0, "reputation-1-1-uuid-5", userHashLowNonSelfDownvotes, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 0, 0, "reputation-1-1-uuid-6", userHashLowNonSelfDownvotes, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 0, 0, "reputation-1-1-uuid-7", userHashLowNonSelfDownvotes, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [`${videoID}A`, 1, 11, -2, 0, "reputation-1-1-uuid-1", users["low-non-self-downvotes"].pubID, 1606240000000, 50, "intro", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 0, 0, "reputation-1-1-uuid-2", users["low-non-self-downvotes"].pubID, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 0, 0, "reputation-1-1-uuid-3", users["low-non-self-downvotes"].pubID, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 0, 0, "reputation-1-1-uuid-4", users["low-non-self-downvotes"].pubID, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, -1, 0, "reputation-1-1-uuid-5", users["low-non-self-downvotes"].pubID, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 0, 0, "reputation-1-1-uuid-6", users["low-non-self-downvotes"].pubID, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 0, 0, "reputation-1-1-uuid-7", users["low-non-self-downvotes"].pubID, 1606240000000, 50, "sponsor", 0, 0]);
// First videos is considered a normal downvote, last is considered a self-downvote (ie. they didn't resubmit to fix their downvote)
await db.prepare("run", sponsorTimesInsertQuery, [`${videoID}A`, 1, 11, 2, 0, "reputation-1-1-1-uuid-0", userHashHighNonSelfDownvotes, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [`${videoID}A`, 1, 11, 2, 0, "reputation-1-1-1-uuid-0", users["high-non-self-downvotes"].pubID, 1606240000000, 50, "sponsor", 0, 0]);
// Different category, same video
await db.prepare("run", sponsorTimesInsertQuery, [`${videoID}A`, 1, 11, -2, 0, "reputation-1-1-1-uuid-1", userHashHighNonSelfDownvotes, 1606240000000, 50, "intro", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [`${videoID}B`, 1, 11, -2, 0, "reputation-1-1-1-uuid-1-b", userHashHighNonSelfDownvotes, 1606240000000, 50, "intro", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [`${videoID}C`, 1, 11, -2, 0, "reputation-1-1-1-uuid-1-c", userHashHighNonSelfDownvotes, 1606240000000, 50, "intro", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 0, 0, "reputation-1-1-1-uuid-2", userHashHighNonSelfDownvotes, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 0, 0, "reputation-1-1-1-uuid-3", userHashHighNonSelfDownvotes, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 0, 0, "reputation-1-1-1-uuid-4", userHashHighNonSelfDownvotes, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, -1, 0, "reputation-1-1-1-uuid-5", userHashHighNonSelfDownvotes, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 0, 0, "reputation-1-1-1-uuid-6", userHashHighNonSelfDownvotes, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 0, 0, "reputation-1-1-1-uuid-7", userHashHighNonSelfDownvotes, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [`${videoID}A`, 1, 11, -2, 0, "reputation-1-1-1-uuid-1", users["high-non-self-downvotes"].pubID, 1606240000000, 50, "intro", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [`${videoID}B`, 1, 11, -2, 0, "reputation-1-1-1-uuid-1-b", users["high-non-self-downvotes"].pubID, 1606240000000, 50, "intro", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [`${videoID}C`, 1, 11, -2, 0, "reputation-1-1-1-uuid-1-c", users["high-non-self-downvotes"].pubID, 1606240000000, 50, "intro", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 0, 0, "reputation-1-1-1-uuid-2", users["high-non-self-downvotes"].pubID, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 0, 0, "reputation-1-1-1-uuid-3", users["high-non-self-downvotes"].pubID, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 0, 0, "reputation-1-1-1-uuid-4", users["high-non-self-downvotes"].pubID, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, -1, 0, "reputation-1-1-1-uuid-5", users["high-non-self-downvotes"].pubID, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 0, 0, "reputation-1-1-1-uuid-6", users["high-non-self-downvotes"].pubID, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 0, 0, "reputation-1-1-1-uuid-7", users["high-non-self-downvotes"].pubID, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 2, 0, "reputation-2-uuid-0", userHashNewSubmissions, Date.now(), 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 2, 0, "reputation-2-uuid-1", userHashNewSubmissions, Date.now(), 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 2, 0, "reputation-2-uuid-2", userHashNewSubmissions, Date.now(), 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 2, 0, "reputation-2-uuid-3", userHashNewSubmissions, Date.now(), 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 2, 0, "reputation-2-uuid-4", userHashNewSubmissions, Date.now(), 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, -1, 0, "reputation-2-uuid-5", userHashNewSubmissions, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 0, 0, "reputation-2-uuid-6", userHashNewSubmissions, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 0, 0, "reputation-2-uuid-7", userHashNewSubmissions, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 2, 0, "reputation-2-uuid-0", users["new-submissions"].pubID, Date.now(), 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 2, 0, "reputation-2-uuid-1", users["new-submissions"].pubID, Date.now(), 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 2, 0, "reputation-2-uuid-2", users["new-submissions"].pubID, Date.now(), 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 2, 0, "reputation-2-uuid-3", users["new-submissions"].pubID, Date.now(), 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 2, 0, "reputation-2-uuid-4", users["new-submissions"].pubID, Date.now(), 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, -1, 0, "reputation-2-uuid-5", users["new-submissions"].pubID, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 0, 0, "reputation-2-uuid-6", users["new-submissions"].pubID, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 0, 0, "reputation-2-uuid-7", users["new-submissions"].pubID, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 2, 0, "reputation-3-uuid-0", userHashLowSum, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 1, 0, "reputation-3-uuid-1", userHashLowSum, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 0, 0, "reputation-3-uuid-2", userHashLowSum, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 0, 0, "reputation-3-uuid-3", userHashLowSum, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 1, 0, "reputation-3-uuid-4", userHashLowSum, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, -1, 0, "reputation-3-uuid-5", userHashLowSum, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 0, 0, "reputation-3-uuid-6", userHashLowSum, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 0, 0, "reputation-3-uuid-7", userHashLowSum, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 2, 0, "reputation-3-uuid-0", users["low-sum"].pubID, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 1, 0, "reputation-3-uuid-1", users["low-sum"].pubID, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 0, 0, "reputation-3-uuid-2", users["low-sum"].pubID, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 0, 0, "reputation-3-uuid-3", users["low-sum"].pubID, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 1, 0, "reputation-3-uuid-4", users["low-sum"].pubID, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, -1, 0, "reputation-3-uuid-5", users["low-sum"].pubID, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 0, 0, "reputation-3-uuid-6", users["low-sum"].pubID, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 0, 0, "reputation-3-uuid-7", users["low-sum"].pubID, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 2, 0, "reputation-4-uuid-0", userHashHighRepBeforeManualVote, 0, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 2, 0, "reputation-4-uuid-1", userHashHighRepBeforeManualVote, 0, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 2, 0, "reputation-4-uuid-2", userHashHighRepBeforeManualVote, 0, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 2, 0, "reputation-4-uuid-3", userHashHighRepBeforeManualVote, 0, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 2, 0, "reputation-4-uuid-4", userHashHighRepBeforeManualVote, 0, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, -1, 0, "reputation-4-uuid-5", userHashHighRepBeforeManualVote, 0, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 0, 0, "reputation-4-uuid-6", userHashHighRepBeforeManualVote, 0, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 0, 0, "reputation-4-uuid-7", userHashHighRepBeforeManualVote, 0, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 2, 0, "reputation-4-uuid-0", users["high-rep-before-manual-vote"].pubID, 0, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 2, 0, "reputation-4-uuid-1", users["high-rep-before-manual-vote"].pubID, 0, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 2, 0, "reputation-4-uuid-2", users["high-rep-before-manual-vote"].pubID, 0, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 2, 0, "reputation-4-uuid-3", users["high-rep-before-manual-vote"].pubID, 0, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 2, 0, "reputation-4-uuid-4", users["high-rep-before-manual-vote"].pubID, 0, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, -1, 0, "reputation-4-uuid-5", users["high-rep-before-manual-vote"].pubID, 0, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 0, 0, "reputation-4-uuid-6", users["high-rep-before-manual-vote"].pubID, 0, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 0, 0, "reputation-4-uuid-7", users["high-rep-before-manual-vote"].pubID, 0, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 2, 0, "reputation-5-uuid-0", userHashHighRep, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 2, 0, "reputation-5-uuid-1", userHashHighRep, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 2, 0, "reputation-5-uuid-2", userHashHighRep, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 2, 0, "reputation-5-uuid-3", userHashHighRep, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 2, 0, "reputation-5-uuid-4", userHashHighRep, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, -1, 0, "reputation-5-uuid-5", userHashHighRep, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 0, 0, "reputation-5-uuid-6", userHashHighRep, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 0, 0, "reputation-5-uuid-7", userHashHighRep, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 2, 0, "reputation-5-uuid-0", users["high-rep"].pubID, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 2, 0, "reputation-5-uuid-1", users["high-rep"].pubID, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 2, 0, "reputation-5-uuid-2", users["high-rep"].pubID, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 2, 0, "reputation-5-uuid-3", users["high-rep"].pubID, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 2, 0, "reputation-5-uuid-4", users["high-rep"].pubID, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, -1, 0, "reputation-5-uuid-5", users["high-rep"].pubID, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 0, 0, "reputation-5-uuid-6", users["high-rep"].pubID, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 0, 0, "reputation-5-uuid-7", users["high-rep"].pubID, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 2, 1, "reputation-6-uuid-0", userHashHighAndLocked, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 2, 1, "reputation-6-uuid-1", userHashHighAndLocked, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 2, 1, "reputation-6-uuid-2", userHashHighAndLocked, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 2, 1, "reputation-6-uuid-3", userHashHighAndLocked, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 2, 0, "reputation-6-uuid-4", userHashHighAndLocked, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, -1, 0, "reputation-6-uuid-5", userHashHighAndLocked, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 0, 0, "reputation-6-uuid-6", userHashHighAndLocked, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 0, 0, "reputation-6-uuid-7", userHashHighAndLocked, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 2, 1, "reputation-6-uuid-0", users["high-rep-locked"].pubID, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 2, 1, "reputation-6-uuid-1", users["high-rep-locked"].pubID, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 2, 1, "reputation-6-uuid-2", users["high-rep-locked"].pubID, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 2, 1, "reputation-6-uuid-3", users["high-rep-locked"].pubID, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 2, 0, "reputation-6-uuid-4", users["high-rep-locked"].pubID, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, -1, 0, "reputation-6-uuid-5", users["high-rep-locked"].pubID, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 0, 0, "reputation-6-uuid-6", users["high-rep-locked"].pubID, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 0, 0, "reputation-6-uuid-7", users["high-rep-locked"].pubID, 1606240000000, 50, "sponsor", 0, 0]);
//Record has most upvoted
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 5, 0, "reputation-7-uuid-0", userHashHaveMostUpvotedInLockedVideo, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 101, 0, "reputation-7-uuid-1", userHashHaveMostUpvotedInLockedVideo, 1606240000000, 50, "intro", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID2, 1, 11, 5, 0, "reputation-7-uuid-8", userHashHaveMostUpvotedInLockedVideo, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID2, 1, 11, 0, 0, "reputation-7-uuid-9", userHashHaveMostUpvotedInLockedVideo, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 5, 0, "reputation-7-uuid-0", users["have-most-upvoted-in-locked-video"].pubID, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 101, 0, "reputation-7-uuid-1", users["have-most-upvoted-in-locked-video"].pubID, 1606240000000, 50, "intro", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID2, 1, 11, 5, 0, "reputation-7-uuid-8", users["have-most-upvoted-in-locked-video"].pubID, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID2, 1, 11, 0, 0, "reputation-7-uuid-9", users["have-most-upvoted-in-locked-video"].pubID, 1606240000000, 50, "sponsor", 0, 0]);
// other segments
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 2, 0, "reputation-7-uuid-2", userHashHaveMostUpvotedInLockedVideo, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 2, 0, "reputation-7-uuid-3", userHashHaveMostUpvotedInLockedVideo, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 2, 0, "reputation-7-uuid-4", userHashHaveMostUpvotedInLockedVideo, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, -1, 0, "reputation-7-uuid-5", userHashHaveMostUpvotedInLockedVideo, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 0, 0, "reputation-7-uuid-6", userHashHaveMostUpvotedInLockedVideo, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 0, 0, "reputation-7-uuid-7", userHashHaveMostUpvotedInLockedVideo, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 2, 0, "reputation-7-uuid-2", users["have-most-upvoted-in-locked-video"].pubID, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 2, 0, "reputation-7-uuid-3", users["have-most-upvoted-in-locked-video"].pubID, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 2, 0, "reputation-7-uuid-4", users["have-most-upvoted-in-locked-video"].pubID, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, -1, 0, "reputation-7-uuid-5", users["have-most-upvoted-in-locked-video"].pubID, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 0, 0, "reputation-7-uuid-6", users["have-most-upvoted-in-locked-video"].pubID, 1606240000000, 50, "sponsor", 0, 0]);
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 0, 0, "reputation-7-uuid-7", users["have-most-upvoted-in-locked-video"].pubID, 1606240000000, 50, "sponsor", 0, 0]);
// lock video
const insertVipUserQuery = 'INSERT INTO "vipUsers" ("userID") VALUES (?)';
await db.prepare("run", insertVipUserQuery, [getHash("VIPUser-getLockCategories")]);
await db.prepare("run", insertVipUserQuery, [users["locking-vip"].pubID]);
const insertLockCategoryQuery = 'INSERT INTO "lockCategories" ("userID", "videoID", "category") VALUES (?, ?, ?)';
await db.prepare("run", insertLockCategoryQuery, [getHash("VIPUser-getLockCategories"), videoID, "sponsor"]);
await db.prepare("run", insertLockCategoryQuery, [getHash("VIPUser-getLockCategories"), videoID, "intro"]);
await db.prepare("run", insertLockCategoryQuery, [getHash("VIPUser-getLockCategories"), videoID2, "sponsor"]);
await db.prepare("run", insertLockCategoryQuery, [users["locking-vip"].pubID, videoID, "sponsor"]);
await db.prepare("run", insertLockCategoryQuery, [users["locking-vip"].pubID, videoID, "intro"]);
await db.prepare("run", insertLockCategoryQuery, [users["locking-vip"].pubID, videoID2, "sponsor"]);
});
it("user in grace period", async () => {
const data = await getReputation(getHash(userIDLowSubmissions));
const data = await getReputation(users["low-submissions"].privID);
assert.strictEqual(data, 0);
});
@ -154,7 +147,7 @@ describe("reputation", () => {
oldUpvotedSubmissions: 1,
mostUpvotedInLockedVideoSum: 0
};
const data = await getReputation(getHash(userIDHighDownvotes));
const data = await getReputation(users["high-downvotes"].pubID);
assert.strictEqual(data, calculateReputationFromMetrics(metrics));
assert.strictEqual(data, -1.7500000000000002);
});
@ -170,26 +163,26 @@ describe("reputation", () => {
oldUpvotedSubmissions: 1,
mostUpvotedInLockedVideoSum: 0
};
const data = await getReputation(userHashLowNonSelfDownvotes);
const data = await getReputation(users["low-non-self-downvotes"].pubID);
assert.strictEqual(data, calculateReputationFromMetrics(metrics));
assert.strictEqual(data, 0);
});
it("user with high non self downvote ratio", async () => {
const data = await getReputation(userHashHighNonSelfDownvotes);
const data = await getReputation(users["high-non-self-downvotes"].pubID);
assert.strictEqual(data, -2.5);
});
it("user with mostly new submissions", async () => {
assert.strictEqual(await getReputation(userHashNewSubmissions), 0);
assert.strictEqual(await getReputation(users["new-submissions"].pubID), 0);
});
it("user with not enough vote sum", async () => {
assert.strictEqual(await getReputation(userHashLowSum), 0);
assert.strictEqual(await getReputation(users["low-sum"].pubID), 0);
});
it("user with lots of old votes (before autovote was disabled) ", async () => {
assert.strictEqual(await getReputation(userHashHighRepBeforeManualVote), 0);
assert.strictEqual(await getReputation(users["high-rep-before-manual-vote"].pubID), 0);
});
it("user with high reputation", async () => {
@ -203,7 +196,7 @@ describe("reputation", () => {
oldUpvotedSubmissions: 5,
mostUpvotedInLockedVideoSum: 0
};
const data = await getReputation(userHashHighRep);
const data = await getReputation(users["high-rep"].pubID);
assert.strictEqual(data, calculateReputationFromMetrics(metrics));
assert.strictEqual(data, 0.19310344827586207);
});
@ -219,7 +212,7 @@ describe("reputation", () => {
oldUpvotedSubmissions: 5,
mostUpvotedInLockedVideoSum: 4
};
const data = await getReputation(userHashHighAndLocked);
const data = await getReputation(users["high-rep-locked"].pubID);
assert.strictEqual(data, calculateReputationFromMetrics(metrics));
assert.strictEqual(data, 3.393103448275862);
});
@ -235,7 +228,7 @@ describe("reputation", () => {
oldUpvotedSubmissions: 6,
mostUpvotedInLockedVideoSum: 2
};
const data = await getReputation(userHashHaveMostUpvotedInLockedVideo);
const data = await getReputation(users["have-most-upvoted-in-locked-video"].pubID);
assert.strictEqual(data, calculateReputationFromMetrics(metrics));
assert.strictEqual(data, 6.158620689655172);
});

View file

@ -5,29 +5,23 @@ import { getHash } from "../../src/utils/getHash";
import { client } from "../utils/httpClient";
describe("userCounter", () => {
it("Should return 200", function (done) {
it("Should return 200", function () {
if (!config.userCounterURL) this.skip(); // skip if no userCounterURL is set
axios.request({
return axios.request({
method: "POST",
baseURL: config.userCounterURL,
url: "/api/v1/addIP",
params: {
hashedIP: getHash("127.0.0.1",1)
}
})
.then(res => {
assert.strictEqual(res.status, 200);
done();
})
.catch(err => done(err));
}).then(res => assert.strictEqual(res.status, 200));
});
it("Should not incremeent counter on OPTIONS", function (done) {
it("Should not incremeent counter on OPTIONS", function () {
/* cannot spy test */
if (!config.userCounterURL) this.skip(); // skip if no userCounterURL is set
//const spy = sinon.spy(UserCounter);
client({ method: "OPTIONS", url: "/api/status" })
return client({ method: "OPTIONS", url: "/api/status" })
.then(() => client({ method: "GET", url: "/api/status" }));
//assert.strictEqual(spy.callCount, 1);
done();
});
});

View file

@ -106,20 +106,16 @@ describe("VideoID Validation - postSkipSegments", () => {
done();
});
it(`Should return 400 for invalid videoID`, (done) => {
it(`Should return 400 for invalid videoID`, () =>
postSkipSegments("123456").then(res => {
assert.strictEqual(res.status, 400);
assert.strictEqual(res.data, expectedError);
done();
})
.catch(err => done(err));
});
);
it(`Should return 200 for valid videoID`, (done) => {
postSkipSegments("dQw4w9WgXcQ").then(res => {
assert.strictEqual(res.status, 200);
done();
})
.catch(err => done(err));
});
it(`Should return 200 for valid videoID`, () =>
postSkipSegments("dQw4w9WgXcQ").then(res =>
assert.strictEqual(res.status, 200)
)
);
});

34
test/utils/genUser.ts Normal file
View file

@ -0,0 +1,34 @@
import { genRandom } from "./getRandom";
import { UserID, HashedUserID } from "../../src/types/user.model";
import { getHash } from "../../src/utils/getHash";
export interface User {
privID: UserID,
pubID: HashedUserID
}
export type userArray = Record<string, User>
export interface UsernameUser extends User {
username: string
}
export type usernameUserArray = Record<string, UsernameUser>
export const genUser = (fnname: string, testcase: string): User => {
const privID = `${fnname}-${testcase}-${genRandom(2)}` as UserID;
const pubID = getHash(privID);
return { privID, pubID };
};
export const genUsers = (fnname: string, testcase: string[]): userArray => {
const users: userArray = {};
for (const tc of testcase)
users[tc] = genUser(fnname, tc);
return users;
};
export const genUsersUsername = (fnname: string, case_usernames: Map<string, string>): usernameUserArray => {
const cases = Array.from(case_usernames.keys());
const users = genUsers(fnname, cases);
case_usernames.forEach((username, tc) => (users[tc] as UsernameUser).username = username);
return users as usernameUserArray;
};

15
test/utils/queryGen.ts Normal file
View file

@ -0,0 +1,15 @@
import { IDatabase } from "../../src/databases/IDatabase";
import { HashedUserID } from "../../src/types/user.model";
import { usernameUserArray } from "./genUser";
export const insertUsername = async (db: IDatabase, userID: HashedUserID, userName: string, locked = false) => {
const query = 'INSERT INTO "userNames" ("userID", "userName", "locked") VALUES(?, ?, ?)';
const lockedValue = Number(locked);
await db.prepare("run", query, [userID, userName, lockedValue]);
};
export const insertUsernameBulk = async (db: IDatabase, users: usernameUserArray) => {
const query = 'INSERT INTO "userNames" ("userID", "userName", "locked") VALUES(?, ?, ?)';
for (const user of Object.values(users))
await db.prepare("run", query, [user.pubID, user.username, 0]);
};