diff --git a/karate-core/src/main/java/com/intuit/karate/FileUtils.java b/karate-core/src/main/java/com/intuit/karate/FileUtils.java index 729023bb6..e01ea48cb 100755 --- a/karate-core/src/main/java/com/intuit/karate/FileUtils.java +++ b/karate-core/src/main/java/com/intuit/karate/FileUtils.java @@ -78,7 +78,7 @@ public class FileUtils { public static final String THIS_COLON = "this:"; public static final String FILE_COLON = "file:"; public static final String SRC_TEST_JAVA = "src/test/java"; - public static final String SRC_TEST_RESOURCES = "src/test/resources"; + public static final String SRC_TEST_RESOURCES = "src/test/resources"; private static final ClassLoader CLASS_LOADER = FileUtils.class.getClassLoader(); private FileUtils() { @@ -323,7 +323,7 @@ public static void writeToFile(File file, byte[] data) { } // try with resources, so will be closed automatically try (FileOutputStream fos = new FileOutputStream(file)) { - fos.write(data); + fos.write(data); } } catch (IOException e) { throw new RuntimeException(e); @@ -452,12 +452,21 @@ public static String toRelativeClassPath(Class clazz) { } public static Path fromRelativeClassPath(String relativePath, ClassLoader cl) { + boolean isFile = isFilePath(relativePath); relativePath = removePrefix(relativePath); - URL url = cl.getResource(relativePath); - if (url == null) { - throw new RuntimeException("file does not exist: " + relativePath); + if (isFile) { + File file = new File(relativePath); + if (!file.exists()) { + throw new RuntimeException("file does not exist: " + relativePath); + } + return file.toPath(); + } else { // classpath + URL url = cl.getResource(relativePath); + if (url == null) { + throw new RuntimeException("file does not exist: " + relativePath); + } + return urlToPath(url, relativePath); } - return urlToPath(url, relativePath); } public static Path fromRelativeClassPath(String relativePath, Path parentPath) { @@ -488,7 +497,7 @@ public static List scanForFeatureFiles(List paths, ClassLoader public static List scanForFeatureFiles(List paths, Class clazz) { if (clazz == null) { - return scanForFeatureFiles(paths, Thread.currentThread().getContextClassLoader()); + return scanForFeatureFiles(paths, ClassLoader.getSystemClassLoader()); } // this resolves paths relative to the passed-in class List list = new ArrayList(); @@ -658,11 +667,11 @@ private static void collectFeatureFiles(URL url, String searchPath, List based and tighter routine for feature files above private static void walkPath(Path root, Set results, Predicate predicate) { Stream stream; @@ -679,10 +688,10 @@ private static void walkPath(Path root, Set results, Predicate pre } catch (IOException e) { // NoSuchFileException LOGGER.trace("unable to walk path: {} - {}", root, e.getMessage()); } - } - + } + private static final Predicate IS_JS_FILE = p -> p != null && p.toString().endsWith(".js"); - + public static Set jsFiles(File baseDir) { Set results = new HashSet(); walkPath(baseDir.toPath().toAbsolutePath(), results, IS_JS_FILE); @@ -702,15 +711,15 @@ public static Set jsFiles(String basePath) { LOGGER.warn("unable to scan for js files at: {}", basePath); } return results; - } - + } + public static InputStream resourceAsStream(String resourcePath) { InputStream is = CLASS_LOADER.getResourceAsStream(resourcePath); if (is == null) { throw new RuntimeException("failed to read: " + resourcePath); } return is; - } + } public static String getBuildDir() { String temp = System.getProperty("karate.output.dir"); diff --git a/karate-core/src/main/java/com/intuit/karate/Resource.java b/karate-core/src/main/java/com/intuit/karate/Resource.java index c83d842bc..75e80edca 100644 --- a/karate-core/src/main/java/com/intuit/karate/Resource.java +++ b/karate-core/src/main/java/com/intuit/karate/Resource.java @@ -46,33 +46,22 @@ public class Resource { private final String relativePath; private final String packageQualifiedName; - public static final Resource EMPTY = new Resource(Paths.get(""), "", -1); - - public static Resource of(Path path, String text) { - return new Resource(path, null, -1) { - final InputStream is = FileUtils.toInputStream(text); - - @Override - public InputStream getStream() { - return is; - } - }; - } - public Resource(File file, String relativePath) { - this(file.toPath(), relativePath, -1); + this(null, file.toPath(), relativePath, -1); } - public Resource(Path path, String relativePath, int line) { + public Resource(ClassLoader cl, Path path, String relativePath, int line) { this.path = path; this.line = line; file = !path.toUri().getScheme().equals("jar"); if (relativePath == null) { - this.relativePath = FileUtils.toRelativeClassPath(path, Thread.currentThread().getContextClassLoader()); - } else { - this.relativePath = relativePath; + if (cl == null) { + cl = ClassLoader.getSystemClassLoader(); + } + relativePath = FileUtils.toRelativeClassPath(path, cl); } - packageQualifiedName = FileUtils.toPackageQualifiedName(this.relativePath); + this.relativePath = relativePath; + packageQualifiedName = FileUtils.toPackageQualifiedName(relativePath); } public Resource(URL url) { @@ -80,21 +69,15 @@ public Resource(URL url) { } public Resource(Path path) { - this(path, null, -1); + this(null, path, null, -1); } public Resource(ClassLoader cl, String relativePath) { - String strippedPath = FileUtils.removePrefix(relativePath); - URL url = cl.getResource(strippedPath); - if (url != null) { - this.path = FileUtils.urlToPath(url, strippedPath); - } else { - this.path = new File(strippedPath).toPath(); - } - this.line = -1; - file = !path.toUri().getScheme().equals("jar"); - this.relativePath = relativePath; - packageQualifiedName = FileUtils.toPackageQualifiedName(relativePath); + this(FileUtils.fromRelativeClassPath(relativePath, cl)); + } + + public Resource(String relativePath) { + this(ClassLoader.getSystemClassLoader(), relativePath); } public String getFileNameWithoutExtension() { @@ -155,4 +138,9 @@ public String toString() { return relativePath; } + public static String relativePathToString(String relativePath) { + Resource resource = new Resource(relativePath); + return resource.getAsString(); + } + } diff --git a/karate-core/src/main/java/com/intuit/karate/core/FeatureParser.java b/karate-core/src/main/java/com/intuit/karate/core/FeatureParser.java index 3f08194df..d5d2ea77a 100644 --- a/karate-core/src/main/java/com/intuit/karate/core/FeatureParser.java +++ b/karate-core/src/main/java/com/intuit/karate/core/FeatureParser.java @@ -64,9 +64,7 @@ public class FeatureParser extends KarateParserBaseListener { private static final List PREFIXES = Arrays.asList("*", "Given", "When", "Then", "And", "But"); public static Feature parse(String relativePath) { - ClassLoader cl = Thread.currentThread().getContextClassLoader(); - Path path = FileUtils.fromRelativeClassPath(relativePath, cl); - return parse(new Resource(path, relativePath, -1)); + return parse(new Resource(relativePath)); } public static Feature parse(File file) { diff --git a/karate-core/src/test/java/com/intuit/karate/FileUtilsTest.java b/karate-core/src/test/java/com/intuit/karate/FileUtilsTest.java index 5b512a6e1..fc38c6f68 100755 --- a/karate-core/src/test/java/com/intuit/karate/FileUtilsTest.java +++ b/karate-core/src/test/java/com/intuit/karate/FileUtilsTest.java @@ -231,7 +231,7 @@ public void testUsingKarateBase() throws Exception { String relativePath = "classpath:demo/jar1/caller.feature"; ClassLoader cl = getJarClassLoader(); Path path = FileUtils.fromRelativeClassPath(relativePath, cl); - Resource resource = new Resource(path, relativePath, -1); + Resource resource = new Resource(cl, path, relativePath, -1); Feature feature = FeatureParser.parse(resource); try { Map map = Runner.runFeature(feature, null, true); diff --git a/karate-core/src/test/java/com/intuit/karate/core/FeatureEditTest.java b/karate-core/src/test/java/com/intuit/karate/core/FeatureEditTest.java index 6adf5e8de..bde8aa12a 100644 --- a/karate-core/src/test/java/com/intuit/karate/core/FeatureEditTest.java +++ b/karate-core/src/test/java/com/intuit/karate/core/FeatureEditTest.java @@ -3,6 +3,7 @@ import com.intuit.karate.FileUtils; import com.intuit.karate.Resource; import java.io.InputStream; +import java.nio.file.Paths; import java.util.List; import org.junit.Test; import static org.junit.Assert.*; @@ -16,22 +17,23 @@ public class FeatureEditTest { private static final Logger logger = LoggerFactory.getLogger(FeatureEditTest.class); - + + public static final Resource EMPTY = new Resource(null, Paths.get(""), "", -1); + private Feature parse(String name) { InputStream is = getClass().getResourceAsStream(name); String text = FileUtils.toString(is); - Resource resource = Resource.EMPTY; - return FeatureParser.parseText(new Feature(resource), text); + return FeatureParser.parseText(new Feature(EMPTY), text); } - + private void printLines(List lines) { int count = lines.size(); for (int i = 0; i < count; i++) { String line = lines.get(i); - logger.trace("{}: {}", i + 1, line); + logger.trace("{}: {}", i + 1, line); } } - + @Test public void testScenario() { Feature feature = parse("scenario.feature"); @@ -41,18 +43,18 @@ public void testScenario() { Background background = feature.getBackground(); Step step = background.getSteps().get(0); assertEquals("def a = 1", step.getText()); - + Scenario scenario = feature.getSections().get(0).getScenario(); - assertFalse(scenario.isOutline()); + assertFalse(scenario.isOutline()); assertEquals(8, scenario.getLine()); // scenario on line 8 List steps = scenario.getSteps(); assertEquals(3, steps.size()); step = steps.get(0); - assertEquals(9, step.getLine()); - step = steps.get(1); - assertEquals(11, step.getLine()); + assertEquals(9, step.getLine()); + step = steps.get(1); + assertEquals(11, step.getLine()); } - + @Test public void testScenarioOutline() { Feature feature = parse("outline.feature"); @@ -63,8 +65,8 @@ public void testScenarioOutline() { assertEquals(4, so.getScenarios().size()); Scenario scenario = so.getScenarios().get(0); assertTrue(scenario.isOutline()); - } - + } + @Test public void testInsert() { Feature feature = parse("scenario.feature"); @@ -73,12 +75,12 @@ public void testInsert() { assertEquals(17, lines.size()); assertEquals(1, feature.getSections().size()); } - + @Test public void testEdit() { Feature feature = parse("scenario.feature"); Step step = feature.getSections().get(0).getScenario().getSteps().get(0); - int line = step.getLine(); + int line = step.getLine(); feature = feature.replaceLines(line, line, "Then assert 2 == 2"); assertEquals(1, feature.getSections().size()); } @@ -99,8 +101,8 @@ public void testMultiLineEditDocString() { assertEquals("Then assert 2 == 2", feature.getLines().get(10)); assertEquals("Then match b == { foo: 'bar'}", feature.getLines().get(11)); assertEquals(1, feature.getSections().size()); - } - + } + @Test public void testMultiLineEditTable() { Feature feature = parse("table.feature"); @@ -115,13 +117,12 @@ public void testMultiLineEditTable() { assertEquals(7, lines.size()); assertEquals("Then assert 2 == 2", feature.getLines().get(3)); assertEquals("* match cats == [{name: 'Bob', age: 2}, {name: 'Wild', age: 4}, {name: 'Nyan', age: 3}]", feature.getLines().get(5)); - } - + } + @Test public void testIdentifyingStepWhichIsAnHttpCall() { String text = "Feature:\nScenario:\n* method post"; - Resource resource = Resource.EMPTY; - Feature feature = FeatureParser.parseText(new Feature(resource), text); + Feature feature = FeatureParser.parseText(new Feature(EMPTY), text); Step step = feature.getSections().get(0).getScenario().getSteps().get(0); logger.debug("step name: '{}'", step.getText()); assertTrue(step.getText().startsWith("method")); diff --git a/karate-core2/src/main/java/com/intuit/karate/match/MatchOperation.java b/karate-core2/src/main/java/com/intuit/karate/match/MatchOperation.java index 01b3da953..f4bc35bdc 100644 --- a/karate-core2/src/main/java/com/intuit/karate/match/MatchOperation.java +++ b/karate-core2/src/main/java/com/intuit/karate/match/MatchOperation.java @@ -227,7 +227,7 @@ private boolean macroEqualsExpected(String expStr) { int closeBracketPos = macro.indexOf(']'); if (closeBracketPos != -1) { // array, match each if (!actual.isList()) { - return fail("actual is not a list or array"); + return fail("actual is not an array"); } if (closeBracketPos > 1) { String bracketContents = macro.substring(1, closeBracketPos); @@ -244,7 +244,7 @@ private boolean macroEqualsExpected(String expStr) { } JsValue jv = jsEngine.eval(sizeExpr); if (!jv.isTrue()) { - return fail("actual array / list size is " + listSize); + return fail("actual array length is " + listSize); } } if (macro.length() > closeBracketPos + 1) { @@ -356,7 +356,7 @@ private boolean actualEqualsExpected() { int actListCount = actList.size(); int expListCount = expList.size(); if (actListCount != expListCount) { - return fail("actual size is not equal to expected size - " + actListCount + ":" + expListCount); + return fail("actual array length is not equal to expected - " + actListCount + ":" + expListCount); } for (int i = 0; i < actListCount; i++) { MatchValue actListValue = new MatchValue(actList.get(i)); @@ -364,7 +364,7 @@ private boolean actualEqualsExpected() { MatchOperation mo = new MatchOperation(context.descend(i), MatchType.EQUALS, actListValue, expListValue); mo.execute(); if (!mo.pass) { - return fail("array / list match failed at index " + i); + return fail("array match failed at index " + i); } } return true; @@ -466,10 +466,10 @@ private boolean actualContainsExpected() { int actListCount = actList.size(); int expListCount = expList.size(); if (expListCount > actListCount) { - return fail("actual size is less than expected size - " + actListCount + ":" + expListCount); + return fail("actual array length is less than expected - " + actListCount + ":" + expListCount); } if (type == MatchType.CONTAINS_ONLY && expListCount != actListCount) { - return fail("actual size is not equal to expected size - " + actListCount + ":" + expListCount); + return fail("actual array length is not equal to expected - " + actListCount + ":" + expListCount); } for (Object exp : expList) { // for each item in the expected list boolean found = false; @@ -494,11 +494,11 @@ private boolean actualContainsExpected() { } } if (!found && type != MatchType.CONTAINS_ANY) { // if we reached here, all items in the actual list were scanned - return fail("actual list does not contain expected item - " + exp); + return fail("actual array does not contain expected item - " + exp); } } if (type == MatchType.CONTAINS_ANY) { - return fail("actual list does not contain any expected item"); + return fail("actual array does not contain any of the expected items"); } return true; // if we reached here, all items in the expected list were found case MAP: @@ -521,7 +521,7 @@ private static BigDecimal toBigDecimal(Object o) { Number n = (Number) o; return BigDecimal.valueOf(n.doubleValue()); } else { - throw new RuntimeException("expected number or big-decimal: " + o); + throw new RuntimeException("expected number instead of: " + o); } } diff --git a/karate-core2/src/main/java/com/intuit/karate/runtime/FeatureRuntime.java b/karate-core2/src/main/java/com/intuit/karate/runtime/FeatureRuntime.java index 07e756b6e..e52024b0a 100644 --- a/karate-core2/src/main/java/com/intuit/karate/runtime/FeatureRuntime.java +++ b/karate-core2/src/main/java/com/intuit/karate/runtime/FeatureRuntime.java @@ -40,6 +40,8 @@ public class FeatureRuntime implements Runnable { public final FeatureResult result; private final ScenarioGenerator scenarios; + private PerfRuntime perfRuntime; + public Path getParentPath() { return feature.getPath().getParent(); } @@ -51,13 +53,26 @@ public Path getRootParentPath() { public Path getPath() { return feature.getPath(); } + + public void setPerfRuntime(PerfRuntime perfRuntime) { + this.perfRuntime = perfRuntime; + } + + public boolean isPerfMode() { + return perfRuntime != null; + } + + public PerfRuntime getPerfRuntime() { + return perfRuntime; + } - public FeatureRuntime(SuiteRuntime suite, Feature feature) { + public FeatureRuntime(SuiteRuntime suite, Feature feature, boolean karateConfigDisabled) { this(suite, feature, ScenarioCall.NONE); + parentCall.setKarateConfigDisabled(karateConfigDisabled); } public FeatureRuntime(ScenarioCall call) { - this(call.parentRuntime.featureRuntime.suite, call.feature, call.parentRuntime.parentCall); + this(call.parentRuntime.featureRuntime.suite, call.feature, call); } private FeatureRuntime(SuiteRuntime suite, Feature feature, ScenarioCall parentCall) { diff --git a/karate-core2/src/main/java/com/intuit/karate/runtime/PerfRuntime.java b/karate-core2/src/main/java/com/intuit/karate/runtime/PerfRuntime.java new file mode 100644 index 000000000..2916fcab2 --- /dev/null +++ b/karate-core2/src/main/java/com/intuit/karate/runtime/PerfRuntime.java @@ -0,0 +1,43 @@ +/* + * The MIT License + * + * Copyright 2020 Intuit Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.intuit.karate.runtime; + +import com.intuit.karate.core.PerfEvent; +import java.util.function.Consumer; + +/** + * + * @author pthomas3 + */ +public interface PerfRuntime { + + String getPerfEventName(ScenarioHttpBuilder http, ScenarioRuntime sr); + + void reportPerfEvent(PerfEvent event); + + void submit(Runnable runnable); + + void afterFeature(); + +} diff --git a/karate-core2/src/main/java/com/intuit/karate/runtime/RuntimeHook.java b/karate-core2/src/main/java/com/intuit/karate/runtime/RuntimeHook.java new file mode 100644 index 000000000..c984fe85b --- /dev/null +++ b/karate-core2/src/main/java/com/intuit/karate/runtime/RuntimeHook.java @@ -0,0 +1,53 @@ +/* + * The MIT License + * + * Copyright 2020 Intuit Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.intuit.karate.runtime; + +import com.intuit.karate.core.Step; +import com.intuit.karate.core.StepResult; + +/** + * + * @author pthomas3 + */ +public interface RuntimeHook { + + // return false if the scenario / item should be excluded from the test-run + // throws RuntimeException (any) to abort + boolean beforeScenario(ScenarioRuntime sr); + + void afterScenario(ScenarioRuntime sr); + + boolean beforeFeature(FeatureRuntime fr); + + void afterFeature(FeatureRuntime fr); + + void beforeSuite(SuiteRuntime suite); + + void afterSuite(SuiteRuntime suite); + + boolean beforeStep(Step step, ScenarioRuntime sr); + + void afterStep(StepResult result, ScenarioRuntime sr); + +} diff --git a/karate-core2/src/main/java/com/intuit/karate/runtime/ScenarioCall.java b/karate-core2/src/main/java/com/intuit/karate/runtime/ScenarioCall.java index 754190d8f..1932b0332 100644 --- a/karate-core2/src/main/java/com/intuit/karate/runtime/ScenarioCall.java +++ b/karate-core2/src/main/java/com/intuit/karate/runtime/ScenarioCall.java @@ -24,6 +24,7 @@ package com.intuit.karate.runtime; import com.intuit.karate.core.Feature; +import java.util.Map; /** * @@ -32,7 +33,7 @@ public class ScenarioCall { public static final ScenarioCall NONE = new ScenarioCall(null, null); - + public final ScenarioRuntime parentRuntime; public final int depth; public final Feature feature; @@ -40,6 +41,7 @@ public class ScenarioCall { private boolean callonce; private Variable arg; private boolean globalScope; + private boolean karateConfigDisabled; public void setGlobalScope(boolean globalScope) { this.globalScope = globalScope; @@ -47,7 +49,7 @@ public void setGlobalScope(boolean globalScope) { public boolean isGlobalScope() { return globalScope; - } + } public void setArg(Variable arg) { this.arg = arg; @@ -59,7 +61,7 @@ public Variable getArg() { public boolean isCallonce() { return callonce; - } + } public boolean isNone() { return depth == 0; @@ -69,6 +71,14 @@ public void setCallonce(boolean callonce) { this.callonce = callonce; } + public void setKarateConfigDisabled(boolean karateConfigDisabled) { + this.karateConfigDisabled = karateConfigDisabled; + } + + public boolean isKarateConfigDisabled() { + return karateConfigDisabled; + } + public ScenarioCall(ScenarioRuntime parentRuntime, Feature feature) { this.parentRuntime = parentRuntime; this.feature = feature; @@ -79,4 +89,18 @@ public ScenarioCall(ScenarioRuntime parentRuntime, Feature feature) { } } + public static class Result { + + public final Variable result; + public final Config config; + public final Map vars; + + public Result(Variable result, Config config, Map vars) { + this.result = result; + this.config = config; + this.vars = vars; + } + + } + } diff --git a/karate-core2/src/main/java/com/intuit/karate/runtime/ScenarioEngine.java b/karate-core2/src/main/java/com/intuit/karate/runtime/ScenarioEngine.java index 3450d7e93..26c5f039b 100644 --- a/karate-core2/src/main/java/com/intuit/karate/runtime/ScenarioEngine.java +++ b/karate-core2/src/main/java/com/intuit/karate/runtime/ScenarioEngine.java @@ -59,14 +59,11 @@ public class ScenarioEngine { private final Logger logger; - public final Map vars = new HashMap(); + public final Map vars; private JsEngine JS; - public ScenarioEngine() { - this(new Logger()); - } - - public ScenarioEngine(Logger logger) { + public ScenarioEngine(Map vars, Logger logger) { + this.vars = vars; this.logger = logger; } @@ -97,9 +94,18 @@ public void put(String key, Object value) { } public void putAll(Map map) { + if (map == null) { + return; + } map.forEach((k, v) -> put(k, v)); } + public Map copyVariables(boolean deep) { + Map map = new HashMap(vars.size()); + vars.forEach((k, v) -> map.put(k, v == null ? Variable.NULL : v.copy(deep))); + return map; + } + public Map getAllVariablesAsMap() { Map map = new HashMap(vars.size()); vars.forEach((k, v) -> map.put(k, v == null ? null : v.getValue())); @@ -758,13 +764,13 @@ public static StringUtils.Pair parseCallArgs(String line) { if (pos == -1) { throw new RuntimeException("failed to parse call arguments: " + line); } - return new StringUtils.Pair(line.substring(0, pos + 1), line.substring(pos + 1)); + return new StringUtils.Pair(line.substring(0, pos + 1), StringUtils.trimToNull(line.substring(pos + 1))); } pos = line.indexOf(' '); if (pos == -1) { return new StringUtils.Pair(line, null); } - return new StringUtils.Pair(line.substring(0, pos), line.substring(pos)); + return new StringUtils.Pair(line.substring(0, pos), StringUtils.trimToNull(line.substring(pos))); } public Variable call(boolean callOnce, String exp, boolean reuseParentConfig) { diff --git a/karate-core2/src/main/java/com/intuit/karate/runtime/ScenarioFileReader.java b/karate-core2/src/main/java/com/intuit/karate/runtime/ScenarioFileReader.java index dee3a481a..085010f9a 100644 --- a/karate-core2/src/main/java/com/intuit/karate/runtime/ScenarioFileReader.java +++ b/karate-core2/src/main/java/com/intuit/karate/runtime/ScenarioFileReader.java @@ -51,11 +51,15 @@ public ScenarioFileReader(ScenarioRuntime runtime) { public Object readFile(String text) { StringUtils.Pair pair = parsePathAndTags(text); text = pair.left; - if (isJsonFile(text) || isXmlFile(text) || isJavaScriptFile(text)) { + if (isJsonFile(text) || isXmlFile(text)) { String contents = readFileAsString(text); - contents = ScenarioEngine.fixJavaScriptFunction(contents); Variable temp = runtime.engine.evalKarateExpression(contents); return temp.getValue(); + } else if (isJavaScriptFile(text)) { + String contents = readFileAsString(text); + contents = ScenarioEngine.fixJavaScriptFunction(contents); + Variable temp = runtime.engine.evalKarateExpression(contents); + return temp.getValue(); } else if (isTextFile(text) || isGraphQlFile(text)) { return readFileAsString(text); } else if (isFeatureFile(text)) { diff --git a/karate-core2/src/main/java/com/intuit/karate/runtime/HttpRequestBuilder.java b/karate-core2/src/main/java/com/intuit/karate/runtime/ScenarioHttpBuilder.java similarity index 98% rename from karate-core2/src/main/java/com/intuit/karate/runtime/HttpRequestBuilder.java rename to karate-core2/src/main/java/com/intuit/karate/runtime/ScenarioHttpBuilder.java index 274f8a07f..f8029ee54 100644 --- a/karate-core2/src/main/java/com/intuit/karate/runtime/HttpRequestBuilder.java +++ b/karate-core2/src/main/java/com/intuit/karate/runtime/ScenarioHttpBuilder.java @@ -38,7 +38,7 @@ * * @author pthomas3 */ -public class HttpRequestBuilder { +public class ScenarioHttpBuilder { private String url; private List paths; @@ -52,8 +52,8 @@ public class HttpRequestBuilder { private String soapAction; private String retryUntil; - public HttpRequestBuilder copy() { - HttpRequestBuilder out = new HttpRequestBuilder(); + public ScenarioHttpBuilder copy() { + ScenarioHttpBuilder out = new ScenarioHttpBuilder(); out.url = url; if (paths != null) { out.paths = new ArrayList(paths); diff --git a/karate-core2/src/main/java/com/intuit/karate/runtime/ScenarioHttpClient.java b/karate-core2/src/main/java/com/intuit/karate/runtime/ScenarioHttpClient.java index a4e411ae1..74281886f 100644 --- a/karate-core2/src/main/java/com/intuit/karate/runtime/ScenarioHttpClient.java +++ b/karate-core2/src/main/java/com/intuit/karate/runtime/ScenarioHttpClient.java @@ -24,7 +24,6 @@ package com.intuit.karate.runtime; import com.intuit.karate.XmlUtils; -import com.intuit.karate.core.ExecutionHook; import com.intuit.karate.core.PerfEvent; import com.intuit.karate.exception.KarateException; import com.intuit.karate.http.Cookie; @@ -54,7 +53,7 @@ public abstract class ScenarioHttpClient { private static final String KARATE_HTTP_PROPERTIES = "karate-http.properties"; - protected HttpRequestBuilder request; + protected ScenarioHttpBuilder request; protected ScenarioRuntime runtime() { return ScenarioRuntime.LOCAL.get(); @@ -111,7 +110,7 @@ private T getEntityInternal(Variable body, String mediaType) { } } - private T buildRequestInternal(HttpRequestBuilder request) { + private T buildRequestInternal(ScenarioHttpBuilder request) { ScenarioRuntime runtime = runtime(); String method = request.getMethod(); if (method == null) { @@ -154,6 +153,9 @@ private T buildRequestInternal(HttpRequestBuilder request) { if (request.getHeaders() != null) { for (Map.Entry entry : request.getHeaders().entrySet()) { for (Object value : entry.getValue()) { + if (entry.getValue() == null) { // TODO seems to happen for retry-until and __arg + continue; + } buildHeader(entry.getKey(), value, false); } } @@ -211,14 +213,12 @@ private T buildRequestInternal(HttpRequestBuilder request) { } } - public HttpResponse invoke(HttpRequestBuilder request) { + public HttpResponse invoke(ScenarioHttpBuilder request) { ScenarioRuntime runtime = runtime(); T body = buildRequestInternal(request); String perfEventName = null; // acts as a flag to report perf if not null - if (runtime.executionHooks != null) { - for (ExecutionHook h : runtime.executionHooks) { - // perfEventName = h.getPerfEventName(request, context); // TODO - } + if (runtime.featureRuntime.isPerfMode()) { + perfEventName = runtime.featureRuntime.getPerfRuntime().getPerfEventName(request, runtime); } try { HttpResponse response = makeHttpRequest(body); diff --git a/karate-core2/src/main/java/com/intuit/karate/runtime/ScenarioRuntime.java b/karate-core2/src/main/java/com/intuit/karate/runtime/ScenarioRuntime.java index 089d8d319..763cb8cda 100644 --- a/karate-core2/src/main/java/com/intuit/karate/runtime/ScenarioRuntime.java +++ b/karate-core2/src/main/java/com/intuit/karate/runtime/ScenarioRuntime.java @@ -28,7 +28,6 @@ import com.intuit.karate.LogAppender; import com.intuit.karate.Logger; import com.intuit.karate.StringUtils; -import com.intuit.karate.core.ExecutionHook; import com.intuit.karate.core.PerfEvent; import com.intuit.karate.core.Result; import com.intuit.karate.core.Scenario; @@ -43,6 +42,7 @@ import com.intuit.karate.shell.FileLogAppender; import java.io.File; import java.util.Collection; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.function.Function; @@ -52,35 +52,38 @@ * @author pthomas3 */ public class ScenarioRuntime implements Runnable { - + public final Logger logger = new Logger(); - + public final FeatureRuntime featureRuntime; public final ScenarioRuntime background; public final ScenarioCall parentCall; public final Scenario scenario; - public final ScenarioActions actions; + public final ScenarioActions actions; public final ScenarioResult result; public final ScenarioEngine engine; public final ScenarioBridge bridge; public final ScenarioFileReader fileReader; public final Function readFunction; - public final Collection executionHooks; - + public final Collection runtimeHooks; + public ScenarioRuntime(FeatureRuntime featureRuntime, Scenario scenario) { this(featureRuntime, scenario, null); } - + public ScenarioRuntime(FeatureRuntime featureRuntime, Scenario scenario, ScenarioRuntime background) { - executionHooks = featureRuntime.suite.resolveHooks(); + runtimeHooks = featureRuntime.suite.runtimeHooks; this.featureRuntime = featureRuntime; this.parentCall = featureRuntime.parentCall; if (parentCall.isNone()) { config = new Config(); + engine = new ScenarioEngine(new HashMap(), logger); } else if (parentCall.isGlobalScope()) { config = parentCall.parentRuntime.config; + engine = new ScenarioEngine(parentCall.parentRuntime.engine.vars, logger); } else { // new, but clone and copy data - config = new Config(parentCall.parentRuntime.config); + config = new Config(parentCall.parentRuntime.config); + engine = new ScenarioEngine(parentCall.parentRuntime.engine.copyVariables(false), logger); } this.scenario = scenario; if (background == null) { @@ -90,26 +93,27 @@ public ScenarioRuntime(FeatureRuntime featureRuntime, Scenario scenario, Scenari this.background = background; result = new ScenarioResult(scenario, background.result.getStepResults()); } - engine = new ScenarioEngine(logger); bridge = new ScenarioBridge(); // uses thread local to get "this" actions = new ScenarioActions(this); fileReader = new ScenarioFileReader(this); readFunction = s -> fileReader.readFile(s); - // TODO appender for perf + if (featureRuntime.isPerfMode()) { + appender = LogAppender.NO_OP; + } } - + public boolean isFailed() { return error != null || result.isFailed(); } - + public Step getCurrentStep() { return currentStep; } - + public boolean isStopped() { return stopped; } - + private List steps; private LogAppender appender; private StepResult lastStepResult; @@ -118,7 +122,7 @@ public boolean isStopped() { private boolean stopped; private boolean aborted; private int stepIndex; - + public void stepBack() { stopped = false; stepIndex -= 2; @@ -126,7 +130,7 @@ public void stepBack() { stepIndex = 0; } } - + public void stepReset() { stopped = false; stepIndex--; @@ -134,15 +138,15 @@ public void stepReset() { stepIndex = 0; } } - + public void stepProceed() { stopped = false; } - + private int nextStepIndex() { return stepIndex++; } - + private void logError(String message) { if (currentStep != null) { message = currentStep.getDebugInfo() @@ -151,7 +155,7 @@ private void logError(String message) { } logger.error("{}", message); } - + @Override public void run() { try { // make sure we call afterRun() even on crashes @@ -175,9 +179,9 @@ public void run() { afterRun(); } } - + protected static final ThreadLocal LOCAL = new ThreadLocal(); - + private static final ThreadLocal APPENDER = new ThreadLocal() { @Override protected LogAppender initialValue() { @@ -185,7 +189,7 @@ protected LogAppender initialValue() { return new FileLogAppender(new File(fileName)); } }; - + public void beforeRun() { if (appender == null) { // not perf, not debug appender = APPENDER.get(); @@ -209,6 +213,23 @@ public void beforeRun() { } result.setThreadName(Thread.currentThread().getName()); result.setStartTime(System.currentTimeMillis() - featureRuntime.suite.results.getStartTime()); + if (parentCall.isNone() && !parentCall.isKarateConfigDisabled()) { + // evaluate config js, variables above will apply ! + evalConfigJs(featureRuntime.suite.karateBase); + evalConfigJs(featureRuntime.suite.karateConfig); + evalConfigJs(featureRuntime.suite.karateConfigEnv); + } + } + + private void evalConfigJs(String js) { + if (js != null) { + Variable fun = engine.evalKarateExpression(js); + if (fun.isFunction()) { + engine.putAll(fun.evalAsMap()); + } else { + logger.warn("config did not evaluate to js function: {}", js); + } + } } // extracted for debug @@ -243,7 +264,7 @@ public StepResult execute(Step step) { return sr; } } - + public void afterRun() { try { result.setEndTime(System.currentTimeMillis() - featureRuntime.suite.results.getStartTime()); @@ -273,15 +294,15 @@ public void call(boolean callOnce, String line) { engine.putAll(v.getValue()); } } - + public void assign(AssignType assignType, String name, String exp) { engine.assign(assignType, name, exp, false); } - + public void eval(String exp) { engine.eval(exp); } - + public void match(MatchType matchType, String expression, String path, String expected) { MatchResult mr = engine.match(matchType, expression, path, expected); if (!mr.pass) { @@ -289,31 +310,31 @@ public void match(MatchType matchType, String expression, String path, String ex throw new KarateException(mr.message); } } - + public void set(String name, String path, String exp) { engine.set(name, path, exp); } - + public void set(String name, String path, List> table) { engine.setViaTable(name, path, table); } - + public void remove(String name, String path) { engine.remove(name, path); } - + public void table(String name, List> table) { engine.table(name, table); } - + public void replace(String name, String token, String value) { engine.replace(name, token, value); } - + public void replace(String name, List> table) { engine.replaceTable(name, table); } - + public void assertTrue(String expression) { if (!engine.assertTrue(expression)) { String message = "did not evaluate to 'true': " + expression; @@ -321,7 +342,7 @@ public void assertTrue(String expression) { throw new KarateException(message); } } - + public void print(List exps) { if (!config.isPrintEnabled()) { return; @@ -332,18 +353,18 @@ public void print(List exps) { // gatling ================================================================= // private PerfEvent prevPerfEvent; - + public void logLastPerfEvent(String failureMessage) { - if (prevPerfEvent != null && executionHooks != null) { + if (prevPerfEvent != null && featureRuntime.isPerfMode()) { if (failureMessage != null) { prevPerfEvent.setFailed(true); prevPerfEvent.setMessage(failureMessage); } - executionHooks.forEach(h -> h.reportPerfEvent(prevPerfEvent)); + featureRuntime.getPerfRuntime().reportPerfEvent(prevPerfEvent); } prevPerfEvent = null; } - + public void capturePerfEvent(PerfEvent event) { logLastPerfEvent(null); prevPerfEvent = event; @@ -354,15 +375,15 @@ public void capturePerfEvent(PerfEvent event) { private Config config; private ScenarioHttpClient http; private HttpRequest prevRequest; - + public HttpRequest getPrevRequest() { return prevRequest; } - + public Config getConfig() { return config; } - + public void updateConfigCookies(Map cookies) { if (cookies == null) { return; @@ -375,7 +396,7 @@ public void updateConfigCookies(Map cookies) { config.setCookies(new Variable(map)); } } - + public void configure(String key, String exp) { Variable v = new Variable(exp); key = StringUtils.trimToEmpty(key); @@ -388,91 +409,91 @@ public void configure(String key, String exp) { } } } - + public void url(String exp) { - + } - + public void path(List paths) { - + } - + public void param(String name, List values) { - + } - + public void params(String expr) { - + } - + public void cookie(String name, String value) { - + } - + public void cookies(String expr) { - + } - + public void header(String name, List values) { - + } - + public void headers(String expr) { - + } - + public void formField(String name, List values) { - + } - + public void formFields(String expr) { - + } - + public void request(String body) { - + } - + public void method(String method) { - + } - + public void retry(String until) { - + } - + public void soapAction(String action) { - + } - + public void multipartField(String name, String value) { - + } - + public void multipartFields(String expr) { - + } - + public void multipartFile(String name, String value) { - + } - + public void multipartFiles(String expr) { - + } - + public void status(int status) { - + } // ui driver / robot ======================================================= // public void driver(String expression) { - + } - + public void robot(String expression) { - + } - + } diff --git a/karate-core2/src/main/java/com/intuit/karate/runtime/SuiteRuntime.java b/karate-core2/src/main/java/com/intuit/karate/runtime/SuiteRuntime.java index 7e23c4dd2..c4333f084 100644 --- a/karate-core2/src/main/java/com/intuit/karate/runtime/SuiteRuntime.java +++ b/karate-core2/src/main/java/com/intuit/karate/runtime/SuiteRuntime.java @@ -23,33 +23,79 @@ */ package com.intuit.karate.runtime; +import com.intuit.karate.Logger; +import com.intuit.karate.Resource; import com.intuit.karate.Results; -import com.intuit.karate.core.ExecutionHook; -import com.intuit.karate.core.ExecutionHookFactory; +import com.intuit.karate.StringUtils; import java.io.File; import java.util.ArrayList; import java.util.Collection; +import java.util.HashMap; +import java.util.Map; /** * * @author pthomas3 */ public class SuiteRuntime { - + + public final String env; + public final Logger logger = new Logger(); public final File workingDir = new File(""); public final ClassLoader classLoader = ClassLoader.getSystemClassLoader(); - public final Results results = Results.startTimer(1); - public final Collection executionHooks = new ArrayList(); - public final ExecutionHookFactory hookFactory = null; - private boolean hooksResolved; - - public Collection resolveHooks() { - if (hookFactory == null || hooksResolved) { - return executionHooks; + public final Results results = Results.startTimer(1); + public final Collection runtimeHooks = new ArrayList(); + + public final Map SUITE_CACHE = new HashMap(); + + public final String karateBase; + public final String karateConfig; + public final String karateConfigEnv; + + private String read(String name) { + try { + return Resource.relativePathToString(name); + } catch (Exception e) { + logger.trace("file not found: {} - {}", name, e.getMessage()); + return null; + } + } + + public SuiteRuntime() { + karateBase = read("classpath:karate-base.js"); + if (karateBase != null) { + logger.info("karate-base.js found on classpath"); + } + String configPrefix = StringUtils.trimToNull(System.getProperty("karate.config.dir")); + if (configPrefix == null) { + configPrefix = "classpath:"; + } else { + if (configPrefix.startsWith("file:") || configPrefix.startsWith("classpath:")) { + // all good + } else { + configPrefix = "file:" + configPrefix; + } + if (configPrefix.endsWith("/") || configPrefix.endsWith("\\")) { + // all good + } else { + configPrefix = configPrefix + File.separator; + } + } + karateConfig = read(configPrefix + "karate-config.js"); + if (karateConfig != null) { + logger.info("karate-config.js found in {}", configPrefix); + } else { + logger.warn("karate-config.js not found in {}", configPrefix); } - hooksResolved = true; - executionHooks.add(hookFactory.create()); - return executionHooks; - } - + env = StringUtils.trimToNull(System.getProperty("karate.env")); + if (env != null) { + karateConfigEnv = read(configPrefix + "karate-config-" + env + ".js"); + if (karateConfigEnv != null) { + logger.info("karate-config-" + env + ".js found in {}", configPrefix); + } + } else { + karateConfigEnv = null; + } + } + } diff --git a/karate-core2/src/test/java/com/intuit/karate/match/MatchTest.java b/karate-core2/src/test/java/com/intuit/karate/match/MatchTest.java index c462ba755..58168db0d 100644 --- a/karate-core2/src/test/java/com/intuit/karate/match/MatchTest.java +++ b/karate-core2/src/test/java/com/intuit/karate/match/MatchTest.java @@ -27,7 +27,7 @@ private void match(Object actual, MatchType mt, Object expected) { String message; private void message(String expected) { - assertTrue(message != null && message.contains(expected)); + assertTrue(message != null && message.contains(expected), message); } private void log() { @@ -116,6 +116,7 @@ void testList() { match("[1, 2, 3]", NOT_CONTAINS, "[1, 2, 4]"); match("[1, 2, 3]", CONTAINS_ANY, "[1, 2, 4]"); match("[{ a: 1 }, { b: 2 }, { c: 3 }]", EQUALS, "[{ a: 1 }, { b: 2 }, { c: 3 }]"); + match("[{ a: 1 }, { b: 2 }, { c: 3 }]", EQUALS, "[{ a: 1 }, { b: 2 }, { c: 4 }]", FAILS); match("[{ a: 1 }, { b: 2 }, { c: 3 }]", CONTAINS, "[{ a: 1 }, { b: 2 }, { c: 3 }]"); match("[{ a: 1 }, { b: 2 }, { c: 3 }]", CONTAINS_ONLY, "[{ a: 1 }, { b: 2 }, { c: 3 }]"); match("[{ a: 1 }, { b: 2 }, { c: 3 }]", CONTAINS, "[{ a: 1 }, { c: 3 }]"); diff --git a/karate-core2/src/test/java/com/intuit/karate/runtime/FeatureRuntimeTest.java b/karate-core2/src/test/java/com/intuit/karate/runtime/FeatureRuntimeTest.java index 42d5f5900..29d83eea6 100644 --- a/karate-core2/src/test/java/com/intuit/karate/runtime/FeatureRuntimeTest.java +++ b/karate-core2/src/test/java/com/intuit/karate/runtime/FeatureRuntimeTest.java @@ -22,11 +22,11 @@ void testPrint() { FeatureRuntime fr = run("print.feature"); assertFalse(fr.result.isFailed()); } - + @Test void testFail1() { FeatureRuntime fr = run("fail1.feature"); assertTrue(fr.result.isFailed()); - } + } } diff --git a/karate-core2/src/test/java/com/intuit/karate/runtime/RuntimeUtils.java b/karate-core2/src/test/java/com/intuit/karate/runtime/RuntimeUtils.java index 5ed7a2f89..4ec7689a4 100644 --- a/karate-core2/src/test/java/com/intuit/karate/runtime/RuntimeUtils.java +++ b/karate-core2/src/test/java/com/intuit/karate/runtime/RuntimeUtils.java @@ -4,6 +4,7 @@ import com.intuit.karate.Resource; import com.intuit.karate.core.Feature; import com.intuit.karate.core.FeatureParser; +import java.io.InputStream; import java.nio.file.Path; import java.nio.file.Paths; @@ -12,21 +13,27 @@ * @author pthomas3 */ public class RuntimeUtils { - - public static Feature toFeature(String name, String ... lines) { + + public static Feature toFeature(String name, String... lines) { StringBuilder sb = new StringBuilder(); sb.append("Feature:\nScenario:\n"); for (String line : lines) { sb.append("* ").append(line).append('\n'); } - Path path = FileUtils.fromRelativeClassPath("classpath:com/intuit/karate/runtime/" + name, ClassLoader.getSystemClassLoader()); - Resource resource = Resource.of(path, sb.toString()); - return FeatureParser.parse(resource); + InputStream is = FileUtils.toInputStream(sb.toString()); + Path path = FileUtils.fromRelativeClassPath("classpath:com/intuit/karate/runtime/" + name, ClassLoader.getSystemClassLoader()); + Resource resource = new Resource(path) { + @Override + public InputStream getStream() { + return is; + } + }; + return FeatureParser.parse(resource); } public static ScenarioRuntime runScenario(String... lines) { Feature feature = toFeature("print.feature", lines); - FeatureRuntime fr = new FeatureRuntime(new SuiteRuntime(), feature); + FeatureRuntime fr = new FeatureRuntime(new SuiteRuntime(), feature, false); ScenarioGenerator sg = new ScenarioGenerator(fr, feature.getSections().iterator()); sg.hasNext(); ScenarioRuntime sr = sg.next(); @@ -36,7 +43,7 @@ public static ScenarioRuntime runScenario(String... lines) { public static FeatureRuntime runFeature(String path) { Feature feature = FeatureParser.parse(path); - FeatureRuntime fr = new FeatureRuntime(new SuiteRuntime(), feature); + FeatureRuntime fr = new FeatureRuntime(new SuiteRuntime(), feature, false); fr.run(); return fr; } diff --git a/karate-core2/src/test/java/com/intuit/karate/runtime/ScenarioEngineTest.java b/karate-core2/src/test/java/com/intuit/karate/runtime/ScenarioEngineTest.java index a1efe4ccf..563ae0268 100644 --- a/karate-core2/src/test/java/com/intuit/karate/runtime/ScenarioEngineTest.java +++ b/karate-core2/src/test/java/com/intuit/karate/runtime/ScenarioEngineTest.java @@ -7,6 +7,7 @@ import com.intuit.karate.match.MatchResult; import com.intuit.karate.match.MatchType; import com.intuit.karate.match.MatchValue; +import java.util.HashMap; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.slf4j.Logger; @@ -21,7 +22,7 @@ public class ScenarioEngineTest { static final Logger logger = LoggerFactory.getLogger(ScenarioEngineTest.class); - ScenarioEngine engine = new ScenarioEngine(); + ScenarioEngine engine = new ScenarioEngine(new HashMap(), new com.intuit.karate.Logger()); @BeforeEach void beforeEach() { diff --git a/karate-core2/src/test/java/com/intuit/karate/runtime/ScenarioRuntimeTest.java b/karate-core2/src/test/java/com/intuit/karate/runtime/ScenarioRuntimeTest.java index 089cd9db3..85b340344 100644 --- a/karate-core2/src/test/java/com/intuit/karate/runtime/ScenarioRuntimeTest.java +++ b/karate-core2/src/test/java/com/intuit/karate/runtime/ScenarioRuntimeTest.java @@ -1,6 +1,7 @@ package com.intuit.karate.runtime; import com.intuit.karate.match.Match; +import com.intuit.karate.match.MatchResult; import static com.intuit.karate.runtime.RuntimeUtils.*; import static org.junit.jupiter.api.Assertions.*; import org.junit.jupiter.api.Test; @@ -26,6 +27,11 @@ ScenarioRuntime run(String... lines) { return sr; } + private void matchVarEquals(String name, Object expected) { + MatchResult mr = Match.that(get(name)).isEqualTo(expected); + assertTrue(mr.pass, mr.message); + } + @Test void testDefAndMatch() { run( @@ -41,12 +47,29 @@ void testDefAndMatch() { assertTrue(sr.result.isFailed()); } + @Test + void testConfig() { + System.setProperty("karate.env", ""); + System.setProperty("karate.config.dir", ""); + run("def foo = configSource"); + matchVarEquals("foo", "normal"); + System.setProperty("karate.config.dir", "src/test/java/com/intuit/karate/runtime"); + run("def foo = configSource"); + matchVarEquals("foo", "custom"); + System.setProperty("karate.env", "dev"); + run("def foo = configSource"); + matchVarEquals("foo", "custom-env"); + // reset for other tests + System.setProperty("karate.env", ""); + System.setProperty("karate.config.dir", ""); + } + @Test void testReadFunction() { run( "def foo = karate.read('data.json')" ); - Match.that(get("foo")).isEqualTo("{ hello: 'world' }"); + matchVarEquals("foo", "{ hello: 'world' }"); } @Test @@ -55,15 +78,16 @@ void testCallJsFunction() { "def fun = function(a){ return a + 1 }", "def foo = call fun 2" ); - Match.that(get("foo")).isEqualTo(3); + matchVarEquals("foo", 3); } @Test void testCallKarateFeature() { run( - "def res = call read('called1.feature')" + "def b = 'bar'", + "def res = call read('called1.feature')" ); - Match.that(get("res")).isEqualTo("{ a: 1, foo: { hello: 'world' } }"); + matchVarEquals("res", "{ a: 1, b: 'bar', foo: { hello: 'world' }, configSource: 'normal' }"); } } diff --git a/karate-core2/src/test/java/com/intuit/karate/runtime/karate-config-dev.js b/karate-core2/src/test/java/com/intuit/karate/runtime/karate-config-dev.js new file mode 100644 index 000000000..6b2778209 --- /dev/null +++ b/karate-core2/src/test/java/com/intuit/karate/runtime/karate-config-dev.js @@ -0,0 +1,5 @@ +function fn() { + return { + configSource: 'custom-env' + } +} diff --git a/karate-core2/src/test/java/com/intuit/karate/runtime/karate-config.js b/karate-core2/src/test/java/com/intuit/karate/runtime/karate-config.js new file mode 100644 index 000000000..091082edb --- /dev/null +++ b/karate-core2/src/test/java/com/intuit/karate/runtime/karate-config.js @@ -0,0 +1,5 @@ +function fn() { + return { + configSource: 'custom' + } +} diff --git a/karate-core2/src/test/java/karate-config.js b/karate-core2/src/test/java/karate-config.js new file mode 100644 index 000000000..03a6e5c34 --- /dev/null +++ b/karate-core2/src/test/java/karate-config.js @@ -0,0 +1,5 @@ +function fn() { + return { + configSource: 'normal' + }; +} diff --git a/karate-junit4/src/test/java/com/intuit/karate/junit4/files/JarLoadingTest.java b/karate-junit4/src/test/java/com/intuit/karate/junit4/files/JarLoadingTest.java index d055c09f2..881bb6f81 100644 --- a/karate-junit4/src/test/java/com/intuit/karate/junit4/files/JarLoadingTest.java +++ b/karate-junit4/src/test/java/com/intuit/karate/junit4/files/JarLoadingTest.java @@ -106,9 +106,7 @@ public void testUsingKarateBase() throws Exception { List> list = new ArrayList(); for (int i = 0; i < 10; i++) { list.add(() -> { - Path path = FileUtils.fromRelativeClassPath(relativePath, cl); - logger.debug("path: {}", path); - Resource resource = new Resource(path, relativePath, -1); + Resource resource = new Resource(cl, relativePath); Feature feature = FeatureParser.parse(resource); Map map = Runner.runFeature(feature, null, true); Boolean result = (Boolean) map.get("success");