Document Designer workflows and qualify the real library example
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Exercise a clean copy of NeitzelLib's actual fx-example in the packaged standalone host."""
|
||||
import argparse
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
import shutil
|
||||
import subprocess
|
||||
import tempfile
|
||||
import time
|
||||
import zipfile
|
||||
|
||||
from native_crashes import NativeCrashGuard
|
||||
|
||||
ROOT = Path(__file__).resolve().parent.parent
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument("--library", type=Path, required=True)
|
||||
parser.add_argument("--app", type=Path, required=True)
|
||||
parser.add_argument("--java-home", type=Path, required=True,
|
||||
help="JDK 25 for the external test agent compiler")
|
||||
parser.add_argument("--target-java-home", type=Path, required=True)
|
||||
args = parser.parse_args()
|
||||
output = Path(tempfile.mkdtemp(prefix="designer-library-example-")).resolve()
|
||||
print("Evidence: " + str(output), flush=True)
|
||||
library = output / "NeitzelLib"
|
||||
shutil.copytree(args.library, library,
|
||||
ignore=shutil.ignore_patterns(".git", "target", ".idea", ".neitzel-fx-designer"))
|
||||
app = output / "NeitzelFXDesigner.app"
|
||||
shutil.copytree(args.app, app, symlinks=True)
|
||||
local = library / ".neitzel-fx-designer"
|
||||
local.mkdir()
|
||||
settings = local / "runtimes.json"
|
||||
settings.write_text(json.dumps({"schemaVersion": "1.0", "runtimes": {"java21": {
|
||||
"build": str(args.target_java_home.resolve()),
|
||||
"target": str(args.target_java_home.resolve())}}}))
|
||||
classes = output / "agent-classes"
|
||||
classes.mkdir()
|
||||
jars = list((app / "Contents/app").glob("*.jar"))
|
||||
subprocess.run([args.java_home / "bin/javac", "-cp", os.pathsep.join(map(str, jars)),
|
||||
"-d", classes, ROOT / "integration-tests/fx-example/FxExampleProbe.java"], check=True)
|
||||
agent = output / "probe.jar"
|
||||
with zipfile.ZipFile(agent, "w") as jar:
|
||||
jar.writestr("META-INF/MANIFEST.MF",
|
||||
"Manifest-Version: 1.0\nPremain-Class: qualification.FxExampleProbe\n\n")
|
||||
for file in classes.rglob("*.class"):
|
||||
jar.write(file, str(file.relative_to(classes)))
|
||||
config = app / "Contents/app/NeitzelFXDesigner.cfg"
|
||||
options = [f"-javaagent:{agent}", f"-Dexample.output={output}", f"-Dexample.library={library}"]
|
||||
config.write_text(config.read_text() + "\n" + "".join("java-options=" + opt + "\n" for opt in options))
|
||||
env = dict(os.environ)
|
||||
for key in ("JAVA_TOOL_OPTIONS", "JDK_JAVA_OPTIONS", "_JAVA_OPTIONS"):
|
||||
env.pop(key, None)
|
||||
command = [app / "Contents/MacOS/NeitzelFXDesigner", "--configuration",
|
||||
library / "neitzel-fx-designer.json", "--settings", settings,
|
||||
"--maven", ROOT / "mvnw",
|
||||
library / "fx-example/src/main/resources/de/neitzel/fx/example/view/Desk.fxml"]
|
||||
crashes = NativeCrashGuard(ROOT)
|
||||
with (output / "launcher.log").open("w") as log:
|
||||
process = subprocess.Popen(list(map(str, command)), env=env, cwd=output,
|
||||
stdout=log, stderr=subprocess.STDOUT)
|
||||
try:
|
||||
code = process.wait(timeout=420)
|
||||
except subprocess.TimeoutExpired:
|
||||
process.terminate()
|
||||
try:
|
||||
process.wait(timeout=15)
|
||||
except subprocess.TimeoutExpired:
|
||||
process.kill()
|
||||
process.wait(timeout=10)
|
||||
raise
|
||||
if code != 0 or not (output / "SUCCESS.txt").exists():
|
||||
raise RuntimeError((output / "launcher.log").read_text()[-10000:])
|
||||
for pid in (output / "workers.txt").read_text().splitlines():
|
||||
until = time.monotonic() + 10
|
||||
while time.monotonic() < until:
|
||||
try:
|
||||
os.kill(int(pid), 0)
|
||||
except ProcessLookupError:
|
||||
break
|
||||
time.sleep(.1)
|
||||
else:
|
||||
raise AssertionError("Preview worker survived host: " + pid)
|
||||
crashes.check()
|
||||
print((output / "SUCCESS.txt").read_text(), end="")
|
||||
@@ -0,0 +1,57 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Create ignored local launch settings for NeitzelLib's checked-in fx-example context."""
|
||||
import argparse
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
ROOT = Path(__file__).resolve().parent.parent
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument("--library", type=Path, required=True)
|
||||
parser.add_argument("--target-java-home", type=Path, required=True)
|
||||
parser.add_argument("--maven", type=Path, default=ROOT / "mvnw")
|
||||
args = parser.parse_args()
|
||||
library = args.library.resolve()
|
||||
java = args.target_java_home.resolve()
|
||||
maven = args.maven.resolve()
|
||||
if not (library / "neitzel-fx-designer.json").is_file():
|
||||
parser.error("Library checkout has no designer configuration")
|
||||
if not all((java / "bin" / name).is_file() for name in ("java", "javac")):
|
||||
parser.error("Supply a full application JDK installation")
|
||||
if not maven.is_file() or not os.access(maven, os.X_OK):
|
||||
parser.error("Supply an executable Maven wrapper or Maven installation")
|
||||
tools = [ROOT / f"designer-{name}/target/designer-{name}-0.1.0-SNAPSHOT.jar"
|
||||
for name in ("target-tools", "contracts", "preview-api")]
|
||||
if not all(file.is_file() for file in tools):
|
||||
parser.error("Build/install the Designer Maven modules first")
|
||||
local = library / ".neitzel-fx-designer"
|
||||
settings = local / "runtimes.json"
|
||||
launch = local / "host.properties"
|
||||
if settings.exists() or launch.exists():
|
||||
parser.error("Local settings already exist; edit them explicitly instead of overwriting them")
|
||||
local.mkdir(exist_ok=True)
|
||||
with settings.open("x") as file:
|
||||
json.dump({"schemaVersion": "1.0", "runtimes": {
|
||||
"java21": {"build": str(java), "target": str(java)}}}, file, indent=2)
|
||||
|
||||
|
||||
def prop(value):
|
||||
"""Escape Java properties values, including non-ASCII local paths."""
|
||||
value = str(value).replace("\\", "\\\\").replace("\n", "\\n").replace("\r", "\\r")
|
||||
escaped = []
|
||||
for character in value:
|
||||
if ord(character) < 128:
|
||||
escaped.append(character)
|
||||
else:
|
||||
encoded = character.encode("utf-16-be")
|
||||
escaped.extend("\\u%04x" % int.from_bytes(encoded[i:i + 2], "big")
|
||||
for i in range(0, len(encoded), 2))
|
||||
return "".join(escaped)
|
||||
|
||||
|
||||
with launch.open("x", encoding="ascii") as file:
|
||||
file.write("configuration=../neitzel-fx-designer.json\ncontext=person-desk\n"
|
||||
"settings=runtimes.json\nmaven=" + prop(maven) + "\ntools="
|
||||
+ os.pathsep.join(map(prop, tools)) + "\n")
|
||||
print(settings)
|
||||
print(launch)
|
||||
Reference in New Issue
Block a user