78 lines
2.7 KiB
JavaScript
78 lines
2.7 KiB
JavaScript
#!/usr/bin/env node
|
|
// 神笔马良 · 自检
|
|
// 不依赖任何三方测试框架. 失败抛出非零退出码.
|
|
'use strict';
|
|
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
const assert = require('assert');
|
|
|
|
const PEN = require('../src/server.js');
|
|
|
|
const TMP_NAME = `test-pen-${Date.now().toString(36)}`;
|
|
const PENNED_DIR = path.resolve(__dirname, '..', 'penned');
|
|
|
|
function cleanup() {
|
|
const d = path.join(PENNED_DIR, TMP_NAME);
|
|
if (fs.existsSync(d)) fs.rmSync(d, { recursive: true, force: true });
|
|
}
|
|
process.on('exit', cleanup);
|
|
|
|
// 1. capabilities 至少有 fs.read / fs.write / shell.run
|
|
const caps = PEN.penCapabilities();
|
|
assert.ok(caps['fs.read'], 'capability fs.read missing');
|
|
assert.ok(caps['fs.write'], 'capability fs.write missing');
|
|
assert.ok(caps['shell.run'], 'capability shell.run missing');
|
|
assert.ok(caps['http.get'], 'capability http.get missing');
|
|
assert.ok(caps['llm.chat'], 'capability llm.chat missing');
|
|
|
|
// 2. write a JS tool
|
|
const w1 = PEN.penWrite({
|
|
name: TMP_NAME,
|
|
description: 'self-test tool',
|
|
language: 'js',
|
|
capabilities: ['fs.read', 'shell.run', 'nonexistent.cap'],
|
|
});
|
|
assert.strictEqual(w1.ok, true);
|
|
assert.deepStrictEqual(w1.meta.capabilities.sort(), ['fs.read', 'shell.run']);
|
|
assert.deepStrictEqual(w1.meta.missing_capabilities, ['nonexistent.cap']);
|
|
assert.ok(fs.existsSync(path.join(PENNED_DIR, TMP_NAME, 'index.js')));
|
|
assert.ok(fs.existsSync(path.join(PENNED_DIR, TMP_NAME, 'tool.meta.json')));
|
|
assert.ok(fs.existsSync(path.join(PENNED_DIR, TMP_NAME, 'README.md')));
|
|
|
|
// 3. list contains it
|
|
const list = PEN.penList();
|
|
assert.ok(list.find((t) => t.name === TMP_NAME), 'penList should include tool');
|
|
|
|
// 4. write same name again → throws
|
|
let threw = false;
|
|
try { PEN.penWrite({ name: TMP_NAME, language: 'js' }); } catch { threw = true; }
|
|
assert.ok(threw, 'duplicate name should throw');
|
|
|
|
// 5. invalid name
|
|
threw = false;
|
|
try { PEN.penWrite({ name: 'BadName', language: 'js' }); } catch { threw = true; }
|
|
assert.ok(threw, 'invalid name should throw');
|
|
|
|
// 6. register
|
|
const reg = PEN.penRegister(TMP_NAME);
|
|
assert.strictEqual(reg.ok, true);
|
|
assert.ok(reg.total >= 1);
|
|
assert.ok(fs.existsSync(reg.registry));
|
|
|
|
// 7. registry.json contains tool
|
|
const regJson = JSON.parse(fs.readFileSync(reg.registry, 'utf8'));
|
|
assert.ok(regJson.tools.find((t) => t.name === TMP_NAME));
|
|
|
|
// Clean registry to avoid polluting the repo
|
|
const regPath = reg.registry;
|
|
const cleaned = JSON.parse(fs.readFileSync(regPath, 'utf8'));
|
|
cleaned.tools = (cleaned.tools || []).filter((t) => t.name !== TMP_NAME);
|
|
if (cleaned.tools.length === 0) {
|
|
fs.unlinkSync(regPath);
|
|
} else {
|
|
fs.writeFileSync(regPath, JSON.stringify(cleaned, null, 2));
|
|
}
|
|
|
|
console.log('✅ all pen tests passed');
|