Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/query-group-macro/tests/cycle.rs')
| -rw-r--r-- | crates/query-group-macro/tests/cycle.rs | 265 |
1 files changed, 0 insertions, 265 deletions
diff --git a/crates/query-group-macro/tests/cycle.rs b/crates/query-group-macro/tests/cycle.rs deleted file mode 100644 index 8d195cbd8d..0000000000 --- a/crates/query-group-macro/tests/cycle.rs +++ /dev/null @@ -1,265 +0,0 @@ -use std::panic::UnwindSafe; - -use expect_test::expect; -use query_group_macro::query_group; -use salsa::Setter; - -/// The queries A, B, and C in `Database` can be configured -/// to invoke one another in arbitrary ways using this -/// enum. -#[derive(Debug, Copy, Clone, PartialEq, Eq)] -enum CycleQuery { - None, - A, - B, - C, - AthenC, -} - -#[salsa::input] -struct ABC { - a: CycleQuery, - b: CycleQuery, - c: CycleQuery, -} - -impl CycleQuery { - fn invoke(self, db: &dyn CycleDatabase, abc: ABC) -> Result<(), Error> { - match self { - CycleQuery::A => db.cycle_a(abc), - CycleQuery::B => db.cycle_b(abc), - CycleQuery::C => db.cycle_c(abc), - CycleQuery::AthenC => { - let _ = db.cycle_a(abc); - db.cycle_c(abc) - } - CycleQuery::None => Ok(()), - } - } -} - -#[salsa::input] -struct MyInput {} - -#[salsa::tracked] -fn memoized_a(db: &dyn CycleDatabase, input: MyInput) { - memoized_b(db, input) -} - -#[salsa::tracked] -fn memoized_b(db: &dyn CycleDatabase, input: MyInput) { - memoized_a(db, input) -} - -#[salsa::tracked] -fn volatile_a(db: &dyn CycleDatabase, input: MyInput) { - db.report_untracked_read(); - volatile_b(db, input) -} - -#[salsa::tracked] -fn volatile_b(db: &dyn CycleDatabase, input: MyInput) { - db.report_untracked_read(); - volatile_a(db, input) -} - -#[track_caller] -fn extract_cycle(f: impl FnOnce() + UnwindSafe) -> salsa::Cycle { - let v = std::panic::catch_unwind(f); - if let Err(d) = &v { - if let Some(cycle) = d.downcast_ref::<salsa::Cycle>() { - return cycle.clone(); - } - } - panic!("unexpected value: {:?}", v) -} - -#[derive(PartialEq, Eq, Hash, Clone, Debug)] -struct Error { - cycle: Vec<String>, -} - -#[query_group] -trait CycleDatabase: salsa::Database { - #[salsa::cycle(recover_a)] - fn cycle_a(&self, abc: ABC) -> Result<(), Error>; - - #[salsa::cycle(recover_b)] - fn cycle_b(&self, abc: ABC) -> Result<(), Error>; - - fn cycle_c(&self, abc: ABC) -> Result<(), Error>; -} - -fn cycle_a(db: &dyn CycleDatabase, abc: ABC) -> Result<(), Error> { - abc.a(db).invoke(db, abc) -} - -fn recover_a(_db: &dyn CycleDatabase, cycle: &salsa::Cycle, _abc: ABC) -> Result<(), Error> { - Err(Error { cycle: cycle.participant_keys().map(|k| format!("{k:?}")).collect() }) -} - -fn cycle_b(db: &dyn CycleDatabase, abc: ABC) -> Result<(), Error> { - abc.b(db).invoke(db, abc) -} - -fn recover_b(_db: &dyn CycleDatabase, cycle: &salsa::Cycle, _abc: ABC) -> Result<(), Error> { - Err(Error { cycle: cycle.participant_keys().map(|k| format!("{k:?}")).collect() }) -} - -fn cycle_c(db: &dyn CycleDatabase, abc: ABC) -> Result<(), Error> { - abc.c(db).invoke(db, abc) -} - -#[test] -fn cycle_memoized() { - let db = salsa::DatabaseImpl::new(); - - let input = MyInput::new(&db); - let cycle = extract_cycle(|| memoized_a(&db, input)); - let expected = expect![[r#" - [ - DatabaseKeyIndex( - IngredientIndex( - 1, - ), - Id(0), - ), - DatabaseKeyIndex( - IngredientIndex( - 2, - ), - Id(0), - ), - ] - "#]]; - expected.assert_debug_eq(&cycle.all_participants(&db)); -} - -#[test] -fn inner_cycle() { - // A --> B <-- C - // ^ | - // +-----+ - let db = salsa::DatabaseImpl::new(); - - let abc = ABC::new(&db, CycleQuery::B, CycleQuery::A, CycleQuery::B); - let err = db.cycle_c(abc); - assert!(err.is_err()); - let expected = expect![[r#" - [ - "cycle_a_shim(Id(0))", - "cycle_b_shim(Id(0))", - ] - "#]]; - expected.assert_debug_eq(&err.unwrap_err().cycle); -} - -#[test] -fn cycle_revalidate() { - // A --> B - // ^ | - // +-----+ - let mut db = salsa::DatabaseImpl::new(); - let abc = ABC::new(&db, CycleQuery::B, CycleQuery::A, CycleQuery::None); - assert!(db.cycle_a(abc).is_err()); - abc.set_b(&mut db).to(CycleQuery::A); // same value as default - assert!(db.cycle_a(abc).is_err()); -} - -#[test] -fn cycle_recovery_unchanged_twice() { - // A --> B - // ^ | - // +-----+ - let mut db = salsa::DatabaseImpl::new(); - let abc = ABC::new(&db, CycleQuery::B, CycleQuery::A, CycleQuery::None); - assert!(db.cycle_a(abc).is_err()); - - abc.set_c(&mut db).to(CycleQuery::A); // force new revision - assert!(db.cycle_a(abc).is_err()); -} - -#[test] -fn cycle_appears() { - let mut db = salsa::DatabaseImpl::new(); - // A --> B - let abc = ABC::new(&db, CycleQuery::B, CycleQuery::None, CycleQuery::None); - assert!(db.cycle_a(abc).is_ok()); - - // A --> B - // ^ | - // +-----+ - abc.set_b(&mut db).to(CycleQuery::A); - assert!(db.cycle_a(abc).is_err()); -} - -#[test] -fn cycle_disappears() { - let mut db = salsa::DatabaseImpl::new(); - - // A --> B - // ^ | - // +-----+ - let abc = ABC::new(&db, CycleQuery::B, CycleQuery::A, CycleQuery::None); - assert!(db.cycle_a(abc).is_err()); - - // A --> B - abc.set_b(&mut db).to(CycleQuery::None); - assert!(db.cycle_a(abc).is_ok()); -} - -#[test] -fn cycle_multiple() { - // No matter whether we start from A or B, we get the same set of participants: - let db = salsa::DatabaseImpl::new(); - - // Configuration: - // - // A --> B <-- C - // ^ | ^ - // +-----+ | - // | | - // +-----+ - // - // Here, conceptually, B encounters a cycle with A and then - // recovers. - let abc = ABC::new(&db, CycleQuery::B, CycleQuery::AthenC, CycleQuery::A); - - let c = db.cycle_c(abc); - let b = db.cycle_b(abc); - let a = db.cycle_a(abc); - let expected = expect![[r#" - ( - [ - "cycle_a_shim(Id(0))", - "cycle_b_shim(Id(0))", - ], - [ - "cycle_a_shim(Id(0))", - "cycle_b_shim(Id(0))", - ], - [ - "cycle_a_shim(Id(0))", - "cycle_b_shim(Id(0))", - ], - ) - "#]]; - expected.assert_debug_eq(&(c.unwrap_err().cycle, b.unwrap_err().cycle, a.unwrap_err().cycle)); -} - -#[test] -fn cycle_mixed_1() { - let db = salsa::DatabaseImpl::new(); - // A --> B <-- C - // | ^ - // +-----+ - let abc = ABC::new(&db, CycleQuery::B, CycleQuery::C, CycleQuery::B); - - let expected = expect![[r#" - [ - "cycle_b_shim(Id(0))", - "cycle_c_shim(Id(0))", - ] - "#]]; - expected.assert_debug_eq(&db.cycle_c(abc).unwrap_err().cycle); -} |