fix clippy warning & unsafety

This commit is contained in:
mpostma 2021-10-06 14:51:46 +02:00
parent a38215de98
commit 9fa61439b1

View File

@ -27,6 +27,7 @@ pub mod test {
use std::panic::{RefUnwindSafe, UnwindSafe}; use std::panic::{RefUnwindSafe, UnwindSafe};
use std::path::Path; use std::path::Path;
use std::path::PathBuf; use std::path::PathBuf;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use serde_json::{Map, Value}; use serde_json::{Map, Value};
@ -42,15 +43,16 @@ pub mod test {
pub struct Stub<A, R> { pub struct Stub<A, R> {
name: String, name: String,
times: Option<usize>, times: Mutex<Option<usize>>,
stub: Box<dyn Fn(A) -> R + Sync + Send>, stub: Box<dyn Fn(A) -> R + Sync + Send>,
invalidated: bool, invalidated: AtomicBool,
} }
impl<A, R> Drop for Stub<A, R> { impl<A, R> Drop for Stub<A, R> {
fn drop(&mut self) { fn drop(&mut self) {
if !self.invalidated { if !self.invalidated.load(Ordering::Relaxed) {
if let Some(n) = self.times { let lock = self.times.lock().unwrap();
if let Some(n) = *lock {
assert_eq!(n, 0, "{} not called enough times", self.name); assert_eq!(n, 0, "{} not called enough times", self.name);
} }
} }
@ -58,14 +60,15 @@ pub mod test {
} }
impl<A, R> Stub<A, R> { impl<A, R> Stub<A, R> {
fn invalidate(&mut self) { fn invalidate(&self) {
self.invalidated = true; self.invalidated.store(true, Ordering::Relaxed);
} }
} }
impl<A: UnwindSafe, R> Stub<A, R> { impl<A: UnwindSafe, R> Stub<A, R> {
fn call(&mut self, args: A) -> R { fn call(&self, args: A) -> R {
match self.times { let mut lock = self.times.lock().unwrap();
match *lock {
Some(0) => panic!("{} called to many times", self.name), Some(0) => panic!("{} called to many times", self.name),
Some(ref mut times) => { Some(ref mut times) => {
*times -= 1; *times -= 1;
@ -102,7 +105,7 @@ pub mod test {
lock.insert(name, Box::new(stub)); lock.insert(name, Box::new(stub));
} }
pub fn get_mut<A, B>(&self, name: &str) -> Option<&mut Stub<A, B>> { pub fn get<A, B>(&self, name: &str) -> Option<&Stub<A, B>> {
let mut lock = self.inner.lock().unwrap(); let mut lock = self.inner.lock().unwrap();
match lock.get_mut(name) { match lock.get_mut(name) {
Some(s) => { Some(s) => {
@ -139,11 +142,12 @@ pub mod test {
/// The function that will be called when the stub is called. This needs to be called to /// The function that will be called when the stub is called. This needs to be called to
/// actually build the stub and register it to the stub store. /// actually build the stub and register it to the stub store.
pub fn then(self, f: impl Fn(A) -> R + Sync + Send + 'static) { pub fn then(self, f: impl Fn(A) -> R + Sync + Send + 'static) {
let times = Mutex::new(self.times);
let stub = Stub { let stub = Stub {
stub: Box::new(f), stub: Box::new(f),
times: self.times, times,
name: self.name.clone(), name: self.name.clone(),
invalidated: false, invalidated: AtomicBool::new(false),
}; };
self.store.insert(self.name, stub); self.store.insert(self.name, stub);
@ -167,15 +171,15 @@ pub mod test {
} }
} }
pub fn get<'a, A, R>(&'a self, name: &str) -> &'a mut Stub<A, R> { pub fn get<A, R>(&self, name: &str) -> &Stub<A, R> {
match self.store.get_mut(name) { match self.store.get(name) {
Some(stub) => stub, Some(stub) => stub,
None => { None => {
// panic here causes the stubs to get dropped, and panic in turn. To prevent // panic here causes the stubs to get dropped, and panic in turn. To prevent
// that, we forget them, and let them be cleaned by the os later. This is not // that, we forget them, and let them be cleaned by the os later. This is not
// optimal, but is still better than nested panicks. // optimal, but is still better than nested panicks.
let mut stubs = self.store.inner.lock().unwrap(); let mut stubs = self.store.inner.lock().unwrap();
let stubs = std::mem::replace(&mut *stubs, HashMap::new()); let stubs = std::mem::take(&mut *stubs);
std::mem::forget(stubs); std::mem::forget(stubs);
panic!("unexpected call to {}", name) panic!("unexpected call to {}", name)
} }