feat: add csharp win helper probe
This commit is contained in:
130
tests/test_win_helper.py
Normal file
130
tests/test_win_helper.py
Normal file
@@ -0,0 +1,130 @@
|
||||
import json
|
||||
import subprocess
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
REPO = Path(__file__).resolve().parents[1]
|
||||
BUILD_SCRIPT = REPO / "scripts" / "build-win-helper.ps1"
|
||||
HELPER_EXE = REPO / "runs" / "win-helper" / "ISphereWinHelper.exe"
|
||||
|
||||
|
||||
def build_helper():
|
||||
result = subprocess.run(
|
||||
[
|
||||
"powershell",
|
||||
"-NoProfile",
|
||||
"-ExecutionPolicy",
|
||||
"Bypass",
|
||||
"-File",
|
||||
str(BUILD_SCRIPT),
|
||||
],
|
||||
cwd=REPO,
|
||||
text=True,
|
||||
encoding="utf-8",
|
||||
errors="replace",
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE,
|
||||
timeout=60,
|
||||
)
|
||||
if result.returncode != 0:
|
||||
raise AssertionError(result.stdout + result.stderr)
|
||||
|
||||
|
||||
def invoke_helper(payload):
|
||||
if isinstance(payload, str):
|
||||
stdin = payload
|
||||
else:
|
||||
stdin = json.dumps(payload, ensure_ascii=False)
|
||||
result = subprocess.run(
|
||||
[str(HELPER_EXE), "--json"],
|
||||
cwd=REPO,
|
||||
input=stdin,
|
||||
text=True,
|
||||
encoding="utf-8",
|
||||
errors="replace",
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE,
|
||||
timeout=30,
|
||||
)
|
||||
try:
|
||||
decoded = json.loads(result.stdout)
|
||||
except json.JSONDecodeError as exc:
|
||||
raise AssertionError(f"stdout was not JSON: {result.stdout!r}; stderr={result.stderr!r}") from exc
|
||||
return result, decoded
|
||||
|
||||
|
||||
class WinHelperBuildTests(unittest.TestCase):
|
||||
def test_build_script_creates_helper_exe(self):
|
||||
if HELPER_EXE.exists():
|
||||
HELPER_EXE.unlink()
|
||||
|
||||
build_helper()
|
||||
|
||||
self.assertTrue(HELPER_EXE.exists(), f"helper exe missing: {HELPER_EXE}")
|
||||
|
||||
|
||||
class WinHelperProtocolTests(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
build_helper()
|
||||
|
||||
def request(self, op, args=None):
|
||||
result, decoded = invoke_helper(
|
||||
{
|
||||
"protocol": "isphere.helper.v1",
|
||||
"request_id": f"test-{op}",
|
||||
"op": op,
|
||||
"timeout_ms": 5000,
|
||||
"args": args or {},
|
||||
}
|
||||
)
|
||||
self.assertEqual(result.returncode, 0, result.stderr)
|
||||
return decoded
|
||||
|
||||
def test_version_returns_contract_metadata(self):
|
||||
decoded = self.request("version")
|
||||
|
||||
self.assertTrue(decoded["ok"])
|
||||
self.assertEqual(decoded["protocol"], "isphere.helper.v1")
|
||||
self.assertEqual(decoded["request_id"], "test-version")
|
||||
self.assertEqual(decoded["op"], "version")
|
||||
self.assertEqual(decoded["data"]["helper_name"], "ISphereWinHelper")
|
||||
self.assertEqual(decoded["data"]["protocol"], "isphere.helper.v1")
|
||||
|
||||
def test_self_check_reports_desktop_and_uia_status(self):
|
||||
decoded = self.request("self_check")
|
||||
|
||||
self.assertTrue(decoded["ok"])
|
||||
self.assertIn("desktop_access", decoded["data"])
|
||||
self.assertIn("uia_available", decoded["data"])
|
||||
|
||||
def test_scan_windows_returns_json_window_list(self):
|
||||
decoded = self.request("scan_windows", {"include_all_visible": True})
|
||||
|
||||
self.assertTrue(decoded["ok"])
|
||||
self.assertIsInstance(decoded["data"]["windows"], list)
|
||||
|
||||
def test_unsupported_op_returns_structured_error(self):
|
||||
decoded = self.request("does_not_exist")
|
||||
|
||||
self.assertFalse(decoded["ok"])
|
||||
self.assertEqual(decoded["error"]["code"], "UNSUPPORTED_OP")
|
||||
|
||||
def test_invalid_json_returns_structured_error(self):
|
||||
result, decoded = invoke_helper("{not json")
|
||||
|
||||
self.assertEqual(result.returncode, 0, result.stderr)
|
||||
self.assertFalse(decoded["ok"])
|
||||
self.assertEqual(decoded["protocol"], "isphere.helper.v1")
|
||||
self.assertEqual(decoded["error"]["code"], "INVALID_REQUEST")
|
||||
|
||||
def test_dump_uia_with_missing_window_returns_structured_error(self):
|
||||
decoded = self.request("dump_uia", {"hwnd": "0x0"})
|
||||
|
||||
self.assertFalse(decoded["ok"])
|
||||
self.assertIn(decoded["error"]["code"], {"WINDOW_NOT_FOUND", "UIA_DUMP_FAILED"})
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user