105 lines
4.1 KiB
Python
Executable File
105 lines
4.1 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""Run required speech regressions, or check each commit tip in a Git push."""
|
|
|
|
import json
|
|
import os
|
|
from pathlib import Path
|
|
import subprocess
|
|
import sys
|
|
import tempfile
|
|
|
|
from native_test_session import run_private_session
|
|
|
|
|
|
requiredTests = {
|
|
"TestSpeechWorkerRadioSelectionDoesNotCancelLabel",
|
|
"TestPrivateWineReviewUpdatesPreserveQueuedTitleSpeech",
|
|
"TestPrivateWineTitleSurvivesReviewFocusBurst",
|
|
"TestAutomaticTitleSurvivesMovementRepeatsBeforeAndAfterDelivery",
|
|
"TestAutomaticTitleStillStopsForExplicitInput",
|
|
"TestTitleProtectionDoesNotChangeOrdinaryReading",
|
|
"TestRepeatTrackerRecognizesNativeSequences",
|
|
"TestTypingEchoModeCombinations",
|
|
"TestTypingEchoVoiceCombinations",
|
|
"TestTypingEchoLineBreakBeforeExistingText",
|
|
"TestTypingEchoLineBreakKeepsPriorCaretContext",
|
|
"TestEchoSpeakerSwitchesBothVoicesTransactionally",
|
|
"TestSpeechWorkerKeyEchoCompletesBeforeCaretSpeech",
|
|
"TestSpeechWorkerKeyEchoWaitStillAllowsInputInterruption",
|
|
}
|
|
|
|
|
|
def run_checks(sourceRoot: Path) -> None:
|
|
testEnv = os.environ.copy()
|
|
# Git exports repository paths to hooks. Tests run against the snapshot.
|
|
for name in tuple(testEnv):
|
|
if name.startswith("GIT_"):
|
|
del testEnv[name]
|
|
testEnv.pop("DISPLAY", None)
|
|
testEnv.pop("WAYLAND_DISPLAY", None)
|
|
testEnv["CTHULHU_WINE_TITLE_DBUS"] = "1"
|
|
command = [
|
|
"dbus-run-session", "--", "go", "test", "-json", "-race", "-count=1",
|
|
"-timeout=60s", "-run", "^Test.*(Title|Repeat|Interrupt|Echo)|^Test(SpeechWorker|Cancel|WineReview)",
|
|
"./internal/app", "./internal/input", "./internal/presentation", "./internal/speech", "./internal/wine",
|
|
]
|
|
print("Checking speech queues, key echo, Wine metadata and key interruption...", flush=True)
|
|
result = run_private_session(command, cwd=sourceRoot, env=testEnv, text=True,
|
|
stdout=subprocess.PIPE, stderr=subprocess.STDOUT, check=False)
|
|
passedTests = set()
|
|
diagnostics = []
|
|
for line in result.stdout.splitlines():
|
|
try:
|
|
event = json.loads(line)
|
|
except ValueError:
|
|
diagnostics.append(line + "\n")
|
|
continue
|
|
if "Output" in event:
|
|
diagnostics.append(event["Output"])
|
|
if event.get("Action") == "pass" and "Test" in event:
|
|
passedTests.add(event["Test"])
|
|
missingTests = requiredTests - passedTests
|
|
if result.returncode or missingTests:
|
|
print("".join(diagnostics), end="", file=sys.stderr)
|
|
if missingTests:
|
|
print("Required tests did not pass (missing or skipped): " +
|
|
", ".join(sorted(missingTests)), file=sys.stderr)
|
|
raise RuntimeError("speech regression check failed")
|
|
print("Speech regression checks passed.", flush=True)
|
|
|
|
|
|
def check_push(repoRoot: Path) -> None:
|
|
checkedCommits = set()
|
|
for line in sys.stdin:
|
|
localRef, localCommit, remoteRef, remoteCommit = line.split()
|
|
if set(localCommit) == {"0"} or localCommit in checkedCommits:
|
|
continue
|
|
checkedCommits.add(localCommit)
|
|
print(f"Checking {localRef} ({localCommit[:12]}) before push...", flush=True)
|
|
with tempfile.TemporaryDirectory(prefix="cthulhu-push-") as directory:
|
|
sourceRoot = Path(directory)
|
|
with tempfile.TemporaryFile() as archive:
|
|
subprocess.run(["git", "archive", "--format=tar", localCommit],
|
|
cwd=repoRoot, stdout=archive, check=True)
|
|
archive.seek(0)
|
|
subprocess.run(["tar", "-xf", "-", "-C", str(sourceRoot)],
|
|
stdin=archive, check=True)
|
|
run_checks(sourceRoot)
|
|
|
|
|
|
def main() -> int:
|
|
repoRoot = Path(__file__).resolve().parents[1]
|
|
try:
|
|
if len(sys.argv) > 1 and sys.argv[1] == "--pre-push":
|
|
check_push(repoRoot)
|
|
else:
|
|
run_checks(repoRoot)
|
|
except (OSError, ValueError, RuntimeError, subprocess.CalledProcessError) as error:
|
|
print(f"Speech check blocked: {error}", file=sys.stderr)
|
|
return 1
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|