1//! An application to run property tests for `bindgen` with _fuzzed_ C headers 2//! using `quickcheck` 3//! 4//! ## Usage 5//! 6//! Print help 7//! ```bash 8//! $ cargo run --bin=quickchecking -- -h 9//! ``` 10//! 11//! Run with default values 12//! ```bash 13//! $ cargo run --bin=quickchecking 14//! ``` 15//! 16#![deny(missing_docs)] 17extern crate clap; 18extern crate quickchecking; 19 20use clap::{App, Arg}; 21use std::path::Path; 22 23// Validate CLI argument input for generation range. 24fn validate_generate_range(v: String) -> Result<(), String> { 25 match v.parse::<usize>() { 26 Ok(_) => Ok(()), 27 Err(_) => Err(String::from( 28 "Generate range could not be converted to a usize.", 29 )), 30 } 31} 32 33// Validate CLI argument input for tests count. 34fn validate_tests_count(v: String) -> Result<(), String> { 35 match v.parse::<usize>() { 36 Ok(_) => Ok(()), 37 Err(_) => Err(String::from( 38 "Tests count could not be converted to a usize.", 39 )), 40 } 41} 42 43// Validate CLI argument input for fuzzed headers output path. 44fn validate_path(v: String) -> Result<(), String> { 45 match Path::new(&v).is_dir() { 46 true => Ok(()), 47 false => Err(String::from("Provided directory path does not exist.")), 48 } 49} 50 51fn main() { 52 let matches = App::new("quickchecking") 53 .version("0.2.0") 54 .about( 55 "Bindgen property tests with quickcheck. \ 56 Generate random valid C code and pass it to the \ 57 csmith/predicate.py script", 58 ) 59 .arg( 60 Arg::with_name("path") 61 .short("p") 62 .long("path") 63 .value_name("PATH") 64 .help( 65 "Optional. Preserve generated headers for inspection, \ 66 provide directory path for header output. [default: None] ", 67 ) 68 .takes_value(true) 69 .validator(validate_path), 70 ) 71 .arg( 72 Arg::with_name("range") 73 .short("r") 74 .long("range") 75 .value_name("RANGE") 76 .help( 77 "Sets the range quickcheck uses during generation. \ 78 Corresponds to things like arbitrary usize and \ 79 arbitrary vector length. This number doesn't have \ 80 to grow much for execution time to increase \ 81 significantly.", 82 ) 83 .takes_value(true) 84 .default_value("32") 85 .validator(validate_generate_range), 86 ) 87 .arg( 88 Arg::with_name("count") 89 .short("c") 90 .long("count") 91 .value_name("COUNT") 92 .help( 93 "Count / number of tests to run. Running a fuzzed \ 94 header through the predicate.py script can take a \ 95 long time, especially if the generation range is \ 96 large. Increase this number if you're willing to \ 97 wait a while.", 98 ) 99 .takes_value(true) 100 .default_value("2") 101 .validator(validate_tests_count), 102 ) 103 .get_matches(); 104 105 let output_path: Option<&str> = matches.value_of("path"); 106 let generate_range: usize = 107 matches.value_of("range").unwrap().parse::<usize>().unwrap(); 108 let tests: usize = 109 matches.value_of("count").unwrap().parse::<usize>().unwrap(); 110 111 quickchecking::test_bindgen(generate_range, tests, output_path) 112} 113