diff --git a/Cargo.lock b/Cargo.lock index 19572d56..5ee2b6a3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -168,6 +168,14 @@ dependencies = [ "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "float-cmp" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "fsevent" version = "0.4.0" @@ -351,6 +359,11 @@ dependencies = [ "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "normalize-line-endings" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "notify" version = "4.0.12" @@ -369,6 +382,14 @@ dependencies = [ "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "num-traits" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "numtoa" version = "0.1.0" @@ -405,7 +426,10 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "float-cmp 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "normalize-line-endings 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "predicates-core 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -613,6 +637,7 @@ dependencies = [ "glob 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "indicatif 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "notify 4.0.12 (registry+https://github.com/rust-lang/crates.io-index)", + "predicates 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", @@ -850,6 +875,7 @@ dependencies = [ "checksum encode_unicode 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "90b2c9496c001e8cb61827acdefad780795c42264c137744cae6f7d9e3450abd" "checksum escargot 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ceb9adbf9874d5d028b5e4c5739d22b71988252b25c9c98fe7cf9738bee84597" "checksum filetime 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "2f8c63033fcba1f51ef744505b3cad42510432b904c062afa67ad7ece008429d" +"checksum float-cmp 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "134a8fa843d80a51a5b77d36d42bc2def9edcb0262c914861d08129fd1926600" "checksum fsevent 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5ab7d1bd1bd33cc98b0889831b72da23c0aa4df9cec7e0702f46ecea04b35db6" "checksum fsevent-sys 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f41b048a94555da0f42f1d632e2e19510084fb8e303b0daa2816e733fb3644a0" "checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" @@ -873,7 +899,9 @@ dependencies = [ "checksum mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "46e73a04c2fa6250b8d802134d56d554a9ec2922bf977777c805ea5def61ce40" "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" "checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" +"checksum normalize-line-endings 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2e0a1a39eab95caf4f5556da9289b9e68f0aafac901b2ce80daaf020d3b733a8" "checksum notify 4.0.12 (registry+https://github.com/rust-lang/crates.io-index)" = "3572d71f13ea8ed41867accd971fd564aa75934cf7a1fae03ddb8c74a8a49943" +"checksum num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "6ba9a427cfca2be13aa6f6403b0b7e7368fe982bfa16fccc450ce74c46cd9b32" "checksum numtoa 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b8f8bdf33df195859076e54ab11ee78a1b208382d3a26ec40d142ffc1ecc49ef" "checksum parking_lot 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fa7767817701cce701d5585b9c4db3cdd02086398322c1d7e8bf5094a96a2ce7" "checksum parking_lot_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cb88cb1cb3790baa6776844f968fea3be44956cf184fa1be5a03341f5491278c" diff --git a/Cargo.toml b/Cargo.toml index 7cbe2a25..45485ce1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,4 +19,5 @@ path = "src/main.rs" [dev-dependencies] assert_cmd = "0.11.0" +predicates = "1.0.1" glob = "0.3.0" diff --git a/src/run.rs b/src/run.rs index 1f777ece..1484351a 100644 --- a/src/run.rs +++ b/src/run.rs @@ -5,9 +5,7 @@ use indicatif::ProgressBar; pub fn run(exercise: &Exercise) -> Result<(), ()> { match exercise.mode { - Mode::Test => { - test(exercise)?; - } + Mode::Test => test(exercise)?, Mode::Compile => compile_and_run(exercise)?, } Ok(()) diff --git a/src/verify.rs b/src/verify.rs index 020102e5..c499c4ad 100644 --- a/src/verify.rs +++ b/src/verify.rs @@ -1,11 +1,11 @@ -use crate::exercise::{ContextLine, Exercise, Mode, State}; +use crate::exercise::{Exercise, Mode, State}; use console::{style, Emoji}; use indicatif::ProgressBar; pub fn verify<'a>(start_at: impl IntoIterator) -> Result<(), ()> { for exercise in start_at { let is_done = match exercise.mode { - Mode::Test => test(&exercise)?, + Mode::Test => compile_and_test_interactively(&exercise)?, Mode::Compile => compile_only(&exercise)?, }; if !is_done { @@ -15,6 +15,11 @@ pub fn verify<'a>(start_at: impl IntoIterator) -> Result<() Ok(()) } +pub fn test(exercise: &Exercise) -> Result<(), ()> { + compile_and_test(exercise, true)?; + Ok(()) +} + fn compile_only(exercise: &Exercise) -> Result { let progress_bar = ProgressBar::new_spinner(); progress_bar.set_message(format!("Compiling {}...", exercise).as_str()); @@ -25,12 +30,7 @@ fn compile_only(exercise: &Exercise) -> Result { let formatstr = format!("{} Successfully compiled {}!", Emoji("✅", "✓"), exercise); println!("{}", style(formatstr).green()); exercise.clean(); - if let State::Pending(context) = exercise.state() { - print_everything_looks_good(exercise.mode, context); - Ok(false) - } else { - Ok(true) - } + Ok(prompt_for_completion(&exercise)) } else { let formatstr = format!( "{} Compilation of {} failed! Compiler error message:\n", @@ -44,7 +44,11 @@ fn compile_only(exercise: &Exercise) -> Result { } } -pub fn test(exercise: &Exercise) -> Result { +fn compile_and_test_interactively(exercise: &Exercise) -> Result { + compile_and_test(exercise, false) +} + +fn compile_and_test(exercise: &Exercise, skip_prompt: bool) -> Result { let progress_bar = ProgressBar::new_spinner(); progress_bar.set_message(format!("Testing {}...", exercise).as_str()); progress_bar.enable_steady_tick(100); @@ -60,12 +64,7 @@ pub fn test(exercise: &Exercise) -> Result { let formatstr = format!("{} Successfully tested {}!", Emoji("✅", "✓"), exercise); println!("{}", style(formatstr).green()); exercise.clean(); - if let State::Pending(context) = exercise.state() { - print_everything_looks_good(exercise.mode, context); - Ok(false) - } else { - Ok(true) - } + Ok(skip_prompt || prompt_for_completion(exercise)) } else { let formatstr = format!( "{} Testing of {} failed! Please try again. Here's the output:", @@ -91,8 +90,13 @@ pub fn test(exercise: &Exercise) -> Result { } } -fn print_everything_looks_good(mode: Mode, context: Vec) { - let success_msg = match mode { +fn prompt_for_completion(exercise: &Exercise) -> bool { + let context = match exercise.state() { + State::Done => return true, + State::Pending(context) => context, + }; + + let success_msg = match exercise.mode { Mode::Compile => "The code is compiling!", Mode::Test => "The code is compiling, and the tests pass!", }; @@ -120,4 +124,6 @@ fn print_everything_looks_good(mode: Mode, context: Vec) { formatted_line ); } + + false } diff --git a/tests/fixture/state/finished_exercise.rs b/tests/fixture/state/finished_exercise.rs index e69de29b..016b827c 100644 --- a/tests/fixture/state/finished_exercise.rs +++ b/tests/fixture/state/finished_exercise.rs @@ -0,0 +1,5 @@ +// fake_exercise + +fn main() { + +} diff --git a/tests/fixture/state/info.toml b/tests/fixture/state/info.toml new file mode 100644 index 00000000..7bfc697e --- /dev/null +++ b/tests/fixture/state/info.toml @@ -0,0 +1,11 @@ +[[exercises]] +name = "pending_exercise" +path = "pending_exercise.rs" +mode = "compile" +hint = """""" + +[[exercises]] +name = "pending_test_exercise" +path = "pending_test_exercise.rs" +mode = "test" +hint = """""" diff --git a/tests/fixture/state/pending_test_exercise.rs b/tests/fixture/state/pending_test_exercise.rs new file mode 100644 index 00000000..8756f02d --- /dev/null +++ b/tests/fixture/state/pending_test_exercise.rs @@ -0,0 +1,4 @@ +// I AM NOT DONE + +#[test] +fn it_works() {} diff --git a/tests/integration_tests.rs b/tests/integration_tests.rs index 754aa635..71317005 100644 --- a/tests/integration_tests.rs +++ b/tests/integration_tests.rs @@ -1,5 +1,6 @@ use assert_cmd::prelude::*; use glob::glob; +use predicates::boolean::PredicateBooleanExt; use std::fs::File; use std::io::Read; use std::process::Command; @@ -136,3 +137,25 @@ fn all_exercises_require_confirmation() { )); } } + +#[test] +fn run_compile_exercise_does_not_prompt() { + Command::cargo_bin("rustlings") + .unwrap() + .args(&["r", "pending_exercise"]) + .current_dir("tests/fixture/state") + .assert() + .code(0) + .stdout(predicates::str::contains("I AM NOT DONE").not()); +} + +#[test] +fn run_test_exercise_does_not_prompt() { + Command::cargo_bin("rustlings") + .unwrap() + .args(&["r", "pending_test_exercise"]) + .current_dir("tests/fixture/state") + .assert() + .code(0) + .stdout(predicates::str::contains("I AM NOT DONE").not()); +}