cc-libs/packages/trapos/tests/install-trapos.lua
2026-06-16 22:16:58 +02:00

205 lines
6.3 KiB
Lua

local createLibTest = require('/apis/libtest');
local testlib = createLibTest({ ... });
local function parentDir(path)
return path:match('^(.*)/[^/]+$');
end
local function sandboxPath(root, path)
if path:sub(1, 1) == '/' then
return root .. path;
end
return root .. '/' .. path;
end
local function fakeFs(root)
return {
exists = function(path)
return fs.exists(sandboxPath(root, path));
end,
makeDir = function(path)
fs.makeDir(sandboxPath(root, path));
end,
open = function(path, mode)
return fs.open(sandboxPath(root, path), mode);
end,
delete = function(path)
fs.delete(sandboxPath(root, path));
end,
};
end
local function fakeHttp(routes)
return {
get = function(url)
local body = routes[url];
if not body then return nil; end
return {
readAll = function() return body; end,
close = function() end,
};
end,
};
end
local INSTALL_BASE = 'https://git.trapcloud.fr/guillaumearm/cc-libs/raw/branch/master/';
local function installRoutes()
return {
[INSTALL_BASE .. 'manifest.json'] = textutils.serializeJSON({ name = 'TrapOS', version = 'test' }),
[INSTALL_BASE .. 'packages/trapos-core/ccpm.json'] = textutils.serializeJSON({
name = 'trapos-core',
version = '1',
dependencies = {},
files = { 'apis/libccpm.lua', 'programs/ccpm.lua' },
}),
[INSTALL_BASE .. 'packages/trapos-core/apis/libccpm.lua'] = 'libccpm-body',
[INSTALL_BASE .. 'packages/trapos-core/programs/ccpm.lua'] = 'ccpm-body',
};
end
-- Run install-trapos.lua inside a sandboxed env. `args` is a list of CLI args.
-- Returns { calls, root } for assertions.
local function runInstall(root, args)
fs.delete(root);
fs.makeDir(root);
local routes = installRoutes();
local calls = {
executes = {},
path = '/rom/programs',
dir = '/',
rebooted = false,
};
local fsApi = fakeFs(root);
local env = setmetatable({
fs = fsApi,
http = fakeHttp(routes),
os = {
reboot = function()
calls.rebooted = true;
calls.executes[#calls.executes + 1] = { program = '__reboot__', args = {} };
end,
},
print = function() end,
read = function() return 'yes'; end,
write = function() end,
shell = {
dir = function() return calls.dir; end,
setDir = function(path) calls.dir = path; end,
path = function() return calls.path; end,
setPath = function(path) calls.path = path; end,
execute = function(program, ...)
local rest = { ... };
calls.executes[#calls.executes + 1] = { program = program, args = rest };
if program ~= 'wget' then return true; end
local url, target = rest[1], rest[2];
local body = routes[url];
if not body then return false; end
local dir = parentDir(target);
if dir then fsApi.makeDir(dir); end
local f = fsApi.open(target, 'w');
f.write(body);
f.close();
return true;
end,
},
}, { __index = _G });
local chunk, loadErr = loadfile('/trapos/install-trapos.lua', 't', env);
if not chunk then error(loadErr, 0); end
local ok, err = pcall(chunk, table.unpack(args));
if not ok then error(err, 0); end
return calls;
end
local function findExecute(calls, program, firstArg)
for _, call in ipairs(calls.executes) do
if call.program == program then
if firstArg == nil or call.args[1] == firstArg then
return true;
end
end
end
return false;
end
local function findExecuteIndex(calls, program, firstArg)
for i, call in ipairs(calls.executes) do
if call.program == program then
if firstArg == nil or call.args[1] == firstArg then
return i;
end
end
end
return nil;
end
testlib.test('programs path resolves the ccpm command', function()
local previous = shell.path();
shell.setPath('/rom/programs:/programs');
local resolved = shell.resolveProgram('ccpm');
shell.setPath(previous);
testlib.assertEquals(resolved, 'programs/ccpm.lua');
end);
testlib.test('fresh bootstrap seeds a gitea master registry and runs ccpm', function()
local root = '/install-trapos-test/full';
local calls = runInstall(root, {});
testlib.assertTrue(fs.exists(root .. '/programs/ccpm.lua'));
testlib.assertTrue(string.find(calls.path, '/programs', 1, true));
local f = fs.open(root .. '/trapos/ccpm.json', 'r');
local config = textutils.unserializeJSON(f.readAll());
f.close();
testlib.assertEquals(config.registries[1].branch, 'master');
testlib.assertEquals(config.registries[1].type, 'gitea');
f = fs.open(root .. '/trapos/ccpm.lock.json', 'r');
local lock = textutils.unserializeJSON(f.readAll());
f.close();
testlib.assertEquals(lock.packages['trapos-core'].explicit, false);
end);
testlib.test('default install runs update, install trapos and postinstall', function()
local root = '/install-trapos-test/default';
local calls = runInstall(root, {});
testlib.assertTrue(findExecute(calls, 'ccpm', 'update'));
testlib.assertTrue(findExecute(calls, 'ccpm', 'install'));
testlib.assertTrue(findExecute(calls, 'trapos-postinstall'));
end);
testlib.test('default install runs postinstall before reboot', function()
local root = '/install-trapos-test/order';
local calls = runInstall(root, {});
local postinstallIndex = findExecuteIndex(calls, 'trapos-postinstall');
local rebootIndex = findExecuteIndex(calls, '__reboot__');
testlib.assertTrue(postinstallIndex ~= nil, 'postinstall was not run');
testlib.assertTrue(rebootIndex ~= nil, 'reboot was not run');
testlib.assertTrue(postinstallIndex < rebootIndex, 'postinstall must run before reboot');
testlib.assertEquals(calls.rebooted, true);
end);
testlib.test('--cpm-only stops after the ccpm bootstrap', function()
local root = '/install-trapos-test/cpm-only';
local calls = runInstall(root, { '--cpm-only' });
testlib.assertTrue(fs.exists(root .. '/programs/ccpm.lua'));
testlib.assertTrue(not findExecute(calls, 'ccpm', 'update'));
testlib.assertTrue(not findExecute(calls, 'ccpm', 'install'));
testlib.assertTrue(not findExecute(calls, 'trapos-postinstall'));
testlib.assertEquals(calls.rebooted, false);
local f = fs.open(root .. '/trapos/ccpm.lock.json', 'r');
local lock = textutils.unserializeJSON(f.readAll());
f.close();
testlib.assertEquals(lock.packages['trapos-core'].explicit, true);
end);
testlib.run();