test_util

Struct Counter

Source
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).

Implementations§

Source§

impl Counter

Source

pub fn new(initial: usize) -> Self

Initializes a new counter to the given value.

Source

pub fn inc(&self) -> usize

Increments the counter by one and returns the new value.

Source

pub fn get(&self) -> usize

Returns the current value of the counter.

Trait Implementations§

Source§

impl Debug for Counter

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.