elaborate a bit more on the GC tests

This commit is contained in:
Niko Matsakis 2019-03-22 05:18:32 -04:00
parent c5795a3e5c
commit 791ec3065c

View file

@ -1,13 +1,21 @@
use crate::db;
use salsa::{Database, SweepStrategy};
/// Query group for tests for how interned keys interact with GC.
#[salsa::query_group(Intern)]
pub(crate) trait InternDatabase {
/// A dummy input that can be used to trigger a new revision.
#[salsa::input]
fn dummy(&self) -> ();
/// Underlying interning query.
#[salsa::interned]
fn intern_str(&self, x: &'static str) -> u32;
/// This just executes the intern query and returns the result.
fn repeat_intern1(&self, x: &'static str) -> u32;
/// Same as `repeat_intern1`. =)
fn repeat_intern2(&self, x: &'static str) -> u32;
}
@ -55,3 +63,46 @@ fn discard_during_same_revision() {
assert_eq!(foo1a, foo1b);
assert_eq!(foo1b, foo2);
}
/// This test highlights the difference between *interned queries* and
/// other non-input queries -- in particular, their results are not
/// *deterministic*. Therefore, we cannot GC values that were created
/// in the current revision; that might cause us to re-execute the
/// query twice on the same key during the same revision, which could
/// yield different results each time, wreaking havoc. This test
/// exercises precisely that scenario.
#[test]
fn discard_outdated() {
let mut db = db::DatabaseImpl::default();
let foo_from_rev0 = db.repeat_intern1("foo");
let bar_from_rev0 = db.repeat_intern1("bar");
// Trigger a new revision.
db.set_dummy(());
// In this revision, we use "bar".
let bar_from_rev1 = db.repeat_intern1("bar");
// This should collect "foo".
db.sweep_all(SweepStrategy::discard_outdated());
// This should be the same as before the GC, as bar
// is not outdated.
let bar2_from_rev1 = db.repeat_intern1("bar");
// This should re-use the index of "foo".
let baz_from_rev1 = db.repeat_intern1("baz");
// This should assign the next index to "foo".
let foo_from_rev1 = db.repeat_intern1("foo");
assert_eq!(bar_from_rev0, bar_from_rev1);
assert_eq!(bar_from_rev0, bar2_from_rev1);
assert_eq!(foo_from_rev0, baz_from_rev1);
assert_ne!(foo_from_rev0, foo_from_rev1);
assert_ne!(foo_from_rev1, bar_from_rev1);
assert_ne!(foo_from_rev1, baz_from_rev1);
}