Skip to content

Commit

Permalink
implements #277
Browse files Browse the repository at this point in the history
- adds -f flag for leo test command, now you choose files to run
- adds tests for leo test
- improves output of test command
  • Loading branch information
damirka committed Feb 8, 2021
1 parent cb245f0 commit 56ec74d
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 47 deletions.
6 changes: 3 additions & 3 deletions leo/commands/new.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<bool>,
is_lib: bool,
}

impl New {
pub fn new(name: String, is_lib: Option<bool>) -> New {
pub fn new(name: String, is_lib: bool) -> New {
New { name, is_lib }
}
}
Expand Down Expand Up @@ -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(())
}
Expand Down
102 changes: 59 additions & 43 deletions leo/commands/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -58,25 +58,46 @@ impl Command for Test {
}

fn apply(self, ctx: Context, _: Self::Input) -> Result<Self::Output> {
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<PathBuf> = Vec::new();

// if -f flag was used, then we'll test only this files
if self.files.is_empty() {
let files: Vec<PathBuf> = 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 {}",
Expand All @@ -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::<Fq, EdwardsGroupType>::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::<Fq, EdwardsGroupType>::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(())
}
Expand Down
9 changes: 8 additions & 1 deletion leo/tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.

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},
};
Expand Down Expand Up @@ -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]
Expand Down

0 comments on commit 56ec74d

Please sign in to comment.