You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jmeter.apache.org by vl...@apache.org on 2019/09/27 07:55:52 UTC

[jmeter] branch master updated: Refactor HttpMetricsSenderTest to WireMock

This is an automated email from the ASF dual-hosted git repository.

vladimirsitnikov pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/jmeter.git


The following commit(s) were added to refs/heads/master by this push:
     new b6fc9b4  Refactor HttpMetricsSenderTest to WireMock
b6fc9b4 is described below

commit b6fc9b4724a7c63d499c87ac0c4f4e17893fcbbf
Author: Vladimir Sitnikov <si...@gmail.com>
AuthorDate: Fri Sep 27 10:55:27 2019 +0300

    Refactor HttpMetricsSenderTest to WireMock
    
    This improves error reporting and allows to start the server just once per test.
---
 settings.gradle.kts                                |   1 +
 src/build.gradle.kts                               |   3 +-
 src/components/build.gradle.kts                    |   1 +
 .../jmeter/extractor/TestXPathExtractor.java       |  12 +-
 .../backend/influxdb/HttpMetricsSenderTest.java    | 136 ++++++++-------------
 .../org/apache/jorphan/exec/TestKeyToolUtils.java  |  41 +++----
 src/protocol/build.gradle.kts                      |   1 +
 src/testkit-wiremock/build.gradle.kts              |  29 +++++
 .../apache/jmeter/wiremock/RequestCountDown.java   |  39 ++++++
 .../apache/jmeter/wiremock/WireMockExtension.java  |  12 +-
 10 files changed, 157 insertions(+), 118 deletions(-)

diff --git a/settings.gradle.kts b/settings.gradle.kts
index 764a9c7..b04ae53 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -46,6 +46,7 @@ include(
         "src:protocol:tcp",
         "src:release",
         "src:testkit",
+        "src:testkit-wiremock",
         "src:dist",
         "src:dist-check")
 
diff --git a/src/build.gradle.kts b/src/build.gradle.kts
index 3cbb3ae..549b737 100644
--- a/src/build.gradle.kts
+++ b/src/build.gradle.kts
@@ -25,7 +25,8 @@ val skipMavenPublication = setOf(
     ":src:licenses",
     ":src:protocol",
     ":src:release",
-    ":src:testkit"
+    ":src:testkit",
+    ":src:testkit-wiremock"
 )
 
 subprojects {
diff --git a/src/components/build.gradle.kts b/src/components/build.gradle.kts
index eebc4ed..ec467a8 100644
--- a/src/components/build.gradle.kts
+++ b/src/components/build.gradle.kts
@@ -71,6 +71,7 @@ dependencies {
     testRuntimeOnly("org.bouncycastle:bcpkix-jdk15on")
     testRuntimeOnly("org.bouncycastle:bcprov-jdk15on")
     testImplementation("nl.jqno.equalsverifier:equalsverifier")
+    testImplementation(testFixtures(project(":src:testkit-wiremock")))
 }
 
 fun String?.toBool(nullAs: Boolean, blankAs: Boolean, default: Boolean) =
diff --git a/src/components/src/test/java/org/apache/jmeter/extractor/TestXPathExtractor.java b/src/components/src/test/java/org/apache/jmeter/extractor/TestXPathExtractor.java
index a7968d2..614cf37 100644
--- a/src/components/src/test/java/org/apache/jmeter/extractor/TestXPathExtractor.java
+++ b/src/components/src/test/java/org/apache/jmeter/extractor/TestXPathExtractor.java
@@ -19,6 +19,8 @@
 package org.apache.jmeter.extractor;
 
 
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.hamcrest.MatcherAssert.assertThat;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNull;
 
@@ -26,11 +28,11 @@ import java.io.UnsupportedEncodingException;
 import java.util.Locale;
 
 import org.apache.commons.lang3.StringUtils;
+import org.apache.jmeter.assertions.AssertionResult;
 import org.apache.jmeter.samplers.SampleResult;
 import org.apache.jmeter.threads.JMeterContext;
 import org.apache.jmeter.threads.JMeterContextService;
 import org.apache.jmeter.threads.JMeterVariables;
-import org.hamcrest.CoreMatchers;
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
@@ -281,9 +283,9 @@ public class TestXPathExtractor {
                 extractor.setXPathQuery("<");
                 extractor.process();
                 assertEquals(1, result.getAssertionResults().length);
-                assertEquals(extractor.getName(), result.getAssertionResults()[0].getName());
-                Assert.assertTrue(result.getAssertionResults()[0].
-                        getFailureMessage().contains("A location path was expected, but the following token was encountered"));
+                AssertionResult firstResult = result.getAssertionResults()[0];
+                assertEquals(extractor.getName(), firstResult.getName());
+                assertThat(firstResult.getFailureMessage(), containsString("A location path was expected, but the following token was encountered"));
                 assertEquals("Default", vars.get(VAL_NAME));
                 assertEquals("0", vars.get(VAL_NAME_NR));
             } finally {
@@ -312,7 +314,7 @@ public class TestXPathExtractor {
             assertEquals(1, result.getAssertionResults().length);
             assertEquals(extractor.getName(), result.getAssertionResults()[0].getName());
             org.junit.Assert.assertThat(result.getAssertionResults()[0].
-                    getFailureMessage(), CoreMatchers.containsString("XML document structures must start and end within the same entity"));
+                    getFailureMessage(), containsString("XML document structures must start and end within the same entity"));
 
             assertEquals("Default", vars.get(VAL_NAME));
             assertEquals("0", vars.get(VAL_NAME_NR));
diff --git a/src/components/src/test/java/org/apache/jmeter/visualizers/backend/influxdb/HttpMetricsSenderTest.java b/src/components/src/test/java/org/apache/jmeter/visualizers/backend/influxdb/HttpMetricsSenderTest.java
index 9737df0..26e4d37 100644
--- a/src/components/src/test/java/org/apache/jmeter/visualizers/backend/influxdb/HttpMetricsSenderTest.java
+++ b/src/components/src/test/java/org/apache/jmeter/visualizers/backend/influxdb/HttpMetricsSenderTest.java
@@ -18,98 +18,66 @@
 
 package org.apache.jmeter.visualizers.backend.influxdb;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
+import static org.junit.jupiter.params.provider.Arguments.arguments;
 
-import java.io.IOException;
-import java.util.Objects;
-import java.util.concurrent.BlockingDeque;
-import java.util.concurrent.LinkedBlockingDeque;
+import java.net.HttpURLConnection;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
-import java.util.stream.IntStream;
-
-import org.apache.http.HttpRequest;
-import org.apache.http.HttpStatus;
-import org.apache.http.impl.bootstrap.HttpServer;
-import org.apache.http.impl.bootstrap.ServerBootstrap;
-import org.apache.http.protocol.HttpRequestHandler;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
 
+import org.apache.jmeter.wiremock.WireMockExtension;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import com.github.tomakehurst.wiremock.WireMockServer;
+import com.github.tomakehurst.wiremock.client.MappingBuilder;
+import com.github.tomakehurst.wiremock.client.WireMock;
+import com.github.tomakehurst.wiremock.extension.Parameters;
+import com.github.tomakehurst.wiremock.http.RequestMethod;
+import com.github.tomakehurst.wiremock.matching.RequestPatternBuilder;
+import com.github.tomakehurst.wiremock.matching.StringValuePattern;
+
+@ExtendWith(WireMockExtension.class)
 public class HttpMetricsSenderTest {
-
-    private HttpServer server;
-    private BlockingDeque<HttpRequest> resultQueue = new LinkedBlockingDeque<>();
-
-    @Before
-    public void startServer() {
-
-        HttpRequestHandler requestHandler = (request, response, context) -> {
-            HttpMetricsSenderTest.this.resultQueue.add(request);
-            response.setStatusCode(HttpStatus.SC_NO_CONTENT);
-        };
-
-        // Start HttpServer on free port
-        server = IntStream
-                .range(8183, 8283)
-                .mapToObj(port -> {
-                    HttpServer httpServer = ServerBootstrap.bootstrap()
-                            .setListenerPort(port)
-                            .registerHandler("*", requestHandler)
-                            .create();
-                    try {
-                        httpServer.start();
-                        return httpServer;
-                    } catch (IOException e) {
-                        return null;
-                    }
-                })
-                .filter(Objects::nonNull)
-                .findFirst()
-                .orElseThrow(() -> new AssertionError("Cannot start HttpServer"));
-    }
-
-    @After
-    public void stopServer() {
-        server.shutdown(1, TimeUnit.SECONDS);
+    private static final String API_URL = "/api/v2/write";
+
+    private MappingBuilder influxRequest(CountDownLatch latch) {
+        return WireMock.post(API_URL)
+                .willReturn(
+                        WireMock.aResponse().withStatus(HttpURLConnection.HTTP_NO_CONTENT)
+                )
+                .withPostServeAction("countdown", Parameters.one("latch", latch));
     }
 
-    @Test
-    public void checkTokenDoesNotPresentInHeader() throws Exception {
-        String influxdbUrl = getInfluxDbUrl();
-        setupSenderAndSendMetric(influxdbUrl, null);
-
-        assertNoAuthHeader(resultQueue.take());
+    static Collection<Arguments> emptyTokens() {
+        return Arrays.asList(arguments((String) null), arguments(""), arguments(" "));
     }
 
+    @ParameterizedTest(name = "[{index}] token=\"{0}\"")
+    @MethodSource("emptyTokens")
+    public void emptyTokenIsNotSentAsAuthorizedHeader(String token, WireMockServer server) throws Exception {
+        CountDownLatch latch = new CountDownLatch(1);
+        server.stubFor(influxRequest(latch));
 
-    @Test
-    public void checkEmptyTokenDoesNotPresentInHeader() throws Exception {
-        String influxdbUrl = getInfluxDbUrl();
-        setupSenderAndSendMetric(influxdbUrl, "");
+        setupSenderAndSendMetric(server.url(API_URL), token);
 
-        assertNoAuthHeader(resultQueue.take());
+        latch.await(2, TimeUnit.SECONDS);
+        assertAuthHeader(server, WireMock.absent());
     }
 
     @Test
-    public void checkEmptyOnlyWhitespaceTokenDoesNotPresentInHeader() throws Exception {
-        String influxdbUrl = getInfluxDbUrl();
-        setupSenderAndSendMetric(influxdbUrl, "  ");
+    public void checkTokenPresentInHeader(WireMockServer server) throws Exception {
+        CountDownLatch latch = new CountDownLatch(1);
+        server.stubFor(influxRequest(latch));
 
-        assertNoAuthHeader(resultQueue.take());
-    }
+        setupSenderAndSendMetric(server.url(API_URL), "my-token");
 
-    @Test
-    public void checkTokenPresentInHeader() throws Exception {
-        String influxdbUrl = getInfluxDbUrl();
-        setupSenderAndSendMetric(influxdbUrl, "my-token");
-
-        HttpRequest request = resultQueue.take();
-        assertEquals(
-                "The authorization header should be: 'Token my-token'",
-                "Token my-token",
-                request.getFirstHeader("Authorization").getValue());
+        latch.await(2, TimeUnit.SECONDS);
+        assertAuthHeader(server, WireMock.equalTo("Token my-token"));
     }
 
     private void setupSenderAndSendMetric(String influxdbUrl, String influxDBToken) throws Exception {
@@ -119,14 +87,10 @@ public class HttpMetricsSenderTest {
         metricsSender.writeAndSendMetrics();
     }
 
-    private void assertNoAuthHeader(HttpRequest request) {
-        assertNull(
-                "The authorization header shouldn't be defined.",
-                request.getFirstHeader("Authorization"));
+    private void assertAuthHeader(WireMockServer server, StringValuePattern authHeader) {
+        server.verify(1, RequestPatternBuilder
+                .newRequestPattern(RequestMethod.POST, WireMock.urlEqualTo(API_URL))
+                .withRequestBody(WireMock.matching("measurementlocation=west size=10 \\d{19}\\s*"))
+                .withHeader("Authorization", authHeader));
     }
-
-    private String getInfluxDbUrl() {
-        return String.format("http://localhost:%s/api/v2/write", Integer.valueOf(server.getLocalPort()));
-    }
-
 }
diff --git a/src/jorphan/src/test/java/org/apache/jorphan/exec/TestKeyToolUtils.java b/src/jorphan/src/test/java/org/apache/jorphan/exec/TestKeyToolUtils.java
index c2f4140..9c111d6 100644
--- a/src/jorphan/src/test/java/org/apache/jorphan/exec/TestKeyToolUtils.java
+++ b/src/jorphan/src/test/java/org/apache/jorphan/exec/TestKeyToolUtils.java
@@ -22,34 +22,32 @@ import static org.junit.Assert.fail;
 
 import java.io.File;
 import java.io.IOException;
+import java.nio.file.Path;
 import java.util.ArrayList;
 import java.util.List;
 
 import org.apache.jorphan.util.JOrphanUtils;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+import org.junit.jupiter.api.parallel.Execution;
+import org.junit.jupiter.api.parallel.ExecutionMode;
 
+@Execution(ExecutionMode.CONCURRENT)
 public class TestKeyToolUtils {
 
-    private File keystore;
-    private String password = JOrphanUtils.generateRandomAlphanumericPassword(32);
-    private int validity = 1;
+    private static File keystore;
+    private static String password;
+    private static final int validity = 1;
 
-    @Before
-    public void setup() throws IOException {
-        keystore = File.createTempFile("dummy-keystore", "jks");
-        keystore.deleteOnExit();
+    @BeforeAll
+    public static void setup(@TempDir Path keystoreDir) throws IOException {
+        keystore = keystoreDir.resolve("dummy-keystore.jks").toFile();
+        password = JOrphanUtils.generateRandomAlphanumericPassword(32);
         KeyToolUtils.generateProxyCA(keystore, password, validity );
     }
 
-    @After
-    public void cleanup() {
-        if (keystore.exists()) {
-            keystore.delete();
-        }
-    }
-
     /*
      * Check the assumption that a missing executable will generate
      * either an IOException or status which is neither 0 nor 1
@@ -60,13 +58,12 @@ public class TestKeyToolUtils {
         SystemCommand sc = new SystemCommand(null, null);
         List<String> arguments = new ArrayList<>();
         arguments.add("xyzqwas"); // should not exist
-        try {
+        Assertions.assertThrows(IOException.class, () -> {
             int status = sc.run(arguments);
-            if (status == 0 || status ==1) {
-                fail("Unexpected status " + status);
+            if (status == 0 || status == 1) {
+                fail("Missing executable should produce exit code of 0 or 1. Actual code is " + status);
             }
-        } catch (IOException expected) {
-        }
+        });
     }
 
     @Test
diff --git a/src/protocol/build.gradle.kts b/src/protocol/build.gradle.kts
index 860b732..b589b3d 100644
--- a/src/protocol/build.gradle.kts
+++ b/src/protocol/build.gradle.kts
@@ -75,6 +75,7 @@ project("http") {
         implementation("dnsjava:dnsjava:2.1.8")
         implementation("org.apache.httpcomponents:httpmime:4.5.8")
         implementation("org.brotli:dec:0.1.2")
+        testImplementation(testFixtures(project(":src:testkit-wiremock")))
         testImplementation("com.github.tomakehurst:wiremock-jre8")
     }
 
diff --git a/src/testkit-wiremock/build.gradle.kts b/src/testkit-wiremock/build.gradle.kts
new file mode 100644
index 0000000..b6b79ef
--- /dev/null
+++ b/src/testkit-wiremock/build.gradle.kts
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+plugins {
+    `java-test-fixtures`
+}
+
+dependencies {
+    api("com.github.tomakehurst:wiremock-jre8")
+    api("org.junit.jupiter:junit-jupiter-api")
+}
+
+// test-fixtures enable to share code across test modules
+// See https://docs.gradle.org/5.6/userguide/java_testing.html#sec:java_test_fixtures
diff --git a/src/testkit-wiremock/src/main/java/org/apache/jmeter/wiremock/RequestCountDown.java b/src/testkit-wiremock/src/main/java/org/apache/jmeter/wiremock/RequestCountDown.java
new file mode 100644
index 0000000..e272093
--- /dev/null
+++ b/src/testkit-wiremock/src/main/java/org/apache/jmeter/wiremock/RequestCountDown.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.jmeter.wiremock;
+
+import java.util.concurrent.CountDownLatch;
+
+import com.github.tomakehurst.wiremock.core.Admin;
+import com.github.tomakehurst.wiremock.extension.Parameters;
+import com.github.tomakehurst.wiremock.extension.PostServeAction;
+import com.github.tomakehurst.wiremock.stubbing.ServeEvent;
+
+public class RequestCountDown extends PostServeAction {
+    @Override
+    public String getName() {
+        return "countdown";
+    }
+
+    @Override
+    public void doAction(ServeEvent serveEvent, Admin admin, Parameters parameters) {
+        CountDownLatch latch = (CountDownLatch) parameters.get("latch");
+        latch.countDown();
+    }
+}
diff --git a/src/protocol/http/src/test/java/org/apache/jmeter/wiremock/WireMockExtension.java b/src/testkit-wiremock/src/main/java/org/apache/jmeter/wiremock/WireMockExtension.java
similarity index 88%
rename from src/protocol/http/src/test/java/org/apache/jmeter/wiremock/WireMockExtension.java
rename to src/testkit-wiremock/src/main/java/org/apache/jmeter/wiremock/WireMockExtension.java
index 4c106c7..bc48ff2 100644
--- a/src/protocol/http/src/test/java/org/apache/jmeter/wiremock/WireMockExtension.java
+++ b/src/testkit-wiremock/src/main/java/org/apache/jmeter/wiremock/WireMockExtension.java
@@ -34,10 +34,10 @@ public class WireMockExtension implements BeforeEachCallback, BeforeAllCallback,
             ExtensionContext.Namespace.create(WireMockExtension.class);
 
     @Override
-    public void beforeEach(ExtensionContext context) throws Exception {
+    public void beforeEach(ExtensionContext context) {
         WireMockServer server = getServer(context);
         if (server != null) {
-            server.resetScenarios();
+            server.resetAll();
         }
     }
 
@@ -60,8 +60,12 @@ public class WireMockExtension implements BeforeEachCallback, BeforeAllCallback,
     }
 
     @Override
-    public void beforeAll(ExtensionContext context) throws Exception {
-        WireMockServer server = new WireMockServer(WireMockConfiguration.wireMockConfig().dynamicPort());
+    public void beforeAll(ExtensionContext context) {
+        WireMockServer server = new WireMockServer(
+                WireMockConfiguration.wireMockConfig()
+                        .dynamicPort()
+                        .extensions(new RequestCountDown())
+        );
         server.start();
         getStore(context).put("server", server);
     }