diff --git a/leo/commands/new.rs b/leo/commands/new.rs index f8fc9b6aa0..264c534d8b 100644 --- a/leo/commands/new.rs +++ b/leo/commands/new.rs @@ -30,11 +30,11 @@ pub struct New { name: String, #[structopt(help = "Init as a library (containing lib.leo)", long = "lib", short = "l")] - is_lib: Option, + is_lib: bool, } impl New { - pub fn new(name: String, is_lib: Option) -> New { + pub fn new(name: String, is_lib: bool) -> New { New { name, is_lib } } } @@ -66,7 +66,7 @@ impl Command for New { // Create the package directory fs::create_dir_all(&path).map_err(|err| anyhow!("Could not create directory {}", err))?; - LeoPackage::initialize(&package_name, self.is_lib.unwrap_or(false), &path)?; + LeoPackage::initialize(&package_name, self.is_lib, &path)?; Ok(()) } diff --git a/leo/commands/test.rs b/leo/commands/test.rs index 07637e8bf6..4c1e1e7a81 100644 --- a/leo/commands/test.rs +++ b/leo/commands/test.rs @@ -28,7 +28,7 @@ use leo_package::{ use snarkvm_curves::edwards_bls12::Fq; -use std::{convert::TryFrom, time::Instant}; +use std::{convert::TryFrom, path::PathBuf, time::Instant}; use tracing::span::Span; /// Build program and run tests command @@ -58,25 +58,46 @@ impl Command for Test { } fn apply(self, ctx: Context, _: Self::Input) -> Result { - let path = ctx.dir()?; - // Get the package name let package_name = ctx.manifest()?.get_package_name(); // Sanitize the package path to the root directory - let mut package_path = path; + let mut package_path = ctx.dir()?; if package_path.is_file() { package_path.pop(); } - let mut file_path = package_path.clone(); - file_path.push(SOURCE_DIRECTORY_NAME); - - // Verify a main or library file exists - if MainFile::exists_at(&package_path) { + let mut to_test: Vec = Vec::new(); + + // if -f flag was used, then we'll test only this files + if self.files.is_empty() { + let files: Vec = self + .files + .into_iter() + .map(|file| { + let mut file_path = package_path.clone(); + file_path.push(file); + file_path + }) + .collect(); + + to_test.extend(files); + + // if args were not passed - try main file + } else if MainFile::exists_at(&package_path) { + let mut file_path = package_path.clone(); + file_path.push(SOURCE_DIRECTORY_NAME); file_path.push(MAIN_FILENAME); + to_test.push(file_path); + + // if main file is not present and no arguments - try library } else if LibraryFile::exists_at(&package_path) { + let mut file_path = package_path.clone(); + file_path.push(SOURCE_DIRECTORY_NAME); file_path.push(LIBRARY_FILENAME); + to_test.push(file_path); + + // nothing found - skip } else { return Err(anyhow!( "Program file does not exist {}", @@ -91,50 +112,45 @@ impl Command for Test { // Create the output directory OutputsDirectory::create(&package_path)?; - // Start the timer - let start = Instant::now(); - - // Parse the current main program file - let program = - Compiler::::parse_program_without_input(package_name, file_path, output_directory)?; - - // Parse all inputs as input pairs - let pairs = match InputPairs::try_from(package_path.as_path()) { - Ok(pairs) => pairs, - Err(_) => { - // tracing::warn!("Could not find inputs, if it is intentional - ignore \ - // or use -i or --inputs option to specify inputs directory"); - tracing::warn!("Unable to find inputs, ignore this message or put them into /inputs folder"); - InputPairs::new() - } - }; - - // Run tests - let temporary_program = program; - let (passed, failed) = temporary_program.compile_test_constraints(pairs)?; - - // Set the result of the test command to passed if no tests failed. - if failed == 0 { - // Begin "Done" context for console logging - tracing::span!(tracing::Level::INFO, "Done").in_scope(|| { + // Finally test every passed file + for file_path in to_test { + tracing::info!("Running tests in file {:?}", file_path); + + let input_pairs = match InputPairs::try_from(package_path.as_path()) { + Ok(pairs) => pairs, + Err(_) => { + tracing::warn!("Unable to find inputs, ignore this message or put them into /inputs folder"); + InputPairs::new() + } + }; + + let timer = Instant::now(); + let program = Compiler::::parse_program_without_input( + package_name.clone(), + file_path, + output_directory.clone(), + )?; + + let temporary_program = program; + let (passed, failed) = temporary_program.compile_test_constraints(input_pairs)?; + let time_taken = timer.elapsed().as_millis(); + + if failed == 0 { tracing::info!( "Tests passed in {} milliseconds. {} passed; {} failed;\n", - start.elapsed().as_millis(), + time_taken, passed, failed ); - }); - } else { - // Begin "Done" context for console logging - tracing::span!(tracing::Level::ERROR, "Done").in_scope(|| { + } else { tracing::error!( "Tests failed in {} milliseconds. {} passed; {} failed;\n", - start.elapsed().as_millis(), + time_taken, passed, failed ); - }); - }; + } + } Ok(()) } diff --git a/leo/tests/mod.rs b/leo/tests/mod.rs index 6697908a88..436061a04f 100644 --- a/leo/tests/mod.rs +++ b/leo/tests/mod.rs @@ -15,7 +15,7 @@ // along with the Leo library. If not, see . use crate::{ - commands::{package::Login, Build, Command, Prove, Run, Setup, Update, UpdateAutomatic}, + commands::{package::Login, Build, Command, Prove, Run, Setup, Test, Update, UpdateAutomatic}, config, context::{create_context, Context}, }; @@ -57,6 +57,13 @@ pub fn run_pedersen_hash() -> Result<()> { Ok(()) } +#[test] +pub fn test_pedersen_hash() -> Result<()> { + Test::new(Vec::new()).apply(ctx()?, ())?; + Test::new(vec![String::from("src/main.leo")]).apply(ctx()?, ())?; + Ok(()) +} + // Decided to not go all-in on error messages since they might change in the future // So this test only tells that error cases are errors #[test]