use assert_cmd::Command;
use std::fs;
use std::time::Duration;
use tempfile::TempDir;
const TEST_TIMEOUT_SECS: u64 = 600;
#[allow(deprecated)]
fn synth_data_bin() -> Command {
let mut cmd = Command::cargo_bin("datasynth-data").expect("binary in target/");
cmd.timeout(Duration::from_secs(TEST_TIMEOUT_SECS));
cmd
}
#[test]
fn camelcase_feature_matrix_config_produces_full_archive() {
let tmp = TempDir::new().expect("tempdir");
let config_path = tmp.path().join("config.yaml");
let output_path = tmp.path().join("out");
let config_yaml = r#"
global:
industry: retail
seed: 42
startDate: "2024-01-01"
periodMonths: 1
companies:
- code: "C001"
name: "CamelCase Corp"
currency: "USD"
country: "US"
annualTransactionVolume: ten_k
volumeWeight: 1.0
chartOfAccounts:
complexity: small
# SDK-style camelCase
analyticsMetadata:
enabled: true
audit:
enabled: true
complianceRegulations:
enabled: true
accountingStandards:
enabled: true
framework: us_gaap
vendorNetwork:
enabled: true
customerSegmentation:
enabled: true
documentFlows:
enabled: true
output:
output_directory: "/tmp/unused"
exportFormat: "json"
"#;
fs::write(&config_path, config_yaml).expect("write config");
let output_str = output_path.to_string_lossy().to_string();
synth_data_bin()
.arg("generate")
.arg("--config")
.arg(&config_path)
.arg("--output")
.arg(&output_str)
.arg("--memory-limit")
.arg("2048")
.arg("--max-threads")
.arg("2")
.assert()
.success();
let je_json = output_path.join("journal_entries.json");
let je_csv = output_path.join("journal_entries.csv");
assert!(
je_json.exists(),
"journal_entries.json missing — `exportFormat: \"json\"` was not honoured \
(camelCase alias regression)"
);
let _ = je_csv;
let sentinels: &[(&str, &str)] = &[
("documentFlows", "document_flows/purchase_orders.json"),
("accountingStandards", "accounting_standards"), (
"complianceRegulations",
"compliance_regulations/compliance_standards.json",
),
("analyticsMetadata", "analytics"), ("audit", "audit/audit_engagements.json"),
("vendorNetwork", "master_data/vendors.json"), ];
for (key, rel) in sentinels {
let p = output_path.join(rel);
assert!(
p.exists(),
"expected sentinel {rel} for camelCase key `{key}` — \
subsection didn't parse or didn't enable its generator"
);
}
let file_count = count_files_recursive(&output_path);
assert!(
file_count > 50,
"archive has only {} files — v4.1.x-style camelCase collapse \
(SDK team saw 19 files; v4.4.1 should have 80+)",
file_count
);
let coa_meta_path = output_path.join("chart_of_accounts_meta.json");
assert!(
coa_meta_path.exists(),
"chart_of_accounts_meta.json missing (v4.4.1 companion file)"
);
let text = fs::read_to_string(&coa_meta_path).expect("read coa meta");
let meta: serde_json::Value = serde_json::from_str(&text).expect("parse coa meta");
assert_eq!(
meta["accounting_framework"].as_str(),
Some("us_gaap"),
"CoA accounting_framework should be 'us_gaap' per config, \
got {:?}",
meta["accounting_framework"]
);
}
fn count_files_recursive(dir: &std::path::Path) -> usize {
let mut n = 0;
let Ok(rd) = fs::read_dir(dir) else {
return 0;
};
for entry in rd.flatten() {
let p = entry.path();
if p.is_dir() {
n += count_files_recursive(&p);
} else if p.is_file() {
n += 1;
}
}
n
}