use rust_ef::prelude::*;
use rust_ef::{entity, EntityType};
use rust_ef_sqlite::DbContextOptionsBuilderExt;
use std::any::TypeId;
#[derive(EntityType, Default, Clone, Debug, PartialEq)]
#[table("cache_blogs")]
struct CacheBlog {
#[primary_key]
#[auto_increment]
id: i64,
rating: i32,
}
#[derive(Default)]
struct CacheBlogConfig;
#[entity(CacheBlog)]
impl IEntityTypeConfiguration<CacheBlog> for CacheBlogConfig {
fn configure(&self, e: &mut EntityTypeBuilder<'_, CacheBlog>) {
e.to_table("cache_blogs_v2");
}
}
#[test]
fn test_cache_populates_metadata_correctly() {
let mut options_builder = DbContextOptionsBuilder::new();
options_builder.use_sqlite_in_memory();
let options = options_builder.build();
let ctx1 = DbContext::from_options(&options).expect("ctx1 from_options");
let ctx2 = DbContext::from_options(&options).expect("ctx2 from_options");
assert!(
ctx1.entity_metas_contains::<CacheBlog>(),
"ctx1 should have CacheBlog metadata from cache"
);
assert!(
ctx2.entity_metas_contains::<CacheBlog>(),
"ctx2 should have CacheBlog metadata from cache (shared options)"
);
let metas1 = ctx1.model_builder().build();
let metas2 = ctx2.model_builder().build();
let blog_meta1 = metas1
.iter()
.find(|m| m.type_name.contains("CacheBlog"))
.expect("CacheBlog meta in ctx1 build output");
let blog_meta2 = metas2
.iter()
.find(|m| m.type_name.contains("CacheBlog"))
.expect("CacheBlog meta in ctx2 build output");
assert_eq!(
blog_meta1.table_name, "cache_blogs_v2",
"ctx1 should have Fluent override from cached config"
);
assert_eq!(
blog_meta2.table_name, "cache_blogs_v2",
"ctx2 should have same Fluent override from cached config"
);
}
#[test]
fn test_per_instance_model_mutation_isolation() {
let mut options_builder = DbContextOptionsBuilder::new();
options_builder.use_sqlite_in_memory();
let options = options_builder.build();
let mut ctx1 = DbContext::from_options(&options).expect("ctx1 from_options");
let ctx2 = DbContext::from_options(&options).expect("ctx2 from_options");
ctx1.model()
.has_query_filter::<CacheBlog>(linq!(filter |b: CacheBlog| b.rating > 5));
let blog_type_id = TypeId::of::<CacheBlog>();
assert!(
ctx1.model_builder()
.get_query_filter(&blog_type_id)
.is_some(),
"ctx1 should have the query filter it just registered"
);
assert!(
ctx2.model_builder()
.get_query_filter(&blog_type_id)
.is_none(),
"ctx2 should not see ctx1's per-instance query filter (cache must not be mutated)"
);
}
#[test]
fn test_discover_entities_noop_is_safe() {
let mut options_builder = DbContextOptionsBuilder::new();
options_builder.use_sqlite_in_memory();
let options = options_builder.build();
let mut ctx = DbContext::from_options(&options).expect("ctx from_options");
assert!(ctx.entity_metas_contains::<CacheBlog>());
ctx.discover_entities().expect("discover_entities no-op");
assert!(
ctx.entity_metas_contains::<CacheBlog>(),
"discover_entities() no-op must not clear pre-populated metadata"
);
}