Early Platform.exit detached JavaFX while queued macOS activation callbacks still called Java. Close the owned example before terminating its JVM, make shutdown idempotent, and reject late preview work. Add real startup-cancellation regressions and native crash-report checks.
92 lines
5.0 KiB
Python
92 lines
5.0 KiB
Python
#!/usr/bin/env python3
|
|
"""Real snapshot/socket/overlay checks against both host document adapters."""
|
|
from pathlib import Path
|
|
import argparse
|
|
import os
|
|
import shutil
|
|
import subprocess
|
|
import tempfile
|
|
import json
|
|
import time
|
|
from native_crashes import NativeCrashGuard
|
|
|
|
ROOT = Path(__file__).resolve().parent.parent
|
|
parser = argparse.ArgumentParser(description=__doc__)
|
|
parser.add_argument("--target-java-home", required=True)
|
|
parser.add_argument("--idea-home", required=True)
|
|
args = parser.parse_args()
|
|
logs = ROOT / "target/connected-workflow"
|
|
logs.mkdir(parents=True, exist_ok=True)
|
|
crashes = NativeCrashGuard(ROOT)
|
|
classpath = os.pathsep.join([str(ROOT / "designer-standalone/target/test-classes"),
|
|
str(ROOT / "designer-standalone/target/classes"),
|
|
(ROOT / "designer-standalone/target/smoke-classpath.txt").read_text().strip()])
|
|
|
|
|
|
def run(name, command):
|
|
with (logs / (name + ".log")).open("w") as output:
|
|
result = subprocess.run(list(map(str, command)), cwd=ROOT, stdout=output,
|
|
stderr=subprocess.STDOUT, timeout=420)
|
|
if result.returncode:
|
|
raise RuntimeError((logs / (name + ".log")).read_text()[-16000:])
|
|
print("PASS " + name, flush=True)
|
|
|
|
|
|
with tempfile.TemporaryDirectory(prefix="designer-connected-") as temporary:
|
|
for host in ("standalone", "intellij"):
|
|
base = Path(temporary) / host
|
|
for mode in ("classpath", "modulepath"):
|
|
fixture = base / mode
|
|
shutil.copytree(ROOT / "integration-fixtures/preview" / mode, fixture,
|
|
ignore=shutil.ignore_patterns("target"))
|
|
if host == "standalone":
|
|
run(host + "-" + mode, [Path(os.environ["JAVA_HOME"]) / "bin/java", "-cp", classpath,
|
|
"de.neitzel.fxdesigner.standalone.WorkflowSmoke", ROOT, args.target_java_home,
|
|
fixture, mode])
|
|
run("worker-lifecycle-" + mode, [Path(os.environ["JAVA_HOME"]) / "bin/java", "-cp", classpath,
|
|
"de.neitzel.fxdesigner.standalone.WorkerLifecycleSmoke", ROOT, fixture])
|
|
crashes.check()
|
|
local = fixture / ".neitzel-fx-designer"
|
|
(local / "runtimes.json").write_text(json.dumps({"schemaVersion":"1.0","runtimes":{"java21":{"build":args.target_java_home,"target":args.target_java_home}}}))
|
|
tools = [ROOT / ("designer-" + name) / "target" / ("designer-" + name + "-0.1.0-SNAPSHOT.jar") for name in ("target-tools","contracts","preview-api")]
|
|
(local / "host.properties").write_text("configuration=../neitzel-fx-designer.json\ncontext=fixture\nsettings=runtimes.json\nmaven="+str(ROOT/"mvnw")+"\ntools="+os.pathsep.join(map(str,tools))+"\n")
|
|
run("native-kit-" + mode, [Path(os.environ["JAVA_HOME"]) / "bin/java", "--enable-native-access=ALL-UNNAMED", "-cp", classpath,
|
|
"de.neitzel.fxdesigner.standalone.KitWorkflowSmoke", local / "host.properties",
|
|
fixture / "app/src/main/resources/fixture/components/Person.fxml", logs / ("kit-" + mode + ".png")])
|
|
if mode == "classpath":
|
|
pidfile = base / "worker.pid"
|
|
owner = subprocess.Popen([str(Path(os.environ["JAVA_HOME"]) / "bin/java"),
|
|
"-cp", classpath, "de.neitzel.fxdesigner.standalone.WorkerOwnerProbe",
|
|
str(ROOT), str(fixture), str(pidfile)], cwd=ROOT)
|
|
try:
|
|
until = time.monotonic() + 20
|
|
while not pidfile.exists() and time.monotonic() < until:
|
|
if owner.poll() is not None:
|
|
raise RuntimeError("Owner probe exited before startup")
|
|
time.sleep(.05)
|
|
worker_pid = int(pidfile.read_text())
|
|
owner.kill()
|
|
owner.wait(timeout=5)
|
|
until = time.monotonic() + 10
|
|
while time.monotonic() < until:
|
|
try:
|
|
os.kill(worker_pid, 0)
|
|
except ProcessLookupError:
|
|
break
|
|
time.sleep(.05)
|
|
else:
|
|
raise RuntimeError("Worker survived abrupt owner death")
|
|
print("PASS abrupt owner death", flush=True)
|
|
finally:
|
|
if owner.poll() is None:
|
|
owner.kill()
|
|
owner.wait(timeout=5)
|
|
|
|
if host == "intellij":
|
|
run(host, [ROOT / "designer-intellij/gradlew", "-p", "designer-intellij", "--no-daemon",
|
|
"-PideaHome=" + args.idea_home, "-Ddesigner.workflow.fixtures=" + str(base),
|
|
"-Ddesigner.repository=" + str(ROOT), "-Ddesigner.target.java=" + args.target_java_home,
|
|
"test"])
|
|
|
|
crashes.check()
|