Skip to content

Commit

Permalink
cukexit wip a big milestone ref #444
Browse files Browse the repository at this point in the history
where the implementation of the call keyword has been switched to the new engine
  • Loading branch information
ptrthomas committed Aug 19, 2018
1 parent a1c4b82 commit 28f1fce
Show file tree
Hide file tree
Showing 22 changed files with 283 additions and 91 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ And you don't need to create additional Java classes for any of the payloads tha
| <a href="#match-contains-any"><code>match contains any</code></a>
| <a href="#not-contains"><code>match !contains</code></a>
| <a href="#match-each"><code>match each</code></a>
| <a href="#match-header"><code>match header</code></a>
| <a href="#fuzzy-matching">Fuzzy Matching</a>
| <a href="#schema-validation">Schema Validation</a>
| <a href="#contains-short-cuts"><code>contains</code> short-cuts</a>
Expand Down
21 changes: 16 additions & 5 deletions karate-core/src/main/java/com/intuit/karate/FileLogAppender.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,13 @@
* @author pthomas3
*/
public class FileLogAppender implements LogAppender {

private final FileChannel file;
private final Logger logger;
private int prevPos;

public FileLogAppender(String tempFilePath, Logger logger) {
this.logger = logger;
try {
if (tempFilePath == null) {
File temp = File.createTempFile("karate", "tmp");
Expand All @@ -51,7 +53,7 @@ public FileLogAppender(String tempFilePath, Logger logger) {
}
logger.setLogAppender(this);
}

@Override
public String collect() {
try {
Expand All @@ -64,8 +66,8 @@ public String collect() {
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}

@Override
public void append(String text) {
try {
Expand All @@ -74,5 +76,14 @@ public void append(String text) {
throw new RuntimeException(e);
}
}


@Override
public void close() {
try {
file.close();
} catch (Exception e) {
logger.warn("log appender close failed: {}", e.getMessage());
}
}

}
15 changes: 12 additions & 3 deletions karate-core/src/main/java/com/intuit/karate/FileUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import java.util.ArrayList;
import java.util.List;
import com.intuit.karate.cucumber.FeatureFilePath;
import com.intuit.karate.cucumber.FeatureWrapper;
import com.intuit.karate.exception.KarateFileNotFoundException;
import com.jayway.jsonpath.DocumentContext;
import java.io.BufferedReader;
Expand All @@ -22,6 +21,8 @@
import java.nio.charset.StandardCharsets;
import java.util.stream.Collectors;
import static com.intuit.karate.Script.evalKarateExpression;
import com.intuit.karate.core.Feature;
import com.intuit.karate.core.FeatureParser;
import java.net.URI;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
Expand Down Expand Up @@ -126,8 +127,16 @@ public static ScriptValue readFile(String text, ScriptContext context) {
String contents = readFileAsString(text, prefix, context);
return new ScriptValue(contents, text);
} else if (isFeatureFile(text)) {
String contents = readFileAsString(text, prefix, context);
FeatureWrapper feature = FeatureWrapper.fromString(contents, context.env, text, pair.right);
String featurePath;
if (prefix == PathPrefix.CLASSPATH) {
featurePath = "classpath:" + text;
} else if (prefix == PathPrefix.NONE) {
featurePath = context.env.featureDir.getPath() + "/" + text;
} else { // FILE
featurePath = text;
}
Feature feature = FeatureParser.parse(featurePath);
feature.setCallTag(pair.right);
return new ScriptValue(feature, text);
} else if (isYamlFile(text)) {
String contents = readFileAsString(text, prefix, context);
Expand Down
2 changes: 2 additions & 0 deletions karate-core/src/main/java/com/intuit/karate/LogAppender.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,6 @@ public interface LogAppender {

void append(String text);

void close();

}
37 changes: 24 additions & 13 deletions karate-core/src/main/java/com/intuit/karate/Script.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,9 @@

import com.intuit.karate.exception.KarateException;
import static com.intuit.karate.ScriptValue.Type.*;
import com.intuit.karate.cucumber.CucumberUtils;
import com.intuit.karate.cucumber.FeatureWrapper;
import com.intuit.karate.core.Engine;
import com.intuit.karate.core.Feature;
import com.intuit.karate.core.FeatureResult;
import com.intuit.karate.validator.ArrayValidator;
import com.intuit.karate.validator.RegexValidator;
import com.intuit.karate.validator.ValidationResult;
Expand Down Expand Up @@ -1584,7 +1585,7 @@ public static ScriptValue call(String name, String argString, ScriptContext cont
}
ScriptObjectMirror som = sv.getValue(ScriptObjectMirror.class);
return evalFunctionCall(som, argValue.getValue(), context);
case FEATURE_WRAPPER:
case FEATURE:
Object callArg = null;
switch (argValue.getType()) {
case LIST:
Expand All @@ -1608,7 +1609,7 @@ public static ScriptValue call(String name, String argString, ScriptContext cont
default:
throw new RuntimeException("only json, list/array or map allowed as feature call argument");
}
FeatureWrapper feature = sv.getValue(FeatureWrapper.class);
Feature feature = sv.getValue(Feature.class);
return evalFeatureCall(feature, callArg, context, reuseParentConfig);
default:
context.logger.warn("not a js function or feature file: {} - {}", name, sv);
Expand Down Expand Up @@ -1636,7 +1637,7 @@ public static ScriptValue evalFunctionCall(ScriptObjectMirror som, Object callAr
}
}

public static ScriptValue evalFeatureCall(FeatureWrapper feature, Object callArg, ScriptContext context, boolean reuseParentConfig) {
public static ScriptValue evalFeatureCall(Feature feature, Object callArg, ScriptContext context, boolean reuseParentConfig) {
if (callArg instanceof Collection) { // JSON array
Collection items = (Collection) callArg;
Object[] array = items.toArray();
Expand All @@ -1651,7 +1652,7 @@ public static ScriptValue evalFeatureCall(FeatureWrapper feature, Object callArg
result.add(rowResult.getValue());
} catch (KarateException ke) {
String message = "feature call (loop) failed at index: " + i + "\ncaller: "
+ feature.getEnv().featureName + "\narg: " + rowArg + "\n" + ke.getMessage();
+ feature.getRelativePath() + "\narg: " + rowArg + "\n" + ke.getMessage();
errors.add(message);
// log but don't stop (yet)
context.logger.error("{}", message);
Expand All @@ -1661,8 +1662,8 @@ public static ScriptValue evalFeatureCall(FeatureWrapper feature, Object callArg
}
}
if (!errors.isEmpty()) {
String message = "feature call (loop) failed: " + feature.getPath()
+ "\ncaller: " + feature.getEnv().featureName + "\nitems: " + items + "\nerrors:";
String message = "feature call (loop) failed: " + feature.getRelativePath()
+ "\ncaller: " + context.env.featureName + "\nitems: " + items + "\nerrors:";
for (String s : errors) {
message = message + "\n-------\n" + s;
}
Expand All @@ -1674,7 +1675,7 @@ public static ScriptValue evalFeatureCall(FeatureWrapper feature, Object callArg
try {
return evalFeatureCall(feature, context, argAsMap, -1, reuseParentConfig);
} catch (KarateException ke) {
String message = "feature call failed: " + feature.getPath()
String message = "feature call failed: " + feature.getRelativePath()
+ "\narg: " + callArg + "\n" + ke.getMessage();
context.logger.error("{}", message);
throw new KarateException(message, ke);
Expand All @@ -1684,14 +1685,24 @@ public static ScriptValue evalFeatureCall(FeatureWrapper feature, Object callArg
}
}

private static ScriptValue evalFeatureCall(FeatureWrapper feature, ScriptContext context,
private static ScriptValue evalFeatureCall(Feature feature, ScriptContext context,
Map<String, Object> callArg, int loopIndex, boolean reuseParentConfig) {
CallContext callContext = new CallContext(context, context.callDepth + 1, callArg, loopIndex,
reuseParentConfig, false, null, context.asyncSystem, null, context.stepInterceptor);
if (context.env.reporter != null) {
context.env.reporter.callBegin(feature, callContext);
// if (context.env.reporter != null) {
// context.env.reporter.callBegin(feature, callContext);
// }
FeatureResult result = Engine.executeSync(null, feature, null, callContext);
if (result.isFailed()) {
Throwable error = result.getErrors().get(0);
if (error instanceof KarateException) {
throw (KarateException) error;
} else {
throw new KarateException("call feature failed", error);
}
}
ScriptValueMap svm = CucumberUtils.callSync(feature, callContext);
// ScriptValueMap svm = CucumberUtils.callSync(feature, callContext);
ScriptValueMap svm = result.getResultVars();
return new ScriptValue(svm.toPrimitiveMap());
}

Expand Down
6 changes: 3 additions & 3 deletions karate-core/src/main/java/com/intuit/karate/ScriptBridge.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
*/
package com.intuit.karate;

import com.intuit.karate.cucumber.FeatureWrapper;
import com.intuit.karate.core.Feature;
import com.intuit.karate.exception.KarateAbortException;
import com.intuit.karate.http.HttpRequest;
import com.intuit.karate.http.HttpRequestBuilder;
Expand Down Expand Up @@ -235,8 +235,8 @@ public Object call(String fileName) {
public Object call(String fileName, Object arg) {
ScriptValue sv = FileUtils.readFile(fileName, context);
switch(sv.getType()) {
case FEATURE_WRAPPER:
FeatureWrapper feature = sv.getValue(FeatureWrapper.class);
case FEATURE:
Feature feature = sv.getValue(Feature.class);
return Script.evalFeatureCall(feature, arg, context, false).getValue();
case JS_FUNCTION:
ScriptObjectMirror som = sv.getValue(ScriptObjectMirror.class);
Expand Down
49 changes: 46 additions & 3 deletions karate-core/src/main/java/com/intuit/karate/core/Engine.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,12 @@
*/
package com.intuit.karate.core;

import com.intuit.karate.CallContext;
import com.intuit.karate.FileLogAppender;
import com.intuit.karate.FileUtils;
import com.intuit.karate.JsonUtils;
import com.intuit.karate.LogAppender;
import com.intuit.karate.ScriptEnv;
import com.intuit.karate.StepDefs;
import com.intuit.karate.StringUtils;
import com.intuit.karate.XmlUtils;
Expand All @@ -41,6 +44,7 @@
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
Expand Down Expand Up @@ -74,11 +78,26 @@ public class Engine {
private Engine() {
// only static methods
}

public static String getBuildDir() {
String command = System.getProperty("sun.java.command", "");
return command.contains("org.gradle.") ? "build" : "target";
}

public static FeatureResult executeSync(Feature feature, StepDefs stepDefs, LogAppender appender) {
public static FeatureResult executeSync(String envString, Feature feature, String tagSelector, CallContext callContext) {
File file = feature.getFile();
ScriptEnv env = ScriptEnv.forEnvTagsAndFeatureFile(envString, tagSelector, file);
if (callContext == null) {
callContext = new CallContext(null, true);
}
StepDefs stepDefs = new StepDefs(env, callContext);
String basePath = feature.getPackageQualifiedName();
LogAppender appender = new FileLogAppender(getBuildDir() + "/surefire-reports/" + basePath + ".log", stepDefs.context.logger);
FeatureExecutionUnit unit = new FeatureExecutionUnit(feature, stepDefs, appender);
unit.submit(SYNC_EXECUTOR, NO_OP);
return unit.getFeatureResult();
unit.submit(SYNC_EXECUTOR, NO_OP);
FeatureResult result = unit.getFeatureResult();
result.setResultVars(stepDefs.context.getVars());
return result;
}

public static Result execute(Scenario scenario, Step step, StepDefs stepDefs) {
Expand All @@ -96,6 +115,8 @@ public static Result execute(Scenario scenario, Step step, StepDefs stepDefs) {
if (step.getDocString() != null) {
last = step.getDocString();
} else if (step.getTable() != null) {
List<String> keys = new ArrayList(step.getTable().getKeys());
String[] columnNames = keys.toArray(new String[]{});
last = DataTable.create(step.getTable().getRows());
} else {
last = null;
Expand Down Expand Up @@ -228,5 +249,27 @@ private static List<MethodMatch> findMethodsMatching(String text) {
}
return matches;
}

public static String fromCucumberOptionsTags(String ... tags) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < tags.length; i++) {
String and = tags[i];
if (and.startsWith("~")) {
sb.append("not('").append(and.substring(1)).append("')");
} else {
sb.append("anyOf(");
List<String> or = StringUtils.split(and, ',');
for (String tag : or) {
sb.append('\'').append(tag).append('\'').append(',');
}
sb.setLength(sb.length() - 1);
sb.append(')');
}
if (i < (tags.length-1)) {
sb.append(" && ");
}
}
return sb.toString();
}

}
32 changes: 23 additions & 9 deletions karate-core/src/main/java/com/intuit/karate/core/Feature.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
*/
package com.intuit.karate.core;

import com.intuit.karate.FileUtils;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
Expand All @@ -33,8 +34,9 @@
*/
public class Feature {

private File file;
private String relativePath;
private final File file;
private final String relativePath;
private final String packageQualifiedName;

private int line;
private List<Tag> tags;
Expand All @@ -43,6 +45,22 @@ public class Feature {
private Background background;
private List<FeatureSection> sections = new ArrayList();

private String callTag;

public Feature(File file, String relativePath) {
this.file = file;
this.relativePath = relativePath;
this.packageQualifiedName = FileUtils.toPackageQualifiedName(relativePath);
}

public String getCallTag() {
return callTag;
}

public void setCallTag(String callTag) {
this.callTag = callTag;
}

public void addSection(FeatureSection section) {
sections.add(section);
}
Expand All @@ -51,18 +69,14 @@ public File getFile() {
return file;
}

public void setFile(File file) {
this.file = file;
}

public String getRelativePath() {
return relativePath;
}

public void setRelativePath(String relativePath) {
this.relativePath = relativePath;
public String getPackageQualifiedName() {
return packageQualifiedName;
}

public int getLine() {
return line;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ public void submit(Consumer<Runnable> system, BiConsumer<FeatureResult, KarateEx
});
});
} else {
appender.close();
next.accept(featureResult, null);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,7 @@ private FeatureParser(String relativePath) {
}

private FeatureParser(File file, String relativePath) {
feature = new Feature();
feature.setFile(file);
feature.setRelativePath(relativePath);
feature = new Feature(file, relativePath);
CharStream stream;
try {
FileInputStream fis = new FileInputStream(file);
Expand Down Expand Up @@ -138,7 +136,7 @@ private static Table toTable(KarateParser.TableContext ctx) {
List<Integer> lineNumbers = new ArrayList(rowCount);
for (TerminalNode node : nodes) {
List<String> tokens = StringUtils.split(node.getText().trim(), '|'); // TODO escaped pipe characters "\|" ?
tokens.remove(0);
// tokens.remove(0);
int count = tokens.size();
for (int i = 0; i < count; i++) {
tokens.set(i, tokens.get(i).trim());
Expand Down
Loading

0 comments on commit 28f1fce

Please sign in to comment.