Compare commits

..

No commits in common. "8d4b5b3f1ce4076283e237130807985424a8ccf9" and "47d7d81f60b107e7b7e2a60c3fab4a90cf702c6b" have entirely different histories.

4 changed files with 21 additions and 115 deletions

View File

@ -3,7 +3,7 @@
This is a (mostly) drop-in replacement for the previous tester written for CMPUT 415. This is a (mostly) drop-in replacement for the previous tester written for CMPUT 415.
Most of the options are specified in the [config file](#configuration-file), so the cli is minimal. We do specify some options: Most of the options are specified in the [config file](#configuration-file), so the cli is minimal. We do specify some options:
``` ``` rust
Usage: tester [OPTIONS] --config-file <CONFIG> <COMMAND> Usage: tester [OPTIONS] --config-file <CONFIG> <COMMAND>
Commands: Commands:
@ -14,11 +14,11 @@ Commands:
Options: Options:
-v, --verbosity... Sets the verbosity of the tester -v, --verbosity... Sets the verbosity of the tester
-t, --threads <THREADS> Set the number of threads (only valid in run and grade mode)
-c, --config-file <CONFIG> Set the config file -c, --config-file <CONFIG> Set the config file
-g, --grading-conf <GRADING_CONFIG> Set the grading config file -g, --grading-conf <GRADING_CONFIG> Set the grading config file
-h, --help Print help -h, --help Print help
-V, --version Print version -V, --version Print version
``` ```
the verbosity defines the level of logging, you can play around with it (specify `-v[v]+` for more verbose logging). the verbosity defines the level of logging, you can play around with it (specify `-v[v]+` for more verbose logging).

View File

@ -16,7 +16,8 @@ fn main() {
let threads = get_threads(cli.threads); let threads = get_threads(cli.threads);
let config = util::config::parse_config(cli.config_file); let config = util::config::parse_config(cli.config_file);
assert!(threads > 0); //parse the config file
// let config = parse_config(cli.config_file);
match &cli.command { match &cli.command {
Command::Validate => validate::validate(verbosity, config), Command::Validate => validate::validate(verbosity, config),

View File

@ -5,39 +5,39 @@ use serde_yaml::{self};
#[derive(Debug, Deserialize)] #[derive(Debug, Deserialize)]
pub struct Config { pub struct Config {
pub tested_executables: Vec<Team>, tested_executables: Vec<Team>,
pub input_path: PathBuf, input_path: PathBuf,
pub output_path: PathBuf, output_path: PathBuf,
pub in_stream_path: PathBuf, in_stream_path: PathBuf,
pub runtimes: Option<Vec<Team>>, runtimes: Option<Vec<Team>>,
pub toolchains: Vec<Toolchain>, toolchains: Vec<Toolchain>,
} }
#[derive(Debug, Deserialize)] #[derive(Debug, Deserialize)]
pub struct Team { pub struct Team {
pub name: String, name: String,
pub executable: PathBuf, executable: PathBuf,
} }
#[derive(Debug, Deserialize)] #[derive(Debug, Deserialize)]
pub struct Toolchain { pub struct Toolchain {
pub name: String, name: String,
pub steps: Vec<Step>,} steps: Vec<Step>,}
#[derive(Debug, Deserialize)] #[derive(Debug, Deserialize)]
pub struct Step { pub struct Step {
pub name: String, name: String,
pub executable_path: Option<PathBuf>, // if None then we use the current executable path executable_path: Option<PathBuf>, // if None then we use the current executable path
pub arguments: Vec<String>, // special string $INPUT corresponds to previous step output arguments: Vec<String>, // special string $INPUT corresponds to previous step output
pub output: String, // the output file name output: String, // the output file name
pub uses_runtime: Option<bool>, uses_runtime: Option<bool>,
pub uses_in_stream: Option<bool>, uses_in_stream: Option<bool>,
pub allow_error: Option<bool> allow_error: Option<bool>
} }
pub fn parse_config(path: PathBuf) -> Config { pub fn parse_config(path: PathBuf) -> Config {

View File

@ -1,104 +1,9 @@
use std::{path::PathBuf, fs};
use crate::util; use crate::util;
pub fn validate(verbosity: u8, config: util::config::Config) { pub fn validate(verbosity: u8, config: util::config::Config) {
println!("Validating"); println!("Validating");
let in_suffix = "in"; //TODO make this configurable?
let out_suffix = "out";
// get list of all file names in input/output
let in_files: Vec<PathBuf> = get_dir_files(config.input_path).expect("Failed to read the input directory contents");
let out_files: Vec<PathBuf> = get_dir_files(config.output_path).expect("Failed to read the output directory contents");
let mismatch: Vec<(PathBuf, PathBuf)>;
let mut invalid_suffix_in: Vec<PathBuf> = vec![];
let mut invalid_suffix_out: Vec<PathBuf> = vec![];
// check if they end in .in or .out respectively
for file in in_files {
if !file.ends_with(in_suffix) {
invalid_suffix_in.push(file);
}
}
for file in out_files {
if !file.ends_with(out_suffix) {
invalid_suffix_out.push(file);
}
}
// print the delinquints
if invalid_suffix_in.len() > 0 {
print_invalid_suffixes(invalid_suffix_in, String::from(in_suffix));
}
if invalid_suffix_out.len() > 0 {
print_invalid_suffixes(invalid_suffix_out, String::from(out_suffix));
}
// make sure each has a match
} }
fn get_dir_files(path: PathBuf) -> Result<Vec<PathBuf>, &'static str> {
let mut res: Vec<PathBuf> = vec![];
// get the readout of the path for error handling
let entries = match fs::read_dir(path) {
Ok(x) => x,
Err(..) => return Err("Failed to read from the given directory"),
};
for entry in entries {
let p = entry.expect("Bad element: validate::get_dir_files(..)");
if p.path().is_dir() {
();
} else {
res.push(p.path());
}
}
return Ok(res);
}
fn compare_files(in_files: Vec<PathBuf>, out_files: Vec<PathBuf>) -> Vec<PathBuf> {
let mut res: Vec<PathBuf> = vec![];
res.append(&mut compare_list(in_files, out_files));
res.append(&mut compare_list(out_files, in_files));
return res;
}
fn compare_list(from: Vec<PathBuf>, against: Vec<PathBuf>) -> Vec<PathBuf> {
let res: Vec<PathBuf> = vec![];
// Compare each input file to each output file
for file in from {
let beg = file.file_stem().unwrap(); // ignore suffix
for out in against {
if beg == out.file_stem().unwrap() {
break;
}
}
res.push(file); // if the file does not have a counterpart, then push to the lost files
}
return res;
}
fn print_invalid_suffixes(files: Vec<PathBuf>, exp: String) {
println!("Invalid suffixes detected 😱:" );
println!("Current => Suggested");
for mut file in files {
let initial = match file.to_str() {
Some(x) => x,
_ => panic!("Failed to load the file"),
};
println!("{} => {}", initial, file.set_extension(exp).to_string());
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {