Black box tests update
This commit is contained in:
parent
cdc72653de
commit
32dd7f0437
21
msa/black-box-tests/README.md
Normal file
21
msa/black-box-tests/README.md
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
|
||||||
|
## Black box tests execution
|
||||||
|
To run the black box tests with using Docker, the local Docker images of Thingsboard's microservices should be built. <br />
|
||||||
|
- Build the local Docker images in the directory with the Thingsboard's main [pom.xml](./../../pom.xml):
|
||||||
|
|
||||||
|
mvn clean install -Ddockerfile.skip=false
|
||||||
|
- Verify that the new local images were built:
|
||||||
|
|
||||||
|
docker image ls
|
||||||
|
As result, in REPOSITORY column, next images should be present:
|
||||||
|
|
||||||
|
thingsboard/tb-coap-transport
|
||||||
|
thingsboard/tb-http-transport
|
||||||
|
thingsboard/tb-mqtt-transport
|
||||||
|
thingsboard/tb-node
|
||||||
|
thingsboard/tb-web-ui
|
||||||
|
thingsboard/tb-js-executor
|
||||||
|
|
||||||
|
- Run the black box tests in the [msa/black-box-tests](../black-box-tests) directory:
|
||||||
|
|
||||||
|
mvn clean install -DblackBoxTests.skip=false
|
||||||
@ -25,16 +25,16 @@
|
|||||||
<artifactId>msa</artifactId>
|
<artifactId>msa</artifactId>
|
||||||
</parent>
|
</parent>
|
||||||
<groupId>org.thingsboard.msa</groupId>
|
<groupId>org.thingsboard.msa</groupId>
|
||||||
<artifactId>integration-tests</artifactId>
|
<artifactId>black-box-tests</artifactId>
|
||||||
|
|
||||||
<name>ThingsBoard Integration Tests</name>
|
<name>ThingsBoard Black Box Tests</name>
|
||||||
<url>https://thingsboard.io</url>
|
<url>https://thingsboard.io</url>
|
||||||
<description>Project for ThingsBoard integration tests with using Docker</description>
|
<description>Project for ThingsBoard black box testing with using Docker</description>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
<main.dir>${basedir}/../..</main.dir>
|
<main.dir>${basedir}/../..</main.dir>
|
||||||
<integrationTests.skip>true</integrationTests.skip>
|
<blackBoxTests.skip>true</blackBoxTests.skip>
|
||||||
<testcontainers.version>1.9.1</testcontainers.version>
|
<testcontainers.version>1.9.1</testcontainers.version>
|
||||||
<java-websocket.version>1.3.9</java-websocket.version>
|
<java-websocket.version>1.3.9</java-websocket.version>
|
||||||
<httpclient.version>4.5.6</httpclient.version>
|
<httpclient.version>4.5.6</httpclient.version>
|
||||||
@ -95,7 +95,7 @@
|
|||||||
<includes>
|
<includes>
|
||||||
<include>**/*TestSuite.java</include>
|
<include>**/*TestSuite.java</include>
|
||||||
</includes>
|
</includes>
|
||||||
<skipTests>${integrationTests.skip}</skipTests>
|
<skipTests>${blackBoxTests.skip}</skipTests>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
@ -22,15 +22,18 @@ import org.testcontainers.containers.DockerComposeContainer;
|
|||||||
import org.testcontainers.containers.wait.strategy.Wait;
|
import org.testcontainers.containers.wait.strategy.Wait;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.time.Duration;
|
||||||
|
|
||||||
@RunWith(ClasspathSuite.class)
|
@RunWith(ClasspathSuite.class)
|
||||||
@ClasspathSuite.ClassnameFilters({"org.thingsboard.server.msa.*"})
|
@ClasspathSuite.ClassnameFilters({"org.thingsboard.server.msa.*Test"})
|
||||||
public class ContainerTestSuite {
|
public class ContainerTestSuite {
|
||||||
|
|
||||||
@ClassRule
|
@ClassRule
|
||||||
public static DockerComposeContainer composeContainer = new DockerComposeContainer(new File("./../docker/docker-compose.yml"))
|
public static DockerComposeContainer composeContainer = new DockerComposeContainer(
|
||||||
|
new File("./../../docker/docker-compose.yml"),
|
||||||
|
new File("./../../docker/docker-compose.postgres.yml"))
|
||||||
.withPull(false)
|
.withPull(false)
|
||||||
.withLocalCompose(true)
|
.withLocalCompose(true)
|
||||||
.withTailChildContainers(true)
|
.withTailChildContainers(true)
|
||||||
.withExposedService("tb-web-ui1", 8080, Wait.forHttp("/login"));
|
.withExposedService("tb-web-ui1", 8080, Wait.forHttp("/login").withStartupTimeout(Duration.ofSeconds(120)));
|
||||||
}
|
}
|
||||||
@ -15,13 +15,23 @@
|
|||||||
*/
|
*/
|
||||||
package org.thingsboard.server.msa;
|
package org.thingsboard.server.msa;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.java_websocket.client.WebSocketClient;
|
import org.java_websocket.client.WebSocketClient;
|
||||||
import org.java_websocket.handshake.ServerHandshake;
|
import org.java_websocket.handshake.ServerHandshake;
|
||||||
|
import org.thingsboard.server.msa.mapper.WsTelemetryResponse;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
import java.util.concurrent.CountDownLatch;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class WsClient extends WebSocketClient {
|
public class WsClient extends WebSocketClient {
|
||||||
private String message;
|
private static final ObjectMapper mapper = new ObjectMapper();
|
||||||
|
private WsTelemetryResponse message;
|
||||||
|
|
||||||
|
private CountDownLatch latch = new CountDownLatch(1);;
|
||||||
|
|
||||||
public WsClient(URI serverUri) {
|
public WsClient(URI serverUri) {
|
||||||
super(serverUri);
|
super(serverUri);
|
||||||
@ -33,11 +43,20 @@ public class WsClient extends WebSocketClient {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onMessage(String message) {
|
public void onMessage(String message) {
|
||||||
this.message = message;
|
try {
|
||||||
|
WsTelemetryResponse response = mapper.readValue(message, WsTelemetryResponse.class);
|
||||||
|
if (!response.getData().isEmpty()) {
|
||||||
|
this.message = response;
|
||||||
|
latch.countDown();
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.error("ws message can't be read");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onClose(int code, String reason, boolean remote) {
|
public void onClose(int code, String reason, boolean remote) {
|
||||||
|
log.info("ws is closed, due to [{}]", reason);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -45,7 +64,13 @@ public class WsClient extends WebSocketClient {
|
|||||||
ex.printStackTrace();
|
ex.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getLastMessage() {
|
public WsTelemetryResponse getLastMessage() {
|
||||||
|
try {
|
||||||
|
latch.await(10, TimeUnit.SECONDS);
|
||||||
return this.message;
|
return this.message;
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
log.error("Timeout, ws message wasn't received");
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -25,12 +25,10 @@ import org.thingsboard.server.msa.AbstractContainerTest;
|
|||||||
import org.thingsboard.server.msa.WsClient;
|
import org.thingsboard.server.msa.WsClient;
|
||||||
import org.thingsboard.server.msa.mapper.WsTelemetryResponse;
|
import org.thingsboard.server.msa.mapper.WsTelemetryResponse;
|
||||||
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
public class HttpClientTest extends AbstractContainerTest {
|
public class HttpClientTest extends AbstractContainerTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void telemetryUpdate() throws Exception {
|
public void telemetryUpload() throws Exception {
|
||||||
restClient.login("tenant@thingsboard.org", "tenant");
|
restClient.login("tenant@thingsboard.org", "tenant");
|
||||||
|
|
||||||
Device device = createDevice("http_");
|
Device device = createDevice("http_");
|
||||||
@ -43,8 +41,8 @@ public class HttpClientTest extends AbstractContainerTest {
|
|||||||
ResponseEntity.class,
|
ResponseEntity.class,
|
||||||
deviceCredentials.getCredentialsId());
|
deviceCredentials.getCredentialsId());
|
||||||
Assert.assertTrue(deviceTelemetryResponse.getStatusCode().is2xxSuccessful());
|
Assert.assertTrue(deviceTelemetryResponse.getStatusCode().is2xxSuccessful());
|
||||||
TimeUnit.SECONDS.sleep(1);
|
WsTelemetryResponse actualLatestTelemetry = wsClient.getLastMessage();
|
||||||
WsTelemetryResponse actualLatestTelemetry = mapper.readValue(wsClient.getLastMessage(), WsTelemetryResponse.class);
|
wsClient.closeBlocking();
|
||||||
|
|
||||||
Assert.assertEquals(Sets.newHashSet("booleanKey", "stringKey", "doubleKey", "longKey"),
|
Assert.assertEquals(Sets.newHashSet("booleanKey", "stringKey", "doubleKey", "longKey"),
|
||||||
actualLatestTelemetry.getLatestValues().keySet());
|
actualLatestTelemetry.getLatestValues().keySet());
|
||||||
@ -23,7 +23,9 @@ import com.google.common.util.concurrent.MoreExecutors;
|
|||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
import io.netty.buffer.Unpooled;
|
import io.netty.buffer.Unpooled;
|
||||||
|
import io.netty.handler.codec.mqtt.MqttQoS;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.lang3.RandomStringUtils;
|
import org.apache.commons.lang3.RandomStringUtils;
|
||||||
import org.junit.*;
|
import org.junit.*;
|
||||||
import org.springframework.core.ParameterizedTypeReference;
|
import org.springframework.core.ParameterizedTypeReference;
|
||||||
@ -50,6 +52,7 @@ import java.nio.charset.StandardCharsets;
|
|||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.*;
|
import java.util.concurrent.*;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class MqttClientTest extends AbstractContainerTest {
|
public class MqttClientTest extends AbstractContainerTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -61,8 +64,8 @@ public class MqttClientTest extends AbstractContainerTest {
|
|||||||
WsClient wsClient = subscribeToWebSocket(device.getId(), "LATEST_TELEMETRY", CmdsType.TS_SUB_CMDS);
|
WsClient wsClient = subscribeToWebSocket(device.getId(), "LATEST_TELEMETRY", CmdsType.TS_SUB_CMDS);
|
||||||
MqttClient mqttClient = getMqttClient(deviceCredentials, null);
|
MqttClient mqttClient = getMqttClient(deviceCredentials, null);
|
||||||
mqttClient.publish("v1/devices/me/telemetry", Unpooled.wrappedBuffer(createPayload().toString().getBytes()));
|
mqttClient.publish("v1/devices/me/telemetry", Unpooled.wrappedBuffer(createPayload().toString().getBytes()));
|
||||||
TimeUnit.SECONDS.sleep(1);
|
WsTelemetryResponse actualLatestTelemetry = wsClient.getLastMessage();
|
||||||
WsTelemetryResponse actualLatestTelemetry = mapper.readValue(wsClient.getLastMessage(), WsTelemetryResponse.class);
|
wsClient.closeBlocking();
|
||||||
|
|
||||||
Assert.assertEquals(4, actualLatestTelemetry.getData().size());
|
Assert.assertEquals(4, actualLatestTelemetry.getData().size());
|
||||||
Assert.assertEquals(Sets.newHashSet("booleanKey", "stringKey", "doubleKey", "longKey"),
|
Assert.assertEquals(Sets.newHashSet("booleanKey", "stringKey", "doubleKey", "longKey"),
|
||||||
@ -87,8 +90,8 @@ public class MqttClientTest extends AbstractContainerTest {
|
|||||||
WsClient wsClient = subscribeToWebSocket(device.getId(), "LATEST_TELEMETRY", CmdsType.TS_SUB_CMDS);
|
WsClient wsClient = subscribeToWebSocket(device.getId(), "LATEST_TELEMETRY", CmdsType.TS_SUB_CMDS);
|
||||||
MqttClient mqttClient = getMqttClient(deviceCredentials, null);
|
MqttClient mqttClient = getMqttClient(deviceCredentials, null);
|
||||||
mqttClient.publish("v1/devices/me/telemetry", Unpooled.wrappedBuffer(createPayload(ts).toString().getBytes()));
|
mqttClient.publish("v1/devices/me/telemetry", Unpooled.wrappedBuffer(createPayload(ts).toString().getBytes()));
|
||||||
TimeUnit.SECONDS.sleep(1);
|
WsTelemetryResponse actualLatestTelemetry = wsClient.getLastMessage();
|
||||||
WsTelemetryResponse actualLatestTelemetry = mapper.readValue(wsClient.getLastMessage(), WsTelemetryResponse.class);
|
wsClient.closeBlocking();
|
||||||
|
|
||||||
Assert.assertEquals(4, actualLatestTelemetry.getData().size());
|
Assert.assertEquals(4, actualLatestTelemetry.getData().size());
|
||||||
Assert.assertEquals(getExpectedLatestValues(ts), actualLatestTelemetry.getLatestValues());
|
Assert.assertEquals(getExpectedLatestValues(ts), actualLatestTelemetry.getLatestValues());
|
||||||
@ -116,8 +119,8 @@ public class MqttClientTest extends AbstractContainerTest {
|
|||||||
clientAttributes.addProperty("attr3", 42.0);
|
clientAttributes.addProperty("attr3", 42.0);
|
||||||
clientAttributes.addProperty("attr4", 73);
|
clientAttributes.addProperty("attr4", 73);
|
||||||
mqttClient.publish("v1/devices/me/attributes", Unpooled.wrappedBuffer(clientAttributes.toString().getBytes()));
|
mqttClient.publish("v1/devices/me/attributes", Unpooled.wrappedBuffer(clientAttributes.toString().getBytes()));
|
||||||
TimeUnit.SECONDS.sleep(1);
|
WsTelemetryResponse actualLatestTelemetry = wsClient.getLastMessage();
|
||||||
WsTelemetryResponse actualLatestTelemetry = mapper.readValue(wsClient.getLastMessage(), WsTelemetryResponse.class);
|
wsClient.closeBlocking();
|
||||||
|
|
||||||
Assert.assertEquals(4, actualLatestTelemetry.getData().size());
|
Assert.assertEquals(4, actualLatestTelemetry.getData().size());
|
||||||
Assert.assertEquals(Sets.newHashSet("attr1", "attr2", "attr3", "attr4"),
|
Assert.assertEquals(Sets.newHashSet("attr1", "attr2", "attr3", "attr4"),
|
||||||
@ -157,7 +160,7 @@ public class MqttClientTest extends AbstractContainerTest {
|
|||||||
Assert.assertTrue(sharedAttributesResponse.getStatusCode().is2xxSuccessful());
|
Assert.assertTrue(sharedAttributesResponse.getStatusCode().is2xxSuccessful());
|
||||||
|
|
||||||
// Subscribe to attributes response
|
// Subscribe to attributes response
|
||||||
mqttClient.on("v1/devices/me/attributes/response/+", listener);
|
mqttClient.on("v1/devices/me/attributes/response/+", listener, MqttQoS.AT_LEAST_ONCE);
|
||||||
// Request attributes
|
// Request attributes
|
||||||
JsonObject request = new JsonObject();
|
JsonObject request = new JsonObject();
|
||||||
request.addProperty("clientKeys", "clientAttr");
|
request.addProperty("clientKeys", "clientAttr");
|
||||||
@ -183,7 +186,7 @@ public class MqttClientTest extends AbstractContainerTest {
|
|||||||
|
|
||||||
MqttMessageListener listener = new MqttMessageListener();
|
MqttMessageListener listener = new MqttMessageListener();
|
||||||
MqttClient mqttClient = getMqttClient(deviceCredentials, listener);
|
MqttClient mqttClient = getMqttClient(deviceCredentials, listener);
|
||||||
mqttClient.on("v1/devices/me/attributes", listener);
|
mqttClient.on("v1/devices/me/attributes", listener, MqttQoS.AT_LEAST_ONCE);
|
||||||
|
|
||||||
String sharedAttributeName = "sharedAttr";
|
String sharedAttributeName = "sharedAttr";
|
||||||
|
|
||||||
@ -226,13 +229,12 @@ public class MqttClientTest extends AbstractContainerTest {
|
|||||||
|
|
||||||
MqttMessageListener listener = new MqttMessageListener();
|
MqttMessageListener listener = new MqttMessageListener();
|
||||||
MqttClient mqttClient = getMqttClient(deviceCredentials, listener);
|
MqttClient mqttClient = getMqttClient(deviceCredentials, listener);
|
||||||
mqttClient.on("v1/devices/me/rpc/request/+", listener);
|
mqttClient.on("v1/devices/me/rpc/request/+", listener, MqttQoS.AT_LEAST_ONCE);
|
||||||
|
|
||||||
// Send an RPC from the server
|
// Send an RPC from the server
|
||||||
JsonObject serverRpcPayload = new JsonObject();
|
JsonObject serverRpcPayload = new JsonObject();
|
||||||
serverRpcPayload.addProperty("method", "getValue");
|
serverRpcPayload.addProperty("method", "getValue");
|
||||||
serverRpcPayload.addProperty("params", true);
|
serverRpcPayload.addProperty("params", true);
|
||||||
serverRpcPayload.addProperty("timeout", 1000);
|
|
||||||
ListeningExecutorService service = MoreExecutors.listeningDecorator(Executors.newSingleThreadExecutor());
|
ListeningExecutorService service = MoreExecutors.listeningDecorator(Executors.newSingleThreadExecutor());
|
||||||
ListenableFuture<ResponseEntity> future = service.submit(() -> {
|
ListenableFuture<ResponseEntity> future = service.submit(() -> {
|
||||||
try {
|
try {
|
||||||
@ -271,7 +273,7 @@ public class MqttClientTest extends AbstractContainerTest {
|
|||||||
|
|
||||||
MqttMessageListener listener = new MqttMessageListener();
|
MqttMessageListener listener = new MqttMessageListener();
|
||||||
MqttClient mqttClient = getMqttClient(deviceCredentials, listener);
|
MqttClient mqttClient = getMqttClient(deviceCredentials, listener);
|
||||||
mqttClient.on("v1/devices/me/rpc/request/+", listener);
|
mqttClient.on("v1/devices/me/rpc/request/+", listener, MqttQoS.AT_LEAST_ONCE);
|
||||||
|
|
||||||
// Get the default rule chain id to make it root again after test finished
|
// Get the default rule chain id to make it root again after test finished
|
||||||
RuleChainId defaultRuleChainId = getDefaultRuleChainId();
|
RuleChainId defaultRuleChainId = getDefaultRuleChainId();
|
||||||
@ -377,6 +379,7 @@ public class MqttClientTest extends AbstractContainerTest {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onMessage(String topic, ByteBuf message) {
|
public void onMessage(String topic, ByteBuf message) {
|
||||||
|
log.info("MQTT message [{}], topic [{}]", message.toString(StandardCharsets.UTF_8), topic);
|
||||||
events.add(new MqttEvent(topic, message.toString(StandardCharsets.UTF_8)));
|
events.add(new MqttEvent(topic, message.toString(StandardCharsets.UTF_8)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,18 +0,0 @@
|
|||||||
|
|
||||||
## Integration tests execution
|
|
||||||
To run the integration tests with using Docker, the local Docker images of Thingsboard's microservices should be built. <br />
|
|
||||||
- Build the local Docker images in the directory with the Thingsboard's main [pom.xml](./../../pom.xml):
|
|
||||||
|
|
||||||
mvn clean install -Ddockerfile.skip=false
|
|
||||||
- Verify that the new local images were built:
|
|
||||||
|
|
||||||
docker image ls
|
|
||||||
As result, in REPOSITORY column, next images should be present:
|
|
||||||
|
|
||||||
local-maven-build/tb-node
|
|
||||||
local-maven-build/tb-web-ui
|
|
||||||
local-maven-build/tb-web-ui
|
|
||||||
|
|
||||||
- Run the integration tests in the [msa/integration-tests](../integration-tests) directory:
|
|
||||||
|
|
||||||
mvn clean install -DintegrationTests.skip=false
|
|
||||||
@ -41,7 +41,7 @@
|
|||||||
<module>web-ui</module>
|
<module>web-ui</module>
|
||||||
<module>tb-node</module>
|
<module>tb-node</module>
|
||||||
<module>transport</module>
|
<module>transport</module>
|
||||||
<module>integration-tests</module>
|
<module>black-box-tests</module>
|
||||||
</modules>
|
</modules>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user