78 lines
2.9 KiB
JavaScript
78 lines
2.9 KiB
JavaScript
import {
|
|||
|
|
spawnSync
|
||
|
|
} from 'node:child_process';
|
||
|
|
import * as e from './common.mjs';
|
||
|
|
function command(cmd, args, opts={
|
||
|
|
}){
|
||
|
|
const r=spawnSync(cmd, args, {
|
||
|
|
encoding:'utf8',
|
||
|
|
...opts
|
||
|
|
});
|
||
|
|
if(r.status!==0)e.fail(r.error?.message??`Command failed (${r.status}): ${cmd}`);
|
||
|
|
return r.stdout;
|
||
|
|
}
|
||
|
|
export function main(){
|
||
|
|
const a=e.cli(['output'], {
|
||
|
|
zig:'zig',
|
||
|
|
optimize:'ReleaseSafe'
|
||
|
|
}),
|
||
|
|
repo=e.ROOT,
|
||
|
|
output=e.path.resolve(a.output);
|
||
|
|
e.fs.mkdirSync(output, {
|
||
|
|
recursive:true
|
||
|
|
});
|
||
|
|
const version=command(a.zig, ['version']).trim();
|
||
|
|
if(version!=='0.14.1')e.fail('Zig 0.14.1 required; found '+version);
|
||
|
|
const zon=e.readText(e.path.join(repo, 'protocol/build.zig.zon')),
|
||
|
|
pkg=zon.match(/\.hash\s*=\s*"(protobuf-[^"]+)"/)?.[1];
|
||
|
|
if(!pkg)e.fail('Missing protobuf package hash');
|
||
|
|
const cache=process.env.ZIG_GLOBAL_CACHE_DIR??e.path.join(e.os.homedir(), '.cache/zig'),
|
||
|
|
protobuf=e.path.join(cache, 'p', pkg, 'src/protobuf.zig');
|
||
|
|
if(!e.fs.existsSync(protobuf))e.fail('Cached protobuf dependency not found: '+protobuf);
|
||
|
|
const scratch=e.fs.mkdtempSync(e.path.join(output, 'gridfight-test-'));
|
||
|
|
e.fs.cpSync(e.path.join(repo, 'gameserver/src'), e.path.join(scratch, 'source/src'), {
|
||
|
|
recursive:true
|
||
|
|
});
|
||
|
|
e.fs.cpSync(e.path.join(repo, 'protocol/src'), e.path.join(scratch, 'protocol'), {
|
||
|
|
recursive:true
|
||
|
|
});
|
||
|
|
const runtime=e.path.join(scratch, 'runtime');
|
||
|
|
e.fs.mkdirSync(runtime);
|
||
|
|
e.fs.symlinkSync(e.path.join(repo, 'resources'), e.path.join(runtime, 'resources'), 'dir');
|
||
|
|
const entry=e.path.join(scratch, 'source/src/gridfight_test_root.zig');
|
||
|
|
e.fs.writeFileSync(entry, 'const std = @import("std");\ntest "GridFight imports" { std.testing.refAllDecls(@import("services/grid_fight.zig")); }\n');
|
||
|
|
const executable=e.path.join(scratch, 'gridfight-tests'),
|
||
|
|
args=['test', `-O${a.optimize}`, '--dep', 'protocol', `-Mroot=${entry}`, '--dep', 'protobuf', `-Mprotocol=${e.path.join(scratch,'protocol/root.zig')}`, `-Mprotobuf=${protobuf}`, '--cache-dir', e.path.join(output, 'test-cache'), '--global-cache-dir', e.path.join(output, 'zig-cache'), `-femit-bin=${executable}`, '--test-no-exec'];
|
||
|
|
function logged(cmd, args, log, opts){
|
||
|
|
const fd=e.fs.openSync(e.path.join(output, log), 'w');
|
||
|
|
try{
|
||
|
|
command(cmd, args, {
|
||
|
|
...opts,
|
||
|
|
stdio:['ignore', fd, fd]
|
||
|
|
});
|
||
|
|
} finally{
|
||
|
|
e.fs.closeSync(fd);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
logged(a.zig, args, 'test-build.log', {
|
||
|
|
cwd:scratch
|
||
|
|
});
|
||
|
|
logged(executable, [], 'tests.log', {
|
||
|
|
cwd:runtime,
|
||
|
|
env:{
|
||
|
|
...process.env,
|
||
|
|
GRIDFIGHT_TEST_RUNTIME:runtime
|
||
|
|
}
|
||
|
|
});
|
||
|
|
const text=e.readText(e.path.join(output, 'tests.log')),
|
||
|
|
m=text.match(/All (\d+) tests passed\./);
|
||
|
|
if(text.includes('SKIP')||!m)e.fail('Skipped or incomplete suite; inspect tests.log');
|
||
|
|
e.atomic_json(e.path.join(output, 'test-result.json'), {
|
||
|
|
zig:version,
|
||
|
|
tests_passed:Number(m[1]),
|
||
|
|
runtime,
|
||
|
|
gameplay_verified:false
|
||
|
|
}, 2, true);
|
||
|
|
process.stdout.write(text);
|
||
|
|
}
|
||
|
|
e.runMain(import.meta.url, main);
|