add testing
This commit is contained in:
9
.github/docker/Dockerfile.alpine
vendored
9
.github/docker/Dockerfile.alpine
vendored
@@ -9,7 +9,6 @@ RUN echo "https://dl-cdn.alpinelinux.org/alpine/edge/main" >> /etc/apk/repositor
|
||||
# Update indexes and install packages
|
||||
RUN apk update && \
|
||||
apk add --no-cache \
|
||||
# Basic dev tools
|
||||
build-base \
|
||||
binutils \
|
||||
mold \
|
||||
@@ -19,21 +18,13 @@ RUN apk update && \
|
||||
git \
|
||||
pkgconf \
|
||||
ccache \
|
||||
# Node.js + npm
|
||||
nodejs \
|
||||
npm \
|
||||
# Misc
|
||||
zip \
|
||||
# Audio/Video dev libs
|
||||
alsa-lib-dev \
|
||||
pulseaudio-dev \
|
||||
libudev-zero-dev \
|
||||
# Wayland dev libs
|
||||
wayland-dev \
|
||||
wayland-protocols \
|
||||
mesa-dev \
|
||||
# Finally, the new SDL3 dev package on Alpine edge
|
||||
sdl3
|
||||
|
||||
# (Optional) If you want a default working directory:
|
||||
WORKDIR /workspace
|
||||
|
||||
15
.github/docker/Dockerfile.linux
vendored
15
.github/docker/Dockerfile.linux
vendored
@@ -1,8 +1,7 @@
|
||||
# Dockerfile.linux
|
||||
FROM ubuntu:24.04
|
||||
FROM ubuntu:plucky
|
||||
|
||||
RUN apt-get update && \
|
||||
apt-get install -y --no-install-recommends \
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
python3 python3-pip \
|
||||
libasound2-dev \
|
||||
libpulse-dev \
|
||||
libudev-dev \
|
||||
@@ -24,8 +23,10 @@ RUN apt-get update && \
|
||||
build-essential \
|
||||
binutils \
|
||||
mold \
|
||||
meson \
|
||||
pkg-config \
|
||||
npm nodejs zip \
|
||||
ccache && \
|
||||
meson \
|
||||
ccache \
|
||||
mingw-w64 \
|
||||
wine \
|
||||
npm nodejs zip && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
8
.github/docker/Dockerfile.mingw
vendored
8
.github/docker/Dockerfile.mingw
vendored
@@ -1,5 +1,4 @@
|
||||
# Dockerfile.windows-cross
|
||||
FROM ubuntu:24.04
|
||||
FROM ubuntu:plucky
|
||||
|
||||
RUN apt-get update && \
|
||||
apt-get install -y --no-install-recommends \
|
||||
@@ -10,8 +9,7 @@ RUN apt-get update && \
|
||||
build-essential \
|
||||
binutils \
|
||||
pkg-config \
|
||||
meson \
|
||||
zip \
|
||||
npm nodejs \
|
||||
ccache && \
|
||||
ccache \
|
||||
npm nodejs && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
31
.github/workflows/build.yml
vendored
31
.github/workflows/build.yml
vendored
@@ -11,7 +11,6 @@ jobs:
|
||||
build-linux:
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
# Pull and run inside your prebuilt Docker image for Linux
|
||||
image: gitea.pockle.world/john/prosperon/linux:latest
|
||||
|
||||
steps:
|
||||
@@ -48,14 +47,27 @@ jobs:
|
||||
- name: Build Prosperon (Linux)
|
||||
run: |
|
||||
export PKG_CONFIG_PATH="${PWD}/sdl3-build/installed_sdl3/lib/pkgconfig:$PKG_CONFIG_PATH"
|
||||
meson setup build_dbg -Dbuildtype=debugoptimized
|
||||
meson compile -C build_dbg
|
||||
meson setup build -Dbuildtype=release -Db_lto=true -Db_ndebug=true
|
||||
meson compile -C build
|
||||
|
||||
- name: Test Prosperon (Linux)
|
||||
env:
|
||||
TRACY_NO_INVARIANT_CHECK: 1
|
||||
run: |
|
||||
meson test --print-errorlogs -C build
|
||||
|
||||
- name: Upload Test Log (Linux)
|
||||
if: ${{ always() }}
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: testlog-linux
|
||||
path: build/meson-logs/testlog.txt
|
||||
|
||||
- name: Create artifact folder (Linux)
|
||||
if: ${{ github.event_name == 'release' && github.event.action == 'published' }}
|
||||
run: |
|
||||
mkdir _pack
|
||||
cp build_dbg/prosperon _pack/
|
||||
# Adjust wildcard if there's a versioned libSDL3. e.g. libSDL3-0.600.0.so
|
||||
cp build/prosperon _pack/
|
||||
cp sdl3-build/installed_sdl3/lib/libSDL3.so _pack/
|
||||
|
||||
- name: Upload Artifact (Linux)
|
||||
@@ -68,8 +80,7 @@ jobs:
|
||||
build-windows:
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
# Pull and run inside your prebuilt Docker image for Windows cross-compilation
|
||||
image: gitea.pockle.world/john/prosperon/mingw:latest
|
||||
image: gitea.pockle.world/john/prosperon/linux:latest
|
||||
|
||||
steps:
|
||||
- name: Check Out Code
|
||||
@@ -112,13 +123,13 @@ jobs:
|
||||
|
||||
- name: Build Prosperon (Windows cross)
|
||||
run: |
|
||||
meson setup -Dbuildtype=debugoptimized --cross-file mingw32.cross build_win
|
||||
meson compile -C build_win
|
||||
meson setup build -Dbuildtype=release -Db_lto=true -Db_ndebug=true --cross-file mingw32.cross
|
||||
meson compile -C build
|
||||
|
||||
- name: Create package folder
|
||||
run: |
|
||||
mkdir _pack
|
||||
cp build_win/prosperon.exe _pack/
|
||||
cp build/prosperon.exe _pack/
|
||||
cp sdl3-build-win/installed_sdl3_win/bin/SDL3.dll _pack/
|
||||
|
||||
- name: Upload Artifact (Windows cross)
|
||||
|
||||
30
meson.build
30
meson.build
@@ -151,9 +151,7 @@ core = custom_target('core.zip',
|
||||
'cd ' + meson.project_source_root() +
|
||||
' && echo "Rebuilding core.zip" && rm -f ' + meson.current_build_dir() + '/core.zip && ' +
|
||||
'zip -r ' + meson.current_build_dir() + '/core.zip scripts fonts icons shaders'
|
||||
],
|
||||
build_always_stale: true,
|
||||
build_by_default: true
|
||||
]
|
||||
)
|
||||
|
||||
prosperon_raw = executable('prosperon_raw', sources,
|
||||
@@ -175,16 +173,36 @@ prosperon = custom_target('prosperon',
|
||||
input: [prosperon_raw, core],
|
||||
command: [
|
||||
'sh', '-c',
|
||||
'cat "$1" "$2" > "$3"',
|
||||
'cat "$1" "$2" > "$3" && chmod +x "$3" >/dev/null 2>&1',
|
||||
'concat',
|
||||
'@INPUT0@',
|
||||
'@INPUT1@',
|
||||
'@OUTPUT@'
|
||||
],
|
||||
build_always: true,
|
||||
build_by_default: true
|
||||
build_always: true
|
||||
)
|
||||
|
||||
prosperon_dep = declare_dependency(
|
||||
link_with:prosperon
|
||||
)
|
||||
|
||||
copy_tests = custom_target(
|
||||
'copy_tests',
|
||||
output: 'tests',
|
||||
command: [
|
||||
'cp', '-rf',
|
||||
join_paths(meson.source_root(), 'tests'),
|
||||
meson.build_root()
|
||||
],
|
||||
build_always: true
|
||||
)
|
||||
|
||||
tests = [
|
||||
'spawn_actor',
|
||||
'empty'
|
||||
]
|
||||
|
||||
foreach file : tests
|
||||
test(file, prosperon, args:['tests/' + file + '.js'], depends:copy_tests)
|
||||
endforeach
|
||||
|
||||
|
||||
@@ -14,4 +14,4 @@ cpu = 'x86_64'
|
||||
endian = 'little'
|
||||
|
||||
[properties]
|
||||
needs_exe_wrapper = false
|
||||
needs_exe_wrapper = true
|
||||
|
||||
@@ -1156,7 +1156,7 @@ var os = use_embed('os')
|
||||
var js = use_embed('js')
|
||||
|
||||
prosperon.on('SIGINT', function() {
|
||||
os.exit()
|
||||
os.exit(1)
|
||||
})
|
||||
|
||||
prosperon.on('SIGABRT', function() {
|
||||
@@ -1218,7 +1218,6 @@ var script_fn = function script_fn(path) {
|
||||
var file = resources.find_script(path)
|
||||
|
||||
if (!file) {
|
||||
// attempt to bare load
|
||||
parsed.module_ret = bare_load(path)
|
||||
if (!parsed.module_ret) throw new Error(`Module ${path} could not be created`)
|
||||
return parsed
|
||||
@@ -1237,8 +1236,6 @@ var script_fn = function script_fn(path) {
|
||||
if (parsed.module_ret === undefined || parsed.module_ret === null)
|
||||
throw new Error(`Module ${module_name} must return a value`)
|
||||
parsed.module_fn = module_fn
|
||||
// console.log(`api for ${path}`)
|
||||
// print_api(parsed.module_ret)
|
||||
}
|
||||
|
||||
if (parsed.program) {
|
||||
@@ -1265,6 +1262,7 @@ function console_rec(category, priority, line, file, msg) {
|
||||
return `${file}:${line}: [${category} ${priority}]: ${msg}\n`
|
||||
}
|
||||
|
||||
io.mkdir('.prosperon')
|
||||
var logfile = io.open('.prosperon/log.txt')
|
||||
|
||||
function pprint(msg, lvl = 0) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
var io = use('io')
|
||||
var util = use('util')
|
||||
var loop = use('loop')
|
||||
|
||||
|
||||
var dumpfolder = ".prosperon";
|
||||
|
||||
@@ -24,51 +24,6 @@ Cmdline.register_order = function (order, fn, doc, usage = "") {
|
||||
fn.usage = `${order} ${usage}`;
|
||||
};
|
||||
|
||||
Cmdline.register_order(
|
||||
"edit",
|
||||
function () {
|
||||
if (!io.exists(projectfile)) {
|
||||
console.print("No game to edit. Try making one with 'prosperon init'.");
|
||||
return;
|
||||
}
|
||||
},
|
||||
"Edit the project in this folder. Give it the name of an UR to edit that specific object.",
|
||||
"?UR?",
|
||||
);
|
||||
|
||||
Cmdline.register_order(
|
||||
"init",
|
||||
function () {
|
||||
if (io.exists(projectfile)) {
|
||||
console.print("Already a game here.");
|
||||
return;
|
||||
}
|
||||
|
||||
io.mkdir(dumpfolder);
|
||||
var project = {};
|
||||
project.version = prosperon.version;
|
||||
project.revision = prosperon.revision;
|
||||
io.slurpwrite(projectfile, json.encode(project));
|
||||
},
|
||||
"Turn the directory into a Prosperon game.",
|
||||
);
|
||||
|
||||
Cmdline.register_order(
|
||||
"debug",
|
||||
function () {
|
||||
Cmdline.orders.play([]);
|
||||
},
|
||||
"Play the game with debugging enabled.",
|
||||
);
|
||||
|
||||
Cmdline.register_order(
|
||||
"web",
|
||||
function () {
|
||||
Cmdline.orders.play([]);
|
||||
},
|
||||
"Play the game in a web browser.",
|
||||
);
|
||||
|
||||
Cmdline.register_order(
|
||||
"makedoc",
|
||||
function() {
|
||||
@@ -115,12 +70,9 @@ for (var m of globals) {
|
||||
"Make documentation."
|
||||
})
|
||||
|
||||
Cmdline.register_order(
|
||||
"play",
|
||||
function (argv) {
|
||||
var app
|
||||
if (io.exists("main.js"))
|
||||
app = actor.spawn("main.js", {}, function(underling, msg) {
|
||||
function spawn_root(script)
|
||||
{
|
||||
return actor.spawn(script, {}, function(underling, msg) {
|
||||
if (msg.message !== "created") return;
|
||||
Object.defineProperty(underling, 'then', {
|
||||
configurable:false,
|
||||
@@ -130,72 +82,26 @@ Cmdline.register_order(
|
||||
}
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
Cmdline.register_order(
|
||||
"play",
|
||||
function (argv) {
|
||||
var app
|
||||
if (io.exists("main.js"))
|
||||
app = spawn_root("main.js")
|
||||
else
|
||||
app = actor.spawn("nogame.js");
|
||||
app = spawn_root("nogame.js")
|
||||
|
||||
// rm actor so it can't be tampered
|
||||
globalThis.actor = undefined
|
||||
|
||||
var ren = use('render')
|
||||
|
||||
var loop = use('loop')
|
||||
while(1) loop.step();
|
||||
},
|
||||
"Play the game present in this folder.",
|
||||
);
|
||||
|
||||
Cmdline.register_order(
|
||||
"pack",
|
||||
function (str) {
|
||||
var packname;
|
||||
if (str.length === 0) packname = "game.zip";
|
||||
else if (str.length > 1) {
|
||||
console.warn("Give me a single filename for the pack.");
|
||||
return;
|
||||
} else packname = str[0];
|
||||
|
||||
console.print(`Packing into ${packname}`);
|
||||
|
||||
io.pack_start(packname);
|
||||
files = allfiles.filter(f => !f.startsWith(".git"));
|
||||
files = files.filter(f => !f.startsWith(".nova"));
|
||||
files = files.filter(f => !f.includes(".DS_Store"));
|
||||
files = files.filter(f => !f.startsWith(".gitignore"));
|
||||
console.print(files);
|
||||
for (var f of files) io.pack_add(f);
|
||||
io.pack_end();
|
||||
},
|
||||
"Pack the game into the given name.",
|
||||
"NAME",
|
||||
);
|
||||
|
||||
Cmdline.register_order(
|
||||
"cdb",
|
||||
function (argv) {
|
||||
var cdb = "game.zip";
|
||||
if (!io.exists(cdb)) {
|
||||
console.print(`No 'game.zip' present.`);
|
||||
return;
|
||||
}
|
||||
if (argv.length === 0) {
|
||||
console.print(`cdb name: ${cdb}`);
|
||||
}
|
||||
},
|
||||
"CDB commands.",
|
||||
);
|
||||
|
||||
Cmdline.register_order(
|
||||
"qoa",
|
||||
function (argv) {
|
||||
var sounds = Resources.sounds.filter(x => x !== "qoa");
|
||||
for (var file of argv) {
|
||||
if (!sounds.includes(file.ext())) continue;
|
||||
console.print(`converting ${file}`);
|
||||
io.save_qoa(file);
|
||||
}
|
||||
},
|
||||
"Convert file(s) to qoa.",
|
||||
);
|
||||
|
||||
Cmdline.register_order(
|
||||
"about",
|
||||
function (argv) {
|
||||
@@ -213,92 +119,6 @@ Cmdline.register_order(
|
||||
"Get information about this game.",
|
||||
);
|
||||
|
||||
Cmdline.register_order(
|
||||
"ur",
|
||||
function (argv) {
|
||||
// game.loadurs();
|
||||
for (var i of ur._list.sort()) console.print(i);
|
||||
},
|
||||
"Get information about the ur types in your game.",
|
||||
);
|
||||
|
||||
Cmdline.register_order(
|
||||
"env",
|
||||
function (argv) {
|
||||
if (argv.length > 2) return;
|
||||
var gg = json.decode(io.slurp(projectfile));
|
||||
if (argv.length === 0) {
|
||||
console.print(json.encode(gg, null, 1));
|
||||
return;
|
||||
}
|
||||
|
||||
if (argv.length === 1) {
|
||||
var v = gg[argv[0]];
|
||||
if (!v) {
|
||||
console.print(`Value ${argv[0]} not found.`);
|
||||
return;
|
||||
}
|
||||
console.print(`${argv[0]}:${v}`);
|
||||
} else {
|
||||
gg[argv[0]] = argv[1];
|
||||
console.print(`Set ${argv[0]}:${v}`);
|
||||
console.print(json.encode(gg, null, 1));
|
||||
io.slurpwrite(projectfile, json.encode(gg));
|
||||
}
|
||||
},
|
||||
"Get or set game variables.",
|
||||
);
|
||||
|
||||
Cmdline.register_order(
|
||||
"unpack",
|
||||
function () {
|
||||
console.print("Unpacking not implemented.");
|
||||
},
|
||||
"Unpack this binary's contents into this folder for editing.",
|
||||
);
|
||||
|
||||
Cmdline.register_order(
|
||||
"build",
|
||||
function () {
|
||||
console.print("Building not implemented.");
|
||||
},
|
||||
"Build static assets for this project.",
|
||||
);
|
||||
|
||||
Cmdline.register_order(
|
||||
"nota",
|
||||
function (argv) {
|
||||
for (var file of argv) {
|
||||
if (!io.exists(file)) {
|
||||
console.print(`File ${file} does not exist.`);
|
||||
continue;
|
||||
}
|
||||
|
||||
var obj = json.decode(io.slurp(file));
|
||||
var nn = nota.encode(obj);
|
||||
io.slurpwrite(file.strip_ext() + ".nota", nn);
|
||||
}
|
||||
},
|
||||
"Create a nota file from a json.",
|
||||
);
|
||||
|
||||
Cmdline.register_order(
|
||||
"json",
|
||||
function (argv) {
|
||||
for (var file of argv) {
|
||||
if (!io.exists(file)) {
|
||||
console.print(`File ${file} does not exist.`);
|
||||
continue;
|
||||
}
|
||||
console.print(file.ext());
|
||||
var obj = nota.decode(io.slurp(file));
|
||||
var nn = json.encode(obj);
|
||||
io.slurpwrite(file.strip_ext() + ".json", nn);
|
||||
}
|
||||
},
|
||||
"Create a JSON from a nota.",
|
||||
);
|
||||
|
||||
Cmdline.register_order(
|
||||
"api",
|
||||
function (obj) {
|
||||
@@ -330,8 +150,12 @@ Cmdline.register_order(
|
||||
console.print("Need something to run.");
|
||||
return;
|
||||
}
|
||||
|
||||
console.print(eval(script));
|
||||
try {
|
||||
spawn_root(script)
|
||||
} catch(e) {
|
||||
console.error(e);
|
||||
os.exit(1);
|
||||
}
|
||||
},
|
||||
"Run a given script. SCRIPT can be the script itself, or a file containing the script",
|
||||
"SCRIPT",
|
||||
@@ -384,80 +208,12 @@ function cmd_args(cmds) {
|
||||
cmds.shift()
|
||||
if (cmds.length === 0) cmds[0] = "play";
|
||||
else if (!Cmdline.orders[cmds[0]]) {
|
||||
console.warn(`Command ${cmds[0]} not found. Playing instead.`);
|
||||
cmds[0] = "play";
|
||||
// assume it's a script
|
||||
cmds[1] = cmds[0]
|
||||
cmds[0] = "run"
|
||||
}
|
||||
|
||||
Cmdline.orders[cmds[0]](cmds.slice(1));
|
||||
}
|
||||
|
||||
Cmdline.register_order(
|
||||
"clean",
|
||||
function (argv) {
|
||||
console.print("Cleaning not implemented.");
|
||||
},
|
||||
"Clean up a given object file.",
|
||||
"JSON ...",
|
||||
);
|
||||
|
||||
Cmdline.register_order(
|
||||
"test",
|
||||
function (argv) {
|
||||
use("test.js");
|
||||
},
|
||||
"Run tests.",
|
||||
);
|
||||
|
||||
Cmdline.register_cmd(
|
||||
"l",
|
||||
function (n) {
|
||||
console.level = n;
|
||||
},
|
||||
"Set log level.",
|
||||
);
|
||||
|
||||
function convertYAMLtoJSON(yamlString) {
|
||||
const lines = yamlString.split("\n");
|
||||
const jsonObj = {};
|
||||
|
||||
let currentKey = "";
|
||||
let currentValue = "";
|
||||
let currentDepth = 0;
|
||||
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
const line = lines[i].trim();
|
||||
if (!line || line.startsWith("#")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const depth = (line.match(/^\s+/g) || [""])[0].length;
|
||||
const keyValue = line.split(":");
|
||||
const key = keyValue[0].trim();
|
||||
const value = keyValue[1].trim();
|
||||
|
||||
if (depth > currentDepth) {
|
||||
jsonObj[currentKey] = convertYAMLtoJSON(currentValue);
|
||||
currentKey = key;
|
||||
currentValue = value;
|
||||
} else if (depth === currentDepth) {
|
||||
jsonObj[currentKey] = convertYAMLtoJSON(currentValue);
|
||||
currentKey = key;
|
||||
currentValue = value;
|
||||
} else {
|
||||
jsonObj[currentKey] = convertYAMLtoJSON(currentValue);
|
||||
currentKey = "";
|
||||
currentValue = "";
|
||||
i--; // To reprocess the current line with updated values
|
||||
}
|
||||
|
||||
currentDepth = depth;
|
||||
}
|
||||
|
||||
if (currentKey) {
|
||||
jsonObj[currentKey] = convertYAMLtoJSON(currentValue);
|
||||
}
|
||||
|
||||
return jsonObj;
|
||||
}
|
||||
|
||||
return cmd_args;
|
||||
|
||||
@@ -93,15 +93,18 @@ if (!ret) {
|
||||
int main(int argc, char **argv) {
|
||||
prosperon = argv[0];
|
||||
|
||||
|
||||
PHYSFS_init(argv[0]);
|
||||
char *base = PHYSFS_getBaseDir();
|
||||
PHYSFS_setWriteDir(base);
|
||||
|
||||
PHYSFS_mount(base, "/", 0);
|
||||
prosperon_mount_core();
|
||||
|
||||
|
||||
/* int mounted = PHYSFS_mount("core.zip", NULL, 0);
|
||||
if (!mounted) {
|
||||
printf("Could not mount core. Reason: %s\n", PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode()));
|
||||
return 1;
|
||||
}
|
||||
*/
|
||||
script_startup(argc, argv); // runs engine.js
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -31,16 +31,11 @@ JSValue on_exception = JS_UNDEFINED;
|
||||
|
||||
#define ENGINE "scripts/core/engine.js"
|
||||
|
||||
#ifndef NDEBUG
|
||||
#define JS_EVAL_FLAGS JS_EVAL_FLAG_STRICT
|
||||
#else
|
||||
#define JS_EVAL_FLAGS JS_EVAL_FLAG_STRICT | JS_EVAL_FLAG_STRIP
|
||||
#endif
|
||||
|
||||
#ifdef TRACY_ENABLE
|
||||
#include <tracy/TracyC.h>
|
||||
|
||||
|
||||
#if defined(__APPLE__)
|
||||
#define MALLOC_OVERHEAD 0
|
||||
#else
|
||||
@@ -183,6 +178,7 @@ void script_startup(int argc, char **argv) {
|
||||
|
||||
void script_stop()
|
||||
{
|
||||
return;
|
||||
JS_FreeContext(js);
|
||||
JS_FreeRuntime(rt);
|
||||
JS_FreeValue(js,on_exception);
|
||||
|
||||
1
tests/empty.js
Normal file
1
tests/empty.js
Normal file
@@ -0,0 +1 @@
|
||||
os.exit(1)
|
||||
2
tests/spawn_actor.js
Normal file
2
tests/spawn_actor.js
Normal file
@@ -0,0 +1,2 @@
|
||||
this.spawn()
|
||||
console.log("SPAWNED")
|
||||
Reference in New Issue
Block a user