[PATCH v5 6/9] rust: bitfield: Add KUNIT tests for bitfield

Joel Fernandes posted 9 patches 2 days, 8 hours ago
[PATCH v5 6/9] rust: bitfield: Add KUNIT tests for bitfield
Posted by Joel Fernandes 2 days, 8 hours ago
Add KUNIT tests to make sure the macro is working correctly.

Signed-off-by: Joel Fernandes <joelagnelf@nvidia.com>
---
 rust/kernel/bitfield.rs | 321 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 321 insertions(+)

diff --git a/rust/kernel/bitfield.rs b/rust/kernel/bitfield.rs
index fed19918c3b9..9a20bcd2eb60 100644
--- a/rust/kernel/bitfield.rs
+++ b/rust/kernel/bitfield.rs
@@ -402,3 +402,324 @@ fn default() -> Self {
         }
     };
 }
+
+#[::kernel::macros::kunit_tests(kernel_bitfield)]
+mod tests {
+    use core::convert::TryFrom;
+
+    // Enum types for testing => and ?=> conversions
+    #[derive(Debug, Clone, Copy, PartialEq)]
+    enum MemoryType {
+        Unmapped = 0,
+        Normal = 1,
+        Device = 2,
+        Reserved = 3,
+    }
+
+    impl Default for MemoryType {
+        fn default() -> Self {
+            MemoryType::Unmapped
+        }
+    }
+
+    impl TryFrom<u8> for MemoryType {
+        type Error = u8;
+        fn try_from(value: u8) -> Result<Self, Self::Error> {
+            match value {
+                0 => Ok(MemoryType::Unmapped),
+                1 => Ok(MemoryType::Normal),
+                2 => Ok(MemoryType::Device),
+                3 => Ok(MemoryType::Reserved),
+                _ => Err(value),
+            }
+        }
+    }
+
+    impl From<MemoryType> for u64 {
+        fn from(mt: MemoryType) -> u64 {
+            mt as u64
+        }
+    }
+
+    #[derive(Debug, Clone, Copy, PartialEq)]
+    enum Priority {
+        Low = 0,
+        Medium = 1,
+        High = 2,
+        Critical = 3,
+    }
+
+    impl Default for Priority {
+        fn default() -> Self {
+            Priority::Low
+        }
+    }
+
+    impl From<u8> for Priority {
+        fn from(value: u8) -> Self {
+            match value & 0x3 {
+                0 => Priority::Low,
+                1 => Priority::Medium,
+                2 => Priority::High,
+                _ => Priority::Critical,
+            }
+        }
+    }
+
+    impl From<Priority> for u16 {
+        fn from(p: Priority) -> u16 {
+            p as u16
+        }
+    }
+
+    bitfield! {
+        struct TestPageTableEntry(u64) {
+            0:0       present     as bool;
+            1:1       writable    as bool;
+            11:9      available   as u8;
+            13:12     mem_type    as u8 ?=> MemoryType;
+            17:14     extended_type as u8 ?=> MemoryType;  // For testing failures
+            51:12     pfn         as u64;
+            51:12     pfn_overlap as u64;
+            61:52     available2  as u16;
+        }
+    }
+
+    bitfield! {
+        struct TestControlRegister(u16) {
+            0:0       enable      as bool;
+            3:1       mode        as u8;
+            5:4       priority    as u8 => Priority;
+            7:4       priority_nibble as u8;
+            15:8      channel     as u8;
+        }
+    }
+
+    bitfield! {
+        struct TestStatusRegister(u8) {
+            0:0       ready       as bool;
+            1:1       error       as bool;
+            3:2       state       as u8;
+            7:4       reserved    as u8;
+            7:0       full_byte   as u8;  // For entire register
+        }
+    }
+
+    #[test]
+    fn test_single_bits() {
+        let mut pte = TestPageTableEntry::default();
+
+        assert!(!pte.present());
+        assert!(!pte.writable());
+
+        pte = pte.set_present(true);
+        assert!(pte.present());
+
+        pte = pte.set_writable(true);
+        assert!(pte.writable());
+
+        pte = pte.set_writable(false);
+        assert!(!pte.writable());
+
+        assert_eq!(pte.available(), 0);
+        pte = pte.set_available(0x5);
+        assert_eq!(pte.available(), 0x5);
+    }
+
+    #[test]
+    fn test_range_fields() {
+        let mut pte = TestPageTableEntry::default();
+
+        pte = pte.set_pfn(0x123456);
+        assert_eq!(pte.pfn(), 0x123456);
+        // Test overlapping field reads same value
+        assert_eq!(pte.pfn_overlap(), 0x123456);
+
+        pte = pte.set_available(0x7);
+        assert_eq!(pte.available(), 0x7);
+
+        pte = pte.set_available2(0x3FF);
+        assert_eq!(pte.available2(), 0x3FF);
+
+        // Test TryFrom with ?=> for MemoryType
+        pte = pte.set_mem_type(MemoryType::Device);
+        assert_eq!(pte.mem_type(), Ok(MemoryType::Device));
+
+        pte = pte.set_mem_type(MemoryType::Normal);
+        assert_eq!(pte.mem_type(), Ok(MemoryType::Normal));
+
+        // Test all valid values for mem_type
+        pte = pte.set_mem_type(MemoryType::Reserved); // Valid value: 3
+        assert_eq!(pte.mem_type(), Ok(MemoryType::Reserved));
+
+        // Test failure case using extended_type field which has 4 bits (0-15)
+        // MemoryType only handles 0-3, so values 4-15 should return Err
+        let mut raw = pte.raw();
+        // Set bits 17:14 to 7 (invalid for MemoryType)
+        raw = (raw & !::kernel::bits::genmask_u64(14..=17)) | (0x7 << 14);
+        let invalid_pte = TestPageTableEntry::new(raw);
+        // Should return Err with the invalid value
+        assert_eq!(invalid_pte.extended_type(), Err(0x7));
+
+        // Test a valid value after testing invalid to ensure both cases work
+        // Set bits 17:14 to 2 (valid: Device)
+        raw = (raw & !::kernel::bits::genmask_u64(14..=17)) | (0x2 << 14);
+        let valid_pte = TestPageTableEntry::new(raw);
+        assert_eq!(valid_pte.extended_type(), Ok(MemoryType::Device));
+
+        let max_pfn = ::kernel::bits::genmask_u64(0..=39);
+        pte = pte.set_pfn(max_pfn);
+        assert_eq!(pte.pfn(), max_pfn);
+        assert_eq!(pte.pfn_overlap(), max_pfn);
+    }
+
+    #[test]
+    fn test_builder_pattern() {
+        let pte = TestPageTableEntry::default()
+            .set_present(true)
+            .set_writable(true)
+            .set_available(0x7)
+            .set_pfn(0xABCDEF)
+            .set_mem_type(MemoryType::Reserved)
+            .set_available2(0x3FF);
+
+        assert!(pte.present());
+        assert!(pte.writable());
+        assert_eq!(pte.available(), 0x7);
+        assert_eq!(pte.pfn(), 0xABCDEF);
+        assert_eq!(pte.pfn_overlap(), 0xABCDEF);
+        assert_eq!(pte.mem_type(), Ok(MemoryType::Reserved));
+        assert_eq!(pte.available2(), 0x3FF);
+    }
+
+    #[test]
+    fn test_raw_operations() {
+        let raw_value = 0x3FF0000003123E03u64;
+
+        let pte = TestPageTableEntry::new(raw_value);
+        assert_eq!(pte.raw(), raw_value);
+
+        assert!(pte.present());
+        assert!(pte.writable());
+        assert_eq!(pte.available(), 0x7);
+        assert_eq!(pte.pfn(), 0x3123);
+        assert_eq!(pte.pfn_overlap(), 0x3123);
+        assert_eq!(pte.mem_type(), Ok(MemoryType::Reserved));
+        assert_eq!(pte.available2(), 0x3FF);
+
+        // Test using direct constructor syntax TestStruct(value)
+        let pte2 = TestPageTableEntry::new(raw_value);
+        assert_eq!(pte2.raw(), raw_value);
+    }
+
+    #[test]
+    fn test_u16_bitfield() {
+        let mut ctrl = TestControlRegister::default();
+
+        assert!(!ctrl.enable());
+        assert_eq!(ctrl.mode(), 0);
+        assert_eq!(ctrl.priority(), Priority::Low);
+        assert_eq!(ctrl.priority_nibble(), 0);
+        assert_eq!(ctrl.channel(), 0);
+
+        ctrl = ctrl.set_enable(true);
+        assert!(ctrl.enable());
+
+        ctrl = ctrl.set_mode(0x5);
+        assert_eq!(ctrl.mode(), 0x5);
+
+        // Test From conversion with =>
+        ctrl = ctrl.set_priority(Priority::High);
+        assert_eq!(ctrl.priority(), Priority::High);
+        assert_eq!(ctrl.priority_nibble(), 0x2); // High = 2 in bits 5:4
+
+        ctrl = ctrl.set_channel(0xAB);
+        assert_eq!(ctrl.channel(), 0xAB);
+
+        // Test overlapping fields
+        ctrl = ctrl.set_priority_nibble(0xF);
+        assert_eq!(ctrl.priority_nibble(), 0xF);
+        assert_eq!(ctrl.priority(), Priority::Critical); // bits 5:4 = 0x3
+
+        let ctrl2 = TestControlRegister::default()
+            .set_enable(true)
+            .set_mode(0x3)
+            .set_priority(Priority::Medium)
+            .set_channel(0x42);
+
+        assert!(ctrl2.enable());
+        assert_eq!(ctrl2.mode(), 0x3);
+        assert_eq!(ctrl2.priority(), Priority::Medium);
+        assert_eq!(ctrl2.channel(), 0x42);
+
+        let raw_value: u16 = 0x4217;
+        let ctrl3 = TestControlRegister::new(raw_value);
+        assert_eq!(ctrl3.raw(), raw_value);
+        assert!(ctrl3.enable());
+        assert_eq!(ctrl3.priority(), Priority::Medium);
+        assert_eq!(ctrl3.priority_nibble(), 0x1);
+        assert_eq!(ctrl3.channel(), 0x42);
+    }
+
+    #[test]
+    fn test_u8_bitfield() {
+        let mut status = TestStatusRegister::default();
+
+        assert!(!status.ready());
+        assert!(!status.error());
+        assert_eq!(status.state(), 0);
+        assert_eq!(status.reserved(), 0);
+        assert_eq!(status.full_byte(), 0);
+
+        status = status.set_ready(true);
+        assert!(status.ready());
+        assert_eq!(status.full_byte(), 0x01);
+
+        status = status.set_error(true);
+        assert!(status.error());
+        assert_eq!(status.full_byte(), 0x03);
+
+        status = status.set_state(0x3);
+        assert_eq!(status.state(), 0x3);
+        assert_eq!(status.full_byte(), 0x0F);
+
+        status = status.set_reserved(0xA);
+        assert_eq!(status.reserved(), 0xA);
+        assert_eq!(status.full_byte(), 0xAF);
+
+        // Test overlapping field
+        status = status.set_full_byte(0x55);
+        assert_eq!(status.full_byte(), 0x55);
+        assert!(status.ready());
+        assert!(!status.error());
+        assert_eq!(status.state(), 0x1);
+        assert_eq!(status.reserved(), 0x5);
+
+        let status2 = TestStatusRegister::default()
+            .set_ready(true)
+            .set_state(0x2)
+            .set_reserved(0x5);
+
+        assert!(status2.ready());
+        assert!(!status2.error());
+        assert_eq!(status2.state(), 0x2);
+        assert_eq!(status2.reserved(), 0x5);
+        assert_eq!(status2.full_byte(), 0x59);
+
+        let raw_value: u8 = 0x59;
+        let status3 = TestStatusRegister::new(raw_value);
+        assert_eq!(status3.raw(), raw_value);
+        assert!(status3.ready());
+        assert!(!status3.error());
+        assert_eq!(status3.state(), 0x2);
+        assert_eq!(status3.reserved(), 0x5);
+        assert_eq!(status3.full_byte(), 0x59);
+
+        let status4 = TestStatusRegister::new(0xFF);
+        assert!(status4.ready());
+        assert!(status4.error());
+        assert_eq!(status4.state(), 0x3);
+        assert_eq!(status4.reserved(), 0xF);
+        assert_eq!(status4.full_byte(), 0xFF);
+    }
+}
-- 
2.34.1
Re: [PATCH v5 6/9] rust: bitfield: Add KUNIT tests for bitfield
Posted by Alexandre Courbot 21 hours ago
On Tue Sep 30, 2025 at 11:45 PM JST, Joel Fernandes wrote:
> Add KUNIT tests to make sure the macro is working correctly.
>
> Signed-off-by: Joel Fernandes <joelagnelf@nvidia.com>
> ---
>  rust/kernel/bitfield.rs | 321 ++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 321 insertions(+)
>
> diff --git a/rust/kernel/bitfield.rs b/rust/kernel/bitfield.rs
> index fed19918c3b9..9a20bcd2eb60 100644
> --- a/rust/kernel/bitfield.rs
> +++ b/rust/kernel/bitfield.rs
> @@ -402,3 +402,324 @@ fn default() -> Self {
>          }
>      };
>  }
> +
> +#[::kernel::macros::kunit_tests(kernel_bitfield)]
> +mod tests {
> +    use core::convert::TryFrom;
> +
> +    // Enum types for testing => and ?=> conversions
> +    #[derive(Debug, Clone, Copy, PartialEq)]
> +    enum MemoryType {
> +        Unmapped = 0,
> +        Normal = 1,
> +        Device = 2,
> +        Reserved = 3,
> +    }
> +
> +    impl Default for MemoryType {
> +        fn default() -> Self {
> +            MemoryType::Unmapped
> +        }
> +    }

Tip: you can add `Default` to the `#[derive]` marker of `MemoryType` and
mark the variant you want as default with `#[default]` instead of
providing a full impl block:

    #[derive(Debug, Default, Clone, Copy, PartialEq)]
    enum MemoryType {
        #[default]
        Unmapped = 0,
        Normal = 1,
        Device = 2,
        Reserved = 3,
    }

> +
> +    impl TryFrom<u8> for MemoryType {
> +        type Error = u8;
> +        fn try_from(value: u8) -> Result<Self, Self::Error> {
> +            match value {
> +                0 => Ok(MemoryType::Unmapped),
> +                1 => Ok(MemoryType::Normal),
> +                2 => Ok(MemoryType::Device),
> +                3 => Ok(MemoryType::Reserved),
> +                _ => Err(value),
> +            }
> +        }
> +    }
> +
> +    impl From<MemoryType> for u64 {
> +        fn from(mt: MemoryType) -> u64 {
> +            mt as u64
> +        }
> +    }
> +
> +    #[derive(Debug, Clone, Copy, PartialEq)]
> +    enum Priority {
> +        Low = 0,
> +        Medium = 1,
> +        High = 2,
> +        Critical = 3,
> +    }
> +
> +    impl Default for Priority {
> +        fn default() -> Self {
> +            Priority::Low
> +        }
> +    }
> +
> +    impl From<u8> for Priority {
> +        fn from(value: u8) -> Self {
> +            match value & 0x3 {
> +                0 => Priority::Low,
> +                1 => Priority::Medium,
> +                2 => Priority::High,
> +                _ => Priority::Critical,
> +            }
> +        }
> +    }
> +
> +    impl From<Priority> for u16 {
> +        fn from(p: Priority) -> u16 {
> +            p as u16
> +        }
> +    }
> +
> +    bitfield! {
> +        struct TestPageTableEntry(u64) {
> +            0:0       present     as bool;
> +            1:1       writable    as bool;
> +            11:9      available   as u8;
> +            13:12     mem_type    as u8 ?=> MemoryType;
> +            17:14     extended_type as u8 ?=> MemoryType;  // For testing failures
> +            51:12     pfn         as u64;
> +            51:12     pfn_overlap as u64;
> +            61:52     available2  as u16;
> +        }
> +    }
> +
> +    bitfield! {
> +        struct TestControlRegister(u16) {
> +            0:0       enable      as bool;
> +            3:1       mode        as u8;
> +            5:4       priority    as u8 => Priority;
> +            7:4       priority_nibble as u8;
> +            15:8      channel     as u8;
> +        }
> +    }
> +
> +    bitfield! {
> +        struct TestStatusRegister(u8) {
> +            0:0       ready       as bool;
> +            1:1       error       as bool;
> +            3:2       state       as u8;
> +            7:4       reserved    as u8;
> +            7:0       full_byte   as u8;  // For entire register
> +        }
> +    }
> +
> +    #[test]
> +    fn test_single_bits() {
> +        let mut pte = TestPageTableEntry::default();
> +
> +        assert!(!pte.present());
> +        assert!(!pte.writable());
> +
> +        pte = pte.set_present(true);
> +        assert!(pte.present());
> +
> +        pte = pte.set_writable(true);
> +        assert!(pte.writable());
> +
> +        pte = pte.set_writable(false);
> +        assert!(!pte.writable());
> +
> +        assert_eq!(pte.available(), 0);
> +        pte = pte.set_available(0x5);
> +        assert_eq!(pte.available(), 0x5);

I'd suggest testing the actual raw value of the register on top of
invoking the getter. That way you also test that:

- The right field is actually written (i.e. if the offset is off by one,
  the getter will return the expected result even though the bitfield
  has the wrong value),
- No other field has been affected.

So something like:

    pte = pte.set_present(true);
    assert!(pte.present());
    assert(pte.into(), 0x1u64);

    pte = pte.set_writable(true);
    assert!(pte.writable());
    assert(pte.into(), 0x3u64);

It might look a bit gross, but it is ok since these are not doctests
that users are going to take as a reference, so we case improve test
coverage at the detriment of readability.
Re: [PATCH v5 6/9] rust: bitfield: Add KUNIT tests for bitfield
Posted by Elle Rhumsaa 20 hours ago
On 10/2/25 1:41 AM, Alexandre Courbot wrote:

> On Tue Sep 30, 2025 at 11:45 PM JST, Joel Fernandes wrote:
>> Add KUNIT tests to make sure the macro is working correctly.
>>
>> Signed-off-by: Joel Fernandes <joelagnelf@nvidia.com>
>> ---
>>   rust/kernel/bitfield.rs | 321 ++++++++++++++++++++++++++++++++++++++++
>>   1 file changed, 321 insertions(+)
>>
>> diff --git a/rust/kernel/bitfield.rs b/rust/kernel/bitfield.rs
>> index fed19918c3b9..9a20bcd2eb60 100644
>> --- a/rust/kernel/bitfield.rs
>> +++ b/rust/kernel/bitfield.rs
>> @@ -402,3 +402,324 @@ fn default() -> Self {
>>           }
>>       };
>>   }
>> +
>> +#[::kernel::macros::kunit_tests(kernel_bitfield)]
>> +mod tests {
>> +    use core::convert::TryFrom;
>> +
>> +    // Enum types for testing => and ?=> conversions
>> +    #[derive(Debug, Clone, Copy, PartialEq)]
>> +    enum MemoryType {
>> +        Unmapped = 0,
>> +        Normal = 1,
>> +        Device = 2,
>> +        Reserved = 3,
>> +    }
>> +
>> +    impl Default for MemoryType {
>> +        fn default() -> Self {
>> +            MemoryType::Unmapped
>> +        }
>> +    }
> Tip: you can add `Default` to the `#[derive]` marker of `MemoryType` and
> mark the variant you want as default with `#[default]` instead of
> providing a full impl block:
>
>      #[derive(Debug, Default, Clone, Copy, PartialEq)]
>      enum MemoryType {
>          #[default]
>          Unmapped = 0,
>          Normal = 1,
>          Device = 2,
>          Reserved = 3,
>      }

I would alternatively recommend to provide a `MemoryType::new` impl with 
a `const` definition:

```rust
impl MemoryType {
     pub const fn new() -> Self {

         Self::Unmapped

     }
}

impl Default for MemoryType {
     fn default() -> Self {
         Self::new()
     }
}
```

This pattern allows using `MemoryType::new()` in `const` contexts, while 
also providing the `Default` impl using the same default. It's somewhat 
of a workaround until we get `const` traits.

>> +
>> +    impl TryFrom<u8> for MemoryType {
>> +        type Error = u8;
>> +        fn try_from(value: u8) -> Result<Self, Self::Error> {
>> +            match value {
>> +                0 => Ok(MemoryType::Unmapped),
>> +                1 => Ok(MemoryType::Normal),
>> +                2 => Ok(MemoryType::Device),
>> +                3 => Ok(MemoryType::Reserved),
>> +                _ => Err(value),
>> +            }
>> +        }
>> +    }
>> +
>> +    impl From<MemoryType> for u64 {
>> +        fn from(mt: MemoryType) -> u64 {
>> +            mt as u64
>> +        }
>> +    }
>> +
>> +    #[derive(Debug, Clone, Copy, PartialEq)]
>> +    enum Priority {
>> +        Low = 0,
>> +        Medium = 1,
>> +        High = 2,
>> +        Critical = 3,
>> +    }
>> +
>> +    impl Default for Priority {
>> +        fn default() -> Self {
>> +            Priority::Low
>> +        }
>> +    }
>> +
>> +    impl From<u8> for Priority {
>> +        fn from(value: u8) -> Self {
>> +            match value & 0x3 {
>> +                0 => Priority::Low,
>> +                1 => Priority::Medium,
>> +                2 => Priority::High,
>> +                _ => Priority::Critical,
>> +            }
>> +        }
>> +    }
>> +
>> +    impl From<Priority> for u16 {
>> +        fn from(p: Priority) -> u16 {
>> +            p as u16
>> +        }
>> +    }
>> +
>> +    bitfield! {
>> +        struct TestPageTableEntry(u64) {
>> +            0:0       present     as bool;
>> +            1:1       writable    as bool;
>> +            11:9      available   as u8;
>> +            13:12     mem_type    as u8 ?=> MemoryType;
>> +            17:14     extended_type as u8 ?=> MemoryType;  // For testing failures
>> +            51:12     pfn         as u64;
>> +            51:12     pfn_overlap as u64;
>> +            61:52     available2  as u16;
>> +        }
>> +    }
>> +
>> +    bitfield! {
>> +        struct TestControlRegister(u16) {
>> +            0:0       enable      as bool;
>> +            3:1       mode        as u8;
>> +            5:4       priority    as u8 => Priority;
>> +            7:4       priority_nibble as u8;
>> +            15:8      channel     as u8;
>> +        }
>> +    }
>> +
>> +    bitfield! {
>> +        struct TestStatusRegister(u8) {
>> +            0:0       ready       as bool;
>> +            1:1       error       as bool;
>> +            3:2       state       as u8;
>> +            7:4       reserved    as u8;
>> +            7:0       full_byte   as u8;  // For entire register
>> +        }
>> +    }
>> +
>> +    #[test]
>> +    fn test_single_bits() {
>> +        let mut pte = TestPageTableEntry::default();
>> +
>> +        assert!(!pte.present());
>> +        assert!(!pte.writable());
>> +
>> +        pte = pte.set_present(true);
>> +        assert!(pte.present());
>> +
>> +        pte = pte.set_writable(true);
>> +        assert!(pte.writable());
>> +
>> +        pte = pte.set_writable(false);
>> +        assert!(!pte.writable());
>> +
>> +        assert_eq!(pte.available(), 0);
>> +        pte = pte.set_available(0x5);
>> +        assert_eq!(pte.available(), 0x5);
> I'd suggest testing the actual raw value of the register on top of
> invoking the getter. That way you also test that:
>
> - The right field is actually written (i.e. if the offset is off by one,
>    the getter will return the expected result even though the bitfield
>    has the wrong value),
> - No other field has been affected.
>
> So something like:
>
>      pte = pte.set_present(true);
>      assert!(pte.present());
>      assert(pte.into(), 0x1u64);
>
>      pte = pte.set_writable(true);
>      assert!(pte.writable());
>      assert(pte.into(), 0x3u64);
>
> It might look a bit gross, but it is ok since these are not doctests
> that users are going to take as a reference, so we case improve test
> coverage at the detriment of readability.
>
Re: [PATCH v5 6/9] rust: bitfield: Add KUNIT tests for bitfield
Posted by Alexandre Courbot 20 hours ago
On Thu Oct 2, 2025 at 11:16 AM JST, Elle Rhumsaa wrote:
> On 10/2/25 1:41 AM, Alexandre Courbot wrote:
>
>> On Tue Sep 30, 2025 at 11:45 PM JST, Joel Fernandes wrote:
>>> Add KUNIT tests to make sure the macro is working correctly.
>>>
>>> Signed-off-by: Joel Fernandes <joelagnelf@nvidia.com>
>>> ---
>>>   rust/kernel/bitfield.rs | 321 ++++++++++++++++++++++++++++++++++++++++
>>>   1 file changed, 321 insertions(+)
>>>
>>> diff --git a/rust/kernel/bitfield.rs b/rust/kernel/bitfield.rs
>>> index fed19918c3b9..9a20bcd2eb60 100644
>>> --- a/rust/kernel/bitfield.rs
>>> +++ b/rust/kernel/bitfield.rs
>>> @@ -402,3 +402,324 @@ fn default() -> Self {
>>>           }
>>>       };
>>>   }
>>> +
>>> +#[::kernel::macros::kunit_tests(kernel_bitfield)]
>>> +mod tests {
>>> +    use core::convert::TryFrom;
>>> +
>>> +    // Enum types for testing => and ?=> conversions
>>> +    #[derive(Debug, Clone, Copy, PartialEq)]
>>> +    enum MemoryType {
>>> +        Unmapped = 0,
>>> +        Normal = 1,
>>> +        Device = 2,
>>> +        Reserved = 3,
>>> +    }
>>> +
>>> +    impl Default for MemoryType {
>>> +        fn default() -> Self {
>>> +            MemoryType::Unmapped
>>> +        }
>>> +    }
>> Tip: you can add `Default` to the `#[derive]` marker of `MemoryType` and
>> mark the variant you want as default with `#[default]` instead of
>> providing a full impl block:
>>
>>      #[derive(Debug, Default, Clone, Copy, PartialEq)]
>>      enum MemoryType {
>>          #[default]
>>          Unmapped = 0,
>>          Normal = 1,
>>          Device = 2,
>>          Reserved = 3,
>>      }
>
> I would alternatively recommend to provide a `MemoryType::new` impl with 
> a `const` definition:
>
> ```rust
> impl MemoryType {
>      pub const fn new() -> Self {
>
>          Self::Unmapped
>
>      }
> }
>
> impl Default for MemoryType {
>      fn default() -> Self {
>          Self::new()
>      }
> }
> ```
>
> This pattern allows using `MemoryType::new()` in `const` contexts, while 
> also providing the `Default` impl using the same default. It's somewhat 
> of a workaround until we get `const` traits.

That's an elegant pattern generally speaking, but I don't think we would
benefit from using it in these unit tests.
Re: [PATCH v5 6/9] rust: bitfield: Add KUNIT tests for bitfield
Posted by Elle Rhumsaa 19 hours ago
On 10/2/25 2:51 AM, Alexandre Courbot wrote:
> On Thu Oct 2, 2025 at 11:16 AM JST, Elle Rhumsaa wrote:
>> On 10/2/25 1:41 AM, Alexandre Courbot wrote:
>>
>>> On Tue Sep 30, 2025 at 11:45 PM JST, Joel Fernandes wrote:
>>>> Add KUNIT tests to make sure the macro is working correctly.
>>>>
>>>> Signed-off-by: Joel Fernandes <joelagnelf@nvidia.com>
>>>> ---
>>>>    rust/kernel/bitfield.rs | 321 ++++++++++++++++++++++++++++++++++++++++
>>>>    1 file changed, 321 insertions(+)
>>>>
>>>> diff --git a/rust/kernel/bitfield.rs b/rust/kernel/bitfield.rs
>>>> index fed19918c3b9..9a20bcd2eb60 100644
>>>> --- a/rust/kernel/bitfield.rs
>>>> +++ b/rust/kernel/bitfield.rs
>>>> @@ -402,3 +402,324 @@ fn default() -> Self {
>>>>            }
>>>>        };
>>>>    }
>>>> +
>>>> +#[::kernel::macros::kunit_tests(kernel_bitfield)]
>>>> +mod tests {
>>>> +    use core::convert::TryFrom;
>>>> +
>>>> +    // Enum types for testing => and ?=> conversions
>>>> +    #[derive(Debug, Clone, Copy, PartialEq)]
>>>> +    enum MemoryType {
>>>> +        Unmapped = 0,
>>>> +        Normal = 1,
>>>> +        Device = 2,
>>>> +        Reserved = 3,
>>>> +    }
>>>> +
>>>> +    impl Default for MemoryType {
>>>> +        fn default() -> Self {
>>>> +            MemoryType::Unmapped
>>>> +        }
>>>> +    }
>>> Tip: you can add `Default` to the `#[derive]` marker of `MemoryType` and
>>> mark the variant you want as default with `#[default]` instead of
>>> providing a full impl block:
>>>
>>>       #[derive(Debug, Default, Clone, Copy, PartialEq)]
>>>       enum MemoryType {
>>>           #[default]
>>>           Unmapped = 0,
>>>           Normal = 1,
>>>           Device = 2,
>>>           Reserved = 3,
>>>       }
>> I would alternatively recommend to provide a `MemoryType::new` impl with
>> a `const` definition:
>>
>> ```rust
>> impl MemoryType {
>>       pub const fn new() -> Self {
>>
>>           Self::Unmapped
>>
>>       }
>> }
>>
>> impl Default for MemoryType {
>>       fn default() -> Self {
>>           Self::new()
>>       }
>> }
>> ```
>>
>> This pattern allows using `MemoryType::new()` in `const` contexts, while
>> also providing the `Default` impl using the same default. It's somewhat
>> of a workaround until we get `const` traits.
> That's an elegant pattern generally speaking, but I don't think we would
> benefit from using it in these unit tests.

*facepalm* right, I lost the context that these data structures were 
KUNIT-specific. Please disregard.