Add KUNIT tests to make sure the macros are working correctly. Signed-off-by: Joel Fernandes <joelagn...@nvidia.com> --- drivers/gpu/nova-core/bitstruct.rs | 198 +++++++++++++++++++++++++++++ 1 file changed, 198 insertions(+)
diff --git a/drivers/gpu/nova-core/bitstruct.rs b/drivers/gpu/nova-core/bitstruct.rs index 661a75da0a9c..7ce2f4ecfbba 100644 --- a/drivers/gpu/nova-core/bitstruct.rs +++ b/drivers/gpu/nova-core/bitstruct.rs @@ -147,3 +147,201 @@ impl $struct_name { } }; } + +#[kunit_tests(nova_core_bitstruct)] +mod kunit_tests { + // These are dummy structures just for testing (not real hardware). + bitstruct! { + #[repr(u64)] + struct TestPageTableEntry { + 0:0 present as bool, + 1:1 writable as bool, + 11:9 available as u8, + 51:12 pfn as u64, + 61:52 available2 as u16, + } + } + + bitstruct! { + #[repr(u16)] + struct TestControlRegister { + 0:0 enable as bool, + 3:1 mode as u8, + 7:4 priority as u8, + 15:8 channel as u8, + } + } + + bitstruct! { + #[repr(u8)] + struct TestStatusRegister { + 0:0 ready as bool, + 1:1 error as bool, + 3:2 state as u8, + 7:4 reserved as u8, + } + } + + #[test] + fn test_single_bits() { + let mut pte = TestPageTableEntry::default(); + + // Test initial state of boolean fields - expected false + assert!(!pte.present()); + assert!(!pte.writable()); + + pte.set_present(true); + assert!(pte.present()); + + pte.set_writable(true); + assert!(pte.writable()); + + pte.set_writable(false); + assert!(!pte.writable()); + + // Test available field (3 bits) + assert_eq!(pte.available(), 0); + pte.set_available(0x5); + assert_eq!(pte.available(), 0x5); + } + + #[test] + fn test_range_fields() { + let mut pte = TestPageTableEntry::default(); + + pte.set_pfn(0x123456); + assert_eq!(pte.pfn(), 0x123456); + + pte.set_available(0x7); + assert_eq!(pte.available(), 0x7); + + pte.set_available2(0x3FF); + assert_eq!(pte.available2(), 0x3FF); + + let max_pfn = (1u64 << 40) - 1; // 40 bits for pfn + pte.set_pfn(max_pfn); + assert_eq!(pte.pfn(), max_pfn); + } + + #[test] + fn test_builder_pattern() { + let pte = TestPageTableEntry::default() + .with_present(true) + .with_writable(true) + .with_available(0x7) + .with_pfn(0xABCDEF) + .with_available2(0x3FF); + + assert!(pte.present()); + assert!(pte.writable()); + assert_eq!(pte.available(), 0x7); + assert_eq!(pte.pfn(), 0xABCDEF); + assert_eq!(pte.available2(), 0x3FF); + } + + #[test] + fn test_raw_operations() { + let raw_value = 0x3FF0000000123E03u64; + let pte = TestPageTableEntry::from_raw(raw_value); + assert_eq!(pte.into_raw(), raw_value); + + assert!(pte.present()); // bit 0 + assert!(pte.writable()); // bit 1 + assert_eq!(pte.available(), 0x7); // bits 9-11: 0xE00 >> 9 = 0x7 + assert_eq!(pte.pfn(), 0x123); // bits 12-51: 0x123 << 12 + assert_eq!(pte.available2(), 0x3FF); // bits 52-61: 0x3FF << 52 + } + + #[test] + fn test_u16_bitstruct() { + let mut ctrl = TestControlRegister::default(); + + // Test initial state + assert!(!ctrl.enable()); + assert_eq!(ctrl.mode(), 0); + assert_eq!(ctrl.priority(), 0); + assert_eq!(ctrl.channel(), 0); + + ctrl.set_enable(true); + assert!(ctrl.enable()); + + ctrl.set_mode(0x5); + assert_eq!(ctrl.mode(), 0x5); + + ctrl.set_priority(0xF); + assert_eq!(ctrl.priority(), 0xF); + + ctrl.set_channel(0xAB); + assert_eq!(ctrl.channel(), 0xAB); + + // Test u16 builder pattern + let ctrl2 = TestControlRegister::default() + .with_enable(true) + .with_mode(0x3) + .with_priority(0x8) + .with_channel(0x42); + + assert!(ctrl2.enable()); + assert_eq!(ctrl2.mode(), 0x3); + assert_eq!(ctrl2.priority(), 0x8); + assert_eq!(ctrl2.channel(), 0x42); + + // Test u16 raw operations + let raw_value: u16 = 0x4281; + let ctrl3 = TestControlRegister::from_raw(raw_value); + assert_eq!(ctrl3.into_raw(), raw_value); + assert!(ctrl3.enable()); + assert_eq!(ctrl3.priority(), 0x8); + assert_eq!(ctrl3.channel(), 0x42); + } + + #[test] + fn test_u8_bitstruct() { + let mut status = TestStatusRegister::default(); + + // Test initial state + assert!(!status.ready()); + assert!(!status.error()); + assert_eq!(status.state(), 0); + assert_eq!(status.reserved(), 0); + + status.set_ready(true); + assert!(status.ready()); + + status.set_error(true); + assert!(status.error()); + + status.set_state(0x3); + assert_eq!(status.state(), 0x3); + + status.set_reserved(0xA); + assert_eq!(status.reserved(), 0xA); + + // Test u8 builder pattern + let status2 = TestStatusRegister::default() + .with_ready(true) + .with_state(0x2) + .with_reserved(0x5); + + assert!(status2.ready()); + assert!(!status2.error()); + assert_eq!(status2.state(), 0x2); + assert_eq!(status2.reserved(), 0x5); + + // Test u8 raw operations + let raw_value: u8 = 0x59; + let status3 = TestStatusRegister::from_raw(raw_value); + assert_eq!(status3.into_raw(), raw_value); + assert!(status3.ready()); + assert!(!status3.error()); + assert_eq!(status3.state(), 0x2); + assert_eq!(status3.reserved(), 0x5); + + // Test max raw value - all bits set + let status4 = TestStatusRegister::from_raw(0xFF); + assert!(status4.ready()); + assert!(status4.error()); + assert_eq!(status4.state(), 0x3); + assert_eq!(status4.reserved(), 0xF); + } +} -- 2.34.1