| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586 |
- #!/usr/bin/env python3
- """Build and run native XInput regression tests without the Arduino SDK."""
- import argparse
- import json
- import os
- from pathlib import Path
- import shlex
- import subprocess
- import tempfile
- ROOT = Path(__file__).resolve().parents[1]
- TESTS = ROOT / "tests" / "xinput"
- def run(command):
- print("+", shlex.join(str(arg) for arg in command), flush=True)
- subprocess.run(command, check=True)
- def fixture_header(destination):
- data = json.loads((TESTS / "fixtures.json").read_text())
- rows = []
- for console in data["consoles"]:
- fields = [json.dumps(console[key]) for key in
- ("console", "nonce", "identification", "init", "init_response")]
- for key in ("verify", "verify_response"):
- fields.append("{" + ",".join(map(json.dumps, console[key])) + "}")
- rows.append("{" + ",".join(fields) + "}")
- text = "static const Fixture fixtures[] = {" + ",\n".join(rows) + "};\n"
- for key in ("mac_wrap", "salt_wrap"):
- text += f"static const char {key}[] = {json.dumps(data[key])};\n"
- destination.write_text(text)
- def main():
- parser = argparse.ArgumentParser(description=__doc__)
- parser.add_argument("--asan", action="store_true",
- help="also enable AddressSanitizer (requires host runtime)")
- parser.add_argument("--check-fixtures", action="store_true",
- help="regenerate/compare independent fixtures; needs OpenSSL")
- args = parser.parse_args()
- if args.check_fixtures:
- actual = subprocess.check_output(
- [os.sys.executable, str(TESTS / "reference.py")], text=True)
- if json.loads(actual) != json.loads((TESTS / "fixtures.json").read_text()):
- raise SystemExit("Independent fixture regeneration differs")
- print("PASS independent OpenSSL/Python fixture regeneration", flush=True)
- cc = shlex.split(os.environ.get("CC", "cc"))
- cxx = shlex.split(os.environ.get("CXX", "c++"))
- flags = ["-O1", "-g", "-Wall", "-Wextra", "-Werror",
- "-fno-omit-frame-pointer", "-fsanitize=undefined",
- "-fsanitize-undefined-trap-on-error"]
- if args.asan:
- flags.append("-fsanitize=address")
- with tempfile.TemporaryDirectory(prefix="openpuck-xinput-") as name:
- build = Path(name)
- fixture_header(build / "fixtures.h")
- includes = ["-I" + str(TESTS), "-I" + str(ROOT / "OpenPuck"),
- "-I" + str(build)]
- sources = [ROOT / "OpenPuck" / "src" / "libxsm3" / name for name in
- ("excrypt_des.c", "excrypt_sha.c", "excrypt_parve.c",
- "usbdsec.c", "xsm3.c")]
- sources += [ROOT / "OpenPuck" / name for name in
- ("xinput_auth.cpp", "xinput_usb.cpp", "xinput_strings.cpp",
- "mode_xinput.cpp")]
- sources += [TESTS / "test.cpp", TESTS / "mode_test.cpp"]
- objects = []
- for source in sources:
- obj = build / (source.name + ".o")
- compiler = cc if source.suffix == ".c" else cxx
- standard = "-std=c11" if source.suffix == ".c" else "-std=c++17"
- run(compiler + [standard] + flags + includes +
- ["-c", str(source), "-o", str(obj)])
- objects.append(str(obj))
- executable = build / "test-xinput"
- run(cxx + flags + objects + ["-o", str(executable)])
- run([str(executable)])
- print("PASS native XInput tests (UBSan trap" +
- (" + ASan" if args.asan else "") + ")", flush=True)
- if __name__ == "__main__":
- main()
|