Compare commits
5 Commits
47d7d81f60
...
8d4b5b3f1c
Author | SHA1 | Date |
---|---|---|
Ayrton Chilibeck | 8d4b5b3f1c | |
Ayrton Chilibeck | eaca213f26 | |
Ayrton Chilibeck | 3693ff1668 | |
Ayrton Chilibeck | 4561caa6cf | |
Ayrton Chilibeck | d4a6c1132d |
|
@ -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).
|
||||||
|
|
|
@ -16,8 +16,7 @@ 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);
|
||||||
|
|
||||||
//parse the config file
|
assert!(threads > 0);
|
||||||
// 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),
|
||||||
|
|
|
@ -5,39 +5,39 @@ use serde_yaml::{self};
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
tested_executables: Vec<Team>,
|
pub tested_executables: Vec<Team>,
|
||||||
|
|
||||||
input_path: PathBuf,
|
pub input_path: PathBuf,
|
||||||
output_path: PathBuf,
|
pub output_path: PathBuf,
|
||||||
in_stream_path: PathBuf,
|
pub in_stream_path: PathBuf,
|
||||||
|
|
||||||
runtimes: Option<Vec<Team>>,
|
pub runtimes: Option<Vec<Team>>,
|
||||||
|
|
||||||
toolchains: Vec<Toolchain>,
|
pub toolchains: Vec<Toolchain>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
pub struct Team {
|
pub struct Team {
|
||||||
name: String,
|
pub name: String,
|
||||||
executable: PathBuf,
|
pub executable: PathBuf,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
pub struct Toolchain {
|
pub struct Toolchain {
|
||||||
name: String,
|
pub name: String,
|
||||||
steps: Vec<Step>,}
|
pub steps: Vec<Step>,}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
pub struct Step {
|
pub struct Step {
|
||||||
name: String,
|
pub name: String,
|
||||||
|
|
||||||
executable_path: Option<PathBuf>, // if None then we use the current executable path
|
pub executable_path: Option<PathBuf>, // if None then we use the current executable path
|
||||||
arguments: Vec<String>, // special string $INPUT corresponds to previous step output
|
pub arguments: Vec<String>, // special string $INPUT corresponds to previous step output
|
||||||
output: String, // the output file name
|
pub output: String, // the output file name
|
||||||
|
|
||||||
uses_runtime: Option<bool>,
|
pub uses_runtime: Option<bool>,
|
||||||
uses_in_stream: Option<bool>,
|
pub uses_in_stream: Option<bool>,
|
||||||
allow_error: Option<bool>
|
pub allow_error: Option<bool>
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_config(path: PathBuf) -> Config {
|
pub fn parse_config(path: PathBuf) -> Config {
|
||||||
|
|
|
@ -1,9 +1,104 @@
|
||||||
|
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 {
|
||||||
|
|
Loading…
Reference in New Issue