mirror of
https://github.com/mimblewimble/grin.git
synced 2025-01-20 19:11:08 +03:00
Introduce fuzz tests for core (#844)
This PR introduces fuzz tests and address #592
This commit is contained in:
parent
4b639cae5c
commit
eb226beea8
7 changed files with 184 additions and 0 deletions
4
core/fuzz/.gitignore
vendored
Normal file
4
core/fuzz/.gitignore
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
|
||||
target
|
||||
corpus
|
||||
artifacts
|
34
core/fuzz/Cargo.toml
Normal file
34
core/fuzz/Cargo.toml
Normal file
|
@ -0,0 +1,34 @@
|
|||
|
||||
[package]
|
||||
name = "grin_core-fuzz"
|
||||
version = "0.0.1"
|
||||
authors = ["Automatically generated"]
|
||||
publish = false
|
||||
|
||||
[package.metadata]
|
||||
cargo-fuzz = true
|
||||
|
||||
[dependencies]
|
||||
grin_core = { path = ".."}
|
||||
grin_keychain = { path = "../../keychain"}
|
||||
libfuzzer-sys = { git = "https://github.com/rust-fuzz/libfuzzer-sys.git" }
|
||||
|
||||
# Prevent this from interfering with workspaces
|
||||
[workspace]
|
||||
members = ["."]
|
||||
|
||||
[[bin]]
|
||||
name = "transaction_read"
|
||||
path = "fuzz_targets/transaction_read.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "gen-corpus"
|
||||
path = "src/main.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "block_read"
|
||||
path = "fuzz_targets/block_read.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "compact_block_read"
|
||||
path = "fuzz_targets/compact_block_read.rs"
|
35
core/fuzz/README.md
Normal file
35
core/fuzz/README.md
Normal file
|
@ -0,0 +1,35 @@
|
|||
# Fuzz testing
|
||||
|
||||
## Installation
|
||||
Cargo-fuzz (https://github.com/rust-fuzz/cargo-fuzz) has been used.
|
||||
To install it:
|
||||
|
||||
```
|
||||
cargo install cargo-fuzz
|
||||
```
|
||||
|
||||
## Pattern generation for corpus
|
||||
This step is optional, libFuzz will generate random patterns to populate
|
||||
corpus (in folder `corpus`). However we can genearete more meaningful pattern
|
||||
e.g. use serialized form of a real block or transaction. To generate them:
|
||||
|
||||
```
|
||||
cd fuzz
|
||||
|
||||
cargo run --bin gen-corpus
|
||||
```
|
||||
|
||||
## Run tests
|
||||
Fuzz test is basically infinite test, run it for some period of time then
|
||||
stop if no failures are found.
|
||||
To run the tests make sure youre in folder `core` otherwise you may get
|
||||
some misleading errors, then run one of the following tests:
|
||||
```
|
||||
cargo fuzz run tx_read
|
||||
|
||||
cargo fuzz run block_read
|
||||
|
||||
cargo fuzz run compact_block_read
|
||||
|
||||
```
|
||||
Check `fuzz/Cargo.toml` for the full list of targets.
|
12
core/fuzz/fuzz_targets/block_read.rs
Normal file
12
core/fuzz/fuzz_targets/block_read.rs
Normal file
|
@ -0,0 +1,12 @@
|
|||
#![no_main]
|
||||
extern crate grin_core;
|
||||
#[macro_use]
|
||||
extern crate libfuzzer_sys;
|
||||
|
||||
use grin_core::ser;
|
||||
use grin_core::core::block;
|
||||
|
||||
fuzz_target!(|data: &[u8]| {
|
||||
let mut d = data.clone();
|
||||
let _t: Result<block::Block, ser::Error> = ser::deserialize(&mut d);
|
||||
});
|
12
core/fuzz/fuzz_targets/compact_block_read.rs
Normal file
12
core/fuzz/fuzz_targets/compact_block_read.rs
Normal file
|
@ -0,0 +1,12 @@
|
|||
#![no_main]
|
||||
extern crate grin_core;
|
||||
#[macro_use]
|
||||
extern crate libfuzzer_sys;
|
||||
|
||||
use grin_core::ser;
|
||||
use grin_core::core::block;
|
||||
|
||||
fuzz_target!(|data: &[u8]| {
|
||||
let mut d = data.clone();
|
||||
let _t: Result<block::CompactBlock, ser::Error> = ser::deserialize(&mut d);
|
||||
});
|
12
core/fuzz/fuzz_targets/transaction_read.rs
Normal file
12
core/fuzz/fuzz_targets/transaction_read.rs
Normal file
|
@ -0,0 +1,12 @@
|
|||
#![no_main]
|
||||
extern crate grin_core;
|
||||
#[macro_use]
|
||||
extern crate libfuzzer_sys;
|
||||
|
||||
use grin_core::ser;
|
||||
use grin_core::core::transaction;
|
||||
|
||||
fuzz_target!(|data: &[u8]| {
|
||||
let mut d = data.clone();
|
||||
let _t: Result<transaction::Transaction, ser::Error> = ser::deserialize(&mut d);
|
||||
});
|
75
core/fuzz/src/main.rs
Normal file
75
core/fuzz/src/main.rs
Normal file
|
@ -0,0 +1,75 @@
|
|||
extern crate grin_core;
|
||||
extern crate grin_keychain;
|
||||
|
||||
use std::path::Path;
|
||||
use std::fs::{self, File};
|
||||
use grin_core::ser;
|
||||
use grin_core::core::{Block, BlockHeader, CompactBlock, Transaction};
|
||||
use grin_core::core::target::Difficulty;
|
||||
|
||||
use grin_core::core::build::{input, output, transaction_with_offset, with_fee};
|
||||
use grin_keychain::keychain::Keychain;
|
||||
|
||||
fn main() {
|
||||
generate("transaction_read", &tx()).unwrap();
|
||||
generate("block_read", &block()).unwrap();
|
||||
generate("compact_block_read", &compact_block()).unwrap();
|
||||
}
|
||||
|
||||
fn generate<W: ser::Writeable>(target: &str, obj: W) -> Result<(), ser::Error> {
|
||||
let dir_path = Path::new("corpus").join(target);
|
||||
if !dir_path.is_dir() {
|
||||
fs::create_dir(&dir_path).map_err(|e| ser::Error::IOErr(e))?;
|
||||
}
|
||||
|
||||
let pattern_path = dir_path.join("pattern");
|
||||
if !pattern_path.exists() {
|
||||
let mut file = File::create(&pattern_path).map_err(|e| ser::Error::IOErr(e))?;
|
||||
ser::serialize(&mut file, &obj)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn block() -> Block {
|
||||
let keychain = Keychain::from_random_seed().unwrap();
|
||||
let key_id = keychain.derive_key_id(1).unwrap();
|
||||
|
||||
let mut tx1 = tx();
|
||||
let mut tx2 = tx();
|
||||
|
||||
Block::new(
|
||||
&BlockHeader::default(),
|
||||
vec![&mut tx1, &mut tx2],
|
||||
&keychain,
|
||||
&key_id,
|
||||
Difficulty::one(),
|
||||
).unwrap()
|
||||
}
|
||||
|
||||
fn compact_block() -> CompactBlock {
|
||||
CompactBlock {
|
||||
header: BlockHeader::default(),
|
||||
nonce: 1,
|
||||
out_full: vec![],
|
||||
kern_full: vec![],
|
||||
kern_ids: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
fn tx() -> Transaction {
|
||||
let keychain = Keychain::from_random_seed().unwrap();
|
||||
let key_id1 = keychain.derive_key_id(1).unwrap();
|
||||
let key_id2 = keychain.derive_key_id(2).unwrap();
|
||||
let key_id3 = keychain.derive_key_id(3).unwrap();
|
||||
|
||||
transaction_with_offset(
|
||||
vec![
|
||||
input(10, key_id1),
|
||||
input(11, key_id2),
|
||||
output(19, key_id3),
|
||||
with_fee(2),
|
||||
],
|
||||
&keychain,
|
||||
).unwrap()
|
||||
}
|
Loading…
Reference in a new issue