diff options
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/expected/runrom/stack.txt | 44 | ||||
| -rw-r--r-- | tests/runrom/stack.s | 44 | ||||
| -rw-r--r-- | tests/vnf-tests/Cargo.toml | 10 | ||||
| -rw-r--r-- | tests/vnf-tests/src/main.rs | 108 |
4 files changed, 206 insertions, 0 deletions
diff --git a/tests/expected/runrom/stack.txt b/tests/expected/runrom/stack.txt new file mode 100644 index 0000000..f35ea16 --- /dev/null +++ b/tests/expected/runrom/stack.txt @@ -0,0 +1,44 @@ +<start> PC: $8000, cycles: 7, registers: [a: $00, x: $00, y: $00, sp: $FD], status: ----I-- + [STACK]: 02 80 00 00 + [STACK]: 34 02 80 00 00 +brk PC: $8003, cycles: 14, registers: [a: $00, x: $00, y: $00, sp: $FA], status: --B-I-- + [STACK]: 00 34 02 80 00 00 +pha PC: $8004, cycles: 17, registers: [a: $00, x: $00, y: $00, sp: $F9], status: --B-I-- +txa PC: $8005, cycles: 19, registers: [a: $00, x: $00, y: $00, sp: $F9], status: --B-IZ- + [STACK]: 00 00 34 02 80 00 00 +pha PC: $8006, cycles: 22, registers: [a: $00, x: $00, y: $00, sp: $F8], status: --B-IZ- +tya PC: $8007, cycles: 24, registers: [a: $00, x: $00, y: $00, sp: $F8], status: --B-IZ- + [STACK]: 00 00 00 34 02 80 00 00 +pha PC: $8008, cycles: 27, registers: [a: $00, x: $00, y: $00, sp: $F7], status: --B-IZ- + [STACK]: 36 00 00 00 34 02 80 00 00 +php PC: $8009, cycles: 30, registers: [a: $00, x: $00, y: $00, sp: $F6], status: --B-IZ- +lda #$01 PC: $800B, cycles: 32, registers: [a: $01, x: $00, y: $00, sp: $F6], status: --B-I-- +ldy #$02 PC: $800D, cycles: 34, registers: [a: $01, x: $00, y: $02, sp: $F6], status: --B-I-- +ldx #$FF PC: $800F, cycles: 36, registers: [a: $01, x: $FF, y: $02, sp: $F6], status: N-B-I-- +inx PC: $8010, cycles: 38, registers: [a: $01, x: $00, y: $02, sp: $F6], status: --B-IZ- +inx PC: $8011, cycles: 40, registers: [a: $01, x: $01, y: $02, sp: $F6], status: --B-I-- + [STACK]: 00 00 00 34 02 80 00 00 +plp PC: $8012, cycles: 44, registers: [a: $01, x: $01, y: $02, sp: $F7], status: ----IZ- + [STACK]: 00 00 34 02 80 00 00 +pla PC: $8013, cycles: 48, registers: [a: $00, x: $01, y: $02, sp: $F8], status: ----IZ- +tay PC: $8014, cycles: 50, registers: [a: $00, x: $01, y: $00, sp: $F8], status: ----IZ- + [STACK]: 00 34 02 80 00 00 +pla PC: $8015, cycles: 54, registers: [a: $00, x: $01, y: $00, sp: $F9], status: ----IZ- +tax PC: $8016, cycles: 56, registers: [a: $00, x: $00, y: $00, sp: $F9], status: ----IZ- + [STACK]: 34 02 80 00 00 +pla PC: $8017, cycles: 60, registers: [a: $00, x: $00, y: $00, sp: $FA], status: ----IZ- + [STACK]: 02 80 00 00 + [STACK]: 00 00 +rti PC: $8002, cycles: 66, registers: [a: $00, x: $00, y: $00, sp: $FD], status: ----I-- +rts PC: $8003, cycles: 72, registers: [a: $00, x: $00, y: $00, sp: $FD], status: ----I-- +<end> + +== Memory dump == + +[$2F7] = $36 [reads=1, writes=1] +[$2F8] = $00 [reads=1, writes=1] +[$2F9] = $00 [reads=1, writes=1] +[$2FA] = $00 [reads=1, writes=1] +[$2FB] = $34 [reads=1, writes=1] +[$2FC] = $02 [reads=1, writes=1] +[$2FD] = $80 [reads=1, writes=1] diff --git a/tests/runrom/stack.s b/tests/runrom/stack.s new file mode 100644 index 0000000..ec15718 --- /dev/null +++ b/tests/runrom/stack.s @@ -0,0 +1,44 @@ +.segment "HEADER" + .byte 'N', 'E', 'S', $1A + .byte $02, $01 + .byte $00 + .byte $00 + +.segment "CHARS" +.byte 0 + +.segment "CODE" +;; asan:stack full + +.proc reset + brk + .byte $42 + rts +.endproc + +.proc irq + pha + txa + pha + tya + pha + php + + lda #1 + ldy #2 + ldx #$FF + inx + inx + + plp + pla + tay + pla + tax + pla + + rti +.endproc + +.segment "VECTORS" + .addr reset, reset, irq 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) + } +} |
