diff --git a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/conf/ConfigurationFieldsTests.java b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/conf/ConfigurationFieldsTests.java index 41fffe6e1373..918278966284 100644 --- a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/conf/ConfigurationFieldsTests.java +++ b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/conf/ConfigurationFieldsTests.java @@ -17,6 +17,7 @@ package org.apache.hadoop.conf; +import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; @@ -135,6 +136,14 @@ public abstract class ConfigurationFieldsTests { @SuppressWarnings("checkstyle:visibilitymodifier") protected Set filtersForDefaultValueCollisionCheck = new HashSet<>(); + /** + * A set of property keys that are allowed to contain a newline. + * Entries are skipped by {@link #testXmlValuesHaveNoEmbeddedNewlines}; keep + * this empty unless a value genuinely requires a line break, otherwise the + * embedded newline corrupts the runtime string (see HDDS-8046). + */ + protected Set xmlPropsAllowedToContainNewline = new HashSet<>(); + /** * Abstract method to be used by subclasses for initializing base * members. @@ -668,6 +677,44 @@ public void testDefaultValueCollision() { LOG.info("Checked {} default values for collision.", valuesChecked); } + } + + /** + * Verifies no default value in the XML embeds a line break, which would + * corrupt the runtime string (see HDDS-8046). Legitimate cases opt out via + * {@link #xmlPropsAllowedToContainNewline}. Unlike the comparison tests, this + * reads the raw XML directly so it is not narrowed by + * {@code xmlPropsToSkipCompare}/{@code xmlPrefixToSkipCompare}: every property + * is checked, and the only exemption is {@link #xmlPropsAllowedToContainNewline}. + */ + @Test + public void testXmlValuesHaveNoEmbeddedNewlines() { + assertNotNull(xmlFilename); + Configuration conf = new Configuration(false); + conf.setAllowNullValueProperties(true); + conf.addResource(xmlFilename); + + Set xmlValuesWithNewlines = new TreeSet<>(); + for (Map.Entry entry : conf) { + String value = entry.getValue(); + if (value == null) { + continue; + } + if (xmlPropsAllowedToContainNewline.contains(entry.getKey())) { + LOG.info("XML Property: {} AllowedToContainNewline", entry.getKey()); + continue; + } + if (value.indexOf('\n') != -1 || value.indexOf('\r') != -1) { + xmlValuesWithNewlines.add(entry.getKey()); + } + } + assertThat(xmlValuesWithNewlines).withFailMessage( + "These properties in " + xmlFilename + " have an embedded line break in " + + "their , which corrupts the runtime string: " + xmlValuesWithNewlines + + " Put the value on a single line. If the newline is genuinely required, " + + "add the property to xmlPropsAllowedToContainNewline (in " + + "initializeMemberVariables) with a reason + Jira. See HDDS-8082.") + .isEmpty(); } }