|
|
|
@@ -10,6 +10,7 @@ import java.nio.file.Path;
|
|
|
|
|
import java.util.List;
|
|
|
|
|
import java.util.Map;
|
|
|
|
|
import java.util.Set;
|
|
|
|
|
import java.util.regex.Pattern;
|
|
|
|
|
|
|
|
|
|
import static org.junit.jupiter.api.Assertions.*;
|
|
|
|
|
|
|
|
|
@@ -1189,6 +1190,79 @@ class BridgedConfigTest {
|
|
|
|
|
assertEquals(5, cfg.leadHeartbeat().quietNudgeCap());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* A top-level key {@code BridgedConfig} reads but that appears nowhere in
|
|
|
|
|
* {@code bridged.example.yaml} — live or commented — is invisible drift: {@code bridged.yaml}
|
|
|
|
|
* is gitignored, so the example is the ONLY committed description of the config schema, and
|
|
|
|
|
* neither {@link #shippedExampleConfigParses} (example → code: does the example still parse)
|
|
|
|
|
* nor {@link #everyOptionalKnobDocumentedInTheExampleBinds} (a hand-maintained list of keys
|
|
|
|
|
* that must bind) can catch a brand-new key nobody added to either.
|
|
|
|
|
*
|
|
|
|
|
* <p>This test compares the OTHER direction: every key in {@link BridgedConfig#KNOWN_TOP_LEVEL_KEYS}
|
|
|
|
|
* (the parser's own accepted set, which backs the unknown-key WARN) must appear as a top-level
|
|
|
|
|
* key in the example text, live or commented-out — see {@link #topLevelKeyDocumented}.
|
|
|
|
|
*/
|
|
|
|
|
@Test
|
|
|
|
|
void everyKnownTopLevelKeyIsDocumentedInTheExample() throws Exception {
|
|
|
|
|
Path example = Path.of("bridged.example.yaml");
|
|
|
|
|
assertTrue(Files.exists(example), "bridged.example.yaml must ship next to the pom");
|
|
|
|
|
String text = Files.readString(example);
|
|
|
|
|
|
|
|
|
|
List<String> undocumented = BridgedConfig.KNOWN_TOP_LEVEL_KEYS.stream()
|
|
|
|
|
.filter(key -> !topLevelKeyDocumented(text, key))
|
|
|
|
|
.sorted()
|
|
|
|
|
.toList();
|
|
|
|
|
|
|
|
|
|
assertTrue(undocumented.isEmpty(), () -> "key(s) " + undocumented
|
|
|
|
|
+ " are read by BridgedConfig but appear nowhere in bridged.example.yaml — "
|
|
|
|
|
+ "document each one there, commented out if optional. bridged.yaml is "
|
|
|
|
|
+ "gitignored, so this file is the only committed description of the config "
|
|
|
|
|
+ "schema an operator or a worker can see.");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Most of {@code bridged.example.yaml} is deliberately commented out — optional sections are
|
|
|
|
|
* documented as commented blocks so the shipped file stays a working minimal config. A key
|
|
|
|
|
* documented ONLY as a comment must still count as documented; parsing the file as YAML and
|
|
|
|
|
* reading its live key set (as an earlier attempt at this guard did) gets this wrong, because
|
|
|
|
|
* every commented section then looks entirely absent.
|
|
|
|
|
*/
|
|
|
|
|
@Test
|
|
|
|
|
void commentedOnlyTopLevelKeyCountsAsDocumented() {
|
|
|
|
|
String yaml = """
|
|
|
|
|
bind:
|
|
|
|
|
port: 8765
|
|
|
|
|
# broker:
|
|
|
|
|
# uri: amqp://guest:guest@127.0.0.1:5672
|
|
|
|
|
""";
|
|
|
|
|
assertTrue(topLevelKeyDocumented(yaml, "broker"),
|
|
|
|
|
"a key documented only inside a commented-out block must still count as documented");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** A key that appears in neither a live nor a commented top-level line must NOT count. */
|
|
|
|
|
@Test
|
|
|
|
|
void absentTopLevelKeyIsNotDocumented() {
|
|
|
|
|
String yaml = """
|
|
|
|
|
bind:
|
|
|
|
|
port: 8765
|
|
|
|
|
""";
|
|
|
|
|
assertFalse(topLevelKeyDocumented(yaml, "broker"),
|
|
|
|
|
"a key mentioned nowhere in the example must not be reported as documented");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* True when {@code key} appears as a top-level YAML key in {@code yaml} — either live
|
|
|
|
|
* ({@code key:} at column 0) or commented out ({@code # key:}, also at column 0, with only
|
|
|
|
|
* whitespace between the {@code #} and the key). Anchoring on column 0 is what keeps this a
|
|
|
|
|
* top-level check: an indented occurrence (a nested field, or prose inside a comment that
|
|
|
|
|
* happens to end in a colon) never matches, because {@code ^} requires the key's own first
|
|
|
|
|
* character — or the sole leading {@code #} — to sit at the very start of the line.
|
|
|
|
|
*/
|
|
|
|
|
private static boolean topLevelKeyDocumented(String yaml, String key) {
|
|
|
|
|
Pattern p = Pattern.compile("(?m)^(?:#\\s*)?" + Pattern.quote(key) + ":");
|
|
|
|
|
return p.matcher(yaml).find();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
void placementDefaultsToFixedForExistingConfigs(@TempDir Path dir) throws Exception {
|
|
|
|
|
Path f = dir.resolve("no-placement.yaml");
|
|
|
|
|