diff --git a/karate-core/src/main/java/com/intuit/karate/Runner.java b/karate-core/src/main/java/com/intuit/karate/Runner.java index d3357d0fd..625829e06 100644 --- a/karate-core/src/main/java/com/intuit/karate/Runner.java +++ b/karate-core/src/main/java/com/intuit/karate/Runner.java @@ -82,7 +82,7 @@ public void onComplete() { public Iterator process(Feature feature) { CompletableFuture future = new CompletableFuture(); try { - FeatureRuntime fr = new FeatureRuntime(suite, feature); + FeatureRuntime fr = new FeatureRuntime(suite, feature, null); fr.setNext(() -> { featureResults.add(fr.result); onFeatureDone(fr, ++index, count); @@ -172,9 +172,8 @@ private static void onFeatureDone(FeatureRuntime fr, int index, int count) { public static Map runFeature(Feature feature, Map vars, boolean evalKarateConfig) { SuiteRuntime suite = new SuiteRuntime(); - FeatureRuntime featureRuntime = new FeatureRuntime(suite, feature); + FeatureRuntime featureRuntime = new FeatureRuntime(suite, feature, vars); featureRuntime.caller.setKarateConfigDisabled(!evalKarateConfig); - featureRuntime.setCallArg(vars); featureRuntime.run(); FeatureResult result = featureRuntime.result; if (result.isFailed()) { @@ -204,10 +203,9 @@ public static void callAsync(String path, List tags, Map builder.tags = tags; SuiteRuntime suite = new SuiteRuntime(builder); // sets tag selector Feature feature = FileUtils.parseFeatureAndCallTag(path); - FeatureRuntime featureRuntime = new FeatureRuntime(suite, feature); + FeatureRuntime featureRuntime = new FeatureRuntime(suite, feature, arg); featureRuntime.setPerfRuntime(perf); featureRuntime.setNext(() -> perf.afterFeature()); - featureRuntime.setCallArg(arg); perf.submit(featureRuntime); } diff --git a/karate-core/src/main/java/com/intuit/karate/core/PerfEvent.java b/karate-core/src/main/java/com/intuit/karate/core/PerfEvent.java index 564687719..306dc2eb7 100644 --- a/karate-core/src/main/java/com/intuit/karate/core/PerfEvent.java +++ b/karate-core/src/main/java/com/intuit/karate/core/PerfEvent.java @@ -28,15 +28,15 @@ * @author pthomas3 */ public class PerfEvent { - + private final String name; - private final long startTime; + private final long startTime; private final long endTime; private final int statusCode; - - private boolean failed; + + private boolean failed; private String message; - + public PerfEvent(long startTime, long endTime, String name, int statusCode) { this.name = name; this.startTime = startTime; @@ -50,15 +50,15 @@ public String getName() { public long getStartTime() { return startTime; - } + } public long getEndTime() { return endTime; } - + public int getStatusCode() { return statusCode; - } + } public boolean isFailed() { return failed; @@ -75,5 +75,16 @@ public String getMessage() { public void setMessage(String message) { this.message = message; } - + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("[name: ").append(name); + sb.append(", startTime: ").append(startTime); + sb.append(", endTime: ").append(endTime); + sb.append(", statusCode: ").append(statusCode); + sb.append("]"); + return sb.toString(); + } + } diff --git a/karate-core/src/main/java/com/intuit/karate/runtime/Config.java b/karate-core/src/main/java/com/intuit/karate/runtime/Config.java index d5dc6060d..98f6ed856 100644 --- a/karate-core/src/main/java/com/intuit/karate/runtime/Config.java +++ b/karate-core/src/main/java/com/intuit/karate/runtime/Config.java @@ -29,16 +29,19 @@ import com.intuit.karate.driver.Target; import com.intuit.karate.http.HttpLogModifier; import com.intuit.karate.server.Cookies; -import com.intuit.karate.server.HttpClientFactory; import java.nio.charset.Charset; import java.util.List; import java.util.Map; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * * @author pthomas3 */ public class Config { + + private static final Logger logger = LoggerFactory.getLogger(Config.class); public static final int DEFAULT_RETRY_INTERVAL = 3000; public static final int DEFAULT_RETRY_COUNT = 3; @@ -65,7 +68,7 @@ public class Config { private String localAddress; private int responseDelay; private boolean lowerCaseResponseHeaders = false; - private boolean corsEnabled = false; + private boolean corsEnabled = false; // TODO deprecate private boolean logPrettyRequest; private boolean logPrettyResponse; private boolean printEnabled = true; @@ -125,6 +128,7 @@ public boolean configure(String key, Variable value) { // TODO use enum lowerCaseResponseHeaders = value.isTrue(); return false; case "cors": + logger.warn("'cors' is deprecated, use server start api instead"); corsEnabled = value.isTrue(); return false; case "logPrettyResponse": diff --git a/karate-core/src/main/java/com/intuit/karate/runtime/FeatureRuntime.java b/karate-core/src/main/java/com/intuit/karate/runtime/FeatureRuntime.java index 035a3dc7f..53794c9b1 100644 --- a/karate-core/src/main/java/com/intuit/karate/runtime/FeatureRuntime.java +++ b/karate-core/src/main/java/com/intuit/karate/runtime/FeatureRuntime.java @@ -73,34 +73,27 @@ public PerfHook getPerfRuntime() { return perfRuntime; } - public void setCallArg(Map arg) { - if (arg != null) { - caller.setArg(new Variable(arg)); - } - } - public void setNext(Runnable next) { this.next = next; } - public FeatureRuntime(SuiteRuntime suite, Feature feature) { - this(suite, feature, ScenarioCall.none()); + public FeatureRuntime(SuiteRuntime suite, Feature feature, Map arg) { + this(suite, feature, ScenarioCall.none(arg)); } public FeatureRuntime(ScenarioCall call) { this(call.parentRuntime.featureRuntime.suite, call.feature, call); - Variable arg = call.getArg(); result.setLoopIndex(call.getLoopIndex()); - if (arg != null) { - result.setCallArg(arg.getValue()); + if (call.arg != null && !call.arg.isNull()) { + result.setCallArg(call.arg.getValue()); } } - private FeatureRuntime(SuiteRuntime suite, Feature feature, ScenarioCall parentCall) { + private FeatureRuntime(SuiteRuntime suite, Feature feature, ScenarioCall caller) { this.suite = suite; this.feature = feature; - this.caller = parentCall; - this.rootFeature = parentCall.isNone() ? this : parentCall.parentRuntime.featureRuntime; + this.caller = caller; + this.rootFeature = caller.isNone() ? this : caller.parentRuntime.featureRuntime; result = new FeatureResult(suite.results, feature); scenarios = new ScenarioGenerator(this, feature.getSections().iterator()); } diff --git a/karate-core/src/main/java/com/intuit/karate/runtime/MockHandler.java b/karate-core/src/main/java/com/intuit/karate/runtime/MockHandler.java index c230c4ed8..f5eec6241 100644 --- a/karate-core/src/main/java/com/intuit/karate/runtime/MockHandler.java +++ b/karate-core/src/main/java/com/intuit/karate/runtime/MockHandler.java @@ -38,6 +38,7 @@ import com.intuit.karate.server.ResourceType; import com.intuit.karate.server.Response; import com.intuit.karate.server.ServerHandler; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.function.BiFunction; @@ -72,6 +73,7 @@ public class MockHandler implements ServerHandler { private final Feature feature; private final String featureName; private final ScenarioRuntime runtime; // holds global config and vars + private final Map globals; protected static final ThreadLocal LOCAL_REQUEST = new ThreadLocal(); @@ -82,8 +84,7 @@ public MockHandler(Feature feature) { public MockHandler(Feature feature, Map args) { this.feature = feature; featureName = feature.getPath().toFile().getName(); - FeatureRuntime featureRuntime = new FeatureRuntime(SuiteRuntime.forMock(), feature); - featureRuntime.setCallArg(args); + FeatureRuntime featureRuntime = new FeatureRuntime(SuiteRuntime.forMock(), feature, args); FeatureSection section = new FeatureSection(); section.setIndex(-1); // TODO util for creating dummy scenario Scenario dummy = new Scenario(feature, section, -1); @@ -110,6 +111,7 @@ public MockHandler(Feature feature, Map args) { } } runtime.logger.info("mock server initialized: {}", featureName); + globals = runtime.engine.detachVariables(); } private static final Result PASSED = Result.passed(0); @@ -119,7 +121,7 @@ public Response handle(Request req) { Thread.currentThread().setContextClassLoader(runtime.featureRuntime.suite.classLoader); LOCAL_REQUEST.set(req); req.processBody(); - ScenarioEngine engine = new ScenarioEngine(runtime); + ScenarioEngine engine = new ScenarioEngine(runtime, new HashMap(globals)); engine.setVariable(ScenarioEngine.REQUEST_URL_BASE, req.getUrlBase()); engine.setVariable(ScenarioEngine.REQUEST_URI, req.getPath()); engine.setVariable(ScenarioEngine.REQUEST_METHOD, req.getMethod()); @@ -160,7 +162,7 @@ public Response handle(Request req) { break; } } - Map vars = runtime.engine.vars; + Map vars = engine.vars; response = vars.remove(ScenarioEngine.RESPONSE); responseStatus = vars.remove(ScenarioEngine.RESPONSE_STATUS); responseHeaders = vars.remove(ScenarioEngine.RESPONSE_HEADERS); diff --git a/karate-core/src/main/java/com/intuit/karate/runtime/MockServer.java b/karate-core/src/main/java/com/intuit/karate/runtime/MockServer.java index 37c53996d..4264c1641 100644 --- a/karate-core/src/main/java/com/intuit/karate/runtime/MockServer.java +++ b/karate-core/src/main/java/com/intuit/karate/runtime/MockServer.java @@ -26,11 +26,12 @@ import com.intuit.karate.core.Feature; import com.intuit.karate.core.FeatureParser; import com.intuit.karate.server.HttpServer; -import com.intuit.karate.server.ServerHandler; +import com.intuit.karate.server.HttpServerHandler; import com.intuit.karate.server.SslContextFactory; -import com.linecorp.armeria.common.SessionProtocol; +import com.linecorp.armeria.server.HttpService; import com.linecorp.armeria.server.Server; import com.linecorp.armeria.server.ServerBuilder; +import com.linecorp.armeria.server.cors.CorsService; import java.io.File; import java.util.HashMap; import java.util.Map; @@ -41,8 +42,8 @@ */ public class MockServer extends HttpServer { - private MockServer(ServerBuilder sb, ServerHandler handler) { - super(sb, handler); + private MockServer(ServerBuilder sb) { + super(sb); } public static class Builder { @@ -54,6 +55,7 @@ public static class Builder { final Feature feature; int port; boolean ssl; + boolean corsEnabled; File certFile; File keyFile; Map args; @@ -92,6 +94,11 @@ public Builder arg(String name, Object value) { return this; } + public Builder corsEnabled() { + corsEnabled = true; + return this; + } + public MockServer build() { ServerBuilder sb = Server.builder(); if (ssl) { @@ -105,7 +112,12 @@ public MockServer build() { sb.http(port); } MockHandler mockHandler = new MockHandler(feature, args); - return new MockServer(sb, mockHandler); + HttpService service = new HttpServerHandler(mockHandler); + if (corsEnabled) { + service = service.decorate(CorsService.builderForAnyOrigin().newDecorator()); + } + sb.service("prefix:/", service); + return new MockServer(sb); } } diff --git a/karate-core/src/main/java/com/intuit/karate/runtime/ScenarioBridge.java b/karate-core/src/main/java/com/intuit/karate/runtime/ScenarioBridge.java index 6122c5cc4..70456943d 100644 --- a/karate-core/src/main/java/com/intuit/karate/runtime/ScenarioBridge.java +++ b/karate-core/src/main/java/com/intuit/karate/runtime/ScenarioBridge.java @@ -25,10 +25,8 @@ import com.intuit.karate.FileUtils; import com.intuit.karate.PerfContext; -import com.intuit.karate.Resource; import com.intuit.karate.StringUtils; import com.intuit.karate.XmlUtils; -import com.intuit.karate.core.Feature; import com.intuit.karate.core.PerfEvent; import com.intuit.karate.core.Scenario; import com.intuit.karate.data.Json; @@ -49,7 +47,6 @@ import com.intuit.karate.shell.Command; import java.io.File; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.LinkedHashMap; @@ -723,8 +720,7 @@ public void stop(int port) { } public String toAbsolutePath(String relativePath) { - Resource resource = getEngine().fileReader.toResource(relativePath); - return resource.getPath().normalize().toAbsolutePath().toString(); + return getEngine().fileReader.toAbsolutePath(relativePath); } public Object toBean(Object o, String className) { diff --git a/karate-core/src/main/java/com/intuit/karate/runtime/ScenarioCall.java b/karate-core/src/main/java/com/intuit/karate/runtime/ScenarioCall.java index 6961ea5a4..dfb761dc5 100644 --- a/karate-core/src/main/java/com/intuit/karate/runtime/ScenarioCall.java +++ b/karate-core/src/main/java/com/intuit/karate/runtime/ScenarioCall.java @@ -35,9 +35,10 @@ public class ScenarioCall { public final ScenarioRuntime parentRuntime; public final int depth; public final Feature feature; + public final Variable arg; private boolean callonce; - private Variable arg; + private boolean sharedScope; private boolean karateConfigDisabled; private int loopIndex = -1; @@ -62,14 +63,6 @@ public boolean isSharedScope() { return sharedScope; } - public void setArg(Variable arg) { - this.arg = arg; - } - - public Variable getArg() { - return arg; - } - public boolean isCallonce() { return callonce; } @@ -85,12 +78,12 @@ public void setKarateConfigDisabled(boolean karateConfigDisabled) { public boolean isKarateConfigDisabled() { return karateConfigDisabled; } - - public static ScenarioCall none() { - return new ScenarioCall(null, null); + + public static ScenarioCall none(Map arg) { + return new ScenarioCall(null, null, arg == null ? null : new Variable(arg)); } - public ScenarioCall(ScenarioRuntime parentRuntime, Feature feature) { + public ScenarioCall(ScenarioRuntime parentRuntime, Feature feature, Variable arg) { this.parentRuntime = parentRuntime; this.feature = feature; if (parentRuntime == null) { @@ -98,6 +91,7 @@ public ScenarioCall(ScenarioRuntime parentRuntime, Feature feature) { } else { depth = parentRuntime.caller.depth + 1; } + this.arg = arg; } public static class Result { diff --git a/karate-core/src/main/java/com/intuit/karate/runtime/ScenarioEngine.java b/karate-core/src/main/java/com/intuit/karate/runtime/ScenarioEngine.java index 1b2a7d572..4b79bbf49 100644 --- a/karate-core/src/main/java/com/intuit/karate/runtime/ScenarioEngine.java +++ b/karate-core/src/main/java/com/intuit/karate/runtime/ScenarioEngine.java @@ -90,6 +90,8 @@ public class ScenarioEngine { private static final String KARATE = "karate"; private static final String READ = "read"; + private static final String DRIVER = "driver"; + private static final String ROBOT = "robot"; public static final String RESPONSE = "response"; public static final String RESPONSE_HEADERS = "responseHeaders"; @@ -102,13 +104,13 @@ public class ScenarioEngine { public static final String REQUEST = "request"; public static final String REQUEST_URL_BASE = "requestUrlBase"; public static final String REQUEST_URI = "requestUri"; - private static final String REQUEST_PARAMS = "requestParams"; + private static final String REQUEST_PARAMS = "requestParams"; public static final String REQUEST_METHOD = "requestMethod"; public static final String REQUEST_HEADERS = "requestHeaders"; private static final String REQUEST_TIME_STAMP = "requestTimeStamp"; public final ScenarioRuntime runtime; - protected final ScenarioFileReader fileReader; + public final ScenarioFileReader fileReader; public final Map vars; public final Logger logger; @@ -121,8 +123,8 @@ public class ScenarioEngine { private JsEngine JS; // only used by mock server - public ScenarioEngine(ScenarioRuntime runtime) { - this(runtime.engine.config, runtime, runtime.engine.vars, runtime.logger); + public ScenarioEngine(ScenarioRuntime runtime, Map vars) { + this(runtime.engine.config, runtime, vars, runtime.logger); } public ScenarioEngine(Config config, ScenarioRuntime runtime, Map vars, Logger logger) { @@ -664,6 +666,7 @@ private void httpInvokeOnce() { if (perfEventName != null) { PerfEvent pe = new PerfEvent(startTime, endTime, perfEventName, response.getStatus()); capturePerfEvent(pe); + } } @@ -809,6 +812,18 @@ public Object listen(long timeout, Runnable runnable) { private Driver driver; private Plugin robot; + private void autoDef(Plugin plugin, String instanceName) { + for (String methodName : plugin.methodNames()) { + String invoke = instanceName + "." + methodName; + String js = "(function(){ if (arguments.length == 0) return " + invoke + "();" + + " if (arguments.length == 1) return " + invoke + "(arguments[0]);" + + " if (arguments.length == 2) return " + invoke + "(arguments[0], arguments[1]);" + + " return " + invoke + "(arguments[0], arguments[1], arguments[2]) })"; + Variable v = evalJs(js); + setHiddenVariable(methodName, v); + } + } + public void driver(String expression) { } @@ -869,7 +884,7 @@ private void attachVariables() { }); } - private Map detachVariables() { + public Map detachVariables() { Map detached = new HashMap(vars.size()); vars.forEach((k, v) -> { switch (v.type) { @@ -1766,11 +1781,11 @@ private Variable callOnce(String cacheKey, Variable called, Variable arg, boolea public Variable callFeature(Feature feature, Variable arg, int index, boolean sharedScope) { if (arg == null || arg.isMap()) { - ScenarioCall call = new ScenarioCall(runtime, feature); - call.setArg(arg); + ScenarioCall call = new ScenarioCall(runtime, feature, arg); call.setLoopIndex(index); call.setSharedScope(sharedScope); FeatureRuntime fr = new FeatureRuntime(call); + fr.setPerfRuntime(runtime.featureRuntime.getPerfRuntime()); fr.run(); // VERY IMPORTANT ! switch back from called feature js context THREAD_LOCAL.set(this); diff --git a/karate-core/src/main/java/com/intuit/karate/runtime/ScenarioFileReader.java b/karate-core/src/main/java/com/intuit/karate/runtime/ScenarioFileReader.java index efa6004e0..e685a3cd2 100644 --- a/karate-core/src/main/java/com/intuit/karate/runtime/ScenarioFileReader.java +++ b/karate-core/src/main/java/com/intuit/karate/runtime/ScenarioFileReader.java @@ -81,11 +81,16 @@ public Object readFile(String text) { return FileUtils.toBytes(is); // TODO stream } } - + public File relativePathToFile(String relativePath) { return toResource(relativePath).getPath().toFile(); } - + + public String toAbsolutePath(String relativePath) { + Resource resource = toResource(relativePath); + return resource.getPath().normalize().toAbsolutePath().toString(); + } + public byte[] readFileAsBytes(String path) { return FileUtils.toBytes(readFileAsStream(path)); } diff --git a/karate-core/src/main/java/com/intuit/karate/runtime/ScenarioRuntime.java b/karate-core/src/main/java/com/intuit/karate/runtime/ScenarioRuntime.java index 86dc66d1a..13b990e23 100644 --- a/karate-core/src/main/java/com/intuit/karate/runtime/ScenarioRuntime.java +++ b/karate-core/src/main/java/com/intuit/karate/runtime/ScenarioRuntime.java @@ -44,7 +44,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import org.graalvm.polyglot.Value; /** * @@ -264,16 +263,15 @@ protected LogAppender initialValue() { private Map initMagicVariables() { Map map = new HashMap(); - Variable arg = caller.getArg(); if (caller.isNone()) { // if feature called via java api - if (arg != null && arg.isMap()) { - map.putAll(arg.getValue()); + if (caller.arg != null && caller.arg.isMap()) { + map.putAll(caller.arg.getValue()); } } else { - map.put("__arg", arg); + map.put("__arg", caller.arg); map.put("__loop", caller.getLoopIndex()); - if (arg != null && arg.isMap()) { - map.putAll(arg.getValue()); + if (caller.arg != null && caller.arg.isMap()) { + map.putAll(caller.arg.getValue()); } } if (scenario.isOutline() && !scenario.isDynamic()) { // init examples row magic variables diff --git a/karate-core/src/main/java/com/intuit/karate/server/HttpServer.java b/karate-core/src/main/java/com/intuit/karate/server/HttpServer.java index 4cc307a08..efc9cfa36 100644 --- a/karate-core/src/main/java/com/intuit/karate/server/HttpServer.java +++ b/karate-core/src/main/java/com/intuit/karate/server/HttpServer.java @@ -37,7 +37,6 @@ public class HttpServer { private static final Logger logger = LoggerFactory.getLogger(HttpServer.class); - private final ServerHandler handler; private final Server server; private final CompletableFuture future; private final int port; @@ -59,12 +58,12 @@ public CompletableFuture stop() { } public HttpServer(int port, ServerHandler handler) { - this(Server.builder().http(port), handler); + this(Server.builder() + .http(port) + .service("prefix:/", new HttpServerHandler(handler))); } - public HttpServer(ServerBuilder sb, ServerHandler handler) { - this.handler = handler; - sb.service("prefix:/", new HttpServerHandler(handler)); + public HttpServer(ServerBuilder sb) { server = sb.build(); future = server.start(); future.join(); diff --git a/karate-core/src/main/java/com/intuit/karate/server/HttpServerHandler.java b/karate-core/src/main/java/com/intuit/karate/server/HttpServerHandler.java index 651b53017..308cd6950 100644 --- a/karate-core/src/main/java/com/intuit/karate/server/HttpServerHandler.java +++ b/karate-core/src/main/java/com/intuit/karate/server/HttpServerHandler.java @@ -33,6 +33,7 @@ import com.linecorp.armeria.server.HttpService; import com.linecorp.armeria.server.ServiceRequestContext; import io.netty.util.AsciiString; +import java.time.Duration; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -55,7 +56,7 @@ public HttpResponse serve(ServiceRequestContext ctx, HttpRequest req) throws Exc return HttpResponse.from(req.aggregate().thenApply(ahr -> { Request request = toRequest(ctx, ahr); Response response = handler.handle(request); - return toResponse(response); + return toResponse(ctx, response); })); } @@ -81,7 +82,7 @@ private Request toRequest(ServiceRequestContext ctx, AggregatedHttpRequest req) return request; } - private HttpResponse toResponse(Response response) { + private HttpResponse toResponse(ServiceRequestContext ctx, Response response) { byte[] body = response.getBody(); if (body == null) { body = HttpConstants.ZERO_BYTES; @@ -91,7 +92,12 @@ private HttpResponse toResponse(Response response) { if (headers != null) { headers.forEach((k, v) -> rhb.add(k, v)); } - return HttpResponse.of(rhb.build(), HttpData.wrap(body)); + HttpResponse hr = HttpResponse.of(rhb.build(), HttpData.wrap(body)); + if (response.getDelay() > 0) { + return HttpResponse.delayed(hr, Duration.ofMillis(response.getDelay()), ctx.eventLoop()); + } else { + return hr; + } } } diff --git a/karate-core/src/main/java/com/intuit/karate/server/Response.java b/karate-core/src/main/java/com/intuit/karate/server/Response.java index b6086345e..14244386c 100644 --- a/karate-core/src/main/java/com/intuit/karate/server/Response.java +++ b/karate-core/src/main/java/com/intuit/karate/server/Response.java @@ -30,7 +30,6 @@ import com.intuit.karate.graal.JsList; import com.intuit.karate.graal.JsValue; import io.netty.handler.codec.http.cookie.Cookie; -import io.netty.handler.codec.http.cookie.DefaultCookie; import io.netty.handler.codec.http.cookie.ServerCookieDecoder; import java.util.ArrayList; import java.util.Arrays; diff --git a/karate-core/src/test/java/com/intuit/karate/MatchTest.java b/karate-core/src/test/java/com/intuit/karate/MatchTest.java index 6df978c27..6039ef968 100644 --- a/karate-core/src/test/java/com/intuit/karate/MatchTest.java +++ b/karate-core/src/test/java/com/intuit/karate/MatchTest.java @@ -12,7 +12,7 @@ */ class MatchTest { - private static final Logger logger = LoggerFactory.getLogger(MatchTest.class); + static final Logger logger = LoggerFactory.getLogger(MatchTest.class); @Test void testSomeMatches() { diff --git a/karate-core/src/test/java/com/intuit/karate/runtime/PerfHookTest.java b/karate-core/src/test/java/com/intuit/karate/runtime/PerfHookTest.java new file mode 100644 index 000000000..0ef7b60be --- /dev/null +++ b/karate-core/src/test/java/com/intuit/karate/runtime/PerfHookTest.java @@ -0,0 +1,73 @@ +package com.intuit.karate.runtime; + +import com.intuit.karate.PerfHook; +import com.intuit.karate.Runner; +import com.intuit.karate.core.PerfEvent; +import com.intuit.karate.server.HttpRequest; +import java.util.Collections; +import java.util.Map; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * + * @author pthomas3 + */ +class PerfHookTest { + + static final Logger logger = LoggerFactory.getLogger(PerfHookTest.class); + + static MockServer server; + + @BeforeAll + static void beforeAll() { + server = MockServer + .feature("classpath:com/intuit/karate/runtime/perf-mock.feature") + .http(0).build(); + System.setProperty("karate.server.port", server.getPort() + ""); + } + + @AfterAll + static void afterAll() { + server.stop(); + } + + @Test + void testPerfHook() { + Map arg = Collections.singletonMap("foo", "bar"); + Runner.callAsync("classpath:com/intuit/karate/runtime/perf.feature", Collections.EMPTY_LIST, arg, perfHook); + assertEquals(eventName, "http://localhost:" + server.getPort() + "/hello?foo=bar"); + } + + String eventName; + + PerfHook perfHook = new PerfHook() { + + @Override + public String getPerfEventName(HttpRequest request, ScenarioRuntime sr) { + return request.getUrl(); + } + + @Override + public void reportPerfEvent(PerfEvent event) { + eventName = event.getName(); + logger.debug("perf event: {}", eventName); + } + + @Override + public void submit(Runnable runnable) { + logger.debug("submit called"); + runnable.run(); + } + + @Override + public void afterFeature() { + logger.debug("afterFeature called"); + } + }; + +} diff --git a/karate-core/src/test/java/com/intuit/karate/runtime/RuntimeUtils.java b/karate-core/src/test/java/com/intuit/karate/runtime/RuntimeUtils.java index 1e07e9040..b2af50338 100644 --- a/karate-core/src/test/java/com/intuit/karate/runtime/RuntimeUtils.java +++ b/karate-core/src/test/java/com/intuit/karate/runtime/RuntimeUtils.java @@ -42,7 +42,7 @@ public InputStream getStream() { public static ScenarioRuntime runtime() { Feature feature = toFeature("* print 'test'"); - FeatureRuntime fr = new FeatureRuntime(new SuiteRuntime(), feature); + FeatureRuntime fr = new FeatureRuntime(new SuiteRuntime(), feature, null); ScenarioGenerator sg = new ScenarioGenerator(fr, feature.getSections().iterator()); return sg.next(); } @@ -54,7 +54,7 @@ public static ScenarioRuntime runScenario(HttpClientFactory clientFactory, Strin public static ScenarioRuntime run(HttpClientFactory clientFactory, Feature feature) { Runner.Builder builder = new Runner.Builder(); builder.clientFactory(clientFactory); - FeatureRuntime fr = new FeatureRuntime(new SuiteRuntime(builder), feature); + FeatureRuntime fr = new FeatureRuntime(new SuiteRuntime(builder), feature, null); ScenarioGenerator sg = new ScenarioGenerator(fr, feature.getSections().iterator()); ScenarioRuntime sr = sg.next(); sr.run(); @@ -69,7 +69,7 @@ public static FeatureRuntime runFeature(String path, String configDir) { Feature feature = FeatureParser.parse(path); Runner.Builder rb = new Runner.Builder(); rb.configDir(configDir); - FeatureRuntime fr = new FeatureRuntime(new SuiteRuntime(rb), feature); + FeatureRuntime fr = new FeatureRuntime(new SuiteRuntime(rb), feature, null); fr.run(); return fr; } diff --git a/karate-core/src/test/java/com/intuit/karate/runtime/mock/MockRunner.java b/karate-core/src/test/java/com/intuit/karate/runtime/mock/MockRunner.java index acd2c58b8..397b0adcd 100644 --- a/karate-core/src/test/java/com/intuit/karate/runtime/mock/MockRunner.java +++ b/karate-core/src/test/java/com/intuit/karate/runtime/mock/MockRunner.java @@ -1,12 +1,9 @@ package com.intuit.karate.runtime.mock; -import com.intuit.karate.FileUtils; import com.intuit.karate.Results; import com.intuit.karate.Runner; -import com.intuit.karate.core.FeatureParser; import com.intuit.karate.runtime.*; import com.intuit.karate.server.HttpServer; -import java.io.File; import static org.junit.jupiter.api.Assertions.*; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; @@ -22,9 +19,9 @@ class MockRunner { static final Logger logger = LoggerFactory.getLogger(MockRunner.class); static HttpServer startMockServer() { - File file = FileUtils.getFileRelativeTo(MockTest.class, "_mock.feature"); - MockHandler mock = new MockHandler(FeatureParser.parse(file)); - HttpServer server = new HttpServer(0, mock); + MockServer server = MockServer + .feature("classpath:com/intuit/karate/runtime/mock/_mock.feature") + .http(0).build(); System.setProperty("karate.server.port", server.getPort() + ""); return server; } diff --git a/karate-core/src/test/java/com/intuit/karate/runtime/perf-mock.feature b/karate-core/src/test/java/com/intuit/karate/runtime/perf-mock.feature new file mode 100644 index 000000000..78f42d49f --- /dev/null +++ b/karate-core/src/test/java/com/intuit/karate/runtime/perf-mock.feature @@ -0,0 +1,4 @@ +Feature: + +Scenario: pathMatches('/hello') +* def response = requestParams diff --git a/karate-core/src/test/java/com/intuit/karate/runtime/perf.feature b/karate-core/src/test/java/com/intuit/karate/runtime/perf.feature new file mode 100644 index 000000000..d087ac6e4 --- /dev/null +++ b/karate-core/src/test/java/com/intuit/karate/runtime/perf.feature @@ -0,0 +1,8 @@ +Feature: + +Scenario: +* url 'http://localhost:' + karate.properties['karate.server.port'] +* path 'hello' +* param foo = foo +* method get +* match response == { foo: ['bar'] } diff --git a/karate-gatling/src/test/scala/mock/MockUtils.java b/karate-gatling/src/test/scala/mock/MockUtils.java index e5f8aca56..f7f67c3ac 100644 --- a/karate-gatling/src/test/scala/mock/MockUtils.java +++ b/karate-gatling/src/test/scala/mock/MockUtils.java @@ -1,11 +1,8 @@ package mock; -import com.intuit.karate.FileUtils; import com.intuit.karate.PerfContext; -import com.intuit.karate.netty.FeatureServer; +import com.intuit.karate.runtime.MockServer; - -import java.io.File; import java.util.Collections; import java.util.Map; @@ -20,8 +17,7 @@ public static void main(String[] args) { } public static void startServer(int port) { - File file = FileUtils.getFileRelativeTo(MockUtils.class, "mock.feature"); - FeatureServer server = FeatureServer.start(file, port, false, null); + MockServer server = MockServer.feature("classpath:mock/mock.feature").http(port).build(); System.setProperty("mock.port", server.getPort() + ""); } diff --git a/karate-junit4/src/main/java/com/intuit/karate/junit4/Karate.java b/karate-junit4/src/main/java/com/intuit/karate/junit4/Karate.java index d25deb614..c87d5c23a 100644 --- a/karate-junit4/src/main/java/com/intuit/karate/junit4/Karate.java +++ b/karate-junit4/src/main/java/com/intuit/karate/junit4/Karate.java @@ -79,7 +79,7 @@ protected Description describeChild(Feature feature) { @Override protected void runChild(Feature feature, RunNotifier notifier) { hook.setNotifier(notifier); - FeatureRuntime fr = new FeatureRuntime(suite, feature); + FeatureRuntime fr = new FeatureRuntime(suite, feature, null); fr.run(); FeatureResult result = fr.result; if (!result.isEmpty()) { diff --git a/karate-junit5/src/main/java/com/intuit/karate/junit5/FeatureNode.java b/karate-junit5/src/main/java/com/intuit/karate/junit5/FeatureNode.java index 3b7c8f57a..a344f6768 100644 --- a/karate-junit5/src/main/java/com/intuit/karate/junit5/FeatureNode.java +++ b/karate-junit5/src/main/java/com/intuit/karate/junit5/FeatureNode.java @@ -50,7 +50,7 @@ public class FeatureNode implements Iterator, Iterable public FeatureNode(SuiteRuntime suite, HtmlSummaryReport summary, Feature feature, String tagSelector) { this.suite = suite; this.summary = summary; - featureRuntime = new FeatureRuntime(suite, feature); + featureRuntime = new FeatureRuntime(suite, feature, null); generator = featureRuntime.scenarios; }