cc-libs/tests/mcpcomputer.lua
2026-06-15 19:57:45 +02:00

147 lines
5.4 KiB
Lua

local createLibTest = require('/apis/libtest');
local createMcpComputer = require('/apis/libmcpcomputer');
local testlib = createLibTest({ ... });
local function fakeOs(id, label)
return {
getComputerID = function() return id; end,
getComputerLabel = function() return label; end,
};
end
local function fakeFs()
local files = {};
return {
files = files,
open = function(path, mode)
if mode ~= 'w' then
return nil, 'unsupported mode';
end
if string.find(path, 'missing-parent', 1, true) then
return nil, 'No such file';
end
local buffer = {};
return {
write = function(value)
buffer[#buffer + 1] = value;
end,
close = function()
files[path] = table.concat(buffer);
end,
};
end,
};
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('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('writeFile writes and overwrites file content', function()
local mcpComputer = createMcpComputer();
local fsLike = fakeFs();
local first = mcpComputer.writeFile('/tmp/note.txt', 'hello', fsLike);
local second = mcpComputer.writeFile('/tmp/note.txt', 'goodbye', fsLike);
testlib.assertEquals(first.ok, true);
testlib.assertEquals(first.path, '/tmp/note.txt');
testlib.assertEquals(first.bytes, 5);
testlib.assertEquals(second.ok, true);
testlib.assertEquals(second.bytes, 7);
testlib.assertEquals(fsLike.files['/tmp/note.txt'], 'goodbye');
end);
testlib.test('writeFile allows empty content', function()
local mcpComputer = createMcpComputer();
local fsLike = fakeFs();
local result = mcpComputer.writeFile('/tmp/empty.txt', '', fsLike);
testlib.assertEquals(result.ok, true);
testlib.assertEquals(result.bytes, 0);
testlib.assertEquals(fsLike.files['/tmp/empty.txt'], '');
end);
testlib.test('writeFile validates path and content', function()
local mcpComputer = createMcpComputer();
local fsLike = fakeFs();
local missingPath = mcpComputer.writeFile('', 'hello', fsLike);
local invalidContent = mcpComputer.writeFile('/tmp/note.txt', 12, fsLike);
local missingParent = mcpComputer.writeFile('/missing-parent/note.txt', 'hello', fsLike);
testlib.assertEquals(missingPath.ok, false);
testlib.assertTrue(string.find(missingPath.error, 'path', 1, true));
testlib.assertEquals(invalidContent.ok, false);
testlib.assertTrue(string.find(invalidContent.error, 'content', 1, true));
testlib.assertEquals(missingParent.ok, false);
testlib.assertTrue(string.find(missingParent.error, 'No such file', 1, true));
end);
testlib.run();