use std::sync::Arc;
use {
super::*,
crate::{CodecError, CodecMetadata, DecodeResult},
};
struct MockCodec;
impl ContentCodec for MockCodec {
fn decode(&self, raw: &[u8]) -> Result<DecodeResult, CodecError> {
Ok(DecodeResult {
content: String::from_utf8_lossy(raw).into_owned(),
annotations: vec![],
metadata: CodecMetadata::new(ContentType::new("text/utf-8")),
lossy: false,
readonly: false,
})
}
fn encode(
&self,
content: &str,
_metadata: &CodecMetadata,
) -> Option<Result<Vec<u8>, CodecError>> {
Some(Ok(content.as_bytes().to_vec()))
}
}
struct MockFactory {
content_type: &'static str,
}
impl ContentCodecFactory for MockFactory {
fn create(&self, content_type: &ContentType) -> Option<Box<dyn ContentCodec>> {
if content_type.as_str() == self.content_type {
Some(Box::new(MockCodec))
} else {
None
}
}
fn supported_content_types(&self) -> Vec<&str> {
vec![self.content_type]
}
fn name(&self) -> &'static str {
self.content_type
}
}
struct MockClassifier {
result: Option<ContentType>,
prio: u8,
classifier_name: &'static str,
}
impl ContentClassifier for MockClassifier {
fn classify(&self, _raw: &[u8], _path: &str) -> Option<ContentType> {
self.result.clone()
}
fn priority(&self) -> u8 {
self.prio
}
fn name(&self) -> &'static str {
self.classifier_name
}
}
#[test]
fn factory_store_new_is_empty() {
let store = ContentCodecFactoryStore::new();
assert!(store.is_empty());
assert_eq!(store.len(), 0);
}
#[test]
fn factory_store_add_and_find() {
let store = ContentCodecFactoryStore::new();
store.add_factory(Arc::new(MockFactory {
content_type: "text/utf-8",
}));
assert_eq!(store.len(), 1);
assert!(!store.is_empty());
let ct = ContentType::new("text/utf-8");
assert!(store.find(&ct).is_some());
let ct2 = ContentType::new("binary/raw");
assert!(store.find(&ct2).is_none());
}
#[test]
fn factory_store_find_first_match() {
let store = ContentCodecFactoryStore::new();
store.add_factory(Arc::new(MockFactory {
content_type: "text/utf-8",
}));
store.add_factory(Arc::new(MockFactory {
content_type: "binary/raw",
}));
assert_eq!(store.len(), 2);
let ct = ContentType::new("binary/raw");
assert!(store.find(&ct).is_some());
}
#[test]
fn factory_store_take_drains() {
let store = ContentCodecFactoryStore::new();
store.add_factory(Arc::new(MockFactory {
content_type: "text/utf-8",
}));
let taken = store.take_factories();
assert_eq!(taken.len(), 1);
assert!(store.is_empty());
}
#[test]
fn factory_store_debug() {
let store = ContentCodecFactoryStore::new();
let debug = format!("{store:?}");
assert!(debug.contains("ContentCodecFactoryStore"));
assert!(debug.contains("count"));
}
#[test]
fn classifier_store_new_is_empty() {
let store = ContentClassifierStore::new();
assert!(store.is_empty());
assert_eq!(store.len(), 0);
}
#[test]
fn classifier_store_add() {
let store = ContentClassifierStore::new();
store.add(Arc::new(MockClassifier {
result: Some(ContentType::new("text/utf-8")),
prio: 10,
classifier_name: "utf8",
}));
assert_eq!(store.len(), 1);
assert!(!store.is_empty());
}
#[test]
fn classifier_store_classify_returns_first_match() {
let store = ContentClassifierStore::new();
store.add(Arc::new(MockClassifier {
result: Some(ContentType::new("text/utf-8")),
prio: 10,
classifier_name: "utf8",
}));
store.add(Arc::new(MockClassifier {
result: Some(ContentType::new("binary/raw")),
prio: 20,
classifier_name: "binary",
}));
let result = store.classify(b"hello", "test.txt");
assert_eq!(result, Some(ContentType::new("binary/raw")));
}
#[test]
fn classifier_store_classify_skips_none() {
let store = ContentClassifierStore::new();
store.add(Arc::new(MockClassifier {
result: None,
prio: 50,
classifier_name: "skip",
}));
store.add(Arc::new(MockClassifier {
result: Some(ContentType::new("text/utf-8")),
prio: 10,
classifier_name: "utf8",
}));
let result = store.classify(b"hello", "test.txt");
assert_eq!(result, Some(ContentType::new("text/utf-8")));
}
#[test]
fn classifier_store_classify_returns_none_when_no_match() {
let store = ContentClassifierStore::new();
store.add(Arc::new(MockClassifier {
result: None,
prio: 50,
classifier_name: "skip",
}));
assert_eq!(store.classify(b"hello", "test.txt"), None);
}
#[test]
fn classifier_store_classify_empty_store() {
let store = ContentClassifierStore::new();
assert_eq!(store.classify(b"hello", "test.txt"), None);
}
#[test]
fn classifier_store_priority_ordering() {
let store = ContentClassifierStore::new();
store.add(Arc::new(MockClassifier {
result: Some(ContentType::new("text/utf-8")),
prio: 10,
classifier_name: "utf8",
}));
store.add(Arc::new(MockClassifier {
result: Some(ContentType::new("text/euc-kr")),
prio: 50,
classifier_name: "cjk",
}));
store.add(Arc::new(MockClassifier {
result: Some(ContentType::new("binary/raw")),
prio: 20,
classifier_name: "binary",
}));
let result = store.classify(b"hello", "test.txt");
assert_eq!(result, Some(ContentType::new("text/euc-kr")));
}
#[test]
fn classifier_store_take_drains() {
let store = ContentClassifierStore::new();
store.add(Arc::new(MockClassifier {
result: None,
prio: 10,
classifier_name: "test",
}));
let taken = store.take_classifiers();
assert_eq!(taken.len(), 1);
assert!(store.is_empty());
}
#[test]
fn classifier_store_debug() {
let store = ContentClassifierStore::new();
let debug = format!("{store:?}");
assert!(debug.contains("ContentClassifierStore"));
assert!(debug.contains("count"));
}