#属性测试 #模糊测试 #属性 #目标 #过程宏 #快速检查 #proptest

derive_fuzztest

一个Rust过程宏,用于启用模糊测试和属性测试使用相同的实现

5个版本

0.1.4 2024年7月29日
0.1.3 2024年6月27日
0.1.2 2024年6月24日
0.1.1 2024年5月29日
0.1.0 2024年5月29日

#259 in 测试

Download history 175/week @ 2024-05-27 57/week @ 2024-06-03 49/week @ 2024-06-10 81/week @ 2024-06-17 441/week @ 2024-06-24 53/week @ 2024-07-01 157/week @ 2024-07-08 139/week @ 2024-07-15 74/week @ 2024-07-22 271/week @ 2024-07-29 148/week @ 2024-08-05

637 每月下载量

Apache-2.0

18KB
110

derive_fuzztest

这不是一个官方支持的Google产品。

Crates.io Docs

描述

生成用于与cargo fuzz一起使用的模糊目标的过程宏,以及用于与cargo test一起使用的属性测试(通过quickcheckproptest)。

两者都有的原因是因为属性测试允许快速迭代以确保测试工作正常,并可以在预提交CI中检查,而模糊测试可以更彻底地测试输入空间并持续运行。

示例

#![cfg_attr(fuzzing, no_main)]

#[derive_fuzztest::fuzztest]
fn transitive_ord(a: u32, b: u32, c: u32) {
    if a >= b && b >= c {
        assert!(a >= c);
    }
    if a <= b && b <= c {
        assert!(a <= c);
    }
}

#[test]
fn additional_test_here() {
    /* ... */
}

结果报告

测试函数通过panic报告测试失败,类似于你编写常规#[test]的方式。如果标记的测试函数在没有panic的情况下完成,则认为测试已通过。

在某些情况下,你可能想要丢弃一些输入,既不将其视为通过也不视为失败,只是继续测试另一个生成的输入。这可以通过从标记的函数中返回一个TestResult来实现。属性测试框架将尝试生成更多测试用例来替换丢弃的一个,最多达到一定限制。对于模糊测试,丢弃的测试结果将不会添加到语料库中。

use derive_fuzztest::TestResult;

#[derive_fuzztest::fuzztest]
fn increment(a: u8) -> TestResult {
    if a < u8::MAX {
        assert_eq!(a + 1 - 1, a);
        TestResult::Passed
    } else {
        TestResult::Discard
    }
}

用法

运行生成的属性测试

cargo test

运行持续模糊测试

cargo install cargo-fuzz
cargo +nightly fuzz run <binary name>

包结构

如果你使用#[fuzz]#[fuzztest],模糊目标强制以下要求

  • 目标必须位于一个单独的 [[bin]] 目标中,该目标只包含一个模糊测试目标。
  • 包含 bin 目标的包中,[package.metadata] cargo-fuzz = true
  • bin 目标使用 #![cfg_attr(fuzzing, no_main)] 进行了标注

对于您的 foo 包,建议的结构是将测试放在 foo/fuzz/src/bin

foo
├── fuzz
│   ├── src
│   │   └── bin
│   │       └── fuzz_target_1.rs
│   └── Cargo.toml
├── src
│   └── [project source]
└── Cargo.toml

这与 cargo fuzz initcargo fuzz add 生成的默认结构不同,这样我们可以利用 目标自动发现。如果您愿意,也可以使用 cargo fuzz 生成的默认结构,但请确保从 Cargo.toml 中的生成目标中删除 test = false

您还需要声明对 libfuzzer-sys 包的依赖,但仅当需要模糊测试时

[target.'cfg(fuzzing)'.dependencies]
libfuzzer-sys = "*"

(这种条件依赖的原因是 libfuzzer-sys 会将一个主函数注入到生成的二进制文件中,如果没有定义相应的 fuzz_target,则会出现链接失败。)

功能

  • quickcheck(默认)— 启用生成 quickcheck 属性测试。
  • proptest— 启用生成 proptest 属性测试。

相关阅读

依赖项

~0.7–2MB
~40K SLoC