From 48fa8abf4436c6efea488ecd76bf9ff6cc7506fd Mon Sep 17 00:00:00 2001 From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com> Date: Tue, 3 Nov 2026 10:45:18 +0100 Subject: [PATCH] chore: audit 24 and 17 cases, host kept out --- install.ps1 | 2 +- install.py | 14 +- install.sh | 2 +- tests/fixtures/tui/colour-120x40.txt | 36 +- tests/fixtures/tui/colour-40x12.txt | 44 +- tests/fixtures/tui/colour-40x15.txt | 48 +- tests/fixtures/tui/colour-80x24.txt | 36 +- tests/fixtures/tui/cores-120x40.txt | 16 +- tests/fixtures/tui/cores-40x12.txt | 20 +- tests/fixtures/tui/cores-40x15.txt | 20 +- tests/fixtures/tui/cores-80x24.txt | 16 +- tests/fixtures/tui/plan-in-place-120x40.txt | 2 +- tests/fixtures/tui/plan-in-place-40x12.txt | 4 +- tests/fixtures/tui/plan-in-place-40x15.txt | 4 +- tests/fixtures/tui/plan-in-place-80x24.txt | 2 +- tests/fixtures/tui/regions-120x40.txt | 4 +- tests/fixtures/tui/regions-40x12.txt | 2 +- tests/fixtures/tui/regions-40x15.txt | 4 +- tests/fixtures/tui/regions-80x24.txt | 4 +- tests/fixtures/tui/result-120x40.txt | 2 +- tests/fixtures/tui/result-40x12.txt | 4 +- tests/fixtures/tui/result-40x15.txt | 4 +- tests/fixtures/tui/result-80x24.txt | 2 +- tests/fixtures/tui/route-evmapy.txt | 124 ++--- tests/fixtures/tui/route-gptokeyb.txt | 124 ++--- tests/fixtures/tui/route-gptokeyb_muxterm.txt | 124 ++--- tests/fixtures/tui/route-keys.txt | 128 +++--- tests/fixtures/tui/route-miyoo.txt | 124 ++--- tests/fixtures/tui/route-muxterm.txt | 124 ++--- tests/fixtures/tui/systems-120x40.txt | 12 +- tests/fixtures/tui/systems-40x12.txt | 14 +- tests/fixtures/tui/systems-40x15.txt | 16 +- tests/fixtures/tui/systems-80x24.txt | 12 +- tests/netguard/__init__.py | 33 ++ tests/netguard/sitecustomize.py | 133 ++++++ tests/test_doc_pages.py | 53 +++ tests/test_install.py | 7 + tests/test_install_tui.py | 432 +++++++++++++++++- 38 files changed, 1208 insertions(+), 544 deletions(-) create mode 100644 tests/netguard/__init__.py create mode 100644 tests/netguard/sitecustomize.py diff --git a/install.ps1 b/install.ps1 index db72b7c21..9c37b8101 100644 --- a/install.ps1 +++ b/install.ps1 @@ -16,7 +16,7 @@ # and Invoke-WebRequest throws on a cut transfer before the hash is read: # the site's build rewrites this line there (scripts/sitebootstrap.py). $mismatchAdvice = "The download was most likely cut short: try again. Within minutes of an update of this project the two files can come from caches of different ages. Waiting five minutes settles that." - $defaultInstallSha256 = "403b6e8a7efcd24858b0f46ffa19c2b9012cdeef149768729d8e48d0b68a296a" + $defaultInstallSha256 = "a5713bf93a8b48b5649aa7040a429ec4ac2a2ae62b14b07eb6c91cb96c15d984" $maximumInstallerBytes = 2MB $installerExit = 0 $installer = if ($PSScriptRoot) { Join-Path $PSScriptRoot "install.py" } else { $null } diff --git a/install.py b/install.py index cbdff8afc..b14943937 100644 --- a/install.py +++ b/install.py @@ -12164,8 +12164,12 @@ def card_setups() -> list[CardSetup]: below = next((rule.bios[len(_card_mount(rule.bios)):] for rule in _EMBEDDED_RULES if rule.name == name and rule.bios and _card_mount(rule.bios)), "") if below: - setups.append(CardSetup(name, "retroarch", below, - tuple(rule for rule in rules if rule.name == name))) + own = tuple(rule for rule in rules if rule.name in (name, _built_on(name))) + # Told by the games part alone, as AmberELEC's: a card that holds + # none of it yet is taken as named, said so (tui_audit_17 P2-3). + setups.append(CardSetup(name, "retroarch", below, own, + bool(own) and all(rule.method == "games_part" + for rule in own))) return setups @@ -19173,7 +19177,13 @@ def _view_plan(state: TuiState, width: int, height: int) -> tuple: for event in events} held = [event for event in chosen if event["dest"] in took] rest = len(chosen) - len(held) + data + # Nothing at hand: the head the whole list's plan says, for the + # systems ticked. "About 0 files, 0 B" stood over 20 files the + # internet would bring (tui_audit_17 P3-5). lines[0] = _styled( + f"{agree(rest, 'file needs', 'files need')} the internet, which " + f"{offline_named()} does not use, for {len(state.ticked)} of " + f"{len(state.systems)} systems", "title") if not held else _styled( f"About {_plural(len(held), 'file')}, " f"{format_size(sum(e['size'] for e in held))}, for {len(state.ticked)} of " f"{len(state.systems)} systems" diff --git a/install.sh b/install.sh index cacf12717..1764d7e94 100755 --- a/install.sh +++ b/install.sh @@ -23,7 +23,7 @@ DEFAULT_INSTALL_URL="https://raw.githubusercontent.com/Abdess/retrobios/main/ins # curl or wget stop on a cut transfer before the hash is read: the site's # build rewrites this line there (scripts/sitebootstrap.py). MISMATCH_ADVICE="The download was most likely cut short: try again. Within minutes of an update of this project the two files can come from caches of different ages. Waiting five minutes settles that." -DEFAULT_INSTALL_SHA256="403b6e8a7efcd24858b0f46ffa19c2b9012cdeef149768729d8e48d0b68a296a" +DEFAULT_INSTALL_SHA256="a5713bf93a8b48b5649aa7040a429ec4ac2a2ae62b14b07eb6c91cb96c15d984" MAX_INSTALLER_BYTES=2097152 cleanup() { diff --git a/tests/fixtures/tui/colour-120x40.txt b/tests/fixtures/tui/colour-120x40.txt index 7b7a0d47d..b6c4ca8d9 100644 --- a/tests/fixtures/tui/colour-120x40.txt +++ b/tests/fixtures/tui/colour-120x40.txt @@ -373,6 +373,7 @@ ^[[0;1m ^[[0;1;32mEverything is in place^[[0m BIOS folder: ^[[0;1m~/.config/retroarch/system^[[0m ^[[0;32m5 in place^[[0m, 0 missing, 0 wrong copies + 1 of the 0 wrong copies is replaced, the old one kept in a backup folder. Free space: 50.0 GB ^[[0;7;35m > Close^[[0m @@ -404,20 +405,19 @@ - ^[[0;1;35mA/Enter^[[0m Close ^[[0;2mB/Esc^[[0m Back ^[[0;2mY/o^[[0m Options ^[[0;2m?^[[0m Help === systems ^[[0;1m ^[[0;1;35mRetroBIOS^[[0;1m: Choose systems^[[0m + Filter (/ to type) + [x] nintendo-gba (gba) 1 file, 16.0 KB + [x] sony-playstation 3 files, 1.0 MB +^[[0;7;35m > [ ] nintendo-famicom-disk (ファミコン) in place^[[0m All None - Filter (/ to type) -^[[0;7;35m > [x] nintendo-gba (gba) 1 file, 16.0 KB^[[0m - [x] sony-playstation 3 files, 1.0 MB -^[[0;2m [ ] nintendo-famicom-disk (ファミコン) in place^[[0m - + ^[[0;32mDone^[[0m @@ -448,7 +448,7 @@ ^[[0;1m ^[[0;1;35m2^[[0;1m of ^[[0;1;35m3^[[0;1m systems: ^[[0;1;35m4^[[0;1m files, ^[[0;1;35m1.0 MB^[[0m - ^[[0;1;35mA/Enter^[[0m Continue ^[[0;2mB/Esc^[[0m Back ^[[0;2mX/Space^[[0m Tick ^[[0;2m?^[[0m Help + ^[[0;1;35mA/Enter^[[0m Tick ^[[0;2mB/Esc^[[0m Done ^[[0;2m?^[[0m Help === options ^[[0;1m ^[[0;1;35mRetroBIOS^[[0;1m: Options^[[0m @@ -498,8 +498,8 @@ ^[[0;7;35m > [1] North America^[[0m [ ] Japan - - + None + ^[[0;32mDone^[[0m @@ -534,14 +534,15 @@ === cores ^[[0;1m ^[[0;1;35mRetroBIOS^[[0;1m: Cores^[[0m - Every core ticked keeps every core's files. Untick the cores you do not use: the platform's own - files are always kept. + Untick the cores you do not use: the platform's own files are always kept, and a core with no + extra file reads only those. -^[[0;7;35m > All^[[0m +^[[0;7;35m > Filter (/ to type)^[[0m + [ ] mesen 1 file, 8.0 KB + [x] pcsx_rearmed 1 file, 4 B + All None - Filter (/ to type) - [ ] mesen - [x] pcsx_rearmed + ^[[0;32mDone^[[0m @@ -570,8 +571,7 @@ - - ^[[0;1;35mA/Enter^[[0m Tick all ^[[0;2mB/Esc^[[0m Back ^[[0;2mX/Space^[[0m Tick ^[[0;2m?^[[0m Help + ^[[0;1;35mA/Enter^[[0m Filter ^[[0;2mB/Esc^[[0m Done ^[[0;2m?^[[0m Help === preview ^[[0;1m ^[[0;1;35mRetroBIOS^[[0;1m: Preview^[[0m @@ -742,6 +742,7 @@ ^[[0;1m ^[[0;1;32m3 installed^[[0;1m, ^[[0;1;31m1 failed^[[0;1m.^[[0m BIOS folder: ^[[0;1m/home/user/.config/retroarch/system^[[0m ^[[0;1;31mfailed:^[[0m scph5500.bin (HTTP 404) + Run it again to retry only those. The files it replaced are kept in /home/user/.config/retroarch/retrobios-backup/2026-10-23_1200 To put them back: python3 install.py \ --restore /home/user/.config/retroarch/retrobios-backup/2026-10-23_1200 @@ -773,7 +774,6 @@ - ^[[0;1;35mA/Enter^[[0m Exit diff --git a/tests/fixtures/tui/colour-40x12.txt b/tests/fixtures/tui/colour-40x12.txt index bbbf7d339..274ec3700 100644 --- a/tests/fixtures/tui/colour-40x12.txt +++ b/tests/fixtures/tui/colour-40x12.txt @@ -122,25 +122,25 @@ BIOS folder: ^[[0;1m~/.config/retroarch/system^[[0m ^[[0;32m5 in place^[[0m, 0 missing, 0 wrong copies + 1 of the 0 wrong copies is replaced, + the old one kept in a backup folder. Free space: 50.0 GB - ^[[0;7;35m > Close^[[0m Options - ^[[0;1;35mA^[[0m Close ^[[0;2mB^[[0m Back ^[[0;2mY^[[0m Options ^[[0;2m?^[[0m Help === systems ^[[0;1m ^[[0;1;35mRetroBIOS^[[0;1m: Choose systems^[[0m + [x] nintendo-gba (gba) 16.0 KB + [x] sony-playstation 1.0 MB +^[[0;7;35m > [ ] nintendo-famicom-disk in place^[[0m All None - Filter (/ to type) -^[[0;7;35m > [x] nintendo-gba (gba) 16.0 KB^[[0m - [x] sony-playstation 1.0 MB -^[[0;2m [ ] nintendo-famicom-disk in place^[[0m - - +^[[0;2m 1-3 of 3^[[0m + nintendo-famicom-disk (ファミコン): in + place ^[[0;1m ^[[0;1;35m2^[[0;1m of ^[[0;1;35m3^[[0;1m systems: ^[[0;1;35m4^[[0;1m files, ^[[0;1;35m1.0 MB^[[0m - ^[[0;1;35mA^[[0m Continue ^[[0;2mB^[[0m Back ^[[0;2mX^[[0m Tick ^[[0;2m?^[[0m Help + ^[[0;1;35mA^[[0m Tick ^[[0;2mB^[[0m Done ^[[0;2m?^[[0m Help === options ^[[0;1m ^[[0;1;35mRetroBIOS^[[0;1m: Options^[[0m @@ -165,21 +165,21 @@ ^[[0;7;35m > [1] North America^[[0m [ ] Japan - +^[[0;2m 1-2 of 2^[[0m ^[[0;1;35mA^[[0m Tick ^[[0;2mB^[[0m Done ^[[0;2m<>^[[0m Order ^[[0;2m?^[[0m Help === cores ^[[0;1m ^[[0;1;35mRetroBIOS^[[0;1m: Cores^[[0m - Every core ticked keeps every core's - files. Untick the cores you do not - use: the platform's own files are - always kept. -^[[0;7;35m > All^[[0m - None - Filter (/ to type) - [ ] mesen - [x] pcsx_rearmed - ^[[0;1;35mA^[[0m Tick all ^[[0;2mB^[[0m Back ^[[0;2mX^[[0m Tick ^[[0;2m?^[[0m Help + Untick the cores you do not use: the + platform's own files are always + kept, and a core with no extra file + reads only those. + +^[[0;7;35m > Filter (/ to type)^[[0m + [ ] mesen 1 file, 8.0 KB + [x] pcsx_rearmed 1 file, 4 B +^[[0;2m 1-2 of 2^[[0m + ^[[0;1;35mA^[[0m Filter ^[[0;2mB^[[0m Done ^[[0;2m?^[[0m Help === preview ^[[0;1m ^[[0;1;35mRetroBIOS^[[0;1m: Preview^[[0m @@ -239,11 +239,11 @@ BIOS folder: ^[[0;1m/home/user/.config/retroarch/system^[[0m ^[[0;1;31mfailed:^[[0m scph5500.bin (HTTP 404) + Run it again to retry only those. The files it replaced are kept in /home/user/.config/retroarch/ retrobios-backup/2026-10-23_1200 - To put them back: python3 install.py \ -^[[0;2m 1-8 of 16^[[0m +^[[0;2m 1-8 of 17^[[0m ^[[0;1;35mA^[[0m Exit ^[[0;2m^v^[[0m Scroll === error ^[[0;1m ^[[0;1;35mRetroBIOS^[[0;1m: ^[[0;1;31mSomething went wrong^[[0m diff --git a/tests/fixtures/tui/colour-40x15.txt b/tests/fixtures/tui/colour-40x15.txt index 9430e9fbd..67c5d1073 100644 --- a/tests/fixtures/tui/colour-40x15.txt +++ b/tests/fixtures/tui/colour-40x15.txt @@ -149,31 +149,31 @@ BIOS folder: ^[[0;1m~/.config/retroarch/system^[[0m ^[[0;32m5 in place^[[0m, 0 missing, 0 wrong copies + 1 of the 0 wrong copies is replaced, + the old one kept in a backup folder. Free space: 50.0 GB ^[[0;7;35m > Close^[[0m Options - - ^[[0;1;35mA^[[0m Close ^[[0;2mB^[[0m Back ^[[0;2mY^[[0m Options ^[[0;2m?^[[0m Help === systems ^[[0;1m ^[[0;1;35mRetroBIOS^[[0;1m: Choose systems^[[0m + Filter (/ to type) + [x] nintendo-gba (gba) 16.0 KB + [x] sony-playstation 1.0 MB +^[[0;7;35m > [ ] nintendo-famicom-disk in place^[[0m All None - Filter (/ to type) -^[[0;7;35m > [x] nintendo-gba (gba) 16.0 KB^[[0m - [x] sony-playstation 1.0 MB -^[[0;2m [ ] nintendo-famicom-disk in place^[[0m - - - + ^[[0;32mDone^[[0m + nintendo-famicom-disk (ファミコン): in + place ^[[0;1m ^[[0;1;35m2^[[0;1m of ^[[0;1;35m3^[[0;1m systems: ^[[0;1;35m4^[[0;1m files, ^[[0;1;35m1.0 MB^[[0m - ^[[0;1;35mA^[[0m Continue ^[[0;2mB^[[0m Back ^[[0;2mX^[[0m Tick ^[[0;2m?^[[0m Help + ^[[0;1;35mA^[[0m Tick ^[[0;2mB^[[0m Done ^[[0;2m?^[[0m Help === options ^[[0;1m ^[[0;1;35mRetroBIOS^[[0;1m: Options^[[0m @@ -201,27 +201,27 @@ ^[[0;7;35m > [1] North America^[[0m [ ] Japan - - + None + ^[[0;32mDone^[[0m ^[[0;1;35mA^[[0m Tick ^[[0;2mB^[[0m Done ^[[0;2m<>^[[0m Order ^[[0;2m?^[[0m Help === cores ^[[0;1m ^[[0;1;35mRetroBIOS^[[0;1m: Cores^[[0m - Every core ticked keeps every core's - files. Untick the cores you do not - use: the platform's own files are - always kept. + Untick the cores you do not use: the + platform's own files are always + kept, and a core with no extra file + reads only those. -^[[0;7;35m > All^[[0m +^[[0;7;35m > Filter (/ to type)^[[0m + [ ] mesen 1 file, 8.0 KB + [x] pcsx_rearmed 1 file, 4 B + All None - Filter (/ to type) - [ ] mesen - [x] pcsx_rearmed + ^[[0;32mDone^[[0m - - ^[[0;1;35mA^[[0m Tick all ^[[0;2mB^[[0m Back ^[[0;2mX^[[0m Tick ^[[0;2m?^[[0m Help + ^[[0;1;35mA^[[0m Filter ^[[0;2mB^[[0m Done ^[[0;2m?^[[0m Help === preview ^[[0;1m ^[[0;1;35mRetroBIOS^[[0;1m: Preview^[[0m @@ -293,14 +293,14 @@ BIOS folder: ^[[0;1m/home/user/.config/retroarch/system^[[0m ^[[0;1;31mfailed:^[[0m scph5500.bin (HTTP 404) + Run it again to retry only those. The files it replaced are kept in /home/user/.config/retroarch/ retrobios-backup/2026-10-23_1200 To put them back: python3 install.py \ --restore .../2026-10-23_1200 ^[[0;2m Shortened to fit this window.^[[0m - Same choice without questions: -^[[0;2m 1-11 of 16^[[0m +^[[0;2m 1-11 of 17^[[0m ^[[0;1;35mA^[[0m Exit ^[[0;2m^v^[[0m Scroll === error ^[[0;1m ^[[0;1;35mRetroBIOS^[[0;1m: ^[[0;1;31mSomething went wrong^[[0m diff --git a/tests/fixtures/tui/colour-80x24.txt b/tests/fixtures/tui/colour-80x24.txt index 8c3fb5a3a..f511e2e8b 100644 --- a/tests/fixtures/tui/colour-80x24.txt +++ b/tests/fixtures/tui/colour-80x24.txt @@ -229,6 +229,7 @@ ^[[0;1m ^[[0;1;32mEverything is in place^[[0m BIOS folder: ^[[0;1m~/.config/retroarch/system^[[0m ^[[0;32m5 in place^[[0m, 0 missing, 0 wrong copies + 1 of the 0 wrong copies is replaced, the old one kept in a backup folder. Free space: 50.0 GB ^[[0;7;35m > Close^[[0m @@ -246,18 +247,17 @@ - ^[[0;1;35mA/Enter^[[0m Close ^[[0;2mB/Esc^[[0m Back ^[[0;2mY/o^[[0m Options ^[[0;2m?^[[0m Help === systems ^[[0;1m ^[[0;1;35mRetroBIOS^[[0;1m: Choose systems^[[0m + Filter (/ to type) + [x] nintendo-gba (gba) 1 file, 16.0 KB + [x] sony-playstation 3 files, 1.0 MB +^[[0;7;35m > [ ] nintendo-famicom-disk (ファミコン) in place^[[0m All None - Filter (/ to type) -^[[0;7;35m > [x] nintendo-gba (gba) 1 file, 16.0 KB^[[0m - [x] sony-playstation 3 files, 1.0 MB -^[[0;2m [ ] nintendo-famicom-disk (ファミコン) in place^[[0m - + ^[[0;32mDone^[[0m @@ -272,7 +272,7 @@ ^[[0;1m ^[[0;1;35m2^[[0;1m of ^[[0;1;35m3^[[0;1m systems: ^[[0;1;35m4^[[0;1m files, ^[[0;1;35m1.0 MB^[[0m - ^[[0;1;35mA/Enter^[[0m Continue ^[[0;2mB/Esc^[[0m Back ^[[0;2mX/Space^[[0m Tick ^[[0;2m?^[[0m Help + ^[[0;1;35mA/Enter^[[0m Tick ^[[0;2mB/Esc^[[0m Done ^[[0;2m?^[[0m Help === options ^[[0;1m ^[[0;1;35mRetroBIOS^[[0;1m: Options^[[0m @@ -307,8 +307,8 @@ ^[[0;7;35m > [1] North America^[[0m [ ] Japan - - + None + ^[[0;32mDone^[[0m @@ -326,14 +326,15 @@ === cores ^[[0;1m ^[[0;1;35mRetroBIOS^[[0;1m: Cores^[[0m - Every core ticked keeps every core's files. Untick the cores you do not use: - the platform's own files are always kept. + Untick the cores you do not use: the platform's own files are always kept, and + a core with no extra file reads only those. -^[[0;7;35m > All^[[0m +^[[0;7;35m > Filter (/ to type)^[[0m + [ ] mesen 1 file, 8.0 KB + [x] pcsx_rearmed 1 file, 4 B + All None - Filter (/ to type) - [ ] mesen - [x] pcsx_rearmed + ^[[0;32mDone^[[0m @@ -346,8 +347,7 @@ - - ^[[0;1;35mA/Enter^[[0m Tick all ^[[0;2mB/Esc^[[0m Back ^[[0;2mX/Space^[[0m Tick ^[[0;2m?^[[0m Help + ^[[0;1;35mA/Enter^[[0m Filter ^[[0;2mB/Esc^[[0m Done ^[[0;2m?^[[0m Help === preview ^[[0;1m ^[[0;1;35mRetroBIOS^[[0;1m: Preview^[[0m @@ -454,6 +454,7 @@ ^[[0;1m ^[[0;1;32m3 installed^[[0;1m, ^[[0;1;31m1 failed^[[0;1m.^[[0m BIOS folder: ^[[0;1m/home/user/.config/retroarch/system^[[0m ^[[0;1;31mfailed:^[[0m scph5500.bin (HTTP 404) + Run it again to retry only those. The files it replaced are kept in /home/user/.config/retroarch/retrobios-backup/2026-10-23_1200 To put them back: python3 install.py \ @@ -471,7 +472,6 @@ - ^[[0;1;35mA/Enter^[[0m Exit === error ^[[0;1m ^[[0;1;35mRetroBIOS^[[0;1m: ^[[0;1;31mSomething went wrong^[[0m diff --git a/tests/fixtures/tui/cores-120x40.txt b/tests/fixtures/tui/cores-120x40.txt index 571c06bea..4bc230c78 100644 --- a/tests/fixtures/tui/cores-120x40.txt +++ b/tests/fixtures/tui/cores-120x40.txt @@ -1,13 +1,14 @@ RetroBIOS: Cores - Every core ticked keeps every core's files. Untick the cores you do not use: the platform's own - files are always kept. + Untick the cores you do not use: the platform's own files are always kept, and a core with no + extra file reads only those. - > All + > Filter (/ to type) + [ ] mesen 1 file, 8.0 KB + [x] pcsx_rearmed 1 file, 4 B + All None - Filter (/ to type) - [ ] mesen - [x] pcsx_rearmed + Done @@ -36,5 +37,4 @@ - - A/Enter Tick all B/Esc Back X/Space Tick ? Help + A/Enter Filter B/Esc Done ? Help diff --git a/tests/fixtures/tui/cores-40x12.txt b/tests/fixtures/tui/cores-40x12.txt index 7557af130..1ce5c1751 100644 --- a/tests/fixtures/tui/cores-40x12.txt +++ b/tests/fixtures/tui/cores-40x12.txt @@ -1,12 +1,12 @@ RetroBIOS: Cores - Every core ticked keeps every core's - files. Untick the cores you do not - use: the platform's own files are - always kept. - > All - None - Filter (/ to type) - [ ] mesen - [x] pcsx_rearmed - A Tick all B Back X Tick ? Help + Untick the cores you do not use: the + platform's own files are always + kept, and a core with no extra file + reads only those. + + > Filter (/ to type) + [ ] mesen 1 file, 8.0 KB + [x] pcsx_rearmed 1 file, 4 B + 1-2 of 2 + A Filter B Done ? Help diff --git a/tests/fixtures/tui/cores-40x15.txt b/tests/fixtures/tui/cores-40x15.txt index 5cbef31a7..650545a60 100644 --- a/tests/fixtures/tui/cores-40x15.txt +++ b/tests/fixtures/tui/cores-40x15.txt @@ -1,15 +1,15 @@ RetroBIOS: Cores - Every core ticked keeps every core's - files. Untick the cores you do not - use: the platform's own files are - always kept. + Untick the cores you do not use: the + platform's own files are always + kept, and a core with no extra file + reads only those. - > All + > Filter (/ to type) + [ ] mesen 1 file, 8.0 KB + [x] pcsx_rearmed 1 file, 4 B + All None - Filter (/ to type) - [ ] mesen - [x] pcsx_rearmed + Done - - A Tick all B Back X Tick ? Help + A Filter B Done ? Help diff --git a/tests/fixtures/tui/cores-80x24.txt b/tests/fixtures/tui/cores-80x24.txt index c2fce774c..bf4061884 100644 --- a/tests/fixtures/tui/cores-80x24.txt +++ b/tests/fixtures/tui/cores-80x24.txt @@ -1,13 +1,14 @@ RetroBIOS: Cores - Every core ticked keeps every core's files. Untick the cores you do not use: - the platform's own files are always kept. + Untick the cores you do not use: the platform's own files are always kept, and + a core with no extra file reads only those. - > All + > Filter (/ to type) + [ ] mesen 1 file, 8.0 KB + [x] pcsx_rearmed 1 file, 4 B + All None - Filter (/ to type) - [ ] mesen - [x] pcsx_rearmed + Done @@ -20,5 +21,4 @@ - - A/Enter Tick all B/Esc Back X/Space Tick ? Help + A/Enter Filter B/Esc Done ? Help diff --git a/tests/fixtures/tui/plan-in-place-120x40.txt b/tests/fixtures/tui/plan-in-place-120x40.txt index 8f6048340..2869a8ecc 100644 --- a/tests/fixtures/tui/plan-in-place-120x40.txt +++ b/tests/fixtures/tui/plan-in-place-120x40.txt @@ -3,6 +3,7 @@ Everything is in place BIOS folder: ~/.config/retroarch/system 5 in place, 0 missing, 0 wrong copies + 1 of the 0 wrong copies is replaced, the old one kept in a backup folder. Free space: 50.0 GB > Close @@ -34,7 +35,6 @@ - A/Enter Close B/Esc Back Y/o Options ? Help diff --git a/tests/fixtures/tui/plan-in-place-40x12.txt b/tests/fixtures/tui/plan-in-place-40x12.txt index e5768b6f9..8c1faea1c 100644 --- a/tests/fixtures/tui/plan-in-place-40x12.txt +++ b/tests/fixtures/tui/plan-in-place-40x12.txt @@ -4,9 +4,9 @@ BIOS folder: ~/.config/retroarch/system 5 in place, 0 missing, 0 wrong copies + 1 of the 0 wrong copies is replaced, + the old one kept in a backup folder. Free space: 50.0 GB - > Close Options - A Close B Back Y Options ? Help diff --git a/tests/fixtures/tui/plan-in-place-40x15.txt b/tests/fixtures/tui/plan-in-place-40x15.txt index 757eb2c59..3f07f6881 100644 --- a/tests/fixtures/tui/plan-in-place-40x15.txt +++ b/tests/fixtures/tui/plan-in-place-40x15.txt @@ -4,12 +4,12 @@ BIOS folder: ~/.config/retroarch/system 5 in place, 0 missing, 0 wrong copies + 1 of the 0 wrong copies is replaced, + the old one kept in a backup folder. Free space: 50.0 GB > Close Options - - A Close B Back Y Options ? Help diff --git a/tests/fixtures/tui/plan-in-place-80x24.txt b/tests/fixtures/tui/plan-in-place-80x24.txt index 8cf344f67..58631365c 100644 --- a/tests/fixtures/tui/plan-in-place-80x24.txt +++ b/tests/fixtures/tui/plan-in-place-80x24.txt @@ -3,6 +3,7 @@ Everything is in place BIOS folder: ~/.config/retroarch/system 5 in place, 0 missing, 0 wrong copies + 1 of the 0 wrong copies is replaced, the old one kept in a backup folder. Free space: 50.0 GB > Close @@ -20,5 +21,4 @@ - A/Enter Close B/Esc Back Y/o Options ? Help diff --git a/tests/fixtures/tui/regions-120x40.txt b/tests/fixtures/tui/regions-120x40.txt index 271fd15d7..fc84c7547 100644 --- a/tests/fixtures/tui/regions-120x40.txt +++ b/tests/fixtures/tui/regions-120x40.txt @@ -5,8 +5,8 @@ > [1] North America [ ] Japan - - + None + Done diff --git a/tests/fixtures/tui/regions-40x12.txt b/tests/fixtures/tui/regions-40x12.txt index 70928bc8b..ef850abcb 100644 --- a/tests/fixtures/tui/regions-40x12.txt +++ b/tests/fixtures/tui/regions-40x12.txt @@ -8,5 +8,5 @@ > [1] North America [ ] Japan - + 1-2 of 2 A Tick B Done <> Order ? Help diff --git a/tests/fixtures/tui/regions-40x15.txt b/tests/fixtures/tui/regions-40x15.txt index fb7897ea1..2843333c6 100644 --- a/tests/fixtures/tui/regions-40x15.txt +++ b/tests/fixtures/tui/regions-40x15.txt @@ -8,8 +8,8 @@ > [1] North America [ ] Japan - - + None + Done A Tick B Done <> Order ? Help diff --git a/tests/fixtures/tui/regions-80x24.txt b/tests/fixtures/tui/regions-80x24.txt index fe09f21c6..6cefb781a 100644 --- a/tests/fixtures/tui/regions-80x24.txt +++ b/tests/fixtures/tui/regions-80x24.txt @@ -6,8 +6,8 @@ > [1] North America [ ] Japan - - + None + Done diff --git a/tests/fixtures/tui/result-120x40.txt b/tests/fixtures/tui/result-120x40.txt index 246502f05..550ec7724 100644 --- a/tests/fixtures/tui/result-120x40.txt +++ b/tests/fixtures/tui/result-120x40.txt @@ -3,6 +3,7 @@ 3 installed, 1 failed. BIOS folder: /home/user/.config/retroarch/system failed: scph5500.bin (HTTP 404) + Run it again to retry only those. The files it replaced are kept in /home/user/.config/retroarch/retrobios-backup/2026-10-23_1200 To put them back: python3 install.py \ --restore /home/user/.config/retroarch/retrobios-backup/2026-10-23_1200 @@ -34,7 +35,6 @@ - A/Enter Exit diff --git a/tests/fixtures/tui/result-40x12.txt b/tests/fixtures/tui/result-40x12.txt index 9b9270843..12339e200 100644 --- a/tests/fixtures/tui/result-40x12.txt +++ b/tests/fixtures/tui/result-40x12.txt @@ -4,9 +4,9 @@ BIOS folder: /home/user/.config/retroarch/system failed: scph5500.bin (HTTP 404) + Run it again to retry only those. The files it replaced are kept in /home/user/.config/retroarch/ retrobios-backup/2026-10-23_1200 - To put them back: python3 install.py \ - 1-8 of 16 + 1-8 of 17 A Exit ^v Scroll diff --git a/tests/fixtures/tui/result-40x15.txt b/tests/fixtures/tui/result-40x15.txt index caf7d87d0..61db5344b 100644 --- a/tests/fixtures/tui/result-40x15.txt +++ b/tests/fixtures/tui/result-40x15.txt @@ -4,12 +4,12 @@ BIOS folder: /home/user/.config/retroarch/system failed: scph5500.bin (HTTP 404) + Run it again to retry only those. The files it replaced are kept in /home/user/.config/retroarch/ retrobios-backup/2026-10-23_1200 To put them back: python3 install.py \ --restore .../2026-10-23_1200 Shortened to fit this window. - Same choice without questions: - 1-11 of 16 + 1-11 of 17 A Exit ^v Scroll diff --git a/tests/fixtures/tui/result-80x24.txt b/tests/fixtures/tui/result-80x24.txt index 172cd1c52..ab4770376 100644 --- a/tests/fixtures/tui/result-80x24.txt +++ b/tests/fixtures/tui/result-80x24.txt @@ -3,6 +3,7 @@ 3 installed, 1 failed. BIOS folder: /home/user/.config/retroarch/system failed: scph5500.bin (HTTP 404) + Run it again to retry only those. The files it replaced are kept in /home/user/.config/retroarch/retrobios-backup/2026-10-23_1200 To put them back: python3 install.py \ @@ -20,5 +21,4 @@ - A/Enter Exit diff --git a/tests/fixtures/tui/route-evmapy.txt b/tests/fixtures/tui/route-evmapy.txt index 757cd93ec..a77266857 100644 --- a/tests/fixtures/tui/route-evmapy.txt +++ b/tests/fixtures/tui/route-evmapy.txt @@ -462,11 +462,11 @@ BIOS folder: ~/.config/retroarch/system 5 in place, 0 missing, 0 wrong copies + 1 of the 0 wrong copies is replaced, + the old one kept in a backup folder. Free space: 50.0 GB - > Close Options - A Close B Back Y Options === plan-in-place 40x15 RetroBIOS: RetroArch @@ -475,14 +475,14 @@ BIOS folder: ~/.config/retroarch/system 5 in place, 0 missing, 0 wrong copies + 1 of the 0 wrong copies is replaced, + the old one kept in a backup folder. Free space: 50.0 GB > Close Options - - A Close B Back Y Options === plan-in-place 80x24 RetroBIOS: RetroArch @@ -490,6 +490,7 @@ Everything is in place BIOS folder: ~/.config/retroarch/system 5 in place, 0 missing, 0 wrong copies + 1 of the 0 wrong copies is replaced, the old one kept in a backup folder. Free space: 50.0 GB > Close @@ -507,47 +508,46 @@ - A Close B Back Y Options === systems 40x12 RetroBIOS: Choose systems + [x] nintendo-gba (gba) 16.0 KB + [x] sony-playstation 1.0 MB + > [ ] nintendo-famicom-disk in place All None - Filter (with a keyboard) - > [x] nintendo-gba (gba) 16.0 KB - [x] sony-playstation 1.0 MB - [ ] nintendo-famicom-disk in place - - + 1-3 of 3 + nintendo-famicom-disk (ファミコン): in + place 2 of 3 systems: 4 files, 1.0 MB - A Continue B Back X Tick + A Tick B Done === systems 40x15 RetroBIOS: Choose systems + Filter (with a keyboard) + [x] nintendo-gba (gba) 16.0 KB + [x] sony-playstation 1.0 MB + > [ ] nintendo-famicom-disk in place All None - Filter (with a keyboard) - > [x] nintendo-gba (gba) 16.0 KB - [x] sony-playstation 1.0 MB - [ ] nintendo-famicom-disk in place - - - + Done + nintendo-famicom-disk (ファミコン): in + place 2 of 3 systems: 4 files, 1.0 MB - A Continue B Back X Tick + A Tick B Done === systems 80x24 RetroBIOS: Choose systems + Filter (with a keyboard) + [x] nintendo-gba (gba) 1 file, 16.0 KB + [x] sony-playstation 3 files, 1.0 MB + > [ ] nintendo-famicom-disk (ファミコン) in place All None - Filter (with a keyboard) - > [x] nintendo-gba (gba) 1 file, 16.0 KB - [x] sony-playstation 3 files, 1.0 MB - [ ] nintendo-famicom-disk (ファミコン) in place - + Done @@ -562,7 +562,7 @@ 2 of 3 systems: 4 files, 1.0 MB - A Continue B Back X Tick + A Tick B Done === options 40x12 RetroBIOS: Options @@ -628,7 +628,7 @@ > [1] North America [ ] Japan - + 1-2 of 2 A Tick B Done <> Order === regions 40x15 RetroBIOS: Preferred regions @@ -641,8 +641,8 @@ > [1] North America [ ] Japan - - + None + Done A Tick B Done <> Order @@ -655,8 +655,8 @@ > [1] North America [ ] Japan - - + None + Done @@ -674,43 +674,44 @@ === cores 40x12 RetroBIOS: Cores - Every core ticked keeps every core's - files. Untick the cores you do not - use: the platform's own files are - always kept. - > All - None - Filter (with a keyboard) - [ ] mesen - [x] pcsx_rearmed - A Tick all B Back X Tick + Untick the cores you do not use: the + platform's own files are always + kept, and a core with no extra file + reads only those. + + > Filter (with a keyboard) + [ ] mesen 1 file, 8.0 KB + [x] pcsx_rearmed 1 file, 4 B + 1-2 of 2 + A Filter B Done === cores 40x15 RetroBIOS: Cores - Every core ticked keeps every core's - files. Untick the cores you do not - use: the platform's own files are - always kept. + Untick the cores you do not use: the + platform's own files are always + kept, and a core with no extra file + reads only those. - > All + > Filter (with a keyboard) + [ ] mesen 1 file, 8.0 KB + [x] pcsx_rearmed 1 file, 4 B + All None - Filter (with a keyboard) - [ ] mesen - [x] pcsx_rearmed + Done - - A Tick all B Back X Tick + A Filter B Done === cores 80x24 RetroBIOS: Cores - Every core ticked keeps every core's files. Untick the cores you do not use: - the platform's own files are always kept. + Untick the cores you do not use: the platform's own files are always kept, and + a core with no extra file reads only those. - > All + > Filter (with a keyboard) + [ ] mesen 1 file, 8.0 KB + [x] pcsx_rearmed 1 file, 4 B + All None - Filter (with a keyboard) - [ ] mesen - [x] pcsx_rearmed + Done @@ -723,8 +724,7 @@ - - A Tick all B Back X Tick + A Filter B Done === preview 80x24 RetroBIOS: Preview @@ -890,11 +890,11 @@ BIOS folder: /home/user/.config/retroarch/system failed: scph5500.bin (HTTP 404) + Run it again to retry only those. The files it replaced are kept in /home/user/.config/retroarch/ retrobios-backup/2026-10-23_1200 Details: /tmp/retrobios-x/install.log - A Exit === result 40x15 RetroBIOS: Finished with errors @@ -903,6 +903,7 @@ BIOS folder: /home/user/.config/retroarch/system failed: scph5500.bin (HTTP 404) + Run it again to retry only those. The files it replaced are kept in /home/user/.config/retroarch/ retrobios-backup/2026-10-23_1200 @@ -910,7 +911,6 @@ - A Exit === result 80x24 RetroBIOS: Finished with errors @@ -918,6 +918,7 @@ 3 installed, 1 failed. BIOS folder: /home/user/.config/retroarch/system failed: scph5500.bin (HTTP 404) + Run it again to retry only those. The files it replaced are kept in /home/user/.config/retroarch/retrobios-backup/2026-10-23_1200 Details: /tmp/retrobios-x/install.log @@ -935,7 +936,6 @@ - A Exit === error 40x12 RetroBIOS: Something went wrong diff --git a/tests/fixtures/tui/route-gptokeyb.txt b/tests/fixtures/tui/route-gptokeyb.txt index 57e529f2c..2e35c755c 100644 --- a/tests/fixtures/tui/route-gptokeyb.txt +++ b/tests/fixtures/tui/route-gptokeyb.txt @@ -462,11 +462,11 @@ BIOS folder: ~/.config/retroarch/system 5 in place, 0 missing, 0 wrong copies + 1 of the 0 wrong copies is replaced, + the old one kept in a backup folder. Free space: 50.0 GB - > Close Options - A Close B Back Y Options === plan-in-place 40x15 RetroBIOS: RetroArch @@ -475,14 +475,14 @@ BIOS folder: ~/.config/retroarch/system 5 in place, 0 missing, 0 wrong copies + 1 of the 0 wrong copies is replaced, + the old one kept in a backup folder. Free space: 50.0 GB > Close Options - - A Close B Back Y Options === plan-in-place 80x24 RetroBIOS: RetroArch @@ -490,6 +490,7 @@ Everything is in place BIOS folder: ~/.config/retroarch/system 5 in place, 0 missing, 0 wrong copies + 1 of the 0 wrong copies is replaced, the old one kept in a backup folder. Free space: 50.0 GB > Close @@ -507,47 +508,46 @@ - A Close B Back Y Options === systems 40x12 RetroBIOS: Choose systems + [x] nintendo-gba (gba) 16.0 KB + [x] sony-playstation 1.0 MB + > [ ] nintendo-famicom-disk in place All None - Filter (with a keyboard) - > [x] nintendo-gba (gba) 16.0 KB - [x] sony-playstation 1.0 MB - [ ] nintendo-famicom-disk in place - - + 1-3 of 3 + nintendo-famicom-disk (ファミコン): in + place 2 of 3 systems: 4 files, 1.0 MB - A Continue B Back X Tick + A Tick B Done === systems 40x15 RetroBIOS: Choose systems + Filter (with a keyboard) + [x] nintendo-gba (gba) 16.0 KB + [x] sony-playstation 1.0 MB + > [ ] nintendo-famicom-disk in place All None - Filter (with a keyboard) - > [x] nintendo-gba (gba) 16.0 KB - [x] sony-playstation 1.0 MB - [ ] nintendo-famicom-disk in place - - - + Done + nintendo-famicom-disk (ファミコン): in + place 2 of 3 systems: 4 files, 1.0 MB - A Continue B Back X Tick + A Tick B Done === systems 80x24 RetroBIOS: Choose systems + Filter (with a keyboard) + [x] nintendo-gba (gba) 1 file, 16.0 KB + [x] sony-playstation 3 files, 1.0 MB + > [ ] nintendo-famicom-disk (ファミコン) in place All None - Filter (with a keyboard) - > [x] nintendo-gba (gba) 1 file, 16.0 KB - [x] sony-playstation 3 files, 1.0 MB - [ ] nintendo-famicom-disk (ファミコン) in place - + Done @@ -562,7 +562,7 @@ 2 of 3 systems: 4 files, 1.0 MB - A Continue B Back X Tick + A Tick B Done === options 40x12 RetroBIOS: Options @@ -628,7 +628,7 @@ > [1] North America [ ] Japan - + 1-2 of 2 A Tick B Done <> Order === regions 40x15 RetroBIOS: Preferred regions @@ -641,8 +641,8 @@ > [1] North America [ ] Japan - - + None + Done A Tick B Done <> Order @@ -655,8 +655,8 @@ > [1] North America [ ] Japan - - + None + Done @@ -674,43 +674,44 @@ === cores 40x12 RetroBIOS: Cores - Every core ticked keeps every core's - files. Untick the cores you do not - use: the platform's own files are - always kept. - > All - None - Filter (with a keyboard) - [ ] mesen - [x] pcsx_rearmed - A Tick all B Back X Tick + Untick the cores you do not use: the + platform's own files are always + kept, and a core with no extra file + reads only those. + + > Filter (with a keyboard) + [ ] mesen 1 file, 8.0 KB + [x] pcsx_rearmed 1 file, 4 B + 1-2 of 2 + A Filter B Done === cores 40x15 RetroBIOS: Cores - Every core ticked keeps every core's - files. Untick the cores you do not - use: the platform's own files are - always kept. + Untick the cores you do not use: the + platform's own files are always + kept, and a core with no extra file + reads only those. - > All + > Filter (with a keyboard) + [ ] mesen 1 file, 8.0 KB + [x] pcsx_rearmed 1 file, 4 B + All None - Filter (with a keyboard) - [ ] mesen - [x] pcsx_rearmed + Done - - A Tick all B Back X Tick + A Filter B Done === cores 80x24 RetroBIOS: Cores - Every core ticked keeps every core's files. Untick the cores you do not use: - the platform's own files are always kept. + Untick the cores you do not use: the platform's own files are always kept, and + a core with no extra file reads only those. - > All + > Filter (with a keyboard) + [ ] mesen 1 file, 8.0 KB + [x] pcsx_rearmed 1 file, 4 B + All None - Filter (with a keyboard) - [ ] mesen - [x] pcsx_rearmed + Done @@ -723,8 +724,7 @@ - - A Tick all B Back X Tick + A Filter B Done === preview 80x24 RetroBIOS: Preview @@ -890,11 +890,11 @@ BIOS folder: /home/user/.config/retroarch/system failed: scph5500.bin (HTTP 404) + Run it again to retry only those. The files it replaced are kept in /home/user/.config/retroarch/ retrobios-backup/2026-10-23_1200 Details: /tmp/retrobios-x/install.log - A Exit === result 40x15 RetroBIOS: Finished with errors @@ -903,6 +903,7 @@ BIOS folder: /home/user/.config/retroarch/system failed: scph5500.bin (HTTP 404) + Run it again to retry only those. The files it replaced are kept in /home/user/.config/retroarch/ retrobios-backup/2026-10-23_1200 @@ -910,7 +911,6 @@ - A Exit === result 80x24 RetroBIOS: Finished with errors @@ -918,6 +918,7 @@ 3 installed, 1 failed. BIOS folder: /home/user/.config/retroarch/system failed: scph5500.bin (HTTP 404) + Run it again to retry only those. The files it replaced are kept in /home/user/.config/retroarch/retrobios-backup/2026-10-23_1200 Details: /tmp/retrobios-x/install.log @@ -935,7 +936,6 @@ - A Exit === error 40x12 RetroBIOS: Something went wrong diff --git a/tests/fixtures/tui/route-gptokeyb_muxterm.txt b/tests/fixtures/tui/route-gptokeyb_muxterm.txt index 7b58f1a18..0718cf57a 100644 --- a/tests/fixtures/tui/route-gptokeyb_muxterm.txt +++ b/tests/fixtures/tui/route-gptokeyb_muxterm.txt @@ -462,11 +462,11 @@ BIOS folder: ~/.config/retroarch/system 5 in place, 0 missing, 0 wrong copies + 1 of the 0 wrong copies is replaced, + the old one kept in a backup folder. Free space: 50.0 GB - > Close Options - A Close B Back Y Options === plan-in-place 40x15 RetroBIOS: RetroArch @@ -475,14 +475,14 @@ BIOS folder: ~/.config/retroarch/system 5 in place, 0 missing, 0 wrong copies + 1 of the 0 wrong copies is replaced, + the old one kept in a backup folder. Free space: 50.0 GB > Close Options - - A Close B Back Y Options === plan-in-place 80x24 RetroBIOS: RetroArch @@ -490,6 +490,7 @@ Everything is in place BIOS folder: ~/.config/retroarch/system 5 in place, 0 missing, 0 wrong copies + 1 of the 0 wrong copies is replaced, the old one kept in a backup folder. Free space: 50.0 GB > Close @@ -507,47 +508,46 @@ - A Close B Back Y Options === systems 40x12 RetroBIOS: Choose systems + [x] nintendo-gba (gba) 16.0 KB + [x] sony-playstation 1.0 MB + > [ ] nintendo-famicom-disk in place All None - Filter (with a keyboard) - > [x] nintendo-gba (gba) 16.0 KB - [x] sony-playstation 1.0 MB - [ ] nintendo-famicom-disk in place - - + 1-3 of 3 + nintendo-famicom-disk (ファミコン): in + place 2 of 3 systems: 4 files, 1.0 MB - A Continue B Back X Tick + A Tick B Done === systems 40x15 RetroBIOS: Choose systems + Filter (with a keyboard) + [x] nintendo-gba (gba) 16.0 KB + [x] sony-playstation 1.0 MB + > [ ] nintendo-famicom-disk in place All None - Filter (with a keyboard) - > [x] nintendo-gba (gba) 16.0 KB - [x] sony-playstation 1.0 MB - [ ] nintendo-famicom-disk in place - - - + Done + nintendo-famicom-disk (ファミコン): in + place 2 of 3 systems: 4 files, 1.0 MB - A Continue B Back X Tick + A Tick B Done === systems 80x24 RetroBIOS: Choose systems + Filter (with a keyboard) + [x] nintendo-gba (gba) 1 file, 16.0 KB + [x] sony-playstation 3 files, 1.0 MB + > [ ] nintendo-famicom-disk (ファミコン) in place All None - Filter (with a keyboard) - > [x] nintendo-gba (gba) 1 file, 16.0 KB - [x] sony-playstation 3 files, 1.0 MB - [ ] nintendo-famicom-disk (ファミコン) in place - + Done @@ -562,7 +562,7 @@ 2 of 3 systems: 4 files, 1.0 MB - A Continue B Back X Tick + A Tick B Done === options 40x12 RetroBIOS: Options @@ -628,7 +628,7 @@ > [1] North America [ ] Japan - + 1-2 of 2 A Tick B Done <> Order === regions 40x15 RetroBIOS: Preferred regions @@ -641,8 +641,8 @@ > [1] North America [ ] Japan - - + None + Done A Tick B Done <> Order @@ -655,8 +655,8 @@ > [1] North America [ ] Japan - - + None + Done @@ -674,43 +674,44 @@ === cores 40x12 RetroBIOS: Cores - Every core ticked keeps every core's - files. Untick the cores you do not - use: the platform's own files are - always kept. - > All - None - Filter (with a keyboard) - [ ] mesen - [x] pcsx_rearmed - A Tick all B Back X Tick + Untick the cores you do not use: the + platform's own files are always + kept, and a core with no extra file + reads only those. + + > Filter (with a keyboard) + [ ] mesen 1 file, 8.0 KB + [x] pcsx_rearmed 1 file, 4 B + 1-2 of 2 + A Filter B Done === cores 40x15 RetroBIOS: Cores - Every core ticked keeps every core's - files. Untick the cores you do not - use: the platform's own files are - always kept. + Untick the cores you do not use: the + platform's own files are always + kept, and a core with no extra file + reads only those. - > All + > Filter (with a keyboard) + [ ] mesen 1 file, 8.0 KB + [x] pcsx_rearmed 1 file, 4 B + All None - Filter (with a keyboard) - [ ] mesen - [x] pcsx_rearmed + Done - - A Tick all B Back X Tick + A Filter B Done === cores 80x24 RetroBIOS: Cores - Every core ticked keeps every core's files. Untick the cores you do not use: - the platform's own files are always kept. + Untick the cores you do not use: the platform's own files are always kept, and + a core with no extra file reads only those. - > All + > Filter (with a keyboard) + [ ] mesen 1 file, 8.0 KB + [x] pcsx_rearmed 1 file, 4 B + All None - Filter (with a keyboard) - [ ] mesen - [x] pcsx_rearmed + Done @@ -723,8 +724,7 @@ - - A Tick all B Back X Tick + A Filter B Done === preview 80x24 RetroBIOS: Preview @@ -890,11 +890,11 @@ BIOS folder: /home/user/.config/retroarch/system failed: scph5500.bin (HTTP 404) + Run it again to retry only those. The files it replaced are kept in /home/user/.config/retroarch/ retrobios-backup/2026-10-23_1200 Details: /tmp/retrobios-x/install.log - A Exit === result 40x15 RetroBIOS: Finished with errors @@ -903,6 +903,7 @@ BIOS folder: /home/user/.config/retroarch/system failed: scph5500.bin (HTTP 404) + Run it again to retry only those. The files it replaced are kept in /home/user/.config/retroarch/ retrobios-backup/2026-10-23_1200 @@ -910,7 +911,6 @@ - A Exit === result 80x24 RetroBIOS: Finished with errors @@ -918,6 +918,7 @@ 3 installed, 1 failed. BIOS folder: /home/user/.config/retroarch/system failed: scph5500.bin (HTTP 404) + Run it again to retry only those. The files it replaced are kept in /home/user/.config/retroarch/retrobios-backup/2026-10-23_1200 Details: /tmp/retrobios-x/install.log @@ -935,7 +936,6 @@ - A Exit === error 40x12 RetroBIOS: Something went wrong diff --git a/tests/fixtures/tui/route-keys.txt b/tests/fixtures/tui/route-keys.txt index 27618219c..a5dee8a02 100644 --- a/tests/fixtures/tui/route-keys.txt +++ b/tests/fixtures/tui/route-keys.txt @@ -437,11 +437,11 @@ BIOS folder: ~/.config/retroarch/system 5 in place, 0 missing, 0 wrong copies + 1 of the 0 wrong copies is replaced, + the old one kept in a backup folder. Free space: 50.0 GB - > Close Options - Enter Close Esc Back o Options === plan-in-place 40x15 RetroBIOS: RetroArch @@ -450,14 +450,14 @@ BIOS folder: ~/.config/retroarch/system 5 in place, 0 missing, 0 wrong copies + 1 of the 0 wrong copies is replaced, + the old one kept in a backup folder. Free space: 50.0 GB > Close Options - - Enter Close Esc Back o Options === plan-in-place 80x24 RetroBIOS: RetroArch @@ -465,6 +465,7 @@ Everything is in place BIOS folder: ~/.config/retroarch/system 5 in place, 0 missing, 0 wrong copies + 1 of the 0 wrong copies is replaced, the old one kept in a backup folder. Free space: 50.0 GB > Close @@ -482,47 +483,46 @@ - Enter Close Esc Back o Options ? Help === systems 40x12 RetroBIOS: Choose systems + [x] nintendo-gba (gba) 16.0 KB + [x] sony-playstation 1.0 MB + > [ ] nintendo-famicom-disk in place All None - Filter (/ to type) - > [x] nintendo-gba (gba) 16.0 KB - [x] sony-playstation 1.0 MB - [ ] nintendo-famicom-disk in place - - + 1-3 of 3 + nintendo-famicom-disk (ファミコン): in + place 2 of 3 systems: 4 files, 1.0 MB - Enter Continue Esc Back Space Tick + Enter Tick Esc Done ? Help === systems 40x15 RetroBIOS: Choose systems + Filter (/ to type) + [x] nintendo-gba (gba) 16.0 KB + [x] sony-playstation 1.0 MB + > [ ] nintendo-famicom-disk in place All None - Filter (/ to type) - > [x] nintendo-gba (gba) 16.0 KB - [x] sony-playstation 1.0 MB - [ ] nintendo-famicom-disk in place - - - + Done + nintendo-famicom-disk (ファミコン): in + place 2 of 3 systems: 4 files, 1.0 MB - Enter Continue Esc Back Space Tick + Enter Tick Esc Done ? Help === systems 80x24 RetroBIOS: Choose systems + Filter (/ to type) + [x] nintendo-gba (gba) 1 file, 16.0 KB + [x] sony-playstation 3 files, 1.0 MB + > [ ] nintendo-famicom-disk (ファミコン) in place All None - Filter (/ to type) - > [x] nintendo-gba (gba) 1 file, 16.0 KB - [x] sony-playstation 3 files, 1.0 MB - [ ] nintendo-famicom-disk (ファミコン) in place - + Done @@ -537,7 +537,7 @@ 2 of 3 systems: 4 files, 1.0 MB - Enter Continue Esc Back Space Tick ? Help + Enter Tick Esc Done ? Help === options 40x12 RetroBIOS: Options @@ -603,7 +603,7 @@ > [1] North America [ ] Japan - + 1-2 of 2 Enter Tick Esc Done <> Order ? Help === regions 40x15 RetroBIOS: Preferred regions @@ -616,8 +616,8 @@ > [1] North America [ ] Japan - - + None + Done Enter Tick Esc Done <> Order ? Help @@ -630,8 +630,8 @@ > [1] North America [ ] Japan - - + None + Done @@ -649,43 +649,44 @@ === cores 40x12 RetroBIOS: Cores - Every core ticked keeps every core's - files. Untick the cores you do not - use: the platform's own files are - always kept. - > All - None - Filter (/ to type) - [ ] mesen - [x] pcsx_rearmed - Enter Tick all Esc Back Space Tick + Untick the cores you do not use: the + platform's own files are always + kept, and a core with no extra file + reads only those. + + > Filter (/ to type) + [ ] mesen 1 file, 8.0 KB + [x] pcsx_rearmed 1 file, 4 B + 1-2 of 2 + Enter Filter Esc Done ? Help === cores 40x15 RetroBIOS: Cores - Every core ticked keeps every core's - files. Untick the cores you do not - use: the platform's own files are - always kept. + Untick the cores you do not use: the + platform's own files are always + kept, and a core with no extra file + reads only those. - > All + > Filter (/ to type) + [ ] mesen 1 file, 8.0 KB + [x] pcsx_rearmed 1 file, 4 B + All None - Filter (/ to type) - [ ] mesen - [x] pcsx_rearmed + Done - - Enter Tick all Esc Back Space Tick + Enter Filter Esc Done ? Help === cores 80x24 RetroBIOS: Cores - Every core ticked keeps every core's files. Untick the cores you do not use: - the platform's own files are always kept. + Untick the cores you do not use: the platform's own files are always kept, and + a core with no extra file reads only those. - > All + > Filter (/ to type) + [ ] mesen 1 file, 8.0 KB + [x] pcsx_rearmed 1 file, 4 B + All None - Filter (/ to type) - [ ] mesen - [x] pcsx_rearmed + Done @@ -698,8 +699,7 @@ - - Enter Tick all Esc Back Space Tick ? Help + Enter Filter Esc Done ? Help === preview 40x12 RetroBIOS: Preview @@ -923,11 +923,11 @@ BIOS folder: /home/user/.config/retroarch/system failed: scph5500.bin (HTTP 404) + Run it again to retry only those. The files it replaced are kept in /home/user/.config/retroarch/ retrobios-backup/2026-10-23_1200 - To put them back: python3 install.py \ - 1-8 of 16 + 1-8 of 17 Enter Exit ^v Scroll === result 40x15 RetroBIOS: Finished with errors @@ -936,14 +936,14 @@ BIOS folder: /home/user/.config/retroarch/system failed: scph5500.bin (HTTP 404) + Run it again to retry only those. The files it replaced are kept in /home/user/.config/retroarch/ retrobios-backup/2026-10-23_1200 To put them back: python3 install.py \ --restore .../2026-10-23_1200 Shortened to fit this window. - Same choice without questions: - 1-11 of 16 + 1-11 of 17 Enter Exit ^v Scroll === result 80x24 RetroBIOS: Finished with errors @@ -951,6 +951,7 @@ 3 installed, 1 failed. BIOS folder: /home/user/.config/retroarch/system failed: scph5500.bin (HTTP 404) + Run it again to retry only those. The files it replaced are kept in /home/user/.config/retroarch/retrobios-backup/2026-10-23_1200 To put them back: python3 install.py \ @@ -968,7 +969,6 @@ - Enter Exit === error 40x12 RetroBIOS: Something went wrong diff --git a/tests/fixtures/tui/route-miyoo.txt b/tests/fixtures/tui/route-miyoo.txt index 80d5b8cbd..064a1f0cd 100644 --- a/tests/fixtures/tui/route-miyoo.txt +++ b/tests/fixtures/tui/route-miyoo.txt @@ -491,11 +491,11 @@ BIOS folder: ~/.config/retroarch/system 5 in place, 0 missing, 0 wrong copies + 1 of the 0 wrong copies is replaced, + the old one kept in a backup folder. Free space: 50.0 GB - > Close Options - A Close R2 Back L2 Options === plan-in-place 40x15 RetroBIOS: RetroArch @@ -504,14 +504,14 @@ BIOS folder: ~/.config/retroarch/system 5 in place, 0 missing, 0 wrong copies + 1 of the 0 wrong copies is replaced, + the old one kept in a backup folder. Free space: 50.0 GB > Close Options - - A Close R2 Back L2 Options === plan-in-place 80x24 RetroBIOS: RetroArch @@ -519,6 +519,7 @@ Everything is in place BIOS folder: ~/.config/retroarch/system 5 in place, 0 missing, 0 wrong copies + 1 of the 0 wrong copies is replaced, the old one kept in a backup folder. Free space: 50.0 GB > Close @@ -536,47 +537,46 @@ - A Close R2 Back L2 Options === systems 40x12 RetroBIOS: Choose systems + [x] nintendo-gba (gba) 16.0 KB + [x] sony-playstation 1.0 MB + > [ ] nintendo-famicom-disk in place All None - Filter (with a keyboard) - > [x] nintendo-gba (gba) 16.0 KB - [x] sony-playstation 1.0 MB - [ ] nintendo-famicom-disk in place - - + 1-3 of 3 + nintendo-famicom-disk (ファミコン): in + place 2 of 3 systems: 4 files, 1.0 MB - Start Continue A Tick R2 Back + A Tick R2 Done === systems 40x15 RetroBIOS: Choose systems + Filter (with a keyboard) + [x] nintendo-gba (gba) 16.0 KB + [x] sony-playstation 1.0 MB + > [ ] nintendo-famicom-disk in place All None - Filter (with a keyboard) - > [x] nintendo-gba (gba) 16.0 KB - [x] sony-playstation 1.0 MB - [ ] nintendo-famicom-disk in place - - - + Done + nintendo-famicom-disk (ファミコン): in + place 2 of 3 systems: 4 files, 1.0 MB - Start Continue A Tick R2 Back + A Tick R2 Done === systems 80x24 RetroBIOS: Choose systems + Filter (with a keyboard) + [x] nintendo-gba (gba) 1 file, 16.0 KB + [x] sony-playstation 3 files, 1.0 MB + > [ ] nintendo-famicom-disk (ファミコン) in place All None - Filter (with a keyboard) - > [x] nintendo-gba (gba) 1 file, 16.0 KB - [x] sony-playstation 3 files, 1.0 MB - [ ] nintendo-famicom-disk (ファミコン) in place - + Done @@ -591,7 +591,7 @@ 2 of 3 systems: 4 files, 1.0 MB - Start Continue A Tick R2 Back + A Tick R2 Done === options 40x12 RetroBIOS: Options @@ -657,7 +657,7 @@ > [1] North America [ ] Japan - + 1-2 of 2 A Tick R2 Done <> Order === regions 40x15 RetroBIOS: Preferred regions @@ -670,8 +670,8 @@ > [1] North America [ ] Japan - - + None + Done A Tick R2 Done <> Order @@ -684,8 +684,8 @@ > [1] North America [ ] Japan - - + None + Done @@ -703,43 +703,44 @@ === cores 40x12 RetroBIOS: Cores - Every core ticked keeps every core's - files. Untick the cores you do not - use: the platform's own files are - always kept. - > All - None - Filter (with a keyboard) - [ ] mesen - [x] pcsx_rearmed - A Tick all R2 Back + Untick the cores you do not use: the + platform's own files are always + kept, and a core with no extra file + reads only those. + + > Filter (with a keyboard) + [ ] mesen 1 file, 8.0 KB + [x] pcsx_rearmed 1 file, 4 B + 1-2 of 2 + A Filter R2 Done === cores 40x15 RetroBIOS: Cores - Every core ticked keeps every core's - files. Untick the cores you do not - use: the platform's own files are - always kept. + Untick the cores you do not use: the + platform's own files are always + kept, and a core with no extra file + reads only those. - > All + > Filter (with a keyboard) + [ ] mesen 1 file, 8.0 KB + [x] pcsx_rearmed 1 file, 4 B + All None - Filter (with a keyboard) - [ ] mesen - [x] pcsx_rearmed + Done - - A Tick all R2 Back + A Filter R2 Done === cores 80x24 RetroBIOS: Cores - Every core ticked keeps every core's files. Untick the cores you do not use: - the platform's own files are always kept. + Untick the cores you do not use: the platform's own files are always kept, and + a core with no extra file reads only those. - > All + > Filter (with a keyboard) + [ ] mesen 1 file, 8.0 KB + [x] pcsx_rearmed 1 file, 4 B + All None - Filter (with a keyboard) - [ ] mesen - [x] pcsx_rearmed + Done @@ -752,8 +753,7 @@ - - A Tick all R2 Back + A Filter R2 Done === preview 80x24 RetroBIOS: Preview @@ -919,11 +919,11 @@ BIOS folder: /home/user/.config/retroarch/system failed: scph5500.bin (HTTP 404) + Run it again to retry only those. The files it replaced are kept in /home/user/.config/retroarch/ retrobios-backup/2026-10-23_1200 Details: /tmp/retrobios-x/install.log - A Exit === result 40x15 RetroBIOS: Finished with errors @@ -932,6 +932,7 @@ BIOS folder: /home/user/.config/retroarch/system failed: scph5500.bin (HTTP 404) + Run it again to retry only those. The files it replaced are kept in /home/user/.config/retroarch/ retrobios-backup/2026-10-23_1200 @@ -939,7 +940,6 @@ - A Exit === result 80x24 RetroBIOS: Finished with errors @@ -947,6 +947,7 @@ 3 installed, 1 failed. BIOS folder: /home/user/.config/retroarch/system failed: scph5500.bin (HTTP 404) + Run it again to retry only those. The files it replaced are kept in /home/user/.config/retroarch/retrobios-backup/2026-10-23_1200 Details: /tmp/retrobios-x/install.log @@ -964,7 +965,6 @@ - A Exit === error 40x12 RetroBIOS: Something went wrong diff --git a/tests/fixtures/tui/route-muxterm.txt b/tests/fixtures/tui/route-muxterm.txt index 1ad851b69..0b540a875 100644 --- a/tests/fixtures/tui/route-muxterm.txt +++ b/tests/fixtures/tui/route-muxterm.txt @@ -491,11 +491,11 @@ BIOS folder: ~/.config/retroarch/system 5 in place, 0 missing, 0 wrong copies + 1 of the 0 wrong copies is replaced, + the old one kept in a backup folder. Free space: 50.0 GB - > Close Options - Start Close B Back === plan-in-place 40x15 RetroBIOS: RetroArch @@ -504,14 +504,14 @@ BIOS folder: ~/.config/retroarch/system 5 in place, 0 missing, 0 wrong copies + 1 of the 0 wrong copies is replaced, + the old one kept in a backup folder. Free space: 50.0 GB > Close Options - - Start Close B Back === plan-in-place 80x24 RetroBIOS: RetroArch @@ -519,6 +519,7 @@ Everything is in place BIOS folder: ~/.config/retroarch/system 5 in place, 0 missing, 0 wrong copies + 1 of the 0 wrong copies is replaced, the old one kept in a backup folder. Free space: 50.0 GB > Close @@ -536,47 +537,46 @@ - Start Close B Back === systems 40x12 RetroBIOS: Choose systems + [x] nintendo-gba (gba) 16.0 KB + [x] sony-playstation 1.0 MB + > [ ] nintendo-famicom-disk in place All None - Filter (Select shows a keyboard) - > [x] nintendo-gba (gba) 16.0 KB - [x] sony-playstation 1.0 MB - [ ] nintendo-famicom-disk in place - - + 1-3 of 3 + nintendo-famicom-disk (ファミコン): in + place 2 of 3 systems: 4 files, 1.0 MB - Start Continue B Back Y Tick + Start Tick B Done === systems 40x15 RetroBIOS: Choose systems + Filter (Select shows a keyboard) + [x] nintendo-gba (gba) 16.0 KB + [x] sony-playstation 1.0 MB + > [ ] nintendo-famicom-disk in place All None - Filter (Select shows a keyboard) - > [x] nintendo-gba (gba) 16.0 KB - [x] sony-playstation 1.0 MB - [ ] nintendo-famicom-disk in place - - - + Done + nintendo-famicom-disk (ファミコン): in + place 2 of 3 systems: 4 files, 1.0 MB - Start Continue B Back Y Tick + Start Tick B Done === systems 80x24 RetroBIOS: Choose systems + Filter (Select shows a keyboard) + [x] nintendo-gba (gba) 1 file, 16.0 KB + [x] sony-playstation 3 files, 1.0 MB + > [ ] nintendo-famicom-disk (ファミコン) in place All None - Filter (Select shows a keyboard) - > [x] nintendo-gba (gba) 1 file, 16.0 KB - [x] sony-playstation 3 files, 1.0 MB - [ ] nintendo-famicom-disk (ファミコン) in place - + Done @@ -591,7 +591,7 @@ 2 of 3 systems: 4 files, 1.0 MB - Start Continue B Back Y Tick + Start Tick B Done === options 40x12 RetroBIOS: Options @@ -657,7 +657,7 @@ > [1] North America [ ] Japan - + 1-2 of 2 Start Tick B Done <> Order === regions 40x15 RetroBIOS: Preferred regions @@ -670,8 +670,8 @@ > [1] North America [ ] Japan - - + None + Done Start Tick B Done <> Order @@ -684,8 +684,8 @@ > [1] North America [ ] Japan - - + None + Done @@ -703,43 +703,44 @@ === cores 40x12 RetroBIOS: Cores - Every core ticked keeps every core's - files. Untick the cores you do not - use: the platform's own files are - always kept. - > All - None - Filter (Select shows a keyboard) - [ ] mesen - [x] pcsx_rearmed - Start Tick all B Back Y Tick + Untick the cores you do not use: the + platform's own files are always + kept, and a core with no extra file + reads only those. + + > Filter (Select shows a keyboard) + [ ] mesen 1 file, 8.0 KB + [x] pcsx_rearmed 1 file, 4 B + 1-2 of 2 + Start Filter B Done === cores 40x15 RetroBIOS: Cores - Every core ticked keeps every core's - files. Untick the cores you do not - use: the platform's own files are - always kept. + Untick the cores you do not use: the + platform's own files are always + kept, and a core with no extra file + reads only those. - > All + > Filter (Select shows a keyboard) + [ ] mesen 1 file, 8.0 KB + [x] pcsx_rearmed 1 file, 4 B + All None - Filter (Select shows a keyboard) - [ ] mesen - [x] pcsx_rearmed + Done - - Start Tick all B Back Y Tick + Start Filter B Done === cores 80x24 RetroBIOS: Cores - Every core ticked keeps every core's files. Untick the cores you do not use: - the platform's own files are always kept. + Untick the cores you do not use: the platform's own files are always kept, and + a core with no extra file reads only those. - > All + > Filter (Select shows a keyboard) + [ ] mesen 1 file, 8.0 KB + [x] pcsx_rearmed 1 file, 4 B + All None - Filter (Select shows a keyboard) - [ ] mesen - [x] pcsx_rearmed + Done @@ -752,8 +753,7 @@ - - Start Tick all B Back Y Tick + Start Filter B Done === preview 40x12 RetroBIOS: Preview @@ -977,11 +977,11 @@ BIOS folder: /home/user/.config/retroarch/system failed: scph5500.bin (HTTP 404) + Run it again to retry only those. The files it replaced are kept in /home/user/.config/retroarch/ retrobios-backup/2026-10-23_1200 Details: /tmp/retrobios-x/install.log - Start Exit === result 40x15 RetroBIOS: Finished with errors @@ -990,6 +990,7 @@ BIOS folder: /home/user/.config/retroarch/system failed: scph5500.bin (HTTP 404) + Run it again to retry only those. The files it replaced are kept in /home/user/.config/retroarch/ retrobios-backup/2026-10-23_1200 @@ -997,7 +998,6 @@ - Start Exit === result 80x24 RetroBIOS: Finished with errors @@ -1005,6 +1005,7 @@ 3 installed, 1 failed. BIOS folder: /home/user/.config/retroarch/system failed: scph5500.bin (HTTP 404) + Run it again to retry only those. The files it replaced are kept in /home/user/.config/retroarch/retrobios-backup/2026-10-23_1200 Details: /tmp/retrobios-x/install.log @@ -1022,7 +1023,6 @@ - Start Exit === error 40x12 RetroBIOS: Something went wrong diff --git a/tests/fixtures/tui/systems-120x40.txt b/tests/fixtures/tui/systems-120x40.txt index 0580bbaa7..8937114b5 100644 --- a/tests/fixtures/tui/systems-120x40.txt +++ b/tests/fixtures/tui/systems-120x40.txt @@ -1,12 +1,12 @@ RetroBIOS: Choose systems + Filter (/ to type) + [x] nintendo-gba (gba) 1 file, 16.0 KB + [x] sony-playstation 3 files, 1.0 MB + > [ ] nintendo-famicom-disk (ファミコン) in place All None - Filter (/ to type) - > [x] nintendo-gba (gba) 1 file, 16.0 KB - [x] sony-playstation 3 files, 1.0 MB - [ ] nintendo-famicom-disk (ファミコン) in place - + Done @@ -37,4 +37,4 @@ 2 of 3 systems: 4 files, 1.0 MB - A/Enter Continue B/Esc Back X/Space Tick ? Help + A/Enter Tick B/Esc Done ? Help diff --git a/tests/fixtures/tui/systems-40x12.txt b/tests/fixtures/tui/systems-40x12.txt index 175f36cc5..82bb1c13a 100644 --- a/tests/fixtures/tui/systems-40x12.txt +++ b/tests/fixtures/tui/systems-40x12.txt @@ -1,12 +1,12 @@ RetroBIOS: Choose systems + [x] nintendo-gba (gba) 16.0 KB + [x] sony-playstation 1.0 MB + > [ ] nintendo-famicom-disk in place All None - Filter (/ to type) - > [x] nintendo-gba (gba) 16.0 KB - [x] sony-playstation 1.0 MB - [ ] nintendo-famicom-disk in place - - + 1-3 of 3 + nintendo-famicom-disk (ファミコン): in + place 2 of 3 systems: 4 files, 1.0 MB - A Continue B Back X Tick ? Help + A Tick B Done ? Help diff --git a/tests/fixtures/tui/systems-40x15.txt b/tests/fixtures/tui/systems-40x15.txt index 60f7b0ccc..95c9c61da 100644 --- a/tests/fixtures/tui/systems-40x15.txt +++ b/tests/fixtures/tui/systems-40x15.txt @@ -1,15 +1,15 @@ RetroBIOS: Choose systems + Filter (/ to type) + [x] nintendo-gba (gba) 16.0 KB + [x] sony-playstation 1.0 MB + > [ ] nintendo-famicom-disk in place All None - Filter (/ to type) - > [x] nintendo-gba (gba) 16.0 KB - [x] sony-playstation 1.0 MB - [ ] nintendo-famicom-disk in place - - - + Done + nintendo-famicom-disk (ファミコン): in + place 2 of 3 systems: 4 files, 1.0 MB - A Continue B Back X Tick ? Help + A Tick B Done ? Help diff --git a/tests/fixtures/tui/systems-80x24.txt b/tests/fixtures/tui/systems-80x24.txt index 317c5e252..e346db6ac 100644 --- a/tests/fixtures/tui/systems-80x24.txt +++ b/tests/fixtures/tui/systems-80x24.txt @@ -1,12 +1,12 @@ RetroBIOS: Choose systems + Filter (/ to type) + [x] nintendo-gba (gba) 1 file, 16.0 KB + [x] sony-playstation 3 files, 1.0 MB + > [ ] nintendo-famicom-disk (ファミコン) in place All None - Filter (/ to type) - > [x] nintendo-gba (gba) 1 file, 16.0 KB - [x] sony-playstation 3 files, 1.0 MB - [ ] nintendo-famicom-disk (ファミコン) in place - + Done @@ -21,4 +21,4 @@ 2 of 3 systems: 4 files, 1.0 MB - A/Enter Continue B/Esc Back X/Space Tick ? Help + A/Enter Tick B/Esc Done ? Help diff --git a/tests/netguard/__init__.py b/tests/netguard/__init__.py new file mode 100644 index 000000000..c2ffc9a2b --- /dev/null +++ b/tests/netguard/__init__.py @@ -0,0 +1,33 @@ +"""The guard a test module turns on for itself and the Python it starts +(sitecustomize). module_guard() gives the setUpModule and tearDownModule +pair: the module fails at its end when anything tried to leave the loopback.""" + +from __future__ import annotations + +import os +from pathlib import Path +from typing import Callable + +from .sitecustomize import disable, enable, refused + +__all__ = ["module_guard", "enable", "disable", "refused"] + + +def module_guard(name: str) -> tuple[Callable[[], None], Callable[[], None]]: + log = Path(__file__).resolve().parents[2] / "tmp" / "tests" / f"netlog-{name}-{os.getpid()}" + state: dict = {} + + def set_up() -> None: + log.parent.mkdir(parents=True, exist_ok=True) + state["before"] = enable(str(log)) + + def tear_down() -> None: + disable(state.pop("before", {})) + tried = refused(str(log)) + log.unlink(missing_ok=True) + if tried: + raise AssertionError( + f"{len(tried)} connections off the loopback during {name} (pid host): " + + ", ".join(tried[:10])) + + return set_up, tear_down diff --git a/tests/netguard/sitecustomize.py b/tests/netguard/sitecustomize.py new file mode 100644 index 000000000..2aa5f732d --- /dev/null +++ b/tests/netguard/sitecustomize.py @@ -0,0 +1,133 @@ +"""The machine running the installer tests, kept out of them. + +Python imports this module at start in every process a test starts with +tests/netguard on PYTHONPATH (enable), and the test module +calls guard() for its own process. Two things the host has never reach a +test: a connection off the loopback, which is refused (OSError, as a network +that is down) and written to RETROBIOS_TEST_NETLOG, and the cards and drives +mounted under /media, /run/media, /mnt and /Volumes, which read as folders +no drive is mounted on. A test module passed on a machine with no network +and no card, and failed with an AmberELEC card in the reader, while 261 +connections to GitHub left the module in a run (code_audit_24 P3-13). +""" + +from __future__ import annotations + +import errno +import os +import socket +import sys + +LOOPBACK = frozenset({"127.0.0.1", "::1", "localhost", "0.0.0.0", ""}) +MOUNT_ROOTS = ("/media", "/run/media", "/mnt", "/Volumes") +NETLOG = "RETROBIOS_TEST_NETLOG" +# What guard() replaced, for unguard(). +_SAVED: dict = {} + + +def _refuse(host: object) -> None: + where = os.environ.get(NETLOG) + if where: + with open(where, "a", encoding="utf-8") as log: + log.write(f"{os.getpid()} {host} {' '.join(sys.argv)[:300]}\n") + raise OSError(errno.ENETUNREACH, f"a test makes no request to {host}") + + +def guard() -> None: + """Refuse every connection off the loopback, hide the host's mounts.""" + if _SAVED: + return + _SAVED.update(connect=socket.socket.__dict__.get("connect"), + connect_ex=socket.socket.__dict__.get("connect_ex"), + getaddrinfo=socket.getaddrinfo, ismount=os.path.ismount) + connect = socket.socket.connect + connect_ex = socket.socket.connect_ex + getaddrinfo = socket.getaddrinfo + + def host_of(address: object) -> object: + return address[0] if isinstance(address, tuple) and address else None + + def checked(sock: socket.socket, address: object) -> None: + if sock.family in (socket.AF_INET, socket.AF_INET6) and \ + host_of(address) not in LOOPBACK: + _refuse(host_of(address)) + + def guarded_connect(self: socket.socket, address: object) -> None: + checked(self, address) + return connect(self, address) + + def guarded_connect_ex(self: socket.socket, address: object) -> int: + checked(self, address) + return connect_ex(self, address) + + def guarded_getaddrinfo(host: object, *args: object, **kwargs: object) -> list: + if host is not None and str(host) not in LOOPBACK: + _refuse(host) + return getaddrinfo(host, *args, **kwargs) + + socket.socket.connect = guarded_connect # type: ignore[method-assign] + socket.socket.connect_ex = guarded_connect_ex # type: ignore[method-assign] + socket.getaddrinfo = guarded_getaddrinfo # type: ignore[assignment] + + ismount = os.path.ismount + + def guarded_ismount(path: object) -> bool: + text = os.fspath(path) if not isinstance(path, str) else path + if isinstance(text, bytes): + text = text.decode(errors="replace") + if any(text == root or text.startswith(root + "/") for root in MOUNT_ROOTS): + return False + return ismount(path) + + os.path.ismount = guarded_ismount # type: ignore[assignment] + + +def unguard() -> None: + """The process as it was before guard().""" + if not _SAVED: + return + for name in ("connect", "connect_ex"): + if _SAVED[name] is None: + delattr(socket.socket, name) + else: + setattr(socket.socket, name, _SAVED[name]) + socket.getaddrinfo = _SAVED["getaddrinfo"] + os.path.ismount = _SAVED["ismount"] + _SAVED.clear() + + +def enable(log: str) -> dict: + """Guard this process and every Python it starts, the refusals written + to log. Returns the variables it changed, for disable().""" + before = {name: os.environ.get(name) for name in ("PYTHONPATH", NETLOG)} + here = os.path.dirname(os.path.abspath(__file__)) + paths = [here, *[p for p in os.environ.get("PYTHONPATH", "").split(os.pathsep) if p]] + os.environ["PYTHONPATH"] = os.pathsep.join(dict.fromkeys(paths)) + os.environ[NETLOG] = log + with open(log, "w", encoding="utf-8"): + pass + guard() + return before + + +def disable(before: dict) -> None: + """This process and the Python it starts as before enable().""" + unguard() + for name, value in before.items(): + if value is None: + os.environ.pop(name, None) + else: + os.environ[name] = value + + +def refused(log: str) -> list[str]: + """The connections refused since enable(log), one line each.""" + try: + with open(log, encoding="utf-8") as text: + return [line.strip() for line in text if line.strip()] + except OSError: + return [] + + +if os.environ.get(NETLOG): + guard() diff --git a/tests/test_doc_pages.py b/tests/test_doc_pages.py index badc4eba8..286bd0b28 100644 --- a/tests/test_doc_pages.py +++ b/tests/test_doc_pages.py @@ -175,6 +175,59 @@ class InstallerOutputExample(unittest.TestCase): self.assertLessEqual(abs(added - float(total) * units[unit]), 0.15 * units[unit]) +class InstallerSamplesSayWhatTheCodePrints(unittest.TestCase): + """code_audit_24 P3-8 to P3-12: samples typed by hand outside the + generated blocks, a sentence on a log read as the terminal's, pages that + described the generator as tables alone, and a sandbox that asked DNS.""" + + def test_the_refused_and_from_samples_are_generated(self): + import install + + page = _page("installer.md") + refused = _generated(page, "check-refused") + self.assertRegex(refused, r"\n \d+ files? [a-z ]+:\n") + self.assertIn("read by beetle_psx, pcsx_rearmed at", refused) + self.assertNotIn("opened at", page) + self.assertIn('"read by ', inspect.getsource(install.opened_line)) + ending = _generated(page, "from-run") + self.assertRegex(ending, r"Done\. \d+ files installed\.\n \d+ files copied from ") + self.assertNotIn("a line under\n`Done`", page) + self.assertNotIn("38 files copied from E:\\, 4 downloaded", page) + + def test_one_line_per_file_is_said_of_a_log(self): + page = _page("installer.md") + at = page.index("") + before = page[page.rindex("\n\n", 0, at - 2):at] + self.assertIn("At a terminal one progress line", before) + self.assertIn("A pipe or a log gets one line per file", before) + + def test_the_generator_pages_name_the_run_samples_and_step_7(self): + tools = _page("tools.md") + row = next(line for line in tools.splitlines() + if line.startswith("| `generate_installer_doc.py`")) + self.assertIn("run samples", row) + self.assertIn("generate_installer_doc.py", next( + line for line in tools.splitlines() if line.startswith("| 7 |"))) + self.assertIn("run samples", _page("installer.md").split( + "The tables of options, events, exit codes, keys and card markers", 1)[1][:600]) + self.assertIn("generate_installer_doc.py", next( + line for line in _page("adding-a-platform.md").splitlines() + if line.startswith("7. "))) + + def test_the_sandbox_looks_nothing_up(self): + import socket + from unittest import mock + + import generate_installer_doc + + def no_lookup(*_args: object) -> str: + raise AssertionError("the sandbox asked for a name") + + with mock.patch.object(socket, "getfqdn", no_lookup), \ + generate_installer_doc.Sandbox() as box: + self.assertEqual(box.server.server_name, "127.0.0.1") + + class OneResolutionChain(unittest.TestCase): """architecture.md drew path_suffix as the first step, before SHA1, while the code and verification-modes.md try it after every hash.""" diff --git a/tests/test_install.py b/tests/test_install.py index 60d2fe8fe..6ddeebd43 100644 --- a/tests/test_install.py +++ b/tests/test_install.py @@ -31,6 +31,13 @@ _spec = importlib.util.spec_from_file_location("install", REPO_ROOT / "install.p install = importlib.util.module_from_spec(_spec) _spec.loader.exec_module(install) +sys.path.insert(0, str(REPO_ROOT / "tests")) +from netguard import module_guard # noqa: E402 + +# No connection off the loopback and no card of the host reaches a test +# (code_audit_24 P3-13): the module fails at its end otherwise. +setUpModule, tearDownModule = module_guard("test_install") + def _tempdir(test: unittest.TestCase) -> str: """A scratch directory under the repository's tmp/, removed after the test. diff --git a/tests/test_install_tui.py b/tests/test_install_tui.py index 58b449467..63c888c59 100644 --- a/tests/test_install_tui.py +++ b/tests/test_install_tui.py @@ -35,7 +35,7 @@ import types import unittest import warnings import zipfile -from pathlib import Path, PureWindowsPath +from pathlib import Path, PurePosixPath, PureWindowsPath from unittest import mock REPO_ROOT = Path(__file__).resolve().parent.parent @@ -45,6 +45,13 @@ sys.path.insert(0, str(REPO_ROOT / "tests")) import install # noqa: E402 from test_install_app import make_card # noqa: E402 from test_install_selection import FakeRepository, _QuietHandler # noqa: E402 +from netguard import module_guard # noqa: E402 + +# No connection off the loopback and no card of the host reaches a test, in +# this process or one it starts (code_audit_24 P3-13): 261 connections to +# GitHub left this module in a run, and two tests failed with an AmberELEC +# card in the reader. The module fails at its end when one is tried. +setUpModule, tearDownModule = module_guard("test_install_tui") try: import pyte @@ -5801,9 +5808,15 @@ def _card_from_rules(root: Path, setup: install.CardSetup) -> Path: (root / path).parent.mkdir(parents=True, exist_ok=True) (root / path).write_text(text + "\n", encoding="utf-8") continue + if rule.method == "games_part": + # What the system writes beside its bios folder on that part. + (root / "bios").mkdir(exist_ok=True) for value in rule.values: (root / value).parent.mkdir(parents=True, exist_ok=True) - (root / value).write_text("", encoding="utf-8") + if rule.method == "games_part" and "." not in PurePosixPath(value).name: + (root / value).mkdir(exist_ok=True) + else: + (root / value).write_text("", encoding="utf-8") return root @@ -13970,5 +13983,420 @@ class AuditTwentyThreeAndSixteen(unittest.TestCase): words.index(install.TUI_INSTALL_ROW)) +def core_list(path: Path, files: list) -> Path: + path.write_text(json.dumps({"manifest_version": 2, "platform": "retroarch", + "categorized": True, "base_destination": "system", + "save_directory": {"folder": "saves", "by_core": True}, + "files": files}), encoding="utf-8") + return path + + +class AuditTwentyFourAndSeventeen(unittest.TestCase): + """code_audit_24 and tui_audit_17: the cores the run accepts, one tick + list, a folder failure said as it happened, every proven card named, + reads that show, and tests that leave the host alone.""" + + setUp = LineModeAndScreenDecideAlike.setUp + line_run = LineModeAndScreenDecideAlike.line_run + entry = staticmethod(LineModeAndScreenDecideAlike.entry) + drive = AuditTwentyTwoAndFifteen.drive + first_screen = AuditTwentyTwoAndFifteen.first_screen + line_from = AuditTwentyThreeAndSixteen.line_from + + # Root cause 1: the cores a choice is made among are the run's. + + def files(self) -> list: + entry = self.entry + return [ + entry("scph5501.bin", b"S" * 8, ["sony-playstation"]), + entry("pcsx/extra.bin", b"P" * 4, ["sony-playstation"], cores=["pcsx_rearmed"]), + entry("fc/disksys.rom", b"F" * 8, ["nintendo-famicom-disk"], cores=["mesen"]), + # Read from the save directory alone: set aside where it is not known. + entry("3ds/aes_keys.txt", b"K" * 4, ["nintendo-3ds"], cores=["azahar"], + root="save"), + # Game data alone: --no-game-data leaves its core no file. + entry("quake/pak0.pak", b"Q" * 4, ["other"], cores=["tyrquake"], + category="game_data"), + ] + + def check_events(self, *extra: str) -> list: + listing = core_list(self.root / "cores.json", self.files()) + dest = self.root / "dest" + dest.mkdir(exist_ok=True) + done = install_run("--platform", "retroarch", "--dest", str(dest), "--manifest", + str(listing), "--check", "--events", *extra, + env={"HOME": str(self.root / "home"), + "RETROBIOS_INSTALL_OFFLINE": "1"}) + return [json.loads(line) for line in done.stdout.splitlines() if line.startswith("{")] + + def cores_state(self, events: list, no_game_data: bool = False) -> install.TuiState: + state = checked_state() + state.manifest = {"manifest_version": 2, "platform": "retroarch", "categorized": True, + "files": self.files()} + state.set_aside = set(next(event for event in events + if event["event"] == "set_aside")["dests"]) + state.no_game_data = no_game_data + return state + + def test_cores_lists_what_the_run_accepts_and_an_untick_runs(self): + """tui_audit_17 P1-1: Cores listed 189 cores where --core accepted 181, + and an untick sent the 8 save-folder-only cores: "unknown core".""" + events = self.check_events() + self.assertEqual(next(e for e in events if e["event"] == "set_aside")["dests"], + ["3ds/aes_keys.txt"]) + state = self.cores_state(events) + self.assertNotIn("azahar", install.tui_choices(state)["cores"]) + state.stack = ["setup", "plan", "options", "cores"] + row = next(r for r in install.tui_rows(state) if r.value == "mesen") + install._tick(state, row, False) + cores = [value for flag, value in install.tui_flags(state) if flag == "--core"] + self.assertEqual(sorted(cores), ["pcsx_rearmed", "tyrquake"]) + listing = self.root / "cores.json" + done = install_run("--platform", "retroarch", "--dest", str(self.root / "dest"), + "--manifest", str(listing), "--dry-run", + *[f"--core={core}" for core in cores], + env={"HOME": str(self.root / "home"), + "RETROBIOS_INSTALL_OFFLINE": "1"}) + self.assertNotIn("unknown core", done.stdout + done.stderr) + + def test_both_modes_count_out_of_the_cores_the_run_keeps(self): + """code_audit_24 P3-3: line mode said "1 of 181 cores", the screen + "1 of 189", and 22 more under --no-game-data.""" + for no_game_data in (False, True): + with self.subTest(no_game_data=no_game_data): + extra = ("--no-game-data",) if no_game_data else () + state = self.cores_state(self.check_events(*extra), no_game_data) + expected = ["mesen", "pcsx_rearmed"] + ([] if no_game_data else ["tyrquake"]) + self.assertEqual(install.tui_choices(state)["cores"], expected) + listing = core_list(self.root / "line.json", self.files()) + # A folder not named system: the save directory is not known. + text, _asked = self.line_run( + _args(manifest=listing, dest=self.root / "dest", declared_only=False, + dry_run=True, no_game_data=no_game_data), ["c", "", "1"]) + head = text.rsplit("Counted again for your choices", 1)[1] + self.assertIn(f"1 of {len(expected)} cores", head) + state.cores = ["mesen"] + self.assertIn(f"1 of {len(expected)}", + next(r.label for r in install.tui_rows( + self.options(state)) if r.action == "cores")) + + @staticmethod + def text(state: install.TuiState, cols: int, rows: int) -> str: + """The frame drawn, its folded lines joined into one text.""" + return " ".join(" ".join(str(line).split()) for line in + install.tui_view(state, cols, rows)) + + @staticmethod + def options(state: install.TuiState) -> install.TuiState: + state.stack = ["setup", "plan", "options"] + return state + + def test_an_untick_keeps_the_other_systems_cores(self): + """code_audit_24 P3-1: with --system sony-playstation, one untick on + pcsx_rearmed cleared mesen, drawn ticked under the other systems.""" + state = checked_state() + state.ticked = {"sony-playstation"} + state.stack = ["setup", "plan", "options", "cores"] + state.cores_all = True + boxes = {r.value: r.label[:3] for r in install.tui_rows(state) if r.action == "core"} + self.assertEqual(boxes, {"mesen": "[x]", "pcsx_rearmed": "[x]"}) + row = next(r for r in install.tui_rows(state) if r.value == "pcsx_rearmed") + install._tick(state, row, None) + boxes = {r.value: r.label[:3] for r in install.tui_rows(state) if r.action == "core"} + self.assertEqual(boxes, {"mesen": "[x]", "pcsx_rearmed": "[ ]"}) + # The --core given is the cores ticked, exactly. + self.assertEqual([v for f, v in install.tui_flags(state) if f == "--core"], ["mesen"]) + + def test_a_core_of_another_system_is_not_all_cores(self): + """code_audit_24 P3-2: mesen ticked alone with the PlayStation chosen + read "Cores: all", the run keeping none of pcsx_rearmed's files.""" + state = checked_state() + state.ticked = {"sony-playstation"} + state.cores = ["mesen"] + options = self.options(state) + self.assertIn("Cores: 0 of 1", [r.label for r in install.tui_rows(options)]) + state.stack = ["setup", "plan"] + self.assertIn("0 of 1 cores", self.text(state, 100, 30)) + self.assertEqual(install.core_count_words(["mesen"], ["pcsx_rearmed"]), "0 of 1 cores") + + def test_none_then_done_says_why_on_a_long_list(self): + """tui_audit_17 P2-4: on 189 cores the status and the sentence were + dropped, Done with nothing ticked did nothing visible.""" + state = checked_state() + state.manifest = {**MANIFEST, "files": [ + *MANIFEST["files"], + *({"dest": f"x/{n}.bin", "size": 1, "systems": ["sony-playstation"], + "cores": [f"core{n:03}"]} for n in range(60))]} + state.stack = ["setup", "plan", "options", "cores"] + state.focus["cores"] = install._first_item(state) + press(state, "n") + done = next(i for i, r in enumerate(install.tui_rows(state)) if r.action == "done") + state.focus["cores"] = done + press(state, "enter") + self.assertEqual(state.screen, "cores") + for cols, rows in ((80, 24), (40, 12)): + text = self.text(state, cols, rows) + self.assertIn("No core is ticked", text) + self.assertIn("Untick the cores", text) + press(state, "esc") + self.assertEqual(state.screen, "cores") + + def test_core_rows_say_what_each_core_adds(self): + """tui_audit_17 P3-2: line mode counted each core's files, the + screen named the cores alone.""" + state = checked_state() + state.stack = ["setup", "plan", "options", "cores"] + rows = {r.value: r.right for r in install.tui_rows(state) if r.action == "core"} + self.assertEqual(rows["pcsx_rearmed"], "1 file, 4 B") + state.cores_all = True + rows = {r.value: r.right for r in install.tui_rows(state) if r.action == "core"} + self.assertEqual(rows["mesen"], "1 file, 8.0 KB") + + def test_one_core_has_no_cores_row(self): + """tui_audit_17 P3-3: a list with one core offered Cores, where line + mode asks nothing.""" + state = checked_state() + state.manifest = {**MANIFEST, "files": [ + entry for entry in MANIFEST["files"] if entry["dest"] != "fc/disksys.rom"]} + self.assertNotIn("cores", [r.action for r in install.tui_rows(self.options(state))]) + + # Root cause 2: one tick list. + + def test_the_three_lists_open_and_answer_alike(self): + """tui_audit_17 P3-1: Choose systems opened on None, A unticking + every system, Cores closed on A, regions ticked on A.""" + for route in ("both", "gptokeyb", "muxterm", "miyoo"): + for screen, opener in (("systems", ("plan", "systems")), + ("cores", ("options", "cores")), + ("regions", ("options", "regions"))): + with self.subTest(route=route, screen=screen): + state = checked_state() + state.pad = route + if opener[0] == "options": + press(state, "o") + state.focus[state.screen] = next( + i for i, r in enumerate(install.tui_rows(state)) + if r.action == opener[1]) + press(state, "enter") + self.assertEqual(state.screen, screen) + rows = install.tui_rows(state) + focused = rows[state.focus[screen]] + self.assertIn(focused.action, install.TUI_TICK_ROWS) + self.assertEqual([r.action for r in rows[-2:]], ["none", "done"]) + hint = install._TUI_VIEWS[screen](state, 78, 21)[2] + self.assertEqual(hint[:2], ("A/Enter Tick", "B/Esc Done")) + before = install.tui_flags(state) + press(state, "enter") + self.assertEqual(state.screen, screen) + self.assertNotEqual(install.tui_flags(state), before) + + # Root cause 3: a folder failure as it happened. + + def test_a_folder_that_cannot_be_created_ends_on_its_reason(self): + """tui_audit_17 P2-1: the result said "22 files not fetched + (RETROBIOS_INSTALL_OFFLINE=1)" and sent the user for a pack.""" + for os_type in ("linux", "android"): + with self.subTest(os_type=os_type): + state = checked_state() + state.os_type = os_type + install.tui_update(state, Key("enter")) + for event in ({"event": "error", "stage": "dest", "reason": "not_writable", + "platform": "retroarch", + "message": f"{SYSTEM_DIR} cannot be created: Permission denied"}, + {"event": "summary", "mode": "install", "installed": 0, + "up_to_date": 0, "pending": 4, "failed": [], "skipped": [], + "left_out": [], "kept": [], "interrupted": False}): + install.tui_receive(state, ("event", state.run_id, event)) + install.tui_receive(state, ("ended", state.run_id, 2, [])) + title, lines = install.tui_outcome(state) + text = " ".join(map(str, lines)) + self.assertEqual(title, "Nothing installed") + self.assertIn("cannot be created (permission denied)", text) + self.assertNotIn("not fetched", text) + self.assertNotIn("not in", text.split("cannot be created")[0]) + self.assertEqual("termux-setup-storage" in text, os_type == "android") + self.assertNotIn("sudo", text if os_type == "android" else "") + + def test_android_never_offers_sudo_and_a_phone_plan_says_why(self): + """tui_audit_17 P2-2: Termux was offered sudo, and at 40x12 the plan + offered Install anyway with no word of why.""" + hint = install.Invocation() + hint.os_type = "android" + remedy = install.write_remedy(Path("/storage/emulated/0/RetroArch/system"), + "retroarch", hint) + self.assertEqual(remedy, [install.TERMUX_STORAGE_WORDS]) + state = checked_state({"free": 50 * 1024 ** 3, "writable": False, "cores": []}) + state.os_type = "android" + for cols, rows in ((40, 12), (80, 24)): + text = self.text(state, cols, rows) + self.assertIn("You cannot write to this folder", text) + self.assertNotIn("sudo", text) + + # Root cause 4: every proven card named, the real marker said. + + def test_an_arkos_card_is_found_beside_an_amberelec_card(self): + """tui_audit_17 P2-3, code_audit_24 P3-6: an ArkOS card its bgmusic + or launchimages prove was named nowhere, and its route said it + could not tell it.""" + games = games_part(self.root / "media" / "GAMES") + for marker in ("bgmusic", "launchimages"): + with self.subTest(marker=marker): + ark = self.drive(f"ARK_{marker}", ("bios", "nes", marker)) + self.assertEqual(install.card_system(ark), ("retroarch", ark / "bios", "ArkOS")) + for name in ("ArkOS", "dArkOS"): + setup = install.card_setup(name, "retroarch") + self.assertEqual(install._card_is(setup, ark)[0], "own", name) + state = self.first_screen([games, ark]) + text = self.text(state, 80, 24) + self.assertIn(f"ArkOS SD card (ARK_{marker})", text) + self.assertIn("AmberELEC SD card (GAMES)", text) + + def test_the_emuelec_refusal_names_its_file(self): + """code_audit_24 P3-7: the refusal named bezels, which AmberELEC's + card holds too.""" + games = games_part(self.root / "media" / "GAMES") + (games / "bezels").mkdir() + setup = install.card_setup("EmuELEC", "emuelec") + choice = install._not_the_card(setup, games, games, "AmberELEC") + self.assertIn("bezels/default.cfg", choice.detail) + + # Root cause 5: the reads before the menu show. + + def test_the_reads_before_the_menu_show_a_count(self): + """code_audit_24 P3-4: a rerun read every file before the menu, one at + a time and with nothing on screen.""" + payload = b"R" * 16 + (self.here / "a.bin").write_bytes(payload) + listing = core_list(self.root / "read.json", + [self.entry("a.bin", payload, ["sony-playstation"])]) + text, _asked = self.line_run(_args(manifest=listing, dest=self.here, + declared_only=False), []) + self.assertIn("\r read 1/1", text) + self.assertLess(text.index("read 1/1"), text.index("every one in place")) + + # Root cause 6: every other item. + + def test_offline_the_plan_promises_no_replacement_it_cannot_make(self): + """code_audit_24 P3-5: offline, the plan said a wrong copy no folder + holds "is replaced".""" + state = checked_state() + with mock.patch.dict(os.environ, {install.OFFLINE_VARIABLE: "1"}): + text = self.text(state, 100, 30) + self.assertIn("1 wrong copy", text) + self.assertNotIn("wrong copy is replaced", text) + + def test_options_name_the_plans_bios_folder(self): + """tui_audit_17 P3-6: AmberELEC's Options read the games part, its + plan the bios folder below it.""" + state = checked_state() + state.manifest = {**MANIFEST, "files": [ + {**entry, "dest": f"bios/{entry['dest']}"} for entry in MANIFEST["files"]]} + state.dest = Path("/media/me/GAMES") + row = next(r for r in install.tui_rows(self.options(state)) if r.action == "folder") + self.assertEqual(row.label, "BIOS folder: /media/me/GAMES/bios") + + def test_finished_with_errors_says_a_rerun_retries(self): + """tui_audit_17 P3-7: the screen never said a rerun retries the files + that failed, and line mode named each failure twice.""" + state = checked_state() + install.tui_update(state, Key("enter")) + install.tui_receive(state, ("event", state.run_id, { + "event": "summary", "mode": "install", "installed": 3, "up_to_date": 0, + "pending": 1, "failed": [{"dest": "gba_bios.bin", "reason": "timed out"}], + "skipped": [], "left_out": [], "kept": [], "interrupted": False})) + install.tui_receive(state, ("ended", state.run_id, 1, [])) + title, lines = install.tui_outcome(state) + self.assertEqual(title, "Finished with errors") + self.assertIn("Run it again to retry only those.", lines) + # Line mode: the FAILED line of the progress names it, the end not again. + install.SAID_FAILED.clear() + install.SAID_FAILED.add("gba_bios.bin") + self.addCleanup(install.SAID_FAILED.clear) + out = io.StringIO() + with contextlib.redirect_stdout(out), contextlib.redirect_stderr(out), \ + contextlib.suppress(SystemExit): + install._report_outcome([Path("/b")], 3, 0, 1, 0, False, + failures=[("gba_bios.bin", "timed out")]) + self.assertNotIn("gba_bios.bin", out.getvalue()) + self.assertIn("Run the same command again to retry only those.", out.getvalue()) + + def test_below_40_columns_no_word_is_broken(self): + """tui_audit_17 P3-8: the reason line, Found and Install for were + left to the terminal, which broke "/media/moi/" and "ONION/BIOS".""" + with mock.patch.object(install, "terminal_size", return_value=(39, 11)), \ + mock.patch.object(install, "_is_terminal", return_value=True): + for text in (" Found Onion at /media/moi/ONION/BIOS (RetroArch files)", + "The window is 39x11: questions come line by line " + "(40x12 for the full screen)."): + lines = install.fold_line(text).split("\n") + self.assertTrue(all(len(line) <= 38 for line in lines), lines) + self.assertEqual(" ".join(" ".join(lines).split()), " ".join(text.split())) + + def test_the_narrowing_line_is_a_sentence(self): + """tui_audit_17 P3-4: the plan read "--region." on a line alone.""" + state = checked_state() + state.regions = ["japan"] + text = self.text(state, 100, 30) + self.assertIn("For your choice: regions ranked.", text) + self.assertNotIn(" --region.", text) + + def test_offline_choice_of_systems_is_never_about_0_files(self): + """tui_audit_17 P3-5: "About 0 files, 0 B, for 10 of 11 systems".""" + state = checked_state() + state.ticked = {"sony-playstation"} + with mock.patch.dict(os.environ, {install.OFFLINE_VARIABLE: "1"}): + text = self.text(state, 100, 30) + self.assertNotIn("About 0 files", text) + self.assertIn("need the internet", text) + + def test_a_phone_bar_after_a_tap_keeps_quit_and_one_wording(self): + """tui_audit_17 P3-11: at 40 columns on Android the armed bar dropped + Esc Quit and said "click", the row "tap again".""" + state = fresh_state() + state.os_type = "android" + state.mouse = True + state.stack = ["setup"] + install.tui_view(state, 40, 12) + state.tapped = install._tapped_row(state) + frame = install.tui_view(state, 40, 12) + text = "\n".join(map(str, frame)) + self.assertNotIn("click", text) + self.assertIn("tap again", text) + self.assertIn("Esc Quit", str(frame[-1])) + + def test_the_offline_screen_names_the_setups_list(self): + """tui_audit_17 P3-12: the offline screen said install/.json + for AmberELEC, chosen one screen before.""" + inbox: queue.Queue = queue.Queue() + install.LOCAL.reset() + with mock.patch.dict(os.environ, {install.OFFLINE_VARIABLE: "1"}): + install._tui_fetch("amberelec", inbox, io.StringIO()) + message = inbox.get_nowait() + self.assertIn("install/amberelec.json", " ".join(message[3])) + + # Root cause 7: the tests leave the host alone. + + def test_no_connection_leaves_the_loopback_nor_a_card_comes_in(self): + """code_audit_24 P3-13: 261 connections to GitHub left this module, + and tests failed with an AmberELEC card in the reader.""" + import socket # noqa: PLC0415 + + log = Path(os.environ["RETROBIOS_TEST_NETLOG"]) + before = log.read_text(encoding="utf-8") + self.addCleanup(log.write_text, before, encoding="utf-8") + with self.assertRaisesRegex(OSError, "makes no request"): + socket.create_connection(("192.0.2.1", 80), timeout=1) + child = subprocess.run( + [sys.executable, "-c", "import os, socket\n" + "print(os.path.ismount('/media/x'), os.path.ismount('/mnt/d'))\n" + "socket.create_connection(('192.0.2.1', 80), 1)"], + capture_output=True, text=True, check=False, timeout=60) + self.assertEqual(child.stdout.strip(), "False False") + self.assertIn("makes no request", child.stderr) + self.assertEqual(len(log.read_text(encoding="utf-8").splitlines()), + len(before.splitlines()) + 2) + self.assertFalse(os.path.ismount("/media/x")) + + if __name__ == "__main__": unittest.main()