unit-testing - 在构建时验证结构布局

标签 unit-testing rust rust-no-std

如何在不运行代码的情况下验证 (repr(C)) 结构的布局?例如。当我有

#[repr(C)]
struct Registers {
    urxd:       u32,        // 0x00
    _rsrvd0:    [u32;15],
    utxd:       u32,        // 0x40
    _rsrvd1:    [u32;15],
    ucr1:       u32,        // 0x80
}

ucr1 不在位置 0x80 时(例如,由于错误计算的 _rsrvd 成员或取决于目标的填充),如何使构建过程失败?

在 C 语言中我会写类似的东西

struct foo {
    uint32_t    a;
    uint32_t    b;
    uint32_t    c;
    uint32_t    d;
};

static void _test() {
    _Static_assert(offsetof(struct foo, d) == 12);
}

对于 _Static_assert 来说,似乎存在像 static_assertions 这样的包,它们实现了类似 C 时代的黑客技术(负数组大小等)。

但是对于 offsetof() 我只找到了非 const 实现。

代码适用于没有 #[test] 支持的嵌入式平台,因此我无法在运行时测试它。在 std 平台上运行 #[test] 可能会给出错误的结果,因为那里的填充/对齐方式不同。

最佳答案

您可以使用 const_field_offset 箱来获取偏移量,并使用 static_assertions 在构建期间进行断言。

use const_field_offset;
use static_assertions as sa;

#[repr(C)]
#[derive(const_field_offset::FieldOffsets)]
struct Registers {
    urxd:       u32,        // 0x00
    _rsrvd0:    [u32;15],
    utxd:       u32,        // 0x40
    _rsrvd1:    [u32;15],
    ucr1:       u32,        // 0x80
}

sa::const_assert!(0x80 == Registers::FIELD_OFFSETS.ucr1.get_byte_offset());

当断言失败时,错误消息并不是很有帮助,但它至少会使构建失败:

sa::const_assert!(0x79 == Registers::FIELD_OFFSETS.ucr1.get_byte_offset());
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attempt to compute `0_usize - 1_usize`, which would overflow

关于unit-testing - 在构建时验证结构布局,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73652563/

相关文章:

rust - 从 fmt::Argus 获取数据而不进行堆分配

arrays - 来自范围的常量数组

python - 如何以一种可以在单个命令中运行所有测试的方式组织 python 测试?

python - 是否有一个python单元测试框架可以在比较字符串时提供紧凑的错误输出

multithreading - 多线程 : what am I missing? 随着时间的推移性能严重下降

rust - 如何在 Rust 中删除目录中的所有文件而不是目录本身?

python - 如何从测试套件中提取测试用例列表?

.net - 如何填充 ObjectSet (EntityFramework)?

if-statement - 结果和 if/else/return 语句 E0308 错误