diff --git a/server/Cargo.lock b/server/Cargo.lock index 7f7abd5..3bdabb9 100644 --- a/server/Cargo.lock +++ b/server/Cargo.lock @@ -103,6 +103,17 @@ dependencies = [ "crypto-common", ] +[[package]] +name = "fail" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe5e43d0f78a42ad591453aedb1d7ae631ce7ee445c7643691055a9ed8d3b01c" +dependencies = [ + "log", + "once_cell", + "rand", +] + [[package]] name = "fallible-iterator" version = "0.2.0" @@ -716,6 +727,7 @@ name = "server" version = "0.1.0" dependencies = [ "anyhow", + "fail", "rand", "rusqlite", "serde", diff --git a/server/Cargo.toml b/server/Cargo.toml index a459342..5e82111 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -8,6 +8,7 @@ default-run = "server" [dependencies] anyhow = { version = "1" } +fail = { version = "0.5" } rand = { version = "0.8" } rusqlite = { version = "0.26" } serde = { version = "1.0", features = ["derive"] } diff --git a/server/src/authentication.rs b/server/src/authentication.rs index 4e7f16b..d63a288 100644 --- a/server/src/authentication.rs +++ b/server/src/authentication.rs @@ -1,4 +1,5 @@ use crate::errors::{error, fatal, ok, AppResult, FatalError}; +use fail::fail_point; use rusqlite::types::{FromSql, FromSqlError, FromSqlResult, ValueRef}; use serde::{Deserialize, Serialize}; use std::collections::HashMap; @@ -179,8 +180,7 @@ pub struct MemoryAuth { impl AuthenticationDB for MemoryAuth { fn create_user(&mut self, username: Username) -> AppResult { - #[cfg(test)] - let _ = maybe_fail::(vec![])?; + fail_point!("create-user", |_| Err(FatalError::DiskFull)); if self.users.contains_key(&username) { return Ok(Err(AuthenticationError::DuplicateUsername)); @@ -310,15 +310,30 @@ impl AuthenticationDB for MemoryAuth { #[cfg(test)] mod test { use super::*; + use fail::FailScenario; + use std::panic; fn with_memory_db(test: F) where - F: Fn(Box), + F: Fn(Box) -> () + panic::UnwindSafe, { let authdb: Box = Box::new(Default::default()); test(authdb); } + fn with_failpoints(failpoints: Vec<&str>, test: F) + where + F: Fn() -> () + panic::UnwindSafe, + { + let scenario = FailScenario::setup(); + for fp in failpoints { + fail::cfg(fp, "return()").unwrap(); + } + let result = panic::catch_unwind(test); + scenario.teardown(); + assert!(result.is_ok()) + } + #[test] fn it_can_create_a_user() { fn test_case(mut authdb: Box) { @@ -331,7 +346,8 @@ mod test { assert_eq!(authdb.get_username(&userid).unwrap(), Ok(username)); assert!(authdb.list_users().unwrap().unwrap().contains(&userid)); } - with_memory_db(test_case); + + with_failpoints(vec![], || with_memory_db(test_case)); } #[test] @@ -347,7 +363,7 @@ mod test { Err(AuthenticationError::DuplicateUsername) ); } - with_memory_db(test_case); + with_failpoints(vec![], || with_memory_db(test_case)); } #[test] @@ -367,7 +383,7 @@ mod test { .expect("no fatal errors") .expect("to receive a session token"); } - with_memory_db(test_case); + with_failpoints(vec![], || with_memory_db(test_case)); } #[test] @@ -397,7 +413,7 @@ mod test { (garrus, garrus_id) ); } - with_memory_db(test_case); + with_failpoints(vec![], || with_memory_db(test_case)); } #[test] @@ -413,7 +429,7 @@ mod test { authdb.authenticate(invite1).unwrap().unwrap(); authdb.authenticate(invite2).unwrap().unwrap(); } - with_memory_db(test_case); + with_failpoints(vec![], || with_memory_db(test_case)); } #[test] @@ -439,7 +455,7 @@ mod test { (username, userid) ); } - with_memory_db(test_case); + with_failpoints(vec![], || with_memory_db(test_case)); } #[test] @@ -461,7 +477,7 @@ mod test { let reuse_result = authdb.authenticate(invitation).expect("no fatal errors"); assert_eq!(reuse_result, Err(AuthenticationError::InvalidInvitation)); } - with_memory_db(test_case); + with_failpoints(vec![], || with_memory_db(test_case)); } #[test] @@ -493,7 +509,7 @@ mod test { Err(AuthenticationError::InvalidInvitation) ); } - with_memory_db(test_case); + with_failpoints(vec![], || with_memory_db(test_case)); } #[test] @@ -516,7 +532,7 @@ mod test { Err(AuthenticationError::InvalidSession) ); } - with_memory_db(test_case); + with_failpoints(vec![], || with_memory_db(test_case)); } #[test] @@ -541,6 +557,6 @@ mod test { Err(AuthenticationError::InvalidInvitation) ); } - with_memory_db(test_case); + with_failpoints(vec![], || with_memory_db(test_case)); } }