#x86-64 #单元测试 #虚拟机 #kvm #测试运行器 #操作系统

nightly x86test

裸机x86测试的定制测试运行器

5个版本

0.0.5 2022年3月3日
0.0.4 2022年1月25日
0.0.3 2020年4月24日
0.0.2 2019年9月12日
0.0.1 2019年8月24日

#396 in 测试

Download history 4/week @ 2024-03-14 36/week @ 2024-03-28 22/week @ 2024-04-04

每月165次下载

MIT/Apache

2MB
9K SLoC

x86test定制测试运行器

x86test是一个定制测试运行器,允许您编写使用特权(x86)指令的单元测试。

它是这样实现的:为每个单元测试创建一个微小的虚拟机(使用kvm),该虚拟机反映了当前测试进程在客户机虚拟机中的地址空间。然后初始化虚拟机,并跳转到单元测试函数,现在在客户机环0中执行(在这里您可以使用所有您喜欢的指令)。最后,一旦测试返回(或恐慌),控制权从虚拟机返回到我们的测试运行器。

很酷?是的。

使用起来困难吗?不!它通过rust定制测试框架和过程宏与rust紧密集成。请看下面的示例。

它有效吗?它有一些限制(这是预期的,您正在运行裸机x86),所以不要期望有太多基础设施。对于panic和assert,您必须使用特殊版本,而且您不能使用任何进行系统调用的东西(如println!,但提供了一个自定义的sprintln!宏)。

示例

这特别有助于测试x86 crate。例如,假设我们有一个这样的函数

/// Read 16 bits from port
#[inline]
pub unsafe fn inw(port: u16) -> u16 {
    let ret: u16;
    asm!("inw %dx, %ax", in("dx") port, out("ax") ret, options(att_syntax));
    ret
}

inw的问题在于它需要在E/RFlags中的IO特权级别下运行,以避免引发异常(从而造成进程崩溃)。普通的Linux进程不会以这个特权级别运行,但是我们现在可以编写一个x86test

#[x86test(ioport(0x1, 0xfe))]
fn check_inw_port_read() {
    unsafe {
        kassert!(
            x86::io::inw(0x1) == 0xfe,
            "`inw` instruction didn't read the correct value"
        );
    }
}

这里发生了一些事情,值得解释

首先,我们不是使用 #[test],而是使用 #[x86test] 来告诉系统我们不希望使用常规单元测试。 x86test 支持一些参数(更多内容将在后面介绍),这里我们只是告诉测试运行器的“虚拟机管理程序”安装一个端口号为1的ioport,在读取时总是返回0xfe。接下来,是我们的函数声明——这里没有特别之处——然后是unsafe,因为 inw 是不安全的。最后,我们使用 kassert!,这是一个在虚拟机管理程序的guest ring 0中工作的自定义断言宏,来检查 inw 是否做了正确的事情。

你可以在 x86 测试 中找到更多示例测试。请注意,目前运行 x86test 仅适用于 Linux,并需要一些链接魔术。设置 RUSTFLAGS="-C relocation-model=dynamic-no-pic -C code-model=kernel" 应该可以。我预计将来不再需要自定义的 RUSTFLAGS

x86test 参考文档

目前 x86test 属性支持以下参数

  • ioport(port, val):读取到 port 将返回 val,对 port 的写入操作如果不是 val 将使测试失败。
  • ram(from, to):在地址范围 from -- to 中添加物理内存。
  • should_halt:告诉虚拟机管理程序测试将停止(注意:使用方法如 #[x86test(should_halt)])。
  • #[should_panic]:如果测试预期会崩溃,则可以添加。

代码组织

  • x86test_macro:包含 x86test 的过程宏实现。
  • x86test_types:包含 kassert、kpanic 和 X86TestFn 结构体的实现。
  • src:包含自定义测试运行器的实现。

更新

应按照以下顺序进行

  • 发布 x86test-types 的新版本
  • 发布 x86test-macro 的新版本(调整 x86test-types 的版本依赖关系)
  • 发布 x86test 的新版本(调整 x86test-types 和 x86test-macro 的版本依赖关系)
  • 使用 git tag x86test-0.0.x 标记

依赖项