mirror of
https://github.com/salsa-rs/salsa.git
synced 2025-07-07 21:35:17 +00:00
chore: Use nextest for miri test runs (#758)
This commit is contained in:
parent
2308261d65
commit
1dc24388d1
8 changed files with 55 additions and 64 deletions
9
.github/workflows/test.yml
vendored
9
.github/workflows/test.yml
vendored
|
@ -41,6 +41,7 @@ jobs:
|
|||
with:
|
||||
toolchain: ${{ matrix.rust }}
|
||||
components: rustfmt, clippy
|
||||
- uses: taiki-e/install-action@nextest
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
|
@ -58,7 +59,7 @@ jobs:
|
|||
- name: Clippy
|
||||
run: cargo clippy --workspace --all-features --all-targets -- -D warnings
|
||||
- name: Test
|
||||
run: cargo test --workspace --all-features --all-targets
|
||||
run: cargo nextest run --workspace --all-features --all-targets --no-fail-fast
|
||||
- name: Test docs
|
||||
run: cargo test --workspace --all-features --doc
|
||||
- name: Check (without default features)
|
||||
|
@ -73,6 +74,7 @@ jobs:
|
|||
- name: Install Miri
|
||||
uses: dtolnay/rust-toolchain@miri
|
||||
id: rust-toolchain
|
||||
- uses: taiki-e/install-action@nextest
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
|
@ -89,12 +91,11 @@ jobs:
|
|||
- name: Setup Miri
|
||||
run: cargo miri setup
|
||||
- name: Test with Miri
|
||||
run: cargo miri test --no-fail-fast --all-features
|
||||
run: cargo miri nextest run --all-features --no-fail-fast --tests
|
||||
env:
|
||||
MIRIFLAGS: -Zmiri-disable-isolation -Zmiri-retag-fields
|
||||
- name: Run examples with Miri
|
||||
run: |
|
||||
cargo miri run --example calc
|
||||
run: cargo miri run --example calc
|
||||
|
||||
benchmarks:
|
||||
# https://github.com/CodSpeedHQ/action/issues/126
|
||||
|
|
|
@ -7,6 +7,8 @@ use salsa::{CycleRecoveryAction, Database as Db, Setter};
|
|||
use std::collections::BTreeSet;
|
||||
use std::iter::IntoIterator;
|
||||
|
||||
include!("shims/global_alloc_overwrite.rs");
|
||||
|
||||
/// A Use of a symbol.
|
||||
#[salsa::input]
|
||||
struct Use {
|
||||
|
|
|
@ -108,7 +108,7 @@ impl<'db> CheckExpression<'_, 'db> {
|
|||
fn check_string(
|
||||
source_text: &str,
|
||||
expected_diagnostics: expect_test::Expect,
|
||||
edits: &[(&str, expect_test::Expect, expect_test::Expect)],
|
||||
edits: &[(&str, expect_test::Expect)],
|
||||
) {
|
||||
use salsa::{Database, Setter};
|
||||
|
||||
|
@ -135,11 +135,8 @@ fn check_string(
|
|||
expected_diagnostics.assert_eq(&rendered_diagnostics);
|
||||
});
|
||||
|
||||
// Clear logs
|
||||
db.take_logs();
|
||||
|
||||
// Apply edits and check diagnostics/logs after each one
|
||||
for (new_source_text, expected_diagnostics, expected_logs) in edits {
|
||||
for (new_source_text, expected_diagnostics) in edits {
|
||||
source_program
|
||||
.set_text(&mut db)
|
||||
.to(new_source_text.to_string());
|
||||
|
@ -149,8 +146,6 @@ fn check_string(
|
|||
expected_diagnostics
|
||||
.assert_debug_eq(&type_check_program::accumulated::<Diagnostic>(db, program));
|
||||
});
|
||||
|
||||
expected_logs.assert_debug_eq(&db.take_logs());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -267,12 +262,6 @@ fn fix_bad_variable_in_function() {
|
|||
expect![[r#"
|
||||
[]
|
||||
"#]],
|
||||
expect![[r#"
|
||||
[
|
||||
"Event: Event { thread_id: ThreadId(11), kind: WillExecute { database_key: parse_statements(Id(0)) } }",
|
||||
"Event: Event { thread_id: ThreadId(11), kind: WillExecute { database_key: type_check_function(Id(1800)) } }",
|
||||
]
|
||||
"#]],
|
||||
)],
|
||||
);
|
||||
}
|
||||
|
|
|
@ -126,7 +126,7 @@ mod tests {
|
|||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn pptional_atomic_revision() {
|
||||
fn optional_atomic_revision() {
|
||||
let val = OptionalAtomicRevision::new(Some(Revision::start()));
|
||||
assert_eq!(val.load(), Some(Revision::start()));
|
||||
assert_eq!(val.swap(None), Some(Revision::start()));
|
||||
|
|
|
@ -6,6 +6,7 @@ mod common;
|
|||
use common::{ExecuteValidateLoggerDatabase, LogDatabase};
|
||||
use expect_test::expect;
|
||||
use salsa::{CycleRecoveryAction, Database as Db, DatabaseImpl as DbImpl, Durability, Setter};
|
||||
#[cfg(not(miri))]
|
||||
use test_log::test;
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, salsa::Update)]
|
||||
|
@ -31,12 +32,13 @@ impl Value {
|
|||
/// `max_iterate`, `min_panic`, `max_panic`) for testing cycle behaviors.
|
||||
#[salsa::input]
|
||||
struct Inputs {
|
||||
#[return_ref]
|
||||
inputs: Vec<Input>,
|
||||
}
|
||||
|
||||
impl Inputs {
|
||||
fn values(self, db: &dyn Db) -> impl Iterator<Item = Value> + '_ {
|
||||
self.inputs(db).into_iter().map(|input| input.eval(db))
|
||||
self.inputs(db).iter().map(|input| input.eval(db))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -69,8 +71,8 @@ enum Input {
|
|||
}
|
||||
|
||||
impl Input {
|
||||
fn eval(self, db: &dyn Db) -> Value {
|
||||
match self {
|
||||
fn eval(&self, db: &dyn Db) -> Value {
|
||||
match *self {
|
||||
Self::Value(value) => value,
|
||||
Self::UntrackedRead(value) => {
|
||||
db.report_untracked_read();
|
||||
|
@ -80,30 +82,30 @@ impl Input {
|
|||
Self::MaxIterate(inputs) => max_iterate(db, inputs),
|
||||
Self::MinPanic(inputs) => min_panic(db, inputs),
|
||||
Self::MaxPanic(inputs) => max_panic(db, inputs),
|
||||
Self::Successor(input) => match input.eval(db) {
|
||||
Self::Successor(ref input) => match input.eval(db) {
|
||||
Value::N(num) => Value::N(num + 1),
|
||||
other => other,
|
||||
},
|
||||
Self::SuccessorOrZero(input) => match input.eval(db) {
|
||||
Self::SuccessorOrZero(ref input) => match input.eval(db) {
|
||||
Value::N(num) => Value::N(num + 1),
|
||||
_ => Value::N(0),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn assert(self, db: &dyn Db, expected: Value) {
|
||||
fn assert(&self, db: &dyn Db, expected: Value) {
|
||||
assert_eq!(self.eval(db), expected)
|
||||
}
|
||||
|
||||
fn assert_value(self, db: &dyn Db, expected: u8) {
|
||||
fn assert_value(&self, db: &dyn Db, expected: u8) {
|
||||
self.assert(db, Value::N(expected))
|
||||
}
|
||||
|
||||
fn assert_bounds(self, db: &dyn Db) {
|
||||
fn assert_bounds(&self, db: &dyn Db) {
|
||||
self.assert(db, Value::OutOfBounds)
|
||||
}
|
||||
|
||||
fn assert_count(self, db: &dyn Db) {
|
||||
fn assert_count(&self, db: &dyn Db) {
|
||||
self.assert(db, Value::TooManyIterations)
|
||||
}
|
||||
}
|
||||
|
@ -734,7 +736,7 @@ fn cycle_becomes_non_cycle() {
|
|||
a_in.set_inputs(&mut db).to(vec![b]);
|
||||
b_in.set_inputs(&mut db).to(vec![a.clone()]);
|
||||
|
||||
a.clone().assert_value(&db, 255);
|
||||
a.assert_value(&db, 255);
|
||||
|
||||
b_in.set_inputs(&mut db).to(vec![value(30)]);
|
||||
|
||||
|
@ -758,7 +760,7 @@ fn non_cycle_becomes_cycle() {
|
|||
a_in.set_inputs(&mut db).to(vec![b]);
|
||||
b_in.set_inputs(&mut db).to(vec![value(30)]);
|
||||
|
||||
a.clone().assert_value(&db, 30);
|
||||
a.assert_value(&db, 30);
|
||||
|
||||
b_in.set_inputs(&mut db).to(vec![a.clone()]);
|
||||
|
||||
|
@ -790,7 +792,7 @@ fn nested_double_multiple_revisions() {
|
|||
Input::Successor(Box::new(b.clone())),
|
||||
]);
|
||||
|
||||
a.clone().assert_count(&db);
|
||||
a.assert_count(&db);
|
||||
|
||||
// next revision, we hit max value instead
|
||||
c_in.set_inputs(&mut db).to(vec![
|
||||
|
@ -799,13 +801,13 @@ fn nested_double_multiple_revisions() {
|
|||
Input::Successor(Box::new(b.clone())),
|
||||
]);
|
||||
|
||||
a.clone().assert_bounds(&db);
|
||||
a.assert_bounds(&db);
|
||||
|
||||
// and next revision, we converge
|
||||
c_in.set_inputs(&mut db)
|
||||
.to(vec![value(240), a.clone(), b.clone()]);
|
||||
|
||||
a.clone().assert_value(&db, 240);
|
||||
a.assert_value(&db, 240);
|
||||
|
||||
// one more revision, without relevant changes
|
||||
a_in.set_inputs(&mut db).to(vec![b]);
|
||||
|
@ -838,7 +840,7 @@ fn cycle_durability() {
|
|||
.with_durability(Durability::HIGH)
|
||||
.to(vec![a.clone()]);
|
||||
|
||||
a.clone().assert_value(&db, 255);
|
||||
a.assert_value(&db, 255);
|
||||
|
||||
// next revision, we converge instead
|
||||
a_in.set_inputs(&mut db)
|
||||
|
@ -866,8 +868,8 @@ fn cycle_unchanged() {
|
|||
b_in.set_inputs(&mut db).to(vec![value(60), c]);
|
||||
c_in.set_inputs(&mut db).to(vec![b.clone()]);
|
||||
|
||||
a.clone().assert_value(&db, 59);
|
||||
b.clone().assert_value(&db, 60);
|
||||
a.assert_value(&db, 59);
|
||||
b.assert_value(&db, 60);
|
||||
|
||||
db.assert_logs_len(4);
|
||||
|
||||
|
@ -912,8 +914,8 @@ fn cycle_unchanged_nested() {
|
|||
.to(vec![value(61), b.clone(), e.clone()]);
|
||||
e_in.set_inputs(&mut db).to(vec![d.clone()]);
|
||||
|
||||
a.clone().assert_value(&db, 59);
|
||||
b.clone().assert_value(&db, 60);
|
||||
a.assert_value(&db, 59);
|
||||
b.assert_value(&db, 60);
|
||||
|
||||
db.assert_logs_len(10);
|
||||
|
||||
|
@ -965,8 +967,8 @@ fn cycle_unchanged_nested_intertwined() {
|
|||
.to(vec![value(61), b.clone(), e.clone()]);
|
||||
e_in.set_inputs(&mut db).to(vec![d.clone()]);
|
||||
|
||||
a.clone().assert_value(&db, 59);
|
||||
b.clone().assert_value(&db, 60);
|
||||
a.assert_value(&db, 59);
|
||||
b.assert_value(&db, 60);
|
||||
|
||||
// First time we run this test, don't fetch c/d/e here; this means they won't get marked
|
||||
// `verified_final` in R6 (this revision), which will leave us in the next revision (R7)
|
||||
|
@ -977,9 +979,9 @@ fn cycle_unchanged_nested_intertwined() {
|
|||
// Second time we run this test, fetch everything in R6, to check the behavior of
|
||||
// `maybe_changed_after` with all validated-final memos.
|
||||
if i == 1 {
|
||||
c.clone().assert_value(&db, 60);
|
||||
d.clone().assert_value(&db, 60);
|
||||
e.clone().assert_value(&db, 60);
|
||||
c.assert_value(&db, 60);
|
||||
d.assert_value(&db, 60);
|
||||
e.assert_value(&db, 60);
|
||||
}
|
||||
|
||||
db.assert_logs_len(16 + i);
|
||||
|
|
32
tests/lru.rs
32
tests/lru.rs
|
@ -36,7 +36,7 @@ struct MyInput {
|
|||
field: u32,
|
||||
}
|
||||
|
||||
#[salsa::tracked(lru = 32)]
|
||||
#[salsa::tracked(lru = 8)]
|
||||
fn get_hot_potato(db: &dyn LogDatabase, input: MyInput) -> Arc<HotPotato> {
|
||||
db.push_log(format!("get_hot_potato({:?})", input.field(db)));
|
||||
Arc::new(HotPotato::new(input.field(db)))
|
||||
|
@ -57,16 +57,16 @@ fn lru_works() {
|
|||
let mut db = common::LoggerDatabase::default();
|
||||
assert_eq!(load_n_potatoes(), 0);
|
||||
|
||||
for i in 0..128u32 {
|
||||
for i in 0..32u32 {
|
||||
let input = MyInput::new(&db, i);
|
||||
let p = get_hot_potato(&db, input);
|
||||
assert_eq!(p.0, i);
|
||||
}
|
||||
|
||||
assert_eq!(load_n_potatoes(), 128);
|
||||
assert_eq!(load_n_potatoes(), 32);
|
||||
// trigger the GC
|
||||
db.synthetic_write(salsa::Durability::HIGH);
|
||||
assert_eq!(load_n_potatoes(), 32);
|
||||
assert_eq!(load_n_potatoes(), 8);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -74,42 +74,42 @@ fn lru_can_be_changed_at_runtime() {
|
|||
let mut db = common::LoggerDatabase::default();
|
||||
assert_eq!(load_n_potatoes(), 0);
|
||||
|
||||
let inputs: Vec<(u32, MyInput)> = (0..128).map(|i| (i, MyInput::new(&db, i))).collect();
|
||||
let inputs: Vec<(u32, MyInput)> = (0..32).map(|i| (i, MyInput::new(&db, i))).collect();
|
||||
|
||||
for &(i, input) in inputs.iter() {
|
||||
let p = get_hot_potato(&db, input);
|
||||
assert_eq!(p.0, i);
|
||||
}
|
||||
|
||||
assert_eq!(load_n_potatoes(), 128);
|
||||
assert_eq!(load_n_potatoes(), 32);
|
||||
// trigger the GC
|
||||
db.synthetic_write(salsa::Durability::HIGH);
|
||||
assert_eq!(load_n_potatoes(), 32);
|
||||
assert_eq!(load_n_potatoes(), 8);
|
||||
|
||||
get_hot_potato::set_lru_capacity(&mut db, 64);
|
||||
assert_eq!(load_n_potatoes(), 32);
|
||||
get_hot_potato::set_lru_capacity(&mut db, 16);
|
||||
assert_eq!(load_n_potatoes(), 8);
|
||||
for &(i, input) in inputs.iter() {
|
||||
let p = get_hot_potato(&db, input);
|
||||
assert_eq!(p.0, i);
|
||||
}
|
||||
|
||||
assert_eq!(load_n_potatoes(), 128);
|
||||
assert_eq!(load_n_potatoes(), 32);
|
||||
// trigger the GC
|
||||
db.synthetic_write(salsa::Durability::HIGH);
|
||||
assert_eq!(load_n_potatoes(), 64);
|
||||
assert_eq!(load_n_potatoes(), 16);
|
||||
|
||||
// Special case: setting capacity to zero disables LRU
|
||||
get_hot_potato::set_lru_capacity(&mut db, 0);
|
||||
assert_eq!(load_n_potatoes(), 64);
|
||||
assert_eq!(load_n_potatoes(), 16);
|
||||
for &(i, input) in inputs.iter() {
|
||||
let p = get_hot_potato(&db, input);
|
||||
assert_eq!(p.0, i);
|
||||
}
|
||||
|
||||
assert_eq!(load_n_potatoes(), 128);
|
||||
assert_eq!(load_n_potatoes(), 32);
|
||||
// trigger the GC
|
||||
db.synthetic_write(salsa::Durability::HIGH);
|
||||
assert_eq!(load_n_potatoes(), 128);
|
||||
assert_eq!(load_n_potatoes(), 32);
|
||||
|
||||
drop(db);
|
||||
assert_eq!(load_n_potatoes(), 0);
|
||||
|
@ -118,10 +118,10 @@ fn lru_can_be_changed_at_runtime() {
|
|||
#[test]
|
||||
fn lru_keeps_dependency_info() {
|
||||
let mut db = common::LoggerDatabase::default();
|
||||
let capacity = 32;
|
||||
let capacity = 8;
|
||||
|
||||
// Invoke `get_hot_potato2` 33 times. This will (in turn) invoke
|
||||
// `get_hot_potato`, which will trigger LRU after 32 executions.
|
||||
// `get_hot_potato`, which will trigger LRU after 8 executions.
|
||||
let inputs: Vec<MyInput> = (0..(capacity + 1))
|
||||
.map(|i| MyInput::new(&db, i as u32))
|
||||
.collect();
|
||||
|
|
|
@ -15,8 +15,8 @@ use crate::setup::{Knobs, KnobsDatabase};
|
|||
struct CycleValue(u32);
|
||||
|
||||
const MIN: CycleValue = CycleValue(0);
|
||||
const MID: CycleValue = CycleValue(11);
|
||||
const MAX: CycleValue = CycleValue(22);
|
||||
const MID: CycleValue = CycleValue(5);
|
||||
const MAX: CycleValue = CycleValue(10);
|
||||
|
||||
#[salsa::tracked(cycle_fn=cycle_fn, cycle_initial=cycle_initial)]
|
||||
fn query_a(db: &dyn KnobsDatabase) -> CycleValue {
|
||||
|
|
|
@ -85,10 +85,7 @@ fn execute() {
|
|||
let mut db = salsa::DatabaseImpl::new();
|
||||
let inputs = MyInputs::new(
|
||||
&db,
|
||||
(0..1024)
|
||||
.into_iter()
|
||||
.map(|i| MyInput::new(&db, i))
|
||||
.collect(),
|
||||
(0..64).into_iter().map(|i| MyInput::new(&db, i)).collect(),
|
||||
);
|
||||
let trackeds = batch(&db, inputs);
|
||||
for (id, tracked) in trackeds.into_iter().enumerate() {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue