Skip to content

Commit

Permalink
[SYNC] Extending unit tests / mocks for testing. (#7)
Browse files Browse the repository at this point in the history
  • Loading branch information
Neloreck authored Jul 5, 2023
2 parents 6eca2d0 + 02abb45 commit 9e5014d
Show file tree
Hide file tree
Showing 54 changed files with 899 additions and 315 deletions.
6 changes: 3 additions & 3 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
[submodule "cli/bin"]
path = cli/bin
url = https://github.com/xray-forge/stalker-xrf-bin.git
branch = master
branch = main

[submodule "src/resources"]
path = src/resources
url = https://github.com/xray-forge/stalker-xrf-resources.git
branch = master
branch = main

[submodule "src/typedefs/xray16"]
path = src/typedefs/xray16
url = https://github.com/xray-forge/xray-16-types
branch = master
branch = main
10 changes: 6 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
# 🎮 [Stalker XRF template](README.md)
# 🎮 [Stalker XRF](README.md)

![status](https://github.com/xray-forge/stalker-xrf-template/actions/workflows/build_and_test.yml/badge.svg)
[![language-ts](https://img.shields.io/badge/language-typescript-blue.svg?style=flat)](https://github.com/xray-forge/stalker-xrf-template/search?l=typescript)
[![types](https://img.shields.io/badge/docs-types-blue.svg?style=flat)](https://xray-forge.github.io/xray-16-types/index.html)
[![license](https://img.shields.io/badge/license-MIT-blue.svg?style=flat)](https://github.com/Neloreck/dreamstate/blob/master/LICENSE)

<p>
XRF template for stalker mods and modded game packages. <br/>
Fully rewritten stalker script engine with typescript. <br/>
Template for stalker mods and modded game packages. <br/>
</p>

## 📦 In short
Expand All @@ -18,6 +19,7 @@ XRF template for stalker mods and modded game packages. <br/>
- Simple translations generation
- Game profiling / debugging tools
- Creation of custom modded game package
- Unit tests coverage

## 📍 Purpose

Expand Down Expand Up @@ -103,6 +105,6 @@ Optimizations, quality and logics updates are welcome.
## 🏗️ Assets

- Extended assets: [https://gitlab.com/xray-forge/stalker-xrf-resources-extended](https://gitlab.com/xray-forge/stalker-xrf-resources-extended)
- EN locale assets: [https://gitlab.com/xray-forge/stalker-xrf-resources-locale-en](https://gitlab.com/xray-forge/stalker-xrf-resources-locale-en)
- EN locale assets: [https://gitlab.com/xray-forge/stalker-xrf-resources-locale-eng](https://gitlab.com/xray-forge/stalker-xrf-resources-locale-eng)
- UA locale assets: [https://gitlab.com/xray-forge/stalker-xrf-resources-locale-ukr](https://gitlab.com/xray-forge/stalker-xrf-resources-locale-ukr)
- RU locale assets: [https://gitlab.com/xray-forge/stalker-xrf-resources-locale-ru](https://gitlab.com/xray-forge/stalker-xrf-resources-locale-ru)
- RU locale assets: [https://gitlab.com/xray-forge/stalker-xrf-resources-locale-rus](https://gitlab.com/xray-forge/stalker-xrf-resources-locale-rus)
4 changes: 2 additions & 2 deletions cli/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
"..\\..\\stalker-xrf-resources-extended"
],
"mod_assets_locales": {
"eng": ["..\\..\\stalker-xrf-resources-locale-en"],
"eng": ["..\\..\\stalker-xrf-resources-locale-eng"],
"ukr": ["..\\..\\stalker-xrf-resources-locale-ukr"],
"rus": ["..\\..\\stalker-xrf-resources-locale-ru"],
"rus": ["..\\..\\stalker-xrf-resources-locale-rus"],
"pol": []
}
},
Expand Down
4 changes: 2 additions & 2 deletions doc/BUILDING_CUSTOM_GAME_PACKAGE.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,6 @@ npm run cli pack game -- --engine release --build
### 🏗️ Assets links

- Extended assets: [https://gitlab.com/xray-forge/stalker-xrf-resources-extended](https://gitlab.com/xray-forge/stalker-xrf-resources-extended)
- EN locale assets: [https://gitlab.com/xray-forge/stalker-xrf-resources-locale-en](https://gitlab.com/xray-forge/stalker-xrf-resources-locale-en)
- EN locale assets: [https://gitlab.com/xray-forge/stalker-xrf-resources-locale-eng](https://gitlab.com/xray-forge/stalker-xrf-resources-locale-eng)
- UA locale assets: [https://gitlab.com/xray-forge/stalker-xrf-resources-locale-ukr](https://gitlab.com/xray-forge/stalker-xrf-resources-locale-ukr)
- RU locale assets: [https://gitlab.com/xray-forge/stalker-xrf-resources-locale-ru](https://gitlab.com/xray-forge/stalker-xrf-resources-locale-ru)
- RU locale assets: [https://gitlab.com/xray-forge/stalker-xrf-resources-locale-rus](https://gitlab.com/xray-forge/stalker-xrf-resources-locale-rus)
2 changes: 1 addition & 1 deletion src/engine/core/database/registry.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ describe("registry storage", () => {
expect(registry.activeSmartTerrainId).toBeNull();
expect(registry.managers instanceof LuaTable).toBeTruthy();
expect(registry.schemes instanceof LuaTable).toBeTruthy();
expect(registry.conditionLists instanceof LuaTable).toBeTruthy();
expect(registry.cache.conditionLists instanceof LuaTable).toBeTruthy();
expect(registry.actorCombat instanceof LuaTable).toBeTruthy();
expect(registry.objects instanceof LuaTable).toBeTruthy();
expect(registry.offlineObjects instanceof LuaTable).toBeTruthy();
Expand Down
10 changes: 6 additions & 4 deletions src/engine/core/database/registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,12 @@ export const registry = {
* List of activated schemes in game.
*/
schemes: new LuaTable<EScheme, TAbstractSchemeConstructor>(),
/**
* Memoized condlist for parsing simplification, where key is string data and value is parsed descriptor.
*/
conditionLists: new LuaTable<string, TConditionList>(),
cache: {
/**
* Memoized condlist for parsing simplification, where key is string data and value is parsed descriptor.
*/
conditionLists: new LuaTable<string, TConditionList>(),
},
/**
* Set of objects in combat with actor.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { GlobalSoundManager } from "@/engine/core/managers/sounds/GlobalSoundMan
import { EStalkerState, ILookTargetDescriptor } from "@/engine/core/objects/state";
import { EZombieCombatAction, ISchemeCombatState } from "@/engine/core/schemes/combat/ISchemeCombatState";
import { LuaLogger } from "@/engine/core/utils/logging";
import { chance } from "@/engine/core/utils/number";
import { chance } from "@/engine/core/utils/random";
import { copyVector, createEmptyVector } from "@/engine/core/utils/vector";
import { scriptSounds } from "@/engine/lib/constants/sound/script_sounds";
import {
Expand Down
2 changes: 1 addition & 1 deletion src/engine/core/schemes/heli_move/HeliCombat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import {
TConditionList,
} from "@/engine/core/utils/ini";
import { LuaLogger } from "@/engine/core/utils/logging";
import { pickRandom } from "@/engine/core/utils/number";
import { pickRandom } from "@/engine/core/utils/random";
import { copyVector, createEmptyVector, createVector, distanceBetween2d } from "@/engine/core/utils/vector";
import { ACTOR, NIL } from "@/engine/lib/constants/words";
import { ClientObject, IniFile, NetPacket, Optional, Reader, TNumberId, TRate, Vector } from "@/engine/lib/types";
Expand Down
2 changes: 1 addition & 1 deletion src/engine/core/schemes/heli_move/HeliFire.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {

import { getIdBySid, registry } from "@/engine/core/database";
import { LuaLogger } from "@/engine/core/utils/logging";
import { pickRandom } from "@/engine/core/utils/number";
import { pickRandom } from "@/engine/core/utils/random";
import { distanceBetween2d } from "@/engine/core/utils/vector";
import { MAX_U16 } from "@/engine/lib/constants/memory";
import { ACTOR, NIL } from "@/engine/lib/constants/words";
Expand Down
15 changes: 13 additions & 2 deletions src/engine/core/utils/assertion.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { describe, expect, it } from "@jest/globals";
import { print_stack } from "xray16";
import { log, print_stack } from "xray16";

import { abort, assert, assertBoolean, assertDefined } from "@/engine/core/utils/assertion";
import { abort, assert, assertBoolean, assertDefined, callstack } from "@/engine/core/utils/assertion";
import { mockDebug } from "@/fixtures/lua/mocks/lua_debug.mock";

describe("'debug' utils", () => {
it("'abort' should correctly throw exceptions", () => {
Expand Down Expand Up @@ -45,4 +46,14 @@ describe("'debug' utils", () => {
expect(() => assertDefined(true)).not.toThrow();
expect(() => assertDefined(false)).not.toThrow();
});

it("'callstack' should correctly print debug stack", () => {
callstack();
callstack(6);
callstack(4);

expect(mockDebug.traceback).toHaveBeenNthCalledWith(1, 5);
expect(mockDebug.traceback).toHaveBeenNthCalledWith(2, 6);
expect(mockDebug.traceback).toHaveBeenNthCalledWith(3, 4);
});
});
6 changes: 3 additions & 3 deletions src/engine/core/utils/ini/ini_parse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -149,8 +149,8 @@ export function parseParameters<T extends string>(data: T): LuaArray<T> {
*/
export function parseConditionsList(data: string): TConditionList {
// All condition lists are just readonly descriptors. Cache them.
if (registry.conditionLists.has(data)) {
return registry.conditionLists.get(data);
if (registry.cache.conditionLists.has(data)) {
return registry.cache.conditionLists.get(data);
}

const result: LuaArray<IConfigSwitchCondition> = new LuaTable();
Expand Down Expand Up @@ -189,7 +189,7 @@ export function parseConditionsList(data: string): TConditionList {
}

// Memoize condlist.
registry.conditionLists.set(data, result);
registry.cache.conditionLists.set(data, result);

return result;
}
Expand Down
95 changes: 95 additions & 0 deletions src/engine/core/utils/logging.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import { describe, expect, it, jest } from "@jest/globals";
import { log, print_stack, time_global } from "xray16";

import { LuaLogger } from "@/engine/core/utils/logging";
import { toJSON } from "@/engine/core/utils/transform/json";
import { gameConfig } from "@/engine/lib/configs/GameConfig";
import { replaceFunctionMock, resetFunctionMock } from "@/fixtures/utils";

describe("'logging' utils", () => {
const logging: { LuaLogger: typeof LuaLogger } = jest.requireActual("@/engine/core/utils/logging");
const Logger: typeof LuaLogger = logging.LuaLogger;

it("'LuaLogger' should correctly initialize", () => {
const logger: LuaLogger = new Logger("tst");

expect(logger.prefix).toBe("[tst]");
expect(logger.isEnabled).toBe(true);

expect(new Logger("another", false).isEnabled).toBe(false);
});

it("'LuaLogger' should correctly handle enabled-disabled state", () => {
const logger: LuaLogger = new Logger("tst");

jest.spyOn(logger, "logAs").mockImplementation(() => {});

logger.isEnabled = false;
gameConfig.DEBUG.IS_LOG_ENABLED = false;

logger.info("test");
expect(logger.logAs).not.toHaveBeenCalled();

logger.isEnabled = true;

logger.info("test");
expect(logger.logAs).not.toHaveBeenCalled();

gameConfig.DEBUG.IS_LOG_ENABLED = true;

logger.info("test");
expect(logger.logAs).toHaveBeenCalled();
});

it("'LuaLogger' should correctly call log", () => {
const logger: LuaLogger = new Logger("tst");

resetFunctionMock(log);
replaceFunctionMock(time_global, () => 1000);

logger.warn("test");
logger.info("test");
logger.error("test");
logger.pushEmptyLine();
logger.pushSeparator();

expect(log).toHaveBeenCalledTimes(5);
expect(log).toHaveBeenNthCalledWith(1, "[1000][tst][warn] test");
expect(log).toHaveBeenNthCalledWith(2, "[1000][tst][info] test");
expect(log).toHaveBeenNthCalledWith(3, "[1000][tst][error] test");
expect(log).toHaveBeenNthCalledWith(4, "[1000][tst][info] ");
expect(log).toHaveBeenNthCalledWith(5, "[1000][tst][info] =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-");
});

it("'LuaLogger' should correctly generate prefix", () => {
replaceFunctionMock(time_global, () => 1000);

expect(new Logger("tst").getFullPrefix()).toBe("[1000][tst]");
expect(new Logger("another").getFullPrefix()).toBe("[1000][another]");
});

it("'LuaLogger' should correctly print stack", () => {
new Logger("tst").printStack();
expect(print_stack).toHaveBeenCalledTimes(1);
});

it("'LuaLogger' should correctly print table", () => {
const logger: LuaLogger = new Logger("tst");

jest.spyOn(logger, "logAs").mockImplementation(() => {});

logger.table({ test: true, another: 10 });

expect(logger.logAs).toHaveBeenCalledWith("[table]", "[tst]", $fromArray([toJSON({ test: true, another: 10 })]));
});

it("'LuaLogger' should correctly print with logAs", () => {
resetFunctionMock(log);

const logger: LuaLogger = new Logger("tst");

logger.logAs("[info]", "[prfx]", $fromArray(["a", "b", "c"]));

expect(log).toHaveBeenCalledWith("[1000][prfx][info] a b c");
});
});
20 changes: 9 additions & 11 deletions src/engine/core/utils/logging.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,15 @@ import { log, print_stack, time_global } from "xray16";
import { toJSON } from "@/engine/core/utils/transform/json";
import { gameConfig } from "@/engine/lib/configs/GameConfig";
import { FALSE, NIL, TRUE } from "@/engine/lib/constants/words";
import { AnyArgs, AnyObject, TLabel, TName } from "@/engine/lib/types";
import { AnyArgs, AnyObject, TLabel } from "@/engine/lib/types";

/**
* Lua logger class.
* Stores prefix, enabled-disabled flags and uses shared statics to print data.
*
* todo: This model does not work with lua and JIT optimisation. Probably should use singleton logger and share logic.
*/
export class LuaLogger {
public readonly prefix: TLabel;
protected isEnabled: boolean;
public isEnabled: boolean;

public constructor(prefix: TLabel, isEnabled: boolean = true) {
this.isEnabled = isEnabled;
Expand All @@ -29,7 +27,7 @@ export class LuaLogger {
*/
public warn(...args: AnyArgs): void {
if (gameConfig.DEBUG.IS_LOG_ENABLED && this.isEnabled) {
this.logAs("[WARN]", this.prefix, $fromArray(args));
this.logAs("[warn]", this.prefix, $fromArray(args));
}
}

Expand All @@ -38,7 +36,7 @@ export class LuaLogger {
*/
public info(...args: AnyArgs): void {
if (gameConfig.DEBUG.IS_LOG_ENABLED && this.isEnabled) {
this.logAs("[INFO]", this.prefix, $fromArray(args));
this.logAs("[info]", this.prefix, $fromArray(args));
}
}

Expand All @@ -47,7 +45,7 @@ export class LuaLogger {
*/
public error(...args: AnyArgs): void {
if (gameConfig.DEBUG.IS_LOG_ENABLED && this.isEnabled) {
this.logAs("[ERROR]", this.prefix, $fromArray(args));
this.logAs("[error]", this.prefix, $fromArray(args));
}
}

Expand All @@ -57,7 +55,7 @@ export class LuaLogger {
public table(table: AnyObject): void;
public table(table: LuaTable): void {
if (gameConfig.DEBUG.IS_LOG_ENABLED && this.isEnabled) {
this.logAs("[TABLE]", this.prefix, $fromArray([toJSON(table)]));
this.logAs("[table]", this.prefix, $fromArray([toJSON(table)]));
}
}

Expand Down Expand Up @@ -85,14 +83,14 @@ export class LuaLogger {
/**
* Get full string prefix for current logger instance.
*/
public getFullPrefix(method: TName = "info"): TLabel {
return string.format("[%s]%s%s", time_global(), this.prefix, method);
public getFullPrefix(): TLabel {
return string.format("[%s]%s", time_global(), this.prefix);
}

/**
* Print generic message with provided level of logging and configured prefix.
*/
protected logAs(level: string, prefix: string, args: LuaTable<number>): void {
public logAs(level: string, prefix: string, args: LuaTable<number>): void {
// Map some values to successfully print in composed string.
for (const idx of $range(1, args.length())) {
const it = args.get(idx);
Expand Down
23 changes: 13 additions & 10 deletions src/engine/core/utils/number.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { describe, expect, it } from "@jest/globals";

import { chance, clampNumber } from "@/engine/core/utils/number";
import { clampNumber, round } from "@/engine/core/utils/number";

describe("'number' utils", () => {
it("'clamp' should correctly limit numbers", () => {
Expand All @@ -11,14 +11,17 @@ describe("'number' utils", () => {
expect(clampNumber(25, 10, 50)).toBe(25);
});

it("'chance' should correctly randomize", () => {
expect(chance(100)).toBeTruthy();
expect(chance(1000, 1000)).toBeTruthy();
expect(chance(0)).toBeFalsy();
expect(chance(0, 1000)).toBeFalsy();

expect(() => chance(101)).toThrow();
expect(() => chance(200, 20)).toThrow();
expect(() => chance(101, 200)).not.toThrow();
it("'round' should correctly round value", () => {
expect(round(1.5)).toBe(2);
expect(round(1.1)).toBe(1);
expect(round(1.155)).toBe(1);
expect(round(5)).toBe(5);
expect(round(0)).toBe(0);
expect(round(0.5)).toBe(1);
expect(round(-0.6)).toBe(-1);
expect(round(-0.5)).toBe(0);
expect(round(-1.6)).toBe(-2);
expect(round(-1.5)).toBe(-1);
expect(round(-1.1)).toBe(-1);
});
});
Loading

0 comments on commit 9e5014d

Please sign in to comment.