blob: d2774eb0d9c242d605571ff28a0ddba9fa23f4f6 [file] [log] [blame]
//! An application to run property tests for `bindgen` with _fuzzed_ C headers
//! using `quickcheck`
//!
//! ## Usage
//!
//! Print help
//! ```bash
//! $ cargo run --bin=quickchecking -- -h
//! ```
//!
//! Run with default values
//! ```bash
//! $ cargo run --bin=quickchecking
//! ```
//!
#![deny(missing_docs)]
extern crate clap;
extern crate quickchecking;
use clap::{App, Arg};
use std::path::Path;
// Validate CLI argument input for generation range.
fn validate_generate_range(v: String) -> Result<(), String> {
match v.parse::<usize>() {
Ok(_) => Ok(()),
Err(_) => Err(String::from(
"Generate range could not be converted to a usize.",
)),
}
}
// Validate CLI argument input for tests count.
fn validate_tests_count(v: String) -> Result<(), String> {
match v.parse::<usize>() {
Ok(_) => Ok(()),
Err(_) => Err(String::from(
"Tests count could not be converted to a usize.",
)),
}
}
// Validate CLI argument input for fuzzed headers output path.
fn validate_path(v: String) -> Result<(), String> {
match Path::new(&v).is_dir() {
true => Ok(()),
false => Err(String::from("Provided directory path does not exist.")),
}
}
fn main() {
let matches = App::new("quickchecking")
.version("0.2.0")
.about(
"Bindgen property tests with quickcheck. \
Generate random valid C code and pass it to the \
csmith/predicate.py script",
)
.arg(
Arg::with_name("path")
.short("p")
.long("path")
.value_name("PATH")
.help(
"Optional. Preserve generated headers for inspection, \
provide directory path for header output. [default: None] ",
)
.takes_value(true)
.validator(validate_path),
)
.arg(
Arg::with_name("range")
.short("r")
.long("range")
.value_name("RANGE")
.help(
"Sets the range quickcheck uses during generation. \
Corresponds to things like arbitrary usize and \
arbitrary vector length. This number doesn't have \
to grow much for execution time to increase \
significantly.",
)
.takes_value(true)
.default_value("32")
.validator(validate_generate_range),
)
.arg(
Arg::with_name("count")
.short("c")
.long("count")
.value_name("COUNT")
.help(
"Count / number of tests to run. Running a fuzzed \
header through the predicate.py script can take a \
long time, especially if the generation range is \
large. Increase this number if you're willing to \
wait a while.",
)
.takes_value(true)
.default_value("2")
.validator(validate_tests_count),
)
.get_matches();
let output_path: Option<&str> = matches.value_of("path");
let generate_range: usize = matches.value_of("range").unwrap().parse::<usize>().unwrap();
let tests: usize = matches.value_of("count").unwrap().parse::<usize>().unwrap();
quickchecking::test_bindgen(generate_range, tests, output_path)
}