mirror of
https://github.com/danieldemus/openhab-core.git
synced 2026-07-29 12:34:22 +02:00
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:
committed by
Christoph Weitkamp
parent
4e07b56279
commit
f1f0e9e52b
@@ -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>
|
||||
-69
@@ -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());
|
||||
}
|
||||
}
|
||||
-120
@@ -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"));
|
||||
}
|
||||
}
|
||||
-87
@@ -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");
|
||||
}
|
||||
}
|
||||
-197
@@ -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));
|
||||
}
|
||||
}
|
||||
-245
@@ -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>
|
||||
Reference in New Issue
Block a user