Browse Source

add tests to Instruction

bidhan-a 1 tháng trước cách đây
mục cha
commit
1f19a9a4d7
1 tập tin đã thay đổi với 161 bổ sung2 xóa
  1. 161 2
      crates/common/src/instruction.rs

+ 161 - 2
crates/common/src/instruction.rs

@@ -132,7 +132,11 @@ impl Instruction {
     pub fn from_bytes(bytes: &[u8]) -> Result<Self, SBPFError> {
         let span = 0..bytes.len();
 
-        let opcode = Opcode::from_u8(bytes[0]).unwrap();
+        let opcode = Opcode::from_u8(bytes[0]).ok_or(SBPFError::BytecodeError {
+            error: format!("Invalid opcode: {:?}", bytes[0]),
+            span: span.clone(),
+            custom_label: None,
+        })?;
         let reg = bytes[1];
         let src = reg >> 4;
         let dst = reg & 0x0f;
@@ -747,13 +751,15 @@ impl Instruction {
 mod test {
     use hex_literal::hex;
 
-    use crate::instruction::Instruction;
+    use crate::instruction::{Instruction, Register};
+    use crate::opcode::Opcode;
 
     #[test]
     fn serialize_e2e() {
         let b = hex!("9700000000000000");
         let i = Instruction::from_bytes(&b).unwrap();
         assert_eq!(i.to_bytes(), &b);
+        assert_eq!(i.to_asm().unwrap(), "mod64 r0, 0");
     }
 
     #[test]
@@ -761,5 +767,158 @@ mod test {
         let b = hex!("18010000000000000000000000000000");
         let i = Instruction::from_bytes(&b).unwrap();
         assert_eq!(i.to_bytes(), &b);
+        assert_eq!(i.to_asm().unwrap(), "lddw r1, 0");
+    }
+
+    #[test]
+    fn serialize_e2e_add64_imm() {
+        let b = hex!("0701000000000000");
+        let i = Instruction::from_bytes(&b).unwrap();
+        assert_eq!(i.to_bytes(), &b);
+        assert_eq!(i.to_asm().unwrap(), "add64 r1, 0");
+    }
+
+    #[test]
+    fn serialize_e2e_add64_reg() {
+        let b = hex!("0f12000000000000");
+        let i = Instruction::from_bytes(&b).unwrap();
+        assert_eq!(i.to_bytes(), &b);
+        assert_eq!(i.to_asm().unwrap(), "add64 r2, r1");
+    }
+
+    #[test]
+    fn serialize_e2e_ja() {
+        let b = hex!("05000a0000000000");
+        let i = Instruction::from_bytes(&b).unwrap();
+        assert_eq!(i.to_bytes(), &b);
+        assert_eq!(i.to_asm().unwrap(), "jeq +10");
+    }
+
+    #[test]
+    fn serialize_e2e_jeq_imm() {
+        let b = hex!("15030a0001000000");
+        let i = Instruction::from_bytes(&b).unwrap();
+        assert_eq!(i.to_bytes(), &b);
+        assert_eq!(i.to_asm().unwrap(), "jeq r3, 1, +10");
+    }
+
+    #[test]
+    fn serialize_e2e_jeq_reg() {
+        let b = hex!("1d210a0000000000");
+        let i = Instruction::from_bytes(&b).unwrap();
+        assert_eq!(i.to_bytes(), &b);
+        assert_eq!(i.to_asm().unwrap(), "jeq r1, r2, +10");
+    }
+
+    #[test]
+    fn serialize_e2e_ldxw() {
+        let b = hex!("6112000000000000");
+        let i = Instruction::from_bytes(&b).unwrap();
+        assert_eq!(i.to_bytes(), &b);
+        assert_eq!(i.to_asm().unwrap(), "ldxw r2, [r1+0]");
+    }
+
+    #[test]
+    fn serialize_e2e_stxw() {
+        let b = hex!("6312000000000000");
+        let i = Instruction::from_bytes(&b).unwrap();
+        assert_eq!(i.to_bytes(), &b);
+        assert_eq!(i.to_asm().unwrap(), "stxw [r2+0], r1");
+    }
+
+    #[test]
+    fn serialize_e2e_neg64() {
+        let b = hex!("8700000000000000");
+        let i = Instruction::from_bytes(&b).unwrap();
+        assert_eq!(i.to_bytes(), &b);
+        assert_eq!(i.to_asm().unwrap(), "neg64 r0");
+    }
+
+    #[test]
+    fn test_instruction_size() {
+        let exit = Instruction::from_bytes(&hex!("9500000000000000")).unwrap();
+        assert_eq!(exit.get_size(), 8);
+
+        let lddw = Instruction::from_bytes(&hex!("18010000000000000000000000000000")).unwrap();
+        assert_eq!(lddw.get_size(), 16);
+    }
+
+    #[test]
+    fn test_is_jump() {
+        let ja = Instruction::from_bytes(&hex!("0500000000000000")).unwrap();
+        assert!(ja.is_jump());
+
+        let jeq_imm = Instruction::from_bytes(&hex!("1502000000000000")).unwrap();
+        assert!(jeq_imm.is_jump());
+
+        let jeq_reg = Instruction::from_bytes(&hex!("1d12000000000000")).unwrap();
+        assert!(jeq_reg.is_jump());
+
+        let exit = Instruction::from_bytes(&hex!("9500000000000000")).unwrap();
+        assert!(!exit.is_jump());
+
+        let add64 = Instruction::from_bytes(&hex!("0701000000000000")).unwrap();
+        assert!(!add64.is_jump());
+    }
+
+    #[test]
+    fn test_off_str() {
+        let pos_off = Instruction {
+            opcode: Opcode::Ja,
+            dst: None,
+            src: None,
+            off: Some(10),
+            imm: None,
+            span: 0..8,
+        };
+        assert_eq!(pos_off.off_str(), "+10");
+
+        let neg_off = Instruction {
+            opcode: Opcode::Ja,
+            dst: None,
+            src: None,
+            off: Some(-10),
+            imm: None,
+            span: 0..8,
+        };
+        assert_eq!(neg_off.off_str(), "-10");
+    }
+
+    #[test]
+    fn test_dst_off() {
+        let inst = Instruction {
+            opcode: Opcode::Ldxw,
+            dst: Some(Register { n: 1 }),
+            src: Some(Register { n: 2 }),
+            off: Some(10),
+            imm: None,
+            span: 0..8,
+        };
+        assert_eq!(inst.dst_off(), "[r1+10]");
+    }
+
+    #[test]
+    fn test_src_off() {
+        let inst = Instruction {
+            opcode: Opcode::Ldxw,
+            dst: Some(Register { n: 1 }),
+            src: Some(Register { n: 2 }),
+            off: Some(-5),
+            imm: None,
+            span: 0..8,
+        };
+        assert_eq!(inst.src_off(), "[r2-5]");
+    }
+
+    #[test]
+    fn test_invalid_opcode() {
+        let result = Instruction::from_bytes(&hex!("ff00000000000000"));
+        assert!(result.is_err());
+    }
+
+    #[test]
+    fn test_unsupported_opcode() {
+        let add32 = Instruction::from_bytes(&hex!("1300000000000000"));
+        assert!(add32.is_err());
     }
 }