Files
BlueArchiveToolkit/infrastructure/tests/synthetic_phase2_import.rs
T

120 lines
4.0 KiB
Rust

use bat_adapters::manifest::ManifestDriverRegistry;
use bat_core::repositories::cas_repository::CasRepository;
use bat_core::repositories::resource_repository::{ResourceQuery, ResourceRepository};
use bat_infrastructure::{
BundleSource, FileSystemCasRepository, InMemoryResourceRepository, ResourceImportService,
};
use serde_json::json;
use tempfile::TempDir;
fn push_c_string(data: &mut Vec<u8>, value: &str) {
data.extend_from_slice(value.as_bytes());
data.push(0);
}
fn push_u16(data: &mut Vec<u8>, value: u16) {
data.extend_from_slice(&value.to_be_bytes());
}
fn push_u32(data: &mut Vec<u8>, value: u32) {
data.extend_from_slice(&value.to_be_bytes());
}
fn push_i32(data: &mut Vec<u8>, value: i32) {
data.extend_from_slice(&value.to_be_bytes());
}
fn push_u64(data: &mut Vec<u8>, value: u64) {
data.extend_from_slice(&value.to_be_bytes());
}
fn align(data: &mut Vec<u8>, alignment: usize) {
let remainder = data.len() % alignment;
if remainder != 0 {
data.resize(data.len() + alignment - remainder, 0);
}
}
fn synthetic_minimal_unityfs_bundle() -> Vec<u8> {
let mut blocks_info = Vec::new();
blocks_info.extend_from_slice(&[0; 16]);
push_i32(&mut blocks_info, 1);
push_u32(&mut blocks_info, 4);
push_u32(&mut blocks_info, 4);
push_u16(&mut blocks_info, 0);
push_i32(&mut blocks_info, 1);
push_u64(&mut blocks_info, 0);
push_u64(&mut blocks_info, 4);
push_u32(&mut blocks_info, 0);
push_c_string(&mut blocks_info, "SYNTHETIC-GOLDEN-CAB");
let mut data = Vec::new();
push_c_string(&mut data, "UnityFS");
push_u32(&mut data, 8);
push_c_string(&mut data, "5.x.x");
push_c_string(&mut data, "2021.3.56f2");
push_u64(&mut data, 0);
push_u32(&mut data, blocks_info.len() as u32);
push_u32(&mut data, blocks_info.len() as u32);
push_u32(&mut data, 0);
align(&mut data, 16);
data.extend_from_slice(&blocks_info);
data.extend_from_slice(b"data");
let total_size = data.len() as u64;
let total_size_offset = b"UnityFS\0".len() + 4 + b"5.x.x\0".len() + b"2021.3.56f2\0".len();
data[total_size_offset..total_size_offset + 8].copy_from_slice(&total_size.to_be_bytes());
data
}
#[tokio::test]
async fn imports_synthetic_addressables_catalog_bundle_against_golden() {
let catalog = include_bytes!("fixtures/synthetic_phase2/catalog.json");
let manifest = ManifestDriverRegistry::with_defaults()
.parse(catalog)
.await
.unwrap();
let temp_dir = TempDir::new().unwrap();
let cas = FileSystemCasRepository::new(temp_dir.path().join("cas"));
let resources = InMemoryResourceRepository::new();
let service = ResourceImportService::new(&cas, &resources);
let report = service
.import_manifest_bundles(
&manifest,
&[BundleSource::new(
"minimal.bundle",
synthetic_minimal_unityfs_bundle(),
)],
)
.await
.unwrap();
assert_eq!(report.imported.len(), 1);
assert!(cas.exists(&report.imported[0].object_id).await);
let indexed = resources.list(ResourceQuery::all()).await.unwrap();
let actual = json!({
"imported": report.imported.iter().map(|imported| {
json!({
"bytes": imported.bytes,
"source_path": imported.source_path,
"unityfs": {
"block_count": imported.unityfs.block_count,
"directories": imported.unityfs.directories,
"directory_count": imported.unityfs.directory_count,
"unity_version": imported.unityfs.unity_version,
}
})
}).collect::<Vec<_>>(),
"resource_count": indexed.len(),
"skipped": report.skipped,
});
let expected: serde_json::Value =
serde_json::from_str(include_str!("golden/synthetic_phase2_import.json")).unwrap();
assert_eq!(actual, expected);
assert_eq!(indexed[0].entry.hash, report.imported[0].object_id);
}