Files

128 lines
6.5 KiB
TypeScript

import assert from "assert";
import * as fs from "fs";
import * as path from "path";
import JSZip from "jszip";
import { describe, it } from "mocha";
import { getIncludeDirs, getIncludePatterns, getSharedFileSystemName, matchDependencyPatterns } from "../../src/common/toolmeta";
import { getToolForPlatform } from "../../src/common/toolselect";
import { toolRoot } from "../../src/tools/toolroot";
import {
parseUrustDiagnostics, urustDebugToResult, urustPlatformName, UrustDebug
} from "../../src/worker/tools/urustparse";
describe('urust tool', function () {
it('is selected by .rs on 6502 platforms', function () {
assert.strictEqual(getToolForPlatform('devel-6502', 'main.rs'), 'urust');
assert.strictEqual(getToolForPlatform('nes', 'game.rs'), 'urust');
});
it('scans include_bytes!/include_str! as dependencies', function () {
const src = 'static A: &[u8] = &*include_bytes!("art/a.bin");\n' +
'const S: &str = include_str!( "t.txt" );\n// include_bytes!("x") is also matched\n';
const deps = matchDependencyPatterns(src, getIncludePatterns('urust'));
assert.deepStrictEqual(deps, ['art/a.bin', 't.txt', 'x']);
});
it('scans //#resource files as dependencies', function () {
const src = '//#resource "vicdual.toml"\n//#flag c --board vicdual.toml\nfn main() {}\n';
assert.deepStrictEqual(matchDependencyPatterns(src, getIncludePatterns('urust')), ['vicdual.toml']);
});
it('scans mod/use as module dependencies', function () {
const src = 'mod audio;\npub mod bcd;\n' +
'use audio::{music_play, SND_COIN};\nuse bcd::bcd_add;\nuse rs8::reset;\n';
const deps = matchDependencyPatterns(src, getIncludePatterns('urust'));
// `mod` names the file (foo.rs or foo/mod.rs); `use` is scanned for editor
// links but skips the bare rs8 items (they live in the compiler)
assert.deepStrictEqual(deps,
['audio.rs', 'bcd.rs', 'audio/mod.rs', 'bcd/mod.rs', 'audio.rs', 'bcd.rs']);
});
it('links rs8 register modules to the bundled sources', function () {
const src = 'use rs8::nes::*;\nuse rs8::io;\nuse rs8::{reg, reset};\n';
const deps = matchDependencyPatterns(src, getIncludePatterns('urust'));
// one file per register module; bare items (reg/reset) have no file
assert.deepStrictEqual(deps, ['nes.rs', 'io.rs']);
});
it('links every platform module urust bundles', function () {
const src = 'use rs8::apple2::*;\nuse rs8::vic20::*;\nuse rs8::zx::*;\n';
assert.deepStrictEqual(matchDependencyPatterns(src, getIncludePatterns('urust')),
['apple2.rs', 'vic20.rs', 'zx.rs']);
});
it('exposes the rs8 sources as a WASI filesystem for the editor', function () {
assert.strictEqual(getSharedFileSystemName('urust', 'devel-6502'), 'wasi:urust-fs.zip');
assert.deepStrictEqual(getIncludeDirs('urust', 'devel-6502'), ['/rs8']);
});
it('ships the rs8 module sources in the WASI filesystem package', async function () {
// the package is built outside the repo, so it may not be here
const zipfile = path.resolve(toolRoot(), 'src/worker/fs/urust-fs.zip');
if (!fs.existsSync(zipfile)) return this.skip();
// /rs8/<module>.rs has to resolve for every module the include pattern links
const zip = await JSZip.loadAsync(fs.readFileSync(zipfile));
for (const f of ['lib.rs', 'apple2.rs', 'atari8.rs', 'c64.rs', 'conio.rs', 'io.rs', 'nes.rs', 'rand.rs', 'vcs.rs', 'vic20.rs', 'zx.rs']) {
assert.ok(zip.file('rs8/' + f), 'missing rs8/' + f);
}
});
it('maps platform ids to urust platforms', function () {
assert.strictEqual(urustPlatformName('devel-6502'), 'devel-6502');
assert.strictEqual(urustPlatformName('nes'), 'nes');
assert.strictEqual(urustPlatformName('c64'), 'c64');
assert.strictEqual(urustPlatformName('atari8-800xl'), 'atari8');
assert.strictEqual(urustPlatformName('vcs'), 'vcs');
assert.strictEqual(urustPlatformName('apple2'), 'apple2');
assert.strictEqual(urustPlatformName('vic20'), 'vic20');
// the Z80 backend names the whole computer, not the CPU
assert.strictEqual(urustPlatformName('zx'), 'zx-spectrum');
});
it('parses JSON diagnostics; end column only on a single line', function () {
const json = JSON.stringify([
{ level: 'error', message: 'bad type', file: 'main.rs', line: 2, col: 5, endLine: 2, endCol: 9 },
{ level: 'error', message: 'spans lines', file: 'main.rs', line: 4, col: 1, endLine: 6, endCol: 2 },
{ level: 'warning', message: 'in `f`: big', file: null, line: 0, col: 0, endLine: 0, endCol: 0 },
]);
const { errors, warnings } = parseUrustDiagnostics(json + '\nurust: unknown option `-x`\n', 'main.rs');
assert.deepStrictEqual(errors[0], { line: 2, path: 'main.rs', msg: 'bad type', start: 4, end: 8 });
assert.deepStrictEqual(errors[1], { line: 4, path: 'main.rs', msg: 'spans lines', start: 0 });
assert.deepStrictEqual(errors[2], { line: 0, path: 'main.rs', msg: 'unknown option `-x`' });
assert.deepStrictEqual(warnings, [{ line: 0, path: 'main.rs', msg: 'in `f`: big', severity: 'warning' }]);
});
const dbg: UrustDebug = {
files: ['main.rs'],
symbols: [
{ name: 'main', addr: 0x8000, size: 20, kind: 'code', bank: null, ram: false },
{ name: 'score', addr: 0x10, size: 2, kind: 'data', bank: null, ram: true },
{ name: 'NMI', addr: 0x8100, size: 0, kind: 'code', bank: null, ram: false },
],
lines: [
{ addr: 0x8000, size: 3, bank: null, file: 'main.rs', line: 3, col: 5, endLine: 3, endCol: 12, func: 'main' },
{ addr: 0x8003, size: 2, bank: null, file: 'main.rs', line: 3, col: 5, endLine: 4, endCol: 2, func: null },
],
segments: [
{ name: 'ROM', start: 0x8000, size: 20, bank: null, type: 'rom' },
{ name: 'RAM', start: 0, size: 0x800, bank: null, type: 'ram' },
],
};
it('converts debug info for the debugger and memory map', function () {
const r = urustDebugToResult(dbg, ['main.rs']);
assert.deepStrictEqual(r.listings['main.rs'].lines[0],
{ line: 3, offset: 0x8000, path: 'main.rs', start: 4, end: 11, iscode: true, func: 'main' });
assert.strictEqual('end' in r.listings['main.rs'].lines[1], false);
assert.deepStrictEqual(r.symbolmap, { main: 0x8000, score: 0x10, NMI: 0x8100 });
assert.deepStrictEqual(r.symbolsizes, { main: 20, score: 2 });
assert.strictEqual(r.segments[1].type, 'ram');
assert.strictEqual(r.banked, false);
});
it('flags banked output', function () {
const banked = { ...dbg, lines: [{ ...dbg.lines[0], bank: 2 }] };
assert.strictEqual(urustDebugToResult(banked, ['main.rs']).banked, true);
});
});