tests: Start adding test for the command-line interface

This commit is contained in:
Vinícius Rodrigues Miguel 2021-03-19 12:40:49 -03:00
parent 39abfdffde
commit 65bc13e8fa
5 changed files with 113 additions and 118 deletions

View File

@ -1,13 +1,13 @@
use std::{convert::TryFrom, ffi::OsStr, path::PathBuf, vec::Vec};
use clap::{Arg};
use clap::{Arg, Values};
use colored::Colorize;
use crate::error;
use crate::extensions::CompressionExtension;
use crate::file::File;
#[derive(Debug)]
#[derive(PartialEq, Eq, Debug)]
pub enum CommandType {
Compression(
// Files to be compressed
@ -19,13 +19,13 @@ pub enum CommandType {
),
}
#[derive(Debug)]
#[derive(PartialEq, Eq, Debug)]
pub struct Command {
pub command_type: CommandType,
pub output: Option<File>,
}
pub fn get_matches() -> clap::ArgMatches<'static> {
pub fn clap_app<'a, 'b>() -> clap::App<'a, 'b> {
clap::App::new("ouch")
.version("0.1.0")
.about("ouch is a unified compression & decompression utility")
@ -53,7 +53,10 @@ pub fn get_matches() -> clap::ArgMatches<'static> {
.help("Output file (TODO description)")
.takes_value(true),
)
.get_matches()
}
pub fn get_matches() -> clap::ArgMatches<'static> {
clap_app().get_matches()
}
// holy spaghetti code
@ -62,24 +65,42 @@ impl TryFrom<clap::ArgMatches<'static>> for Command {
type Error = error::Error;
fn try_from(matches: clap::ArgMatches<'static>) -> error::OuchResult<Command> {
let process_decompressible_input = |input_files: Values| {
let input_files = input_files
.map(|filename| (filename, CompressionExtension::try_from(filename)));
for file in input_files.clone() {
if let (file, Err(_)) = file {
// eprintln!("{}: file '{}' is not decompressible.", "error".red(), file);
return Err(error::Error::InputsMustHaveBeenDecompressible(file.into()));
}
}
Ok(input_files
.map(|(filename, extension)|
(PathBuf::from(filename), extension.unwrap())
)
.collect::<Vec<_>>())
};
// Possibilities:
// * Case 1: output not supplied, therefore try to infer output by checking if all input files are decompressible
// * Case 2: output supplied
let output_was_supplied = matches.is_present("output");
let input_files = matches
.values_of("input")
.unwrap(); // Safe to unwrap since input is an obligatory argument
if output_was_supplied {
let output_file = matches
.value_of("output")
.unwrap(); // Safe unwrap since we've established that output was supplied
let input_files = matches
.values_of("input")
.unwrap(); // Safe to unwrap since input is an obligatory argument
// .map(PathBuf::from)
// .collect();
let output_file_extension = CompressionExtension::try_from(output_file);
let output_is_compressible = output_file_extension.is_ok();
if output_is_compressible {
@ -99,22 +120,8 @@ impl TryFrom<clap::ArgMatches<'static>> for Command {
}
else {
// Checking if input files are decompressible
let input_files = input_files
.map(|filename| (filename, CompressionExtension::try_from(filename)));
for file in input_files.clone() {
if let (file, Err(_)) = file {
// eprintln!("{}: file '{}' is not decompressible.", "error".red(), file);
return Err(error::Error::InputsMustHaveBeenDecompressible(file.into()));
}
}
let input_files =
input_files
.map(|(filename, extension)|
(PathBuf::from(filename), extension.unwrap())
)
.collect();
let input_files = process_decompressible_input(input_files)?;
println!("{}: attempting to decompress input files into {}", "info".yellow(), output_file);
return Ok(
@ -125,94 +132,17 @@ impl TryFrom<clap::ArgMatches<'static>> for Command {
);
}
} else {
// BIG TODO
Err(error::Error::MissingExtensionError("placeholder result".into()))
// else: output file not supplied
// Case 1: all input files are decompressible
// Case 2: error
let input_files = process_decompressible_input(input_files)?;
return Ok(
Command {
command_type: CommandType::Decompression(input_files),
output: None
}
);
}
}
}
// impl TryFrom<clap::ArgMatches<'static>> for ArgValues {
// type Error = error::OuchError;
// fn try_from(matches: clap::ArgMatches<'static>) -> error::OuchResult<ArgValues> {
// // Case 1: -o was set
// // Case 1.1: -o was set and has a (supported) compression file extension
// // |--> Compress all input files into the supplied output file (no extension checks on inputs)
// // Case 1.2: -o was set and is not a supported expression
// // Case 2: -o was not set
// // Case 2.1: -o was not set and all input files are (supported) compression file extensions
// // |--> Decompress input files into inferred filenames or directories
// // Case 2.2: -o was not set and not all input files are (supported) compression file extensions
// // |--> Issue an error
// let inputs = matches
// .values_of("input")
// .unwrap() // Safe to unwrap since this is a required argument
// .map(|input: &str| {
// (
// PathBuf::from(input),
// CompressionExtension::try_from(input).ok(),
// )
// });
// let output_was_supplied = matches.is_present("output");
// let inputs_are_compressed_files = inputs.clone().all(|(_, ext)| ext.is_some());
// match (output_was_supplied, inputs_are_compressed_files) {
// (true, true) => {
// // -o was set and inputs are all valid compressed files
// let output = matches.value_of("output").unwrap();
// let output = PathBuf::from(output);
// match CompressionExtension::try_from(&output) {
// Ok(ext) => {
// // If the output file is a valid compressed file, then we compress the input files into it
// Ok(Self {
// command_type: CommandType::Compress(
// inputs.map(|(path, _)| path).collect(),
// ),
// output: Some((output, ext)),
// })
// }
// Err(_) => {
// // If the output file is not a compressed file, then we decompress the input files into it
// Ok(Self {
// command_type: CommandType::Decompress(
// inputs.map(|(path, ext)| (path, ext.unwrap())).collect(),
// ),
// output: Some((output, CompressionExtension::NotCompressed)),
// })
// }
// }
// }
// (true, false) => {
// // -o was set and inputs are not (all) valid compressed files
// let output_str = matches.value_of("output").unwrap();
// let output = PathBuf::from(output_str);
// let output_ext = match CompressionExtension::try_from(&output) {
// Ok(ext) => ext,
// Err(_) => {
// return Err(error::OuchError::MissingExtensionError(output_str.into()));
// }
// };
// Ok(Self {
// command_type: CommandType::Compress(inputs.map(|(path, _)| path).collect()),
// output: Some((output, output_ext)),
// })
// }
// (false, true) => {
// // Case 2.1: -o was not set and all input files are (supported) compression file extensions
// Ok(Self {
// command_type: CommandType::Decompress(
// inputs.map(|(path, ext)| (path, ext.unwrap())).collect(),
// ),
// output: None,
// })
// }
// (false, false) => {
// // Case 2.2: -o was not set and not all input files are not (supported) compression file extensions
// Err(error::OuchError::InvalidInput)
// }
// }
// }
// }
}

View File

@ -4,7 +4,7 @@ use std::{
};
use crate::error;
#[derive(Debug)]
#[derive(PartialEq, Eq, Debug)]
/// Accepted extensions for input and output
pub enum CompressionExtension {
// .gz

View File

@ -12,7 +12,7 @@ use crate::extensions::CompressionExtension;
// pub filename: PathBuf,
// }
#[derive(Debug)]
#[derive(PartialEq, Eq, Debug)]
pub enum File {
WithExtension((PathBuf, CompressionExtension)),
WithoutExtension(PathBuf)

View File

@ -6,6 +6,7 @@ mod cli;
mod file;
mod extensions;
mod error;
mod test;
fn main() {

View File

@ -0,0 +1,64 @@
#[cfg(test)]
mod cli {
use std::{convert::TryFrom};
use crate::cli::clap_app;
use crate::cli::Command;
use crate::file::File;
use crate::cli::CommandType::*;
use crate::extensions::CompressionExtension::*;
use crate::error::OuchResult;
#[test]
fn decompress_files_into_folder() -> OuchResult<()> {
let matches = clap_app().
get_matches_from(
vec!["ouch", "-i", "file.zip", "-o", "folder/"]
);
let command_from_matches = Command::try_from(matches)?;
assert_eq!(
command_from_matches,
Command {
command_type: Decompression(
vec![
(
"file.zip".into(),
Zip,
),
],
),
output: Some(File::WithoutExtension("folder".into())),
}
);
Ok(())
}
#[test]
fn decompress_files() -> OuchResult<()> {
let matches = clap_app().
get_matches_from(
vec!["ouch", "-i", "file.zip"]
);
let command_from_matches = Command::try_from(matches)?;
assert_eq!(
command_from_matches,
Command {
command_type: Decompression(
vec![
(
"file.zip".into(),
Zip,
),
],
),
output: None,
}
);
Ok(())
}
}