JVM & system properties¶
Horizon-QA reads Java system properties from the Minecraft server JVM. With Retrofuturagradle runServer, pass them through RFG's --mcJvmArgs option:
Passing -Dhorizonqa.mode=ci directly to Gradle sets the property on the Gradle daemon, where the server never sees it.
horizonqa.mode¶
| Property | Values | Default |
|---|---|---|
horizonqa.mode | off / interactive / ci | interactive |
Controls Horizon-QA runtime behavior.
interactive- Enables
/horizonqacommands, discovery, and client-side test visuals for local authoring. This is the default when the property is unset. ci- Automation preset: non-interactive server behavior, automatic selected-test execution, report writing, and server exit. Defaults to the void test world.
off- Loads the mod while leaving commands, discovery, runner behavior, and test visuals inert.
Modes are presets. Runtime behavior is resolved from the mode defaults plus the override properties below, so you do not need a new mode for every combination of world, autorun, shutdown, and placement policy.
Examples:
./gradlew runServer --mcJvmArgs="-Dhorizonqa.mode=interactive"
./gradlew runServer --mcJvmArgs="-Dhorizonqa.mode=ci"
./gradlew runServer --mcJvmArgs="-Dhorizonqa.mode=ci -Dhorizonqa.autoRun=false"
./gradlew runServer --mcJvmArgs="-Dhorizonqa.mode=ci -Dhorizonqa.autoRun=false -Dhorizonqa.world=normal -Dhorizonqa.gridOrigin=0,128,0"
./gradlew runServer --mcJvmArgs="-Dhorizonqa.mode=off"
Runtime behavior overrides¶
| Property | Values | Default |
|---|---|---|
horizonqa.world | void / normal | void in ci, otherwise normal |
horizonqa.autoRun | true / false | true in ci, otherwise false |
horizonqa.stopServer | true / false | true in ci when autorun is enabled, otherwise false |
horizonqa.gridOrigin | x,y,z | 0,64,0 |
horizonqa.worldvoidforces Horizon-QA's dedicated void world type for dimension 0.normalleaves the server's configured or existing world type alone.horizonqa.autoRun- Runs the selected tests automatically after server startup. When this is
false,/horizonqa run,/horizonqa runall, and/horizonqa runfailedstill use reported non-interactive batches incimode. If enabled in interactive mode, the startup batch uses the batch runner; interactive launch, relaunch, and clear commands are rejected until that batch finishes. horizonqa.stopServer- Requests process exit after an auto-run or reported batch finishes. When
false, the server remains up after the result is written. horizonqa.gridOrigin- Sets the absolute world coordinate where the test grid starts. Use
x,y,z;ymust be between0and255, and the full template height must still fit below the build limit. This affects both automatic and manual test placement.
Useful combinations:
# CI reports, normal terrain, exit when done
./gradlew runServer --mcJvmArgs="-Dhorizonqa.mode=ci -Dhorizonqa.world=normal"
# CI-style autorun, normal terrain, keep the server available afterward
./gradlew runServer --mcJvmArgs="-Dhorizonqa.mode=ci -Dhorizonqa.world=normal -Dhorizonqa.stopServer=false"
# Manual reported batches at Y=128 in the configured world
./gradlew runServer --mcJvmArgs="-Dhorizonqa.mode=ci -Dhorizonqa.autoRun=false -Dhorizonqa.world=normal -Dhorizonqa.gridOrigin=0,128,0"
# Manual reported batches with CI overrides
./gradlew runServer --mcJvmArgs="-Dhorizonqa.mode=ci -Dhorizonqa.autoRun=false -Dhorizonqa.reportDir=build/horizonqa"
horizonqa.tests¶
| Property | Values | Default |
|---|---|---|
horizonqa.tests | comma-separated selectors | all valid tests |
Limits automatic execution to selected tests. Manual reported batches use the command arguments instead and ignore this property.
Selector grammar:
selectors := selector ("," selector)*
selector := namespace | exact-test-id
namespace := token-without-colon
exact-test-id := namespace ":" class-and-method
Rules:
- unset or empty selects all valid tests,
namespaceselects every valid test whose id starts withnamespace:,namespace:Class.methodselects one exact test id,- tokens are trimmed around commas,
- empty tokens such as
a,,bare invalid, *is not supported,- exact test ids must contain exactly one
:.
Examples:
-Dhorizonqa.tests=horizonqaexamples
-Dhorizonqa.tests=horizonqaexamples:BasicTests.simplePass
-Dhorizonqa.tests=horizonqaexamples,othermod:SmokeTests.boots
For automatic execution, invalid selector syntax is a fatal CI configuration issue and exits 2. Selectors that are syntactically valid but match no valid tests are reported as CI infrastructure issues; any other matched tests still run.
horizonqa.allowNoTests¶
| Property | Values | Default |
|---|---|---|
horizonqa.allowNoTests | true / false | false |
Allows an automatic CI run with no selected valid tests to pass. This has no effect on manual reported batches, which select tests from the command arguments. For automatic execution, this only applies when the empty selection is otherwise clean; selector/configuration infrastructure issues still fail CI.
horizonqa.events¶
| Property | Values | Default |
|---|---|---|
horizonqa.events | on / off | on |
Controls the event recorder behind EventLog.
on- Records typed events. Each JUnit
<testcase>may include the event log under<system-out>. off- Disables recording. Emit sites use suppliers that are never invoked, so payload allocation work is skipped.
Disable event recording only for performance investigations; it is the primary CI failure diagnostic.
Report paths¶
Default outputs:
| Property | Meaning |
|---|---|
horizonqa.reportFile | Exact JUnit XML output path |
horizonqa.reportDir | Directory containing TEST-horizonqa.xml |
horizonqa.statusFile | Exact status JSON output path |
horizonqa.reportFile wins over horizonqa.reportDir for the JUnit XML path. When horizonqa.reportDir is set and horizonqa.statusFile is not set, status JSON defaults to horizonqa-result.json in that same directory. Relative paths resolve from the server process working directory.
Recommended CI and manual-report forms:
./gradlew runServer --mcJvmArgs="-Dhorizonqa.mode=ci -Dhorizonqa.reportDir=build/horizonqa"
./gradlew runServer --mcJvmArgs="-Dhorizonqa.mode=ci -Dhorizonqa.autoRun=false -Dhorizonqa.reportDir=build/horizonqa"
Status JSON¶
The status JSON is a concise machine-readable summary. Schema version 1 contains:
| Top-level field | Meaning |
|---|---|
schemaVersion | Integer schema version, currently 1 |
status | passed, failed, or error |
exitCode | Process exit code Horizon-QA requests |
configuration | Effective property values and defaults |
counts | Aggregate selected, passed, failed, timeout, optional, issue, and JUnit counts |
reports | JUnit and status report paths |
issues | Infrastructure/configuration/selection/reporting issues |
tests | Per-test status and optional failure details |
Issue entries contain id, kind, source, name, message, fatalInCi, and optional details / stackTrace. Test entries contain id, classname, name, status, required, ticks, timeSeconds, optional blockedByIssueId, and optional failure.
Exit codes¶
| Code | Status | Meaning |
|---|---|---|
0 | passed | No required test failures and no infrastructure errors |
1 | failed | At least one required test failed or timed out |
2 | error | Infrastructure, configuration, discovery-selection, template, cleanup, report-path, reporting, or incomplete-run error |
Optional failures do not change the process exit code by themselves. They are counted in status JSON and represented as skipped in JUnit XML.
Use lowercase property values
CI property parsing is strict. Use ci, interactive, void, normal, true, false, on, and off exactly as documented.