implements PR-05.7

This commit is contained in:
bQUARKz 2026-03-09 07:15:17 +00:00
parent 0cc836246f
commit 6dacedb5ed
Signed by: bquarkz
SSH Key Fingerprint: SHA256:Z7dgqoglWwoK6j6u4QC87OveEq74WOhFN+gitsxtkf8
3 changed files with 82 additions and 1 deletions

View File

@ -6,5 +6,6 @@ enum CompatibilityError {
HOSTCALL_INDEX_OUT_OF_BOUNDS, HOSTCALL_INDEX_OUT_OF_BOUNDS,
UNUSED_SYSC_DECL, UNUSED_SYSC_DECL,
MISSING_CAPABILITY, MISSING_CAPABILITY,
RUNTIME_BACKED_REQUIRED,
RUNTIME_REJECTED, RUNTIME_REJECTED,
} }

View File

@ -11,27 +11,39 @@ import java.util.List;
final class RuntimeBackedCompatibilityAdapter implements RuntimeCompatibilityAdapter { final class RuntimeBackedCompatibilityAdapter implements RuntimeCompatibilityAdapter {
private static final String DEFAULT_RUNTIME_LINE = "runtime-line-unknown"; private static final String DEFAULT_RUNTIME_LINE = "runtime-line-unknown";
private static final String FALLBACK_MODE = "local-fallback"; private static final String FALLBACK_MODE = "local-fallback";
private static final String STRICT_FLAG_ENV = "PROMETEU_GATE_I_STRICT";
private final RuntimeCompatibilityAdapter fallback; private final RuntimeCompatibilityAdapter fallback;
private final Path runtimeRoot; private final Path runtimeRoot;
private final String runtimeLine; private final String runtimeLine;
private final String runtimeCheckCommand; private final String runtimeCheckCommand;
private final boolean strictRuntimeBacked;
RuntimeBackedCompatibilityAdapter(final RuntimeCompatibilityAdapter fallback) { RuntimeBackedCompatibilityAdapter(final RuntimeCompatibilityAdapter fallback) {
this( this(
fallback == null ? new LocalRuntimeCompatibilityAdapter() : fallback, fallback == null ? new LocalRuntimeCompatibilityAdapter() : fallback,
Path.of("../runtime"), Path.of("../runtime"),
System.getenv("PROMETEU_RUNTIME_CHECK_CMD")); System.getenv("PROMETEU_RUNTIME_CHECK_CMD"),
strictRuntimeBackedFromEnvironment());
} }
RuntimeBackedCompatibilityAdapter( RuntimeBackedCompatibilityAdapter(
final RuntimeCompatibilityAdapter fallback, final RuntimeCompatibilityAdapter fallback,
final Path runtimeRoot, final Path runtimeRoot,
final String runtimeCheckCommand) { final String runtimeCheckCommand) {
this(fallback, runtimeRoot, runtimeCheckCommand, false);
}
RuntimeBackedCompatibilityAdapter(
final RuntimeCompatibilityAdapter fallback,
final Path runtimeRoot,
final String runtimeCheckCommand,
final boolean strictRuntimeBacked) {
this.fallback = fallback == null ? new LocalRuntimeCompatibilityAdapter() : fallback; this.fallback = fallback == null ? new LocalRuntimeCompatibilityAdapter() : fallback;
this.runtimeRoot = runtimeRoot == null ? Path.of("../runtime") : runtimeRoot; this.runtimeRoot = runtimeRoot == null ? Path.of("../runtime") : runtimeRoot;
this.runtimeLine = readRuntimeLine(this.runtimeRoot); this.runtimeLine = readRuntimeLine(this.runtimeRoot);
this.runtimeCheckCommand = runtimeCheckCommand == null ? "" : runtimeCheckCommand.trim(); this.runtimeCheckCommand = runtimeCheckCommand == null ? "" : runtimeCheckCommand.trim();
this.strictRuntimeBacked = strictRuntimeBacked;
} }
@Override @Override
@ -87,6 +99,14 @@ final class RuntimeBackedCompatibilityAdapter implements RuntimeCompatibilityAda
private CompatibilityResult fallbackWithReason( private CompatibilityResult fallbackWithReason(
final CompatibilityResult local, final CompatibilityResult local,
final String reason) { final String reason) {
if (strictRuntimeBacked) {
return new CompatibilityResult(
CompatibilityError.RUNTIME_BACKED_REQUIRED,
local.hostcallCount(),
runtimeLine,
FALLBACK_MODE,
"strict gate-i requires runtime-backed adapter: " + reason);
}
return new CompatibilityResult( return new CompatibilityResult(
local.error(), local.error(),
local.hostcallCount(), local.hostcallCount(),
@ -134,4 +154,21 @@ final class RuntimeBackedCompatibilityAdapter implements RuntimeCompatibilityAda
} }
return output.substring(0, 160) + "..."; return output.substring(0, 160) + "...";
} }
private static boolean strictRuntimeBackedFromEnvironment() {
if (isTruthy(System.getenv(STRICT_FLAG_ENV))) {
return true;
}
return isTruthy(System.getenv("CI"));
}
private static boolean isTruthy(final String value) {
if (value == null) {
return false;
}
return switch (value.trim().toLowerCase()) {
case "1", "true", "yes", "on" -> true;
default -> false;
};
}
} }

View File

@ -35,6 +35,49 @@ class RuntimeBackedCompatibilityAdapterTest {
assertTrue(!result.runtimeLine().isBlank()); assertTrue(!result.runtimeLine().isBlank());
} }
@Test
void checkMustFailInStrictModeWhenRuntimeCommandIsUnavailable() {
final var adapter = new RuntimeBackedCompatibilityAdapter(
new LocalRuntimeCompatibilityAdapter(),
Path.of("."),
"",
true);
final var module = moduleWithSingleRet();
final var result = adapter.check(module);
assertEquals(CompatibilityError.RUNTIME_BACKED_REQUIRED, result.error());
assertEquals("local-fallback", result.adapterMode());
assertTrue(result.reason().contains("strict gate-i requires runtime-backed adapter"));
}
@Test
void checkMustPassInStrictModeWhenRuntimeCommandIsValid() {
final var adapter = new RuntimeBackedCompatibilityAdapter(
new LocalRuntimeCompatibilityAdapter(),
Path.of("."),
"echo runtime-check-ok",
true);
final var module = moduleWithSingleRet();
final var result = adapter.check(module);
assertEquals(CompatibilityError.NONE, result.error());
assertEquals("runtime-backed", result.adapterMode());
assertTrue(result.reason().contains("accepted artifact"));
}
private BytecodeModule moduleWithSingleRet() {
return new BytecodeModule(
0,
ReadOnlyList.empty(),
ReadOnlyList.from(new BytecodeModule.FunctionMeta(0, 2, 0, 0, 0, 1)),
codeRet(),
null,
ReadOnlyList.empty(),
ReadOnlyList.empty());
}
private byte[] codeRet() { private byte[] codeRet() {
final var out = ByteBuffer.allocate(2).order(ByteOrder.LITTLE_ENDIAN); final var out = ByteBuffer.allocate(2).order(ByteOrder.LITTLE_ENDIAN);
out.putShort((short) 0x51); out.putShort((short) 0x51);