Compare commits

..

5 Commits

Author SHA1 Message Date
Ayrton Chilibeck 8d4b5b3f1c
Initial implementation of the Validate function
ci/woodpecker/push/workflow Pipeline failed Details
Added stubs and general flow, some rust stuff to figure out
2024-01-12 23:58:58 -07:00
Ayrton Chilibeck eaca213f26
Pub-ed the Config fields 2024-01-12 23:09:55 -07:00
Ayrton Chilibeck 3693ff1668
Fixed README to include threading 2024-01-12 23:01:28 -07:00
Ayrton Chilibeck 4561caa6cf
Implemented the get_dir_files function 2024-01-12 22:57:11 -07:00
Ayrton Chilibeck d4a6c1132d
Added Stubs 2024-01-12 22:56:38 -07:00
4 changed files with 115 additions and 21 deletions

View File

@ -3,7 +3,7 @@
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:
``` rust
```
Usage: tester [OPTIONS] --config-file <CONFIG> <COMMAND>
Commands:
@ -14,11 +14,11 @@ Commands:
Options:
-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
-g, --grading-conf <GRADING_CONFIG> Set the grading config file
-h, --help Print help
-V, --version Print version
```
the verbosity defines the level of logging, you can play around with it (specify `-v[v]+` for more verbose logging).

View File

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

View File

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

View File

@ -1,9 +1,104 @@
use std::{path::PathBuf, fs};
use crate::util;
pub fn validate(verbosity: u8, config: util::config::Config) {
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)]
mod tests {