From d5e9028750f6137f5d8d679c6ff4642d905fb18a Mon Sep 17 00:00:00 2001 From: Vomitblood Date: Sat, 2 May 2026 01:00:35 +0800 Subject: [PATCH] added test script to test feature parity of ezgame.formulas with ns.formulas functions --- src/ezgame/formulas/test.ts | 190 ++++++++++++++++++++++++++++++++++++ 1 file changed, 190 insertions(+) create mode 100644 src/ezgame/formulas/test.ts diff --git a/src/ezgame/formulas/test.ts b/src/ezgame/formulas/test.ts new file mode 100644 index 0000000..3e6a76a --- /dev/null +++ b/src/ezgame/formulas/test.ts @@ -0,0 +1,190 @@ +import { ezgame } from "@/ezgame"; +import { randomNumber } from "@/utils/utils"; +import { NS } from "@ns"; + +interface TestCase { + name: string; + fn: (ns: NS, serverName: string) => void; +} + +// add servers to be tested against here +const serverNames: string[] = ["n00dles", "foodnstuff", "joesguns", "sigma-cosmetics", "max-hardware"]; + +// test generator for gang +const gangTests = (ns: NS, serverName: string): TestCase[] => [ + { + name: "gang.ascensionMultiplier", + fn: (ns, serverName) => { + const points = randomNumber(0, 1e9); + const testResult = ezgame.formulas.gang.ascensionMultiplier(points); + const actualResult = ns.formulas.gang.ascensionMultiplier(points); + if (testResult !== actualResult) { + throw new Error(`expected ${actualResult}, got ${testResult}`); + } + }, + }, + { + name: "gang.ascensionPointsGain", + fn: (ns, serverName) => { + const exp = randomNumber(0, 1e9); + const testResult = ezgame.formulas.gang.ascensionPointsGain(exp); + const actualResult = ns.formulas.gang.ascensionPointsGain(exp); + if (testResult !== actualResult) { + throw new Error(`expected ${actualResult}, got ${testResult}`); + } + }, + }, + // TODO: moneyGain() cannot do yet + // TODO: respectGain() cannot do yet + // TODO: wantedLevelGain() cannot do yet + // TODO: wantedPenalty() cannot do yet +]; + +// test generator for hacking +const hackingTests = (ns: NS, serverName: string): TestCase[] => [ + { + name: "hacking.growAmount", + fn: (ns, serverName) => { + const server = ns.getServer(serverName); + const player = ns.getPlayer(); + const threads = randomNumber(1, 100); + const cores = randomNumber(1, 16); + const testResult = ezgame.formulas.hacking.growAmount(server, player, threads, cores); + const actualResult = ns.formulas.hacking.growAmount(server, player, threads, cores); + if (testResult !== actualResult) { + throw new Error(`expected ${actualResult}, got ${testResult}`); + } + }, + }, + { + name: "hacking.growPercent", + fn: (ns, serverName) => { + const server = ns.getServer(serverName); + const threads = randomNumber(1, 100); + const player = ns.getPlayer(); + const cores = randomNumber(1, 16); + const testResult = ezgame.formulas.hacking.growPercent(server, threads, player, cores); + const actualResult = ns.formulas.hacking.growPercent(server, threads, player, cores); + if (testResult !== actualResult) { + throw new Error(`expected ${actualResult}, got ${testResult}`); + } + }, + }, + { + name: "hacking.growThreads", + fn: (ns, serverName) => { + const server = ns.getServer(serverName); + const player = ns.getPlayer(); + // if moneyMax is not set, use a large number to ensure growThreads returns a valid number of threads + // anyways if it is above moneyMax, the function should clamp it to the max (hopefully) + const targetMoney = server.moneyMax ?? 1e120; + const cores = randomNumber(1, 16); + const testResult = ezgame.formulas.hacking.growThreads(server, player, targetMoney, cores); + const actualResult = ns.formulas.hacking.growThreads(server, player, targetMoney, cores); + if (testResult !== actualResult) { + throw new Error(`expected ${actualResult}, got ${testResult}`); + } + }, + }, + { + name: "hacking.growTime", + fn: (ns, serverName) => { + const server = ns.getServer(serverName); + const player = ns.getPlayer(); + const testResult = ezgame.formulas.hacking.growTime(server, player); + const actualResult = ns.formulas.hacking.growTime(server, player); + if (testResult !== actualResult) { + throw new Error(`expected ${actualResult}, got ${testResult}`); + } + }, + }, + { + name: "hacking.hackChance", + fn: (ns, serverName) => { + const server = ns.getServer(serverName); + const player = ns.getPlayer(); + const testResult = ezgame.formulas.hacking.hackChance(server, player); + const actualResult = ns.formulas.hacking.hackChance(server, player); + if (testResult !== actualResult) { + throw new Error(`expected ${actualResult}, got ${testResult}`); + } + }, + }, + { + name: "hacking.hackExp", + fn: (ns, serverName) => { + const server = ns.getServer(serverName); + const player = ns.getPlayer(); + const testResult = ezgame.formulas.hacking.hackExp(server, player); + const actualResult = ns.formulas.hacking.hackExp(server, player); + if (testResult !== actualResult) { + throw new Error(`expected ${actualResult}, got ${testResult}`); + } + }, + }, + { + name: "hacking.hackPercent", + fn: (ns, serverName) => { + const server = ns.getServer(serverName); + const player = ns.getPlayer(); + const testResult = ezgame.formulas.hacking.hackPercent(server, player); + const actualResult = ns.formulas.hacking.hackPercent(server, player); + if (testResult !== actualResult) { + throw new Error(`expected ${actualResult}, got ${testResult}`); + } + }, + }, + { + name: "hacking.hackTime", + fn: (ns, serverName) => { + const server = ns.getServer(serverName); + const player = ns.getPlayer(); + const testResult = ezgame.formulas.hacking.hackTime(server, player); + const actualResult = ns.formulas.hacking.hackTime(server, player); + if (testResult !== actualResult) { + throw new Error(`expected ${actualResult}, got ${testResult}`); + } + }, + }, + { + name: "hacking.weakenTime", + fn: (ns, serverName) => { + const server = ns.getServer(serverName); + const player = ns.getPlayer(); + const testResult = ezgame.formulas.hacking.weakenTime(server, player); + const actualResult = ns.formulas.hacking.weakenTime(server, player); + if (testResult !== actualResult) { + throw new Error(`expected ${actualResult}, got ${testResult}`); + } + }, + }, +]; + +export const main = (ns: NS) => { + const passedTests: string[] = []; + const failedTests: string[] = []; + + // gather all the test generators here + const testGenerators = [gangTests, hackingTests]; + + // run tests for each server and generator + for (const serverName of serverNames) { + for (const generator of testGenerators) { + const tests = generator(ns, serverName); + for (const test of tests) { + try { + test.fn(ns, serverName); + passedTests.push(`[${serverName}] ${test.name}`); + } catch (error) { + failedTests.push(`[${serverName}] ${test.name}: ${error}`); + } + } + } + } + + // print results + ns.tprint(`Passed: ${passedTests.length}/${passedTests.length + failedTests.length}`); + passedTests.forEach((t) => ns.tprint(` ✓ ${t}`)); + ns.tprint(`Failed: ${failedTests.length}/${passedTests.length + failedTests.length}`); + failedTests.forEach((t) => ns.tprint(` ✗ ${t}`)); +};