summaryrefslogtreecommitdiff
path: root/src/exercise.rs
diff options
context:
space:
mode:
authorAbdou Seck <djily02016@gmail.com>2020-06-04 10:31:17 -0400
committerAbdou Seck <djily02016@gmail.com>2020-06-04 11:18:26 -0400
commit8ad5f9bf531a4848b1104b7b389a20171624c82f (patch)
tree331c5d3725140b07d836ed8be6df30c8ddfd63fb /src/exercise.rs
parent02a2fe48714a4546b28d38fb611e6bfce9f43cf6 (diff)
feat: Add a --nocapture option to display test harnesses' outputs
This new feature can be accessed by invoking rustlings with --nocapture. Both unit and integration tests added. closes #262 BREAKING CHANGES: The following function take a new boolean argument: * `run` * `verify` * `test` * `compile_and_test`
Diffstat (limited to 'src/exercise.rs')
-rw-r--r--src/exercise.rs44
1 files changed, 43 insertions, 1 deletions
diff --git a/src/exercise.rs b/src/exercise.rs
index d1eaa1a..177b7f3 100644
--- a/src/exercise.rs
+++ b/src/exercise.rs
@@ -11,15 +11,21 @@ const I_AM_DONE_REGEX: &str = r"(?m)^\s*///?\s*I\s+AM\s+NOT\s+DONE";
const CONTEXT: usize = 2;
const CLIPPY_CARGO_TOML_PATH: &str = "./exercises/clippy/Cargo.toml";
+// Get a temporary file name that is hopefully unique to this process
+#[inline]
fn temp_file() -> String {
format!("./temp_{}", process::id())
}
+// The mode of the exercise.
#[derive(Deserialize, Copy, Clone)]
#[serde(rename_all = "lowercase")]
pub enum Mode {
+ // Indicates that the exercise should be compiled as a binary
Compile,
+ // Indicates that the exercise should be compiled as a test harness
Test,
+ // Indicates that the exercise should be linted with clippy
Clippy,
}
@@ -28,41 +34,60 @@ pub struct ExerciseList {
pub exercises: Vec<Exercise>,
}
+// A representation of a rustlings exercise.
+// This is deserialized from the accompanying info.toml file
#[derive(Deserialize)]
pub struct Exercise {
+ // Name of the exercise
pub name: String,
+ // The path to the file containing the exercise's source code
pub path: PathBuf,
+ // The mode of the exercise (Test, Compile, or Clippy)
pub mode: Mode,
+ // The hint text associated with the exercise
pub hint: String,
}
+// An enum to track of the state of an Exercise.
+// An Exercise can be either Done or Pending
#[derive(PartialEq, Debug)]
pub enum State {
+ // The state of the exercise once it's been completed
Done,
+ // The state of the exercise while it's not completed yet
Pending(Vec<ContextLine>),
}
+// The context information of a pending exercise
#[derive(PartialEq, Debug)]
pub struct ContextLine {
+ // The source code that is still pending completion
pub line: String,
+ // The line number of the source code still pending completion
pub number: usize,
+ // Whether or not this is important
pub important: bool,
}
+// The result of compiling an exercise
pub struct CompiledExercise<'a> {
exercise: &'a Exercise,
_handle: FileHandle,
}
impl<'a> CompiledExercise<'a> {
+ // Run the compiled exercise
pub fn run(&self) -> Result<ExerciseOutput, ExerciseOutput> {
self.exercise.run()
}
}
+// A representation of an already executed binary
#[derive(Debug)]
pub struct ExerciseOutput {
+ // The textual contents of the standard output of the binary
pub stdout: String,
+ // The textual contents of the standard error of the binary
pub stderr: String,
}
@@ -140,7 +165,11 @@ path = "{}.rs""#,
}
fn run(&self) -> Result<ExerciseOutput, ExerciseOutput> {
- let cmd = Command::new(&temp_file())
+ let arg = match self.mode {
+ Mode::Test => "--show-output",
+ _ => ""
+ };
+ let cmd = Command::new(&temp_file()).arg(arg)
.output()
.expect("Failed to run 'run' command");
@@ -205,6 +234,7 @@ impl Display for Exercise {
}
}
+#[inline]
fn clean() {
let _ignored = remove_file(&temp_file());
}
@@ -280,4 +310,16 @@ mod test {
assert_eq!(exercise.state(), State::Done);
}
+
+ #[test]
+ fn test_exercise_with_output() {
+ let exercise = Exercise {
+ name: "finished_exercise".into(),
+ path: PathBuf::from("tests/fixture/success/testSuccess.rs"),
+ mode: Mode::Test,
+ hint: String::new(),
+ };
+ let out = exercise.compile().unwrap().run().unwrap();
+ assert!(out.stdout.contains("THIS TEST TOO SHALL PASS"));
+ }
}