diff --git a/core/src/main/java/org/elasticsearch/common/logging/DeprecationLogger.java b/core/src/main/java/org/elasticsearch/common/logging/DeprecationLogger.java
index 39b882f1a1d..12f3a5d3be6 100644
--- a/core/src/main/java/org/elasticsearch/common/logging/DeprecationLogger.java
+++ b/core/src/main/java/org/elasticsearch/common/logging/DeprecationLogger.java
@@ -21,13 +21,21 @@ package org.elasticsearch.common.logging;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
+import org.elasticsearch.Build;
+import org.elasticsearch.Version;
import org.elasticsearch.common.SuppressLoggerChecks;
import org.elasticsearch.common.util.concurrent.ThreadContext;
+import java.time.ZoneId;
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
import java.util.Iterator;
+import java.util.Locale;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
/**
* A logger that logs deprecation notices.
@@ -36,14 +44,6 @@ public class DeprecationLogger {
private final Logger logger;
- /**
- * The "Warning" Header comes from RFC-7234. As the RFC describes, it's generally used for caching purposes, but it can be
- * used for any warning.
- *
- * https://tools.ietf.org/html/rfc7234#section-5.5
- */
- public static final String WARNING_HEADER = "Warning";
-
/**
* This is set once by the {@code Node} constructor, but it uses {@link CopyOnWriteArraySet} to ensure that tests can run in parallel.
*
@@ -112,6 +112,57 @@ public class DeprecationLogger {
deprecated(THREAD_CONTEXT, msg, params);
}
+ /*
+ * RFC7234 specifies the warning format as warn-code warn-agent "warn-text" [ "warn-date"]. Here, warn-code is a
+ * three-digit number with various standard warn codes specified. The warn code 299 is apt for our purposes as it represents a
+ * miscellaneous persistent warning (can be presented to a human, or logged, and must not be removed by a cache). The warn-agent is an
+ * arbitrary token; here we use the Elasticsearch version and build hash. The warn text must be quoted. The warn-date is an optional
+ * quoted field that can be in a variety of specified date formats; here we use RFC 1123 format.
+ */
+ private static final String WARNING_FORMAT =
+ String.format(
+ Locale.ROOT,
+ "299 Elasticsearch-%s%s-%s ",
+ Version.CURRENT.toString(),
+ Build.CURRENT.isSnapshot() ? "-SNAPSHOT" : "",
+ Build.CURRENT.shortHash()) +
+ "\"%s\" \"%s\"";
+
+ private static final ZoneId GMT = ZoneId.of("GMT");
+
+ /**
+ * Regular expression to test if a string matches the RFC7234 specification for warning headers. This pattern assumes that the warn code
+ * is always 299. Further, this pattern assumes that the warn agent represents a version of Elasticsearch including the build hash.
+ */
+ public static Pattern WARNING_HEADER_PATTERN = Pattern.compile(
+ "299 " + // warn code
+ "Elasticsearch-\\d+\\.\\d+\\.\\d+(?:-(?:alpha|beta|rc)\\d+)?(?:-SNAPSHOT)?-(?:[a-f0-9]{7}|Unknown) " + // warn agent
+ "\"((?:\t| |!|[\\x23-\\x5b]|[\\x5d-\\x7e]|[\\x80-\\xff]|\\\\|\\\\\")*)\" " + // quoted warning value, captured
+ // quoted RFC 1123 date format
+ "\"" + // opening quote
+ "(?:Mon|Tue|Wed|Thu|Fri|Sat|Sun), " + // weekday
+ "\\d{2} " + // 2-digit day
+ "(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) " + // month
+ "\\d{4} " + // 4-digit year
+ "\\d{2}:\\d{2}:\\d{2} " + // (two-digit hour):(two-digit minute):(two-digit second)
+ "GMT" + // GMT
+ "\""); // closing quote
+
+ /**
+ * Extracts the warning value from the value of a warning header that is formatted according to RFC 7234. That is, given a string
+ * {@code 299 Elasticsearch-6.0.0 "warning value" "Sat, 25 Feb 2017 10:27:43 GMT"}, the return value of this method would be {@code
+ * warning value}.
+ *
+ * @param s the value of a warning header formatted according to RFC 7234.
+ * @return the extracted warning value
+ */
+ public static String extractWarningValueFromWarningHeader(final String s) {
+ final Matcher matcher = WARNING_HEADER_PATTERN.matcher(s);
+ final boolean matches = matcher.matches();
+ assert matches;
+ return matcher.group(1);
+ }
+
/**
* Logs a deprecated message to the deprecation log, as well as to the local {@link ThreadContext}.
*
@@ -120,16 +171,19 @@ public class DeprecationLogger {
* @param params The parameters used to fill in the message, if any exist.
*/
@SuppressLoggerChecks(reason = "safely delegates to logger")
- void deprecated(Set threadContexts, String message, Object... params) {
- Iterator iterator = threadContexts.iterator();
+ void deprecated(final Set threadContexts, final String message, final Object... params) {
+ final Iterator iterator = threadContexts.iterator();
if (iterator.hasNext()) {
final String formattedMessage = LoggerMessageFormat.format(message, params);
-
+ final String warningHeaderValue = formatWarning(formattedMessage);
+ assert WARNING_HEADER_PATTERN.matcher(warningHeaderValue).matches();
+ assert extractWarningValueFromWarningHeader(warningHeaderValue).equals(escape(formattedMessage));
while (iterator.hasNext()) {
try {
- iterator.next().addResponseHeader(WARNING_HEADER, formattedMessage);
- } catch (IllegalStateException e) {
+ final ThreadContext next = iterator.next();
+ next.addResponseHeader("Warning", warningHeaderValue, DeprecationLogger::extractWarningValueFromWarningHeader);
+ } catch (final IllegalStateException e) {
// ignored; it should be removed shortly
}
}
@@ -139,4 +193,25 @@ public class DeprecationLogger {
}
}
+ /**
+ * Format a warning string in the proper warning format by prepending a warn code, warn agent, wrapping the warning string in quotes,
+ * and appending the RFC 1123 date.
+ *
+ * @param s the warning string to format
+ * @return a warning value formatted according to RFC 7234
+ */
+ public static String formatWarning(final String s) {
+ return String.format(Locale.ROOT, WARNING_FORMAT, escape(s), DateTimeFormatter.RFC_1123_DATE_TIME.format(ZonedDateTime.now(GMT)));
+ }
+
+ /**
+ * Escape backslashes and quotes in the specified string.
+ *
+ * @param s the string to escape
+ * @return the escaped string
+ */
+ public static String escape(String s) {
+ return s.replaceAll("(\\\\|\")", "\\\\$1");
+ }
+
}
diff --git a/core/src/main/java/org/elasticsearch/common/util/concurrent/ThreadContext.java b/core/src/main/java/org/elasticsearch/common/util/concurrent/ThreadContext.java
index d439696b720..409a70eb649 100644
--- a/core/src/main/java/org/elasticsearch/common/util/concurrent/ThreadContext.java
+++ b/core/src/main/java/org/elasticsearch/common/util/concurrent/ThreadContext.java
@@ -34,7 +34,9 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -257,12 +259,25 @@ public final class ThreadContext implements Closeable, Writeable {
}
/**
- * Add the unique response {@code value} for the specified {@code key}.
- *
- * Any duplicate {@code value} is ignored.
+ * Add the {@code value} for the specified {@code key} Any duplicate {@code value} is ignored.
+ *
+ * @param key the header name
+ * @param value the header value
*/
- public void addResponseHeader(String key, String value) {
- threadLocal.set(threadLocal.get().putResponse(key, value));
+ public void addResponseHeader(final String key, final String value) {
+ addResponseHeader(key, value, v -> v);
+ }
+
+ /**
+ * Add the {@code value} for the specified {@code key} with the specified {@code uniqueValue} used for de-duplication. Any duplicate
+ * {@code value} after applying {@code uniqueValue} is ignored.
+ *
+ * @param key the header name
+ * @param value the header value
+ * @param uniqueValue the function that produces de-duplication values
+ */
+ public void addResponseHeader(final String key, final String value, final Function uniqueValue) {
+ threadLocal.set(threadLocal.get().putResponse(key, value, uniqueValue));
}
/**
@@ -396,14 +411,16 @@ public final class ThreadContext implements Closeable, Writeable {
return new ThreadContextStruct(requestHeaders, newResponseHeaders, transientHeaders);
}
- private ThreadContextStruct putResponse(String key, String value) {
+ private ThreadContextStruct putResponse(final String key, final String value, final Function uniqueValue) {
assert value != null;
final Map> newResponseHeaders = new HashMap<>(this.responseHeaders);
final List existingValues = newResponseHeaders.get(key);
if (existingValues != null) {
- if (existingValues.contains(value)) {
+ final Set existingUniqueValues = existingValues.stream().map(uniqueValue).collect(Collectors.toSet());
+ assert existingValues.size() == existingUniqueValues.size();
+ if (existingUniqueValues.contains(uniqueValue.apply(value))) {
return this;
}
diff --git a/core/src/test/java/org/elasticsearch/common/logging/DeprecationLoggerTests.java b/core/src/test/java/org/elasticsearch/common/logging/DeprecationLoggerTests.java
index d0e1b807baf..562b9b97eb3 100644
--- a/core/src/test/java/org/elasticsearch/common/logging/DeprecationLoggerTests.java
+++ b/core/src/test/java/org/elasticsearch/common/logging/DeprecationLoggerTests.java
@@ -18,9 +18,11 @@
*/
package org.elasticsearch.common.logging;
+import com.carrotsearch.randomizedtesting.generators.CodepointSetGenerator;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.util.concurrent.ThreadContext;
import org.elasticsearch.test.ESTestCase;
+import org.elasticsearch.test.hamcrest.RegexMatcher;
import java.io.IOException;
import java.util.Collections;
@@ -28,17 +30,22 @@ import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.stream.IntStream;
-import static org.hamcrest.Matchers.not;
+import static org.elasticsearch.common.logging.DeprecationLogger.WARNING_HEADER_PATTERN;
+import static org.elasticsearch.test.hamcrest.RegexMatcher.matches;
+import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo;
-import static org.hamcrest.Matchers.hasItem;
import static org.hamcrest.Matchers.hasSize;
+import static org.hamcrest.Matchers.not;
/**
* Tests {@link DeprecationLogger}
*/
public class DeprecationLoggerTests extends ESTestCase {
+ private static final RegexMatcher warningValueMatcher = matches(WARNING_HEADER_PATTERN.pattern());
+
private final DeprecationLogger logger = new DeprecationLogger(Loggers.getLogger(getClass()));
@Override
@@ -48,43 +55,42 @@ public class DeprecationLoggerTests extends ESTestCase {
}
public void testAddsHeaderWithThreadContext() throws IOException {
- String msg = "A simple message [{}]";
- String param = randomAsciiOfLengthBetween(1, 5);
- String formatted = LoggerMessageFormat.format(msg, (Object)param);
-
try (ThreadContext threadContext = new ThreadContext(Settings.EMPTY)) {
- Set threadContexts = Collections.singleton(threadContext);
+ final Set threadContexts = Collections.singleton(threadContext);
- logger.deprecated(threadContexts, msg, param);
+ final String param = randomAsciiOfLengthBetween(1, 5);
+ logger.deprecated(threadContexts, "A simple message [{}]", param);
- Map> responseHeaders = threadContext.getResponseHeaders();
+ final Map> responseHeaders = threadContext.getResponseHeaders();
- assertEquals(1, responseHeaders.size());
- assertEquals(formatted, responseHeaders.get(DeprecationLogger.WARNING_HEADER).get(0));
+ assertThat(responseHeaders.size(), equalTo(1));
+ final List responses = responseHeaders.get("Warning");
+ assertThat(responses, hasSize(1));
+ assertThat(responses.get(0), warningValueMatcher);
+ assertThat(responses.get(0), containsString("\"A simple message [" + param + "]\""));
}
}
public void testAddsCombinedHeaderWithThreadContext() throws IOException {
- String msg = "A simple message [{}]";
- String param = randomAsciiOfLengthBetween(1, 5);
- String formatted = LoggerMessageFormat.format(msg, (Object)param);
- String formatted2 = randomAsciiOfLengthBetween(1, 10);
-
try (ThreadContext threadContext = new ThreadContext(Settings.EMPTY)) {
- Set threadContexts = Collections.singleton(threadContext);
+ final Set threadContexts = Collections.singleton(threadContext);
- logger.deprecated(threadContexts, msg, param);
- logger.deprecated(threadContexts, formatted2);
+ final String param = randomAsciiOfLengthBetween(1, 5);
+ logger.deprecated(threadContexts, "A simple message [{}]", param);
+ final String second = randomAsciiOfLengthBetween(1, 10);
+ logger.deprecated(threadContexts, second);
- Map> responseHeaders = threadContext.getResponseHeaders();
+ final Map> responseHeaders = threadContext.getResponseHeaders();
assertEquals(1, responseHeaders.size());
- List responses = responseHeaders.get(DeprecationLogger.WARNING_HEADER);
+ final List responses = responseHeaders.get("Warning");
assertEquals(2, responses.size());
- assertEquals(formatted, responses.get(0));
- assertEquals(formatted2, responses.get(1));
+ assertThat(responses.get(0), warningValueMatcher);
+ assertThat(responses.get(0), containsString("\"A simple message [" + param + "]\""));
+ assertThat(responses.get(1), warningValueMatcher);
+ assertThat(responses.get(1), containsString("\"" + second + "\""));
}
}
@@ -93,28 +99,30 @@ public class DeprecationLoggerTests extends ESTestCase {
final String unexpected = "testCannotRemoveThreadContext";
try (ThreadContext threadContext = new ThreadContext(Settings.EMPTY)) {
- // NOTE: by adding it to the logger, we allow any concurrent test to write to it (from their own threads)
DeprecationLogger.setThreadContext(threadContext);
-
logger.deprecated(expected);
- Map> responseHeaders = threadContext.getResponseHeaders();
- List responses = responseHeaders.get(DeprecationLogger.WARNING_HEADER);
+ {
+ final Map> responseHeaders = threadContext.getResponseHeaders();
+ final List responses = responseHeaders.get("Warning");
- // ensure it works (note: concurrent tests may be adding to it, but in different threads, so it should have no impact)
- assertThat(responses, hasSize(atLeast(1)));
- assertThat(responses, hasItem(equalTo(expected)));
+ assertThat(responses, hasSize(1));
+ assertThat(responses.get(0), warningValueMatcher);
+ assertThat(responses.get(0), containsString(expected));
+ }
DeprecationLogger.removeThreadContext(threadContext);
-
logger.deprecated(unexpected);
- responseHeaders = threadContext.getResponseHeaders();
- responses = responseHeaders.get(DeprecationLogger.WARNING_HEADER);
+ {
+ final Map> responseHeaders = threadContext.getResponseHeaders();
+ final List responses = responseHeaders.get("Warning");
- assertThat(responses, hasSize(atLeast(1)));
- assertThat(responses, hasItem(expected));
- assertThat(responses, not(hasItem(unexpected)));
+ assertThat(responses, hasSize(1));
+ assertThat(responses.get(0), warningValueMatcher);
+ assertThat(responses.get(0), containsString(expected));
+ assertThat(responses.get(0), not(containsString(unexpected)));
+ }
}
}
@@ -158,4 +166,28 @@ public class DeprecationLoggerTests extends ESTestCase {
}
}
+ public void testWarningValueFromWarningHeader() throws InterruptedException {
+ final String s = randomAsciiOfLength(16);
+ final String first = DeprecationLogger.formatWarning(s);
+ assertThat(DeprecationLogger.extractWarningValueFromWarningHeader(first), equalTo(s));
+ }
+
+ public void testEscape() {
+ assertThat(DeprecationLogger.escape("\\"), equalTo("\\\\"));
+ assertThat(DeprecationLogger.escape("\""), equalTo("\\\""));
+ assertThat(DeprecationLogger.escape("\\\""), equalTo("\\\\\\\""));
+ assertThat(DeprecationLogger.escape("\"foo\\bar\""),equalTo("\\\"foo\\\\bar\\\""));
+ // test that characters other than '\' and '"' are left unchanged
+ String chars = "\t !" + range(0x23, 0x5b + 1) + range(0x5d, 0x73 + 1) + range(0x80, 0xff + 1);
+ final String s = new CodepointSetGenerator(chars.toCharArray()).ofCodePointsLength(random(), 16, 16);
+ assertThat(DeprecationLogger.escape(s), equalTo(s));
+ }
+
+ private String range(int lowerInclusive, int upperInclusive) {
+ return IntStream
+ .range(lowerInclusive, upperInclusive + 1)
+ .collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append)
+ .toString();
+ }
+
}
diff --git a/core/src/test/java/org/elasticsearch/common/util/concurrent/ThreadContextTests.java b/core/src/test/java/org/elasticsearch/common/util/concurrent/ThreadContextTests.java
index 582f5d58d80..698e216ea16 100644
--- a/core/src/test/java/org/elasticsearch/common/util/concurrent/ThreadContextTests.java
+++ b/core/src/test/java/org/elasticsearch/common/util/concurrent/ThreadContextTests.java
@@ -19,6 +19,7 @@
package org.elasticsearch.common.util.concurrent;
import org.elasticsearch.common.io.stream.BytesStreamOutput;
+import org.elasticsearch.common.logging.DeprecationLogger;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.test.ESTestCase;
@@ -178,6 +179,14 @@ public class ThreadContextTests extends ESTestCase {
threadContext.addResponseHeader("foo", "bar");
}
+ final String value = DeprecationLogger.formatWarning("qux");
+ threadContext.addResponseHeader("baz", value, DeprecationLogger::extractWarningValueFromWarningHeader);
+ // pretend that another thread created the same response at a different time
+ if (randomBoolean()) {
+ final String duplicateValue = DeprecationLogger.formatWarning("qux");
+ threadContext.addResponseHeader("baz", duplicateValue, DeprecationLogger::extractWarningValueFromWarningHeader);
+ }
+
threadContext.addResponseHeader("Warning", "One is the loneliest number");
threadContext.addResponseHeader("Warning", "Two can be as bad as one");
if (expectThird) {
@@ -186,11 +195,14 @@ public class ThreadContextTests extends ESTestCase {
final Map> responseHeaders = threadContext.getResponseHeaders();
final List foo = responseHeaders.get("foo");
+ final List baz = responseHeaders.get("baz");
final List warnings = responseHeaders.get("Warning");
final int expectedWarnings = expectThird ? 3 : 2;
assertThat(foo, hasSize(1));
+ assertThat(baz, hasSize(1));
assertEquals("bar", foo.get(0));
+ assertEquals(value, baz.get(0));
assertThat(warnings, hasSize(expectedWarnings));
assertThat(warnings, hasItem(equalTo("One is the loneliest number")));
assertThat(warnings, hasItem(equalTo("Two can be as bad as one")));
diff --git a/plugins/discovery-azure-classic/src/main/java/org/elasticsearch/plugin/discovery/azure/classic/AzureDiscoveryPlugin.java b/plugins/discovery-azure-classic/src/main/java/org/elasticsearch/plugin/discovery/azure/classic/AzureDiscoveryPlugin.java
index 1661c69c725..38e29e04583 100644
--- a/plugins/discovery-azure-classic/src/main/java/org/elasticsearch/plugin/discovery/azure/classic/AzureDiscoveryPlugin.java
+++ b/plugins/discovery-azure-classic/src/main/java/org/elasticsearch/plugin/discovery/azure/classic/AzureDiscoveryPlugin.java
@@ -102,9 +102,9 @@ public class AzureDiscoveryPlugin extends Plugin implements DiscoveryPlugin {
// setting existed. This check looks for the legacy setting, and sets hosts provider if set
String discoveryType = DiscoveryModule.DISCOVERY_TYPE_SETTING.get(settings);
if (discoveryType.equals(AZURE)) {
- deprecationLogger.deprecated("Using " + DiscoveryModule.DISCOVERY_TYPE_SETTING.getKey() +
- " setting to set hosts provider is deprecated. " +
- "Set \"" + DiscoveryModule.DISCOVERY_HOSTS_PROVIDER_SETTING.getKey() + ": " + AZURE + "\" instead");
+ deprecationLogger.deprecated("using [" + DiscoveryModule.DISCOVERY_TYPE_SETTING.getKey() +
+ "] to set hosts provider is deprecated; " +
+ "set \"" + DiscoveryModule.DISCOVERY_HOSTS_PROVIDER_SETTING.getKey() + ": " + AZURE + "\" instead");
if (DiscoveryModule.DISCOVERY_HOSTS_PROVIDER_SETTING.exists(settings) == false) {
return Settings.builder().put(DiscoveryModule.DISCOVERY_HOSTS_PROVIDER_SETTING.getKey(), AZURE).build();
}
diff --git a/plugins/discovery-ec2/src/main/java/org/elasticsearch/plugin/discovery/ec2/Ec2DiscoveryPlugin.java b/plugins/discovery-ec2/src/main/java/org/elasticsearch/plugin/discovery/ec2/Ec2DiscoveryPlugin.java
index b3209ec571e..0529404ea9f 100644
--- a/plugins/discovery-ec2/src/main/java/org/elasticsearch/plugin/discovery/ec2/Ec2DiscoveryPlugin.java
+++ b/plugins/discovery-ec2/src/main/java/org/elasticsearch/plugin/discovery/ec2/Ec2DiscoveryPlugin.java
@@ -165,9 +165,9 @@ public class Ec2DiscoveryPlugin extends Plugin implements DiscoveryPlugin, Close
// setting existed. This check looks for the legacy setting, and sets hosts provider if set
String discoveryType = DiscoveryModule.DISCOVERY_TYPE_SETTING.get(settings);
if (discoveryType.equals(EC2)) {
- deprecationLogger.deprecated("Using " + DiscoveryModule.DISCOVERY_TYPE_SETTING.getKey() +
- " setting to set hosts provider is deprecated. " +
- "Set \"" + DiscoveryModule.DISCOVERY_HOSTS_PROVIDER_SETTING.getKey() + ": " + EC2 + "\" instead");
+ deprecationLogger.deprecated("using [" + DiscoveryModule.DISCOVERY_TYPE_SETTING.getKey() +
+ "] setting to set hosts provider is deprecated; " +
+ "set [" + DiscoveryModule.DISCOVERY_HOSTS_PROVIDER_SETTING.getKey() + ": " + EC2 + "] instead");
if (DiscoveryModule.DISCOVERY_HOSTS_PROVIDER_SETTING.exists(settings) == false) {
builder.put(DiscoveryModule.DISCOVERY_HOSTS_PROVIDER_SETTING.getKey(), EC2).build();
}
diff --git a/plugins/repository-s3/src/test/java/org/elasticsearch/cloud/aws/AwsS3ServiceImplTests.java b/plugins/repository-s3/src/test/java/org/elasticsearch/cloud/aws/AwsS3ServiceImplTests.java
index 09a3222d63e..e13aa61f3a2 100644
--- a/plugins/repository-s3/src/test/java/org/elasticsearch/cloud/aws/AwsS3ServiceImplTests.java
+++ b/plugins/repository-s3/src/test/java/org/elasticsearch/cloud/aws/AwsS3ServiceImplTests.java
@@ -23,7 +23,6 @@ import com.amazonaws.ClientConfiguration;
import com.amazonaws.Protocol;
import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.AWSCredentialsProvider;
-
import org.elasticsearch.common.settings.MockSecureSettings;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.repositories.s3.S3Repository;
@@ -65,8 +64,7 @@ public class AwsS3ServiceImplTests extends ESTestCase {
.put(AwsS3Service.SECRET_SETTING.getKey(), "aws_secret")
.build();
launchAWSCredentialsWithElasticsearchSettingsTest(Settings.EMPTY, settings, "aws_key", "aws_secret");
- assertWarnings("[" + AwsS3Service.KEY_SETTING.getKey() + "] setting was deprecated",
- "[" + AwsS3Service.SECRET_SETTING.getKey() + "] setting was deprecated");
+ assertSettingDeprecations(AwsS3Service.KEY_SETTING, AwsS3Service.SECRET_SETTING);
}
public void testAWSCredentialsWithElasticsearchS3SettingsBackcompat() {
@@ -75,8 +73,7 @@ public class AwsS3ServiceImplTests extends ESTestCase {
.put(AwsS3Service.CLOUD_S3.SECRET_SETTING.getKey(), "s3_secret")
.build();
launchAWSCredentialsWithElasticsearchSettingsTest(Settings.EMPTY, settings, "s3_key", "s3_secret");
- assertWarnings("[" + AwsS3Service.CLOUD_S3.KEY_SETTING.getKey() + "] setting was deprecated",
- "[" + AwsS3Service.CLOUD_S3.SECRET_SETTING.getKey() + "] setting was deprecated");
+ assertSettingDeprecations(AwsS3Service.CLOUD_S3.KEY_SETTING, AwsS3Service.CLOUD_S3.SECRET_SETTING);
}
public void testAWSCredentialsWithElasticsearchAwsAndS3SettingsBackcompat() {
@@ -87,10 +84,11 @@ public class AwsS3ServiceImplTests extends ESTestCase {
.put(AwsS3Service.CLOUD_S3.SECRET_SETTING.getKey(), "s3_secret")
.build();
launchAWSCredentialsWithElasticsearchSettingsTest(Settings.EMPTY, settings, "s3_key", "s3_secret");
- assertWarnings("[" + AwsS3Service.KEY_SETTING.getKey() + "] setting was deprecated",
- "[" + AwsS3Service.SECRET_SETTING.getKey() + "] setting was deprecated",
- "[" + AwsS3Service.CLOUD_S3.KEY_SETTING.getKey() + "] setting was deprecated",
- "[" + AwsS3Service.CLOUD_S3.SECRET_SETTING.getKey() + "] setting was deprecated");
+ assertSettingDeprecations(
+ AwsS3Service.KEY_SETTING,
+ AwsS3Service.SECRET_SETTING,
+ AwsS3Service.CLOUD_S3.KEY_SETTING,
+ AwsS3Service.CLOUD_S3.SECRET_SETTING);
}
public void testAWSCredentialsWithElasticsearchRepositoriesSettingsBackcompat() {
@@ -99,8 +97,7 @@ public class AwsS3ServiceImplTests extends ESTestCase {
.put(S3Repository.Repositories.SECRET_SETTING.getKey(), "repositories_secret")
.build();
launchAWSCredentialsWithElasticsearchSettingsTest(Settings.EMPTY, settings, "repositories_key", "repositories_secret");
- assertWarnings("[" + S3Repository.Repositories.KEY_SETTING.getKey() + "] setting was deprecated",
- "[" + S3Repository.Repositories.SECRET_SETTING.getKey() + "] setting was deprecated");
+ assertSettingDeprecations(S3Repository.Repositories.KEY_SETTING, S3Repository.Repositories.SECRET_SETTING);
}
public void testAWSCredentialsWithElasticsearchAwsAndRepositoriesSettingsBackcompat() {
@@ -111,10 +108,11 @@ public class AwsS3ServiceImplTests extends ESTestCase {
.put(S3Repository.Repositories.SECRET_SETTING.getKey(), "repositories_secret")
.build();
launchAWSCredentialsWithElasticsearchSettingsTest(Settings.EMPTY, settings, "repositories_key", "repositories_secret");
- assertWarnings("[" + AwsS3Service.KEY_SETTING.getKey() + "] setting was deprecated",
- "[" + AwsS3Service.SECRET_SETTING.getKey() + "] setting was deprecated",
- "[" + S3Repository.Repositories.KEY_SETTING.getKey() + "] setting was deprecated",
- "[" + S3Repository.Repositories.SECRET_SETTING.getKey() + "] setting was deprecated");
+ assertSettingDeprecations(
+ AwsS3Service.KEY_SETTING,
+ AwsS3Service.SECRET_SETTING,
+ S3Repository.Repositories.KEY_SETTING,
+ S3Repository.Repositories.SECRET_SETTING);
}
public void testAWSCredentialsWithElasticsearchAwsAndS3AndRepositoriesSettingsBackcompat() {
@@ -127,12 +125,13 @@ public class AwsS3ServiceImplTests extends ESTestCase {
.put(S3Repository.Repositories.SECRET_SETTING.getKey(), "repositories_secret")
.build();
launchAWSCredentialsWithElasticsearchSettingsTest(Settings.EMPTY, settings, "repositories_key", "repositories_secret");
- assertWarnings("[" + AwsS3Service.KEY_SETTING.getKey() + "] setting was deprecated",
- "[" + AwsS3Service.SECRET_SETTING.getKey() + "] setting was deprecated",
- "[" + AwsS3Service.CLOUD_S3.KEY_SETTING.getKey() + "] setting was deprecated",
- "[" + AwsS3Service.CLOUD_S3.SECRET_SETTING.getKey() + "] setting was deprecated",
- "[" + S3Repository.Repositories.KEY_SETTING.getKey() + "] setting was deprecated",
- "[" + S3Repository.Repositories.SECRET_SETTING.getKey() + "] setting was deprecated");
+ assertSettingDeprecations(
+ AwsS3Service.KEY_SETTING,
+ AwsS3Service.SECRET_SETTING,
+ AwsS3Service.CLOUD_S3.KEY_SETTING,
+ AwsS3Service.CLOUD_S3.SECRET_SETTING,
+ S3Repository.Repositories.KEY_SETTING,
+ S3Repository.Repositories.SECRET_SETTING);
}
public void testAWSCredentialsWithElasticsearchRepositoriesSettingsAndRepositorySettingsBackcompat() {
@@ -142,8 +141,7 @@ public class AwsS3ServiceImplTests extends ESTestCase {
.put(S3Repository.Repositories.SECRET_SETTING.getKey(), "repositories_secret")
.build();
launchAWSCredentialsWithElasticsearchSettingsTest(repositorySettings, settings, "repository_key", "repository_secret");
- assertWarnings("[" + S3Repository.Repository.KEY_SETTING.getKey() + "] setting was deprecated",
- "[" + S3Repository.Repository.SECRET_SETTING.getKey() + "] setting was deprecated");
+ assertSettingDeprecations(S3Repository.Repository.KEY_SETTING, S3Repository.Repository.SECRET_SETTING);
}
public void testAWSCredentialsWithElasticsearchAwsAndRepositoriesSettingsAndRepositorySettingsBackcompat() {
@@ -155,8 +153,7 @@ public class AwsS3ServiceImplTests extends ESTestCase {
.put(S3Repository.Repositories.SECRET_SETTING.getKey(), "repositories_secret")
.build();
launchAWSCredentialsWithElasticsearchSettingsTest(repositorySettings, settings, "repository_key", "repository_secret");
- assertWarnings("[" + S3Repository.Repository.KEY_SETTING.getKey() + "] setting was deprecated",
- "[" + S3Repository.Repository.SECRET_SETTING.getKey() + "] setting was deprecated");
+ assertSettingDeprecations(S3Repository.Repository.KEY_SETTING, S3Repository.Repository.SECRET_SETTING);
}
public void testAWSCredentialsWithElasticsearchAwsAndS3AndRepositoriesSettingsAndRepositorySettingsBackcompat() {
@@ -170,8 +167,7 @@ public class AwsS3ServiceImplTests extends ESTestCase {
.put(S3Repository.Repositories.SECRET_SETTING.getKey(), "repositories_secret")
.build();
launchAWSCredentialsWithElasticsearchSettingsTest(repositorySettings, settings, "repository_key", "repository_secret");
- assertWarnings("[" + S3Repository.Repository.KEY_SETTING.getKey() + "] setting was deprecated",
- "[" + S3Repository.Repository.SECRET_SETTING.getKey() + "] setting was deprecated");
+ assertSettingDeprecations(S3Repository.Repository.KEY_SETTING, S3Repository.Repository.SECRET_SETTING);
}
protected void launchAWSCredentialsWithElasticsearchSettingsTest(Settings singleRepositorySettings, Settings settings,
@@ -215,13 +211,14 @@ public class AwsS3ServiceImplTests extends ESTestCase {
.build();
launchAWSConfigurationTest(settings, Settings.EMPTY, Protocol.HTTP, "aws_proxy_host", 8080, "aws_proxy_username",
"aws_proxy_password", "AWS3SignerType", 3, false, 10000);
- assertWarnings("[" + AwsS3Service.PROXY_USERNAME_SETTING.getKey() + "] setting was deprecated",
- "[" + AwsS3Service.PROXY_PASSWORD_SETTING.getKey() + "] setting was deprecated",
- "[" + AwsS3Service.PROTOCOL_SETTING.getKey() + "] setting was deprecated",
- "[" + AwsS3Service.PROXY_HOST_SETTING.getKey() + "] setting was deprecated",
- "[" + AwsS3Service.PROXY_PORT_SETTING.getKey() + "] setting was deprecated",
- "[" + AwsS3Service.SIGNER_SETTING.getKey() + "] setting was deprecated",
- "[" + AwsS3Service.READ_TIMEOUT.getKey() + "] setting was deprecated");
+ assertSettingDeprecations(
+ AwsS3Service.PROXY_USERNAME_SETTING,
+ AwsS3Service.PROXY_PASSWORD_SETTING,
+ AwsS3Service.PROTOCOL_SETTING,
+ AwsS3Service.PROXY_HOST_SETTING,
+ AwsS3Service.PROXY_PORT_SETTING,
+ AwsS3Service.SIGNER_SETTING,
+ AwsS3Service.READ_TIMEOUT);
}
public void testAWSConfigurationWithAwsAndS3SettingsBackcompat() {
@@ -243,20 +240,21 @@ public class AwsS3ServiceImplTests extends ESTestCase {
.build();
launchAWSConfigurationTest(settings, Settings.EMPTY, Protocol.HTTPS, "s3_proxy_host", 8081, "s3_proxy_username",
"s3_proxy_password", "NoOpSignerType", 3, false, 10000);
- assertWarnings("[" + AwsS3Service.PROXY_USERNAME_SETTING.getKey() + "] setting was deprecated",
- "[" + AwsS3Service.PROXY_PASSWORD_SETTING.getKey() + "] setting was deprecated",
- "[" + AwsS3Service.PROTOCOL_SETTING.getKey() + "] setting was deprecated",
- "[" + AwsS3Service.PROXY_HOST_SETTING.getKey() + "] setting was deprecated",
- "[" + AwsS3Service.PROXY_PORT_SETTING.getKey() + "] setting was deprecated",
- "[" + AwsS3Service.SIGNER_SETTING.getKey() + "] setting was deprecated",
- "[" + AwsS3Service.READ_TIMEOUT.getKey() + "] setting was deprecated",
- "[" + AwsS3Service.CLOUD_S3.PROXY_USERNAME_SETTING.getKey() + "] setting was deprecated",
- "[" + AwsS3Service.CLOUD_S3.PROXY_PASSWORD_SETTING.getKey() + "] setting was deprecated",
- "[" + AwsS3Service.CLOUD_S3.PROTOCOL_SETTING.getKey() + "] setting was deprecated",
- "[" + AwsS3Service.CLOUD_S3.PROXY_HOST_SETTING.getKey() + "] setting was deprecated",
- "[" + AwsS3Service.CLOUD_S3.PROXY_PORT_SETTING.getKey() + "] setting was deprecated",
- "[" + AwsS3Service.CLOUD_S3.SIGNER_SETTING.getKey() + "] setting was deprecated",
- "[" + AwsS3Service.CLOUD_S3.READ_TIMEOUT.getKey() + "] setting was deprecated");
+ assertSettingDeprecations(
+ AwsS3Service.PROXY_USERNAME_SETTING,
+ AwsS3Service.PROXY_PASSWORD_SETTING,
+ AwsS3Service.PROTOCOL_SETTING,
+ AwsS3Service.PROXY_HOST_SETTING,
+ AwsS3Service.PROXY_PORT_SETTING,
+ AwsS3Service.SIGNER_SETTING,
+ AwsS3Service.READ_TIMEOUT,
+ AwsS3Service.CLOUD_S3.PROXY_USERNAME_SETTING,
+ AwsS3Service.CLOUD_S3.PROXY_PASSWORD_SETTING,
+ AwsS3Service.CLOUD_S3.PROTOCOL_SETTING,
+ AwsS3Service.CLOUD_S3.PROXY_HOST_SETTING,
+ AwsS3Service.CLOUD_S3.PROXY_PORT_SETTING,
+ AwsS3Service.CLOUD_S3.SIGNER_SETTING,
+ AwsS3Service.CLOUD_S3.READ_TIMEOUT);
}
public void testGlobalMaxRetries() {
@@ -338,13 +336,13 @@ public class AwsS3ServiceImplTests extends ESTestCase {
public void testEndpointSettingBackcompat() {
assertEndpoint(generateRepositorySettings("repository_key", "repository_secret", "repository.endpoint", null),
Settings.EMPTY, "repository.endpoint");
- assertWarnings("[" + S3Repository.Repository.ENDPOINT_SETTING.getKey() + "] setting was deprecated");
+ assertSettingDeprecations(S3Repository.Repository.ENDPOINT_SETTING);
Settings settings = Settings.builder()
.put(S3Repository.Repositories.ENDPOINT_SETTING.getKey(), "repositories.endpoint")
.build();
assertEndpoint(generateRepositorySettings("repository_key", "repository_secret", null, null), settings,
"repositories.endpoint");
- assertWarnings("[" + S3Repository.Repositories.ENDPOINT_SETTING.getKey() + "] setting was deprecated");
+ assertSettingDeprecations(S3Repository.Repositories.ENDPOINT_SETTING);
}
private void assertEndpoint(Settings repositorySettings, Settings settings,
diff --git a/plugins/repository-s3/src/test/java/org/elasticsearch/repositories/s3/S3RepositoryTests.java b/plugins/repository-s3/src/test/java/org/elasticsearch/repositories/s3/S3RepositoryTests.java
index 79fc453e0ed..f20c2a7ad30 100644
--- a/plugins/repository-s3/src/test/java/org/elasticsearch/repositories/s3/S3RepositoryTests.java
+++ b/plugins/repository-s3/src/test/java/org/elasticsearch/repositories/s3/S3RepositoryTests.java
@@ -19,8 +19,6 @@
package org.elasticsearch.repositories.s3;
-import java.io.IOException;
-
import com.amazonaws.services.s3.AbstractAmazonS3;
import com.amazonaws.services.s3.AmazonS3;
import org.elasticsearch.cloud.aws.AwsS3Service;
@@ -35,6 +33,8 @@ import org.elasticsearch.repositories.RepositoryException;
import org.elasticsearch.test.ESTestCase;
import org.hamcrest.Matchers;
+import java.io.IOException;
+
import static org.elasticsearch.repositories.s3.S3Repository.Repositories;
import static org.elasticsearch.repositories.s3.S3Repository.Repository;
import static org.elasticsearch.repositories.s3.S3Repository.getValue;
@@ -78,8 +78,7 @@ public class S3RepositoryTests extends ESTestCase {
getValue(Settings.EMPTY, globalSettings, Repository.KEY_SETTING, Repositories.KEY_SETTING));
assertEquals(new SecureString("".toCharArray()),
getValue(Settings.EMPTY, Settings.EMPTY, Repository.KEY_SETTING, Repositories.KEY_SETTING));
- assertWarnings("[" + Repository.KEY_SETTING.getKey() + "] setting was deprecated",
- "[" + Repositories.KEY_SETTING.getKey() + "] setting was deprecated");
+ assertSettingDeprecations(Repository.KEY_SETTING, Repositories.KEY_SETTING);
}
public void testInvalidChunkBufferSizeSettings() throws IOException {
diff --git a/test/framework/src/main/java/org/elasticsearch/test/ESTestCase.java b/test/framework/src/main/java/org/elasticsearch/test/ESTestCase.java
index 633a04f5f60..1a349ff0ef2 100644
--- a/test/framework/src/main/java/org/elasticsearch/test/ESTestCase.java
+++ b/test/framework/src/main/java/org/elasticsearch/test/ESTestCase.java
@@ -59,6 +59,7 @@ import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.Writeable;
import org.elasticsearch.common.logging.DeprecationLogger;
import org.elasticsearch.common.logging.Loggers;
+import org.elasticsearch.common.settings.Setting;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.TransportAddress;
import org.elasticsearch.common.util.MockBigArrays;
@@ -134,10 +135,8 @@ import java.util.stream.Collectors;
import static java.util.Collections.emptyList;
import static java.util.Collections.singletonList;
import static org.elasticsearch.common.util.CollectionUtils.arrayAsArrayList;
-import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.empty;
import static org.hamcrest.Matchers.equalTo;
-import static org.hamcrest.Matchers.hasItem;
/**
* Base testcase for randomized unit testing with Elasticsearch
@@ -297,21 +296,33 @@ public abstract class ESTestCase extends LuceneTestCase {
//Check that there are no unaccounted warning headers. These should be checked with {@link #assertWarnings(String...)} in the
//appropriate test
try {
- final List warnings = threadContext.getResponseHeaders().get(DeprecationLogger.WARNING_HEADER);
+ final List warnings = threadContext.getResponseHeaders().get("Warning");
assertNull("unexpected warning headers", warnings);
} finally {
resetDeprecationLogger();
}
}
+ protected final void assertSettingDeprecations(Setting... settings) {
+ assertWarnings(
+ Arrays
+ .stream(settings)
+ .map(Setting::getKey)
+ .map(k -> "[" + k + "] setting was deprecated in Elasticsearch and will be removed in a future release! " +
+ "See the breaking changes documentation for the next major version.")
+ .toArray(String[]::new));
+ }
+
protected final void assertWarnings(String... expectedWarnings) {
if (enableWarningsCheck() == false) {
throw new IllegalStateException("unable to check warning headers if the test is not set to do so");
}
try {
- final List actualWarnings = threadContext.getResponseHeaders().get(DeprecationLogger.WARNING_HEADER);
+ final List actualWarnings = threadContext.getResponseHeaders().get("Warning");
+ final Set actualWarningValues =
+ actualWarnings.stream().map(DeprecationLogger::extractWarningValueFromWarningHeader).collect(Collectors.toSet());
for (String msg : expectedWarnings) {
- assertThat(actualWarnings, hasItem(containsString(msg)));
+ assertTrue(actualWarningValues.contains(DeprecationLogger.escape(msg)));
}
assertEquals("Expected " + expectedWarnings.length + " warnings but found " + actualWarnings.size() + "\nExpected: "
+ Arrays.asList(expectedWarnings) + "\nActual: " + actualWarnings,
diff --git a/test/framework/src/main/java/org/elasticsearch/test/rest/yaml/section/DoSection.java b/test/framework/src/main/java/org/elasticsearch/test/rest/yaml/section/DoSection.java
index 744b52303b5..5eb92220d90 100644
--- a/test/framework/src/main/java/org/elasticsearch/test/rest/yaml/section/DoSection.java
+++ b/test/framework/src/main/java/org/elasticsearch/test/rest/yaml/section/DoSection.java
@@ -16,12 +16,14 @@
* specific language governing permissions and limitations
* under the License.
*/
+
package org.elasticsearch.test.rest.yaml.section;
import org.apache.logging.log4j.Logger;
import org.elasticsearch.common.ParsingException;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.collect.Tuple;
+import org.elasticsearch.common.logging.DeprecationLogger;
import org.elasticsearch.common.logging.Loggers;
import org.elasticsearch.common.xcontent.NamedXContentRegistry;
import org.elasticsearch.common.xcontent.XContentLocation;
@@ -39,10 +41,13 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
+import java.util.regex.Matcher;
+import java.util.stream.Collectors;
import static java.util.Collections.emptyList;
import static java.util.Collections.unmodifiableList;
import static org.elasticsearch.common.collect.Tuple.tuple;
+import static org.elasticsearch.common.logging.DeprecationLogger.WARNING_HEADER_PATTERN;
import static org.elasticsearch.test.hamcrest.RegexMatcher.matches;
import static org.hamcrest.Matchers.allOf;
import static org.hamcrest.Matchers.equalTo;
@@ -247,33 +252,48 @@ public class DoSection implements ExecutableSection {
/**
* Check that the response contains only the warning headers that we expect.
*/
- void checkWarningHeaders(List warningHeaders) {
- StringBuilder failureMessage = null;
+ void checkWarningHeaders(final List warningHeaders) {
+ final List unexpected = new ArrayList<>();
+ final List unmatched = new ArrayList<>();
+ final List missing = new ArrayList<>();
// LinkedHashSet so that missing expected warnings come back in a predictable order which is nice for testing
- Set expected = new LinkedHashSet<>(expectedWarningHeaders);
- for (String header : warningHeaders) {
- if (expected.remove(header)) {
- // Was expected, all good.
- continue;
- }
- if (failureMessage == null) {
- failureMessage = new StringBuilder("got unexpected warning headers [");
- }
- failureMessage.append('\n').append(header);
- }
- if (false == expected.isEmpty()) {
- if (failureMessage == null) {
- failureMessage = new StringBuilder();
+ final Set expected =
+ new LinkedHashSet<>(expectedWarningHeaders.stream().map(DeprecationLogger::escape).collect(Collectors.toList()));
+ for (final String header : warningHeaders) {
+ final Matcher matcher = WARNING_HEADER_PATTERN.matcher(header);
+ final boolean matches = matcher.matches();
+ if (matches) {
+ final String message = matcher.group(1);
+ if (expected.remove(message) == false) {
+ unexpected.add(header);
+ }
} else {
- failureMessage.append("\n] ");
- }
- failureMessage.append("didn't get expected warning headers [");
- for (String header : expected) {
- failureMessage.append('\n').append(header);
+ unmatched.add(header);
}
}
- if (failureMessage != null) {
- fail(failureMessage + "\n]");
+ if (expected.isEmpty() == false) {
+ for (final String header : expected) {
+ missing.add(header);
+ }
+ }
+
+ if (unexpected.isEmpty() == false || unmatched.isEmpty() == false || missing.isEmpty() == false) {
+ final StringBuilder failureMessage = new StringBuilder();
+ appendBadHeaders(failureMessage, unexpected, "got unexpected warning header" + (unexpected.size() > 1 ? "s" : ""));
+ appendBadHeaders(failureMessage, unmatched, "got unmatched warning header" + (unmatched.size() > 1 ? "s" : ""));
+ appendBadHeaders(failureMessage, missing, "did not get expected warning header" + (missing.size() > 1 ? "s" : ""));
+ fail(failureMessage.toString());
+ }
+
+ }
+
+ private void appendBadHeaders(final StringBuilder sb, final List headers, final String message) {
+ if (headers.isEmpty() == false) {
+ sb.append(message).append(" [\n");
+ for (final String header : headers) {
+ sb.append("\t").append(header).append("\n");
+ }
+ sb.append("]\n");
}
}
diff --git a/test/framework/src/test/java/org/elasticsearch/test/rest/yaml/section/DoSectionTests.java b/test/framework/src/test/java/org/elasticsearch/test/rest/yaml/section/DoSectionTests.java
index 463e71341bb..2ff0f56d2b3 100644
--- a/test/framework/src/test/java/org/elasticsearch/test/rest/yaml/section/DoSectionTests.java
+++ b/test/framework/src/test/java/org/elasticsearch/test/rest/yaml/section/DoSectionTests.java
@@ -19,6 +19,9 @@
package org.elasticsearch.test.rest.yaml.section;
+import org.elasticsearch.Version;
+import org.elasticsearch.common.hash.MessageDigests;
+import org.elasticsearch.common.logging.DeprecationLogger;
import org.elasticsearch.common.xcontent.XContent;
import org.elasticsearch.common.xcontent.XContentLocation;
import org.elasticsearch.common.xcontent.XContentParser;
@@ -26,6 +29,7 @@ import org.elasticsearch.common.xcontent.yaml.YamlXContent;
import org.hamcrest.MatcherAssert;
import java.io.IOException;
+import java.io.UnsupportedEncodingException;
import java.util.Arrays;
import java.util.Map;
@@ -37,39 +41,80 @@ import static org.hamcrest.Matchers.notNullValue;
import static org.hamcrest.Matchers.nullValue;
public class DoSectionTests extends AbstractClientYamlTestFragmentParserTestCase {
+
public void testWarningHeaders() throws IOException {
- DoSection section = new DoSection(new XContentLocation(1, 1));
+ {
+ final DoSection section = new DoSection(new XContentLocation(1, 1));
- // No warning headers doesn't throw an exception
- section.checkWarningHeaders(emptyList());
+ // No warning headers doesn't throw an exception
+ section.checkWarningHeaders(emptyList());
+ }
+ final String testHeader = DeprecationLogger.formatWarning("test");
+ final String anotherHeader = DeprecationLogger.formatWarning("another");
+ final String someMoreHeader = DeprecationLogger.formatWarning("some more");
+ final String catHeader = DeprecationLogger.formatWarning("cat");
// Any warning headers fail
- AssertionError e = expectThrows(AssertionError.class, () -> section.checkWarningHeaders(singletonList("test")));
- assertEquals("got unexpected warning headers [\ntest\n]", e.getMessage());
- e = expectThrows(AssertionError.class, () -> section.checkWarningHeaders(Arrays.asList("test", "another", "some more")));
- assertEquals("got unexpected warning headers [\ntest\nanother\nsome more\n]", e.getMessage());
+ {
+ final DoSection section = new DoSection(new XContentLocation(1, 1));
+
+ final AssertionError one = expectThrows(AssertionError.class, () -> section.checkWarningHeaders(singletonList(testHeader)));
+ assertEquals("got unexpected warning header [\n\t" + testHeader + "\n]\n", one.getMessage());
+
+ final AssertionError multiple =
+ expectThrows(
+ AssertionError.class,
+ () -> section.checkWarningHeaders(Arrays.asList(testHeader, anotherHeader, someMoreHeader)));
+ assertEquals(
+ "got unexpected warning headers [\n\t" +
+ testHeader + "\n\t" +
+ anotherHeader + "\n\t" +
+ someMoreHeader + "\n]\n",
+ multiple.getMessage());
+ }
// But not when we expect them
- section.setExpectedWarningHeaders(singletonList("test"));
- section.checkWarningHeaders(singletonList("test"));
- section.setExpectedWarningHeaders(Arrays.asList("test", "another", "some more"));
- section.checkWarningHeaders(Arrays.asList("test", "another", "some more"));
+ {
+ final DoSection section = new DoSection(new XContentLocation(1, 1));
+ section.setExpectedWarningHeaders(singletonList("test"));
+ section.checkWarningHeaders(singletonList(testHeader));
+ }
+ {
+ final DoSection section = new DoSection(new XContentLocation(1, 1));
+ section.setExpectedWarningHeaders(Arrays.asList("test", "another", "some more"));
+ section.checkWarningHeaders(Arrays.asList(testHeader, anotherHeader, someMoreHeader));
+ }
// But if you don't get some that you did expect, that is an error
- section.setExpectedWarningHeaders(singletonList("test"));
- e = expectThrows(AssertionError.class, () -> section.checkWarningHeaders(emptyList()));
- assertEquals("didn't get expected warning headers [\ntest\n]", e.getMessage());
- section.setExpectedWarningHeaders(Arrays.asList("test", "another", "some more"));
- e = expectThrows(AssertionError.class, () -> section.checkWarningHeaders(emptyList()));
- assertEquals("didn't get expected warning headers [\ntest\nanother\nsome more\n]", e.getMessage());
- e = expectThrows(AssertionError.class, () -> section.checkWarningHeaders(Arrays.asList("test", "some more")));
- assertEquals("didn't get expected warning headers [\nanother\n]", e.getMessage());
+ {
+ final DoSection section = new DoSection(new XContentLocation(1, 1));
+ section.setExpectedWarningHeaders(singletonList("test"));
+ final AssertionError e = expectThrows(AssertionError.class, () -> section.checkWarningHeaders(emptyList()));
+ assertEquals("did not get expected warning header [\n\ttest\n]\n", e.getMessage());
+ }
+ {
+ final DoSection section = new DoSection(new XContentLocation(1, 1));
+ section.setExpectedWarningHeaders(Arrays.asList("test", "another", "some more"));
+
+ final AssertionError multiple = expectThrows(AssertionError.class, () -> section.checkWarningHeaders(emptyList()));
+ assertEquals("did not get expected warning headers [\n\ttest\n\tanother\n\tsome more\n]\n", multiple.getMessage());
+
+ final AssertionError one =
+ expectThrows(AssertionError.class, () -> section.checkWarningHeaders(Arrays.asList(testHeader, someMoreHeader)));
+ assertEquals("did not get expected warning header [\n\tanother\n]\n", one.getMessage());
+ }
// It is also an error if you get some warning you want and some you don't want
- section.setExpectedWarningHeaders(Arrays.asList("test", "another", "some more"));
- e = expectThrows(AssertionError.class, () -> section.checkWarningHeaders(Arrays.asList("test", "cat")));
- assertEquals("got unexpected warning headers [\ncat\n] didn't get expected warning headers [\nanother\nsome more\n]",
- e.getMessage());
+ {
+ final DoSection section = new DoSection(new XContentLocation(1, 1));
+ section.setExpectedWarningHeaders(Arrays.asList("test", "another", "some more"));
+ final AssertionError e =
+ expectThrows(AssertionError.class, () -> section.checkWarningHeaders(Arrays.asList(testHeader, catHeader)));
+ assertEquals("got unexpected warning header [\n\t" +
+ catHeader + "\n]\n" +
+ "did not get expected warning headers [\n\tanother\n\tsome more\n]\n",
+ e.getMessage());
+ }
}
public void testParseDoSectionNoBody() throws Exception {