Move IO Net unit tests (#1082)

* Move IO Net unit tests

All IO Net tests are unit tests so there is no need for an itests project.

Signed-off-by: Wouter Born <github@maindrain.net>
This commit is contained in:
Wouter Born
2019-10-03 20:00:04 +02:00
committed by Christoph Weitkamp
parent 4e07b56279
commit f1f0e9e52b
13 changed files with 6 additions and 134 deletions
@@ -1,32 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" output="target/classes" path="src/main/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="output" path="target/classes"/>
</classpath>
@@ -1,23 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>org.openhab.core.io.net.tests</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.m2e.core.maven2Nature</nature>
</natures>
</projectDescription>
@@ -1,14 +0,0 @@
This content is produced and maintained by the openHAB project.
* Project home: https://www.openhab.org
== Declared Project Licenses
This program and the accompanying materials are made available under the terms
of the Eclipse Public License 2.0 which is available at
https://www.eclipse.org/legal/epl-2.0/.
== Source Code
https://github.com/openhab/openhab-core
@@ -1,48 +0,0 @@
-include: ../itest-common.bndrun
Bundle-SymbolicName: ${project.artifactId}
Fragment-Host: org.openhab.core.io.net
-runrequires: \
bnd.identity;id='org.openhab.core.io.net.tests'
#
# done
#
-runbundles: \
javax.measure.unit-api;version='[1.0.0,1.0.1)',\
org.apache.commons.exec;version='[1.1.0,1.1.1)',\
org.apache.commons.lang;version='[2.6.0,2.6.1)',\
org.apache.felix.http.servlet-api;version='[1.1.2,1.1.3)',\
org.apache.felix.scr;version='[2.1.10,2.1.11)',\
org.eclipse.equinox.event;version='[1.4.300,1.4.301)',\
org.eclipse.jetty.client;version='[9.4.11,9.4.12)',\
org.eclipse.jetty.http;version='[9.4.11,9.4.12)',\
org.eclipse.jetty.io;version='[9.4.11,9.4.12)',\
org.eclipse.jetty.util;version='[9.4.11,9.4.12)',\
org.eclipse.jetty.websocket.api;version='[9.4.11,9.4.12)',\
org.eclipse.jetty.websocket.client;version='[9.4.11,9.4.12)',\
org.eclipse.jetty.websocket.common;version='[9.4.11,9.4.12)',\
org.eclipse.jetty.xml;version='[9.4.11,9.4.12)',\
org.mockito.mockito-core;version='[2.25.0,2.25.1)',\
org.objenesis;version='[2.6.0,2.6.1)',\
org.openhab.core;version='[2.5.0,2.5.1)',\
org.openhab.core.config.core;version='[2.5.0,2.5.1)',\
org.openhab.core.io.net;version='[2.5.0,2.5.1)',\
org.openhab.core.io.net.tests;version='[2.5.0,2.5.1)',\
org.openhab.core.storage.json;version='[2.5.0,2.5.1)',\
org.osgi.service.event;version='[1.4.0,1.4.1)',\
osgi.enroute.hamcrest.wrapper;version='[1.3.0,1.3.1)',\
osgi.enroute.junit.wrapper;version='[4.12.0,4.12.1)',\
ch.qos.logback.core;version='[1.2.3,1.2.4)',\
slf4j.api;version='[1.7.25,1.7.26)',\
ch.qos.logback.classic;version='[1.2.3,1.2.4)',\
net.bytebuddy.byte-buddy;version='[1.9.7,1.9.8)',\
net.bytebuddy.byte-buddy-agent;version='[1.9.7,1.9.8)',\
com.google.gson;version='[2.8.2,2.8.3)',\
org.apache.servicemix.specs.activation-api-1.1;version='[2.9.0,2.9.1)',\
org.apache.servicemix.specs.annotation-api-1.3;version='[1.3.0,1.3.1)',\
org.apache.servicemix.specs.jaxb-api-2.2;version='[2.9.0,2.9.1)',\
org.apache.servicemix.specs.stax-api-1.2;version='[2.9.0,2.9.1)',\
tec.uom.lib.uom-lib-common;version='[1.0.3,1.0.4)',\
tec.uom.se;version='[1.0.10,1.0.11)'
@@ -1,16 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.openhab.core.itests</groupId>
<artifactId>org.openhab.core.reactor.itests</artifactId>
<version>2.5.0-SNAPSHOT</version>
</parent>
<artifactId>org.openhab.core.io.net.tests</artifactId>
<name>openHAB Core :: Integration Tests :: Network I/O Tests</name>
</project>
@@ -1,69 +0,0 @@
/**
* Copyright (c) 2010-2019 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.eclipse.smarthome.io.net.http;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.when;
import static org.mockito.MockitoAnnotations.initMocks;
import java.lang.reflect.Field;
import java.util.concurrent.TimeUnit;
import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.client.api.ContentResponse;
import org.eclipse.jetty.client.api.Request;
import org.eclipse.jetty.http.HttpMethod;
import org.junit.Before;
import org.mockito.Mock;
/**
* Base class for tests for the <code>HttpRequestBuilder</code> and <code>HttpUtil</code> to validate their behavior
*
* @author Martin van Wingerden & Wouter Born - Initial contribution
* @author Markus Rathgeb - Base test classes without tests needs to be abstract
*/
public abstract class BaseHttpUtilTest {
static final String URL = "http://example.org/test";
@Mock
private HttpClientFactory clientFactoryMock;
@Mock
HttpClient httpClientMock;
@Mock
Request requestMock;
@Mock
ContentResponse contentResponseMock;
@Before
public void setUp() throws Exception {
initMocks(this);
Field httpClientFactory = HttpUtil.class.getDeclaredField("httpClientFactory");
httpClientFactory.setAccessible(true);
httpClientFactory.set(null, clientFactoryMock);
when(clientFactoryMock.getCommonHttpClient()).thenReturn(httpClientMock);
when(httpClientMock.newRequest(URL)).thenReturn(requestMock);
when(requestMock.method(any(HttpMethod.class))).thenReturn(requestMock);
when(requestMock.timeout(anyLong(), any(TimeUnit.class))).thenReturn(requestMock);
when(requestMock.send()).thenReturn(contentResponseMock);
}
void mockResponse(int httpStatus) {
when(contentResponseMock.getStatus()).thenReturn(httpStatus);
when(contentResponseMock.getContent()).thenReturn("Some content".getBytes());
}
}
@@ -1,120 +0,0 @@
/**
* Copyright (c) 2010-2019 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.eclipse.smarthome.io.net.http;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.verify;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.util.concurrent.TimeUnit;
import org.eclipse.jetty.client.api.ContentProvider;
import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.http.HttpStatus;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.ArgumentMatchers;
/**
* Test cases for the <code>HttpRequestBuilder</code> to validate its behaviour
*
* @author Martin van Wingerden & Wouter Born - Initial contribution
*/
public class HttpRequestBuilderTest extends BaseHttpUtilTest {
@Test
public void baseTest() throws Exception {
mockResponse(HttpStatus.OK_200);
String result = HttpRequestBuilder.getFrom(URL).getContentAsString();
assertEquals("Some content", result);
verify(httpClientMock).newRequest(URL);
verify(requestMock).method(HttpMethod.GET);
verify(requestMock).send();
}
@Test
public void testHeader() throws Exception {
mockResponse(HttpStatus.OK_200);
// @formatter:off
String result = HttpRequestBuilder.getFrom(URL)
.withHeader("Authorization", "Bearer sometoken")
.withHeader("X-Token", "test")
.getContentAsString();
// @formatter:on
assertEquals("Some content", result);
// verify the headers to be added to the request
verify(requestMock).header("Authorization", "Bearer sometoken");
verify(requestMock).header("X-Token", "test");
}
@Test
public void testTimeout() throws Exception {
mockResponse(HttpStatus.OK_200);
String result = HttpRequestBuilder.getFrom(URL).withTimeout(Duration.ofMillis(200)).getContentAsString();
assertEquals("Some content", result);
// verify the timeout to be forwarded
verify(requestMock).timeout(200, TimeUnit.MILLISECONDS);
}
@Test
public void testPostWithContent() throws Exception {
ArgumentCaptor<ContentProvider> argumentCaptor = ArgumentCaptor.forClass(ContentProvider.class);
mockResponse(HttpStatus.OK_200);
String result = HttpRequestBuilder.postTo(URL).withContent("{json: true}").getContentAsString();
assertEquals("Some content", result);
// verify the content to be added to the request
verify(requestMock).content(argumentCaptor.capture(), ArgumentMatchers.eq(null));
assertEquals("{json: true}", getContentFromProvider(argumentCaptor.getValue()));
}
private String getContentFromProvider(ContentProvider value) {
ByteBuffer element = value.iterator().next();
byte[] data = new byte[element.limit()];
// Explicit cast for compatibility with covariant return type on JDK 9's ByteBuffer
((ByteBuffer) ((Buffer) element.duplicate()).clear()).get(data);
return new String(data, StandardCharsets.UTF_8);
}
@Test
public void testPostWithContentType() throws Exception {
ArgumentCaptor<ContentProvider> argumentCaptor = ArgumentCaptor.forClass(ContentProvider.class);
mockResponse(HttpStatus.OK_200);
String result = HttpRequestBuilder.postTo(URL).withContent("{json: true}", "application/json")
.getContentAsString();
assertEquals("Some content", result);
// verify just the content-type to be added to the request
verify(requestMock).method(HttpMethod.POST);
verify(requestMock).content(argumentCaptor.capture(), ArgumentMatchers.eq("application/json"));
}
}
@@ -1,87 +0,0 @@
/**
* Copyright (c) 2010-2019 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.eclipse.smarthome.io.net.http;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.*;
import java.util.concurrent.TimeUnit;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.http.HttpStatus;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
/**
* Tests for the HttpUtil
*
* @author Thomas Eichstaedt-Engelen - Initial contribution
* @author Martin van Wingerden - Added tests based on HttpClientFactory
*/
public class HttpUtilTest extends BaseHttpUtilTest {
@Rule
public ExpectedException thrown = ExpectedException.none();
@Test
public void baseTest() throws Exception {
mockResponse(HttpStatus.OK_200);
String result = HttpUtil.executeUrl("GET", URL, 500);
assertEquals("Some content", result);
verify(httpClientMock).newRequest(URL);
verify(requestMock).method(HttpMethod.GET);
verify(requestMock).timeout(500, TimeUnit.MILLISECONDS);
verify(requestMock).send();
}
@Test
public void testAuthentication() throws Exception {
when(httpClientMock.newRequest("http://john:doe@example.org/")).thenReturn(requestMock);
mockResponse(HttpStatus.OK_200);
String result = HttpUtil.executeUrl("GET", "http://john:doe@example.org/", 500);
assertEquals("Some content", result);
verify(requestMock).header(HttpHeader.AUTHORIZATION, "Basic am9objpkb2U=");
}
@Test
public void testCreateHttpMethod() {
assertEquals(HttpMethod.GET, HttpUtil.createHttpMethod("GET"));
assertEquals(HttpMethod.PUT, HttpUtil.createHttpMethod("PUT"));
assertEquals(HttpMethod.POST, HttpUtil.createHttpMethod("POST"));
assertEquals(HttpMethod.DELETE, HttpUtil.createHttpMethod("DELETE"));
}
@Test
public void testCreateHttpMethodForUnsupportedFake() {
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage("Given HTTP Method 'FAKE' is unknown");
HttpUtil.createHttpMethod("FAKE");
}
@Test
public void testCreateHttpMethodForUnsupportedTrace() {
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage("Given HTTP Method 'TRACE' is unknown");
HttpUtil.createHttpMethod("TRACE");
}
}
@@ -1,197 +0,0 @@
/**
* Copyright (c) 2010-2019 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.eclipse.smarthome.io.net.http.internal;
import static org.mockito.Mockito.*;
import static org.mockito.MockitoAnnotations.initMocks;
import java.net.Socket;
import java.security.cert.CertificateException;
import java.security.cert.CertificateParsingException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.X509ExtendedTrustManager;
import javax.security.auth.x500.X500Principal;
import org.apache.commons.lang.reflect.FieldUtils;
import org.eclipse.smarthome.io.net.http.TlsTrustManagerProvider;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
/**
* Tests which validate the behavior of the ExtensibleTrustManager
*
* @author Martin van Wingerden - Initial contribution
*/
public class ExtensibleTrustManagerImplTest {
private ExtensibleTrustManagerImpl subject;
@Mock
private TlsTrustManagerProvider trustmanagerProvider;
@Mock
private TlsTrustManagerProvider trustmanagerProviderHostPort;
@Mock
private X509ExtendedTrustManager trustmanager;
@Mock
private X509ExtendedTrustManager trustmanager2;
@Mock
private X509ExtendedTrustManager defaultTrustManager;
@Mock
private SSLEngine sslEngine;
@Mock
private X509Certificate topOfChain;
@Mock
private X509Certificate bottomOfChain;
private X509Certificate[] chain;
@Before
public void setup() {
initMocks(this);
when(trustmanagerProvider.getHostName()).thenReturn("example.org");
when(trustmanagerProvider.getTrustManager()).thenReturn(trustmanager);
when(trustmanagerProviderHostPort.getHostName()).thenReturn("example.org:443");
when(trustmanagerProviderHostPort.getTrustManager()).thenReturn(trustmanager2);
subject = new ExtensibleTrustManagerImpl();
subject.addTlsTrustManagerProvider(trustmanagerProvider);
subject.addTlsTrustManagerProvider(trustmanagerProviderHostPort);
chain = new X509Certificate[] { topOfChain, bottomOfChain };
}
@Test
public void shouldForwardCallsToMockForMatchingCN() throws CertificateException {
when(topOfChain.getSubjectX500Principal())
.thenReturn(new X500Principal("CN=example.org, OU=Smarthome, O=Eclipse, C=DE"));
subject.checkServerTrusted(chain, "just");
verify(trustmanager).checkServerTrusted(chain, "just", (Socket) null);
verifyNoMoreInteractions(trustmanager, trustmanager2);
}
@Test
public void shouldForwardCallsToMockForMatchingHost() throws CertificateException {
when(sslEngine.getPeerHost()).thenReturn("example.org");
when(sslEngine.getPeerPort()).thenReturn(443);
subject.checkServerTrusted(chain, "just", sslEngine);
verify(trustmanager2).checkServerTrusted(chain, "just", sslEngine);
verifyNoMoreInteractions(trustmanager, trustmanager2);
}
@Test
public void shouldForwardCallsToMockForMatchingAlternativeNames() throws CertificateException {
when(topOfChain.getSubjectX500Principal())
.thenReturn(new X500Principal("CN=example.com, OU=Smarthome, O=Eclipse, C=DE"));
when(topOfChain.getSubjectAlternativeNames())
.thenReturn(constructAlternativeNames("example1.com", "example.org"));
subject.checkClientTrusted(chain, "just");
verify(trustmanager).checkClientTrusted(chain, "just", (Socket) null);
verifyNoMoreInteractions(trustmanager);
}
@Test
public void shouldBeResilientAgainstNullSubjectAlternativeNames()
throws CertificateException, IllegalAccessException {
FieldUtils.writeField(subject, "defaultTrustManager", defaultTrustManager, true);
when(topOfChain.getSubjectX500Principal())
.thenReturn(new X500Principal("CN=example.com, OU=Smarthome, O=Eclipse, C=DE"));
when(topOfChain.getSubjectAlternativeNames()).thenReturn(null);
subject.checkClientTrusted(chain, "just");
verify(defaultTrustManager).checkClientTrusted(chain, "just", (Socket) null);
verifyNoMoreInteractions(trustmanager);
}
@Test
public void shouldBeResilientAgainstMissingCommonNames() throws CertificateException, IllegalAccessException {
FieldUtils.writeField(subject, "defaultTrustManager", defaultTrustManager, true);
when(topOfChain.getSubjectX500Principal()).thenReturn(new X500Principal("OU=Smarthome, O=Eclipse, C=DE"));
subject.checkClientTrusted(chain, "just");
verify(defaultTrustManager).checkClientTrusted(chain, "just", (Socket) null);
verifyNoMoreInteractions(trustmanager);
}
@Test
public void shouldBeResilientAgainstInvalidCertificates() throws CertificateException, IllegalAccessException {
FieldUtils.writeField(subject, "defaultTrustManager", defaultTrustManager, true);
when(topOfChain.getSubjectX500Principal())
.thenReturn(new X500Principal("CN=example.com, OU=Smarthome, O=Eclipse, C=DE"));
when(topOfChain.getSubjectAlternativeNames())
.thenThrow(new CertificateParsingException("Invalid certificate!!!"));
subject.checkClientTrusted(chain, "just");
verify(defaultTrustManager).checkClientTrusted(chain, "just", (Socket) null);
verifyNoMoreInteractions(trustmanager);
}
@Test
public void shouldNotForwardCallsToMockForDifferentCN() throws CertificateException, IllegalAccessException {
FieldUtils.writeField(subject, "defaultTrustManager", defaultTrustManager, true);
mockSubjectForCertificate(topOfChain, "CN=example.com, OU=Smarthome, O=Eclipse, C=DE");
mockIssuerForCertificate(topOfChain, "CN=Eclipse, OU=Smarthome, O=Eclipse, C=DE");
mockSubjectForCertificate(bottomOfChain, "CN=Eclipse, OU=Smarthome, O=Eclipse, C=DE");
mockIssuerForCertificate(bottomOfChain, "");
when(topOfChain.getEncoded()).thenReturn(new byte[0]);
subject.checkServerTrusted(chain, "just");
verify(defaultTrustManager).checkServerTrusted(chain, "just", (Socket) null);
verifyZeroInteractions(trustmanager);
}
private Collection<List<?>> constructAlternativeNames(String... alternatives) {
Collection<List<?>> alternativeNames = new ArrayList<>();
for (String alternative : alternatives) {
alternativeNames.add(Stream.of(0, alternative).collect(Collectors.toList()));
}
return alternativeNames;
}
private void mockSubjectForCertificate(X509Certificate certificate, String principal) {
when(certificate.getSubjectX500Principal()).thenReturn(new X500Principal(principal));
}
private void mockIssuerForCertificate(X509Certificate certificate, String principal) {
when(certificate.getIssuerX500Principal()).thenReturn(new X500Principal(principal));
}
}
@@ -1,245 +0,0 @@
/**
* Copyright (c) 2010-2019 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.eclipse.smarthome.io.net.http.internal;
import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.*;
import static org.mockito.MockitoAnnotations.initMocks;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.stream.Stream;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLHandshakeException;
import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.client.api.ContentResponse;
import org.eclipse.jetty.websocket.client.WebSocketClient;
import org.eclipse.smarthome.io.net.http.TrustManagerProvider;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.ArgumentMatchers;
import org.mockito.Mock;
/**
* @author Kai Kreuzer - Initial contribution
*/
public class WebClientFactoryImplTest {
private WebClientFactoryImpl webClientFactory;
private static final String TEST_URL = "https://www.eclipse.org/";
@Mock
private TrustManagerProvider trustmanagerProvider;
@Mock
private ExtensibleTrustManagerImpl extensibleTrustManager;
@Before
public void setup() {
initMocks(this);
webClientFactory = new WebClientFactoryImpl(extensibleTrustManager);
webClientFactory.setTrustmanagerProvider(trustmanagerProvider);
webClientFactory.activate(createConfigMap(4, 200, 60, 2, 10, 60));
}
@After
public void tearDown() {
webClientFactory.deactivate();
}
@Test
public void testGetClients() throws Exception {
HttpClient httpClient = webClientFactory.getCommonHttpClient();
WebSocketClient webSocketClient = webClientFactory.getCommonWebSocketClient();
assertThat(httpClient, is(notNullValue()));
assertThat(webSocketClient, is(notNullValue()));
}
@Test
@Ignore("connecting to the outside world makes this test flaky")
public void testCommonClientUsesExtensibleTrustManager() throws Exception {
ArgumentCaptor<X509Certificate[]> certificateChainCaptor = ArgumentCaptor.forClass(X509Certificate[].class);
ArgumentCaptor<SSLEngine> sslEngineCaptor = ArgumentCaptor.forClass(SSLEngine.class);
HttpClient httpClient = webClientFactory.getCommonHttpClient();
ContentResponse response = httpClient.GET(TEST_URL);
if (response.getStatus() != 200) {
fail("Statuscode != 200");
}
verify(extensibleTrustManager).checkServerTrusted(certificateChainCaptor.capture(), anyString(),
sslEngineCaptor.capture());
verifyNoMoreInteractions(extensibleTrustManager);
assertThat(sslEngineCaptor.getValue().getPeerHost(), is("www.eclipse.org"));
assertThat(sslEngineCaptor.getValue().getPeerPort(), is(443));
assertThat(certificateChainCaptor.getValue()[0].getSubjectX500Principal().getName(),
containsString("eclipse.org"));
}
@Test
public void testGetHttpClientWithEndpoint() throws Exception {
when(trustmanagerProvider.getTrustManagers("https://www.heise.de")).thenReturn(Stream.empty());
HttpClient httpClient = webClientFactory.createHttpClient("consumer", TEST_URL);
assertThat(httpClient, is(notNullValue()));
verify(trustmanagerProvider).getTrustManagers(TEST_URL);
httpClient.stop();
}
@Test
public void testGetWebSocketClientWithEndpoint() throws Exception {
when(trustmanagerProvider.getTrustManagers("https://www.heise.de")).thenReturn(Stream.empty());
WebSocketClient webSocketClient = webClientFactory.createWebSocketClient("consumer", TEST_URL);
assertThat(webSocketClient, is(notNullValue()));
verify(trustmanagerProvider).getTrustManagers(TEST_URL);
webSocketClient.stop();
}
@Ignore("connecting to the outside world makes this test flaky")
@Test(expected = SSLHandshakeException.class)
public void testCommonClientUsesExtensibleTrustManagerFailure() throws Throwable {
doThrow(new CertificateException()).when(extensibleTrustManager).checkServerTrusted(
ArgumentMatchers.any(X509Certificate[].class), anyString(), ArgumentMatchers.any(SSLEngine.class));
HttpClient httpClient = webClientFactory.getCommonHttpClient();
try {
httpClient.GET(TEST_URL);
} catch (ExecutionException e) {
throw e.getCause();
}
}
@Ignore("only for manual test")
@Test
public void testMultiThreadedShared() throws Exception {
ThreadPoolExecutor workers = new ThreadPoolExecutor(20, 80, 60, TimeUnit.SECONDS,
new ArrayBlockingQueue<>(50 * 50));
final List<HttpClient> clients = new ArrayList<>();
final int maxClients = 2;
final int maxRequests = 2;
for (int i = 0; i < maxClients; i++) {
HttpClient httpClient = webClientFactory.getCommonHttpClient();
clients.add(httpClient);
}
final List<String> failures = new ArrayList<>();
for (int i = 0; i < maxRequests; i++) {
for (final HttpClient client : clients) {
workers.execute(new Runnable() {
@Override
public void run() {
try {
ContentResponse response = client.GET(TEST_URL);
if (response.getStatus() != 200) {
failures.add("Statuscode != 200");
}
} catch (InterruptedException | ExecutionException | TimeoutException e) {
failures.add("Unexpected exception:" + e.getMessage());
}
}
});
}
}
workers.shutdown();
workers.awaitTermination(120, TimeUnit.SECONDS);
if (!failures.isEmpty()) {
fail(failures.toString());
}
}
@Ignore("only for manual test")
@Test
public void testMultiThreadedCustom() throws Exception {
ThreadPoolExecutor workers = new ThreadPoolExecutor(20, 80, 60, TimeUnit.SECONDS,
new ArrayBlockingQueue<>(50 * 50));
final List<HttpClient> clients = new ArrayList<>();
final int maxClients = 2;
final int maxRequests = 2;
for (int i = 0; i < maxClients; i++) {
HttpClient httpClient = webClientFactory.createHttpClient("consumer" + i, "https://www.heise.de");
clients.add(httpClient);
}
final List<String> failures = new ArrayList<>();
for (int i = 0; i < maxRequests; i++) {
for (final HttpClient client : clients) {
workers.execute(new Runnable() {
@Override
public void run() {
try {
ContentResponse response = client.GET(TEST_URL);
if (response.getStatus() != 200) {
failures.add("Statuscode != 200");
}
} catch (InterruptedException | ExecutionException | TimeoutException e) {
failures.add("Unexpected exception:" + e.getMessage());
}
}
});
}
}
workers.shutdown();
workers.awaitTermination(120, TimeUnit.SECONDS);
if (!failures.isEmpty()) {
fail(failures.toString());
}
for (HttpClient client : clients) {
client.stop();
}
}
private Map<String, Object> createConfigMap(int minThreadsShared, int maxThreadsShared, int keepAliveTimeoutShared,
int minThreadsCustom, int maxThreadsCustom, int keepAliveTimeoutCustom) {
Map<String, Object> configMap = new HashMap<>();
configMap.put("minThreadsShared", minThreadsShared);
configMap.put("maxThreadsShared", maxThreadsShared);
configMap.put("keepAliveTimeoutShared", keepAliveTimeoutShared);
configMap.put("minThreadsCustom", minThreadsCustom);
configMap.put("maxThreadsCustom", maxThreadsCustom);
configMap.put("keepAliveTimeoutCustom", keepAliveTimeoutCustom);
return configMap;
}
}
@@ -1,51 +0,0 @@
<?xml version="1.0"?>
<xml_api_reply version="1">
<weather module_id="0" tab_id="0" mobile_row="0" mobile_zipped="1"
row="0" section="0">
<forecast_information>
<city data="Krefeld, North Rhine-Westphalia" />
<postal_code data="Krefeld Germany" />
<latitude_e6 data="" />
<longitude_e6 data="" />
<forecast_date data="2011-03-01" />
<current_date_time data="2011-03-01 15:20:00 +0000" />
<unit_system data="SI" />
</forecast_information>
<current_conditions>
<condition data="Meistens bewölkt" />
<temp_f data="46" />
<temp_c data="8" />
<humidity data="Feuchtigkeit: 66 %" />
<icon data="/ig/images/weather/mostly_cloudy.gif" />
<wind_condition data="Wind: N mit 26 km/h" />
</current_conditions>
<forecast_conditions>
<day_of_week data="Di." />
<low data="-1" />
<high data="6" />
<icon data="/ig/images/weather/sunny.gif" />
<condition data="Klar" />
</forecast_conditions>
<forecast_conditions>
<day_of_week data="Mi." />
<low data="-1" />
<high data="8" />
<icon data="/ig/images/weather/sunny.gif" />
<condition data="Klar" />
</forecast_conditions>
<forecast_conditions>
<day_of_week data="Do." />
<low data="-1" />
<high data="8" />
<icon data="/ig/images/weather/sunny.gif" />
<condition data="Klar" />
</forecast_conditions>
<forecast_conditions>
<day_of_week data="Fr." />
<low data="0" />
<high data="8" />
<icon data="/ig/images/weather/sunny.gif" />
<condition data="Klar" />
</forecast_conditions>
</weather>
</xml_api_reply>