227 lines
7.4 KiB
Lua
227 lines
7.4 KiB
Lua
local createLibTest = require('/apis/libtest');
|
|
|
|
local testlib = createLibTest({ ... });
|
|
|
|
local function containsLine(lines, expected)
|
|
for _, line in ipairs(lines) do
|
|
if line == expected then return true; end
|
|
end
|
|
return false;
|
|
end
|
|
|
|
local function containsText(lines, expected)
|
|
for _, line in ipairs(lines) do
|
|
if string.find(line, expected, 1, true) then return true; end
|
|
end
|
|
return false;
|
|
end
|
|
|
|
local function fakeSettings(values)
|
|
return {
|
|
values = values or {},
|
|
saveCount = 0,
|
|
get = function(self, key)
|
|
return self.values[key];
|
|
end,
|
|
set = function(self, key, value)
|
|
self.values[key] = value;
|
|
end,
|
|
save = function(self)
|
|
self.saveCount = self.saveCount + 1;
|
|
return true;
|
|
end,
|
|
};
|
|
end
|
|
|
|
local function runCloud(args, opts)
|
|
opts = opts or {};
|
|
local lines = {};
|
|
local writes = {};
|
|
local readMasks = {};
|
|
local cloudRequests = {};
|
|
local queuedEvents = {};
|
|
local settingsLib = opts.settings or fakeSettings();
|
|
local readValues = opts.readValues or {};
|
|
|
|
local env = setmetatable({
|
|
print = function(line)
|
|
lines[#lines + 1] = line or '';
|
|
end,
|
|
write = function(text)
|
|
writes[#writes + 1] = text or '';
|
|
end,
|
|
read = function(mask)
|
|
readMasks[#readMasks + 1] = mask;
|
|
local value = readValues[#readMasks];
|
|
if value == nil then return ''; end
|
|
return value;
|
|
end,
|
|
settings = {
|
|
get = function(key) return settingsLib:get(key); end,
|
|
set = function(key, value) return settingsLib:set(key, value); end,
|
|
save = function() return settingsLib:save(); end,
|
|
},
|
|
os = setmetatable({
|
|
queueEvent = function(...)
|
|
queuedEvents[#queuedEvents + 1] = table.pack(...);
|
|
end,
|
|
}, { __index = os }),
|
|
require = function(path)
|
|
if path == '/apis/libcloud' then
|
|
return function()
|
|
return {
|
|
request = function(msgType, payload, requestOpts)
|
|
cloudRequests[#cloudRequests + 1] = {
|
|
msgType = msgType,
|
|
payload = payload,
|
|
opts = requestOpts,
|
|
};
|
|
return opts.requestOk ~= false, opts.requestResult or { serverOk = true, opencodeOk = true };
|
|
end,
|
|
};
|
|
end;
|
|
end
|
|
if path == '/apis/libversion' then
|
|
return function()
|
|
return { forSelf = function() return '0.0.0-test'; end };
|
|
end;
|
|
end
|
|
return require(path);
|
|
end,
|
|
}, { __index = _G });
|
|
|
|
local chunk, loadErr = loadfile('/programs/cloud.lua', 't', env);
|
|
if not chunk then error(loadErr, 0); end
|
|
local ok, err = pcall(chunk, table.unpack(args or {}));
|
|
if not ok then error(err, 0); end
|
|
|
|
return {
|
|
lines = lines,
|
|
writes = writes,
|
|
readMasks = readMasks,
|
|
cloudRequests = cloudRequests,
|
|
queuedEvents = queuedEvents,
|
|
settings = settingsLib,
|
|
};
|
|
end
|
|
|
|
testlib.test('cloud help lists status and login without health', function()
|
|
local ctx = runCloud({ '--help' });
|
|
|
|
testlib.assertTrue(containsLine(ctx.lines, ' cloud status'));
|
|
testlib.assertTrue(containsLine(ctx.lines, ' cloud login [--force|-f] [password]'));
|
|
testlib.assertTrue(not containsLine(ctx.lines, ' cloud health'));
|
|
testlib.assertTrue(not containsText(ctx.lines, 'set-password'));
|
|
end);
|
|
|
|
testlib.test('cloud health is not kept as an alias', function()
|
|
local ctx = runCloud({ 'health' }, {
|
|
settings = fakeSettings({ ['cloud.url'] = 'wss://example.test' }),
|
|
});
|
|
|
|
testlib.assertEquals(#ctx.cloudRequests, 0);
|
|
testlib.assertTrue(containsLine(ctx.lines, 'cloud usage:'));
|
|
end);
|
|
|
|
testlib.test('cloud status probes the server', function()
|
|
local ctx = runCloud({ 'status' }, {
|
|
settings = fakeSettings({ ['cloud.url'] = 'wss://example.test' }),
|
|
requestResult = { serverOk = true, opencodeOk = false, opencodeDetail = 'missing key' },
|
|
});
|
|
|
|
testlib.assertEquals(#ctx.cloudRequests, 1);
|
|
testlib.assertEquals(ctx.cloudRequests[1].msgType, 'probe_server');
|
|
testlib.assertTrue(containsLine(ctx.lines, 'serverOk: true'));
|
|
testlib.assertTrue(containsLine(ctx.lines, 'opencodeOk: false'));
|
|
testlib.assertTrue(containsLine(ctx.lines, 'opencode: missing key'));
|
|
end);
|
|
|
|
testlib.test('cloud set-password is not kept as an alias', function()
|
|
local ctx = runCloud({ 'set-password', 'hunter2' });
|
|
|
|
testlib.assertEquals(ctx.settings.values['cloud.password'], nil);
|
|
testlib.assertEquals(ctx.settings.saveCount, 0);
|
|
testlib.assertTrue(containsLine(ctx.lines, 'cloud usage:'));
|
|
end);
|
|
|
|
testlib.test('cloud login stores a missing password with masked input', function()
|
|
local settingsLib = fakeSettings();
|
|
local ctx = runCloud({ 'login' }, {
|
|
settings = settingsLib,
|
|
readValues = { 'hunter2' },
|
|
});
|
|
|
|
testlib.assertEquals(ctx.writes[1], 'Password: ');
|
|
testlib.assertEquals(ctx.readMasks[1], '*');
|
|
testlib.assertEquals(settingsLib.values['cloud.password'], 'hunter2');
|
|
testlib.assertEquals(settingsLib.saveCount, 1);
|
|
testlib.assertEquals(ctx.queuedEvents[1][1], 'trapos_cloud_reconnect');
|
|
testlib.assertTrue(containsLine(ctx.lines, 'cloud.password set'));
|
|
end);
|
|
|
|
testlib.test('cloud login stores a password argument without prompting', function()
|
|
local settingsLib = fakeSettings();
|
|
local ctx = runCloud({ 'login', 'hunter2' }, {
|
|
settings = settingsLib,
|
|
readValues = { 'unused' },
|
|
});
|
|
|
|
testlib.assertEquals(#ctx.readMasks, 0);
|
|
testlib.assertEquals(settingsLib.values['cloud.password'], 'hunter2');
|
|
testlib.assertEquals(settingsLib.saveCount, 1);
|
|
testlib.assertEquals(ctx.queuedEvents[1][1], 'trapos_cloud_reconnect');
|
|
end);
|
|
|
|
testlib.test('cloud login rejects replacing without force', function()
|
|
local settingsLib = fakeSettings({ ['cloud.password'] = 'old' });
|
|
local ctx = runCloud({ 'login' }, {
|
|
settings = settingsLib,
|
|
readValues = { 'new' },
|
|
});
|
|
|
|
testlib.assertEquals(#ctx.readMasks, 0);
|
|
testlib.assertEquals(settingsLib.values['cloud.password'], 'old');
|
|
testlib.assertEquals(settingsLib.saveCount, 0);
|
|
testlib.assertEquals(#ctx.queuedEvents, 0);
|
|
testlib.assertTrue(containsText(ctx.lines, 'use cloud login --force'));
|
|
end);
|
|
|
|
testlib.test('cloud login --force replaces an existing password', function()
|
|
local settingsLib = fakeSettings({ ['cloud.password'] = 'old' });
|
|
local ctx = runCloud({ 'login', '--force' }, {
|
|
settings = settingsLib,
|
|
readValues = { 'new' },
|
|
});
|
|
|
|
testlib.assertEquals(settingsLib.values['cloud.password'], 'new');
|
|
testlib.assertEquals(settingsLib.saveCount, 1);
|
|
testlib.assertEquals(ctx.queuedEvents[1][1], 'trapos_cloud_reconnect');
|
|
end);
|
|
|
|
testlib.test('cloud login -f replaces an existing password from argument', function()
|
|
local settingsLib = fakeSettings({ ['cloud.password'] = 'old' });
|
|
local ctx = runCloud({ 'login', '-f', 'new' }, {
|
|
settings = settingsLib,
|
|
});
|
|
|
|
testlib.assertEquals(#ctx.readMasks, 0);
|
|
testlib.assertEquals(settingsLib.values['cloud.password'], 'new');
|
|
testlib.assertEquals(settingsLib.saveCount, 1);
|
|
testlib.assertEquals(ctx.queuedEvents[1][1], 'trapos_cloud_reconnect');
|
|
end);
|
|
|
|
testlib.test('cloud login rejects an empty password', function()
|
|
local settingsLib = fakeSettings();
|
|
local ctx = runCloud({ 'login' }, {
|
|
settings = settingsLib,
|
|
readValues = { '' },
|
|
});
|
|
|
|
testlib.assertEquals(settingsLib.values['cloud.password'], nil);
|
|
testlib.assertEquals(settingsLib.saveCount, 0);
|
|
testlib.assertEquals(#ctx.queuedEvents, 0);
|
|
testlib.assertTrue(containsLine(ctx.lines, 'cloud.password not changed: password cannot be empty'));
|
|
end);
|
|
|
|
testlib.run();
|