-
Notifications
You must be signed in to change notification settings - Fork 3
/
tarpaulin-report-rustlings.json
1 lines (1 loc) Β· 78.2 KB
/
tarpaulin-report-rustlings.json
1
{"files":[{"path":["/","usr","src","rustlings","exercises","conversions","from_into.rs"],"content":"// The From trait is used for value-to-value conversions.\n// If From is implemented correctly for a type, the Into trait should work conversely.\n// You can read more about it at https://doc.rust-lang.org/std/convert/trait.From.html\n#[derive(Debug)]\nstruct Person {\n name: String,\n age: usize,\n}\n\n// We implement the Default trait to use it as a fallback\n// when the provided string is not convertible into a Person object\nimpl Default for Person {\n fn default() -> Person {\n Person {\n name: String::from(\"John\"),\n age: 30,\n }\n }\n}\n\n// I AM NOT DONE\n// Your task is to complete this implementation\n// in order for the line `let p = Person::from(\"Mark,20\")` to compile\n// Please note that you'll need to parse the age component into a `usize`\n// with something like `\"4\".parse::<usize>()`. The outcome of this needs to\n// be handled appropriately.\n//\n// Steps:\n// 1. If the length of the provided string is 0, then return the default of Person\n// 2. Split the given string on the commas present in it\n// 3. Extract the first element from the split operation and use it as the name\n// 4. If the name is empty, then return the default of Person\n// 5. Extract the other element from the split operation and parse it into a `usize` as the age\n// If while parsing the age, something goes wrong, then return the default of Person\n// Otherwise, then return an instantiated Person object with the results\nimpl From<&str> for Person {\n fn from(s: &str) -> Person {\n }\n}\n\nfn main() {\n // Use the `from` function\n let p1 = Person::from(\"Mark,20\");\n // Since From is implemented for Person, we should be able to use Into\n let p2: Person = \"Gerald,70\".into();\n println!(\"{:?}\", p1);\n println!(\"{:?}\", p2);\n}\n\n#[cfg(test)]\nmod tests {\n use super::*;\n #[test]\n fn test_default() {\n // Test that the default person is 30 year old John\n let dp = Person::default();\n assert_eq!(dp.name, \"John\");\n assert_eq!(dp.age, 30);\n }\n #[test]\n fn test_bad_convert() {\n // Test that John is returned when bad string is provided\n let p = Person::from(\"\");\n assert_eq!(p.name, \"John\");\n assert_eq!(p.age, 30);\n }\n #[test]\n fn test_good_convert() {\n // Test that \"Mark,20\" works\n let p = Person::from(\"Mark,20\");\n assert_eq!(p.name, \"Mark\");\n assert_eq!(p.age, 20);\n }\n #[test]\n fn test_bad_age() {\n // Test that \"Mark.twenty\" will return the default person due to an error in parsing age\n let p = Person::from(\"Mark,twenty\");\n assert_eq!(p.name, \"John\");\n assert_eq!(p.age, 30);\n }\n\n #[test]\n fn test_missing_comma_and_age() {\n let p: Person = Person::from(\"Mark\");\n assert_eq!(p.name, \"John\");\n assert_eq!(p.age, 30);\n }\n\n #[test]\n fn test_missing_age() {\n let p: Person = Person::from(\"Mark,\");\n assert_eq!(p.name, \"John\");\n assert_eq!(p.age, 30);\n }\n\n #[test]\n fn test_missing_name() {\n let p: Person = Person::from(\",1\");\n assert_eq!(p.name, \"John\");\n assert_eq!(p.age, 30);\n }\n\n #[test]\n fn test_missing_name_and_age() {\n let p: Person = Person::from(\",\");\n assert_eq!(p.name, \"John\");\n assert_eq!(p.age, 30);\n }\n\n #[test]\n fn test_missing_name_and_invalid_age() {\n let p: Person = Person::from(\",one\");\n assert_eq!(p.name, \"John\");\n assert_eq!(p.age, 30);\n }\n}\n","traces":[{"line":13,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":15,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":37,"address":[],"length":0,"stats":{"Line":0},"fn_name":null}],"covered":0,"coverable":3},{"path":["/","usr","src","rustlings","exercises","conversions","from_str.rs"],"content":"// This does practically the same thing that TryFrom<&str> does.\n// Additionally, upon implementing FromStr, you can use the `parse` method\n// on strings to generate an object of the implementor type.\n// You can read more about it at https://doc.rust-lang.org/std/str/trait.FromStr.html\nuse std::str::FromStr;\n\n#[derive(Debug)]\nstruct Person {\n name: String,\n age: usize,\n}\n\n// I AM NOT DONE\n// Steps:\n// 1. If the length of the provided string is 0, then return an error\n// 2. Split the given string on the commas present in it\n// 3. Extract the first element from the split operation and use it as the name\n// 4. If the name is empty, then return an error\n// 5. Extract the other element from the split operation and parse it into a `usize` as the age\n// with something like `\"4\".parse::<usize>()`.\n// If while parsing the age, something goes wrong, then return an error\n// Otherwise, then return a Result of a Person object\nimpl FromStr for Person {\n type Err = String;\n fn from_str(s: &str) -> Result<Person, Self::Err> {\n }\n}\n\nfn main() {\n let p = \"Mark,20\".parse::<Person>().unwrap();\n println!(\"{:?}\", p);\n}\n\n#[cfg(test)]\nmod tests {\n use super::*;\n\n #[test]\n fn empty_input() {\n assert!(\"\".parse::<Person>().is_err());\n }\n #[test]\n fn good_input() {\n let p = \"John,32\".parse::<Person>();\n assert!(p.is_ok());\n let p = p.unwrap();\n assert_eq!(p.name, \"John\");\n assert_eq!(p.age, 32);\n }\n #[test]\n #[should_panic]\n fn missing_age() {\n \"John,\".parse::<Person>().unwrap();\n }\n\n #[test]\n #[should_panic]\n fn invalid_age() {\n \"John,twenty\".parse::<Person>().unwrap();\n }\n\n #[test]\n #[should_panic]\n fn missing_comma_and_age() {\n \"John\".parse::<Person>().unwrap();\n }\n\n #[test]\n #[should_panic]\n fn missing_name() {\n \",1\".parse::<Person>().unwrap();\n }\n\n #[test]\n #[should_panic]\n fn missing_name_and_age() {\n \",\".parse::<Person>().unwrap();\n }\n\n #[test]\n #[should_panic]\n fn missing_name_and_invalid_age() {\n \",one\".parse::<Person>().unwrap();\n }\n\n}\n","traces":[{"line":25,"address":[],"length":0,"stats":{"Line":0},"fn_name":null}],"covered":0,"coverable":1},{"path":["/","usr","src","rustlings","exercises","conversions","try_from_into.rs"],"content":"// TryFrom is a simple and safe type conversion that may fail in a controlled way under some circumstances.\n// Basically, this is the same as From. The main difference is that this should return a Result type\n// instead of the target type itself.\n// You can read more about it at https://doc.rust-lang.org/std/convert/trait.TryFrom.html\nuse std::convert::{TryInto, TryFrom};\n\n#[derive(Debug)]\nstruct Color {\n red: u8,\n green: u8,\n blue: u8,\n}\n\n// I AM NOT DONE\n\n// Your task is to complete this implementation\n// and return an Ok result of inner type Color.\n// You need create implementation for a tuple of three integer,\n// an array of three integer and slice of integer.\n//\n// Note, that implementation for tuple and array will be checked at compile-time,\n// but slice implementation need check slice length!\n// Also note, that chunk of correct rgb color must be integer in range 0..=255.\n\n// Tuple implementation\nimpl TryFrom<(i16, i16, i16)> for Color {\n type Error = String;\n fn try_from(tuple: (i16, i16, i16)) -> Result<Self, Self::Error> {\n }\n}\n\n// Array implementation\nimpl TryFrom<[i16; 3]> for Color {\n type Error = String;\n fn try_from(arr: [i16; 3]) -> Result<Self, Self::Error> {\n }\n}\n\n// Slice implementation\nimpl TryFrom<&[i16]> for Color {\n type Error = String;\n fn try_from(slice: &[i16]) -> Result<Self, Self::Error> {\n }\n}\n\nfn main() {\n // Use the `from` function\n let c1 = Color::try_from((183, 65, 14));\n println!(\"{:?}\", c1);\n\n // Since From is implemented for Color, we should be able to use Into\n let c2: Result<Color, _> = [183, 65, 14].try_into();\n println!(\"{:?}\", c2);\n\n let v = vec![183, 65, 14];\n // With slice we should use `from` function\n let c3 = Color::try_from(&v[..]);\n println!(\"{:?}\", c3);\n // or take slice within round brackets and use Into\n let c4: Result<Color, _> = (&v[..]).try_into();\n println!(\"{:?}\", c4);\n}\n\n#[cfg(test)]\nmod tests {\n use super::*;\n\n #[test]\n #[should_panic]\n fn test_tuple_out_of_range_positive() {\n let _ = Color::try_from((256, 1000, 10000)).unwrap();\n }\n #[test]\n #[should_panic]\n fn test_tuple_out_of_range_negative() {\n let _ = Color::try_from((-1, -10, -256)).unwrap();\n }\n #[test]\n fn test_tuple_correct() {\n let c: Color = (183, 65, 14).try_into().unwrap();\n assert_eq!(c.red, 183);\n assert_eq!(c.green, 65);\n assert_eq!(c.blue, 14);\n }\n\n #[test]\n #[should_panic]\n fn test_array_out_of_range_positive() {\n let _: Color = [1000, 10000, 256].try_into().unwrap();\n }\n #[test]\n #[should_panic]\n fn test_array_out_of_range_negative() {\n let _: Color = [-10, -256, -1].try_into().unwrap();\n }\n #[test]\n fn test_array_correct() {\n let c: Color = [183, 65, 14].try_into().unwrap();\n assert_eq!(c.red, 183);\n assert_eq!(c.green, 65);\n assert_eq!(c.blue, 14);\n }\n\n #[test]\n #[should_panic]\n fn test_slice_out_of_range_positive() {\n let arr = [10000, 256, 1000];\n let _ = Color::try_from(&arr[..]).unwrap();\n }\n #[test]\n #[should_panic]\n fn test_slice_out_of_range_negative() {\n let arr = [-256, -1, -10];\n let _ = Color::try_from(&arr[..]).unwrap();\n }\n #[test]\n fn test_slice_correct() {\n let v = vec![183, 65, 14];\n let c = Color::try_from(&v[..]).unwrap();\n assert_eq!(c.red, 183);\n assert_eq!(c.green, 65);\n assert_eq!(c.blue, 14);\n }\n #[test]\n #[should_panic]\n fn test_slice_excess_length() {\n let v = vec![0, 0, 0, 0];\n let _ = Color::try_from(&v[..]).unwrap();\n }\n}\n","traces":[{"line":28,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":35,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":42,"address":[],"length":0,"stats":{"Line":0},"fn_name":null}],"covered":0,"coverable":3},{"path":["/","usr","src","rustlings","exercises","enums","enums2.rs"],"content":"// enums2.rs\n// Make me compile! Execute `rustlings hint enums2` for hints!\n\n// I AM NOT DONE\n\n#[derive(Debug)]\nenum Message {\n // TODO: define the different variants used below\n}\n\nimpl Message {\n fn call(&self) {\n println!(\"{:?}\", &self);\n }\n}\n\nfn main() {\n let messages = [\n Message::Move{ x: 10, y: 30 },\n Message::Echo(String::from(\"hello world\")),\n Message::ChangeColor(200, 255, 255),\n Message::Quit\n ];\n\n for message in &messages {\n message.call();\n }\n}\n","traces":[{"line":12,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":13,"address":[],"length":0,"stats":{"Line":0},"fn_name":null}],"covered":0,"coverable":2},{"path":["/","usr","src","rustlings","exercises","enums","enums3.rs"],"content":"// enums3.rs\n// Address all the TODOs to make the tests pass!\n\n// I AM NOT DONE\n\nenum Message {\n // TODO: implement the message variant types based on their usage below\n}\n\nstruct Point {\n x: u8,\n y: u8\n}\n\nstruct State {\n color: (u8, u8, u8),\n position: Point,\n quit: bool\n}\n\nimpl State {\n fn change_color(&mut self, color: (u8, u8, u8)) {\n self.color = color;\n }\n\n fn quit(&mut self) {\n self.quit = true;\n }\n\n fn echo(&self, s: String) {\n println!(\"{}\", s);\n }\n\n fn move_position(&mut self, p: Point) {\n self.position = p;\n }\n\n fn process(&mut self, message: Message) {\n // TODO: create a match expression to process the different message variants\n }\n}\n\n#[cfg(test)]\nmod tests {\n use super::*;\n\n #[test]\n fn test_match_message_call() {\n let mut state = State{\n quit: false,\n position: Point{ x: 0, y: 0 },\n color: (0, 0, 0)\n };\n state.process(Message::ChangeColor(255, 0, 255));\n state.process(Message::Echo(String::from(\"hello world\")));\n state.process(Message::Move(Point{ x: 10, y: 15 }));\n state.process(Message::Quit);\n\n assert_eq!(state.color, (255, 0, 255));\n assert_eq!(state.position.x, 10);\n assert_eq!(state.position.y, 15);\n assert_eq!(state.quit, true);\n }\n\n}\n","traces":[{"line":22,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":23,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":26,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":27,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":30,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":31,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":34,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":35,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":38,"address":[],"length":0,"stats":{"Line":0},"fn_name":null}],"covered":0,"coverable":9},{"path":["/","usr","src","rustlings","exercises","error_handling","result1.rs"],"content":"// result1.rs\n// Make this test pass! Execute `rustlings hint result1` for hints :)\n\n// I AM NOT DONE\n\n#[derive(PartialEq, Debug)]\nstruct PositiveNonzeroInteger(u64);\n\n#[derive(PartialEq, Debug)]\nenum CreationError {\n Negative,\n Zero,\n}\n\nimpl PositiveNonzeroInteger {\n fn new(value: i64) -> Result<PositiveNonzeroInteger, CreationError> {\n Ok(PositiveNonzeroInteger(value as u64))\n }\n}\n\n#[test]\nfn test_creation() {\n assert!(PositiveNonzeroInteger::new(10).is_ok());\n assert_eq!(\n Err(CreationError::Negative),\n PositiveNonzeroInteger::new(-10)\n );\n assert_eq!(Err(CreationError::Zero), PositiveNonzeroInteger::new(0));\n}\n","traces":[{"line":16,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":17,"address":[],"length":0,"stats":{"Line":0},"fn_name":null}],"covered":0,"coverable":2},{"path":["/","usr","src","rustlings","exercises","generics","generics2.rs"],"content":"// This powerful wrapper provides the ability to store a positive integer value.\n// Rewrite it using generics so that it supports wrapping ANY type.\n\n// I AM NOT DONE\nstruct Wrapper {\n value: u32\n}\n\nimpl Wrapper {\n pub fn new(value: u32) -> Self {\n Wrapper { value }\n }\n}\n\n#[cfg(test)]\nmod tests {\n use super::*;\n\n #[test]\n fn store_u32_in_wrapper() {\n assert_eq!(Wrapper::new(42).value, 42);\n }\n\n #[test]\n fn store_str_in_wrapper() {\n assert_eq!(Wrapper::new(\"Foo\").value, \"Foo\");\n }\n}","traces":[{"line":10,"address":[],"length":0,"stats":{"Line":0},"fn_name":null}],"covered":0,"coverable":1},{"path":["/","usr","src","rustlings","exercises","generics","generics3.rs"],"content":"// An imaginary magical school has a new report card generation system written in Rust!\n// Currently the system only supports creating report cards where the student's grade \n// is represented numerically (e.g. 1.0 -> 5.5). \n// However, the school also issues alphabetical grades (A+ -> F-) and needs \n// to be able to print both types of report card!\n\n// Make the necessary code changes to support alphabetical report cards, thereby making \n// the second test pass.\n\n// I AM NOT DONE\npub struct ReportCard {\n pub grade: f32,\n pub student_name: String,\n pub student_age: u8,\n}\n\nimpl ReportCard {\n pub fn print(&self) -> String {\n format!(\"{} ({}) - achieved a grade of {}\", \n &self.student_name, &self.student_age, &self.grade)\n }\n}\n\n#[cfg(test)]\nmod tests {\n use super::*;\n\n #[test]\n fn generate_numeric_report_card() {\n let report_card = ReportCard {\n grade: 2.1, \n student_name: \"Tom Wriggle\".to_string(), \n student_age: 12,\n };\n assert_eq!(report_card.print(), \"Tom Wriggle (12) - achieved a grade of 2.1\");\n }\n\n #[test]\n fn generate_alphabetic_report_card() {\n // TODO: Make sure to change the grade here after you finish the exercise.\n let report_card = ReportCard {\n grade: 2.1, \n student_name: \"Gary Plotter\".to_string(), \n student_age: 11,\n };\n assert_eq!(report_card.print(), \"Gary Plotter (11) - achieved a grade of A+\");\n }\n}","traces":[{"line":18,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":19,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":20,"address":[],"length":0,"stats":{"Line":0},"fn_name":null}],"covered":0,"coverable":3},{"path":["/","usr","src","rustlings","src","exercise.rs"],"content":"use regex::Regex;\nuse serde::Deserialize;\nuse std::fmt::{self, Display, Formatter};\nuse std::fs::{self, remove_file, File};\nuse std::io::Read;\nuse std::path::PathBuf;\nuse std::process::{self, Command};\n\nconst RUSTC_COLOR_ARGS: &[&str] = &[\"--color\", \"always\"];\nconst I_AM_DONE_REGEX: &str = r\"(?m)^\\s*///?\\s*I\\s+AM\\s+NOT\\s+DONE\";\nconst CONTEXT: usize = 2;\nconst CLIPPY_CARGO_TOML_PATH: &str = \"./exercises/clippy/Cargo.toml\";\n\n// Get a temporary file name that is hopefully unique to this process\n#[inline]\nfn temp_file() -> String {\n format!(\"./temp_{}\", process::id())\n}\n\n// The mode of the exercise.\n#[derive(Deserialize, Copy, Clone)]\n#[serde(rename_all = \"lowercase\")]\npub enum Mode {\n // Indicates that the exercise should be compiled as a binary\n Compile,\n // Indicates that the exercise should be compiled as a test harness\n Test,\n // Indicates that the exercise should be linted with clippy\n Clippy,\n}\n\n#[derive(Deserialize)]\npub struct ExerciseList {\n pub exercises: Vec<Exercise>,\n}\n\n// A representation of a rustlings exercise.\n// This is deserialized from the accompanying info.toml file\n#[derive(Deserialize)]\npub struct Exercise {\n // Name of the exercise\n pub name: String,\n // The path to the file containing the exercise's source code\n pub path: PathBuf,\n // The mode of the exercise (Test, Compile, or Clippy)\n pub mode: Mode,\n // The hint text associated with the exercise\n pub hint: String,\n}\n\n// An enum to track of the state of an Exercise.\n// An Exercise can be either Done or Pending\n#[derive(PartialEq, Debug)]\npub enum State {\n // The state of the exercise once it's been completed\n Done,\n // The state of the exercise while it's not completed yet\n Pending(Vec<ContextLine>),\n}\n\n// The context information of a pending exercise\n#[derive(PartialEq, Debug)]\npub struct ContextLine {\n // The source code that is still pending completion\n pub line: String,\n // The line number of the source code still pending completion\n pub number: usize,\n // Whether or not this is important\n pub important: bool,\n}\n\n// The result of compiling an exercise\npub struct CompiledExercise<'a> {\n exercise: &'a Exercise,\n _handle: FileHandle,\n}\n\nimpl<'a> CompiledExercise<'a> {\n // Run the compiled exercise\n pub fn run(&self) -> Result<ExerciseOutput, ExerciseOutput> {\n self.exercise.run()\n }\n}\n\n// A representation of an already executed binary\n#[derive(Debug)]\npub struct ExerciseOutput {\n // The textual contents of the standard output of the binary\n pub stdout: String,\n // The textual contents of the standard error of the binary\n pub stderr: String,\n}\n\nstruct FileHandle;\n\nimpl Drop for FileHandle {\n fn drop(&mut self) {\n clean();\n }\n}\n\nimpl Exercise {\n pub fn compile(&self) -> Result<CompiledExercise, ExerciseOutput> {\n let cmd = match self.mode {\n Mode::Compile => Command::new(\"rustc\")\n .args(&[self.path.to_str().unwrap(), \"-o\", &temp_file()])\n .args(RUSTC_COLOR_ARGS)\n .output(),\n Mode::Test => Command::new(\"rustc\")\n .args(&[\"--test\", self.path.to_str().unwrap(), \"-o\", &temp_file()])\n .args(RUSTC_COLOR_ARGS)\n .output(),\n Mode::Clippy => {\n let cargo_toml = format!(\n r#\"[package]\nname = \"{}\"\nversion = \"0.0.1\"\nedition = \"2018\"\n[[bin]]\nname = \"{}\"\npath = \"{}.rs\"\"#,\n self.name, self.name, self.name\n );\n fs::write(CLIPPY_CARGO_TOML_PATH, cargo_toml)\n .expect(\"Failed to write π Clippy π Cargo.toml file.\");\n // To support the ability to run the clipy exercises, build\n // an executable, in addition to running clippy. With a\n // compilation failure, this would silently fail. But we expect\n // clippy to reflect the same failure while compiling later.\n Command::new(\"rustc\")\n .args(&[self.path.to_str().unwrap(), \"-o\", &temp_file()])\n .args(RUSTC_COLOR_ARGS)\n .output()\n .expect(\"Failed to compile!\");\n // Due to an issue with Clippy, a cargo clean is required to catch all lints.\n // See https://github.com/rust-lang/rust-clippy/issues/2604\n // This is already fixed on Clippy's master branch. See this issue to track merging into Cargo:\n // https://github.com/rust-lang/rust-clippy/issues/3837\n Command::new(\"cargo\")\n .args(&[\"clean\", \"--manifest-path\", CLIPPY_CARGO_TOML_PATH])\n .args(RUSTC_COLOR_ARGS)\n .output()\n .expect(\"Failed to run 'cargo clean'\");\n Command::new(\"cargo\")\n .args(&[\"clippy\", \"--manifest-path\", CLIPPY_CARGO_TOML_PATH])\n .args(RUSTC_COLOR_ARGS)\n .args(&[\"--\", \"-D\", \"warnings\"])\n .output()\n }\n }\n .expect(\"Failed to run 'compile' command.\");\n\n if cmd.status.success() {\n Ok(CompiledExercise {\n exercise: &self,\n _handle: FileHandle,\n })\n } else {\n clean();\n Err(ExerciseOutput {\n stdout: String::from_utf8_lossy(&cmd.stdout).to_string(),\n stderr: String::from_utf8_lossy(&cmd.stderr).to_string(),\n })\n }\n }\n\n fn run(&self) -> Result<ExerciseOutput, ExerciseOutput> {\n let arg = match self.mode {\n Mode::Test => \"--show-output\",\n _ => \"\",\n };\n let cmd = Command::new(&temp_file())\n .arg(arg)\n .output()\n .expect(\"Failed to run 'run' command\");\n\n let output = ExerciseOutput {\n stdout: String::from_utf8_lossy(&cmd.stdout).to_string(),\n stderr: String::from_utf8_lossy(&cmd.stderr).to_string(),\n };\n\n if cmd.status.success() {\n Ok(output)\n } else {\n Err(output)\n }\n }\n\n pub fn state(&self) -> State {\n let mut source_file =\n File::open(&self.path).expect(\"We were unable to open the exercise file!\");\n\n let source = {\n let mut s = String::new();\n source_file\n .read_to_string(&mut s)\n .expect(\"We were unable to read the exercise file!\");\n s\n };\n\n let re = Regex::new(I_AM_DONE_REGEX).unwrap();\n\n if !re.is_match(&source) {\n return State::Done;\n }\n\n let matched_line_index = source\n .lines()\n .enumerate()\n .filter_map(|(i, line)| if re.is_match(line) { Some(i) } else { None })\n .next()\n .expect(\"This should not happen at all\");\n\n let min_line = ((matched_line_index as i32) - (CONTEXT as i32)).max(0) as usize;\n let max_line = matched_line_index + CONTEXT;\n\n let context = source\n .lines()\n .enumerate()\n .filter(|&(i, _)| i >= min_line && i <= max_line)\n .map(|(i, line)| ContextLine {\n line: line.to_string(),\n number: i + 1,\n important: i == matched_line_index,\n })\n .collect();\n\n State::Pending(context)\n }\n}\n\nimpl Display for Exercise {\n fn fmt(&self, f: &mut Formatter) -> fmt::Result {\n write!(f, \"{}\", self.path.to_str().unwrap())\n }\n}\n\n#[inline]\nfn clean() {\n let _ignored = remove_file(&temp_file());\n}\n\n#[cfg(test)]\nmod test {\n use super::*;\n use std::path::Path;\n\n #[test]\n fn test_clean() {\n File::create(&temp_file()).unwrap();\n let exercise = Exercise {\n name: String::from(\"example\"),\n path: PathBuf::from(\"tests/fixture/state/pending_exercise.rs\"),\n mode: Mode::Compile,\n hint: String::from(\"\"),\n };\n let compiled = exercise.compile().unwrap();\n drop(compiled);\n assert!(!Path::new(&temp_file()).exists());\n }\n\n #[test]\n fn test_pending_state() {\n let exercise = Exercise {\n name: \"pending_exercise\".into(),\n path: PathBuf::from(\"tests/fixture/state/pending_exercise.rs\"),\n mode: Mode::Compile,\n hint: String::new(),\n };\n\n let state = exercise.state();\n let expected = vec![\n ContextLine {\n line: \"// fake_exercise\".to_string(),\n number: 1,\n important: false,\n },\n ContextLine {\n line: \"\".to_string(),\n number: 2,\n important: false,\n },\n ContextLine {\n line: \"// I AM NOT DONE\".to_string(),\n number: 3,\n important: true,\n },\n ContextLine {\n line: \"\".to_string(),\n number: 4,\n important: false,\n },\n ContextLine {\n line: \"fn main() {\".to_string(),\n number: 5,\n important: false,\n },\n ];\n\n assert_eq!(state, State::Pending(expected));\n }\n\n #[test]\n fn test_finished_exercise() {\n let exercise = Exercise {\n name: \"finished_exercise\".into(),\n path: PathBuf::from(\"tests/fixture/state/finished_exercise.rs\"),\n mode: Mode::Compile,\n hint: String::new(),\n };\n\n assert_eq!(exercise.state(), State::Done);\n }\n\n // #[test]\n // fn test_exercise_with_output() {\n // let exercise = Exercise {\n // name: \"finished_exercise\".into(),\n // path: PathBuf::from(\"tests/fixture/success/testSuccess.rs\"),\n // mode: Mode::Test,\n // hint: String::new(),\n // };\n // let out = exercise.compile().unwrap().run().unwrap();\n // assert!(out.stdout.contains(\"THIS TEST TOO SHALL PASS\"));\n // }\n}\n","traces":[{"line":16,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":17,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":80,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":81,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":97,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":98,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":103,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":104,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":106,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":107,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":110,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":111,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":113,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":114,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":122,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":124,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":131,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":132,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":140,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":141,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":145,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":146,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":147,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":153,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":154,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":155,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":156,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":159,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":160,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":161,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":162,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":167,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":168,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":169,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":170,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":172,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":173,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":178,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":179,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":182,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":183,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":185,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":189,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":190,"address":[],"length":0,"stats":{"Line":4},"fn_name":null},{"line":191,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":193,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":194,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":195,"address":[],"length":0,"stats":{"Line":4},"fn_name":null},{"line":196,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":198,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":201,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":203,"address":[],"length":0,"stats":{"Line":4},"fn_name":null},{"line":204,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":207,"address":[],"length":0,"stats":{"Line":3},"fn_name":null},{"line":210,"address":[],"length":0,"stats":{"Line":3},"fn_name":null},{"line":214,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":215,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":217,"address":[],"length":0,"stats":{"Line":3},"fn_name":null},{"line":220,"address":[],"length":0,"stats":{"Line":3},"fn_name":null},{"line":221,"address":[],"length":0,"stats":{"Line":4},"fn_name":null},{"line":222,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":223,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":224,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":228,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":233,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":234,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":239,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":240,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":249,"address":[4308000,4308005],"length":1,"stats":{"Line":3},"fn_name":"{{closure}}"},{"line":250,"address":[4347495,4347532],"length":1,"stats":{"Line":2},"fn_name":null},{"line":252,"address":[4347617],"length":1,"stats":{"Line":1},"fn_name":null},{"line":253,"address":[4347638],"length":1,"stats":{"Line":1},"fn_name":null},{"line":255,"address":[4347673],"length":1,"stats":{"Line":1},"fn_name":null},{"line":257,"address":[4347858,4347832,4347905],"length":1,"stats":{"Line":3},"fn_name":null},{"line":258,"address":[4347913],"length":1,"stats":{"Line":1},"fn_name":null},{"line":259,"address":[4347931,4348053],"length":1,"stats":{"Line":1},"fn_name":null},{"line":263,"address":[4308037,4308032],"length":1,"stats":{"Line":3},"fn_name":"{{closure}}"},{"line":265,"address":[4348222],"length":1,"stats":{"Line":1},"fn_name":null},{"line":266,"address":[4348261],"length":1,"stats":{"Line":1},"fn_name":null},{"line":268,"address":[4348304],"length":1,"stats":{"Line":1},"fn_name":null},{"line":271,"address":[4348441],"length":1,"stats":{"Line":1},"fn_name":null},{"line":272,"address":[4348815,4348909,4348625,4348976,4349746,4348722,4348477],"length":1,"stats":{"Line":2},"fn_name":null},{"line":273,"address":[4348532],"length":1,"stats":{"Line":1},"fn_name":null},{"line":274,"address":[4348490],"length":1,"stats":{"Line":1},"fn_name":null},{"line":278,"address":[4348643],"length":1,"stats":{"Line":1},"fn_name":null},{"line":279,"address":[4348584],"length":1,"stats":{"Line":1},"fn_name":null},{"line":283,"address":[4348737],"length":1,"stats":{"Line":1},"fn_name":null},{"line":284,"address":[4348695],"length":1,"stats":{"Line":1},"fn_name":null},{"line":288,"address":[4348830],"length":1,"stats":{"Line":1},"fn_name":null},{"line":289,"address":[4348789],"length":1,"stats":{"Line":1},"fn_name":null},{"line":293,"address":[4348924],"length":1,"stats":{"Line":1},"fn_name":null},{"line":294,"address":[4348882],"length":1,"stats":{"Line":1},"fn_name":null},{"line":300,"address":[4349206],"length":1,"stats":{"Line":1},"fn_name":null},{"line":304,"address":[4308069,4308064],"length":1,"stats":{"Line":3},"fn_name":"{{closure}}"},{"line":306,"address":[4349982],"length":1,"stats":{"Line":1},"fn_name":null},{"line":307,"address":[4350021],"length":1,"stats":{"Line":1},"fn_name":null},{"line":309,"address":[4350064],"length":1,"stats":{"Line":1},"fn_name":null},{"line":312,"address":[4350201,4350227,4350336],"length":1,"stats":{"Line":3},"fn_name":null}],"covered":61,"coverable":98},{"path":["/","usr","src","rustlings","src","main.rs"],"content":"use crate::exercise::{Exercise, ExerciseList};\nuse crate::run::run;\nuse crate::verify::verify;\nuse clap::{crate_version, App, Arg, SubCommand};\nuse console::Emoji;\nuse notify::DebouncedEvent;\nuse notify::{RecommendedWatcher, RecursiveMode, Watcher};\nuse std::ffi::OsStr;\nuse std::fs;\nuse std::io;\nuse std::path::Path;\nuse std::process::{Command, Stdio};\nuse std::sync::mpsc::channel;\nuse std::sync::{Arc, Mutex};\nuse std::thread;\nuse std::time::Duration;\n\n#[macro_use]\nmod ui;\n\nmod exercise;\nmod run;\nmod verify;\n\nfn main() {\n let matches = App::new(\"rustlings\")\n .version(crate_version!())\n .author(\"Olivia Hugger, Carol Nichols\")\n .about(\"Rustlings is a collection of small exercises to get you used to writing and reading Rust code\")\n .arg(\n Arg::with_name(\"nocapture\")\n .long(\"nocapture\")\n .help(\"Show outputs from the test exercises\")\n )\n .subcommand(\n SubCommand::with_name(\"verify\")\n .alias(\"v\")\n .about(\"Verifies all exercises according to the recommended order\")\n )\n .subcommand(\n SubCommand::with_name(\"watch\")\n .alias(\"w\")\n .about(\"Reruns `verify` when files were edited\")\n )\n .subcommand(\n SubCommand::with_name(\"run\")\n .alias(\"r\")\n .about(\"Runs/Tests a single exercise\")\n .arg(Arg::with_name(\"name\").required(true).index(1)),\n )\n .subcommand(\n SubCommand::with_name(\"hint\")\n .alias(\"h\")\n .about(\"Returns a hint for the current exercise\")\n .arg(Arg::with_name(\"name\").required(true).index(1)),\n )\n .get_matches();\n\n if matches.subcommand_name().is_none() {\n println!();\n println!(r#\" welcome to... \"#);\n println!(r#\" _ _ _ \"#);\n println!(r#\" _ __ _ _ ___| |_| (_)_ __ __ _ ___ \"#);\n println!(r#\" | '__| | | / __| __| | | '_ \\ / _` / __| \"#);\n println!(r#\" | | | |_| \\__ \\ |_| | | | | | (_| \\__ \\ \"#);\n println!(r#\" |_| \\__,_|___/\\__|_|_|_| |_|\\__, |___/ \"#);\n println!(r#\" |___/ \"#);\n println!();\n }\n\n if !Path::new(\"info.toml\").exists() {\n println!(\n \"{} must be run from the rustlings directory\",\n std::env::current_exe().unwrap().to_str().unwrap()\n );\n println!(\"Try `cd rustlings/`!\");\n std::process::exit(1);\n }\n\n if !rustc_exists() {\n println!(\"We cannot find `rustc`.\");\n println!(\"Try running `rustc --version` to diagnose your problem.\");\n println!(\"For instructions on how to install Rust, check the README.\");\n std::process::exit(1);\n }\n\n let toml_str = &fs::read_to_string(\"info.toml\").unwrap();\n let exercises = toml::from_str::<ExerciseList>(toml_str).unwrap().exercises;\n let verbose = matches.is_present(\"nocapture\");\n\n if let Some(ref matches) = matches.subcommand_matches(\"run\") {\n let name = matches.value_of(\"name\").unwrap();\n\n let matching_exercise = |e: &&Exercise| name == e.name;\n\n let exercise = exercises.iter().find(matching_exercise).unwrap_or_else(|| {\n println!(\"No exercise found for your given name!\");\n std::process::exit(1)\n });\n\n run(&exercise, verbose).unwrap_or_else(|_| std::process::exit(1));\n }\n\n if let Some(ref matches) = matches.subcommand_matches(\"hint\") {\n let name = matches.value_of(\"name\").unwrap();\n\n let exercise = exercises\n .iter()\n .find(|e| name == e.name)\n .unwrap_or_else(|| {\n println!(\"No exercise found for your given name!\");\n std::process::exit(1)\n });\n\n println!(\"{}\", exercise.hint);\n }\n\n if matches.subcommand_matches(\"verify\").is_some() {\n verify(&exercises, verbose).unwrap_or_else(|_| std::process::exit(1));\n }\n\n if matches.subcommand_matches(\"watch\").is_some() && watch(&exercises, verbose).is_ok() {\n println!(\n \"{emoji} All exercises completed! {emoji}\",\n emoji = Emoji(\"π\", \"β
\")\n );\n println!();\n println!(\"We hope you enjoyed learning about the various aspects of Rust!\");\n println!(\n \"If you noticed any issues, please don't hesitate to report them to our repo.\"\n );\n println!(\"You can also contribute your own exercises to help the greater community!\");\n println!();\n println!(\"Before reporting an issue or contributing, please read our guidelines:\");\n println!(\"https://github.com/rust-lang/rustlings/blob/main/CONTRIBUTING.md\");\n }\n\n if matches.subcommand_name().is_none() {\n let text = fs::read_to_string(\"default_out.txt\").unwrap();\n println!(\"{}\", text);\n }\n}\n\nfn spawn_watch_shell(failed_exercise_hint: &Arc<Mutex<Option<String>>>) {\n let failed_exercise_hint = Arc::clone(failed_exercise_hint);\n println!(\"Type 'hint' to get help\");\n thread::spawn(move || loop {\n let mut input = String::new();\n match io::stdin().read_line(&mut input) {\n Ok(_) => {\n if input.trim().eq(\"hint\") {\n if let Some(hint) = &*failed_exercise_hint.lock().unwrap() {\n println!(\"{}\", hint);\n }\n } else {\n println!(\"unknown command: {}\", input);\n }\n }\n Err(error) => println!(\"error reading command: {}\", error),\n }\n });\n}\n\nfn watch(exercises: &[Exercise], verbose: bool) -> notify::Result<()> {\n /* Clears the terminal with an ANSI escape code.\n Works in UNIX and newer Windows terminals. */\n fn clear_screen() {\n println!(\"\\x1Bc\");\n }\n\n let (tx, rx) = channel();\n\n let mut watcher: RecommendedWatcher = Watcher::new(tx, Duration::from_secs(2))?;\n watcher.watch(Path::new(\"./exercises\"), RecursiveMode::Recursive)?;\n\n clear_screen();\n\n let to_owned_hint = |t: &Exercise| t.hint.to_owned();\n let failed_exercise_hint = match verify(exercises.iter(), verbose) {\n Ok(_) => return Ok(()),\n Err(exercise) => Arc::new(Mutex::new(Some(to_owned_hint(exercise)))),\n };\n spawn_watch_shell(&failed_exercise_hint);\n loop {\n match rx.recv() {\n Ok(event) => match event {\n DebouncedEvent::Create(b) | DebouncedEvent::Chmod(b) | DebouncedEvent::Write(b) => {\n if b.extension() == Some(OsStr::new(\"rs\")) && b.exists() {\n let filepath = b.as_path().canonicalize().unwrap();\n let pending_exercises = exercises\n .iter()\n .skip_while(|e| !filepath.ends_with(&e.path));\n clear_screen();\n match verify(pending_exercises, verbose) {\n Ok(_) => return Ok(()),\n Err(exercise) => {\n let mut failed_exercise_hint = failed_exercise_hint.lock().unwrap();\n *failed_exercise_hint = Some(to_owned_hint(exercise));\n }\n }\n }\n }\n _ => {}\n },\n Err(e) => println!(\"watch error: {:?}\", e),\n }\n }\n}\n\nfn rustc_exists() -> bool {\n Command::new(\"rustc\")\n .args(&[\"--version\"])\n .stdout(Stdio::null())\n .spawn()\n .and_then(|mut child| child.wait())\n .map(|status| status.success())\n .unwrap_or(false)\n}\n","traces":[{"line":25,"address":[4256688,4256788],"length":1,"stats":{"Line":0},"fn_name":"main"},{"line":31,"address":[4256920],"length":1,"stats":{"Line":0},"fn_name":null},{"line":36,"address":[4257084],"length":1,"stats":{"Line":0},"fn_name":null},{"line":41,"address":[4257248],"length":1,"stats":{"Line":0},"fn_name":null},{"line":46,"address":[4257412,4257620],"length":1,"stats":{"Line":0},"fn_name":null},{"line":48,"address":[4257517],"length":1,"stats":{"Line":0},"fn_name":null},{"line":49,"address":[4262418,4257525,4257659],"length":1,"stats":{"Line":0},"fn_name":null},{"line":52,"address":[4257934,4257726],"length":1,"stats":{"Line":0},"fn_name":null},{"line":54,"address":[4257831],"length":1,"stats":{"Line":0},"fn_name":null},{"line":55,"address":[4262496,4257973,4257839],"length":1,"stats":{"Line":0},"fn_name":null},{"line":59,"address":[4258054,4258173,4258704],"length":1,"stats":{"Line":0},"fn_name":null},{"line":60,"address":[4258182],"length":1,"stats":{"Line":0},"fn_name":null},{"line":61,"address":[4258240],"length":1,"stats":{"Line":0},"fn_name":null},{"line":62,"address":[4258298],"length":1,"stats":{"Line":0},"fn_name":null},{"line":63,"address":[4258356],"length":1,"stats":{"Line":0},"fn_name":null},{"line":64,"address":[4258414],"length":1,"stats":{"Line":0},"fn_name":null},{"line":65,"address":[4258472],"length":1,"stats":{"Line":0},"fn_name":null},{"line":66,"address":[4258530],"length":1,"stats":{"Line":0},"fn_name":null},{"line":67,"address":[4258588],"length":1,"stats":{"Line":0},"fn_name":null},{"line":68,"address":[4258646],"length":1,"stats":{"Line":0},"fn_name":null},{"line":71,"address":[4258706],"length":1,"stats":{"Line":0},"fn_name":null},{"line":72,"address":[4258947,4259056],"length":1,"stats":{"Line":0},"fn_name":null},{"line":74,"address":[4258966,4258816],"length":1,"stats":{"Line":0},"fn_name":null},{"line":76,"address":[4259245],"length":1,"stats":{"Line":0},"fn_name":null},{"line":80,"address":[4259329,4258792],"length":1,"stats":{"Line":0},"fn_name":null},{"line":81,"address":[4259365],"length":1,"stats":{"Line":0},"fn_name":null},{"line":82,"address":[4259423],"length":1,"stats":{"Line":0},"fn_name":null},{"line":83,"address":[4259481],"length":1,"stats":{"Line":0},"fn_name":null},{"line":87,"address":[4259335,4259558],"length":1,"stats":{"Line":0},"fn_name":null},{"line":88,"address":[4259604,4259673],"length":1,"stats":{"Line":0},"fn_name":null},{"line":89,"address":[4259805,4259742],"length":1,"stats":{"Line":0},"fn_name":null},{"line":91,"address":[4260285,4259814],"length":1,"stats":{"Line":0},"fn_name":null},{"line":92,"address":[4259913],"length":1,"stats":{"Line":0},"fn_name":null},{"line":94,"address":[4260046],"length":1,"stats":{"Line":0},"fn_name":null},{"line":96,"address":[4260062],"length":1,"stats":{"Line":0},"fn_name":null},{"line":97,"address":[4380825],"length":1,"stats":{"Line":0},"fn_name":null},{"line":98,"address":[4380881,4380897],"length":1,"stats":{"Line":0},"fn_name":null},{"line":101,"address":[4260226],"length":1,"stats":{"Line":0},"fn_name":null},{"line":104,"address":[4260287,4260875],"length":1,"stats":{"Line":0},"fn_name":null},{"line":105,"address":[4260386],"length":1,"stats":{"Line":0},"fn_name":null},{"line":107,"address":[4260519,4260629],"length":1,"stats":{"Line":0},"fn_name":null},{"line":109,"address":[4260621],"length":1,"stats":{"Line":0},"fn_name":null},{"line":110,"address":[4380992],"length":1,"stats":{"Line":0},"fn_name":"{{closure}}"},{"line":111,"address":[4381001],"length":1,"stats":{"Line":0},"fn_name":null},{"line":112,"address":[4381073,4381057],"length":1,"stats":{"Line":0},"fn_name":null},{"line":115,"address":[4260699],"length":1,"stats":{"Line":0},"fn_name":null},{"line":118,"address":[4260877,4261010],"length":1,"stats":{"Line":0},"fn_name":null},{"line":119,"address":[4260970],"length":1,"stats":{"Line":0},"fn_name":null},{"line":122,"address":[4261842,4261012],"length":1,"stats":{"Line":0},"fn_name":null},{"line":123,"address":[4261276],"length":1,"stats":{"Line":0},"fn_name":null},{"line":125,"address":[4261269],"length":1,"stats":{"Line":0},"fn_name":null},{"line":127,"address":[4261436],"length":1,"stats":{"Line":0},"fn_name":null},{"line":128,"address":[4261494],"length":1,"stats":{"Line":0},"fn_name":null},{"line":129,"address":[4261559],"length":1,"stats":{"Line":0},"fn_name":null},{"line":132,"address":[4261610],"length":1,"stats":{"Line":0},"fn_name":null},{"line":133,"address":[4261668],"length":1,"stats":{"Line":0},"fn_name":null},{"line":134,"address":[4261726],"length":1,"stats":{"Line":0},"fn_name":null},{"line":135,"address":[4261784],"length":1,"stats":{"Line":0},"fn_name":null},{"line":138,"address":[4262192,4261844],"length":1,"stats":{"Line":0},"fn_name":null},{"line":139,"address":[4261935],"length":1,"stats":{"Line":0},"fn_name":null},{"line":140,"address":[4262154,4261992],"length":1,"stats":{"Line":0},"fn_name":null},{"line":144,"address":[4262834,4262800],"length":1,"stats":{"Line":0},"fn_name":"spawn_watch_shell"},{"line":145,"address":[4262812],"length":1,"stats":{"Line":0},"fn_name":null},{"line":146,"address":[4262846],"length":1,"stats":{"Line":0},"fn_name":null},{"line":147,"address":[4262898],"length":1,"stats":{"Line":0},"fn_name":null},{"line":148,"address":[4381143],"length":1,"stats":{"Line":0},"fn_name":null},{"line":149,"address":[4381424,4382080,4381180,4382216],"length":1,"stats":{"Line":0},"fn_name":null},{"line":150,"address":[4381266],"length":1,"stats":{"Line":0},"fn_name":null},{"line":151,"address":[4381503,4381992,4381434,4382078],"length":1,"stats":{"Line":0},"fn_name":null},{"line":152,"address":[4381975,4381635,4381769],"length":1,"stats":{"Line":0},"fn_name":null},{"line":153,"address":[4381805],"length":1,"stats":{"Line":0},"fn_name":null},{"line":156,"address":[4381999,4381546],"length":1,"stats":{"Line":0},"fn_name":null},{"line":159,"address":[4381322,4382093],"length":1,"stats":{"Line":0},"fn_name":null},{"line":164,"address":[4263008,4263154],"length":1,"stats":{"Line":0},"fn_name":"watch"},{"line":167,"address":[4266832],"length":1,"stats":{"Line":0},"fn_name":"clear_screen"},{"line":168,"address":[4266841],"length":1,"stats":{"Line":0},"fn_name":null},{"line":171,"address":[4263049,4263169],"length":1,"stats":{"Line":0},"fn_name":null},{"line":173,"address":[4263241,4263351,4263601,4266061],"length":1,"stats":{"Line":0},"fn_name":null},{"line":174,"address":[4264043,4263559,4263779],"length":1,"stats":{"Line":0},"fn_name":null},{"line":176,"address":[4264048],"length":1,"stats":{"Line":0},"fn_name":null},{"line":178,"address":[4382433,4382416],"length":1,"stats":{"Line":0},"fn_name":"{{closure}}"},{"line":179,"address":[4264234,4264071],"length":1,"stats":{"Line":0},"fn_name":null},{"line":180,"address":[4264244,4264156],"length":1,"stats":{"Line":0},"fn_name":null},{"line":181,"address":[4264256,4264179],"length":1,"stats":{"Line":0},"fn_name":null},{"line":183,"address":[4264358],"length":1,"stats":{"Line":0},"fn_name":null},{"line":184,"address":[4266534,4264365],"length":1,"stats":{"Line":0},"fn_name":null},{"line":185,"address":[4266029,4266335,4264518,4264401],"length":1,"stats":{"Line":0},"fn_name":null},{"line":186,"address":[4264520,4264764,4264822,4264883,4265931,4264408],"length":1,"stats":{"Line":0},"fn_name":null},{"line":187,"address":[4264708,4264766,4264608,4264827],"length":1,"stats":{"Line":0},"fn_name":null},{"line":188,"address":[4264682,4265910,4264888,4265049],"length":1,"stats":{"Line":0},"fn_name":null},{"line":189,"address":[4265224],"length":1,"stats":{"Line":0},"fn_name":null},{"line":190,"address":[4265328,4265361],"length":1,"stats":{"Line":0},"fn_name":null},{"line":192,"address":[4265353],"length":1,"stats":{"Line":0},"fn_name":null},{"line":193,"address":[4265413],"length":1,"stats":{"Line":0},"fn_name":null},{"line":194,"address":[4265420,4265564],"length":1,"stats":{"Line":0},"fn_name":null},{"line":195,"address":[4265574,4265646,4265500],"length":1,"stats":{"Line":0},"fn_name":null},{"line":196,"address":[4265523],"length":1,"stats":{"Line":0},"fn_name":null},{"line":197,"address":[4265552,4265664],"length":1,"stats":{"Line":0},"fn_name":null},{"line":198,"address":[4265848,4266185,4265731],"length":1,"stats":{"Line":0},"fn_name":null},{"line":203,"address":[4265912,4265028,4265600],"length":1,"stats":{"Line":0},"fn_name":null},{"line":205,"address":[4265944,4264432],"length":1,"stats":{"Line":0},"fn_name":null},{"line":210,"address":[4266912,4266949],"length":1,"stats":{"Line":0},"fn_name":"rustc_exists"},{"line":212,"address":[4266964],"length":1,"stats":{"Line":0},"fn_name":null},{"line":213,"address":[4266991],"length":1,"stats":{"Line":0},"fn_name":null},{"line":215,"address":[4382567,4382560],"length":1,"stats":{"Line":0},"fn_name":"{{closure}}"},{"line":216,"address":[4382656,4382664],"length":1,"stats":{"Line":0},"fn_name":"{{closure}}"}],"covered":0,"coverable":106},{"path":["/","usr","src","rustlings","src","run.rs"],"content":"use crate::exercise::{Exercise, Mode};\nuse crate::verify::test;\nuse indicatif::ProgressBar;\n\n// Invoke the rust compiler on the path of the given exercise,\n// and run the ensuing binary.\n// The verbose argument helps determine whether or not to show\n// the output from the test harnesses (if the mode of the exercise is test)\npub fn run(exercise: &Exercise, verbose: bool) -> Result<(), ()> {\n match exercise.mode {\n Mode::Test => test(exercise, verbose)?,\n Mode::Compile => compile_and_run(exercise)?,\n Mode::Clippy => compile_and_run(exercise)?,\n }\n Ok(())\n}\n\n// Invoke the rust compiler on the path of the given exercise\n// and run the ensuing binary.\n// This is strictly for non-test binaries, so output is displayed\nfn compile_and_run(exercise: &Exercise) -> Result<(), ()> {\n let progress_bar = ProgressBar::new_spinner();\n progress_bar.set_message(format!(\"Compiling {}...\", exercise).as_str());\n progress_bar.enable_steady_tick(100);\n\n let compilation_result = exercise.compile();\n let compilation = match compilation_result {\n Ok(compilation) => compilation,\n Err(output) => {\n progress_bar.finish_and_clear();\n warn!(\n \"Compilation of {} failed!, Compiler error message:\\n\",\n exercise\n );\n println!(\"{}\", output.stderr);\n return Err(());\n }\n };\n\n progress_bar.set_message(format!(\"Running {}...\", exercise).as_str());\n let result = compilation.run();\n progress_bar.finish_and_clear();\n\n match result {\n Ok(output) => {\n println!(\"{}\", output.stdout);\n success!(\"Successfully ran {}\", exercise);\n Ok(())\n }\n Err(output) => {\n println!(\"{}\", output.stdout);\n println!(\"{}\", output.stderr);\n\n warn!(\"Ran {} with errors\", exercise);\n Err(())\n }\n }\n}\n","traces":[{"line":9,"address":[4400736],"length":1,"stats":{"Line":0},"fn_name":"run"},{"line":10,"address":[4400818,4400982,4401044,4400885],"length":1,"stats":{"Line":0},"fn_name":null},{"line":11,"address":[4400754,4400890,4400824,4400914],"length":1,"stats":{"Line":0},"fn_name":null},{"line":12,"address":[4400984,4400934],"length":1,"stats":{"Line":0},"fn_name":null},{"line":13,"address":[4400804,4401009,4401046],"length":1,"stats":{"Line":0},"fn_name":null},{"line":15,"address":[4401070],"length":1,"stats":{"Line":0},"fn_name":null},{"line":21,"address":[4401159,4401088],"length":1,"stats":{"Line":0},"fn_name":"compile_and_run"},{"line":22,"address":[4401103],"length":1,"stats":{"Line":0},"fn_name":null},{"line":23,"address":[4401350,4401174],"length":1,"stats":{"Line":0},"fn_name":null},{"line":24,"address":[4401513],"length":1,"stats":{"Line":0},"fn_name":null},{"line":26,"address":[4401537],"length":1,"stats":{"Line":0},"fn_name":null},{"line":27,"address":[4401642],"length":1,"stats":{"Line":0},"fn_name":null},{"line":28,"address":[4401644,4401560],"length":1,"stats":{"Line":0},"fn_name":null},{"line":29,"address":[4401575],"length":1,"stats":{"Line":0},"fn_name":null},{"line":30,"address":[4401623],"length":1,"stats":{"Line":0},"fn_name":null},{"line":31,"address":[4401865,4405439,4401774],"length":1,"stats":{"Line":0},"fn_name":null},{"line":35,"address":[4402576],"length":1,"stats":{"Line":0},"fn_name":null},{"line":36,"address":[4402813,4402756],"length":1,"stats":{"Line":0},"fn_name":null},{"line":40,"address":[4401668,4402907,4402823],"length":1,"stats":{"Line":0},"fn_name":null},{"line":41,"address":[4403086],"length":1,"stats":{"Line":0},"fn_name":null},{"line":42,"address":[4403109],"length":1,"stats":{"Line":0},"fn_name":null},{"line":44,"address":[4405415,4403293,4404378],"length":1,"stats":{"Line":0},"fn_name":null},{"line":45,"address":[4403295,4403128],"length":1,"stats":{"Line":0},"fn_name":null},{"line":46,"address":[4403530,4403351],"length":1,"stats":{"Line":0},"fn_name":null},{"line":47,"address":[4403549,4405592],"length":1,"stats":{"Line":0},"fn_name":null},{"line":48,"address":[4404355],"length":1,"stats":{"Line":0},"fn_name":null},{"line":50,"address":[4403512,4403147,4404371],"length":1,"stats":{"Line":0},"fn_name":null},{"line":51,"address":[4404391,4403203,4404475],"length":1,"stats":{"Line":0},"fn_name":null},{"line":52,"address":[4404494],"length":1,"stats":{"Line":0},"fn_name":null},{"line":54,"address":[4404656,4405634],"length":1,"stats":{"Line":0},"fn_name":null},{"line":55,"address":[4405392],"length":1,"stats":{"Line":0},"fn_name":null}],"covered":0,"coverable":31},{"path":["/","usr","src","rustlings","src","verify.rs"],"content":"use crate::exercise::{CompiledExercise, Exercise, Mode, State};\nuse console::style;\nuse indicatif::ProgressBar;\n\n// Verify that the provided container of Exercise objects\n// can be compiled and run without any failures.\n// Any such failures will be reported to the end user.\n// If the Exercise being verified is a test, the verbose boolean\n// determines whether or not the test harness outputs are displayed.\npub fn verify<'a>(\n start_at: impl IntoIterator<Item = &'a Exercise>,\n verbose: bool\n) -> Result<(), &'a Exercise> {\n for exercise in start_at {\n let compile_result = match exercise.mode {\n Mode::Test => compile_and_test(&exercise, RunMode::Interactive, verbose),\n Mode::Compile => compile_and_run_interactively(&exercise),\n Mode::Clippy => compile_only(&exercise),\n };\n if !compile_result.unwrap_or(false) {\n return Err(exercise);\n }\n }\n Ok(())\n}\n\nenum RunMode {\n Interactive,\n NonInteractive,\n}\n\n// Compile and run the resulting test harness of the given Exercise\npub fn test(exercise: &Exercise, verbose: bool) -> Result<(), ()> {\n compile_and_test(exercise, RunMode::NonInteractive, verbose)?;\n Ok(())\n}\n\n// Invoke the rust compiler without running the resulting binary\nfn compile_only(exercise: &Exercise) -> Result<bool, ()> {\n let progress_bar = ProgressBar::new_spinner();\n progress_bar.set_message(format!(\"Compiling {}...\", exercise).as_str());\n progress_bar.enable_steady_tick(100);\n\n let _ = compile(&exercise, &progress_bar)?;\n progress_bar.finish_and_clear();\n\n success!(\"Successfully compiled {}!\", exercise);\n Ok(prompt_for_completion(&exercise, None))\n}\n\n// Compile the given Exercise and run the resulting binary in an interactive mode\nfn compile_and_run_interactively(exercise: &Exercise) -> Result<bool, ()> {\n let progress_bar = ProgressBar::new_spinner();\n progress_bar.set_message(format!(\"Compiling {}...\", exercise).as_str());\n progress_bar.enable_steady_tick(100);\n\n let compilation = compile(&exercise, &progress_bar)?;\n\n progress_bar.set_message(format!(\"Running {}...\", exercise).as_str());\n let result = compilation.run();\n progress_bar.finish_and_clear();\n\n let output = match result {\n Ok(output) => output,\n Err(output) => {\n warn!(\"Ran {} with errors\", exercise);\n println!(\"{}\", output.stdout);\n return Err(());\n }\n };\n\n success!(\"Successfully ran {}!\", exercise);\n\n Ok(prompt_for_completion(&exercise, Some(output.stdout)))\n}\n\n// Compile the given Exercise as a test harness and display\n// the output if verbose is set to true\nfn compile_and_test(\n exercise: &Exercise, run_mode: RunMode, verbose: bool\n) -> Result<bool, ()> {\n let progress_bar = ProgressBar::new_spinner();\n progress_bar.set_message(format!(\"Testing {}...\", exercise).as_str());\n progress_bar.enable_steady_tick(100);\n\n let compilation = compile(exercise, &progress_bar)?;\n let result = compilation.run();\n progress_bar.finish_and_clear();\n\n match result {\n Ok(output) => {\n if verbose {\n println!(\"{}\", output.stdout);\n }\n success!(\"Successfully tested {}\", &exercise);\n if let RunMode::Interactive = run_mode {\n Ok(prompt_for_completion(&exercise, None))\n } else {\n Ok(true)\n }\n }\n Err(output) => {\n warn!(\n \"Testing of {} failed! Please try again. Here's the output:\",\n exercise\n );\n println!(\"{}\", output.stdout);\n Err(())\n }\n }\n}\n\n// Compile the given Exercise and return an object with information\n// about the state of the compilation\nfn compile<'a, 'b>(\n exercise: &'a Exercise,\n progress_bar: &'b ProgressBar,\n) -> Result<CompiledExercise<'a>, ()> {\n let compilation_result = exercise.compile();\n\n match compilation_result {\n Ok(compilation) => Ok(compilation),\n Err(output) => {\n progress_bar.finish_and_clear();\n warn!(\n \"Compiling of {} failed! Please try again. Here's the output:\",\n exercise\n );\n println!(\"{}\", output.stderr);\n Err(())\n }\n }\n}\n\nfn prompt_for_completion(exercise: &Exercise, prompt_output: Option<String>) -> bool {\n let context = match exercise.state() {\n State::Done => return true,\n State::Pending(context) => context,\n };\n\n let success_msg = match exercise.mode {\n Mode::Compile => \"The code is compiling!\",\n Mode::Test => \"The code is compiling, and the tests pass!\",\n Mode::Clippy => \"The code is compiling, and π Clippy π is happy!\",\n };\n\n println!();\n println!(\"π π {} π π\", success_msg);\n println!();\n\n if let Some(output) = prompt_output {\n println!(\"Output:\");\n println!(\"{}\", separator());\n println!(\"{}\", output);\n println!(\"{}\", separator());\n println!();\n }\n\n println!(\"You can keep working on this exercise,\");\n println!(\n \"or jump into the next one by removing the {} comment:\",\n style(\"`I AM NOT DONE`\").bold()\n );\n println!();\n for context_line in context {\n let formatted_line = if context_line.important {\n format!(\"{}\", style(context_line.line).bold())\n } else {\n context_line.line.to_string()\n };\n\n println!(\n \"{:>2} {} {}\",\n style(context_line.number).blue().bold(),\n style(\"|\").blue(),\n formatted_line\n );\n }\n\n false\n}\n\nfn separator() -> console::StyledObject<&'static str> {\n style(\"====================\").bold()\n}\n","traces":[{"line":10,"address":[4236464,4235726,4235680,4236543,4236123,4236080],"length":1,"stats":{"Line":0},"fn_name":"verify<core::slice::Iter<rustlings::exercise::Exercise>>"},{"line":14,"address":[4236106,4236179,4236628,4236006,4235709,4236894,4236483,4236666,4236211,4235814,4236558,4236403,4235743,4235782,4236140],"length":1,"stats":{"Line":0},"fn_name":null},{"line":15,"address":[4236339,4235942,4236365,4236818,4236291,4236758,4235894,4235968,4236850],"length":1,"stats":{"Line":0},"fn_name":null},{"line":16,"address":[4235896,4236700,4235842,4236760,4236293,4236239],"length":1,"stats":{"Line":0},"fn_name":null},{"line":17,"address":[4235944,4236820,4236341],"length":1,"stats":{"Line":0},"fn_name":null},{"line":18,"address":[4236275,4235878,4235974,4236739,4236856,4236371],"length":1,"stats":{"Line":0},"fn_name":null},{"line":20,"address":[4236863,4236375,4235978],"length":1,"stats":{"Line":0},"fn_name":null},{"line":21,"address":[4236899,4236408,4236011],"length":1,"stats":{"Line":0},"fn_name":null},{"line":24,"address":[4236435,4236929,4236038],"length":1,"stats":{"Line":0},"fn_name":null},{"line":33,"address":[4382704],"length":1,"stats":{"Line":0},"fn_name":"test"},{"line":34,"address":[4382832,4382722,4382808],"length":1,"stats":{"Line":0},"fn_name":null},{"line":35,"address":[4382801],"length":1,"stats":{"Line":0},"fn_name":null},{"line":39,"address":[4382848,4382887],"length":1,"stats":{"Line":0},"fn_name":"compile_only"},{"line":40,"address":[4382863],"length":1,"stats":{"Line":0},"fn_name":null},{"line":41,"address":[4383078,4382902],"length":1,"stats":{"Line":0},"fn_name":null},{"line":42,"address":[4383241],"length":1,"stats":{"Line":0},"fn_name":null},{"line":44,"address":[4383471,4383420,4383265],"length":1,"stats":{"Line":0},"fn_name":null},{"line":45,"address":[4383473],"length":1,"stats":{"Line":0},"fn_name":null},{"line":47,"address":[4383492,4384299],"length":1,"stats":{"Line":0},"fn_name":null},{"line":48,"address":[4384228],"length":1,"stats":{"Line":0},"fn_name":null},{"line":52,"address":[4384464,4384535],"length":1,"stats":{"Line":0},"fn_name":"compile_and_run_interactively"},{"line":53,"address":[4384479],"length":1,"stats":{"Line":0},"fn_name":null},{"line":54,"address":[4384726,4384550],"length":1,"stats":{"Line":0},"fn_name":null},{"line":55,"address":[4384889],"length":1,"stats":{"Line":0},"fn_name":null},{"line":57,"address":[4384913,4385133,4385161,4385220],"length":1,"stats":{"Line":0},"fn_name":null},{"line":59,"address":[4385050,4385248],"length":1,"stats":{"Line":0},"fn_name":null},{"line":60,"address":[4385493],"length":1,"stats":{"Line":0},"fn_name":null},{"line":61,"address":[4385516],"length":1,"stats":{"Line":0},"fn_name":null},{"line":63,"address":[4385696],"length":1,"stats":{"Line":0},"fn_name":null},{"line":64,"address":[4385698,4385535],"length":1,"stats":{"Line":0},"fn_name":null},{"line":65,"address":[4385554],"length":1,"stats":{"Line":0},"fn_name":null},{"line":66,"address":[4385610,4385988,4385904,4387773],"length":1,"stats":{"Line":0},"fn_name":null},{"line":67,"address":[4386609],"length":1,"stats":{"Line":0},"fn_name":null},{"line":68,"address":[4386833,4386771],"length":1,"stats":{"Line":0},"fn_name":null},{"line":72,"address":[4386846,4387879,4385810],"length":1,"stats":{"Line":0},"fn_name":null},{"line":74,"address":[4387509],"length":1,"stats":{"Line":0},"fn_name":null},{"line":79,"address":[4388333,4388240],"length":1,"stats":{"Line":0},"fn_name":"compile_and_test"},{"line":82,"address":[4388278],"length":1,"stats":{"Line":0},"fn_name":null},{"line":83,"address":[4388348,4388524],"length":1,"stats":{"Line":0},"fn_name":null},{"line":84,"address":[4388687],"length":1,"stats":{"Line":0},"fn_name":null},{"line":86,"address":[4388711,4388871,4388956,4388899],"length":1,"stats":{"Line":0},"fn_name":null},{"line":87,"address":[4388976,4388864],"length":1,"stats":{"Line":0},"fn_name":null},{"line":88,"address":[4388992],"length":1,"stats":{"Line":0},"fn_name":null},{"line":90,"address":[4389172,4390340,4391217],"length":1,"stats":{"Line":0},"fn_name":null},{"line":91,"address":[4389174,4389011],"length":1,"stats":{"Line":0},"fn_name":null},{"line":92,"address":[4389228,4389437],"length":1,"stats":{"Line":0},"fn_name":null},{"line":93,"address":[4389418,4389239],"length":1,"stats":{"Line":0},"fn_name":null},{"line":95,"address":[4391352,4389439],"length":1,"stats":{"Line":0},"fn_name":null},{"line":96,"address":[4390243,4390271],"length":1,"stats":{"Line":0},"fn_name":null},{"line":97,"address":[4390273],"length":1,"stats":{"Line":0},"fn_name":null},{"line":102,"address":[4390333,4389030,4389400],"length":1,"stats":{"Line":0},"fn_name":null},{"line":103,"address":[4389101,4390353,4391394,4390437],"length":1,"stats":{"Line":0},"fn_name":null},{"line":107,"address":[4391034],"length":1,"stats":{"Line":0},"fn_name":null},{"line":108,"address":[4391194],"length":1,"stats":{"Line":0},"fn_name":null},{"line":115,"address":[4391908,4391744],"length":1,"stats":{"Line":0},"fn_name":"compile"},{"line":119,"address":[4391764],"length":1,"stats":{"Line":0},"fn_name":null},{"line":121,"address":[4391903,4392858,4391877],"length":1,"stats":{"Line":0},"fn_name":null},{"line":122,"address":[4391798,4391879],"length":1,"stats":{"Line":0},"fn_name":null},{"line":123,"address":[4391813],"length":1,"stats":{"Line":0},"fn_name":null},{"line":124,"address":[4391861],"length":1,"stats":{"Line":0},"fn_name":null},{"line":125,"address":[4391935,4392014,4392860],"length":1,"stats":{"Line":0},"fn_name":null},{"line":129,"address":[4392671],"length":1,"stats":{"Line":0},"fn_name":null},{"line":130,"address":[4392831],"length":1,"stats":{"Line":0},"fn_name":null},{"line":135,"address":[4393024,4393124],"length":1,"stats":{"Line":0},"fn_name":"prompt_for_completion"},{"line":136,"address":[4393293,4393039],"length":1,"stats":{"Line":0},"fn_name":null},{"line":137,"address":[4393139,4393295],"length":1,"stats":{"Line":0},"fn_name":null},{"line":138,"address":[4393166],"length":1,"stats":{"Line":0},"fn_name":null},{"line":141,"address":[4393447,4393416],"length":1,"stats":{"Line":0},"fn_name":null},{"line":142,"address":[4393246,4393427],"length":1,"stats":{"Line":0},"fn_name":null},{"line":143,"address":[4393456],"length":1,"stats":{"Line":0},"fn_name":null},{"line":144,"address":[4393396],"length":1,"stats":{"Line":0},"fn_name":null},{"line":147,"address":[4393476],"length":1,"stats":{"Line":0},"fn_name":null},{"line":148,"address":[4393534],"length":1,"stats":{"Line":0},"fn_name":null},{"line":149,"address":[4393714],"length":1,"stats":{"Line":0},"fn_name":null},{"line":151,"address":[4394622,4393784],"length":1,"stats":{"Line":0},"fn_name":null},{"line":152,"address":[4393846],"length":1,"stats":{"Line":0},"fn_name":null},{"line":153,"address":[4393923],"length":1,"stats":{"Line":0},"fn_name":null},{"line":154,"address":[4394144],"length":1,"stats":{"Line":0},"fn_name":null},{"line":155,"address":[4394324],"length":1,"stats":{"Line":0},"fn_name":null},{"line":156,"address":[4394545],"length":1,"stats":{"Line":0},"fn_name":null},{"line":159,"address":[4394624],"length":1,"stats":{"Line":0},"fn_name":null},{"line":160,"address":[4394758],"length":1,"stats":{"Line":0},"fn_name":null},{"line":162,"address":[4394689],"length":1,"stats":{"Line":0},"fn_name":null},{"line":164,"address":[4394941],"length":1,"stats":{"Line":0},"fn_name":null},{"line":165,"address":[4396754,4395167,4394999],"length":1,"stats":{"Line":0},"fn_name":null},{"line":166,"address":[4395415,4395853],"length":1,"stats":{"Line":0},"fn_name":null},{"line":167,"address":[4395479],"length":1,"stats":{"Line":0},"fn_name":null},{"line":169,"address":[4395469],"length":1,"stats":{"Line":0},"fn_name":null},{"line":172,"address":[4395987,4396033],"length":1,"stats":{"Line":0},"fn_name":null},{"line":174,"address":[4395953,4395864],"length":1,"stats":{"Line":0},"fn_name":null},{"line":175,"address":[4395960,4396018],"length":1,"stats":{"Line":0},"fn_name":null},{"line":180,"address":[4396503],"length":1,"stats":{"Line":0},"fn_name":null},{"line":183,"address":[4397104],"length":1,"stats":{"Line":0},"fn_name":"separator"}],"covered":0,"coverable":93},{"path":["/","usr","src","rustlings","tests","integration_tests.rs"],"content":"use assert_cmd::prelude::*;\nuse glob::glob;\nuse predicates::boolean::PredicateBooleanExt;\nuse std::fs::File;\nuse std::io::Read;\nuse std::process::Command;\n\n#[test]\nfn runs_without_arguments() {\n let mut cmd = Command::cargo_bin(\"rustlings\").unwrap();\n cmd.assert().success();\n}\n\n#[test]\nfn fails_when_in_wrong_dir() {\n Command::cargo_bin(\"rustlings\")\n .unwrap()\n .current_dir(\"tests/\")\n .assert()\n .code(1);\n}\n\n#[test]\nfn verify_all_success() {\n Command::cargo_bin(\"rustlings\")\n .unwrap()\n .arg(\"v\")\n .current_dir(\"tests/fixture/success\")\n .assert()\n .success();\n}\n\n#[test]\nfn verify_fails_if_some_fails() {\n Command::cargo_bin(\"rustlings\")\n .unwrap()\n .arg(\"v\")\n .current_dir(\"tests/fixture/failure\")\n .assert()\n .code(1);\n}\n\n#[test]\nfn run_single_compile_success() {\n Command::cargo_bin(\"rustlings\")\n .unwrap()\n .args(&[\"r\", \"compSuccess\"])\n .current_dir(\"tests/fixture/success/\")\n .assert()\n .success();\n}\n\n#[test]\nfn run_single_compile_failure() {\n Command::cargo_bin(\"rustlings\")\n .unwrap()\n .args(&[\"r\", \"compFailure\"])\n .current_dir(\"tests/fixture/failure/\")\n .assert()\n .code(1);\n}\n\n#[test]\nfn run_single_test_success() {\n Command::cargo_bin(\"rustlings\")\n .unwrap()\n .args(&[\"r\", \"testSuccess\"])\n .current_dir(\"tests/fixture/success/\")\n .assert()\n .success();\n}\n\n#[test]\nfn run_single_test_failure() {\n Command::cargo_bin(\"rustlings\")\n .unwrap()\n .args(&[\"r\", \"testFailure\"])\n .current_dir(\"tests/fixture/failure/\")\n .assert()\n .code(1);\n}\n\n#[test]\nfn run_single_test_not_passed() {\n Command::cargo_bin(\"rustlings\")\n .unwrap()\n .args(&[\"r\", \"testNotPassed.rs\"])\n .current_dir(\"tests/fixture/failure/\")\n .assert()\n .code(1);\n}\n\n#[test]\nfn run_single_test_no_filename() {\n Command::cargo_bin(\"rustlings\")\n .unwrap()\n .arg(\"r\")\n .current_dir(\"tests/fixture/\")\n .assert()\n .code(1);\n}\n\n#[test]\nfn run_single_test_no_exercise() {\n Command::cargo_bin(\"rustlings\")\n .unwrap()\n .args(&[\"r\", \"compNoExercise.rs\"])\n .current_dir(\"tests/fixture/failure\")\n .assert()\n .code(1);\n}\n\n#[test]\nfn get_hint_for_single_test() {\n Command::cargo_bin(\"rustlings\")\n .unwrap()\n .args(&[\"h\", \"testFailure\"])\n .current_dir(\"tests/fixture/failure\")\n .assert()\n .code(0)\n .stdout(\"Hello!\\n\");\n}\n\n#[test]\nfn all_exercises_require_confirmation() {\n for exercise in glob(\"exercises/**/*.rs\").unwrap() {\n let path = exercise.unwrap();\n let source = {\n let mut file = File::open(&path).unwrap();\n let mut s = String::new();\n file.read_to_string(&mut s).unwrap();\n s\n };\n source.matches(\"// I AM NOT DONE\").next().expect(&format!(\n \"There should be an `I AM NOT DONE` annotation in {:?}\",\n path\n ));\n }\n}\n\n#[test]\nfn run_compile_exercise_does_not_prompt() {\n Command::cargo_bin(\"rustlings\")\n .unwrap()\n .args(&[\"r\", \"pending_exercise\"])\n .current_dir(\"tests/fixture/state\")\n .assert()\n .code(0)\n .stdout(predicates::str::contains(\"I AM NOT DONE\").not());\n}\n\n#[test]\nfn run_test_exercise_does_not_prompt() {\n Command::cargo_bin(\"rustlings\")\n .unwrap()\n .args(&[\"r\", \"pending_test_exercise\"])\n .current_dir(\"tests/fixture/state\")\n .assert()\n .code(0)\n .stdout(predicates::str::contains(\"I AM NOT DONE\").not());\n}\n\n#[test]\nfn run_single_test_success_with_output() {\n Command::cargo_bin(\"rustlings\")\n .unwrap()\n .args(&[\"--nocapture\", \"r\", \"testSuccess\"])\n .current_dir(\"tests/fixture/success/\")\n .assert()\n .code(0)\n .stdout(predicates::str::contains(\"THIS TEST TOO SHALL PAS\"));\n}\n\n#[test]\nfn run_single_test_success_without_output() {\n Command::cargo_bin(\"rustlings\")\n .unwrap()\n .args(&[\"r\", \"testSuccess\"])\n .current_dir(\"tests/fixture/success/\")\n .assert()\n .code(0)\n .stdout(predicates::str::contains(\"THIS TEST TOO SHALL PAS\").not());\n}","traces":[{"line":9,"address":[4231184,4231221],"length":1,"stats":{"Line":3},"fn_name":"runs_without_arguments"},{"line":10,"address":[4231198,4231243],"length":1,"stats":{"Line":2},"fn_name":null},{"line":11,"address":[4231322,4231262],"length":1,"stats":{"Line":2},"fn_name":null},{"line":15,"address":[4231376,4231413],"length":1,"stats":{"Line":3},"fn_name":"fails_when_in_wrong_dir"},{"line":24,"address":[4231653,4231616],"length":1,"stats":{"Line":3},"fn_name":"verify_all_success"},{"line":34,"address":[4231888,4231925],"length":1,"stats":{"Line":3},"fn_name":"verify_fails_if_some_fails"},{"line":44,"address":[4232160,4232197],"length":1,"stats":{"Line":3},"fn_name":"run_single_compile_success"},{"line":47,"address":[4232243],"length":1,"stats":{"Line":1},"fn_name":null},{"line":54,"address":[4228549,4228544],"length":1,"stats":{"Line":3},"fn_name":"{{closure}}"},{"line":57,"address":[4232499],"length":1,"stats":{"Line":1},"fn_name":null},{"line":64,"address":[4228576,4228581],"length":1,"stats":{"Line":3},"fn_name":"{{closure}}"},{"line":67,"address":[4232755],"length":1,"stats":{"Line":1},"fn_name":null},{"line":74,"address":[4228613,4228608],"length":1,"stats":{"Line":3},"fn_name":"{{closure}}"},{"line":77,"address":[4233011],"length":1,"stats":{"Line":1},"fn_name":null},{"line":84,"address":[4228640,4228645],"length":1,"stats":{"Line":3},"fn_name":"{{closure}}"},{"line":87,"address":[4233267],"length":1,"stats":{"Line":1},"fn_name":null},{"line":94,"address":[4228672,4228677],"length":1,"stats":{"Line":3},"fn_name":"{{closure}}"},{"line":104,"address":[4228709,4228704],"length":1,"stats":{"Line":3},"fn_name":"{{closure}}"},{"line":107,"address":[4233795],"length":1,"stats":{"Line":1},"fn_name":null},{"line":114,"address":[4228736,4228741],"length":1,"stats":{"Line":3},"fn_name":"{{closure}}"},{"line":117,"address":[4234051],"length":1,"stats":{"Line":1},"fn_name":null},{"line":125,"address":[4228773,4228768],"length":1,"stats":{"Line":3},"fn_name":"{{closure}}"},{"line":126,"address":[4234270,4234324,4235516,4234441],"length":1,"stats":{"Line":4},"fn_name":null},{"line":127,"address":[4234699],"length":1,"stats":{"Line":1},"fn_name":null},{"line":129,"address":[4234820,4234876],"length":1,"stats":{"Line":2},"fn_name":null},{"line":130,"address":[4234891],"length":1,"stats":{"Line":1},"fn_name":null},{"line":131,"address":[4234945,4234922],"length":1,"stats":{"Line":2},"fn_name":null},{"line":132,"address":[4234983],"length":1,"stats":{"Line":1},"fn_name":null},{"line":134,"address":[4235124,4235166,4235042],"length":1,"stats":{"Line":3},"fn_name":null},{"line":135,"address":[4235151],"length":1,"stats":{"Line":1},"fn_name":null},{"line":142,"address":[4228805,4228800],"length":1,"stats":{"Line":3},"fn_name":"{{closure}}"},{"line":145,"address":[4235787],"length":1,"stats":{"Line":1},"fn_name":null},{"line":149,"address":[4235913,4235814,4235996,4236042],"length":1,"stats":{"Line":2},"fn_name":null},{"line":153,"address":[4228832,4228837],"length":1,"stats":{"Line":3},"fn_name":"{{closure}}"},{"line":156,"address":[4236219],"length":1,"stats":{"Line":1},"fn_name":null},{"line":160,"address":[4236474,4236246,4236345,4236428],"length":1,"stats":{"Line":2},"fn_name":null},{"line":164,"address":[4228864,4228869],"length":1,"stats":{"Line":3},"fn_name":"{{closure}}"},{"line":167,"address":[4236651],"length":1,"stats":{"Line":1},"fn_name":null},{"line":171,"address":[4236835,4236678,4236775,4236881],"length":1,"stats":{"Line":2},"fn_name":null},{"line":175,"address":[4228901,4228896],"length":1,"stats":{"Line":3},"fn_name":"{{closure}}"},{"line":178,"address":[4237051],"length":1,"stats":{"Line":1},"fn_name":null},{"line":182,"address":[4237078,4237177,4237260,4237306],"length":1,"stats":{"Line":2},"fn_name":null}],"covered":42,"coverable":42}]}