Added Dynamic RAM calculation unit tests

This commit is contained in:
danielyxie 2019-05-10 02:24:50 -07:00
parent db5fdb1fcb
commit 9dd68947f1
9 changed files with 1436 additions and 22 deletions

6
.gitignore vendored

@ -3,6 +3,6 @@ Netburner.txt
/doc/build
/node_modules
/dist/*.map
/tests/*.map
/tests/*.bundle.*
/tests/*.css
/test/*.map
/test/*.bundle.*
/test/*.css

@ -76,7 +76,7 @@ export class WorkerScript {
output: string = "";
/**
* Script's RAM usage. Equivalent to underlying script's RAM usage
* Script's Static RAM usage. Equivalent to underlying script's RAM usage
*/
ramUsage: number = 0;

@ -4346,7 +4346,7 @@ function NetscriptFunctions(workerScript) {
if (Player.bitNodeN !== 10 && !SourceFileFlags[10]) {
throw makeRuntimeRejectMsg(workerScript, "getStats() failed because you do not currently have access to the Sleeve API. This is either because you are not in BitNode-10 or because you do not have Source-File 10");
}
updateDynamicRam("workoutAtGym", getRamCost("sleeve", "getSleeveStats"));
updateDynamicRam("getSleeveStats", getRamCost("sleeve", "getSleeveStats"));
if (sleeveNumber >= Player.sleeves.length || sleeveNumber < 0) {
workerScript.log(`ERROR: sleeve.workoutAtGym(${sleeveNumber}) failed because it is an invalid sleeve number.`);
return false;

@ -359,21 +359,24 @@ export function hasProgram(programName) {
export function setMoney(money) {
if (isNaN(money)) {
console.log("ERR: NaN passed into Player.setMoney()"); return;
console.error("NaN passed into Player.setMoney()");
return;
}
this.money = money;
this.money = new Decimal(money);
}
export function gainMoney(money) {
if (isNaN(money)) {
console.log("ERR: NaN passed into Player.gainMoney()"); return;
console.error("NaN passed into Player.gainMoney()");
return;
}
this.money = this.money.plus(money);
}
export function loseMoney(money) {
if (isNaN(money)) {
console.log("ERR: NaN passed into Player.loseMoney()"); return;
console.error("NaN passed into Player.loseMoney()");
return;
}
this.money = this.money.minus(money);
}

@ -97,7 +97,7 @@ function prestigeAugmentation() {
}
if (augmentationExists(AugmentationNames.CashRoot) &&
Augmentations[AugmentationNames.CashRoot].owned) {
Player.setMoney(new Decimal(1000000));
Player.setMoney(1e6);
homeComp.programs.push(Programs.BruteSSHProgram.name);
}

File diff suppressed because it is too large Load Diff

@ -10,7 +10,7 @@ const HacknetNamespaceCost = RamCostConstants.ScriptHacknetNodesRamCost;
describe("Netscript Static RAM Calculation/Generation Tests", function() {
// Tests numeric equality, allowing for floating point imprecision
function testEquality(val, expected) {
expect(val).to.be.within(expected - 10 * Number.EPSILON, expected + 10 * Number.EPSILON);
expect(val).to.be.within(expected - 100 * Number.EPSILON, expected + 100 * Number.EPSILON);
}
/**

@ -1,4 +1,11 @@
import { CONSTANTS } from "../src/Constants";
import { Player } from "../src/Player";
import {
buyStock,
sellStock,
shortStock,
sellShort,
} from "../src/StockMarket/BuyingAndSelling";
import { Order } from "../src/StockMarket/Order";
import { processOrders } from "../src/StockMarket/OrderProcessing";
import { Stock } from "../src/StockMarket/Stock";
@ -7,6 +14,7 @@ import {
initStockMarket,
initSymbolToStockMap,
loadStockMarket,
processStockPrices,
StockMarket,
SymbolToStockMap,
} from "../src/StockMarket/StockMarket";
@ -22,8 +30,6 @@ import {
import { OrderTypes } from "../src/StockMarket/data/OrderTypes"
import { PositionTypes } from "../src/StockMarket/data/PositionTypes";
//const assert = chai.assert;
//const expect = chai.expect;
import { expect } from "chai";
console.log("Beginning Stock Market Tests");
@ -192,7 +198,9 @@ describe("Stock Market Tests", function() {
it("should have properties for managing game cycles", function() {
expect(StockMarket).to.have.property("storedCycles");
expect(StockMarket["storedCycles"]).to.equal(0);
expect(StockMarket).to.have.property("lastUpdate");
expect(StockMarket["lastUpdate"]).to.equal(0);
});
});
@ -206,15 +214,59 @@ describe("Stock Market Tests", function() {
});
});
// Reset stock market for each test
beforeEach(function() {
describe("processStockPrices()", function() {
before(function() {
deleteStockMarket();
initStockMarket();
initSymbolToStockMap();
});
it("should properly initialize", function() {
it("should store cycles until it actually processes", function() {
expect(StockMarket["storedCycles"]).to.equal(0);
processStockPrices(10);
expect(StockMarket["storedCycles"]).to.equal(10);
});
it("should trigger a price update when it has enough cycles", function() {
// Get the initial prices
const initialValues = {};
for (const stockName in StockMarket) {
const stock = StockMarket[stockName];
if (!(stock instanceof Stock)) { continue; }
initialValues[stock.symbol] = {
price: stock.price,
otlkMag: stock.otlkMag,
}
}
// Don't know or care how many exact cycles are required
processStockPrices(1e9);
// Both price and 'otlkMag' should be different
for (const stockName in StockMarket) {
const stock = StockMarket[stockName];
if (!(stock instanceof Stock)) { continue; }
expect(initialValues[stock.symbol].price).to.not.equal(stock.price);
expect(initialValues[stock.symbol].otlkMag).to.not.equal(stock.otlkMag);
}
});
});
});
describe("StockToSymbolMap", function() {
before(function() {
deleteStockMarket();
initStockMarket();
initSymbolToStockMap();
});
it("should map stock symbols to their corresponding Stock Objects", function() {
for (const stockName in StockMarket) {
const stock = StockMarket[stockName];
if (!(stock instanceof Stock)) { continue; }
expect(SymbolToStockMap[stock.symbol]).to.equal(stock);
}
});
});
@ -637,6 +689,190 @@ describe("Stock Market Tests", function() {
});
});
describe("Transaction (Buy/Sell) Functions", function() {
const suppressDialogOpt = { suppressDialog: true };
describe("buyStock()", function() {
it("should fail for invalid arguments", function() {
expect(buyStock({}, 1, null, suppressDialogOpt)).to.equal(false);
expect(buyStock(stock, 0, null, suppressDialogOpt)).to.equal(false);
expect(buyStock(stock, -1, null, suppressDialogOpt)).to.equal(false);
expect(buyStock(stock, NaN, null, suppressDialogOpt)).to.equal(false);
});
it("should fail if player doesn't have enough money", function() {
Player.setMoney(0);
expect(buyStock(stock, 1, null, suppressDialogOpt)).to.equal(false);
});
it("should not allow for transactions that exceed the maximum shares", function() {
const maxShares = stock.maxShares;
expect(buyStock(stock, maxShares + 1, null, suppressDialogOpt)).to.equal(false);
});
it("should return true and properly update stock properties for successful transactions", function() {
const shares = 1e3;
const cost = getBuyTransactionCost(stock, shares, PositionTypes.Long);
Player.setMoney(cost);
expect(buyStock(stock, shares, null, suppressDialogOpt)).to.equal(true);
expect(stock.playerShares).to.equal(shares);
expect(stock.playerAvgPx).to.be.above(0);
expect(Player.money.toNumber()).to.equal(0);
});
});
describe("sellStock()", function() {
it("should fail for invalid arguments", function() {
expect(sellStock({}, 1, null, suppressDialogOpt)).to.equal(false);
expect(sellStock(stock, 0, null, suppressDialogOpt)).to.equal(false);
expect(sellStock(stock, -1, null, suppressDialogOpt)).to.equal(false);
expect(sellStock(stock, NaN, null, suppressDialogOpt)).to.equal(false);
});
it("should fail if player doesn't have any shares", function() {
Player.setMoney(0);
expect(sellStock(stock, 1, null, suppressDialogOpt)).to.equal(false);
});
it("should not allow for transactions that exceed the maximum shares", function() {
const maxShares = stock.maxShares;
expect(sellStock(stock, maxShares + 1, null, suppressDialogOpt)).to.equal(false);
});
it("should return true and properly update stock properties for successful transactions", function() {
const shares = 1e3;
stock.playerShares = shares;
stock.playerAvgPx = stock.price;
const gain = getSellTransactionGain(stock, shares, PositionTypes.Long);
Player.setMoney(0);
expect(sellStock(stock, shares, null, suppressDialogOpt)).to.equal(true);
expect(stock.playerShares).to.equal(0);
expect(stock.playerAvgPx).to.equal(0);
expect(Player.money.toNumber()).to.equal(gain);
});
it("should cap the number of sharse sold to however many the player owns", function() {
const attemptedShares = 2e3;
const actualShares = 1e3;
stock.playerShares = actualShares;
stock.playerAvgPx = stock.price;
const gain = getSellTransactionGain(stock, actualShares, PositionTypes.Long);
Player.setMoney(0);
expect(sellStock(stock, attemptedShares, null, suppressDialogOpt)).to.equal(true);
expect(stock.playerShares).to.equal(0);
expect(stock.playerAvgPx).to.equal(0);
expect(Player.money.toNumber()).to.equal(gain);
});
it("should properly update stock properties for partial transactions", function() {
const shares = 1e3;
const origPrice = stock.price;
stock.playerShares = 2 * shares;
stock.playerAvgPx = origPrice;
const gain = getSellTransactionGain(stock, shares, PositionTypes.Long);
Player.setMoney(0);
expect(sellStock(stock, shares, null, suppressDialogOpt)).to.equal(true);
expect(stock.playerShares).to.equal(shares);
expect(stock.playerAvgPx).to.equal(origPrice);
expect(Player.money.toNumber()).to.equal(gain);
});
});
describe("shortStock()", function() {
it("should fail for invalid arguments", function() {
expect(shortStock({}, 1, null, suppressDialogOpt)).to.equal(false);
expect(shortStock(stock, 0, null, suppressDialogOpt)).to.equal(false);
expect(shortStock(stock, -1, null, suppressDialogOpt)).to.equal(false);
expect(shortStock(stock, NaN, null, suppressDialogOpt)).to.equal(false);
});
it("should fail if player doesn't have enough money", function() {
Player.setMoney(0);
expect(shortStock(stock, 1, null, suppressDialogOpt)).to.equal(false);
});
it("should not allow for transactions that exceed the maximum shares", function() {
const maxShares = stock.maxShares;
expect(shortStock(stock, maxShares + 1, null, suppressDialogOpt)).to.equal(false);
});
it("should return true and properly update stock properties for successful transactions", function() {
const shares = 1e3;
const cost = getBuyTransactionCost(stock, shares, PositionTypes.Short);
Player.setMoney(cost);
expect(shortStock(stock, shares, null, suppressDialogOpt)).to.equal(true);
expect(stock.playerShortShares).to.equal(shares);
expect(stock.playerAvgShortPx).to.be.above(0);
expect(Player.money.toNumber()).to.equal(0);
});
});
describe("sellShort()", function() {
it("should fail for invalid arguments", function() {
expect(sellShort({}, 1, null, suppressDialogOpt)).to.equal(false);
expect(sellShort(stock, 0, null, suppressDialogOpt)).to.equal(false);
expect(sellShort(stock, -1, null, suppressDialogOpt)).to.equal(false);
expect(sellShort(stock, NaN, null, suppressDialogOpt)).to.equal(false);
});
it("should fail if player doesn't have any shares", function() {
Player.setMoney(0);
expect(sellShort(stock, 1, null, suppressDialogOpt)).to.equal(false);
});
it("should not allow for transactions that exceed the maximum shares", function() {
const maxShares = stock.maxShares;
expect(sellShort(stock, maxShares + 1, null, suppressDialogOpt)).to.equal(false);
});
it("should return true and properly update stock properties for successful transactions", function() {
const shares = 1e3;
stock.playerShortShares = shares;
stock.playerAvgShortPx = stock.price;
const gain = getSellTransactionGain(stock, shares, PositionTypes.Short);
Player.setMoney(0);
expect(sellShort(stock, shares, null, suppressDialogOpt)).to.equal(true);
expect(stock.playerShortShares).to.equal(0);
expect(stock.playerAvgShortPx).to.equal(0);
expect(Player.money.toNumber()).to.equal(gain);
});
it("should cap the number of sharse sold to however many the player owns", function() {
const attemptedShares = 2e3;
const actualShares = 1e3;
stock.playerShortShares = actualShares;
stock.playerAvgShortPx = stock.price;
const gain = getSellTransactionGain(stock, actualShares, PositionTypes.Short);
Player.setMoney(0);
expect(sellShort(stock, attemptedShares, null, suppressDialogOpt)).to.equal(true);
expect(stock.playerShortShares).to.equal(0);
expect(stock.playerAvgShortPx).to.equal(0);
expect(Player.money.toNumber()).to.equal(gain);
});
it("should properly update stock properties for partial transactions", function() {
const shares = 1e3;
const origPrice = stock.price;
stock.playerShortShares = 2 * shares;
stock.playerAvgShortPx = origPrice;
const gain = getSellTransactionGain(stock, shares, PositionTypes.Short);
Player.setMoney(0);
expect(sellShort(stock, shares, null, suppressDialogOpt)).to.equal(true);
expect(stock.playerShortShares).to.equal(shares);
expect(stock.playerAvgShortPx).to.equal(origPrice);
expect(Player.money.toNumber()).to.equal(gain);
});
});
});
describe("Order Class", function() {
it("should throw on invalid arguments", function() {
function invalid1() {

@ -1,3 +1,3 @@
// export * from "./Netscript/DynamicRamCalculationTests";
export * from "./Netscript/DynamicRamCalculationTests";
export * from "./Netscript/StaticRamCalculationTests";
export * from "./StockMarketTests";