From e12f50a148276fd4c6093cf87442e8162000dba9 Mon Sep 17 00:00:00 2001 From: Ian Moore Date: Thu, 12 Jan 2017 23:18:16 +0000 Subject: [PATCH] parameter substitution using values from config --- README.md | 1 + api/src/main/resources/reference.conf | 16 ++++++- .../substeps/model/ParentStep.java | 4 +- .../com/technophobia/substeps/model/Util.java | 46 +++++++++++++++++-- .../runner/ExecutionNodeRunnerTest.java | 16 ++++++- core/src/test/resources/localhost.conf | 6 +++ .../test/scala/org/substeps/ConfigTest.scala | 7 +++ 7 files changed, 87 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index c8e81582..fbe67bab 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,7 @@ Requirements * Corrected the path to the screenshots in the report data and the final report * Replaced Apache config with [Typesafe Config](https://github.com/typesafehub/config) - similar functionality but provides better nesting of properties, variable substitution * Added System property switch to use original properties files over new .conf files (`-Dsubsteps.use.dot.properties=true`) +* Enable any parameters to be substituted with values from config - user ${config.expression}. Delimitters can be specified and Charset conversion too, see core-api reference.conf for details 1.0.3 ----- diff --git a/api/src/main/resources/reference.conf b/api/src/main/resources/reference.conf index 54e7a1e5..1d3f9e3f 100644 --- a/api/src/main/resources/reference.conf +++ b/api/src/main/resources/reference.conf @@ -9,4 +9,18 @@ log.unused.uncalled=false report.data.pretty.print=false # the base directory under which report data will be written -report.data.base.dir=target \ No newline at end of file +report.data.base.dir=target + +parameter{ + substitution{ + enabled=true + start="${" + end="}" + normalizeValue=false + normalize{ + from="ISO-8859-1" + to="UTF-8" + } + + } +} \ No newline at end of file diff --git a/core/src/main/java/com/technophobia/substeps/model/ParentStep.java b/core/src/main/java/com/technophobia/substeps/model/ParentStep.java index 94ccc690..052dda7b 100644 --- a/core/src/main/java/com/technophobia/substeps/model/ParentStep.java +++ b/core/src/main/java/com/technophobia/substeps/model/ParentStep.java @@ -75,7 +75,7 @@ public void initialiseParamValues(final Step step) { final HashMap map = new HashMap(); final String[] paramValues = Util.getArgs(this.parent.getPattern(), - step.getLine(), null); + step.getLine(), null, Configuration.INSTANCE.getConfig()); if (paramValues != null) { for (int i = 0; i < paramValues.length; i++) { @@ -98,7 +98,7 @@ public void initialiseParamValues(final int lineNumber, final String line, Strin log.debug("initialiseParamValues with line: " + line); final String[] paramValues = Util.getArgs(this.parent.getPattern(), - line, keywordPrecedence); + line, keywordPrecedence, Configuration.INSTANCE.getConfig()); if (paramValues != null) { diff --git a/core/src/main/java/com/technophobia/substeps/model/Util.java b/core/src/main/java/com/technophobia/substeps/model/Util.java index 031c564a..fe62417b 100644 --- a/core/src/main/java/com/technophobia/substeps/model/Util.java +++ b/core/src/main/java/com/technophobia/substeps/model/Util.java @@ -18,12 +18,15 @@ */ package com.technophobia.substeps.model; +import com.technophobia.substeps.model.exception.SubstepsRuntimeException; import com.technophobia.substeps.model.parameter.Converter; import com.technophobia.substeps.model.parameter.ConverterFactory; +import com.typesafe.config.Config; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.List; import java.util.regex.Matcher; @@ -35,15 +38,50 @@ public final class Util { private static final Logger log = LoggerFactory.getLogger(Util.class); + private static final boolean substituteParameters = Configuration.INSTANCE.getConfig().getBoolean("parameter.substitution.enabled"); + private static final String startDelimiter = Configuration.INSTANCE.getConfig().getString("parameter.substitution.start"); + private static final String endDelimiter = Configuration.INSTANCE.getConfig().getString("parameter.substitution.end"); + + private static final boolean normalizeValues = Configuration.INSTANCE.getConfig().getBoolean("parameter.substitution.normalizeValue"); + private static final String normalizeFrom = Configuration.INSTANCE.getConfig().getString("parameter.substitution.normalize.from"); + private static final String normalizeTo = Configuration.INSTANCE.getConfig().getString("parameter.substitution.normalize.to"); + + private Util() { // no op } + public static String substituteValues(String src) { + + + if (src != null && substituteParameters && src.startsWith(startDelimiter)){ + String key = StringUtils.stripStart(StringUtils.stripEnd(src, endDelimiter), startDelimiter); + String substitute = Configuration.INSTANCE.getString(key); + if (substitute == null){ + throw new SubstepsRuntimeException("Failed to resolve property " + src + " to be substituted "); + } + String normalizedValue = substitute; + + if (normalizeValues) { + // This part will support the conversion of properties files containing accented characters + try { + normalizedValue = new String(substitute.getBytes(normalizeFrom), normalizeTo); + } catch (UnsupportedEncodingException e) { + log.error("error substituting accented characters", e); + } + } + + return normalizedValue; + } + return src; + } + + // TODO - these two methods are both used - used to be one, but now it's two // - could they be combined ?? - public static String[] getArgs(final String patternString, final String sourceString, final String[] keywordPrecedence) { + public static String[] getArgs(final String patternString, final String sourceString, final String[] keywordPrecedence, Config cfg) { log.debug("Util getArgs String[] with pattern: " + patternString + " and sourceStr: " + sourceString); @@ -74,7 +112,7 @@ public static String[] getArgs(final String patternString, final String sourceSt if (matcher.find()) { for (int i = 1; i <= groupCount; i++) { - final String arg = matcher.group(i); + final String arg = substituteValues(matcher.group(i)); if (arg != null) { if (argsList == null) { @@ -131,8 +169,8 @@ public static List getArgs(final String patternString, final String sour if (argsList == null) { argsList = new ArrayList(); } - - argsList.add(getObjectArg(arg, parameterTypes[argIdx], converterTypes[argIdx])); + String substituted = substituteValues(arg); + argsList.add(getObjectArg(substituted, parameterTypes[argIdx], converterTypes[argIdx])); } argIdx++; diff --git a/core/src/test/java/com/technophobia/substeps/runner/ExecutionNodeRunnerTest.java b/core/src/test/java/com/technophobia/substeps/runner/ExecutionNodeRunnerTest.java index ea39401b..ef69241f 100644 --- a/core/src/test/java/com/technophobia/substeps/runner/ExecutionNodeRunnerTest.java +++ b/core/src/test/java/com/technophobia/substeps/runner/ExecutionNodeRunnerTest.java @@ -31,6 +31,8 @@ import com.technophobia.substeps.runner.setupteardown.SetupAndTearDown; import com.technophobia.substeps.stepimplementations.MockStepImplementations; import com.technophobia.substeps.steps.TestStepImplementations; +import com.typesafe.config.Config; +import com.typesafe.config.ConfigFactory; import org.junit.Assert; import org.junit.Before; import org.junit.Ignore; @@ -700,15 +702,21 @@ protected Map, Object> getImplsCache(final ExecutionNodeRunner runner) @Test public void testArgSubstituion() { + Config cfg = ConfigFactory.load("localhost.conf"); + + String parameterFromConfig = cfg.getString("users.default.name"); + Assert.assertThat(parameterFromConfig, is("bob")); final String srcString1 = "Given a substep that takes one parameter \"src1\""; final String srcString2 = "And a substep that takes one parameter \"src2\""; + final String srcString3 = "And a substep that takes one parameter \"${users.default.name}\""; + final String patternString = "Given a substep that takes one parameter \"([^\"]*)\""; final String[] keywordPrecedence = new String[]{"Given", "And"}; - String[] args1 = Util.getArgs(patternString, srcString1, keywordPrecedence); + String[] args1 = Util.getArgs(patternString, srcString1, keywordPrecedence, cfg); - String[] args2 = Util.getArgs(patternString, srcString2, keywordPrecedence); + String[] args2 = Util.getArgs(patternString, srcString2, keywordPrecedence, cfg); Assert.assertNotNull(args2); Assert.assertThat(args2[0], is("src2")); @@ -716,6 +724,10 @@ public void testArgSubstituion() { Assert.assertNotNull(args1); Assert.assertThat(args1[0], is("src1")); + String[] args3 = Util.getArgs(patternString, srcString3, keywordPrecedence, cfg); + Assert.assertNotNull(args3); + Assert.assertThat(args3[0], is("bob")); + } @Ignore("wip") diff --git a/core/src/test/resources/localhost.conf b/core/src/test/resources/localhost.conf index 0e141b2c..9cbae294 100644 --- a/core/src/test/resources/localhost.conf +++ b/core/src/test/resources/localhost.conf @@ -23,4 +23,10 @@ some.accesskey=${?ACCESS_KEY} some.val="https://"${some.username}":"${some.accesskey}"@ondemand.saucelabs.com:443/wd/hub" +users{ + default { + name="bob" + } +} + diff --git a/core/src/test/scala/org/substeps/ConfigTest.scala b/core/src/test/scala/org/substeps/ConfigTest.scala index d273746c..21513c91 100644 --- a/core/src/test/scala/org/substeps/ConfigTest.scala +++ b/core/src/test/scala/org/substeps/ConfigTest.scala @@ -8,6 +8,8 @@ import com.typesafe.config.ConfigFactory */ class ConfigTest extends FunSuite with Matchers{ + + test("test property substitution with env vars in conf files") { val configVal: String = runTest @@ -43,7 +45,12 @@ class ConfigTest extends FunSuite with Matchers{ val config = ConfigFactory.load(s"localhost.$ext") + println("cfg: " + + config.root().render()) + val configVal = config.getString("some.val") + configVal + } }