chore: Use nextest for miri test runs (#758)

This commit is contained in:
Lukas Wirth 2025-03-15 11:30:23 +01:00 committed by GitHub
parent 2308261d65
commit 1dc24388d1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 55 additions and 64 deletions

View file

@ -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

View file

@ -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 {

View file

@ -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)) } }",
]
"#]],
)],
);
}

View file

@ -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()));

View file

@ -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);

View file

@ -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();

View file

@ -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 {

View file

@ -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() {