mirror of
https://github.com/transistorfet/moa.git
synced 2025-04-11 13:38:51 +00:00
Added test running for Tom Harte's ProcessorTests test suite
This commit is contained in:
parent
8060f7179b
commit
c57c8f87b4
@ -4,8 +4,7 @@ version = "0.1.0"
|
||||
edition = "2018"
|
||||
|
||||
[workspace]
|
||||
members = [".", "frontends/moa-common", "frontends/moa-console", "frontends/moa-minifb"]
|
||||
members = [".", "frontends/moa-common", "frontends/moa-console", "frontends/moa-minifb", "tests/harte_tests"]
|
||||
default-members = ["frontends/moa-console"]
|
||||
|
||||
[dependencies]
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||
pub enum ErrorType {
|
||||
Assertion,
|
||||
Emulator,
|
||||
Processor,
|
||||
Breakpoint,
|
||||
@ -37,6 +38,14 @@ impl Error {
|
||||
msg: msg.to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn assertion(msg: &str) -> Error {
|
||||
Error {
|
||||
err: ErrorType::Assertion,
|
||||
native: 0,
|
||||
msg: msg.to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
1
tests/ProcessorTests
Submodule
1
tests/ProcessorTests
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 204846854d522fea3de0fdd260808d18bb180b05
|
12
tests/harte_tests/Cargo.toml
Normal file
12
tests/harte_tests/Cargo.toml
Normal file
@ -0,0 +1,12 @@
|
||||
[package]
|
||||
name = "harte_tests"
|
||||
version = "0.1.0"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
moa = { path = "../../" }
|
||||
serde = "1.0"
|
||||
serde_json = "1.0"
|
||||
serde_derive = "1.0"
|
||||
flate2 = "1.0"
|
||||
clap = { version = "3.2.20", features = ["derive"] }
|
18
tests/harte_tests/README.md
Normal file
18
tests/harte_tests/README.md
Normal file
@ -0,0 +1,18 @@
|
||||
|
||||
Tom Harte Test Suite
|
||||
====================
|
||||
|
||||
This is a test running for moa that uses the [Tom Harte Test Suite](https://github.com/TomHarte/ProcessorTests).
|
||||
|
||||
To run, the ProcessorTests repository must be cloned into tests/ and then from the moa project root:
|
||||
```shell
|
||||
cargo run -p harte_tests -- [FILTER]
|
||||
```
|
||||
|
||||
An optional filter can be specified, which will only run test files who's file name starts with the
|
||||
filter text. Timing tests are not done by default, but can be run with `-t` or `--timing`. The output
|
||||
can be increased or decreased with the `--debug` or `--quiet` flags, respectively.
|
||||
|
||||
Special thanks to [Tom](https://github.com/TomHarte) for painstakingly constructing this test suite.
|
||||
Emulators everywhere will be better for your efforts!
|
||||
|
130
tests/harte_tests/previous.txt
Normal file
130
tests/harte_tests/previous.txt
Normal file
@ -0,0 +1,130 @@
|
||||
Last run on 2022-09-09
|
||||
|
||||
ABCD.json.gz completed: 150 passed, 7915 FAILED
|
||||
ADD.b.json.gz completed: 4924 passed, 3141 FAILED
|
||||
ADD.l.json.gz completed: 3636 passed, 4429 FAILED
|
||||
ADD.w.json.gz completed: 3669 passed, 4396 FAILED
|
||||
ADDA.l.json.gz completed: 4843 passed, 3222 FAILED
|
||||
ADDA.w.json.gz completed: 4916 passed, 3149 FAILED
|
||||
ADDX.b.json.gz completed: 4051 passed, 4014 FAILED
|
||||
ADDX.l.json.gz completed: 4065 passed, 4000 FAILED
|
||||
ADDX.w.json.gz completed: 4012 passed, 4053 FAILED
|
||||
AND.b.json.gz completed: 5274 passed, 2791 FAILED
|
||||
AND.l.json.gz completed: 3263 passed, 4802 FAILED
|
||||
AND.w.json.gz completed: 3293 passed, 4772 FAILED
|
||||
ANDItoCCR.json.gz completed, all passed!
|
||||
ANDItoSR.json.gz completed, all passed!
|
||||
ASL.b.json.gz completed: 3941 passed, 4124 FAILED
|
||||
ASL.l.json.gz completed: 3578 passed, 4487 FAILED
|
||||
ASL.w.json.gz completed: 3246 passed, 4819 FAILED
|
||||
ASR.b.json.gz completed: 6316 passed, 1749 FAILED
|
||||
ASR.l.json.gz completed: 7007 passed, 1058 FAILED
|
||||
ASR.w.json.gz completed: 5414 passed, 2651 FAILED
|
||||
BCHG.json.gz completed: 4316 passed, 3749 FAILED
|
||||
BCLR.json.gz completed: 4701 passed, 3364 FAILED
|
||||
BSET.json.gz completed: 4475 passed, 3590 FAILED
|
||||
BSR.json.gz completed: 4078 passed, 3987 FAILED
|
||||
BTST.json.gz completed: 6851 passed, 1214 FAILED
|
||||
Bcc.json.gz completed: 5861 passed, 2204 FAILED
|
||||
CHK.json.gz completed: 0 passed, 8065 FAILED
|
||||
CLR.b.json.gz completed: 6594 passed, 1471 FAILED
|
||||
CLR.l.json.gz completed: 4301 passed, 3764 FAILED
|
||||
CLR.w.json.gz completed: 4327 passed, 3738 FAILED
|
||||
CMP.b.json.gz completed: 6627 passed, 1438 FAILED
|
||||
CMP.l.json.gz completed: 4634 passed, 3431 FAILED
|
||||
CMP.w.json.gz completed: 4597 passed, 3468 FAILED
|
||||
CMPA.l.json.gz completed: 4998 passed, 3067 FAILED
|
||||
CMPA.w.json.gz completed: 3895 passed, 4170 FAILED
|
||||
DBcc.json.gz completed: 5194 passed, 2871 FAILED
|
||||
DIVS.json.gz completed: 539 passed, 7526 FAILED
|
||||
DIVU.json.gz completed: 1093 passed, 6972 FAILED
|
||||
EOR.b.json.gz completed: 4359 passed, 3706 FAILED
|
||||
EOR.l.json.gz completed: 2898 passed, 5167 FAILED
|
||||
EOR.w.json.gz completed: 2936 passed, 5129 FAILED
|
||||
EORItoCCR.json.gz completed: 1067 passed, 6998 FAILED
|
||||
EORItoSR.json.gz completed: 141 passed, 7924 FAILED
|
||||
EXG.json.gz completed, all passed!
|
||||
EXT.l.json.gz completed, all passed!
|
||||
EXT.w.json.gz completed, all passed!
|
||||
JMP.json.gz completed: 533 passed, 7532 FAILED
|
||||
JSR.json.gz completed: 152 passed, 7913 FAILED
|
||||
LEA.json.gz completed: 5726 passed, 2339 FAILED
|
||||
LINK.json.gz completed: 7060 passed, 1005 FAILED
|
||||
LSL.b.json.gz completed: 7774 passed, 291 FAILED
|
||||
LSL.l.json.gz completed: 7017 passed, 1048 FAILED
|
||||
LSL.w.json.gz completed: 6151 passed, 1914 FAILED
|
||||
LSR.b.json.gz completed: 7797 passed, 268 FAILED
|
||||
LSR.l.json.gz completed: 7044 passed, 1021 FAILED
|
||||
LSR.w.json.gz completed: 6157 passed, 1908 FAILED
|
||||
MOVE.b.json.gz completed: 5383 passed, 2682 FAILED
|
||||
MOVE.l.json.gz completed: 2626 passed, 5439 FAILED
|
||||
MOVE.q.json.gz completed, all passed!
|
||||
MOVE.w.json.gz completed: 2709 passed, 5356 FAILED
|
||||
MOVEA.l.json.gz completed: 4827 passed, 3238 FAILED
|
||||
MOVEA.w.json.gz completed: 4813 passed, 3252 FAILED
|
||||
MOVEM.l.json.gz completed: 3286 passed, 4779 FAILED
|
||||
MOVEM.w.json.gz completed: 3324 passed, 4741 FAILED
|
||||
MOVEP.l.json.gz completed: 4036 passed, 4029 FAILED
|
||||
MOVEP.w.json.gz completed: 4046 passed, 4019 FAILED
|
||||
MOVEfromSR.json.gz completed: 4456 passed, 3609 FAILED
|
||||
MOVEfromUSP.json.gz completed, all passed!
|
||||
MOVEtoCCR.json.gz completed: 541 passed, 7524 FAILED
|
||||
MOVEtoSR.json.gz completed: 90 passed, 7975 FAILED
|
||||
MOVEtoUSP.json.gz completed, all passed!
|
||||
MULS.json.gz completed: 2241 passed, 5824 FAILED
|
||||
MULU.json.gz completed: 4388 passed, 3677 FAILED
|
||||
NBCD.json.gz completed: 0 passed, 8065 FAILED
|
||||
NEG.b.json.gz completed: 4372 passed, 3693 FAILED
|
||||
NEG.l.json.gz completed: 2991 passed, 5074 FAILED
|
||||
NEG.w.json.gz completed: 2870 passed, 5195 FAILED
|
||||
NEGX.b.json.gz completed: 0 passed, 8065 FAILED
|
||||
NEGX.l.json.gz completed: 0 passed, 8065 FAILED
|
||||
NEGX.w.json.gz completed: 0 passed, 8065 FAILED
|
||||
NOP.json.gz completed, all passed!
|
||||
NOT.b.json.gz completed: 4424 passed, 3641 FAILED
|
||||
NOT.l.json.gz completed: 2915 passed, 5150 FAILED
|
||||
NOT.w.json.gz completed: 2944 passed, 5121 FAILED
|
||||
OR.b.json.gz completed: 5220 passed, 2845 FAILED
|
||||
OR.l.json.gz completed: 3294 passed, 4771 FAILED
|
||||
OR.w.json.gz completed: 3204 passed, 4861 FAILED
|
||||
ORItoCCR.json.gz completed: 987 passed, 7078 FAILED
|
||||
ORItoSR.json.gz completed: 118 passed, 7947 FAILED
|
||||
PEA.json.gz completed: 5798 passed, 2267 FAILED
|
||||
RESET.json.gz completed: 0 passed, 8065 FAILED
|
||||
ROL.b.json.gz completed, all passed!
|
||||
ROL.l.json.gz completed, all passed!
|
||||
ROL.w.json.gz completed: 6560 passed, 1505 FAILED
|
||||
ROR.b.json.gz completed, all passed!
|
||||
ROR.l.json.gz completed, all passed!
|
||||
ROR.w.json.gz completed: 6511 passed, 1554 FAILED
|
||||
ROXL.b.json.gz completed: 8039 passed, 26 FAILED
|
||||
ROXL.l.json.gz completed: 8029 passed, 36 FAILED
|
||||
ROXL.w.json.gz completed: 6534 passed, 1531 FAILED
|
||||
ROXR.b.json.gz completed: 8037 passed, 28 FAILED
|
||||
ROXR.l.json.gz completed: 8022 passed, 43 FAILED
|
||||
ROXR.w.json.gz completed: 6531 passed, 1534 FAILED
|
||||
RTE.json.gz completed: 0 passed, 8065 FAILED
|
||||
RTR.json.gz completed: 0 passed, 8065 FAILED
|
||||
RTS.json.gz completed: 11 passed, 8054 FAILED
|
||||
SBCD.json.gz completed: 439 passed, 7626 FAILED
|
||||
SUB.b.json.gz completed: 5037 passed, 3028 FAILED
|
||||
SUB.l.json.gz completed: 3635 passed, 4430 FAILED
|
||||
SUB.w.json.gz completed: 3603 passed, 4462 FAILED
|
||||
SUBA.l.json.gz completed: 4787 passed, 3278 FAILED
|
||||
SUBA.w.json.gz completed: 4842 passed, 3223 FAILED
|
||||
SUBX.b.json.gz completed: 3861 passed, 4204 FAILED
|
||||
SUBX.l.json.gz completed: 3955 passed, 4110 FAILED
|
||||
SUBX.w.json.gz completed: 3876 passed, 4189 FAILED
|
||||
SWAP.json.gz completed: 509 passed, 7556 FAILED
|
||||
Scc.json.gz completed: 6637 passed, 1428 FAILED
|
||||
TAS.json.gz completed: 4409 passed, 3656 FAILED
|
||||
TRAP.json.gz completed: 0 passed, 8065 FAILED
|
||||
TRAPV.json.gz completed: 3970 passed, 4095 FAILED
|
||||
TST.b.json.gz completed: 6566 passed, 1499 FAILED
|
||||
TST.l.json.gz completed: 4381 passed, 3684 FAILED
|
||||
TST.w.json.gz completed: 4362 passed, 3703 FAILED
|
||||
UNLINK.json.gz completed, all passed!
|
||||
|
||||
passed: 541447, failed: 458613, total: 54%
|
||||
completed in 17m 28s
|
||||
|
314
tests/harte_tests/src/main.rs
Normal file
314
tests/harte_tests/src/main.rs
Normal file
@ -0,0 +1,314 @@
|
||||
|
||||
const HART_TESTS: &str = "tests/ProcessorTests/680x0/68000/v1/";
|
||||
|
||||
use std::io::prelude::*;
|
||||
use std::fmt::Debug;
|
||||
use std::path::PathBuf;
|
||||
use std::time::SystemTime;
|
||||
use std::fs::{self, File};
|
||||
|
||||
use clap::Parser;
|
||||
use flate2::read::GzDecoder;
|
||||
use serde_derive::Deserialize;
|
||||
|
||||
use moa::error::Error;
|
||||
use moa::system::System;
|
||||
use moa::memory::{MemoryBlock, BusPort};
|
||||
use moa::devices::{Addressable, Steppable, wrap_transmutable};
|
||||
|
||||
use moa::cpus::m68k::{M68k, M68kType};
|
||||
use moa::cpus::m68k::state::Status;
|
||||
|
||||
#[derive(Parser)]
|
||||
struct Args {
|
||||
/// Filter the tests by gzip file name
|
||||
filter: Option<String>,
|
||||
/// Dump the CPU state when a test fails
|
||||
#[clap(short, long)]
|
||||
debug: bool,
|
||||
/// Only print a summary for each test file
|
||||
#[clap(short, long)]
|
||||
quiet: bool,
|
||||
/// Also test instruction timing
|
||||
#[clap(short, long)]
|
||||
timing: bool,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
|
||||
enum InfoLevel {
|
||||
Quiet,
|
||||
Normal,
|
||||
Debug,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let args = Args::parse();
|
||||
|
||||
let level = if args.debug {
|
||||
InfoLevel::Debug
|
||||
} else if args.quiet {
|
||||
InfoLevel::Quiet
|
||||
} else {
|
||||
InfoLevel::Normal
|
||||
};
|
||||
|
||||
run_all_tests(args, level);
|
||||
}
|
||||
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct TestState {
|
||||
d0: u32,
|
||||
d1: u32,
|
||||
d2: u32,
|
||||
d3: u32,
|
||||
d4: u32,
|
||||
d5: u32,
|
||||
d6: u32,
|
||||
d7: u32,
|
||||
a0: u32,
|
||||
a1: u32,
|
||||
a2: u32,
|
||||
a3: u32,
|
||||
a4: u32,
|
||||
a5: u32,
|
||||
a6: u32,
|
||||
usp: u32,
|
||||
ssp: u32,
|
||||
sr: u16,
|
||||
pc: u32,
|
||||
prefetch: Vec<u16>,
|
||||
ram: Vec<(u32, u8)>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct TestCase {
|
||||
name: String,
|
||||
#[serde(rename(deserialize = "initial"))]
|
||||
initial_state: TestState,
|
||||
#[serde(rename(deserialize = "final"))]
|
||||
final_state: TestState,
|
||||
length: usize
|
||||
}
|
||||
|
||||
fn init_execute_test(cputype: M68kType, state: &TestState) -> Result<(M68k, System), Error> {
|
||||
let mut system = System::new();
|
||||
|
||||
// Insert basic initialization
|
||||
let data = vec![0; 0x01000000];
|
||||
let mem = MemoryBlock::new(data);
|
||||
system.add_addressable_device(0x00000000, wrap_transmutable(mem)).unwrap();
|
||||
|
||||
let port = if cputype <= M68kType::MC68010 {
|
||||
BusPort::new(0, 24, 16, system.bus.clone())
|
||||
} else {
|
||||
BusPort::new(0, 32, 32, system.bus.clone())
|
||||
};
|
||||
let mut cpu = M68k::new(cputype, 10_000_000, port);
|
||||
cpu.state.status = Status::Running;
|
||||
|
||||
load_state(&mut cpu, &mut system, state)?;
|
||||
|
||||
Ok((cpu, system))
|
||||
}
|
||||
|
||||
fn assert_value<T: PartialEq + Debug>(actual: T, expected: T, message: &str) -> Result<(), Error> {
|
||||
if actual == expected {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(Error::assertion(&format!("{:?} != {:?}, {}", actual, expected, message)))
|
||||
}
|
||||
}
|
||||
|
||||
fn load_state(cpu: &mut M68k, system: &mut System, initial: &TestState) -> Result<(), Error> {
|
||||
cpu.state.d_reg[0] = initial.d0;
|
||||
cpu.state.d_reg[1] = initial.d1;
|
||||
cpu.state.d_reg[2] = initial.d2;
|
||||
cpu.state.d_reg[3] = initial.d3;
|
||||
cpu.state.d_reg[4] = initial.d4;
|
||||
cpu.state.d_reg[5] = initial.d5;
|
||||
cpu.state.d_reg[6] = initial.d6;
|
||||
cpu.state.d_reg[7] = initial.d7;
|
||||
cpu.state.a_reg[0] = initial.a0;
|
||||
cpu.state.a_reg[1] = initial.a1;
|
||||
cpu.state.a_reg[2] = initial.a2;
|
||||
cpu.state.a_reg[3] = initial.a3;
|
||||
cpu.state.a_reg[4] = initial.a4;
|
||||
cpu.state.a_reg[5] = initial.a5;
|
||||
cpu.state.a_reg[6] = initial.a6;
|
||||
|
||||
cpu.state.usp = initial.usp;
|
||||
cpu.state.ssp = initial.ssp;
|
||||
cpu.state.sr = initial.sr;
|
||||
cpu.state.pc = initial.pc;
|
||||
|
||||
// Load instructions into memory
|
||||
for (i, ins) in initial.prefetch.iter().enumerate() {
|
||||
system.get_bus().write_beu16((initial.pc + (i as u32 * 2)) as u64, *ins)?;
|
||||
}
|
||||
|
||||
// Load data bytes into memory
|
||||
for (addr, byte) in initial.ram.iter() {
|
||||
system.get_bus().write_u8(*addr as u64, *byte)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn assert_state(cpu: &M68k, system: &System, expected: &TestState) -> Result<(), Error> {
|
||||
assert_value(cpu.state.d_reg[0], expected.d0, "d0")?;
|
||||
assert_value(cpu.state.d_reg[1], expected.d1, "d1")?;
|
||||
assert_value(cpu.state.d_reg[2], expected.d2, "d2")?;
|
||||
assert_value(cpu.state.d_reg[3], expected.d3, "d3")?;
|
||||
assert_value(cpu.state.d_reg[4], expected.d4, "d4")?;
|
||||
assert_value(cpu.state.d_reg[5], expected.d5, "d5")?;
|
||||
assert_value(cpu.state.d_reg[6], expected.d6, "d6")?;
|
||||
assert_value(cpu.state.d_reg[7], expected.d7, "d7")?;
|
||||
assert_value(cpu.state.a_reg[0], expected.a0, "a0")?;
|
||||
assert_value(cpu.state.a_reg[1], expected.a1, "a1")?;
|
||||
assert_value(cpu.state.a_reg[2], expected.a2, "a2")?;
|
||||
assert_value(cpu.state.a_reg[3], expected.a3, "a3")?;
|
||||
assert_value(cpu.state.a_reg[4], expected.a4, "a4")?;
|
||||
assert_value(cpu.state.a_reg[5], expected.a5, "a5")?;
|
||||
assert_value(cpu.state.a_reg[6], expected.a6, "a6")?;
|
||||
|
||||
assert_value(cpu.state.usp, expected.usp, "usp")?;
|
||||
assert_value(cpu.state.ssp, expected.ssp, "ssp")?;
|
||||
assert_value(cpu.state.sr, expected.sr, "sr")?;
|
||||
assert_value(cpu.state.pc, expected.pc, "pc")?;
|
||||
|
||||
// Load instructions into memory
|
||||
for (i, ins) in expected.prefetch.iter().enumerate() {
|
||||
let addr = expected.pc + (i as u32 * 2);
|
||||
let actual = system.get_bus().read_beu16(addr as u64)?;
|
||||
assert_value(actual, *ins, &format!("prefetch at {}", addr))?;
|
||||
}
|
||||
|
||||
// Load data bytes into memory
|
||||
for (addr, byte) in expected.ram.iter() {
|
||||
let actual = system.get_bus().read_u8(*addr as u64)?;
|
||||
assert_value(actual, *byte, &format!("ram at {}", addr))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn step_cpu_and_assert(cpu: &mut M68k, system: &System, case: &TestCase, test_timing: bool) -> Result<(), Error> {
|
||||
let clock_elapsed = cpu.step(&system)?;
|
||||
let cycles = clock_elapsed / (1_000_000_000 / cpu.frequency as u64);
|
||||
|
||||
assert_state(&cpu, &system, &case.final_state)?;
|
||||
|
||||
if test_timing {
|
||||
assert_value(cycles, case.length as u64, "clock cycles")?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn run_test(case: &TestCase, level: InfoLevel, test_timing: bool) -> Result<(), Error> {
|
||||
let (mut cpu, system) = init_execute_test(M68kType::MC68010, &case.initial_state).unwrap();
|
||||
|
||||
let result = step_cpu_and_assert(&mut cpu, &system, case, test_timing);
|
||||
|
||||
match result {
|
||||
Ok(()) => Ok(()),
|
||||
Err(err) => {
|
||||
if level > InfoLevel::Quiet {
|
||||
if level == InfoLevel::Debug {
|
||||
cpu.dump_state(&system);
|
||||
}
|
||||
println!("FAILED: {}", err.msg);
|
||||
}
|
||||
Err(err)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn test_json_file(path: PathBuf, level: InfoLevel, test_timing: bool) -> (usize, usize, String) {
|
||||
let file = File::open(&path).unwrap();
|
||||
let mut decoder = GzDecoder::new(file);
|
||||
let mut data = String::new();
|
||||
decoder.read_to_string(&mut data).unwrap();
|
||||
let cases: Vec<TestCase> = serde_json::from_str(&data).unwrap();
|
||||
|
||||
let mut passed = 0;
|
||||
let mut failed = 0;
|
||||
for case in cases {
|
||||
if level > InfoLevel::Quiet {
|
||||
println!("Running test {}", case.name);
|
||||
}
|
||||
let result = run_test(&case, level, test_timing);
|
||||
|
||||
if let Err(err) = result {
|
||||
failed += 1;
|
||||
if level > InfoLevel::Quiet {
|
||||
println!("FAILED: {:?}", err);
|
||||
}
|
||||
} else {
|
||||
passed += 1
|
||||
}
|
||||
}
|
||||
|
||||
let name = path.file_name().unwrap().to_str().unwrap();
|
||||
let message = if failed == 0 {
|
||||
format!("{} completed, all passed!", name)
|
||||
} else {
|
||||
format!("{} completed: {} passed, {} FAILED", name, passed, failed)
|
||||
};
|
||||
|
||||
(passed, failed, message)
|
||||
}
|
||||
|
||||
|
||||
fn run_all_tests(args: Args, level: InfoLevel) {
|
||||
let mut passed = 0;
|
||||
let mut failed = 0;
|
||||
let mut messages = vec![];
|
||||
|
||||
|
||||
let mut tests: Vec<PathBuf> = fs::read_dir(HART_TESTS)
|
||||
.unwrap()
|
||||
.map(|dirent| dirent.unwrap().path())
|
||||
.collect();
|
||||
tests.sort();
|
||||
|
||||
let start = SystemTime::now();
|
||||
for path in tests {
|
||||
// Only test gzip files (the repo has .md files as well)
|
||||
if path.extension().unwrap() != "gz" {
|
||||
continue;
|
||||
}
|
||||
|
||||
// If specified, only test files that start with a given string
|
||||
if let Some(filter) = &args.filter {
|
||||
if !path.file_name().unwrap().to_str().unwrap().starts_with(filter) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Run every test in the file
|
||||
let (test_passed, test_failed, message) = test_json_file(path, level, args.timing);
|
||||
|
||||
// In quiet mode, print each summary as it's received to give a progress update
|
||||
if level == InfoLevel::Quiet {
|
||||
println!("{}", message);
|
||||
}
|
||||
|
||||
passed += test_passed;
|
||||
failed += test_failed;
|
||||
messages.push(message);
|
||||
}
|
||||
let elapsed_secs = start.elapsed().unwrap().as_secs();
|
||||
|
||||
// Print the stored summary if not in quite mode
|
||||
if level > InfoLevel::Quiet {
|
||||
for message in messages {
|
||||
println!("{}", message);
|
||||
}
|
||||
}
|
||||
|
||||
println!("");
|
||||
println!("passed: {}, failed: {}, total {}%", passed, failed, (passed / (passed + failed)) * 100);
|
||||
println!("completed in {}m {}s", elapsed_secs / 60, elapsed_secs % 60);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user