mirror of
https://github.com/Yuyi-Oak/BlueArchiveToolkit.git
synced 2026-09-18 07:24:55 +08:00
fix(sync): 移除多线程下载并补齐staging复用回归
This commit is contained in:
@@ -330,6 +330,75 @@ fn official_update_second_run_audits_existing_resources_before_reuse() {
|
||||
assert!(version_state.in_progress_version.is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn official_update_reuses_failed_staging_after_interrupted_download() {
|
||||
let harness = TestHarness::new();
|
||||
let bootstrap = harness.fetch_bootstrap();
|
||||
let fetcher = harness.fetcher();
|
||||
let server_info_url = bootstrap
|
||||
.game_main_config
|
||||
.server_info_data_url
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.clone();
|
||||
let server_info_bytes = fetcher.fetch_bytes(&server_info_url).unwrap();
|
||||
let server_info = YostarJpServerInfo::from_slice(&server_info_bytes).unwrap();
|
||||
let discovery = server_info
|
||||
.discovery_plan(
|
||||
bootstrap
|
||||
.game_main_config
|
||||
.default_connection_group
|
||||
.as_deref()
|
||||
.unwrap(),
|
||||
&bootstrap.game_config.game_latest_version,
|
||||
&verified_official_platforms(),
|
||||
)
|
||||
.unwrap();
|
||||
let inventory = fetch_platform_inventory(&fetcher, &discovery);
|
||||
let plan = build_official_pull_plan_from_platform_inventory(discovery, inventory);
|
||||
let all_urls = plan.all_urls().unwrap();
|
||||
let resume_url = all_urls
|
||||
.iter()
|
||||
.find(|url| url.ends_with("/Windows_PatchPack/catalog_StandaloneWindows64.zip"))
|
||||
.expect("fixture plan should contain Windows addressables catalog zip")
|
||||
.clone();
|
||||
let resources_assets_path = harness.temp.path().join("resources.assets");
|
||||
let zip_fixture = harness.temp.path().join("downloaded.zip");
|
||||
let curl_failure_state = harness.temp.path().join("curl-failure.state");
|
||||
write_executable(
|
||||
&harness.curl_script,
|
||||
&official_curl_script(
|
||||
&harness.curl_log,
|
||||
&zip_fixture,
|
||||
&resources_assets_path,
|
||||
fs::metadata(&resources_assets_path).unwrap().len() as usize,
|
||||
TEST_LAUNCHER_MANIFEST_SOURCE,
|
||||
Some(&curl_failure_state),
|
||||
),
|
||||
);
|
||||
|
||||
let config = harness.sync_config("failed-staging-output");
|
||||
let first_error = OfficialUpdateService::new().run(&config).unwrap_err();
|
||||
assert!(first_error.to_string().contains("quarantine"));
|
||||
assert!(first_error.to_string().contains("simulated failure"));
|
||||
|
||||
let first_log = fs::read_to_string(&harness.curl_log).unwrap();
|
||||
assert!(first_log.contains(&resume_url));
|
||||
|
||||
let report = OfficialUpdateService::new().run(&config).unwrap();
|
||||
assert_eq!(report.update_status, OfficialUpdateStatus::Downloaded);
|
||||
|
||||
let second_log = fs::read_to_string(&harness.curl_log).unwrap();
|
||||
assert_eq!(second_log.matches(&resume_url).count(), 1);
|
||||
|
||||
let version_state = read_version_state(&report.version_state_path)
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
assert!(version_state.failed_versions.is_empty());
|
||||
assert!(version_state.in_progress_version.is_none());
|
||||
assert!(version_state.current_completed_version.is_some());
|
||||
}
|
||||
|
||||
struct TestHarness {
|
||||
temp: TempDir,
|
||||
curl_script: std::path::PathBuf,
|
||||
@@ -362,6 +431,7 @@ impl TestHarness {
|
||||
&resources_assets_path,
|
||||
resources_assets.len(),
|
||||
manifest_source,
|
||||
None,
|
||||
),
|
||||
);
|
||||
|
||||
@@ -478,11 +548,16 @@ fn official_curl_script(
|
||||
resources_assets_fixture: &Path,
|
||||
resources_assets_size: usize,
|
||||
manifest_source: &str,
|
||||
failure_state: Option<&Path>,
|
||||
) -> String {
|
||||
let failure_state = failure_state
|
||||
.map(shell_quote)
|
||||
.unwrap_or_else(|| "''".to_string());
|
||||
format!(
|
||||
r#"#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
log={}
|
||||
failure_state={failure_state}
|
||||
printf '%s\n' "$*" >> "$log"
|
||||
output=""
|
||||
url=""
|
||||
@@ -522,6 +597,23 @@ emit_resources_assets_fixture() {{
|
||||
cp {} "$output"
|
||||
}}
|
||||
|
||||
maybe_fail_once() {{
|
||||
if [[ -z "$failure_state" ]]; then
|
||||
return 0
|
||||
fi
|
||||
local attempt=0
|
||||
if [[ -f "$failure_state" ]]; then
|
||||
attempt="$(cat "$failure_state")"
|
||||
fi
|
||||
attempt=$((attempt + 1))
|
||||
mkdir -p "$(dirname "$failure_state")"
|
||||
printf '%s' "$attempt" > "$failure_state"
|
||||
if [[ "$attempt" -le 3 ]]; then
|
||||
echo "simulated failure for $url attempt=$attempt" >&2
|
||||
exit 22
|
||||
fi
|
||||
}}
|
||||
|
||||
if [[ "$url" == "https://api-launcher-jp.yo-star.com/api/launcher/game/config" ]]; then
|
||||
cat <<'JSON'
|
||||
{{"code":200,"message":"ok","data":{{"game_latest_version":"{launcher_latest_version}","game_latest_file_path":"{launcher_latest_file_path}"}}}}
|
||||
@@ -573,6 +665,7 @@ elif [[ "$url" == "{addressables_root}/MediaResources/Catalog/MediaCatalog.bytes
|
||||
elif [[ "$url" == "{addressables_root}/MediaResources/Catalog/MediaCatalog.hash" ]]; then
|
||||
emit_text "{android_media_catalog_hash}"
|
||||
elif [[ -n "$output" && "$url" == "{addressables_root}/"* ]]; then
|
||||
maybe_fail_once
|
||||
filename="${{url##*/}}"
|
||||
if [[ "$filename" == *.zip ]]; then
|
||||
emit_zip_fixture
|
||||
@@ -604,6 +697,7 @@ fi
|
||||
windows_media_catalog_hash = xxhash32(b"GameData\\Audio\\VOC_JP\\JP_Airi_Win.zip"),
|
||||
android_bundle_catalog_hash = xxhash32(b"FullPatch_001.zip"),
|
||||
android_media_catalog_hash = xxhash32(b"GameData\\Audio\\VOC_JP\\JP_Airi_Android.zip"),
|
||||
failure_state = failure_state,
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user