Convert tests to Typescript
This commit is contained in:
parent
f2dd9b96a3
commit
3f6cfd67b7
|
@ -0,0 +1,29 @@
|
||||||
|
module.exports = {
|
||||||
|
'moduleNameMapper': {
|
||||||
|
'^js/(.*)': '<rootDir>/js/$1',
|
||||||
|
'^test/(.*)': '<rootDir>/test/$1',
|
||||||
|
'\\.css$': 'identity-obj-proxy',
|
||||||
|
'\\.scss$': 'identity-obj-proxy',
|
||||||
|
},
|
||||||
|
'roots': [
|
||||||
|
'js/',
|
||||||
|
'test/',
|
||||||
|
],
|
||||||
|
'testMatch': [
|
||||||
|
'**/?(*.)+(spec|test).+(ts|js|tsx)'
|
||||||
|
],
|
||||||
|
'transform': {
|
||||||
|
'^.+\\.js$': 'babel-jest',
|
||||||
|
'^.+\\.ts$': 'ts-jest',
|
||||||
|
'^.*\\.tsx$': 'ts-jest',
|
||||||
|
},
|
||||||
|
'transformIgnorePatterns': [
|
||||||
|
'/node_modules/(?!(@testing-library/preact/dist/esm)/)',
|
||||||
|
],
|
||||||
|
'coveragePathIgnorePatterns': [
|
||||||
|
'/node_modules/',
|
||||||
|
'/js/roms/',
|
||||||
|
'/test/',
|
||||||
|
],
|
||||||
|
'preset': 'ts-jest',
|
||||||
|
};
|
File diff suppressed because it is too large
Load Diff
|
@ -30,10 +30,11 @@
|
||||||
"@babel/preset-env": "^7.4.2",
|
"@babel/preset-env": "^7.4.2",
|
||||||
"@types/micromodal": "^0.3.3",
|
"@types/micromodal": "^0.3.3",
|
||||||
"ajv": "^6.9.2",
|
"ajv": "^6.9.2",
|
||||||
"babel-jest": "^26.3.0",
|
"babel-jest": "^29.5.0",
|
||||||
"eslint": "^8.3.0",
|
"eslint": "^8.3.0",
|
||||||
"jest": "^27.3.1",
|
"jest": "^29.5.0",
|
||||||
"node-forge": "^1.3.0",
|
"node-forge": "^1.3.0",
|
||||||
|
"ts-jest": "^29.1.1",
|
||||||
"ts-loader": "^9.4.4",
|
"ts-loader": "^9.4.4",
|
||||||
"typescript": "^5.1.6",
|
"typescript": "^5.1.6",
|
||||||
"webpack": "^5.64.4",
|
"webpack": "^5.64.4",
|
||||||
|
@ -41,6 +42,7 @@
|
||||||
"webpack-dev-server": "^4.6.0"
|
"webpack-dev-server": "^4.6.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@types/jest": "^29.5.3",
|
||||||
"micromodal": "^0.4.9"
|
"micromodal": "^0.4.9"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,25 +1,25 @@
|
||||||
|
import CPU6502, { FLAVOR_ROCKWELL_65C02 } from '../js/cpu6502';
|
||||||
import CPU6502 from '../js/cpu6502';
|
// From https://github.com/Klaus2m5/6502_65C02_functional_tests
|
||||||
import Test6502 from './roms/6502test';
|
import Test6502 from './roms/6502test';
|
||||||
import Test65C02 from './roms/65C02test';
|
import Test65C02 from './roms/65C02test';
|
||||||
|
|
||||||
import { toHex } from '../js/util';
|
import { toHex } from '../js/util';
|
||||||
|
|
||||||
describe.skip('CPU', function () {
|
describe('CPU', function () {
|
||||||
var cpu;
|
let cpu: CPU6502;
|
||||||
var lastPC = 0;
|
let lastPC = 0;
|
||||||
var done = false;
|
let done = false;
|
||||||
|
|
||||||
function traceCB() {
|
function traceCB() {
|
||||||
var pc = cpu.getPC();
|
const pc = cpu.getPC();
|
||||||
done = lastPC == pc;
|
done = lastPC === pc;
|
||||||
lastPC = pc;
|
lastPC = pc;
|
||||||
}
|
}
|
||||||
|
|
||||||
describe('6502', function () {
|
describe('6502', function () {
|
||||||
it('completes the test ROM', function () {
|
it('completes the test ROM', function () {
|
||||||
cpu = new CPU6502();
|
cpu = new CPU6502();
|
||||||
var test = new Test6502();
|
const test = new Test6502();
|
||||||
cpu.addPageHandler(test);
|
cpu.addPageHandler(test);
|
||||||
cpu.setPC(0x400);
|
cpu.setPC(0x400);
|
||||||
|
|
||||||
|
@ -33,8 +33,8 @@ describe.skip('CPU', function () {
|
||||||
|
|
||||||
describe('65C02', function () {
|
describe('65C02', function () {
|
||||||
it('completes the test ROM', function () {
|
it('completes the test ROM', function () {
|
||||||
cpu = new CPU6502({'65C02': true});
|
cpu = new CPU6502({ flavor: FLAVOR_ROCKWELL_65C02 });
|
||||||
var test = new Test65C02();
|
const test = new Test65C02();
|
||||||
cpu.addPageHandler(test);
|
cpu.addPageHandler(test);
|
||||||
cpu.setPC(0x400);
|
cpu.setPC(0x400);
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,29 @@
|
||||||
|
// From https://github.com/Klaus2m5/6502_65C02_functional_tests
|
||||||
|
|
||||||
|
import fs from 'fs';
|
||||||
|
import path from 'path';
|
||||||
|
import { MemoryPages, byte } from '../../js/types';
|
||||||
|
|
||||||
|
export default class Test6502 implements MemoryPages {
|
||||||
|
private data: Buffer;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.data = fs.readFileSync(path.join(__dirname, '6502_functional_test.bin'));
|
||||||
|
}
|
||||||
|
|
||||||
|
start = () => {
|
||||||
|
return 0x00;
|
||||||
|
};
|
||||||
|
|
||||||
|
end = () => {
|
||||||
|
return 0xff;
|
||||||
|
};
|
||||||
|
|
||||||
|
read = (page: byte, off: byte) => {
|
||||||
|
return this.data[page << 8 | off];
|
||||||
|
};
|
||||||
|
|
||||||
|
write = (page: byte, off: byte, val: byte) => {
|
||||||
|
this.data[page << 8 | off] = val;
|
||||||
|
};
|
||||||
|
}
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,29 @@
|
||||||
|
// From https://github.com/Klaus2m5/6502_65C02_functional_tests
|
||||||
|
|
||||||
|
import fs from 'fs';
|
||||||
|
import path from 'path';
|
||||||
|
import { MemoryPages, byte } from '../../js/types';
|
||||||
|
|
||||||
|
export default class Test65C02 implements MemoryPages {
|
||||||
|
private data: Buffer;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.data = fs.readFileSync(path.join(__dirname, '65C02_extended_opcodes_test.bin'));
|
||||||
|
}
|
||||||
|
|
||||||
|
start = () => {
|
||||||
|
return 0x00;
|
||||||
|
};
|
||||||
|
|
||||||
|
end = () => {
|
||||||
|
return 0xff;
|
||||||
|
};
|
||||||
|
|
||||||
|
read = (page: byte, off: byte) => {
|
||||||
|
return this.data[page << 8 | off];
|
||||||
|
};
|
||||||
|
|
||||||
|
write = (page: byte, off: byte, val: byte) => {
|
||||||
|
this.data[page << 8 | off] = val;
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
import { byte } from '../../js/types';
|
||||||
|
|
||||||
|
export const assertByte = (b: byte) => {
|
||||||
|
expect(b <= 0xFF).toEqual(true);
|
||||||
|
expect(b >= 0x00).toEqual(true);
|
||||||
|
};
|
|
@ -0,0 +1,63 @@
|
||||||
|
import { MemoryPages, byte } from '../../js/types';
|
||||||
|
import { assertByte } from './asserts';
|
||||||
|
|
||||||
|
export class Program implements MemoryPages {
|
||||||
|
private data: Buffer;
|
||||||
|
|
||||||
|
constructor(private page: byte, code: byte[]) {
|
||||||
|
this.data = Buffer.from(code);
|
||||||
|
}
|
||||||
|
|
||||||
|
start() {
|
||||||
|
return this.page;
|
||||||
|
}
|
||||||
|
|
||||||
|
end() {
|
||||||
|
return this.page;
|
||||||
|
}
|
||||||
|
|
||||||
|
read(page: byte, off: byte) {
|
||||||
|
assertByte(page);
|
||||||
|
assertByte(off);
|
||||||
|
return this.data[off];
|
||||||
|
}
|
||||||
|
|
||||||
|
write(_page: byte, _off: byte, _val: byte) {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const bios = new Program(0xff, [
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x48, 0x45, 0x4C, 0x4C, 0x4F, 0x0D, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0xff, 0x00, 0x04, 0x00, 0xff
|
||||||
|
]);
|
|
@ -0,0 +1,34 @@
|
||||||
|
import { flags, CpuState } from "js/cpu6502";
|
||||||
|
import { byte } from "js/types";
|
||||||
|
import { toHex } from "js/util";
|
||||||
|
|
||||||
|
export const dumpStatusRegister = (sr: byte) =>
|
||||||
|
[
|
||||||
|
sr & flags.N ? "N" : "-",
|
||||||
|
sr & flags.V ? "V" : "-",
|
||||||
|
sr & flags.X ? "X" : "-",
|
||||||
|
sr & flags.B ? "B" : "-",
|
||||||
|
sr & flags.D ? "D" : "-",
|
||||||
|
sr & flags.I ? "I" : "-",
|
||||||
|
sr & flags.Z ? "Z" : "-",
|
||||||
|
sr & flags.C ? "C" : "-",
|
||||||
|
].join("");
|
||||||
|
|
||||||
|
const detail = !!process.env.JEST_DETAIL;
|
||||||
|
|
||||||
|
export function toReadableState(state: CpuState) {
|
||||||
|
if (detail) {
|
||||||
|
const { pc, sp, a, x, y, s } = state;
|
||||||
|
|
||||||
|
return {
|
||||||
|
pc: toHex(pc, 4),
|
||||||
|
sp: toHex(sp),
|
||||||
|
a: toHex(a),
|
||||||
|
x: toHex(x),
|
||||||
|
y: toHex(y),
|
||||||
|
s: dumpStatusRegister(s),
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,61 @@
|
||||||
|
import { MemoryPages, byte, word } from 'js/types';
|
||||||
|
import { assertByte } from './asserts';
|
||||||
|
|
||||||
|
export type Log = [address: word, value: byte, types: 'read'|'write'];
|
||||||
|
export class TestMemory implements MemoryPages {
|
||||||
|
private data: Buffer;
|
||||||
|
private logging: boolean = false;
|
||||||
|
private log: Log[] = [];
|
||||||
|
|
||||||
|
constructor(private size: number) {
|
||||||
|
this.data = Buffer.alloc(size << 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
start() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
end() {
|
||||||
|
return this.size - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
read(page: byte, off: byte) {
|
||||||
|
assertByte(page);
|
||||||
|
assertByte(off);
|
||||||
|
|
||||||
|
const val = this.data[(page << 8) | off];
|
||||||
|
if (this.logging) {
|
||||||
|
this.log.push([page << 8 | off, val, 'read']);
|
||||||
|
}
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
write(page: byte, off: byte, val: byte) {
|
||||||
|
assertByte(page);
|
||||||
|
assertByte(off);
|
||||||
|
assertByte(val);
|
||||||
|
|
||||||
|
if (this.logging) {
|
||||||
|
this.log.push([page << 8 | off, val, 'write']);
|
||||||
|
}
|
||||||
|
this.data[(page << 8) | off] = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
reset() {
|
||||||
|
this.log = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
logStart() {
|
||||||
|
this.log = [];
|
||||||
|
this.logging = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
logStop() {
|
||||||
|
this.logging = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
getLog() {
|
||||||
|
return this.log;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue