extern crate env_logger;
use remember_this::*;
use std::sync::atomic::Ordering;
#[tokio::test]
async fn test_simple() {
let _ = env_logger::builder().is_test(true).try_init();
let manager = CacheManager::new(
&CacheManagerOptions::builder()
.path("/tmp/test_simple.db")
.use_temporary(true)
.build(),
)
.unwrap();
let cache = manager
.cache("cache_1", &CacheOptions::builder().purge(true).build())
.unwrap();
for i in 0..100 {
let obtained = cache.get(&i).unwrap();
assert!(obtained.is_none(), "Cache should initially be empty");
}
for i in 0..100 {
let was_evaluated = std::sync::atomic::AtomicBool::new(false);
let obtained = cache
.get_or_insert_infallible(&i, async {
let _ = was_evaluated.store(true, Ordering::SeqCst);
i * i
})
.await
.unwrap();
assert_eq!(
*obtained,
i * i,
"The cache should return the right value when it's evaluating."
);
assert_eq!(
was_evaluated.load(Ordering::SeqCst),
true,
"The cache should be evaluating when there is no data."
);
}
for _ in 0..3 {
for i in 0..100 {
let was_evaluated = std::sync::atomic::AtomicBool::new(false);
let obtained = cache
.get_or_insert_infallible(&i, async {
let _ = was_evaluated.store(true, Ordering::SeqCst);
i * i
})
.await
.unwrap();
assert_eq!(
*obtained,
i * i,
"The cache should return the right value when it's not evaluating."
);
assert_eq!(
was_evaluated.load(Ordering::SeqCst),
false,
"The cache should not be evaluating when there is data already."
);
assert_eq!(cache.get(&i).unwrap().unwrap(), obtained);
}
}
}
#[tokio::test]
async fn test_format_change() {
let _ = env_logger::builder().is_test(true).try_init();
let manager = CacheManager::new(
&CacheManagerOptions::builder()
.path("/tmp/test_format_change.db")
.use_temporary(true)
.build(),
)
.unwrap();
{
let cache = manager
.cache("cache_2", &CacheOptions::builder().purge(true).build())
.unwrap();
for i in 0..100 {
cache
.get_or_insert_infallible(&i, async { i * i })
.await
.unwrap();
}
}
{
let cache = manager
.cache("cache_2", &CacheOptions::builder().purge(true).build())
.unwrap();
for i in 0..100 {
let was_evaluated = std::sync::atomic::AtomicBool::new(false);
let found = cache
.get_or_insert_infallible(&i, async {
was_evaluated.store(true, Ordering::SeqCst);
format!("{}", i * i)
})
.await
.unwrap();
assert_eq!(
*found,
format!("{}", i * i),
"When silently overwriting because of format change, we get the right result"
);
assert_eq!(
was_evaluated.load(Ordering::SeqCst),
true,
"When silently overwriting because of format change, we executed the thunk"
);
}
}
{
let cache = manager
.cache("cache_2", &CacheOptions::builder().purge(true).build())
.unwrap();
for i in 0..100 {
let was_evaluated = std::sync::atomic::AtomicBool::new(false);
let found = cache
.get_or_insert_infallible(&i, async {
was_evaluated.store(true, Ordering::SeqCst);
i % 2 == 0
})
.await
.unwrap();
assert_eq!(
*found,
i % 2 == 0,
"When silently overwriting because of format change, we get the right result"
);
assert_eq!(
was_evaluated.load(Ordering::SeqCst),
true,
"When silently overwriting because of format change, we executed the thunk"
);
}
}
}
#[tokio::test]
async fn test_reopen() {
let _ = env_logger::builder().is_test(true).try_init();
let manager = CacheManager::new(
&CacheManagerOptions::builder()
.path("/tmp/test_reopen.db")
.use_temporary(true)
.build(),
)
.unwrap();
async fn walk_through_cache(
manager: &CacheManager,
options: &CacheOptions,
should_execute: bool,
subtest: &str,
) {
eprintln!("Starting test {}", subtest);
let cache = manager.cache("cache_1", &options).unwrap();
for i in 0..100 {
eprintln!("{}:{}", subtest, i);
let was_evaluated = std::sync::atomic::AtomicBool::new(false);
let obtained = cache
.get_or_insert_infallible(&i, async {
let _ = was_evaluated.store(true, Ordering::SeqCst);
i * i
})
.await
.unwrap();
assert_eq!(
*obtained,
i * i,
"The cache should return the right value: {}.",
subtest
);
assert_eq!(
was_evaluated.load(Ordering::SeqCst),
should_execute,
"The cache should be evaluating: {}.",
subtest
);
}
}
walk_through_cache(
&manager,
&CacheOptions::builder().purge(true).build(),
true,
"initializer",
)
.await;
walk_through_cache(
&manager,
&CacheOptions::builder().build(),
false,
"simple reopen",
)
.await;
walk_through_cache(
&manager,
&CacheOptions::builder().purge(true).build(),
true,
"purge",
)
.await;
walk_through_cache(
&manager,
&CacheOptions::builder().build(),
false,
"reopen 2",
)
.await;
walk_through_cache(
&manager,
&CacheOptions::builder().version(1).build(),
true,
"change version number",
)
.await;
walk_through_cache(
&manager,
&CacheOptions::builder().version(1).build(),
false,
"reopen with same new version",
)
.await;
}