589cce18af
* chore: ignore local worktrees * fix: improve Windows local skill file reading * fix: address Windows path and decoding review feedback * fix: simplify shell decoding follow-up * fix: harden sandbox skill prompt metadata * fix: preserve safe sandbox skill summaries * fix: relax sandbox summary sanitization * fix: tighten path sanitization for skill prompts * fix: harden sandbox skill display metadata * fix: preserve Unicode skill paths in prompts * fix: quote Windows skill prompt paths * fix: simplify local shell output decoding * fix: localize Windows prompt path handling * fix: normalize Windows-style skill paths in prompts * fix: align prompt and shell decoding behavior
89 lines
2.6 KiB
Python
89 lines
2.6 KiB
Python
from __future__ import annotations
|
|
|
|
import asyncio
|
|
import subprocess
|
|
|
|
from astrbot.core.computer.booters import local as local_booter
|
|
from astrbot.core.computer.booters.local import LocalShellComponent
|
|
|
|
|
|
class _FakeCompletedProcess:
|
|
def __init__(self, stdout: bytes, stderr: bytes = b"", returncode: int = 0):
|
|
self.stdout = stdout
|
|
self.stderr = stderr
|
|
self.returncode = returncode
|
|
|
|
|
|
def test_local_shell_component_decodes_utf8_output(monkeypatch):
|
|
def fake_run(*args, **kwargs):
|
|
_ = args, kwargs
|
|
return _FakeCompletedProcess(stdout="技能内容".encode())
|
|
|
|
monkeypatch.setattr(subprocess, "run", fake_run)
|
|
|
|
result = asyncio.run(LocalShellComponent().exec("dummy"))
|
|
|
|
assert result["stdout"] == "技能内容"
|
|
assert result["stderr"] == ""
|
|
assert result["exit_code"] == 0
|
|
|
|
|
|
def test_local_shell_component_prefers_utf8_before_windows_locale(
|
|
monkeypatch,
|
|
):
|
|
def fake_run(*args, **kwargs):
|
|
_ = args, kwargs
|
|
return _FakeCompletedProcess(stdout="技能内容".encode())
|
|
|
|
monkeypatch.setattr(subprocess, "run", fake_run)
|
|
monkeypatch.setattr(local_booter.os, "name", "nt", raising=False)
|
|
monkeypatch.setattr(
|
|
local_booter.locale,
|
|
"getpreferredencoding",
|
|
lambda _do_setlocale=False: "cp936",
|
|
)
|
|
|
|
result = asyncio.run(LocalShellComponent().exec("dummy"))
|
|
|
|
assert result["stdout"] == "技能内容"
|
|
assert result["stderr"] == ""
|
|
assert result["exit_code"] == 0
|
|
|
|
|
|
def test_local_shell_component_falls_back_to_gbk_on_windows(monkeypatch):
|
|
def fake_run(*args, **kwargs):
|
|
_ = args, kwargs
|
|
return _FakeCompletedProcess(stdout="微博热搜".encode("gbk"))
|
|
|
|
monkeypatch.setattr(subprocess, "run", fake_run)
|
|
monkeypatch.setattr(local_booter.os, "name", "nt", raising=False)
|
|
monkeypatch.setattr(
|
|
local_booter.locale,
|
|
"getpreferredencoding",
|
|
lambda _do_setlocale=False: "cp1252",
|
|
)
|
|
|
|
result = asyncio.run(LocalShellComponent().exec("dummy"))
|
|
|
|
assert result["stdout"] == "微博热搜"
|
|
assert result["stderr"] == ""
|
|
assert result["exit_code"] == 0
|
|
|
|
|
|
def test_local_shell_component_falls_back_to_utf8_replace(monkeypatch):
|
|
def fake_run(*args, **kwargs):
|
|
_ = args, kwargs
|
|
return _FakeCompletedProcess(stdout=b"\xffabc")
|
|
|
|
monkeypatch.setattr(subprocess, "run", fake_run)
|
|
monkeypatch.setattr(local_booter.os, "name", "posix", raising=False)
|
|
monkeypatch.setattr(
|
|
local_booter.locale,
|
|
"getpreferredencoding",
|
|
lambda _do_setlocale=False: "utf-8",
|
|
)
|
|
|
|
result = asyncio.run(LocalShellComponent().exec("dummy"))
|
|
|
|
assert result["stdout"] == "\ufffdabc"
|