Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions benchmark/report.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from .contract_test import load_cases
from .definition import PROFILE
from .healthcheck import CONTAINER_HEALTHCHECK, validate_policy
from .java_versions import JAVA_VERSION
from .results import (
number,
object_fields,
Expand Down Expand Up @@ -183,9 +184,15 @@ def validate_report(report: dict, *, expected_context: dict | None = None) -> No
keys = registry.implementation(implementation)["version_fields"]
values = versions[implementation]
require(type(values) is dict and set(keys) <= set(values), "missing stack versions")
for value in values.values():
for key, value in values.items():
# Only the Java runtime uses an exact build; dependencies stay triplets.
pattern = (
JAVA_VERSION
if implementation == "java-spring-boot" and key == "java"
else r"[0-9]+\.[0-9]+\.[0-9]+"
)
require(
type(value) is str and re.fullmatch(r"\d+\.\d+\.\d+", value) is not None,
type(value) is str and re.fullmatch(pattern, value) is not None,
"invalid stack version",
)
backends = report["implementations"]
Expand Down
14 changes: 14 additions & 0 deletions docs/IMPLEMENTATIONS.md
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,20 @@ implementations, while official measurement selects the active cohort. Local or
partial data cannot become a complete official result by setting a flag or
supplying a smaller list. No partial benchmark publication mode is introduced.

Stack version values are preserved as strings, never normalized or truncated.
The `java-spring-boot` runtime field `java` follows the extractor's exact-build
contract: three or four dot-separated ASCII digit components, then `+` and an
ASCII digit build number (for example, `25.0.4.1+1` or `25.0.4+1`). The build is
mandatory. This intentionally narrow release format excludes early-access/vendor
suffixes, whitespace and control characters; it is not a general Java version
parser. Existing numeric spelling, including leading zeroes, is preserved.
All other required and additional version fields keep the three-component ASCII
numeric contract, including Java dependencies. A `java` key on a different stack
does not enable the Java exception. Both validators exercise the same valid and
invalid cases in `tests/fixtures/stack-versions.json`. Java-inclusive validation
and rendering tests use only a synthetic trusted cohort, which production rejects;
this support neither admits Java to an official cohort nor publishes a result.

JavaScript performs presentation validation, not publication authorization. It
renders the report's known cohort rather than the current active list. Missing or
invalid results remain empty/unavailable, never zero. The result JSON link stays
Expand Down
13 changes: 11 additions & 2 deletions site/app.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,15 @@ function validateMeasuredRun(run, expectedRun) {
return { run: run.run, rps, mean, memory: memoryBytes / 1048576 };
}

function validStackVersion(id, key, value) {
// Match java_versions.py's exact runtime build, never arbitrary dependency suffixes.
const pattern = id === "java-spring-boot" && key === "java"
? /^[0-9]+\.[0-9]+\.[0-9]+(?:\.[0-9]+)?\+[0-9]+$/
: /^[0-9]+\.[0-9]+\.[0-9]+$/;
// JavaScript's $ also matches before a final newline; require the whole string.
return typeof value === "string" && pattern.exec(value)?.[0] === value;
}

function validateReport(report) {
object(report, "report");
const cohort = reportCohort(report);
Expand Down Expand Up @@ -148,9 +157,9 @@ function validateReport(report) {
assert(id === members[backendIndex], "implementation identity/order mismatch");
const versionSet = object(versions[id], `versions for ${id}`);
for (const key of STACKS[id].version_fields) {
assert(typeof versionSet[key] === "string" && /^\d+\.\d+\.\d+$/.test(versionSet[key]), `invalid ${id} ${key} version`);
assert(Object.hasOwn(versionSet, key) && validStackVersion(id, key, versionSet[key]), `invalid ${id} ${key} version`);
}
assert(Object.values(versionSet).every((value) => typeof value === "string" && /^\d+\.\d+\.\d+$/.test(value)), "invalid stack version");
assert(Object.entries(versionSet).every(([key, value]) => validStackVersion(id, key, value)), "invalid stack version");
assert(Array.isArray(backend.endpoints) && backend.endpoints.length === ENDPOINTS.length, "three endpoints required");
backend.endpoints.forEach((entry, endpointIndex) => {
object(entry, "endpoint result");
Expand Down
Loading
Loading