112a9d9c8Sopenharmony_ci//! An application to run property tests for `bindgen` with _fuzzed_ C headers 212a9d9c8Sopenharmony_ci//! using `quickcheck` 312a9d9c8Sopenharmony_ci//! 412a9d9c8Sopenharmony_ci//! ## Usage 512a9d9c8Sopenharmony_ci//! 612a9d9c8Sopenharmony_ci//! Print help 712a9d9c8Sopenharmony_ci//! ```bash 812a9d9c8Sopenharmony_ci//! $ cargo run --bin=quickchecking -- -h 912a9d9c8Sopenharmony_ci//! ``` 1012a9d9c8Sopenharmony_ci//! 1112a9d9c8Sopenharmony_ci//! Run with default values 1212a9d9c8Sopenharmony_ci//! ```bash 1312a9d9c8Sopenharmony_ci//! $ cargo run --bin=quickchecking 1412a9d9c8Sopenharmony_ci//! ``` 1512a9d9c8Sopenharmony_ci//! 1612a9d9c8Sopenharmony_ci#![deny(missing_docs)] 1712a9d9c8Sopenharmony_ciextern crate clap; 1812a9d9c8Sopenharmony_ciextern crate quickchecking; 1912a9d9c8Sopenharmony_ci 2012a9d9c8Sopenharmony_ciuse clap::{App, Arg}; 2112a9d9c8Sopenharmony_ciuse std::path::Path; 2212a9d9c8Sopenharmony_ci 2312a9d9c8Sopenharmony_ci// Validate CLI argument input for generation range. 2412a9d9c8Sopenharmony_cifn validate_generate_range(v: String) -> Result<(), String> { 2512a9d9c8Sopenharmony_ci match v.parse::<usize>() { 2612a9d9c8Sopenharmony_ci Ok(_) => Ok(()), 2712a9d9c8Sopenharmony_ci Err(_) => Err(String::from( 2812a9d9c8Sopenharmony_ci "Generate range could not be converted to a usize.", 2912a9d9c8Sopenharmony_ci )), 3012a9d9c8Sopenharmony_ci } 3112a9d9c8Sopenharmony_ci} 3212a9d9c8Sopenharmony_ci 3312a9d9c8Sopenharmony_ci// Validate CLI argument input for tests count. 3412a9d9c8Sopenharmony_cifn validate_tests_count(v: String) -> Result<(), String> { 3512a9d9c8Sopenharmony_ci match v.parse::<usize>() { 3612a9d9c8Sopenharmony_ci Ok(_) => Ok(()), 3712a9d9c8Sopenharmony_ci Err(_) => Err(String::from( 3812a9d9c8Sopenharmony_ci "Tests count could not be converted to a usize.", 3912a9d9c8Sopenharmony_ci )), 4012a9d9c8Sopenharmony_ci } 4112a9d9c8Sopenharmony_ci} 4212a9d9c8Sopenharmony_ci 4312a9d9c8Sopenharmony_ci// Validate CLI argument input for fuzzed headers output path. 4412a9d9c8Sopenharmony_cifn validate_path(v: String) -> Result<(), String> { 4512a9d9c8Sopenharmony_ci match Path::new(&v).is_dir() { 4612a9d9c8Sopenharmony_ci true => Ok(()), 4712a9d9c8Sopenharmony_ci false => Err(String::from("Provided directory path does not exist.")), 4812a9d9c8Sopenharmony_ci } 4912a9d9c8Sopenharmony_ci} 5012a9d9c8Sopenharmony_ci 5112a9d9c8Sopenharmony_cifn main() { 5212a9d9c8Sopenharmony_ci let matches = App::new("quickchecking") 5312a9d9c8Sopenharmony_ci .version("0.2.0") 5412a9d9c8Sopenharmony_ci .about( 5512a9d9c8Sopenharmony_ci "Bindgen property tests with quickcheck. \ 5612a9d9c8Sopenharmony_ci Generate random valid C code and pass it to the \ 5712a9d9c8Sopenharmony_ci csmith/predicate.py script", 5812a9d9c8Sopenharmony_ci ) 5912a9d9c8Sopenharmony_ci .arg( 6012a9d9c8Sopenharmony_ci Arg::with_name("path") 6112a9d9c8Sopenharmony_ci .short("p") 6212a9d9c8Sopenharmony_ci .long("path") 6312a9d9c8Sopenharmony_ci .value_name("PATH") 6412a9d9c8Sopenharmony_ci .help( 6512a9d9c8Sopenharmony_ci "Optional. Preserve generated headers for inspection, \ 6612a9d9c8Sopenharmony_ci provide directory path for header output. [default: None] ", 6712a9d9c8Sopenharmony_ci ) 6812a9d9c8Sopenharmony_ci .takes_value(true) 6912a9d9c8Sopenharmony_ci .validator(validate_path), 7012a9d9c8Sopenharmony_ci ) 7112a9d9c8Sopenharmony_ci .arg( 7212a9d9c8Sopenharmony_ci Arg::with_name("range") 7312a9d9c8Sopenharmony_ci .short("r") 7412a9d9c8Sopenharmony_ci .long("range") 7512a9d9c8Sopenharmony_ci .value_name("RANGE") 7612a9d9c8Sopenharmony_ci .help( 7712a9d9c8Sopenharmony_ci "Sets the range quickcheck uses during generation. \ 7812a9d9c8Sopenharmony_ci Corresponds to things like arbitrary usize and \ 7912a9d9c8Sopenharmony_ci arbitrary vector length. This number doesn't have \ 8012a9d9c8Sopenharmony_ci to grow much for execution time to increase \ 8112a9d9c8Sopenharmony_ci significantly.", 8212a9d9c8Sopenharmony_ci ) 8312a9d9c8Sopenharmony_ci .takes_value(true) 8412a9d9c8Sopenharmony_ci .default_value("32") 8512a9d9c8Sopenharmony_ci .validator(validate_generate_range), 8612a9d9c8Sopenharmony_ci ) 8712a9d9c8Sopenharmony_ci .arg( 8812a9d9c8Sopenharmony_ci Arg::with_name("count") 8912a9d9c8Sopenharmony_ci .short("c") 9012a9d9c8Sopenharmony_ci .long("count") 9112a9d9c8Sopenharmony_ci .value_name("COUNT") 9212a9d9c8Sopenharmony_ci .help( 9312a9d9c8Sopenharmony_ci "Count / number of tests to run. Running a fuzzed \ 9412a9d9c8Sopenharmony_ci header through the predicate.py script can take a \ 9512a9d9c8Sopenharmony_ci long time, especially if the generation range is \ 9612a9d9c8Sopenharmony_ci large. Increase this number if you're willing to \ 9712a9d9c8Sopenharmony_ci wait a while.", 9812a9d9c8Sopenharmony_ci ) 9912a9d9c8Sopenharmony_ci .takes_value(true) 10012a9d9c8Sopenharmony_ci .default_value("2") 10112a9d9c8Sopenharmony_ci .validator(validate_tests_count), 10212a9d9c8Sopenharmony_ci ) 10312a9d9c8Sopenharmony_ci .get_matches(); 10412a9d9c8Sopenharmony_ci 10512a9d9c8Sopenharmony_ci let output_path: Option<&str> = matches.value_of("path"); 10612a9d9c8Sopenharmony_ci let generate_range: usize = 10712a9d9c8Sopenharmony_ci matches.value_of("range").unwrap().parse::<usize>().unwrap(); 10812a9d9c8Sopenharmony_ci let tests: usize = 10912a9d9c8Sopenharmony_ci matches.value_of("count").unwrap().parse::<usize>().unwrap(); 11012a9d9c8Sopenharmony_ci 11112a9d9c8Sopenharmony_ci quickchecking::test_bindgen(generate_range, tests, output_path) 11212a9d9c8Sopenharmony_ci} 113