Skip to content

Commit cb04c54

Browse files
committed
test(base): Add tests for EventCacheStoreLock::lock_*.
This patch adds tests for `EventCacheStoreLock::lock` and `lock_unchecked`.
1 parent 529e963 commit cb04c54

File tree

1 file changed

+101
-0
lines changed
  • crates/matrix-sdk-base/src/event_cache/store

1 file changed

+101
-0
lines changed

crates/matrix-sdk-base/src/event_cache/store/mod.rs

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,3 +311,104 @@ impl BackingStore for LockableEventCacheStore {
311311
})
312312
}
313313
}
314+
315+
#[cfg(all(test, not(target_arch = "wasm32")))] // because time is a thing
316+
mod tests {
317+
use std::{sync::Arc, time::Duration};
318+
319+
use matrix_sdk_common::store_locks::MAX_BACKOFF_MS;
320+
use matrix_sdk_test::async_test;
321+
use ruma::user_id;
322+
use tokio::time::sleep;
323+
324+
use super::MemoryStore;
325+
use crate::{store::StoreConfig, test_utils::logged_in_base_client_with_store_config};
326+
327+
#[async_test]
328+
async fn test_not_poisoned_lock() {
329+
let client = logged_in_base_client_with_store_config(
330+
Some(user_id!("@client:sdk.rust")),
331+
StoreConfig::new("holderA".to_string()),
332+
)
333+
.await;
334+
335+
let event_cache_store_lock = client.event_cache_store();
336+
337+
// `lock_unchecked` is okay.
338+
let guard = event_cache_store_lock.lock_unchecked().await;
339+
assert!(guard.is_ok()); // lock has been acquired and may or may not be poisoned
340+
341+
// `lock` is okay.
342+
let guard = event_cache_store_lock.lock().await;
343+
344+
assert!(guard.is_ok()); // lock has been acquired
345+
assert!(guard.unwrap().is_ok()); // lock is not poisoned
346+
}
347+
348+
#[async_test]
349+
async fn test_poisoned_lock() {
350+
// Use the same memory store between clients A and B.
351+
let memory_store = Arc::new(MemoryStore::new());
352+
353+
let client_a = logged_in_base_client_with_store_config(
354+
Some(user_id!("@client_a:sdk.rust")),
355+
StoreConfig::new("holderA".to_string()).event_cache_store(memory_store.clone()),
356+
)
357+
.await;
358+
359+
let client_b = logged_in_base_client_with_store_config(
360+
Some(user_id!("@client_b:sdk.rust")),
361+
StoreConfig::new("holderB".to_string()).event_cache_store(memory_store),
362+
)
363+
.await;
364+
365+
let event_cache_store_lock_a = client_a.event_cache_store();
366+
let event_cache_store_lock_b = client_b.event_cache_store();
367+
368+
// Client A can take the lock because no one has taken it so far.
369+
{
370+
// `lock` is okay.
371+
let guard = event_cache_store_lock_a.lock().await;
372+
373+
assert!(guard.is_ok()); // lock has been acquired
374+
assert!(guard.unwrap().is_ok()); // lock is not poisoned
375+
}
376+
377+
sleep(Duration::from_millis(MAX_BACKOFF_MS as u64 + 100)).await;
378+
379+
// Client B can take the lock since all locks from A are expired, but
380+
// now, B is poisoned because the content of the event cache might have
381+
// been modified (if someone takes a lock, it's probably for a good
382+
// reason, right?).
383+
{
384+
// `lock` is okay.
385+
let guard = event_cache_store_lock_b.lock().await;
386+
387+
assert!(guard.is_ok()); // lock has been acquired
388+
assert!(guard.unwrap().is_err()); // lock is poisoned!
389+
}
390+
391+
sleep(Duration::from_millis(MAX_BACKOFF_MS as u64 + 100)).await;
392+
393+
// Client A can take the lock since all locks from B are expired, but
394+
// now, A is poisoned. Let's not test `lock` but `lock_unchecked` this
395+
// time.
396+
{
397+
// `lock_unchecked` is okay.
398+
let guard = event_cache_store_lock_a.lock_unchecked().await;
399+
400+
assert!(guard.is_ok()); // lock has been acquired and might be
401+
// poisoned, we don't know with this method
402+
}
403+
404+
// Client A can still take the lock because it is holding it. The lock
405+
// is no more poisoned.
406+
{
407+
// `lock` is okay.
408+
let guard = event_cache_store_lock_a.lock().await;
409+
410+
assert!(guard.is_ok()); // lock has been acquired
411+
assert!(guard.unwrap().is_ok()); // lock is not poisoned
412+
}
413+
}
414+
}

0 commit comments

Comments
 (0)