From 1ae73aed06e4e8c9fa1495bb1265c9ed3a98e1c9 Mon Sep 17 00:00:00 2001 From: John Alanbrook Date: Mon, 17 Feb 2025 21:10:16 -0600 Subject: [PATCH] add testing --- .github/docker/Dockerfile.alpine | 9 - .github/docker/Dockerfile.linux | 59 +++---- .github/docker/Dockerfile.mingw | 8 +- .github/workflows/build.yml | 31 ++-- meson.build | 30 +++- mingw32.cross | 2 +- scripts/core/engine.js | 6 +- scripts/modules/cmd.js | 290 +++---------------------------- source/prosperon.c | 11 +- source/script.c | 6 +- tests/empty.js | 1 + tests/spawn_actor.js | 2 + 12 files changed, 115 insertions(+), 340 deletions(-) create mode 100644 tests/empty.js create mode 100644 tests/spawn_actor.js diff --git a/.github/docker/Dockerfile.alpine b/.github/docker/Dockerfile.alpine index bf598cf7..a99591a8 100644 --- a/.github/docker/Dockerfile.alpine +++ b/.github/docker/Dockerfile.alpine @@ -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 diff --git a/.github/docker/Dockerfile.linux b/.github/docker/Dockerfile.linux index 86b111b3..66762b70 100644 --- a/.github/docker/Dockerfile.linux +++ b/.github/docker/Dockerfile.linux @@ -1,31 +1,32 @@ -# Dockerfile.linux -FROM ubuntu:24.04 +FROM ubuntu:plucky -RUN apt-get update && \ - apt-get install -y --no-install-recommends \ - libasound2-dev \ - libpulse-dev \ - libudev-dev \ - libwayland-dev \ - wayland-protocols \ - libxkbcommon-dev \ - libx11-dev \ - libxext-dev \ - libxrandr-dev \ - libxcursor-dev \ - libxi-dev \ - libxinerama-dev \ - libxss-dev \ - libegl1-mesa-dev \ - libgl1-mesa-dev \ - cmake \ - ninja-build \ - git \ - build-essential \ - binutils \ - mold \ - meson \ - pkg-config \ - npm nodejs zip \ - ccache && \ +RUN apt-get update && apt-get install -y --no-install-recommends \ + python3 python3-pip \ + libasound2-dev \ + libpulse-dev \ + libudev-dev \ + libwayland-dev \ + wayland-protocols \ + libxkbcommon-dev \ + libx11-dev \ + libxext-dev \ + libxrandr-dev \ + libxcursor-dev \ + libxi-dev \ + libxinerama-dev \ + libxss-dev \ + libegl1-mesa-dev \ + libgl1-mesa-dev \ + cmake \ + ninja-build \ + git \ + build-essential \ + binutils \ + mold \ + pkg-config \ + meson \ + ccache \ + mingw-w64 \ + wine \ + npm nodejs zip && \ rm -rf /var/lib/apt/lists/* diff --git a/.github/docker/Dockerfile.mingw b/.github/docker/Dockerfile.mingw index 2b966b24..60d8d5f4 100644 --- a/.github/docker/Dockerfile.mingw +++ b/.github/docker/Dockerfile.mingw @@ -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/* diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index cfa3e82b..043671c3 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -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) diff --git a/meson.build b/meson.build index 695f44a9..090924fc 100644 --- a/meson.build +++ b/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 + diff --git a/mingw32.cross b/mingw32.cross index f8e6e8a1..af60c542 100644 --- a/mingw32.cross +++ b/mingw32.cross @@ -14,4 +14,4 @@ cpu = 'x86_64' endian = 'little' [properties] -needs_exe_wrapper = false +needs_exe_wrapper = true diff --git a/scripts/core/engine.js b/scripts/core/engine.js index 83c82533..75452249 100644 --- a/scripts/core/engine.js +++ b/scripts/core/engine.js @@ -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) { diff --git a/scripts/modules/cmd.js b/scripts/modules/cmd.js index ba247a53..e02fee9f 100644 --- a/scripts/modules/cmd.js +++ b/scripts/modules/cmd.js @@ -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; diff --git a/source/prosperon.c b/source/prosperon.c index d1364547..0c923f6c 100644 --- a/source/prosperon.c +++ b/source/prosperon.c @@ -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; + return 0; } diff --git a/source/script.c b/source/script.c index b89636db..b2057728 100644 --- a/source/script.c +++ b/source/script.c @@ -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 - #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); diff --git a/tests/empty.js b/tests/empty.js new file mode 100644 index 00000000..1788a682 --- /dev/null +++ b/tests/empty.js @@ -0,0 +1 @@ +os.exit(1) diff --git a/tests/spawn_actor.js b/tests/spawn_actor.js new file mode 100644 index 00000000..117d28a0 --- /dev/null +++ b/tests/spawn_actor.js @@ -0,0 +1,2 @@ +this.spawn() +console.log("SPAWNED")