334: test: expect reuse field X changes but fn depends on field Y r=nikomatsakis a=XFFXFF

ref: #328 

Co-authored-by: XFFXFF <1247714429@qq.com>
This commit is contained in:
bors[bot] 2022-08-09 05:16:40 +00:00 committed by GitHub
commit bd2992a621
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 194 additions and 0 deletions

View file

@ -0,0 +1,109 @@
//! Test that if field X of a tracked struct changes but not field Y,
//! functions that depend on X re-execute, but those depending only on Y do not
//! compiles and executes successfully.
#![allow(dead_code)]
use salsa_2022_tests::{HasLogger, Logger};
use expect_test::expect;
#[salsa::jar(db = Db)]
struct Jar(
MyInput,
MyTracked,
final_result_deponds_on_x,
final_result_deponds_on_y,
intermediate_result,
);
trait Db: salsa::DbWithJar<Jar> + HasLogger {}
#[salsa::input(jar = Jar)]
struct MyInput {
field: u32,
}
#[salsa::tracked(jar = Jar)]
fn final_result_deponds_on_x(db: &dyn Db, input: MyInput) -> u32 {
db.push_log(format!("final_result_deponds_on_x({:?})", input));
intermediate_result(db, input).x(db) * 2
}
#[salsa::tracked(jar = Jar)]
fn final_result_deponds_on_y(db: &dyn Db, input: MyInput) -> u32 {
db.push_log(format!("final_result_deponds_on_y({:?})", input));
intermediate_result(db, input).y(db) * 2
}
#[salsa::tracked(jar = Jar)]
struct MyTracked {
x: u32,
y: u32,
}
#[salsa::tracked(jar = Jar)]
fn intermediate_result(db: &dyn Db, input: MyInput) -> MyTracked {
MyTracked::new(db, (input.field(db) + 1) / 2, input.field(db) / 2)
}
#[salsa::db(Jar)]
#[derive(Default)]
struct Database {
storage: salsa::Storage<Self>,
logger: Logger,
}
impl salsa::Database for Database {
fn salsa_runtime(&self) -> &salsa::Runtime {
self.storage.runtime()
}
}
impl Db for Database {}
impl HasLogger for Database {
fn logger(&self) -> &Logger {
&self.logger
}
}
#[test]
fn execute() {
// x = (input.field + 1) / 2
// y = input.field / 2
// final_result_deponds_on_x = x * 2 = (input.field + 1) / 2 * 2
// final_result_deponds_on_y = y * 2 = input.field / 2 * 2
let mut db = Database::default();
// intermediate results:
// x = (22 + 1) / 2 = 11
// y = 22 / 2 = 11
let input = MyInput::new(&mut db, 22);
assert_eq!(final_result_deponds_on_x(&db, input), 22);
db.assert_logs(expect![[r#"
[
"final_result_deponds_on_x(MyInput(Id { value: 1 }))",
]"#]]);
assert_eq!(final_result_deponds_on_y(&db, input), 22);
db.assert_logs(expect![[r#"
[
"final_result_deponds_on_y(MyInput(Id { value: 1 }))",
]"#]]);
input.set_field(&mut db, 23);
// x = (23 + 1) / 2 = 12
// Intermediate result x changes, so final result depends on x
// needs to be recomputed;
assert_eq!(final_result_deponds_on_x(&db, input), 24);
db.assert_logs(expect![[r#"
[
"final_result_deponds_on_x(MyInput(Id { value: 1 }))",
]"#]]);
// y = 23 / 2 = 11
// Intermediate result y is the same, so final result depends on y
// does not need to be recomputed;
assert_eq!(final_result_deponds_on_y(&db, input), 22);
db.assert_logs(expect!["[]"]);
}

View file

@ -0,0 +1,85 @@
//! Test that if field X of an input changes but not field Y,
//! functions that depend on X re-execute, but those depending only on Y do not
//! compiles and executes successfully.
#![allow(dead_code)]
use salsa_2022_tests::{HasLogger, Logger};
use expect_test::expect;
#[salsa::jar(db = Db)]
struct Jar(MyInput, result_deponds_on_x, result_deponds_on_y);
trait Db: salsa::DbWithJar<Jar> + HasLogger {}
#[salsa::input(jar = Jar)]
struct MyInput {
x: u32,
y: u32,
}
#[salsa::tracked(jar = Jar)]
fn result_deponds_on_x(db: &dyn Db, input: MyInput) -> u32 {
db.push_log(format!("result_deponds_on_x({:?})", input));
input.x(db) + 1
}
#[salsa::tracked(jar = Jar)]
fn result_deponds_on_y(db: &dyn Db, input: MyInput) -> u32 {
db.push_log(format!("result_deponds_on_y({:?})", input));
input.y(db) - 1
}
#[salsa::db(Jar)]
#[derive(Default)]
struct Database {
storage: salsa::Storage<Self>,
logger: Logger,
}
impl salsa::Database for Database {
fn salsa_runtime(&self) -> &salsa::Runtime {
self.storage.runtime()
}
}
impl Db for Database {}
impl HasLogger for Database {
fn logger(&self) -> &Logger {
&self.logger
}
}
#[test]
fn execute() {
// result_deponds_on_x = x + 1
// result_deponds_on_y = y - 1
let mut db = Database::default();
let input = MyInput::new(&mut db, 22, 33);
assert_eq!(result_deponds_on_x(&db, input), 23);
db.assert_logs(expect![[r#"
[
"result_deponds_on_x(MyInput(Id { value: 1 }))",
]"#]]);
assert_eq!(result_deponds_on_y(&db, input), 32);
db.assert_logs(expect![[r#"
[
"result_deponds_on_y(MyInput(Id { value: 1 }))",
]"#]]);
input.set_x(&mut db, 23);
// input x changes, so result depends on x needs to be recomputed;
assert_eq!(result_deponds_on_x(&db, input), 24);
db.assert_logs(expect![[r#"
[
"result_deponds_on_x(MyInput(Id { value: 1 }))",
]"#]]);
// input y is the same, so result depends on y
// does not need to be recomputed;
assert_eq!(result_deponds_on_y(&db, input), 32);
db.assert_logs(expect!["[]"]);
}