use insta::assert_snapshot;
use ocr::core::*;
use ocr::lang::cjk::{CJKLanguage, CJKProcessor as LangCJKProcessor};
use ocr::recognition::RecognitionEngine;
use ocr::recognition::*;
use std::path::Path;
#[test]
fn test_basic_ocr_pipeline() {
assert!(LangCJKProcessor::is_cjk_character('中'));
assert!(LangCJKProcessor::is_cjk_character('ひ'));
assert!(LangCJKProcessor::is_cjk_character('한'));
assert!(!LangCJKProcessor::is_cjk_character('A'));
let model = LstmModelBuilder::new().build().unwrap();
assert_eq!(model.model_type(), ModelType::LSTM);
}
#[test]
fn test_cjk_language_detection() {
let processor = LangCJKProcessor::new();
let chinese_scores = processor.detect_cjk_language("中文测试");
assert!(!chinese_scores.is_empty());
assert!(chinese_scores
.iter()
.any(|(lang, _)| *lang == CJKLanguage::ChineseSimplified));
let japanese_scores = processor.detect_cjk_language("ひらがなカタカナ");
assert!(!japanese_scores.is_empty());
assert!(japanese_scores
.iter()
.any(|(lang, _)| *lang == CJKLanguage::Japanese));
let korean_scores = processor.detect_cjk_language("한글테스트");
assert!(!korean_scores.is_empty());
assert!(korean_scores
.iter()
.any(|(lang, _)| *lang == CJKLanguage::Korean));
}
#[test]
fn test_cjk_text_segmentation() {
let processor = LangCJKProcessor::new();
let chinese_result = processor
.segment_text("中文测试", CJKLanguage::ChineseSimplified)
.unwrap();
assert_eq!(chinese_result.language, CJKLanguage::ChineseSimplified);
assert!(!chinese_result.segments.is_empty());
let japanese_result = processor
.segment_text("ひらがなカタカナ", CJKLanguage::Japanese)
.unwrap();
assert_eq!(japanese_result.language, CJKLanguage::Japanese);
assert!(!japanese_result.segments.is_empty());
let korean_result = processor
.segment_text("한글테스트", CJKLanguage::Korean)
.unwrap();
assert_eq!(korean_result.language, CJKLanguage::Korean);
assert!(!korean_result.segments.is_empty());
}
#[test]
fn test_geometry_types() {
let coord = ICoord::new(10, 20);
assert_eq!(coord.x(), 10);
assert_eq!(coord.y(), 20);
assert_eq!(coord.length(), (10.0_f32.powi(2) + 20.0_f32.powi(2)).sqrt());
let fcoord = FCoord::new(10.5, 20.7);
assert_eq!(fcoord.x(), 10.5);
assert_eq!(fcoord.y(), 20.7);
let bbox = TBox::new(0, 0, 100, 200);
assert_eq!(bbox.width(), 100);
assert_eq!(bbox.height(), 200);
assert_eq!(bbox.area(), 20000);
assert!(!bbox.is_null());
let mut bbox2 = TBox::new(10, 10, 50, 50);
bbox2.move_by(ICoord::new(5, 5));
assert_eq!(bbox2.left(), 15);
assert_eq!(bbox2.bottom(), 15);
}
#[test]
fn test_text_structures() {
let blob_choice = BlobChoice::new(
65, 0.1,
0.9,
0, 10.0,
20.0,
0.0,
BlobChoiceClassifier::StaticClassifier,
);
assert_eq!(blob_choice.unichar_id, 65);
assert_eq!(blob_choice.rating, 0.1);
assert_eq!(blob_choice.certainty, 0.9);
let mut word_choice = WordChoice::new();
word_choice.add_choice(vec![blob_choice.clone()]);
assert_eq!(word_choice.text(), "A");
let mut word = Word::new();
word.set_flag(WordFlag::Bold, true);
word.set_flag(WordFlag::Italic, false);
word.correct_text = "Hello".to_string();
assert!(word.has_flag(WordFlag::Bold));
assert!(!word.has_flag(WordFlag::Italic));
assert_eq!(word.correct_text, "Hello");
}
#[tokio::test]
async fn test_model_management() {
let mut manager = ModelManager::new(DeviceType::CPU);
let config = ModelConfig {
model_type: ModelType::LSTM,
model_path: "test_model.lstm".to_string(),
supported_languages: vec![LanguageVariant::English],
input_shape: (32, 128, 1),
max_text_length: Some(50),
confidence_threshold: 0.7,
device: DeviceType::CPU,
quantization: Some(QuantizationType::FP32),
};
let model = LstmModel::new(config);
manager.load_model(model).await.unwrap();
assert!(manager.switch_model(ModelType::LSTM).is_ok());
assert!(manager.switch_model(ModelType::Transformer).is_err());
let available = manager.available_models();
assert!(available.contains(&ModelType::LSTM));
}
#[tokio::test]
async fn test_recognition_engine() {
let config = ModelConfig {
model_type: ModelType::LSTM,
model_path: "test_model.lstm".to_string(),
supported_languages: vec![LanguageVariant::English],
input_shape: (32, 128, 1),
max_text_length: Some(50),
confidence_threshold: 0.7,
device: DeviceType::CPU,
quantization: Some(QuantizationType::FP32),
};
let mut engine = BasicRecognitionEngine::new(config);
assert_eq!(engine.model_type(), ModelType::LSTM);
assert!(engine
.supported_languages()
.contains(&LanguageVariant::English));
assert!(engine.switch_model(ModelType::LSTM).await.is_ok());
}
#[test]
fn test_error_handling() {
let config = ModelConfig {
model_type: ModelType::LSTM,
model_path: "nonexistent_model.lstm".to_string(),
supported_languages: vec![LanguageVariant::English],
input_shape: (32, 128, 1),
max_text_length: Some(50),
confidence_threshold: 0.7,
device: DeviceType::CPU,
quantization: Some(QuantizationType::FP32),
};
let model = LstmModel::new(config);
let result = model.predict(b"test");
assert!(result.is_err());
if let Err(e) = result {
assert!(e.to_string().contains("not loaded"));
}
}
#[test]
fn test_cjk_character_categorization() {
assert!(LangCJKProcessor::is_cjk_character('中'));
assert!(LangCJKProcessor::is_cjk_character('ひ'));
assert!(LangCJKProcessor::is_cjk_character('한'));
assert!(!LangCJKProcessor::is_cjk_character('A'));
}
#[test]
fn test_model_configuration() {
let config = ModelConfig {
model_type: ModelType::Transformer,
model_path: "transformer_model.onnx".to_string(),
supported_languages: vec![
LanguageVariant::English,
LanguageVariant::ChineseSimplified,
LanguageVariant::Japanese,
],
input_shape: (224, 224, 3),
max_text_length: Some(200),
confidence_threshold: 0.8,
device: DeviceType::GPU,
quantization: Some(QuantizationType::FP16),
};
assert_eq!(config.model_type, ModelType::Transformer);
assert_eq!(config.input_shape, (224, 224, 3));
assert_eq!(config.device, DeviceType::GPU);
assert_eq!(config.quantization, Some(QuantizationType::FP16));
assert!(config
.supported_languages
.contains(&LanguageVariant::English));
assert!(config
.supported_languages
.contains(&LanguageVariant::ChineseSimplified));
assert!(config
.supported_languages
.contains(&LanguageVariant::Japanese));
}
#[test]
fn test_recognition_result_serialization() {
let mut result = ocr::core::RecognitionResult::new("Test Result".to_string(), 0.95);
result.metadata.processing_time_ms = 150;
result.metadata.language = Some("en".to_string());
let json = serde_json::to_string(&result).unwrap();
assert!(json.contains("Test Result"));
assert!(json.contains("0.95"));
let deserialized: ocr::core::RecognitionResult = serde_json::from_str(&json).unwrap();
assert_eq!(deserialized.text, "Test Result");
assert_eq!(deserialized.confidence, 0.95);
assert_eq!(deserialized.metadata.processing_time_ms, 150);
}
#[test]
fn test_mixed_script_segmentation() {
let processor = LangCJKProcessor::new();
let mixed_text = "Hello 世界";
let scores = processor.detect_cjk_language(mixed_text);
assert!(!scores.is_empty());
let mixed_japanese = "Hello こんにちは";
let japanese_scores = processor.detect_cjk_language(mixed_japanese);
assert!(!japanese_scores.is_empty());
let mixed_korean = "Hello 안녕하세요";
let korean_scores = processor.detect_cjk_language(mixed_korean);
assert!(!korean_scores.is_empty());
}
#[test]
fn test_model_builder_pattern() {
let config = ModelConfig {
model_type: ModelType::LSTM,
model_path: "custom_model.lstm".to_string(),
supported_languages: vec![LanguageVariant::English, LanguageVariant::ChineseSimplified],
input_shape: (64, 256, 1),
max_text_length: Some(100),
confidence_threshold: 0.6,
device: DeviceType::GPU,
quantization: Some(QuantizationType::INT8),
};
let model = LstmModelBuilder::new().with_config(config).build().unwrap();
assert_eq!(model.model_type(), ModelType::LSTM);
assert!(model.supports_language(&LanguageVariant::English));
assert!(model.supports_language(&LanguageVariant::ChineseSimplified));
assert!(model.supports_language(&LanguageVariant::Korean));
}
#[test]
fn test_device_type_handling() {
let cpu_manager = ModelManager::new(DeviceType::CPU);
let gpu_manager = ModelManager::new(DeviceType::GPU);
let auto_manager = ModelManager::new(DeviceType::Auto);
assert_eq!(cpu_manager.available_models().len(), 0);
assert_eq!(gpu_manager.available_models().len(), 0);
assert_eq!(auto_manager.available_models().len(), 0);
}
#[test]
fn test_quantization_types() {
let quantization_types = vec![
QuantizationType::FP32,
QuantizationType::FP16,
QuantizationType::INT8,
QuantizationType::Dynamic,
];
for qt in quantization_types {
let config = ModelConfig {
model_type: ModelType::LSTM,
model_path: "test.lstm".to_string(),
supported_languages: vec![LanguageVariant::English],
input_shape: (32, 128, 1),
max_text_length: Some(50),
confidence_threshold: 0.7,
device: DeviceType::CPU,
quantization: Some(qt),
};
assert_eq!(config.quantization, Some(qt));
}
}