pub struct Counter { /* private fields */ }
Expand description
A mutually exclusive counter that is not shareable, but can be defined statically for the duration of a test. This simplifies the implementation of a simple test-global counter, avoiding the complexity of alternatives like std::sync::atomic objects that are typically wrapped in Arc()s, cloned, and require non-intuitive memory management options.
§Example
use test_util::Counter;
use lazy_static::lazy_static;
#[test]
async fn my_test() {
lazy_static! {
static ref CALL_COUNT: Counter = Counter::new(0);
}
let handler = || {
// some async callback
// ...
CALL_COUNT.inc();
};
handler();
// ...
CALL_COUNT.inc();
assert_eq!(CALL_COUNT.get(), 2);
}
Important: Since inc() and get() obtain separate Mutex lock()s to access the underlying counter value, it is very possible that a separate thread, if also mutating the same counter, may increment the value between the first thread’s calls to inc() and get(), in which case, the two threads could get() the same value (the result after both calls to inc()). If get() is used to, for example, print the values after each call to inc(), the resulting values might include duplicate intermediate counter values, with some numbers skipped, but the final value after all threads complete will be the exact number of all calls to inc() (offset by the initial value).
To provide slightly more consistent results, inc() returns the new value after incrementing the counter, obtaining the value while the lock is held. This way, each incremental value will be returned to the calling threads; however the threads could still receive the values out of order.
Consider, thread 1 calls inc() starting at count 0. A value of 1 is returned, but before thread 1 receives the new value, it might be interrupted by thread 2. Thread 2 increments the counter from 1 to 2, return the new value 2, and (let’s say, for example) prints the value “2”. Thread 1 then resumes, and prints “1”.
Specifically, the Counter guarantees that each invocation of inc() will return a value that is
1 greater than the previous value returned by inc() (or 1 greater than the initial
value, if
it is the first invocation). Call get() after completing all invocations of inc() to get the
total number of times inc() was called (offset by the initial value).