#![cfg(feature = "audio")]
#![allow(unused_imports)]
#![allow(dead_code)]
use std::collections::HashMap;
use std::fs;
use std::path::Path;
use unity_asset_decode::audio::AudioCompressionFormat;
use unity_asset_decode::bundle::load_bundle_from_memory;
use unity_asset_decode::object::UnityObject;
use unity_asset_decode::unity_version::UnityVersion;
const SAMPLES_DIR: &str = "tests/samples";
#[test]
#[ignore]
fn test_comprehensive_compatibility_report() {
println!("=== Unity Asset Parser - Comprehensive Compatibility Report ===");
println!(
"Generated on: {}",
std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap()
.as_secs()
);
println!();
let sample_files = get_sample_files();
let mut report = CompatibilityReport::new();
for file_path in sample_files {
let file_name = file_path.file_name().unwrap_or_default().to_string_lossy();
println!("📁 Processing: {}", file_name);
if let Ok(data) = fs::read(&file_path) {
match load_bundle_from_memory(data) {
Ok(bundle) => {
report.successful_files += 1;
println!(" ✅ Bundle loaded successfully");
println!(" 📊 Assets: {}", bundle.assets.len());
for asset in &bundle.assets {
report.total_assets += 1;
println!(" 📄 Asset with {} objects", asset.objects.len());
for asset_object_info in &asset.objects {
report.total_objects += 1;
let unity_object =
UnityObject::from_serialized_file(asset, asset_object_info)
.unwrap_or_else(|_| {
let fallback_data = asset
.object_bytes(asset_object_info)
.map(|b| b.to_vec())
.unwrap_or_default();
UnityObject::from_raw(
asset_object_info.type_id,
asset_object_info.path_id,
fallback_data,
)
});
let class_name = unity_object.class_name().to_string();
*report.object_types.entry(class_name.clone()).or_insert(0) += 1;
report.parsed_objects += 1;
let unity_class = unity_object.as_unity_class();
match class_name.as_str() {
"Texture2D" => {
report.texture_objects += 1;
analyze_texture(unity_class, &mut report);
}
"AudioClip" => {
report.audio_objects += 1;
analyze_audio(unity_class, &mut report);
}
"GameObject" => {
report.gameobject_objects += 1;
}
"Transform" => {
report.transform_objects += 1;
}
"Sprite" => {
report.sprite_objects += 1;
}
"SpriteAtlas" => {
report.sprite_atlas_objects += 1;
}
_ => {}
}
}
}
}
Err(e) => {
report.failed_files += 1;
println!(" ❌ Failed to load: {}", e);
let error_msg = e.to_string();
if error_msg.contains("LZMA") {
report.lzma_failures += 1;
} else if error_msg.contains("Not enough data") {
report.data_failures += 1;
} else {
report.other_failures += 1;
}
}
}
} else {
report.failed_files += 1;
println!(" ❌ Failed to read file");
}
println!();
}
generate_report(&report);
let success_rate = (report.successful_files as f64 / report.total_files() as f64) * 100.0;
let parse_rate = (report.parsed_objects as f64 / report.total_objects as f64) * 100.0;
assert!(
success_rate >= 60.0,
"File success rate should be at least 60%, got {:.1}%",
success_rate
);
assert!(
parse_rate >= 90.0,
"Object parse rate should be at least 90%, got {:.1}%",
parse_rate
);
assert!(
report.total_objects >= 40,
"Should process at least 40 objects total"
);
println!("✅ Comprehensive compatibility report completed successfully!");
}
fn get_sample_files() -> Vec<std::path::PathBuf> {
let samples_path = Path::new(SAMPLES_DIR);
if !samples_path.exists() {
return Vec::new();
}
let mut files = Vec::new();
if let Ok(entries) = fs::read_dir(samples_path) {
for entry in entries.flatten() {
let path = entry.path();
if path.is_file() {
files.push(path);
}
}
}
files
}
#[derive(Debug, Default)]
struct CompatibilityReport {
successful_files: usize,
failed_files: usize,
total_assets: usize,
total_objects: usize,
parsed_objects: usize,
object_types: HashMap<String, usize>,
texture_objects: usize,
audio_objects: usize,
gameobject_objects: usize,
transform_objects: usize,
sprite_objects: usize,
sprite_atlas_objects: usize,
texture_formats: HashMap<String, usize>,
audio_formats: HashMap<String, usize>,
lzma_failures: usize,
data_failures: usize,
other_failures: usize,
}
impl CompatibilityReport {
fn new() -> Self {
Self::default()
}
fn total_files(&self) -> usize {
self.successful_files + self.failed_files
}
}
fn analyze_texture(unity_class: &unity_asset_core::UnityClass, report: &mut CompatibilityReport) {
if let Some(unity_asset_core::UnityValue::Integer(format_id)) =
unity_class.get("m_TextureFormat")
{
let format_name = get_texture_format_name(*format_id as i32);
*report.texture_formats.entry(format_name).or_insert(0) += 1;
}
}
fn analyze_audio(unity_class: &unity_asset_core::UnityClass, report: &mut CompatibilityReport) {
if let Some(unity_asset_core::UnityValue::Integer(format_id)) =
unity_class.get("m_CompressionFormat")
{
let format = AudioCompressionFormat::from(*format_id as i32);
let format_name = format!("{:?}", format);
*report.audio_formats.entry(format_name).or_insert(0) += 1;
}
}
fn get_texture_format_name(format_id: i32) -> String {
match format_id {
3 => "RGB24".to_string(),
4 => "RGBA32".to_string(),
5 => "ARGB32".to_string(),
10 => "DXT1".to_string(),
12 => "DXT5".to_string(),
14 => "BGRA32".to_string(),
29 => "DXT1Crunched".to_string(),
30 => "DXT5Crunched".to_string(),
38 => "ETC_RGB4".to_string(),
41 => "ETC2_RGB".to_string(),
43 => "ETC2_RGBA8".to_string(),
_ => format!("Format_{}", format_id),
}
}
fn generate_report(report: &CompatibilityReport) {
println!("📊 === COMPREHENSIVE COMPATIBILITY REPORT ===");
println!();
println!("🗂️ FILE PROCESSING SUMMARY");
println!(" Total files processed: {}", report.total_files());
println!(
" Successfully loaded: {} ({:.1}%)",
report.successful_files,
(report.successful_files as f64 / report.total_files() as f64) * 100.0
);
println!(
" Failed to load: {} ({:.1}%)",
report.failed_files,
(report.failed_files as f64 / report.total_files() as f64) * 100.0
);
println!();
println!("🎯 OBJECT PROCESSING SUMMARY");
println!(" Total assets: {}", report.total_assets);
println!(" Total objects: {}", report.total_objects);
println!(
" Successfully parsed: {} ({:.1}%)",
report.parsed_objects,
(report.parsed_objects as f64 / report.total_objects as f64) * 100.0
);
println!();
println!("📋 OBJECT TYPE DISTRIBUTION");
let mut sorted_types: Vec<_> = report.object_types.iter().collect();
sorted_types.sort_by(|a, b| b.1.cmp(a.1));
for (type_name, count) in sorted_types.iter().take(10) {
println!(" {}: {} objects", type_name, count);
}
println!();
println!("🔍 SPECIFIC OBJECT ANALYSIS");
println!(" Texture2D objects: {}", report.texture_objects);
println!(" AudioClip objects: {}", report.audio_objects);
println!(" GameObject objects: {}", report.gameobject_objects);
println!(" Transform objects: {}", report.transform_objects);
println!(" Sprite objects: {}", report.sprite_objects);
println!(" SpriteAtlas objects: {}", report.sprite_atlas_objects);
println!();
if !report.texture_formats.is_empty() {
println!("🖼️ TEXTURE FORMAT ANALYSIS");
let mut sorted_formats: Vec<_> = report.texture_formats.iter().collect();
sorted_formats.sort_by(|a, b| b.1.cmp(a.1));
for (format_name, count) in sorted_formats {
println!(" {}: {} textures", format_name, count);
}
println!();
}
if !report.audio_formats.is_empty() {
println!("🔊 AUDIO FORMAT ANALYSIS");
let mut sorted_formats: Vec<_> = report.audio_formats.iter().collect();
sorted_formats.sort_by(|a, b| b.1.cmp(a.1));
for (format_name, count) in sorted_formats {
println!(" {}: {} audio clips", format_name, count);
}
println!();
}
if report.failed_files > 0 {
println!("❌ FAILURE ANALYSIS");
println!(" LZMA decompression failures: {}", report.lzma_failures);
println!(" Data reading failures: {}", report.data_failures);
println!(" Other failures: {}", report.other_failures);
println!();
}
println!("🏆 COMPATIBILITY ASSESSMENT");
let file_success_rate = (report.successful_files as f64 / report.total_files() as f64) * 100.0;
let parse_success_rate = (report.parsed_objects as f64 / report.total_objects as f64) * 100.0;
println!(" File loading success rate: {:.1}%", file_success_rate);
println!(" Object parsing success rate: {:.1}%", parse_success_rate);
let overall_score = (file_success_rate + parse_success_rate) / 2.0;
let grade = match overall_score {
90.0..=100.0 => "A+ (Excellent)",
80.0..=89.9 => "A (Very Good)",
70.0..=79.9 => "B (Good)",
60.0..=69.9 => "C (Acceptable)",
_ => "D (Needs Improvement)",
};
println!(
" Overall compatibility score: {:.1}% ({})",
overall_score, grade
);
println!();
println!("📈 RECOMMENDATIONS");
if report.lzma_failures > 0 {
println!(" • Improve LZMA decompression support");
}
if report.data_failures > 0 {
println!(" • Enhance data reading robustness");
}
if report.audio_objects == 0 {
println!(" • Add more audio test samples");
}
if parse_success_rate < 95.0 {
println!(" • Improve object parsing reliability");
}
println!(" • Continue expanding Unity version support");
println!(" • Add more specialized object type handlers");
println!(" • Implement external resource file support");
println!();
}