From a8929042f99eacbb7d4e9d5e68f0f434eb48269a Mon Sep 17 00:00:00 2001 From: Jonathan Shook Date: Mon, 11 Oct 2021 17:23:23 -0500 Subject: [PATCH] extend NBEnvironment tokens to other data sources --- .../io/nosqlbench/nb/api/NBEnvironment.java | 63 +++++++++++++++---- .../nosqlbench/nb/api/NBEnvironmentTest.java | 11 ++++ 2 files changed, 63 insertions(+), 11 deletions(-) diff --git a/nb-api/src/main/java/io/nosqlbench/nb/api/NBEnvironment.java b/nb-api/src/main/java/io/nosqlbench/nb/api/NBEnvironment.java index 825e2fb14..c18b5d3be 100644 --- a/nb-api/src/main/java/io/nosqlbench/nb/api/NBEnvironment.java +++ b/nb-api/src/main/java/io/nosqlbench/nb/api/NBEnvironment.java @@ -1,6 +1,7 @@ package io.nosqlbench.nb.api; import io.nosqlbench.nb.api.errors.BasicError; +import io.nosqlbench.nb.api.metadata.SessionNamer; import org.apache.logging.log4j.Logger; import java.util.*; @@ -46,11 +47,11 @@ public class NBEnvironment { private final LinkedHashMap references = new LinkedHashMap<>(); private final static Map envToProp = Map.of( - "PWD", "user.dir", - "HOME", "user.home", - "USERNAME", "user.name", // Win* - "USER", "user.name", // *n*x - "LOGNAME", "user.name" // *n*x + "PWD", "user.dir", + "HOME", "user.home", + "USERNAME", "user.name", // Win* + "USER", "user.name", // *n*x + "LOGNAME", "user.name" // *n*x ); public NBEnvironment resetRefs() { @@ -61,7 +62,7 @@ public class NBEnvironment { public void put(String propname, String value) { if (envToProp.containsKey(propname)) { throw new RuntimeException("The property you are changing should be considered immutable in this " + - "process: '" + propname + "'"); + "process: '" + propname + "'"); } if (references.containsKey(propname)) { if (references.get(propname).equals(value)) { @@ -70,8 +71,8 @@ public class NBEnvironment { } } else { throw new BasicError("Changing already referenced property '" + propname + "' from \n" + - "'" + references.get(propname) + "' to '" + value + "' is not supported.\n" + - " (maybe you can change the order of your options to set higher-level parameters first.)"); + "'" + references.get(propname) + "' to '" + value + "' is not supported.\n" + + " (maybe you can change the order of your options to set higher-level parameters first.)"); } } @@ -138,7 +139,7 @@ public class NBEnvironment { String value = getOr(name, null); if (value == null) { throw new BasicError("No variable was found for '" + name + "' in system properties nor in the shell " + - "environment."); + "environment."); } return value; } @@ -185,8 +186,8 @@ public class NBEnvironment { return Optional.of(sb.toString()); } - public List interpolate(CharSequence delim, String combined) { - String[] split = combined.split(delim.toString()); + public List interpolateEach(CharSequence delim, String toBeRecombined) { + String[] split = toBeRecombined.split(delim.toString()); List mapped = new ArrayList<>(); for (String pattern : split) { Optional interpolated = interpolate(pattern); @@ -195,4 +196,44 @@ public class NBEnvironment { return mapped; } + /** + * Interpolate system properties, environment variables, time fields, and arbitrary replacement strings + * into a single result. Templates such as {@code /tmp/%d-${testrun}-$System.index-SCENARIO} are supported. + * + *
+ * + * The tokens found in the raw template are interpolated in the following order. + *
    + *
  • Any token which exactly matches one of the keys in the provided map is substituted + * directly as is. No token sigil like '$' is used here, so if you want to support that + * as is, you need to provide the keys in your substitution map as such.
  • + *
  • Any tokens in the form {@code %f} which is supported by the time fields in + * {@link Formatter}
  • are honored and used with the timestamp provided.* + *
  • System Properties: Any token in the form {@code $word.word} will be taken as the name + * of a system property to be substited.
  • + *
  • Environment Variables: Any token in the form {@code $name}
  • will be takens as + * an environment variable to be substituted. + *
+ * + * @param rawtext The template, including any of the supported token forms + * @param millis The timestamp to use for any temporal tokens + * @param map Any additional parameters to interpolate into the template first + * @return Optionally, the interpolated string, as long as all references were qualified. Error + * handling is contextual to the caller -- If not getting a valid result would cause a downstream error, + * an error should likely be thrown. + */ + public final Optional interpolateWithTimestamp(String rawtext, long millis, Map map) { + String result = rawtext; + for (String key : map.keySet()) { + String value = map.get(key); + result = result.replaceAll(Pattern.quote(key), value); + } + result = SessionNamer.format(result, millis); + return interpolate(result); + } + + public final Optional interpolateWithTimestamp(String rawText, long millis) { + return interpolateWithTimestamp(rawText, millis, Map.of()); + } + } diff --git a/nb-api/src/test/java/io/nosqlbench/nb/api/NBEnvironmentTest.java b/nb-api/src/test/java/io/nosqlbench/nb/api/NBEnvironmentTest.java index 9693e4d04..014abb111 100644 --- a/nb-api/src/test/java/io/nosqlbench/nb/api/NBEnvironmentTest.java +++ b/nb-api/src/test/java/io/nosqlbench/nb/api/NBEnvironmentTest.java @@ -2,6 +2,8 @@ package io.nosqlbench.nb.api; import org.junit.jupiter.api.Test; +import java.util.Map; + import static org.assertj.core.api.Assertions.assertThat; public class NBEnvironmentTest { @@ -15,4 +17,13 @@ public class NBEnvironmentTest { assertThat(home1).matches(".+"); } + @Test + public void testInterpolationWithTimestamp() { + NBEnvironment env = new NBEnvironment(); + long millis = 1633964892320L; + String time1 = env.interpolateWithTimestamp("word WOO %td %% end", millis, Map.of("WOO","WOW")).orElse(null); + assertThat(time1).isEqualTo("word WOW 11 % end"); + + } + }