Skip to content

Commit 5073cd1

Browse files
committed
test(base): Add tests for EventCacheStoreLock::lock_*.
This patch adds tests for `EventCacheStoreLock::lock` and `lock_unchecked`.
1 parent 4ace281 commit 5073cd1

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

0 commit comments

Comments
 (0)