org.elasticsearch.test.rest.Stash Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of framework Show documentation
Show all versions of framework Show documentation
Elasticsearch subproject :test:framework
The newest version!
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
package org.elasticsearch.test.rest;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.elasticsearch.common.Strings;
import org.elasticsearch.xcontent.ToXContentFragment;
import org.elasticsearch.xcontent.XContentBuilder;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Allows to cache the last obtained test response and or part of it within variables
* 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 PATH = Pattern.compile("\\$_path");
private static final Logger logger = LogManager.getLogger(Stash.class);
public static final Stash EMPTY = new Stash();
private final Map stash = new HashMap<>();
private final ObjectPath stashObjectPath = new ObjectPath(stash);
/**
* Allows to saved a specific field in the stash as key-value pair
*/
public void stashValue(String key, Object value) {
logger.trace("stashing [{}]=[{}]", key, value);
Object old = stash.put(key, value);
if (old != null && old != value) {
logger.trace("replaced stashed value [{}] with same key [{}]", old, key);
}
}
/**
* Clears the previously stashed values
*/
public void clear() {
stash.clear();
}
/**
* Tells whether a particular key needs to be looked up in the stash based on its name.
* Returns true if the string representation of the key starts with "$", false otherwise
* The stash contains fields eventually extracted from previous responses that can be reused
* as arguments for following requests (e.g. scroll_id)
*/
public boolean containsStashedValue(Object key) {
if (key == null || false == key instanceof CharSequence) {
return false;
}
String stashKey = key.toString();
if (false == Strings.hasLength(stashKey)) {
return false;
}
if (stashKey.startsWith("$")) {
return true;
}
return EXTENDED_KEY.matcher(stashKey).find();
}
/**
* Retrieves a value from the current stash.
* The stash contains fields eventually extracted from previous responses that can be reused
* as arguments for following requests (e.g. scroll_id)
*/
public Object getValue(String key) throws IOException {
if (key.charAt(0) == '$' && key.charAt(1) != '{') {
return unstash(key.substring(1));
}
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,
* very cheap so that should not be a problem.
*/
StringBuffer result = new StringBuffer(key.length());
if (false == matcher.find()) {
throw new IllegalArgumentException("Doesn't contain any stash keys [" + key + "]");
}
do {
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();
}
private Object unstash(String key) throws IOException {
Object stashedValue = stashObjectPath.evaluate(key, this);
if (stashedValue == null) {
throw new IllegalArgumentException("stashed value not found for key [" + key + "]");
}
return stashedValue;
}
/**
* Goes recursively against each map entry and replaces any string value starting with "$" with its
* corresponding value retrieved from the stash
*/
@SuppressWarnings("unchecked") // Safe because we check that all the map keys are string in unstashObject
public Map replaceStashedValues(Map map) throws IOException {
return (Map) unstashObject(new ArrayList<>(), map);
}
private Object unstashObject(List