1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
#![cfg(target_os = "linux")]
use assay_common::encode_kernel_dev;
use proptest::prelude::*;
// Inverse of kernel new_encode_dev logic:
// (minor & 0xff) | (major << 8) | ((minor & !0xff) << 12)
//
// Decoded:
// major = (dev >> 8) & 0xfff
// minor = (dev & 0xff) | ((dev >> 12) & 0xfff00)
fn decode_kernel_dev(dev: u32) -> (u32, u32) {
let major = (dev >> 8) & 0xfff;
let minor = (dev & 0xff) | ((dev >> 12) & 0xfff00);
(major, minor)
}
// Helper mimicking Linux kernel `new_encode_dev` (include/linux/kdev_t.h)
// (minor & 0xff) | ((major & 0xfff) << 8) | ((minor & !0xff) << 12)
fn expected_new_encode_dev(major: u32, minor: u32) -> u32 {
(minor & 0xff) | ((major & 0xfff) << 8) | ((minor & !0xff) << 12)
}
#[test]
fn test_regression_pairs() {
let pairs = vec![
(0, 0), // Zero
(1, 1), // Basic (1, 1) -> 0x101
(8, 1), // SDA1 typical -> 0x801
(255, 255), // Classic 8-bit limits
(4095, 1048575), // Max standard (12-bit major, 20-bit minor)
(0, 256), // Minor > 255 (extended minor part usage)
(300, 0), // Major > 255
];
for (maj, min) in pairs {
// Construct a "fake" dev_t.
// On Linux we could use libc::makedev, but we want to verify OUR encoding logic
// against the expected bit pattern regardless of the host platform's libc.
// Functional test: if we strictly assume input `dev` to encode_kernel_dev is
// a u64 coming from a Linux-compatible source (or our own internal representation).
//
// Actually, encode_kernel_dev takes u64 and calls libc::major/minor.
// We can't easily mock libc here.
// Ideally we would verify: encode_kernel_dev(makedev(maj, min)) == mkdev_u32(maj, min).
// But makedev varies by platform.
//
// Since this test runs on the Linux CI runner (or is gated), we can assume real Linux behavior.
let dev_t = libc::makedev(maj as _, min as _) as u64;
// Sanity check: does the platform libc agree with our inputs?
let extracted_maj = libc::major(dev_t as _) as u32;
let extracted_min = libc::minor(dev_t as _) as u32;
if extracted_maj == maj && extracted_min == min {
let encoded = encode_kernel_dev(dev_t);
let expected = expected_new_encode_dev(maj, min);
assert_eq!(
encoded, expected,
"Failed for ({}, {}) -> Expected {:#x}, Got {:#x}",
maj, min, expected, encoded
);
} else {
eprintln!(
"Skipping ({}, {}) - Platform makedev/major mismatch (Got {}, {})",
maj, min, extracted_maj, extracted_min
);
}
}
}
proptest! {
#[test]
fn test_roundtrip_property(major in 0u32..4096, minor in 0u32..1048576) {
// We want to verify: decode(encode_logic(maj, min)) == (maj, min)
// We cannot easily use `encode_kernel_dev` because of `libc` platform dependency on input.
// So we test the *logic* directly here essentially.
//
// Manual encode logic matching `encode_kernel_dev`:
let encoded = expected_new_encode_dev(major, minor);
let (dec_maj, dec_min) = decode_kernel_dev(encoded);
assert_eq!(dec_maj, major);
assert_eq!(dec_min, minor);
}
}