use std::{borrow::Cow, collections::HashMap};
use fluent_zero::{
CacheEntry, CacheStore, ConcurrentFluentBundle, FluentArgs, FluentResource, LanguageIdentifier,
lookup_dynamic, lookup_static, set_lang,
};
fn create_bundle(lang: &str, source: &str) -> ConcurrentFluentBundle<FluentResource> {
let lang_id: LanguageIdentifier = lang.parse().unwrap();
let mut bundle = ConcurrentFluentBundle::new_concurrent(vec![lang_id]);
bundle.set_use_isolating(false);
let res = FluentResource::try_new(source.to_string()).unwrap();
bundle.add_resource(res).unwrap();
bundle
}
struct MockCache {
data: HashMap<String, HashMap<&'static str, CacheEntry>>,
}
impl MockCache {
fn new() -> Self {
Self {
data: HashMap::new(),
}
}
fn insert_static(&mut self, lang: &str, key: &'static str, value: &'static str) {
self.data
.entry(lang.to_string())
.or_default()
.insert(key, CacheEntry::Static(value));
}
fn insert_dynamic(&mut self, lang: &str, key: &'static str) {
self.data
.entry(lang.to_string())
.or_default()
.insert(key, CacheEntry::Dynamic);
}
}
impl CacheStore for MockCache {
fn get_entry(&self, lang: &str, key: &str) -> Option<CacheEntry> {
self.data.get(lang).and_then(|c| c.get(key)).copied()
}
}
struct MockLocales {
bundles: HashMap<String, ConcurrentFluentBundle<FluentResource>>,
cache: MockCache,
}
impl MockLocales {
fn new() -> Self {
let en_us: LanguageIdentifier = "en-US".parse().unwrap();
let fr_fr: LanguageIdentifier = "fr-FR".parse().unwrap();
let mut bundles = HashMap::new();
bundles.insert(
en_us.to_string(),
create_bundle(
"en-US",
r#"
hello = Hello World
welcome = Welcome { $name }
emoji = { "😀" }
"#,
),
);
bundles.insert(
fr_fr.to_string(),
create_bundle("fr-FR", "hello = Bonjour le monde"),
);
let mut cache = MockCache::new();
cache.insert_static("en-US", "hello", "Hello World");
cache.insert_static("fr-FR", "hello", "Bonjour le monde");
cache.insert_dynamic("en-US", "welcome");
cache.insert_dynamic("en-US", "emoji");
Self { bundles, cache }
}
}
#[test]
fn t01_static_hit_returns_borrowed() {
let mocks = MockLocales::new();
set_lang("en-US".parse().unwrap());
let result = lookup_static(&mocks.bundles, &mocks.cache, "hello");
assert_eq!(result, "Hello World");
assert!(matches!(result, Cow::Borrowed(_)));
}
#[test]
fn t02_static_miss_hits_bundle_via_dynamic_entry() {
let mocks = MockLocales::new();
set_lang("en-US".parse().unwrap());
let result = lookup_static(&mocks.bundles, &mocks.cache, "emoji");
assert_eq!(result, "😀");
}
#[test]
fn t03_dynamic_lookup_always_returns_owned_if_args_used() {
let mocks = MockLocales::new();
set_lang("en-US".parse().unwrap());
let mut args = FluentArgs::new();
args.set("name", "Alice");
let result = lookup_dynamic(&mocks.bundles, &mocks.cache, "welcome", &args);
assert_eq!(result, "Welcome Alice");
}
#[test]
fn t04_fallback_static_returns_borrowed() {
let mocks = MockLocales::new();
set_lang("de-DE".parse().unwrap());
let result = lookup_static(&mocks.bundles, &mocks.cache, "hello");
assert_eq!(result, "Hello World");
assert!(matches!(result, Cow::Borrowed(_)));
}
#[test]
fn t06_language_switch_updates_static_return() {
let mocks = MockLocales::new();
set_lang("en-US".parse().unwrap());
assert_eq!(
lookup_static(&mocks.bundles, &mocks.cache, "hello"),
"Hello World"
);
set_lang("fr-FR".parse().unwrap());
assert_eq!(
lookup_static(&mocks.bundles, &mocks.cache, "hello"),
"Bonjour le monde"
);
}
#[test]
fn t08_verify_zero_copy_pointer_address() {
let mocks = MockLocales::new();
set_lang("en-US".parse().unwrap());
let entry = mocks.cache.data.get("en-US").unwrap().get("hello").unwrap();
let cached_str_ref = match entry {
CacheEntry::Static(s) => s,
CacheEntry::Dynamic => panic!("Expected static"),
};
let cached_ptr = std::ptr::from_ref::<str>(*cached_str_ref);
let result = lookup_static(&mocks.bundles, &mocks.cache, "hello");
if let Cow::Borrowed(res_str) = result {
let res_ptr = std::ptr::from_ref::<str>(res_str);
assert_eq!(
cached_ptr, res_ptr,
"Returned string should point to the exact same memory address."
);
} else {
panic!("Expected Borrowed result");
}
}
#[test]
fn t09_verify_charset_merging() {
let app_charset = "abc😀";
let dep_charset = "cde";
let ui_charset = "zxa";
let merged = fluent_zero::join_charsets(&[app_charset, dep_charset, ui_charset]);
assert_eq!(merged, "abcdexz😀");
}