mirror of
https://github.com/Abdess/retroarch_system.git
synced 2026-10-23 20:29:06 -05:00
fix: read a typed folder and quit with 130
A folder typed in quotes at the BIOS folder question was used with its quotes, and its missing parents were created without the question --dest asks. The quotes go, ~ and variables expand on every system, and a default folder that does not exist is named as such, not as found. q at a menu now leaves with 130 like Ctrl+C, and Ctrl+C before anything started no longer offers to carry on.
This commit is contained in:
1 parent
69179c95de
commit
84646d00a6
7 files changed
+165
-23
No files matched your search
@@ -392,7 +392,8 @@ class ExitStatusTable(unittest.TestCase):
|
||||
section = _section(_page("installer.md"), "Exit status")
|
||||
documented = {int(row[0].strip("`")) for row in _table_rows(section)}
|
||||
raised = {int(code) for code in re.findall(r"sys\.exit\((\d+)\)", source)}
|
||||
self.assertEqual(documented, raised | {2})
|
||||
# 0 is a run that returns, 2 the code argparse leaves with.
|
||||
self.assertEqual(documented, raised | {0, 2})
|
||||
self.assertIn("install.py: error:", section)
|
||||
for option in set(re.findall(r"(--[a-z][a-z-]+)", section)):
|
||||
self.assertIn(f'"{option}"', source, option)
|
||||
|
||||
+43
-3
@@ -1784,7 +1784,7 @@ class TestDetectedPlatformPrompt(unittest.TestCase):
|
||||
def test_q_quits_and_the_menu_says_so(self):
|
||||
result, out = self._answer("q")
|
||||
self.assertIsInstance(result, SystemExit)
|
||||
self.assertEqual(result.code, 0)
|
||||
self.assertEqual(result.code, 130)
|
||||
self.assertIn("q) quit", out)
|
||||
|
||||
def test_a_wrong_answer_names_the_choices(self):
|
||||
@@ -1820,11 +1820,51 @@ class TestManualPlatformPrompt(unittest.TestCase):
|
||||
chosen = install._prompt_manual_platform("linux")
|
||||
self.assertEqual(chosen, [("batocera", install.DEFAULT_DESTS["batocera"])])
|
||||
|
||||
def test_quit_exits_cleanly(self):
|
||||
def test_quit_stops_like_ctrl_c(self):
|
||||
"""`install.sh && retroarch` went on to start RetroArch with no BIOS
|
||||
after a q, which left with 0 where Ctrl+C leaves with 130."""
|
||||
with unittest.mock.patch("builtins.input", lambda _prompt="": "q"):
|
||||
with self.assertRaises(SystemExit) as raised:
|
||||
install._prompt_manual_platform("linux")
|
||||
self.assertEqual(raised.exception.code, 0)
|
||||
self.assertEqual(raised.exception.code, 130)
|
||||
|
||||
def test_quotes_around_a_typed_folder_are_dropped(self):
|
||||
"""Explorer's "Copy as path" quotes the folder: the files went into a
|
||||
folder named `"` under the current directory, and the run said Done."""
|
||||
root = Path(_tempdir(self))
|
||||
for typed in (f'"{root}/My Card/bios"', f"'{root}/My Card/bios'",
|
||||
f' "{root}/My Card/bios" '):
|
||||
answers = iter(["1", typed])
|
||||
with self.subTest(typed=typed), \
|
||||
unittest.mock.patch("builtins.input", lambda _prompt="": next(answers)), \
|
||||
contextlib.redirect_stdout(io.StringIO()):
|
||||
chosen = install._prompt_manual_platform("linux")
|
||||
self.assertEqual(chosen, [("retroarch", root / "My Card" / "bios")])
|
||||
|
||||
def test_home_and_variables_are_expanded_on_every_system(self):
|
||||
for os_type in ("linux", "windows", "darwin"):
|
||||
answers = iter(["1", '"~/$RB_TEST_DIR/bios"'])
|
||||
with self.subTest(os_type=os_type), \
|
||||
unittest.mock.patch.dict(os.environ, {"RB_TEST_DIR": "cards"}), \
|
||||
unittest.mock.patch("builtins.input", lambda _prompt="": next(answers)), \
|
||||
contextlib.redirect_stdout(io.StringIO()):
|
||||
chosen = install._prompt_manual_platform(os_type)
|
||||
self.assertEqual(chosen[0][1], Path.home() / "cards" / "bios")
|
||||
|
||||
def test_a_default_folder_not_there_is_not_found(self):
|
||||
"""With nothing installed, Enter printed "Found RetroArch at" a
|
||||
folder that did not exist."""
|
||||
root = Path(_tempdir(self))
|
||||
answers = iter(["1", ""])
|
||||
out = io.StringIO()
|
||||
with unittest.mock.patch.object(install, "_default_dest",
|
||||
return_value=root / "retroarch" / "system"), \
|
||||
unittest.mock.patch("builtins.input", lambda _prompt="": next(answers)), \
|
||||
contextlib.redirect_stdout(out):
|
||||
install._prompt_manual_platform("linux")
|
||||
self.assertIn("default BIOS folder", out.getvalue())
|
||||
self.assertIn("will be created", out.getvalue())
|
||||
self.assertNotIn("Found", out.getvalue())
|
||||
|
||||
def test_a_wrong_answer_says_what_to_type(self):
|
||||
answers = iter(["99", "1", ""])
|
||||
|
||||
@@ -544,6 +544,74 @@ class TheOneLinerNarrows(unittest.TestCase):
|
||||
self.assertIn("--system sony-playstation --region north-america", out)
|
||||
self.assertEqual(repo.installed(), ["pcsx/extra.bin", "scph5501.bin"])
|
||||
|
||||
@unittest.skipUnless(shutil.which("script"), "script(1) provides the terminal")
|
||||
def test_a_quoted_folder_typed_at_the_prompt(self):
|
||||
"""The quotes "Copy as path" adds were kept: the files went into a
|
||||
folder named `"` under the current directory, created without the
|
||||
question --dest asks, and the run said Done."""
|
||||
with FakeRepository() as repo:
|
||||
home = repo.root / "home"
|
||||
home.mkdir()
|
||||
# Read for the standalone emulator folders, of which there are none.
|
||||
(repo.root / "install" / "emudeck.json").write_text(json.dumps(
|
||||
{"manifest_version": 2, "platform": "emudeck", "files": []}))
|
||||
card = repo.root / "My Card" / "bios"
|
||||
env = dict(repo.env(), HOME=str(home), USERPROFILE=str(home),
|
||||
XDG_CONFIG_HOME=str(home), RETROBIOS_OS="linux")
|
||||
command = f"{shlex.quote(sys.executable)} {shlex.quote(str(REPO_ROOT / 'install.py'))}"
|
||||
for answer, code in (("n", 2), ("y", 0)):
|
||||
with self.subTest(answer=answer):
|
||||
proc = subprocess.run(
|
||||
["script", "-qec", command, "/dev/null"],
|
||||
input=f'1\n"{card}"\n{answer}\n\n', env=env, cwd=repo.root,
|
||||
capture_output=True, text=True, timeout=60, check=False,
|
||||
)
|
||||
self.assertEqual(proc.returncode, code, proc.stdout + proc.stderr)
|
||||
self.assertIn(f"Create 2 folders under {repo.root}?", proc.stdout)
|
||||
self.assertFalse((repo.root / '"').exists())
|
||||
self.assertEqual(len([p for p in card.rglob("*") if p.is_file()]), 5)
|
||||
|
||||
def test_q_at_every_menu_stops_on_130(self):
|
||||
"""`install.sh && retroarch` started RetroArch after a q, which left
|
||||
with 0 where Ctrl+C and Ctrl+D leave with 130."""
|
||||
files = [{"dest": "a.bin", "size": 1, "systems": ["nintendo-gba"]}]
|
||||
menus = (
|
||||
lambda: install._choose_platform("Platform:"),
|
||||
lambda: install._pick("Systems:", [("nintendo-gba", files)]),
|
||||
lambda: install._prompt_custom_selection("retroarch", files, []),
|
||||
)
|
||||
for menu in menus:
|
||||
with self.subTest(menu=menu), \
|
||||
mock.patch("builtins.input", lambda _prompt="": "q"), \
|
||||
mock.patch("sys.stdout", new_callable=lambda: open(os.devnull, "w")), \
|
||||
self.assertRaises(SystemExit) as stop:
|
||||
menu()
|
||||
self.assertEqual(stop.exception.code, 130)
|
||||
|
||||
@unittest.skipIf(os.name == "nt", "a pseudo-terminal is a POSIX one")
|
||||
def test_ctrl_d_at_the_first_question_has_nothing_to_carry_on(self):
|
||||
import pty # noqa: PLC0415
|
||||
|
||||
with FakeRepository() as repo:
|
||||
home = repo.root / "home"
|
||||
home.mkdir()
|
||||
(repo.root / "install" / "emudeck.json").write_text(json.dumps(
|
||||
{"manifest_version": 2, "platform": "emudeck", "files": []}))
|
||||
env = dict(repo.env(), HOME=str(home), USERPROFILE=str(home),
|
||||
XDG_CONFIG_HOME=str(home), RETROBIOS_OS="linux")
|
||||
leader, follower = pty.openpty()
|
||||
proc = subprocess.Popen(
|
||||
[sys.executable, str(REPO_ROOT / "install.py")], stdin=follower,
|
||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env, text=True,
|
||||
)
|
||||
os.close(follower)
|
||||
os.write(leader, b"\x04")
|
||||
out, err = proc.communicate(timeout=60)
|
||||
os.close(leader)
|
||||
self.assertEqual(proc.returncode, 130, out + err)
|
||||
self.assertIn("Stopped. Nothing was installed.", out)
|
||||
self.assertNotIn("carry on", out)
|
||||
|
||||
@unittest.skipUnless(shutil.which("script"), "script(1) provides the terminal")
|
||||
def test_enter_installs_everything_at_a_terminal(self):
|
||||
with FakeRepository() as repo:
|
||||
|
||||
Reference in new issue
Block a user