cc-libs/tests/mcpcomputer.lua

195 lines
7.0 KiB
Lua

local createLibTest = require('/apis/libtest');
local createMcpComputer = require('/apis/libmcpcomputer');
local testlib = createLibTest({ ... });
local function packed(...)
return table.pack(...);
end
local function fakeOs(id, label)
return {
getComputerID = function() return id; end,
getComputerLabel = function() return label; end,
};
end
testlib.test('parseArgs accepts positional URL', function()
local mcpComputer = createMcpComputer();
local config = mcpComputer.parseArgs(packed('ws://127.0.0.1:3001'));
testlib.assertEquals(config.url, 'ws://127.0.0.1:3001');
end);
testlib.test('parseArgs accepts -url option', function()
local mcpComputer = createMcpComputer();
local config = mcpComputer.parseArgs(packed('-url', 'ws://bridge:3001'));
testlib.assertEquals(config.url, 'ws://bridge:3001');
end);
testlib.test('parseArgs rejects missing URL', function()
local mcpComputer = createMcpComputer();
local config, err = mcpComputer.parseArgs(packed());
testlib.assertEquals(config, nil);
testlib.assertTrue(string.find(err, 'missing websocket URL', 1, true));
end);
testlib.test('formatPong includes computer id and label', function()
local mcpComputer = createMcpComputer();
testlib.assertEquals(mcpComputer.formatPong(fakeOs(12, 'base-turtle')), 'pong from 12 (Label: base-turtle)');
end);
testlib.test('formatPong renders missing or empty labels as null', function()
local mcpComputer = createMcpComputer();
testlib.assertEquals(mcpComputer.formatPong(fakeOs(7, nil)), 'pong from 7 (Label: null)');
testlib.assertEquals(mcpComputer.formatPong(fakeOs(8, '')), 'pong from 8 (Label: null)');
end);
testlib.test('hello identifies the current computer', function()
local mcpComputer = createMcpComputer();
local hello = mcpComputer.hello(fakeOs(3, 'agent'));
testlib.assertEquals(hello.type, 'hello');
testlib.assertEquals(hello.computerId, 3);
testlib.assertEquals(hello.computerLabel, 'agent');
end);
testlib.test('handleRequest responds to ping', function()
local mcpComputer = createMcpComputer();
local response = mcpComputer.handleRequest({
type = 'request',
id = 'req-1',
method = 'ping',
}, fakeOs(42, 'worker'));
testlib.assertEquals(response.type, 'response');
testlib.assertEquals(response.id, 'req-1');
testlib.assertEquals(response.ok, true);
testlib.assertEquals(response.result, 'pong from 42 (Label: worker)');
end);
testlib.test('executeLua captures output and return values', function()
local mcpComputer = createMcpComputer();
local result = mcpComputer.executeLua("print('hello', 'world'); write('tail'); return 2 + 3, nil, 'ok'");
testlib.assertEquals(result.ok, true);
testlib.assertEquals(result.output, 'hello\tworld\ntail');
testlib.assertEquals(result.returns[1].type, 'number');
testlib.assertEquals(result.returns[1].value, 5);
testlib.assertEquals(result.returns[2].type, 'nil');
testlib.assertEquals(result.returns[3].type, 'string');
testlib.assertEquals(result.returns[3].value, 'ok');
end);
testlib.test('executeLua reports runtime errors with captured output', function()
local mcpComputer = createMcpComputer();
local result = mcpComputer.executeLua("print('before'); error('boom', 0)");
testlib.assertEquals(result.ok, false);
testlib.assertEquals(result.output, 'before\n');
testlib.assertTrue(string.find(result.error, 'boom', 1, true));
end);
testlib.test('executeLua reports syntax errors', function()
local mcpComputer = createMcpComputer();
local result = mcpComputer.executeLua("print('unterminated'\nreturn 1");
testlib.assertEquals(result.ok, false);
testlib.assertEquals(result.output, '');
testlib.assertTrue(string.find(result.error, 'expected', 1, true)
or string.find(result.error, 'near', 1, true));
end);
testlib.test('executeLua serializes non-json return values as descriptors', function()
local mcpComputer = createMcpComputer();
local result = mcpComputer.executeLua('return { answer = 42 }, function() end, coroutine.create(function() end)');
testlib.assertEquals(result.ok, true);
testlib.assertEquals(result.returns[1].type, 'table');
testlib.assertTrue(type(result.returns[1].repr) == 'string');
testlib.assertEquals(result.returns[2].type, 'function');
testlib.assertTrue(type(result.returns[2].repr) == 'string');
testlib.assertEquals(result.returns[3].type, 'thread');
testlib.assertTrue(type(result.returns[3].repr) == 'string');
end);
testlib.test('executeLua leaves direct terminal writes out of captured output', function()
local mcpComputer = createMcpComputer();
local result = mcpComputer.executeLua("term.write('visible'); return 'done'");
testlib.assertEquals(result.ok, true);
testlib.assertEquals(result.output, '');
testlib.assertEquals(result.returns[1].type, 'string');
testlib.assertEquals(result.returns[1].value, 'done');
end);
testlib.test('handleRequest executes lua code', function()
local mcpComputer = createMcpComputer();
local response = mcpComputer.handleRequest({
type = 'request',
id = 'req-exec',
method = 'exec-lua',
params = { code = "print('ran'); return true" },
}, fakeOs(42, 'worker'));
testlib.assertEquals(response.type, 'response');
testlib.assertEquals(response.id, 'req-exec');
testlib.assertEquals(response.ok, true);
testlib.assertEquals(response.result.output, 'ran\n');
testlib.assertEquals(response.result.returns[1].type, 'boolean');
testlib.assertEquals(response.result.returns[1].value, true);
end);
testlib.test('handleRequest reports invalid exec-lua code', function()
local mcpComputer = createMcpComputer();
local response = mcpComputer.handleRequest({
type = 'request',
id = 'req-empty-exec',
method = 'exec-lua',
params = { code = '' },
}, fakeOs(42, 'worker'));
testlib.assertEquals(response.type, 'response');
testlib.assertEquals(response.id, 'req-empty-exec');
testlib.assertEquals(response.ok, false);
testlib.assertEquals(response.result.output, '');
testlib.assertTrue(string.find(response.error, 'non-empty string', 1, true));
local missing = mcpComputer.handleRequest({
type = 'request',
id = 'req-missing-exec',
method = 'exec-lua',
params = {},
}, fakeOs(42, 'worker'));
testlib.assertEquals(missing.ok, false);
testlib.assertTrue(string.find(missing.error, 'non-empty string', 1, true));
end);
testlib.test('handleRequest reports unknown methods', function()
local mcpComputer = createMcpComputer();
local response = mcpComputer.handleRequest({
type = 'request',
id = 'req-2',
method = 'dance',
}, fakeOs(42, 'worker'));
testlib.assertEquals(response.type, 'response');
testlib.assertEquals(response.id, 'req-2');
testlib.assertEquals(response.ok, false);
testlib.assertEquals(response.error, 'unknown method');
end);
testlib.test('handleRequest ignores malformed frames', function()
local mcpComputer = createMcpComputer();
testlib.assertEquals(mcpComputer.handleRequest({ type = 'request', method = 'ping' }, fakeOs(1, nil)), nil);
testlib.assertEquals(mcpComputer.handleRequest({ type = 'hello' }, fakeOs(1, nil)), nil);
end);
testlib.run();