1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
#![warn( missing_docs, trivial_casts, trivial_numeric_casts, unused_import_braces, unused_qualifications )] #![deny(clippy::all, clippy::pedantic)] #![allow(clippy::module_name_repetitions)] //! This library contains all necessary tools to run a PISA benchmark //! on a collection of a significant size. extern crate downcast_rs; extern crate failure; extern crate strum; use downcast_rs::impl_downcast; use error::Error; use std::fmt; use std::fs::create_dir_all; use std::path::Path; use strum_macros::{Display, EnumIter, EnumString}; pub mod build; pub mod command; pub mod config; pub mod error; pub mod executor; pub mod run; pub mod source; /// Available stages of the experiment. /// # Examples /// /// All names are lowercase: /// /// ``` /// # extern crate stdbench; /// # use::stdbench::*; /// assert_eq!("compile".parse(), Ok(Stage::Compile)); /// assert_eq!("build".parse(), Ok(Stage::BuildIndex)); /// assert_eq!("parse".parse(), Ok(Stage::ParseCollection)); /// assert_eq!("invert".parse(), Ok(Stage::Invert)); /// assert!("?".parse::<Stage>().is_err()); /// assert_eq!("compile", format!("{}", Stage::Compile)); /// assert_eq!("build", format!("{}", Stage::BuildIndex)); /// assert_eq!("parse", format!("{}", Stage::ParseCollection)); /// assert_eq!("invert", format!("{}", Stage::Invert)); /// ``` #[cfg_attr(tarpaulin, skip)] #[derive(Debug, PartialEq, Eq, Hash, Copy, Clone, EnumString, Display, EnumIter)] pub enum Stage { /// Compilation stage; includes things such as: fetching code, configuring, /// and actual compilation of the source code. The exact meaning depends on /// the type of the source being processed. #[strum(serialize = "compile")] Compile, /// Includes building forward/inverted index and index compressing. #[strum(serialize = "build")] BuildIndex, /// A subset of `BuildIndex`; means: build an inverted index but assume the /// forward index has been already built (e.g., in a previous run). #[strum(serialize = "parse")] ParseCollection, /// A subset of `ParseCollection`; means: use `parse_collection` with /// `merge` subcommand to only merge previously produced batch files. #[strum(serialize = "parse-batches")] ParseBatches, /// Inverting stage; mean: compress an inverted index but do not invert forward /// index, assuming it has been done already. #[strum(serialize = "invert")] Invert, } /// If the parent directory of `path` does not exist, create it. /// /// # Examples /// /// ``` /// # extern crate stdbench; /// # extern crate tempdir; /// # use stdbench::*; /// # use stdbench::error::*; /// # use std::path::Path; /// # use tempdir::TempDir; /// assert_eq!( /// ensure_parent_exists(Path::new("/")), /// Err(Error::from("cannot access parent of path: /")) /// ); /// /// let tmp = TempDir::new("parent_exists").unwrap(); /// let parent = tmp.path().join("parent"); /// let child = parent.join("child"); /// assert!(ensure_parent_exists(child.as_path()).is_ok()); /// assert!(parent.exists()); /// ``` pub fn ensure_parent_exists(path: &Path) -> Result<(), Error> { let parent = path .parent() .ok_or_else(|| format!("cannot access parent of path: {}", path.display()))?; create_dir_all(parent)?; Ok(()) } /// Executes a `$cmd`, checks for results, and returns an error with `$errmsg` message. /// It is designed to be similar to `?` operator, removing bulky boilerplate from /// functions that execute many consecutive commands. /// /// This macro will return error in one of the two cases: /// - command execution failed, /// - command returned an exit status equivalent to an error. /// /// This macro is intended to be used in simple cases when we do not want to capture /// the output or learn more about exit status, since the only feedback we get /// is the error message passed at the call site. /// /// # Example /// /// ``` /// # #[macro_use] /// # extern crate stdbench; /// extern crate boolinator; /// # use stdbench::error::Error; /// # use std::process::Command; /// use boolinator::Boolinator; /// # fn main() { /// fn f() -> Result<(), Error> { /// execute!(Command::new("ls"); "couldn't ls"); /// execute!(Command::new("cat").args(&["some_file"]); "couldn't cat"); /// Ok(()) /// } /// /// match f() { /// Ok(()) => println!(), /// Err(err) => println!("Here's what went wrong"), /// } /// # } /// ``` #[macro_export] macro_rules! execute { ($cmd:expr; $errmsg:expr) => {{ $cmd.status()?.success().ok_or(Error::from($errmsg))?; }}; } #[cfg(test)] mod tests;