Loom is a concurrency permutation testing tool for Rust.

Related tags

Testing loom
Overview

Loom

Loom is a testing tool for concurrent Rust code. It runs a test many times, permuting the possible concurrent executions of that test under the C11 memory model. It uses state reduction techniques to avoid combinatorial explosion.

Crates.io Documentation Build Status

Quickstart

The loom documentation has significantly more documentation on how to use loom. But if you just want a jump-start, first add this to your Cargo.toml.

[target.'cfg(loom)'.dependencies]
loom = "0.5"

Next, create a test file and add a test:

use loom::sync::Arc;
use loom::sync::atomic::AtomicUsize;
use loom::sync::atomic::Ordering::{Acquire, Release, Relaxed};
use loom::thread;

#[test]
#[should_panic]
fn buggy_concurrent_inc() {
    loom::model(|| {
        let num = Arc::new(AtomicUsize::new(0));

        let ths: Vec<_> = (0..2)
            .map(|_| {
                let num = num.clone();
                thread::spawn(move || {
                    let curr = num.load(Acquire);
                    num.store(curr + 1, Release);
                })
            })
            .collect();

        for th in ths {
            th.join().unwrap();
        }

        assert_eq!(2, num.load(Relaxed));
    });
}

Then, run the test with

RUSTFLAGS="--cfg loom" cargo test --test buggy_concurrent_inc --release

Unsupported features

Loom currently does not implement the full C11 memory model. Here is the (incomplete) list of unsupported features.

  • SeqCst accesses (e.g. load, store, ..): They are are regarded as AcqRel. That is, they impose weaker synchronization, causing Loom to generate false alarms (not complete). See #180 for example. On the other hand, fence(SeqCst) is supported.
  • Load buffering behavior: Loom does not explore some executions that are possible in the C11 memory model. That is, there can be a bug in the checked code even if Loom says there is no bug (not sound). See the load_buffering test case in tests/litmus.rs.

License

This project is licensed under the MIT license.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in loom by you, shall be licensed as MIT, without any additional terms or conditions.

Comments
  • Add support for RwLock

    Add support for RwLock

    Fixes #21

    Oh snap when did this move to the Tokio org? Well, all the same: I added support for RwLock!

    I don't know if this is done, but the tests (which I got from the RwLock docs) pass so I'm happy.

    I would love some feedback. The is_read_locked() and is_write_locked() functions cause "Already Locked" panics so I am not using them at the moment. Let me know if you want more info on that.

    cc: @pickfire ?

    opened by pop 12
  • Checkpointing with Loom

    Checkpointing with Loom

    I am trying to debug a loom test which is failing, but I am having issues using the checkpoint.

    When I run: $ RUST_BACKTRACE=full RUSTFLAGS='--cfg loom' cargo +nightly test --test loom --release

    I get: " process didn't exit successfully: . . . (signal: 4, SIGILL: illegal instruction)"

    When I try to run with checkpointing I get issues on resolving imports: $ LOOM_CHECKPOINT_FILE=fpath.txt RUST_BACKTRACE=full RUSTFLAGS='--cfg loom --cfg feature="checkpoint"' cargo +nightly test --test loom --release

    Compiling generator v0.7.0 Compiling loom v0.5.1 error[E0432]: unresolved import serde --> /home/matan/.cargo/registry/src/github.com-1ecc6299db9ec823/loom-0.5.1/src/rt/object.rs:8:5 | 8 | use serde::{Deserialize, Serialize}; | ^^^^^ use of undeclared crate or module serde

    error[E0432]: unresolved import serde --> /home/matan/.cargo/registry/src/github.com-1ecc6299db9ec823/loom-0.5.1/src/rt/path.rs:4:5 | 4 | use serde::{Deserialize, Serialize}; | ^^^^^ use of undeclared crate or module serde

    error[E0432]: unresolved import serde --> /home/matan/.cargo/registry/src/github.com-1ecc6299db9ec823/loom-0.5.1/src/rt/vv.rs:4:5 | 4 | use serde::{Deserialize, Serialize}; | ^^^^^ use of undeclared crate or module serde

    error: cannot determine resolution for the derive macro Serialize --> /home/matan/.cargo/registry/src/github.com-1ecc6299db9ec823/loom-0.5.1/src/rt/object.rs:12:43 | 12 | #[cfg_attr(feature = "checkpoint", derive(Serialize, Deserialize))] | ^^^^^^^^^ | = note: import resolution is stuck, try simplifying macro imports

    error: cannot determine resolution for the derive macro Deserialize --> /home/matan/.cargo/registry/src/github.com-1ecc6299db9ec823/loom-0.5.1/src/rt/object.rs:12:54 | 12 | #[cfg_attr(feature = "checkpoint", derive(Serialize, Deserialize))] | ^^^^^^^^^^^ | = note: import resolution is stuck, try simplifying macro imports

    error: cannot determine resolution for the derive macro Serialize --> /home/matan/.cargo/registry/src/github.com-1ecc6299db9ec823/loom-0.5.1/src/rt/object.rs:36:43 | 36 | #[cfg_attr(feature = "checkpoint", derive(Serialize, Deserialize))] | ^^^^^^^^^ | = note: import resolution is stuck, try simplifying macro imports

    error: cannot determine resolution for the derive macro Deserialize --> /home/matan/.cargo/registry/src/github.com-1ecc6299db9ec823/loom-0.5.1/src/rt/object.rs:36:54 | 36 | #[cfg_attr(feature = "checkpoint", derive(Serialize, Deserialize))] | ^^^^^^^^^^^ | = note: import resolution is stuck, try simplifying macro imports

    error: cannot determine resolution for the derive macro Serialize --> /home/matan/.cargo/registry/src/github.com-1ecc6299db9ec823/loom-0.5.1/src/rt/path.rs:8:43 | 8 | #[cfg_attr(feature = "checkpoint", derive(Serialize, Deserialize))] | ^^^^^^^^^ | = note: import resolution is stuck, try simplifying macro imports

    error: cannot determine resolution for the derive macro Deserialize --> /home/matan/.cargo/registry/src/github.com-1ecc6299db9ec823/loom-0.5.1/src/rt/path.rs:8:54 | 8 | #[cfg_attr(feature = "checkpoint", derive(Serialize, Deserialize))] | ^^^^^^^^^^^ | = note: import resolution is stuck, try simplifying macro imports

    error: cannot determine resolution for the derive macro Serialize --> /home/matan/.cargo/registry/src/github.com-1ecc6299db9ec823/loom-0.5.1/src/rt/path.rs:28:43 | 28 | #[cfg_attr(feature = "checkpoint", derive(Serialize, Deserialize))] | ^^^^^^^^^ | = note: import resolution is stuck, try simplifying macro imports

    error: cannot determine resolution for the derive macro Deserialize --> /home/matan/.cargo/registry/src/github.com-1ecc6299db9ec823/loom-0.5.1/src/rt/path.rs:28:54 | 28 | #[cfg_attr(feature = "checkpoint", derive(Serialize, Deserialize))] | ^^^^^^^^^^^ | = note: import resolution is stuck, try simplifying macro imports

    error: cannot determine resolution for the derive macro Serialize --> /home/matan/.cargo/registry/src/github.com-1ecc6299db9ec823/loom-0.5.1/src/rt/path.rs:45:43 | 45 | #[cfg_attr(feature = "checkpoint", derive(Serialize, Deserialize))] | ^^^^^^^^^ | = note: import resolution is stuck, try simplifying macro imports

    error: cannot determine resolution for the derive macro Deserialize --> /home/matan/.cargo/registry/src/github.com-1ecc6299db9ec823/loom-0.5.1/src/rt/path.rs:45:54 | 45 | #[cfg_attr(feature = "checkpoint", derive(Serialize, Deserialize))] | ^^^^^^^^^^^ | = note: import resolution is stuck, try simplifying macro imports

    error: cannot determine resolution for the derive macro Serialize --> /home/matan/.cargo/registry/src/github.com-1ecc6299db9ec823/loom-0.5.1/src/rt/path.rs:58:43 | 58 | #[cfg_attr(feature = "checkpoint", derive(Serialize, Deserialize))] | ^^^^^^^^^ | = note: import resolution is stuck, try simplifying macro imports

    error: cannot determine resolution for the derive macro Deserialize --> /home/matan/.cargo/registry/src/github.com-1ecc6299db9ec823/loom-0.5.1/src/rt/path.rs:58:54 | 58 | #[cfg_attr(feature = "checkpoint", derive(Serialize, Deserialize))] | ^^^^^^^^^^^ | = note: import resolution is stuck, try simplifying macro imports

    error: cannot determine resolution for the derive macro Serialize --> /home/matan/.cargo/registry/src/github.com-1ecc6299db9ec823/loom-0.5.1/src/rt/path.rs:63:47 | 63 | #[cfg_attr(feature = "checkpoint", derive(Serialize, Deserialize))] | ^^^^^^^^^ | = note: import resolution is stuck, try simplifying macro imports

    error: cannot determine resolution for the derive macro Deserialize --> /home/matan/.cargo/registry/src/github.com-1ecc6299db9ec823/loom-0.5.1/src/rt/path.rs:63:58 | 63 | #[cfg_attr(feature = "checkpoint", derive(Serialize, Deserialize))] | ^^^^^^^^^^^ | = note: import resolution is stuck, try simplifying macro imports

    error: cannot determine resolution for the derive macro Serialize --> /home/matan/.cargo/registry/src/github.com-1ecc6299db9ec823/loom-0.5.1/src/rt/path.rs:71:43 | 71 | #[cfg_attr(feature = "checkpoint", derive(Serialize, Deserialize))] | ^^^^^^^^^ | = note: import resolution is stuck, try simplifying macro imports

    error: cannot determine resolution for the derive macro Deserialize --> /home/matan/.cargo/registry/src/github.com-1ecc6299db9ec823/loom-0.5.1/src/rt/path.rs:71:54 | 71 | #[cfg_attr(feature = "checkpoint", derive(Serialize, Deserialize))] | ^^^^^^^^^^^ | = note: import resolution is stuck, try simplifying macro imports

    error: cannot determine resolution for the derive macro Serialize --> /home/matan/.cargo/registry/src/github.com-1ecc6299db9ec823/loom-0.5.1/src/rt/vv.rs:9:43 | 9 | #[cfg_attr(feature = "checkpoint", derive(Serialize, Deserialize))] | ^^^^^^^^^ | = note: import resolution is stuck, try simplifying macro imports

    error: cannot determine resolution for the derive macro Deserialize --> /home/matan/.cargo/registry/src/github.com-1ecc6299db9ec823/loom-0.5.1/src/rt/vv.rs:9:54 | 9 | #[cfg_attr(feature = "checkpoint", derive(Serialize, Deserialize))] | ^^^^^^^^^^^ | = note: import resolution is stuck, try simplifying macro imports

    error[E0433]: failed to resolve: use of undeclared crate or module serde_json --> /home/matan/.cargo/registry/src/github.com-1ecc6299db9ec823/loom-0.5.1/src/model.rs:244:9 | 244 | serde_json::from_str(&contents).unwrap() | ^^^^^^^^^^ use of undeclared crate or module serde_json

    error[E0433]: failed to resolve: use of undeclared crate or module serde_json --> /home/matan/.cargo/registry/src/github.com-1ecc6299db9ec823/loom-0.5.1/src/model.rs:248:26 | 248 | let serialized = serde_json::to_string(path).unwrap(); | ^^^^^^^^^^ use of undeclared crate or module serde_json

    error: aborting due to 23 previous errors

    Some errors have detailed explanations: E0432, E0433. For more information about an error, try rustc --explain E0432. error: could not compile loom

    To learn more, run the command again with --verbose.

    opened by matanmarkind 9
  • Add a loom aware block_on for running futures to completion

    Add a loom aware block_on for running futures to completion

    This solves https://github.com/tokio-rs/tokio/issues/2463

    Adding a way to run a Future to completion inside a loom model. Allows using loom to test the correctness of Future::poll implementations.

    Do you want to have this in loom? If not, I might publish it as loom-executor or something along those lines. But the further upstream it can be the better IMO.

    Feedback on the implementation greatly appreciated!

    opened by faern 8
  • Arc requires T: Sized

    Arc requires T: Sized

    std::sync::Arc<T> does not require T: Sized, where as loom's version does. This means that code that uses, say, Arc<dyn Fn> will not compile with loom, which is unfortunate. I believe we would need to move the T to the end of loom::Arc for this to work, though that also breaks the layout needed according to loom::Arc's comment: https://github.com/carllerche/loom/blob/339dd48f57d3b9b786e44db4914d08882d7659bf/src/sync/arc.rs#L11-L17

    opened by jonhoo 8
  • cannot access a scoped thread local variable without calling `set` first

    cannot access a scoped thread local variable without calling `set` first

    Running the following code -

    use loom::sync::atomic::AtomicUsize;
    use std::sync::atomic::Ordering;
    use std::thread;
    
    #[test]
    fn main() {
        loom::model(|| {
            let busy = AtomicUsize::new(0);
            thread::spawn(move || busy.swap(1, Ordering::SeqCst));
        });
    }
    

    results in

    running 1 test
    thread '<unnamed>' panicked at 'cannot access a scoped thread local variable without calling `set` first', <::std::macros::panic macros>:2:4
    

    This is not deterministic either. I see this error message only once in about 5 runs.

    I couldn't understand how this error message corresponds to the source code. Is there anything wrong with the code? I couldn't figure out if this error message is an issue with Loom or with the Rust compiler.

    Corresponding section from Cargo.toml:

    [dependencies]
    loom = "0.3.4"
    

    Result of uname -a:

    Linux anduin 4.15.0-101-generic #102-Ubuntu SMP Mon May 11 10:07:26 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
    

    Cargo version: cargo 1.42.0 (86334295e 2020-01-31) Rustc version: rustc 1.42.0 (b8cedc004 2020-03-09)

    opened by nitishch 7
  • Change `last_dependent_accesses` for atomics

    Change `last_dependent_accesses` for atomics

    Consider the following program (x is a shared variable, the SeqCst ordering is assumed):

    • thread 0 (main): store 0 in x
    • thread 1: store 1 in x
    • thread 2: store 2 in x
    • thread 0 (main): wait for thread 1; wait for thread 2; load x

    Without this change, concurrent writes are considered independent, so Loom fails to explore store 2 followed by store 1.

    For orderings other than SeqCst, this is likely to introduce redundant dependencies, resulting in more thread interleavings being explored than necessary.

    opened by nkaretnikov 7
  • Add support for mpsc channels

    Add support for mpsc channels

    Adds Loom mocks for std::sync::mpsc. Also, adds unimplemented stubs for std::sync::barrier that the code that depends on them could be at least compiled.

    Note: This PR includes the changes from #88, so you probably want to merge it first. cc: @pop

    opened by vakaras 6
  • coredump with illegal hardware instruction

    coredump with illegal hardware instruction

    I try to use loom to check my project

    When I run cargo test --features=concurrent-test --test test, it report

       Compiling atomic_value v0.1.0 (/home/sherlock/git/atomic_value)
        Finished test [unoptimized + debuginfo] target(s) in 0.57s
         Running target/debug/deps/test-6a9029d909e56a54
    
    running 1 test
    thread panicked while panicking. aborting.
    error: test failed, to rerun pass '--test test'
    
    Caused by:
      process didn't exit successfully: `/home/sherlock/git/atomic_value/target/debug/deps/test-6a9029d909e56a54` (signal: 4, SIGILL: illegal instruction)
    

    Is there anything I write wrong? If have, could anyone help me to fix it?

    question 
    opened by Sherlock-Holo 6
  • Unable to substitute Arc<dyn Fn>

    Unable to substitute Arc

    I have the following code using std::sync::Arc: https://github.com/kvark/choir/blob/6cb29be018a19135d947942aad37f42b47161e7b/src/lib.rs#L58

    Arc<dyn Fn(SubIndex) + Send + Sync + 'static>,
    

    Loom's Arc doesn't appear to support this:

    error[E0277]: the size for values of type `(dyn Fn(u32) + Send + Sync + 'static)` cannot be known at compilation time
      --> src/lib.rs:68:9
       |
    68 |         Arc<dyn Fn(SubIndex) + Send + Sync + 'static>,
       |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
       |
       = help: the trait `Sized` is not implemented for `(dyn Fn(u32) + Send + Sync + 'static)`
    note: required by a bound in `loom::sync::Arc`
      --> /Users/kvark/.cargo/registry/src/github.com-1ecc6299db9ec823/loom-0.5.4/src/sync/arc.rs:8:16
       |
    8  | pub struct Arc<T> {
       |                ^ required by this bound in `loom::sync::Arc`
    
    opened by kvark 5
  • Consider using a feature rather than cfg flag

    Consider using a feature rather than cfg flag

    Currently Loom recommends using target specific dependencies.

    [target.'cfg(loom)'.dependencies]
    loom = "0.5"
    

    This works, however it has certain drawbacks:

    • Building with RUSTFLAGS="--cfg loom" requires rebuilding every dependency.

    • cargo vendor vendors dependencies of loom.

    • Dependencies of loom are included in Cargo.lock when using a crate that depends on loom.

    • cargo audit includes dependencies of loom when using a crate that depends on loom.

    • Requiring an user to use RUSTFLAGS="--cfg loom" to test crate with loom.

    • Requiring an user to import loom or std types depending on whether loom is enabled.

      #[cfg(loom)]
      pub(crate) use loom::sync::atomic::AtomicUsize;
      
      #[cfg(not(loom))]
      pub(crate) use std::sync::atomic::AtomicUsize;
      

    All those issues would be solvable if loom did use a feature rather than a config flag. To clarify what I mean: the user could use loom like this in Cargo.toml.

    [dependencies]
    loom = "0.6"
    [dev-dependencies]
    loom = { version = "0.6", features = ["model"] }
    

    Then import whatever they want by simply using use, without having to bother with #[cfg] or cfg_if!.

    use loom::sync::atomic::AtomicUsize;
    

    That would work because Loom crate would provide a basic AtomicUsize implementation that directly uses methods from std when model feature is not enabled. This means no performance cost when not using model feature.

    if_cfg! {
        if #[cfg(feature = "model")] {
            pub struct AtomicUsize(loom::Atomic<usize>);
            impl AtomicUsize {
                #[track_caller]
                pub fn with_mut<R>(&mut self, f: impl FnOnce(&mut usize) -> R) -> R {
                    self.0.with_mut(f)
                }
    
                // ...
            }
        } else {
            pub struct AtomicUsize(std::sync::atomic::AtomicUsize);
            impl AtomicUsize {
                pub fn with_mut<R>(&mut self, f: impl FnOnce(&mut usize) -> R) -> R {
                    f(self.get_mut())
                }
    
                // ...
            }
        }
    }
    

    Some possible concerns:

    • Does that mean that crates that use loom have to use loom as a dependency? No, if they choose to they can use #[cfg(test)] themselves to mock loom APIs, just like they have to right now.
    • What about running loom tests from another library (see #134)? Cargo compiles crates once, having a feature turned on turns it on for all users.
    • Would that cause a performance cost for programs that use loom in tests due to Cargo merging all features used within a crate? No, assuming new feature resolver is being used (Rust 1.51+, needs to be opted-in with resolver = "2" or edition = "2021"). That said, a note in documentation should be added recommending using new feature resolver for programs that use loom for testing themselves (it's not necessary for libraries or programs that happen to use libraries that use loom).
    opened by xfix 5
  • arc: re-enable `Arc::strong_count`

    arc: re-enable `Arc::strong_count`

    This branch re-enables the Arc::strong_count API method, which previously panicked as it was not implemented.

    This is just @Restioson's PR #172 but updated to compile with the latest changes from master. Unfortunately, I can't push to the base branch for that PR (since I believe "allow edits from maintainers" was not enabled), so I'm opening a new PR so we can get this change merged.

    Closes #171. Closes #172.

    Authored-by: Restioson [email protected] Co-authored-by: Eliza Weisman [email protected]

    opened by hawkw 4
  • Fix for corner case where `RwLock` could be acquired in write mode while write locked

    Fix for corner case where `RwLock` could be acquired in write mode while write locked

    This PR contains a minor 2 line fix for a corner case where a RwLock could erroneously be acquired in write mode while already being write locked. This led to a panic saying loom::RwLock state corrupt: "WouldBlock", while it instead should return the WouldBlock error state on RwLock::try_write or (potentially) signal a deadlock when calling RwLock::write. I also took the liberty of adding some more test cases for RwLock, which will also detect any regressions of this bug.

    opened by Pointerbender 0
  • Add a mock MaybeUninit

    Add a mock MaybeUninit

    It would be nice if loom could add a MaybeUninit type, which internally keeps track of if it is in an initialized state, and asserts that it is indeed initialized when the user calls assume_init(). Additionally it could provide a new API to mark the value as uninitalized again, which for std would simply be a no-op. This would increase the confidence of users that in all possible interleavings only initialized data is read, and with the option to mark a MaybeUninit as unitialized, we could also check that data is not read after it was "moved out" e.g. by ptr::read

    opened by jschwe 4
  • What to do when loom::AtomicUsize do not implement as_mut_ptr()

    What to do when loom::AtomicUsize do not implement as_mut_ptr()

    Hi, I was tring to use loom for a special ref counter. Here is the sample code, basically trying to deallocate a AtomicUsize when down to 0.

    But I found that loom::AtomicUsize do not have api .as_mut_ptr() to get the mutable pointer. What should I do in this case? I read the doc and found that we should implement API for std type if there is API difference. But for this case, it is the loom type that miss the function, how can I implement this? It seems not feasible via with_mut.

    Thanks!

    #[repr(transparent)]
    #[derive(Clone, Copy, Debug)]
    pub struct TaskLocalBytesAllocated(Option<&'static AtomicUsize>);
    impl TaskLocalBytesAllocated {
        /// Subtracts from the counter value, and `drop` the counter while the count reaches zero.
        #[inline(always)]
        pub(crate) fn sub(&self, val: usize) {
            if let Some(bytes) = self.0 {
                // Use Release to synchronize with the below deletion.
                let old_bytes = bytes.fetch_sub(val, Ordering::Release);
                // If the counter reaches zero, delete the counter. Note that we've ensured there's no
                // zero deltas in `wrap_layout`, so there'll be no more uses of the counter.
                if old_bytes == val {
                    // This fence is needed to prevent reordering of use of the counter and deletion of
                    // the counter. Because it is marked `Release`, the decreasing of the counter
                    // synchronizes with this `Acquire` fence. This means that use of the counter
                    // happens before decreasing the counter, which happens before this fence, which
                    // happens before the deletion of the counter.
                    fence(Ordering::Acquire);
    
                    unsafe { Box::from_raw_in(bytes.as_mut_ptr(), System) };
                }
            }
        }
    }
    
    opened by BowenXiao1999 7
  • Fix drop order of tls and statics and avoid double panics on deadlock

    Fix drop order of tls and statics and avoid double panics on deadlock

    Hello! I ran into some of the same issues as mentioned in #152, #179 and #291 and developed a fix for all of those issues. In a nutshell, the changes are:

    • clarify the documentation of the mock lazy_static implementation regarding its Drop implementation
    • ensure that global statics are dropped after thread locals
    • ensure that loom does not panic inside a panic when dropping thread locals on the main thread
    • add two regression tests for #152
    • ensure that thread locals are destructed when a spawned thread panics
    • ensure that loom doesn't double panic on deadlock
    • add a test to verify that thread locals are properly destructed on spawned threads
    • sprinkle comments generously everywhere to explain the code changes

    This is my first time contributing to loom, please let me know if I can somehow improve this PR or if additional information is needed. Thank you!

    opened by Pointerbender 0
  • cell::MutPtr doesn't provide a way to directly get an immutable reference

    cell::MutPtr doesn't provide a way to directly get an immutable reference

    MutPtr provides deref, which returns a &mut T, but nothing that returns a &T.

    I'm working around it by calling MutPtr::with, dereferencing the pointer myself, and "smuggling" it out of the closure. Looking at the implementation of MutPtr I don't think I'm missing any validation by doing this, but it's not obvious from the API.

    Ideally the current method would be called deref_mut and you could add deref, but I suppose if you don't want to make a breaking change, maybe you could add deref_const?

    All of this is for a guard for a mutex that I'm testing; the guard stores a MutPtr from the mutex's UnsafeCell, and I'm currently implementing Deref and DerefMut roughly like so:

    impl<'a, T> std::ops::Deref for SelfContainedMutexGuard<'a, T> {
        type Target = T;
    
        fn deref(&self) -> &Self::Target {
            self.ptr.with(|p| unsafe { &*p })
        }
    }
    
    impl<'a, T> std::ops::DerefMut for SelfContainedMutexGuard<'a, T>
    {
        fn deref_mut(&mut self) -> &mut Self::Target {
            unsafe { self.ptr.deref() }
        }
    }
    
    opened by sporksmith 0
  • Track which reference belongs to which store

    Track which reference belongs to which store

    Add a unique id to stores, and keep track of this id in references. When a reference is used with a different store, this will panic with a message explaining that the user might be trying to reuse object across executions.

    This implements the suggestion in #290, although it adds a new id to stores, rather than reusing the execution ids.

    One point I would like some more feedback on, is the naming of Ref::from_usize. I changed the signature to also take a store id, but left the name as is. Changing it to Ref::new feels natural, but figured I'd ask for the rationale behind naming it from_usize in the first place.

    opened by alexkeizer 2
Releases(v0.5.6)
  • v0.5.6(May 19, 2022)

    Added

    • cell: add UnsafeCell::into_inner for parity with std (#272)
    • sync: re-enable Arc::strong_count (#172)
    • sync: implement Arc::try_unwrap (#262)
    • sync: add mpsc::Receiver::try_recv (#262)

    Documented

    • show feature flags in docs (#151)
    • fix broken RustDoc links (#273)
    Source code(tar.gz)
    Source code(zip)
  • v0.5.5(May 13, 2022)

    Added

    • sync: Add Arc::from_std without T: Sized bound (#226)
    • sync: Implement Debug for AtomicPtr for all T (#255)
    • logs: Add location tracking for threads and atomic operations (#258)
    • logs: Add additional location tracking to Arc, alloc, and mpsc (#265)
    • logs: Improve tracing configuration for LOOM_LOG (#266)
    • logs: Add a span for the current model's iteration (#267)

    Documented

    • Add note about in-memory representation of atomic types (#253)
    • Document LOOM_LOG syntax (#257)

    Fixed

    • Fix double panic when exceeding the branch limit in Drop (#245)
    • cell: Allow using {Mut,Const}Ptr::{deref,with} when the pointee is !Sized (#247)
    • thread: Fix semantics of thread::park after Thread::unpark (#250)
    Source code(tar.gz)
    Source code(zip)
  • v0.5.2(Oct 7, 2021)

    0.5.2 (October 7, 2021)

    Added

    • Add a loom::cell::Cell, which provides a basic wrapper of the loom UnsafeCell (#196)
    • Arc counter manipulations (#225)
    • Implement Mutex::into_inner and RwLock::into_inner (#215)
    • Implement Release, AcqRel, and SeqCst fences (#220)
    • Arc::as_ptr added (#230)
    • Arc::pin added (#224)

    Changed

    • Remove implicit T: Sized requirement from UnsafeCell (#222)
    • Update tracing (#227)
    Source code(tar.gz)
    Source code(zip)
Owner
Tokio
Rust's asynchronous runtime.
Tokio
Rnp - A simple cloud-friendly tool for testing network reachability.

Rnp - A simple cloud-friendly tool for testing network reachability. Release Status Crates.io Github release Nuget packages NOTE: This project is in e

Riff 50 Dec 13, 2022
hb is an endpoint focused HTTP load testing / benchmark tool.

hb hb is an endpoint focused HTTP load testing / benchmark tool. Description The goal of hb is to provide a simple, robust tool to apply load against

Mark Pritchard 2 Aug 23, 2022
Testing Framework for Rust

Polish Polish is Test-Driven Development done right Getting Started Installing the Package The crates.io package is kept up-to-date with all the major

Fadi Hanna Al-Kass 49 Dec 18, 2022
Automated property based testing for Rust (with shrinking).

quickcheck QuickCheck is a way to do property based testing using randomly generated input. This crate comes with the ability to randomly generate and

Andrew Gallant 2k Jan 2, 2023
Hypothesis-like property testing for Rust

Proptest Introduction Proptest is a property testing framework (i.e., the QuickCheck family) inspired by the Hypothesis framework for Python. It allow

Jason Lingle 1.1k Jan 1, 2023
Simple goldenfile testing in Rust.

?? Rust Goldenfile Simple goldenfile testing in Rust. Goldenfile tests generate one or more output files as they run. At the end of the test, the gene

Calder Coalson 24 Nov 26, 2022
Cucumber testing framework for Rust. Fully native, no external test runners or dependencies.

An implementation of the Cucumber testing framework for Rust. Fully native, no external test runners or dependencies.

Brendan Molloy 394 Jan 1, 2023
Drill is an HTTP load testing application written in Rust inspired by Ansible syntax

Drill is an HTTP load testing application written in Rust inspired by Ansible syntax

Ferran Basora 1.5k Jan 1, 2023
assay - A super powered testing macro for Rust

assay - A super powered testing macro for Rust as·say /ˈaˌsā,aˈsā/ noun - the testing of a metal or ore to determine its ingredients and quality. Rust

Michael Gattozzi 105 Dec 4, 2022
Rust testing library

K9 - Rust Testing Library Snapshot testing + better assertions Available test macros snapshot assert_equal assert_greater_than assert_greater_than_or_

Aaron Abramov 269 Dec 10, 2022
Testing Framework for Rust

Polish Polish is Test-Driven Development done right Getting Started Installing the Package The crates.io package is kept up-to-date with all the major

Fadi Hanna Al-Kass 49 Dec 18, 2022
Rustress - stress testing library in Rust. For fun

rustress Simple network stress testing library. To get familiar with Rust Planned features (Subject to change) Multithreaded client/server Throughput

Hakan Sönmez 7 Sep 22, 2022
insta: a snapshot testing library for Rust

insta: a snapshot testing library for Rust Introduction Snapshots tests (also sometimes called approval tests) are tests that assert values against a

Armin Ronacher 1.4k Jan 1, 2023
Simple assertion library for unit testing in python with a fluent API

Simple assertions library for unit testing in Python with a nice fluent API. Supports both Python 2 and 3.

snakedye 19 Sep 10, 2022
Viceroy provides local testing for developers working with Compute@Edge.

Viceroy provides local testing for developers working with Compute@Edge. It allows you to run services written against the Compute@Edge APIs on your local development machine, and allows you to configure testing backends for your service to communicate with.

Fastly 99 Jan 7, 2023
Declarative Testing Framework

Demonstrate allows tests to be written without as a much repetitive code within the demonstrate! macro, which will generate the corresponding full tests.

Austin Baugh 41 Aug 17, 2022
🧵 Generate self-describing strings of a given length to help aid software testing

rust-counter-strings Counter strings generator written in rust to help aid software testing What is a counterstring? "A counterstring is a graduated s

Thomas Chaplin 23 Jun 24, 2022
🔥 Unit testing framework for Subgraph development on The Graph protocol. ⚙️

?? Welcome to Matchstick - a unit testing framework for The Graph protocol. Try out your mapping logic in a sandboxed environment and ensure your hand

null 157 Dec 20, 2022
This is a tiny (but delightful!) utility library for exhaustive testing.

Exhaustigen This is a tiny (but delightful!) utility library for exhaustive testing. It is based (directly) on the idea and code in the following blog

Graydon Hoare 34 Dec 14, 2022