Ver Fonte

Test: handle escape stash reference (#78020)

You can write `foo${response.hits.hits.0._score}` in our tests to make a
string that contains `foo<the score of the first hit>`. This is useful
in *places*. But there are other places where we want to generate random
strings and never bump into the stash. We tried to stop this by escaping
the `$` lookup. That's how it works in bash. But we didn't support this
escaping. Now we do. So the string `foo\${bar}` represents the string
`foo${bar}`. No lookups.

Closes #74378
Nik Everett há 4 anos atrás
pai
commit
262fdc09b2

+ 2 - 2
docs/src/test/java/org/elasticsearch/smoketest/DocsClientYamlTestSuiteIT.java

@@ -19,10 +19,10 @@ import org.apache.lucene.util.TimeUnits;
 import org.elasticsearch.Version;
 import org.elasticsearch.client.Request;
 import org.elasticsearch.client.RestClient;
-import org.elasticsearch.common.xcontent.ParseField;
 import org.elasticsearch.common.util.CollectionUtils;
 import org.elasticsearch.common.xcontent.ConstructingObjectParser;
 import org.elasticsearch.common.xcontent.NamedXContentRegistry;
+import org.elasticsearch.common.xcontent.ParseField;
 import org.elasticsearch.common.xcontent.XContentLocation;
 import org.elasticsearch.common.xcontent.XContentParser;
 import org.elasticsearch.common.xcontent.XContentParser.Token;
@@ -267,7 +267,7 @@ public class DocsClientYamlTestSuiteIT extends ESClientYamlSuiteTestCase {
             int maxLength = 15;
             List<String> testText = new ArrayList<>(size);
             for (int i = 0; i < size; i++) {
-                /**
+                /*
                  * Build a string with a few unicode sequences separated by
                  * spaces. The unicode sequences aren't going to be of the same
                  * code page which is a shame because it makes the entire

+ 6 - 3
test/framework/src/main/java/org/elasticsearch/test/rest/yaml/Stash.java

@@ -28,7 +28,7 @@ import java.util.regex.Pattern;
  * that can be used as input values in following requests and assertions.
  */
 public class Stash implements ToXContentFragment {
-    private static final Pattern EXTENDED_KEY = Pattern.compile("\\$\\{([^}]+)\\}");
+    private static final Pattern EXTENDED_KEY = Pattern.compile("(\\\\)?\\$\\{([^}]+)\\}");
     private static final Pattern PATH = Pattern.compile("\\$_path");
 
     private static final Logger logger = LogManager.getLogger(Stash.class);
@@ -87,7 +87,8 @@ public class Stash implements ToXContentFragment {
         }
         Matcher matcher = EXTENDED_KEY.matcher(key);
         /*
-         * String*Buffer* because that is what the Matcher API takes. In modern versions of java the uncontended synchronization is very,
+         * String*Buffer* because that is what the Matcher API takes. In
+         * modern versions of java the uncontended synchronization is very,
          * very cheap so that should not be a problem.
          */
         StringBuffer result = new StringBuffer(key.length());
@@ -95,7 +96,9 @@ public class Stash implements ToXContentFragment {
             throw new IllegalArgumentException("Doesn't contain any stash keys [" + key + "]");
         }
         do {
-            matcher.appendReplacement(result, Matcher.quoteReplacement(unstash(matcher.group(1)).toString()));
+            boolean unstash = matcher.group(1) == null;
+            String value = unstash ? unstash(matcher.group(2)).toString() : matcher.group(0).substring(1);
+            matcher.appendReplacement(result, Matcher.quoteReplacement(value));
         } while (matcher.find());
         matcher.appendTail(result);
         return result.toString();

+ 13 - 0
test/framework/src/test/java/org/elasticsearch/test/rest/yaml/StashTests.java

@@ -15,6 +15,8 @@ import java.util.Arrays;
 import java.util.HashMap;
 import java.util.Map;
 
+import static io.github.nik9000.mapmatcher.MapMatcher.assertMap;
+import static io.github.nik9000.mapmatcher.MapMatcher.matchesMap;
 import static java.util.Collections.singletonMap;
 import static org.hamcrest.Matchers.not;
 import static org.hamcrest.Matchers.sameInstance;
@@ -155,4 +157,15 @@ public class StashTests extends ESTestCase {
         assertEquals(expected, actual);
         assertThat(actual, not(sameInstance(map)));
     }
+
+    public void testEscapeExtendedKey() throws IOException {
+        Stash stash = new Stash();
+
+        Map<String, Object> map = new HashMap<>();
+        map.put("key", singletonMap("a", "foo\\${bar}"));
+
+        Map<String, Object> actual = stash.replaceStashedValues(map);
+        assertMap(actual, matchesMap().entry("key", matchesMap().entry("a", "foo${bar}")));
+        assertThat(actual, not(sameInstance(map)));
+    }
 }