tests: Update tests to match current behavior.
This commit is contained in:
		
							
								
								
									
										20
									
								
								src/cpu.rs
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								src/cpu.rs
									
									
									
									
									
								
							| @@ -522,6 +522,11 @@ impl CPU { | ||||
|     } | ||||
|  | ||||
|     /// Executes a single instruction | ||||
|     /// | ||||
|     /// Returns [Error::BreakpointHit] if a breakpoint was hit after the instruction executed.   | ||||
|     /// This result contains information about the breakpoint, but can be safely ignored. | ||||
|     /// | ||||
|     /// Returns [Error::UnimplementedInstruction] if the instruction at `pc` is unimplemented. | ||||
|     /// # Examples | ||||
|     /// ```rust | ||||
|     /// # use chirp::*; | ||||
| @@ -552,11 +557,8 @@ impl CPU { | ||||
|     ///     ], | ||||
|     ///     Screen  [0x0f00..0x1000], | ||||
|     /// }; | ||||
|     /// match cpu.tick(&mut bus) { | ||||
|     ///     Err(Error::UnimplementedInstruction {word}) | ||||
|     ///         => assert_eq!(0xffff, word), | ||||
|     ///     _ => panic!(), | ||||
|     /// } | ||||
|     /// dbg!(cpu.tick(&mut bus)) | ||||
|     ///     .expect_err("Should return Error::InvalidInstruction { 0xffff }"); | ||||
|     /// ``` | ||||
|     pub fn tick(&mut self, bus: &mut Bus) -> Result<&mut Self> { | ||||
|         // Do nothing if paused | ||||
| @@ -571,7 +573,9 @@ impl CPU { | ||||
|         // fetch opcode | ||||
|         let opcode: &[u8; 2] = if let Some(slice) = bus.get(self.pc as usize..self.pc as usize + 2) | ||||
|         { | ||||
|             slice.try_into()? | ||||
|             slice | ||||
|                 .try_into() | ||||
|                 .expect("`slice` should be exactly 2 bytes.") | ||||
|         } else { | ||||
|             return Err(Error::InvalidBusRange { | ||||
|                 range: self.pc as usize..self.pc as usize + 2, | ||||
| @@ -603,6 +607,10 @@ impl CPU { | ||||
|         // process breakpoints | ||||
|         if !self.breakpoints.is_empty() && self.breakpoints.contains(&self.pc) { | ||||
|             self.flags.pause = true; | ||||
|             return Err(Error::BreakpointHit { | ||||
|                 addr: self.pc, | ||||
|                 next: bus.read(self.pc), | ||||
|             }); | ||||
|         } | ||||
|         Ok(self) | ||||
|     } | ||||
|   | ||||
| @@ -939,6 +939,7 @@ mod io { | ||||
|             output: &'static [u8], | ||||
|         } | ||||
|  | ||||
|         /// Verify the character sprite addresses with the data they should return | ||||
|         #[rustfmt::skip] | ||||
|         const TESTS: [SpriteTest; 16] = [ | ||||
|             SpriteTest { input: 0x0, output: &[0xf0, 0x90, 0x90, 0x90, 0xf0] }, | ||||
| @@ -1121,15 +1122,51 @@ mod behavior { | ||||
|         } | ||||
|     } | ||||
|     mod breakpoint { | ||||
|  | ||||
|         use super::*; | ||||
|         #[test] | ||||
|         #[cfg_attr(feature = "unstable", no_coverage)] | ||||
|         fn hit_break() { | ||||
|             let (mut cpu, mut bus) = setup_environment(); | ||||
|             cpu.set_break(0x202); | ||||
|             cpu.multistep(&mut bus, 10) | ||||
|                 .expect("Running valid instructions should always succeed"); | ||||
|             match cpu.multistep(&mut bus, 10) { | ||||
|                 Err(crate::error::Error::BreakpointHit { addr, next }) => { | ||||
|                     assert_eq!(0x202, addr); // current address is 202 | ||||
|                     assert_eq!(0x1204, next); // next insn is `jmp 204` | ||||
|                 } | ||||
|                 other => unreachable!("{:?}", other), | ||||
|             } | ||||
|             assert!(cpu.flags.pause); | ||||
|             assert_eq!(0x202, cpu.pc); | ||||
|         } | ||||
|         #[test] | ||||
|         #[cfg_attr(feature = "unstable", no_coverage)] | ||||
|         fn hit_break_singlestep() { | ||||
|             let (mut cpu, mut bus) = setup_environment(); | ||||
|             cpu.set_break(0x202); | ||||
|             match cpu.singlestep(&mut bus) { | ||||
|                 Err(crate::error::Error::BreakpointHit { addr, next }) => { | ||||
|                     assert_eq!(0x202, addr); // current address is 202 | ||||
|                     assert_eq!(0x1204, next); // next insn is `jmp 204` | ||||
|                 } | ||||
|                 other => unreachable!("{:?}", other), | ||||
|             } | ||||
|             assert!(cpu.flags.pause); | ||||
|             assert_eq!(0x202, cpu.pc); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     #[test] | ||||
|     #[cfg_attr(feature = "unstable", no_coverage)] | ||||
|     fn invalid_pc() { | ||||
|         let (mut cpu, mut bus) = setup_environment(); | ||||
|         // The bus extends from 0x0..0x1000 | ||||
|         cpu.pc = 0xfff; | ||||
|         match cpu.tick(&mut bus) { | ||||
|             Err(Error::InvalidBusRange { range }) => { | ||||
|                 eprintln!("InvalidBusRange {{ {range:04x?} }}") | ||||
|             } | ||||
|             other => unreachable!("{other:04x?}"), | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -14,6 +14,14 @@ pub type Result<T> = std::result::Result<T, Error>; | ||||
| /// Error type for Chirp. | ||||
| #[derive(Debug, Error)] | ||||
| pub enum Error { | ||||
|     /// Represents a breakpoint being hit | ||||
|     #[error("Breakpoint hit: {addr:03x} ({next:04x})")] | ||||
|     BreakpointHit { | ||||
|         /// The address of the breakpoint | ||||
|         addr: u16, | ||||
|         /// The instruction after the breakpoint | ||||
|         next: u16, | ||||
|     }, | ||||
|     /// Represents an unimplemented operation | ||||
|     #[error("Unrecognized opcode: {word:04x}")] | ||||
|     UnimplementedInstruction { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user