use std::path::PathBuf;
use tempfile::TempDir;
fn create_test_file_with_emoji(content: &str) -> (TempDir, PathBuf) {
let temp_dir = TempDir::new().unwrap();
let file_path = temp_dir.path().join("test_emoji.rs");
std::fs::write(&file_path, content).unwrap();
(temp_dir, file_path)
}
#[test]
fn test_extract_symbol_content_with_emoji_comment() {
let source = r#"
/// This function says hi
fn greet(name: &str) -> String {
format!("Hello, {}!", name)
}
"#;
let (_temp_dir, file_path) = create_test_file_with_emoji(source);
let content = std::fs::read(&file_path).unwrap();
let result = magellan::extract_symbol_content_safe(&content, 0, content.len());
assert!(result.is_some());
assert_eq!(result.unwrap(), source);
}
#[test]
fn test_extract_symbol_content_cjk_characters() {
let source = r#"
// 你好世界 - Hello World in Chinese
fn 计算总和(a: i32, b: i32) -> i32 {
a + b
}
"#;
let (_temp_dir, file_path) = create_test_file_with_emoji(source);
let content = std::fs::read(&file_path).unwrap();
let result = magellan::extract_symbol_content_safe(&content, 0, content.len());
assert!(result.is_some());
assert_eq!(result.unwrap(), source);
}
#[test]
fn test_extract_symbol_content_accented_characters() {
let source = r#"
// Fonction pour calculer la somme
fn calculer_somme(a: i32, b: i32) -> i32 {
a + b
}
"#;
let (_temp_dir, file_path) = create_test_file_with_emoji(source);
let content = std::fs::read(&file_path).unwrap();
let result = magellan::extract_symbol_content_safe(&content, 0, content.len());
assert!(result.is_some());
assert_eq!(result.unwrap(), source);
}
#[test]
fn test_extract_context_with_multi_byte_chars() {
let source = "line1\nline2 你好\nline3 \nline4";
let (_temp_dir, file_path) = create_test_file_with_emoji(source);
let content = std::fs::read(&file_path).unwrap();
let result = magellan::extract_context_safe(&content, 6, 15, 5);
assert!(result.is_some());
let context = result.unwrap();
assert!(context.contains("line2"));
}
#[test]
fn test_extract_symbol_splits_emoji_at_end() {
let source: Vec<u8> = vec![
b'f', b'n', b' ', b't', b'e', b's', b't', b'(', b')', b' ', b'{', b'\n', b' ', b' ', b'/',
b'/', 0xF0, 0x9F, 0x91, 0x8B, b'\n', b'}',
];
let result = magellan::extract_symbol_content_safe(&source, 0, 16);
assert!(result.is_some());
let extracted = result.unwrap();
assert!(!extracted.contains('\u{1f44b}'));
}
#[test]
fn test_extract_symbol_splits_cjk_at_end() {
let mut source = "fn test() {\n".to_string();
source.push_str("// "); source.push('你'); source.push('\n');
source.push('}');
let content = source.as_bytes();
let ni_pos = source.find('你').unwrap();
let result = magellan::extract_symbol_content_safe(content, 0, ni_pos + 1);
assert!(result.is_some());
let extracted = result.unwrap();
assert!(!extracted.contains('你'));
}
#[test]
fn test_extract_symbol_start_splits_multi_byte_returns_none() {
let source = "fn test() \u{1f44b} {}";
let content = source.as_bytes();
let emoji_pos = source.find('\u{1f44b}').unwrap();
let result = magellan::extract_symbol_content_safe(content, emoji_pos + 1, content.len());
assert!(result.is_none());
}
#[test]
fn test_extract_symbol_out_of_bounds() {
let source = "fn test() {}";
let content = source.as_bytes();
assert!(magellan::extract_symbol_content_safe(content, 100, 200).is_none());
assert!(magellan::extract_symbol_content_safe(content, 0, 1000).is_none());
assert!(magellan::extract_symbol_content_safe(content, 10, 5).is_none());
}
#[test]
fn test_extract_context_various_sizes() {
let source = "a\nb\nc\nd\ne\nf\ng\nh\ni\nj";
let content = source.as_bytes();
for context_size in [0, 1, 5, 10, 100] {
let result = magellan::extract_context_safe(content, 2, 4, context_size);
assert!(
result.is_some(),
"Failed with context_size={}",
context_size
);
}
}
#[test]
fn test_extract_symbol_empty_source() {
let source = "";
let content = source.as_bytes();
let result = magellan::extract_symbol_content_safe(content, 0, 0);
assert_eq!(result, Some("".to_string()));
}
#[test]
fn test_extract_context_empty_source() {
let source = "";
let content = source.as_bytes();
let result = magellan::extract_context_safe(content, 0, 0, 10);
assert_eq!(result, Some("".to_string()));
}
#[test]
fn test_extract_symbol_with_mixed_utf8_widths() {
let source = "fn héllo() { // 你好 \u{1f44b} }";
let content = source.as_bytes();
let result = magellan::extract_symbol_content_safe(content, 0, content.len());
assert_eq!(result, Some(source.to_string()));
let hello_start = source.find("héllo").unwrap();
let hello_end = hello_start + "héllo".len();
let result = magellan::extract_symbol_content_safe(content, hello_start, hello_end);
assert_eq!(result, Some("héllo".to_string()));
}
#[test]
fn test_safe_extraction_with_invalid_utf8() {
let invalid_utf8: &[u8] = &[0xFF, 0xFE, 0xFD, 0xFA];
let result = magellan::extract_symbol_content_safe(invalid_utf8, 0, invalid_utf8.len());
assert!(result.is_none());
}
#[test]
fn test_context_extraction_with_newlines() {
let source = "line1\nline2\nline3\nline4\nline5";
let content = source.as_bytes();
let line3_start = source.find("line3").unwrap();
let line3_end = line3_start + 5;
let result = magellan::extract_context_safe(content, line3_start, line3_end, 6);
assert!(result.is_some());
let context = result.unwrap();
assert!(context.contains("line2"));
assert!(context.contains("line3"));
assert!(context.contains("line4"));
}