diff --git a/CHANGELOG.md b/CHANGELOG.md index a07a2f08..8dbec477 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ All notable changes to insta and cargo-insta are documented here. - Added support for rendering some invisibles in diffs. This now also should make sure that ANSI sequences in strings are no longer screwing up the terminal output. (#308) +- Prevent inline snapshots to be used in loops. (#307) ## 1.21.2 diff --git a/src/runtime.rs b/src/runtime.rs index 19f3e6ad..6f4610b2 100644 --- a/src/runtime.rs +++ b/src/runtime.rs @@ -1,5 +1,5 @@ use std::borrow::Cow; -use std::collections::BTreeMap; +use std::collections::{BTreeMap, BTreeSet}; use std::error::Error; use std::fs; use std::io::Write; @@ -21,6 +21,8 @@ lazy_static::lazy_static! { Mutex::new(BTreeMap::new()); static ref TEST_NAME_CLASH_DETECTION: Mutex> = Mutex::new(BTreeMap::new()); + static ref INLINE_DUPLICATES: Mutex> = + Mutex::new(BTreeSet::new()); } // This macro is basically eprintln but without being captured and @@ -243,6 +245,7 @@ impl<'a> SnapshotAssertionContext<'a> { snapshot_file = Some(file); } ReferenceValue::Inline(contents) => { + prevent_inline_duplicate(function_name, assertion_file, assertion_line); snapshot_name = detect_snapshot_name(function_name, module_path, true, is_doctest) .ok() .map(Cow::Owned); @@ -411,6 +414,17 @@ impl<'a> SnapshotAssertionContext<'a> { } } +fn prevent_inline_duplicate(function_name: &str, assertion_file: &str, assertion_line: u32) { + let key = format!("{}|{}|{}", function_name, assertion_file, assertion_line); + let mut set = INLINE_DUPLICATES.lock().unwrap(); + if set.contains(&key) { + // drop the lock so we don't poison it + drop(set); + panic!("Insta does not allow inline snapshot assertions in loops"); + } + set.insert(key); +} + /// This prints the information about the snapshot fn print_snapshot_info(ctx: &SnapshotAssertionContext, new_snapshot: &Snapshot) { match get_output_behavior() { diff --git a/tests/test_inline.rs b/tests/test_inline.rs index e7c5f909..93637681 100644 --- a/tests/test_inline.rs +++ b/tests/test_inline.rs @@ -278,3 +278,11 @@ fn test_compact_json() { ] "###); } + +#[test] +#[should_panic = "Insta does not allow inline snapshot assertions in loops"] +fn test_inline_test_in_loop() { + for i in 0..10 { + assert_snapshot!(i.to_string(), @"0"); + } +}