Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
f-delahaye committed Nov 4, 2023
1 parent a213ae6 commit 266fe89
Show file tree
Hide file tree
Showing 17 changed files with 364 additions and 29 deletions.
79 changes: 57 additions & 22 deletions karate-gatling/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -32,48 +32,83 @@
<artifactId>scala-library</artifactId>
<version>2.13.9</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>${junit5.version}</version>
</dependency>


</dependencies>

<build>
<sourceDirectory>src/main/scala</sourceDirectory>
<!-- <testSourceDirectory>src/test/scala</testSourceDirectory> -->
<testResources>

<testResources>
<testResource>
<directory>src/test/resources</directory>
</testResource>
<testResource>
<directory>src/test/scala</directory>
<directory>src/test/java</directory>
<excludes>
<exclude>**/*.java</exclude>
<exclude>**/*.scala</exclude>
</excludes>
</testResource>
</testResources>
</testResources>


<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<executions>
<execution>
<id>default-compile</id>
<!-- Disable java compiler since Zinc will compile both scala and java sources -->
<phase>none</phase>
</execution>
<execution>
<id>default-testCompile</id>
<!-- Disable java compiler since Zinc will compile both scala and java sources -->
<phase>none</phase>
</execution>
</executions>
</plugin>

<plugin>
<groupId>net.alchim31.maven</groupId>
<artifactId>scala-maven-plugin</artifactId>
<version>4.8.1</version>
<configuration>
<args>
<arg>-Jbackend:GenBCode</arg>
<arg>-Jdelambdafy:method</arg>
<arg>-release:11</arg>
<arg>-deprecation</arg>
<arg>-feature</arg>
<arg>-unchecked</arg>
<arg>-language:implicitConversions</arg>
<arg>-language:postfixOps</arg>
</args>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>testCompile</goal>
</goals>
<configuration>
<args>
<arg>-Jbackend:GenBCode</arg>
<arg>-Jdelambdafy:method</arg>
<arg>-release:11</arg>
<arg>-deprecation</arg>
<arg>-feature</arg>
<arg>-unchecked</arg>
<arg>-language:implicitConversions</arg>
<arg>-language:postfixOps</arg>
</args>
</configuration>
<id>scala-compile</id>
<phase>compile</phase>
<goals>
<goal>add-source</goal>
<goal>compile</goal>
</goals>
</execution>
<execution>
<id>scala-test-compile</id>
<phase>test-compile</phase>
<goals>
<goal>add-source</goal>
<goal>testCompile</goal>
</goals>
</execution>
</executions>

</plugin>
<plugin>
<groupId>io.gatling</groupId>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package com.intuit.karate.gatling.javaapi;

import java.util.Map;
import java.util.Set;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;

import io.gatling.javaapi.core.*;
import io.gatling.javaapi.core.internal.Converters;
import io.gatling.javaapi.http.*;
import scala.collection.mutable.ArrayBuffer;
import scala.collection.mutable.Buffer;
import scala.collection.immutable.Seq;

import com.intuit.karate.gatling.PreDef;
import com.intuit.karate.gatling.javaapi.KarateUriPattern;
import com.intuit.karate.gatling.javaapi.KarateUriPattern.KarateUriPatternBuilder;
import com.intuit.karate.gatling.MethodPause;

import static io.gatling.javaapi.core.CoreDsl.*;
import static io.gatling.javaapi.http.HttpDsl.*;

public class KarateDsl {

public static KarateUriPatternBuilder uri(String uri) {
return new KarateUriPatternBuilder(uri);
}

public static KarateProtocolBuilder karateProtocol(KarateUriPattern... patterns) {
return new KarateProtocolBuilder(Arrays.stream(patterns).collect(Collectors.toMap(KarateUriPattern::getUri, pattern -> Converters.toScalaSeq(pattern.getPauses()))));
}

public static ActionBuilder karateFeature(String name, String... tags) {
return () -> PreDef.karateFeature(name, Converters.toScalaSeq(tags));
}


public static ActionBuilder karateSet(String key, final Function<Session, Object> supplier) {
return () -> PreDef.karateSet(key, session -> supplier.apply(new Session(session)));
}

public static MethodPause method(String method, int durationInMillis) {
return new MethodPause(method, durationInMillis);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package com.intuit.karate.gatling.javaapi;


import java.util.Collections;
import java.util.function.BiFunction;

import com.intuit.karate.Runner;
import com.intuit.karate.core.ScenarioRuntime;
import com.intuit.karate.gatling.KarateProtocol;
import com.intuit.karate.gatling.MethodPause;
import com.intuit.karate.http.HttpRequest;

import io.gatling.core.protocol.Protocol;
import io.gatling.javaapi.core.ProtocolBuilder;
import io.gatling.javaapi.core.internal.Converters;
import scala.collection.immutable.Seq;
import scala.collection.immutable.Map;

public class KarateProtocolBuilder implements ProtocolBuilder {

public BiFunction<HttpRequest, ScenarioRuntime, String> nameResolver;
public Runner.Builder runner = new Runner.Builder();

private final Map<String, Seq<MethodPause>> uriPatterns;

// Takes a JAVA Map (easier for testing) containaing SCALA MethodPauses (easier to read, save an extra Java MethodPause class and another conversion)
public KarateProtocolBuilder(java.util.Map<String, Seq<MethodPause>> uriPatterns) {
this.uriPatterns = Converters.toScalaMap(uriPatterns);
}

@Override
public KarateProtocol protocol() {
KarateProtocol protocol = new KarateProtocol(uriPatterns);
if (nameResolver != null) {
protocol.nameResolver_$eq((req, sr) -> nameResolver.apply(req, sr));
}
protocol.runner_$eq(runner);
return protocol;
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package com.intuit.karate.gatling.javaapi;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import com.intuit.karate.gatling.MethodPause;

/** CLass to be used as a parameter of KarateDsl.karateProtocol.
*
* Instances are obtained from KarateDsl.uri(<uri>) chained with nil() or pauseFor() and won't typically be created directly.
*/
public class KarateUriPattern {
final String uri;
final List<MethodPause> pauses;

KarateUriPattern(String uri, List<MethodPause> pauses) {
this.uri = uri;
this.pauses = pauses;
}

String getUri() {
return uri;
}

List<MethodPause> getPauses() {
return pauses;
}

public static class KarateUriPatternBuilder {
private final String uri;

KarateUriPatternBuilder(String uri) {
this.uri = uri;
}

/**
* Creates a uriPattern with no pauses
* @return
*/
public KarateUriPattern nil() {
return new KarateUriPattern(uri, Collections.emptyList());
}

public KarateUriPattern pauseFor(String method, int durationInMillis) {
return pauseFor(KarateDsl.method(method, durationInMillis));
}

public KarateUriPattern pauseFor(String method1, int durationInMillis1, String method2, int durationInMillis2) {
return pauseFor(KarateDsl.method(method1, durationInMillis1), KarateDsl.method(method2, durationInMillis2));
}

public KarateUriPattern pauseFor(MethodPause... pauses) {
return new KarateUriPattern(uri, Arrays.asList(pauses));
}
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package com.intuit.karate.gatling.javaapi;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.lang.reflect.Field;
import java.util.Collections;
import java.util.function.BiFunction;

import org.junit.jupiter.api.Test;

import com.intuit.karate.Runner;
import com.intuit.karate.core.ScenarioRuntime;
import com.intuit.karate.http.HttpRequest;

import io.gatling.javaapi.core.internal.Converters;

import com.intuit.karate.gatling.KarateProtocol;
import com.intuit.karate.gatling.MethodPause;


class KarateProtocolBuilderTest {

// Validates that the supplied nameResolver, runner and uriPatterns are taken into account.
@Test
void karateProtocol() throws Exception {
KarateProtocolBuilder protocolBuilder = new KarateProtocolBuilder(Collections.singletonMap("foo", Converters.toScalaSeq(Collections.singletonList(new MethodPause("get", 110)))));

protocolBuilder.nameResolver = (req, sr) -> "test name resolver";

protocolBuilder.runner.karateEnv("test");

KarateProtocol protocol = protocolBuilder.protocol();

assertEquals("test name resolver", protocol.nameResolver().apply(null, null));

Field envField = Runner.Builder.class.getDeclaredField("env");
envField.setAccessible(true);
String env = (String)envField.get(protocol.runner());

assertEquals("test", env);

assertEquals(110, protocol.pauseFor("foo", "get"));
}

@Test
void uriPatterns() {

KarateProtocol protocol = KarateDsl.karateProtocol(
KarateDsl.uri("foo").nil(),
KarateDsl.uri("bar").pauseFor("get", 110, "post", 220)
).protocol();

assertEquals(110, protocol.pauseFor("bar", "get"));
assertEquals(220, protocol.pauseFor("bar", "post"));
assertEquals(0, protocol.pauseFor("bar", "put"));
assertEquals(0, protocol.pauseFor("foo", "get"));
assertEquals(0, protocol.pauseFor("foobar", "get"));

assertTrue(protocol.pathMatches("/foo").isDefined());
assertTrue(protocol.pathMatches("/bar").isDefined());
assertFalse(protocol.pathMatches("/foobar").isDefined());

}
}
45 changes: 45 additions & 0 deletions karate-gatling/src/test/java/mock/CatsChainedSimulation.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package mock;

import java.util.Collections;
import java.util.Iterator;
import java.util.Map;
import java.util.Random;
import java.util.stream.Stream;
import static com.intuit.karate.gatling.javaapi.KarateDsl.*;
import static io.gatling.javaapi.core.CoreDsl.details;
import static io.gatling.javaapi.core.CoreDsl.feed;
import static io.gatling.javaapi.core.CoreDsl.rampUsers;
import static io.gatling.javaapi.core.CoreDsl.scenario;

import io.gatling.javaapi.core.*;

public class CatsChainedSimulation extends Simulation {

public CatsChainedSimulation() {
MockUtils.startServer(0);

ProtocolBuilder protocol = karateProtocol(uri("/cats/{id}").nil());

Iterator<Map<String, Object>> feeder = Stream.generate(() -> Collections.<String, Object>singletonMap("name", new Random().nextInt(20)+"-name")).iterator();

ScenarioBuilder createAndRead = scenario("createAndRead")
.group("createAndRead").on(
feed(() -> feeder)
.exec(karateSet("name", session -> session.getString("name")))
.exec(karateFeature("classpath:mock/cats-chained.feature@name=create"))
// for demo: injecting a new variable name expected by the 'read' feature
.exec(karateSet("expectedName", session -> session.getString("name")))
.exec(karateFeature("classpath:mock/cats-chained.feature@name=read")).exec(session -> {
System.out.println("*** id in gatling: " + session.getString("id"));
System.out.println("*** session status in gatling: " + session.asScala().status());
return session;
}));


setUp(
createAndRead.injectOpen(rampUsers(10).during(5)).protocols(protocol)
).assertions(details("createAndRead").failedRequests().percent().is(0d));

}

}
Loading

0 comments on commit 266fe89

Please sign in to comment.