Tests read the stock chain: added patch archives are left out
The tests that read the install assert the stock 1.12.1 data, so a player's texture pack (Project Reforged's patch-A, -G, -T...) or an interface mod (patch-F) in the same Data folder failed them. With $BENILLA_STOCK_CHAIN set, Chain::open mounts a Data directory's base set, patch.MPQ, patch-2.MPQ and speech2.MPQ, and leaves out every other patch-?.MPQ; the language pack's folder is not filtered. scripts/unit-tests.sh, the gates' test runner, exports it. Verified: a chain test (stock mode keeps patch and patch-2, drops patch-A.mpq and patch-F.MPQ; without it all mount); benilla-formats' 547 tests pass on the install with Reforged's A and G under BENILLA_STOCK_CHAIN=1, where three character tests failed before. The other crates' install tests were not run here. Built on Windows. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -59,6 +59,19 @@ fn is_patch_glob_match(name: &str) -> bool {
|
||||
/// [`VANILLA_BASE_ORDER`] archives, `patch.MPQ`, every `patch-?.MPQ` by case-folded name (the
|
||||
/// reference sorts descending with `strnicmp` and walks backwards), then `speech2.MPQ`. Names
|
||||
/// match case-insensitively and come back as found on disk.
|
||||
/// `$BENILLA_STOCK_CHAIN` set and not empty: a `Data` directory mounts only the stock 1.12.1
|
||||
/// archives, its base set, `patch.MPQ`, `patch-2.MPQ` and `speech2.MPQ`, and leaves out every
|
||||
/// other `patch-?.MPQ` (texture packs, interface mods), so the tests that read the install see the
|
||||
/// data they assert. The language pack's folder is not filtered. `scripts/unit-tests.sh` sets it.
|
||||
fn stock_chain_only() -> bool {
|
||||
std::env::var_os("BENILLA_STOCK_CHAIN").is_some_and(|v| !v.is_empty())
|
||||
}
|
||||
|
||||
/// Whether `name` is a stock 1.12.1 patch archive.
|
||||
fn is_stock_patch(name: &str) -> bool {
|
||||
name.eq_ignore_ascii_case("patch-2.MPQ")
|
||||
}
|
||||
|
||||
fn mount_order(dir_names: &[String]) -> Vec<String> {
|
||||
let find = |want: &str| {
|
||||
dir_names
|
||||
@@ -86,11 +99,17 @@ impl Chain {
|
||||
/// `"Failed to open archive"` and goes on, because a skipped corrupt archive surfaces only as
|
||||
/// missing files far downstream.
|
||||
pub fn open(path: &Path) -> Result<Self> {
|
||||
Self::open_without(path, &[])
|
||||
Self::open_dir(path, stock_chain_only(), &[])
|
||||
}
|
||||
|
||||
/// [`Chain::open`], `Data`'s archives named in `skip` left out.
|
||||
fn open_without(path: &Path, skip: &[String]) -> Result<Self> {
|
||||
Self::open_dir(path, stock_chain_only(), skip)
|
||||
}
|
||||
|
||||
/// [`Chain::open`]; `stock` keeps the `Data` directory to its stock archives
|
||||
/// ([`stock_chain_only`]).
|
||||
fn open_dir(path: &Path, stock: bool, skip: &[String]) -> Result<Self> {
|
||||
let mut archives = Vec::new();
|
||||
if path.is_dir() {
|
||||
let mut names: Vec<String> = std::fs::read_dir(path)
|
||||
@@ -105,7 +124,9 @@ impl Chain {
|
||||
// read_dir order is arbitrary; sort so case-variant ties resolve deterministically.
|
||||
names.sort();
|
||||
for name in mount_order(&names) {
|
||||
if skip.iter().any(|s| s.eq_ignore_ascii_case(&name)) {
|
||||
if skip.iter().any(|s| s.eq_ignore_ascii_case(&name))
|
||||
|| (stock && is_patch_glob_match(&name) && !is_stock_patch(&name))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
let mpq = path.join(&name);
|
||||
@@ -161,7 +182,9 @@ impl Chain {
|
||||
let folder = pack
|
||||
.pack_folder(path)
|
||||
.context("ruRU language pack is not installed")?;
|
||||
chain.archives.extend(Self::open(&folder)?.archives);
|
||||
chain
|
||||
.archives
|
||||
.extend(Self::open_dir(&folder, false, &[])?.archives);
|
||||
}
|
||||
chain.locale = Locale::for_language_pack(pack);
|
||||
Ok(chain)
|
||||
@@ -473,6 +496,54 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
/// The stock chain keeps the base set, `patch.MPQ` and `patch-2.MPQ`, and drops the other
|
||||
/// `patch-?.MPQ` in any case; without it every patch mounts.
|
||||
#[test]
|
||||
fn the_stock_chain_mounts_only_the_stock_patches() {
|
||||
let dir = std::env::temp_dir().join(format!(
|
||||
"benilla-chain-stock-{}-{:?}",
|
||||
std::process::id(),
|
||||
std::thread::current().id()
|
||||
));
|
||||
let _ = std::fs::remove_dir_all(&dir);
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
for archive in [
|
||||
"interface.MPQ",
|
||||
"patch.MPQ",
|
||||
"patch-2.MPQ",
|
||||
"patch-A.mpq",
|
||||
"patch-F.MPQ",
|
||||
] {
|
||||
let line = format!("X\\{archive}\r\n");
|
||||
std::fs::write(
|
||||
dir.join(archive),
|
||||
fixture_mpq(&[("(listfile)", line.as_bytes())]),
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
let stock = Chain::open_dir(&dir, true, &[])
|
||||
.expect("open")
|
||||
.enumerate_archive_files("x\\");
|
||||
let every = Chain::open_dir(&dir, false, &[])
|
||||
.expect("open")
|
||||
.enumerate_archive_files("x\\");
|
||||
let _ = std::fs::remove_dir_all(&dir);
|
||||
assert_eq!(
|
||||
stock,
|
||||
["X\\patch.MPQ", "X\\patch-2.MPQ", "X\\interface.MPQ"]
|
||||
);
|
||||
assert_eq!(
|
||||
every,
|
||||
[
|
||||
"X\\patch.MPQ",
|
||||
"X\\patch-2.MPQ",
|
||||
"X\\patch-A.mpq",
|
||||
"X\\patch-F.MPQ",
|
||||
"X\\interface.MPQ"
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/// An archive left out by name, in any case, does not mount; the others keep their order.
|
||||
#[test]
|
||||
fn a_left_out_archive_does_not_mount() {
|
||||
@@ -491,7 +562,7 @@ mod tests {
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
let chain = Chain::open_without(&dir, &["PATCH-3.mpq".to_owned()]).expect("open");
|
||||
let chain = Chain::open_dir(&dir, false, &["PATCH-3.mpq".to_owned()]).expect("open");
|
||||
let walked = chain.enumerate_archive_files("x\\");
|
||||
let _ = std::fs::remove_dir_all(&dir);
|
||||
assert_eq!(
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
# scripts/unit-tests.sh --workspace
|
||||
# scripts/unit-tests.sh -p benilla-app --no-default-features --lib
|
||||
set -euo pipefail
|
||||
# The tests that read the install assert the stock 1.12.1 data: the chain leaves out any other
|
||||
# patch archive a player added (texture packs, interface mods) (`Chain::open`).
|
||||
export BENILLA_STOCK_CHAIN=1
|
||||
if cargo nextest --version >/dev/null 2>&1; then
|
||||
exec cargo nextest run --no-fail-fast --no-tests=pass "$@"
|
||||
fi
|
||||
|
||||
Reference in New Issue
Block a user