Ability to mock behaviours for tests
This commit is contained in:
parent
081fc2cbc8
commit
b2704bd3d2
7 changed files with 340 additions and 80 deletions
|
@ -25,6 +25,7 @@ use my_tasks::SyncStatus;
|
|||
use my_tasks::Task;
|
||||
use my_tasks::calendar::cached_calendar::CachedCalendar;
|
||||
use my_tasks::Provider;
|
||||
use my_tasks::mock_behaviour::MockBehaviour;
|
||||
|
||||
pub enum LocatedState {
|
||||
/// Item does not exist yet or does not exist anymore
|
||||
|
@ -575,21 +576,21 @@ pub fn scenarii_transient_task() -> Vec<ItemScenario> {
|
|||
|
||||
|
||||
/// Build a `Provider` that contains the data (defined in the given scenarii) before sync
|
||||
pub async fn populate_test_provider_before_sync(scenarii: &[ItemScenario]) -> Provider<Cache, CachedCalendar, Cache, CachedCalendar> {
|
||||
let mut provider = populate_test_provider(scenarii, false).await;
|
||||
pub async fn populate_test_provider_before_sync(scenarii: &[ItemScenario], mock_behaviour: Arc<Mutex<MockBehaviour>>) -> Provider<Cache, CachedCalendar, Cache, CachedCalendar> {
|
||||
let mut provider = populate_test_provider(scenarii, mock_behaviour, false).await;
|
||||
apply_changes_on_provider(&mut provider, scenarii).await;
|
||||
provider
|
||||
}
|
||||
|
||||
/// Build a `Provider` that contains the data (defined in the given scenarii) after sync
|
||||
pub async fn populate_test_provider_after_sync(scenarii: &[ItemScenario]) -> Provider<Cache, CachedCalendar, Cache, CachedCalendar> {
|
||||
populate_test_provider(scenarii, true).await
|
||||
pub async fn populate_test_provider_after_sync(scenarii: &[ItemScenario], mock_behaviour: Arc<Mutex<MockBehaviour>>) -> Provider<Cache, CachedCalendar, Cache, CachedCalendar> {
|
||||
populate_test_provider(scenarii, mock_behaviour, true).await
|
||||
}
|
||||
|
||||
async fn populate_test_provider(scenarii: &[ItemScenario], populate_for_final_state: bool) -> Provider<Cache, CachedCalendar, Cache, CachedCalendar> {
|
||||
async fn populate_test_provider(scenarii: &[ItemScenario], mock_behaviour: Arc<Mutex<MockBehaviour>>, populate_for_final_state: bool) -> Provider<Cache, CachedCalendar, Cache, CachedCalendar> {
|
||||
let mut local = Cache::new(&PathBuf::from(String::from("test_cache_local/")));
|
||||
let mut remote = Cache::new(&PathBuf::from(String::from("test_cache_remote/")));
|
||||
remote.set_is_mocking_remote_source();
|
||||
remote.set_mock_behaviour(Some(mock_behaviour));
|
||||
|
||||
// Create the initial state, as if we synced both sources in a given state
|
||||
for item in scenarii {
|
||||
|
|
|
@ -1,5 +1,10 @@
|
|||
mod scenarii;
|
||||
|
||||
#[cfg(feature = "local_calendar_mocks_remote_calendars")]
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
#[cfg(feature = "local_calendar_mocks_remote_calendars")]
|
||||
use my_tasks::mock_behaviour::MockBehaviour;
|
||||
|
||||
|
||||
|
||||
|
@ -8,6 +13,8 @@ mod scenarii;
|
|||
struct TestFlavour {
|
||||
#[cfg(feature = "local_calendar_mocks_remote_calendars")]
|
||||
scenarii: Vec<scenarii::ItemScenario>,
|
||||
#[cfg(feature = "local_calendar_mocks_remote_calendars")]
|
||||
mock_behaviour: Arc<Mutex<MockBehaviour>>,
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "local_calendar_mocks_remote_calendars"))]
|
||||
|
@ -16,8 +23,9 @@ impl TestFlavour {
|
|||
pub fn first_sync_to_local() -> Self { Self{} }
|
||||
pub fn first_sync_to_server() -> Self { Self{} }
|
||||
pub fn transient_task() -> Self { Self{} }
|
||||
pub fn normal_with_errors() -> Self { Self{} }
|
||||
|
||||
pub async fn run(&self) {
|
||||
pub async fn run(&self, _max_attempts: u32) {
|
||||
println!("WARNING: This test required the \"integration_tests\" Cargo feature");
|
||||
}
|
||||
}
|
||||
|
@ -27,34 +35,54 @@ impl TestFlavour {
|
|||
pub fn normal() -> Self {
|
||||
Self {
|
||||
scenarii: scenarii::scenarii_basic(),
|
||||
mock_behaviour: Arc::new(Mutex::new(MockBehaviour::new())),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn first_sync_to_local() -> Self {
|
||||
Self {
|
||||
scenarii: scenarii::scenarii_first_sync_to_local(),
|
||||
mock_behaviour: Arc::new(Mutex::new(MockBehaviour::new())),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn first_sync_to_server() -> Self {
|
||||
Self {
|
||||
scenarii: scenarii::scenarii_first_sync_to_server(),
|
||||
mock_behaviour: Arc::new(Mutex::new(MockBehaviour::new())),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn transient_task() -> Self {
|
||||
Self {
|
||||
scenarii: scenarii::scenarii_transient_task(),
|
||||
mock_behaviour: Arc::new(Mutex::new(MockBehaviour::new())),
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn run(&self) {
|
||||
let mut provider = scenarii::populate_test_provider_before_sync(&self.scenarii).await;
|
||||
pub fn normal_with_errors() -> Self {
|
||||
Self {
|
||||
scenarii: scenarii::scenarii_basic(),
|
||||
mock_behaviour: Arc::new(Mutex::new(MockBehaviour::fail_now(10))),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub async fn run(&self, max_attempts: u32) {
|
||||
self.mock_behaviour.lock().unwrap().suspend();
|
||||
|
||||
let mut provider = scenarii::populate_test_provider_before_sync(&self.scenarii, Arc::clone(&self.mock_behaviour)).await;
|
||||
print_provider(&provider, "before sync").await;
|
||||
|
||||
println!("\nsyncing...\n");
|
||||
provider.sync().await.unwrap();
|
||||
self.mock_behaviour.lock().unwrap().resume();
|
||||
for attempt in 0..max_attempts {
|
||||
println!("\nSyncing...\n");
|
||||
if provider.sync().await == true {
|
||||
println!("Sync complete after {} attempts (multiple attempts are due to forced errors in mocked behaviour)", attempt+1);
|
||||
break
|
||||
}
|
||||
}
|
||||
self.mock_behaviour.lock().unwrap().suspend();
|
||||
|
||||
print_provider(&provider, "after sync").await;
|
||||
|
||||
|
@ -62,7 +90,7 @@ impl TestFlavour {
|
|||
assert!(provider.remote().has_same_observable_content_as(provider.local()).await.unwrap());
|
||||
|
||||
// But also explicitely check that every item is expected
|
||||
let expected_provider = scenarii::populate_test_provider_after_sync(&self.scenarii).await;
|
||||
let expected_provider = scenarii::populate_test_provider_after_sync(&self.scenarii, Arc::clone(&self.mock_behaviour)).await;
|
||||
println!("\n");
|
||||
print_provider(&expected_provider, "expected after sync").await;
|
||||
|
||||
|
@ -71,7 +99,7 @@ impl TestFlavour {
|
|||
|
||||
// Perform a second sync, even if no change has happened, just to check
|
||||
println!("Syncing again");
|
||||
provider.sync().await.unwrap();
|
||||
provider.sync().await;
|
||||
assert!(provider.local() .has_same_observable_content_as(expected_provider.local() ).await.unwrap());
|
||||
assert!(provider.remote().has_same_observable_content_as(expected_provider.remote()).await.unwrap());
|
||||
}
|
||||
|
@ -85,7 +113,7 @@ async fn test_regular_sync() {
|
|||
let _ = env_logger::builder().is_test(true).try_init();
|
||||
|
||||
let flavour = TestFlavour::normal();
|
||||
flavour.run().await;
|
||||
flavour.run(1).await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
|
@ -93,7 +121,7 @@ async fn test_sync_empty_initial_local() {
|
|||
let _ = env_logger::builder().is_test(true).try_init();
|
||||
|
||||
let flavour = TestFlavour::first_sync_to_local();
|
||||
flavour.run().await;
|
||||
flavour.run(1).await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
|
@ -101,7 +129,7 @@ async fn test_sync_empty_initial_server() {
|
|||
let _ = env_logger::builder().is_test(true).try_init();
|
||||
|
||||
let flavour = TestFlavour::first_sync_to_server();
|
||||
flavour.run().await;
|
||||
flavour.run(1).await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
|
@ -109,9 +137,16 @@ async fn test_sync_transient_task() {
|
|||
let _ = env_logger::builder().is_test(true).try_init();
|
||||
|
||||
let flavour = TestFlavour::transient_task();
|
||||
flavour.run().await;
|
||||
flavour.run(1).await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_errors_in_regular_sync() {
|
||||
let _ = env_logger::builder().is_test(true).try_init();
|
||||
|
||||
let flavour = TestFlavour::normal_with_errors();
|
||||
flavour.run(100).await;
|
||||
}
|
||||
|
||||
#[cfg(feature = "integration_tests")]
|
||||
use my_tasks::{traits::CalDavSource,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue