diff options
| author | Miquel Sabaté Solà <mssola@mssola.com> | 2026-08-27 07:12:42 +0200 |
|---|---|---|
| committer | Miquel Sabaté Solà <mssola@mssola.com> | 2026-08-27 07:12:42 +0200 |
| commit | 50ebac34fec99c853b2f010bfd100c11b5e0a603 (patch) | |
| tree | 2353404e148fcf56019c478b05a449ad6331ea2e /tests/vnf-tests | |
| parent | 1bc9db2e8de21995fef2a4f59d8e1d20eef7d470 (diff) | |
| download | tools.nes-50ebac34fec99c853b2f010bfd100c11b5e0a603.tar.gz tools.nes-50ebac34fec99c853b2f010bfd100c11b5e0a603.zip | |
vnf: add support for all stack instructions
This also includes brk and rti, for which we are also storing and
exporting the break mark, just in case it can be useful to library users
in case they want to add error codes in break marks.
This commit also includes a fix for accounting the Z and N flags on
transfer instructions, which couldn't easily be split into a separate
commit, but it's a fairly simple change.
Signed-off-by: Miquel Sabaté Solà <mssola@mssola.com>
Diffstat (limited to 'tests/vnf-tests')
| -rw-r--r-- | tests/vnf-tests/Cargo.toml | 10 | ||||
| -rw-r--r-- | tests/vnf-tests/src/main.rs | 108 |
2 files changed, 118 insertions, 0 deletions
diff --git a/tests/vnf-tests/Cargo.toml b/tests/vnf-tests/Cargo.toml new file mode 100644 index 0000000..8ad6b70 --- /dev/null +++ b/tests/vnf-tests/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "vnf-tests" +version = "0.1.0" +edition = "2024" +license.workspace = true +authors.workspace = true + +[dependencies] +vnf.workspace = true +xixanta.workspace = true diff --git a/tests/vnf-tests/src/main.rs b/tests/vnf-tests/src/main.rs new file mode 100644 index 0000000..6c62dbd --- /dev/null +++ b/tests/vnf-tests/src/main.rs @@ -0,0 +1,108 @@ +use std::path::PathBuf; + +use vnf::{Machine, MemoryPolicy}; +use xixanta::opcodes::InstructionIdentifier; + +#[derive(Default)] +struct Args { + file: String, +} + +fn print_help() { + println!("End-to-end tests for the vnf library\n"); + println!("usage: vnf-tests [OPTIONS] <tests/ directory>\n"); + println!("Options:"); + println!(" -h, --help\t\t\tPrint this message and quit."); + std::process::exit(0); +} + +// Print the given `message` and exit(1). +fn die(message: String) -> ! { + eprintln!("error: {message}"); + std::process::exit(1); +} + +fn parse_arguments() -> Args { + let mut args = std::env::args(); + let mut res = Args::default(); + + // Skip command name. + args.next(); + + for arg in args { + match arg.as_str() { + "-h" | "--help" => print_help(), + _ => { + if arg.starts_with('-') { + die(format!("don't know how to handle the '{arg}' flag")); + } + if !res.file.is_empty() { + die("cannot have multiple paths".to_string()); + } + res.file = arg; + } + } + } + + if res.file.is_empty() { + die("you have to provide a path to the tests/ directory".to_string()); + } + + res +} + +fn run_break_mark_test(path: &String) -> Result<(), String> { + let rom = PathBuf::from(path).join("out/stack.nes"); + let roms: String = rom.to_string_lossy().into_owned().to_string(); + + let mut machine = Machine::from(&roms, 0x8000, MemoryPolicy::default())?; + + // Get out of <start> + let _ = machine.next_iteration(); + + // Assert that we are at the expected location. + assert!(matches!( + machine.current_instruction.identifier, + InstructionIdentifier::Brk + )); + + // Before vs after running 'brk'. + assert_eq!(machine.status_register.break_mark, 0); + assert!(!machine.status_register.brk); + let _ = machine.next_iteration(); + assert_eq!(machine.status_register.break_mark, 0x42); + assert!(machine.status_register.brk); + + // Skip instructions we don't care about here. + for _ in 0..11 { + let _ = machine.next_iteration(); + } + + // Before running 'plp', everything is still as expected. + assert!(matches!( + machine.current_instruction.identifier, + InstructionIdentifier::Plp + )); + assert_eq!(machine.status_register.break_mark, 0x42); + assert!(machine.status_register.brk); + + // After running 'plp'. + let _ = machine.next_iteration(); + assert_eq!(machine.status_register.break_mark, 0x00); + assert!(!machine.status_register.brk); + + Ok(()) +} + +fn main() { + let args = parse_arguments(); + let file = PathBuf::from(args.file.clone()); + + if !file.is_dir() { + die("you have to provide a path to the tests/ directory".to_string()); + } + + if let Err(e) = run_break_mark_test(&args.file) { + die(e) + } +} |
