Commit 32dd7f0437053fdbb42227ff939dc9f2e7be17d1

Authored by Viacheslav Kukhtyn
1 parent cdc72653

Black box tests update

Showing 12 changed files with 80 additions and 48 deletions
  1 +
  2 +## Black box tests execution
  3 +To run the black box tests with using Docker, the local Docker images of Thingsboard's microservices should be built. <br />
  4 +- Build the local Docker images in the directory with the Thingsboard's main [pom.xml](./../../pom.xml):
  5 +
  6 + mvn clean install -Ddockerfile.skip=false
  7 +- Verify that the new local images were built:
  8 +
  9 + docker image ls
  10 +As result, in REPOSITORY column, next images should be present:
  11 +
  12 + thingsboard/tb-coap-transport
  13 + thingsboard/tb-http-transport
  14 + thingsboard/tb-mqtt-transport
  15 + thingsboard/tb-node
  16 + thingsboard/tb-web-ui
  17 + thingsboard/tb-js-executor
  18 +
  19 +- Run the black box tests in the [msa/black-box-tests](../black-box-tests) directory:
  20 +
  21 + mvn clean install -DblackBoxTests.skip=false
msa/black-box-tests/pom.xml renamed from msa/integration-tests/pom.xml
@@ -25,16 +25,16 @@ @@ -25,16 +25,16 @@
25 <artifactId>msa</artifactId> 25 <artifactId>msa</artifactId>
26 </parent> 26 </parent>
27 <groupId>org.thingsboard.msa</groupId> 27 <groupId>org.thingsboard.msa</groupId>
28 - <artifactId>integration-tests</artifactId> 28 + <artifactId>black-box-tests</artifactId>
29 29
30 - <name>ThingsBoard Integration Tests</name> 30 + <name>ThingsBoard Black Box Tests</name>
31 <url>https://thingsboard.io</url> 31 <url>https://thingsboard.io</url>
32 - <description>Project for ThingsBoard integration tests with using Docker</description> 32 + <description>Project for ThingsBoard black box testing with using Docker</description>
33 33
34 <properties> 34 <properties>
35 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 35 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
36 <main.dir>${basedir}/../..</main.dir> 36 <main.dir>${basedir}/../..</main.dir>
37 - <integrationTests.skip>true</integrationTests.skip> 37 + <blackBoxTests.skip>true</blackBoxTests.skip>
38 <testcontainers.version>1.9.1</testcontainers.version> 38 <testcontainers.version>1.9.1</testcontainers.version>
39 <java-websocket.version>1.3.9</java-websocket.version> 39 <java-websocket.version>1.3.9</java-websocket.version>
40 <httpclient.version>4.5.6</httpclient.version> 40 <httpclient.version>4.5.6</httpclient.version>
@@ -95,7 +95,7 @@ @@ -95,7 +95,7 @@
95 <includes> 95 <includes>
96 <include>**/*TestSuite.java</include> 96 <include>**/*TestSuite.java</include>
97 </includes> 97 </includes>
98 - <skipTests>${integrationTests.skip}</skipTests> 98 + <skipTests>${blackBoxTests.skip}</skipTests>
99 </configuration> 99 </configuration>
100 </plugin> 100 </plugin>
101 </plugins> 101 </plugins>
msa/black-box-tests/src/test/java/org/thingsboard/server/msa/AbstractContainerTest.java renamed from msa/integration-tests/src/test/java/org/thingsboard/server/msa/AbstractContainerTest.java
msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ContainerTestSuite.java renamed from msa/integration-tests/src/test/java/org/thingsboard/server/msa/ContainerTestSuite.java
@@ -22,15 +22,18 @@ import org.testcontainers.containers.DockerComposeContainer; @@ -22,15 +22,18 @@ import org.testcontainers.containers.DockerComposeContainer;
22 import org.testcontainers.containers.wait.strategy.Wait; 22 import org.testcontainers.containers.wait.strategy.Wait;
23 23
24 import java.io.File; 24 import java.io.File;
  25 +import java.time.Duration;
25 26
26 @RunWith(ClasspathSuite.class) 27 @RunWith(ClasspathSuite.class)
27 -@ClasspathSuite.ClassnameFilters({"org.thingsboard.server.msa.*"}) 28 +@ClasspathSuite.ClassnameFilters({"org.thingsboard.server.msa.*Test"})
28 public class ContainerTestSuite { 29 public class ContainerTestSuite {
29 30
30 @ClassRule 31 @ClassRule
31 - public static DockerComposeContainer composeContainer = new DockerComposeContainer(new File("./../docker/docker-compose.yml")) 32 + public static DockerComposeContainer composeContainer = new DockerComposeContainer(
  33 + new File("./../../docker/docker-compose.yml"),
  34 + new File("./../../docker/docker-compose.postgres.yml"))
32 .withPull(false) 35 .withPull(false)
33 .withLocalCompose(true) 36 .withLocalCompose(true)
34 .withTailChildContainers(true) 37 .withTailChildContainers(true)
35 - .withExposedService("tb-web-ui1", 8080, Wait.forHttp("/login")); 38 + .withExposedService("tb-web-ui1", 8080, Wait.forHttp("/login").withStartupTimeout(Duration.ofSeconds(120)));
36 } 39 }
msa/black-box-tests/src/test/java/org/thingsboard/server/msa/WsClient.java renamed from msa/integration-tests/src/test/java/org/thingsboard/server/msa/WsClient.java
@@ -15,13 +15,23 @@ @@ -15,13 +15,23 @@
15 */ 15 */
16 package org.thingsboard.server.msa; 16 package org.thingsboard.server.msa;
17 17
  18 +import com.fasterxml.jackson.databind.ObjectMapper;
  19 +import lombok.extern.slf4j.Slf4j;
18 import org.java_websocket.client.WebSocketClient; 20 import org.java_websocket.client.WebSocketClient;
19 import org.java_websocket.handshake.ServerHandshake; 21 import org.java_websocket.handshake.ServerHandshake;
  22 +import org.thingsboard.server.msa.mapper.WsTelemetryResponse;
20 23
  24 +import java.io.IOException;
21 import java.net.URI; 25 import java.net.URI;
  26 +import java.util.concurrent.CountDownLatch;
  27 +import java.util.concurrent.TimeUnit;
22 28
  29 +@Slf4j
23 public class WsClient extends WebSocketClient { 30 public class WsClient extends WebSocketClient {
24 - private String message; 31 + private static final ObjectMapper mapper = new ObjectMapper();
  32 + private WsTelemetryResponse message;
  33 +
  34 + private CountDownLatch latch = new CountDownLatch(1);;
25 35
26 public WsClient(URI serverUri) { 36 public WsClient(URI serverUri) {
27 super(serverUri); 37 super(serverUri);
@@ -33,11 +43,20 @@ public class WsClient extends WebSocketClient { @@ -33,11 +43,20 @@ public class WsClient extends WebSocketClient {
33 43
34 @Override 44 @Override
35 public void onMessage(String message) { 45 public void onMessage(String message) {
36 - this.message = message; 46 + try {
  47 + WsTelemetryResponse response = mapper.readValue(message, WsTelemetryResponse.class);
  48 + if (!response.getData().isEmpty()) {
  49 + this.message = response;
  50 + latch.countDown();
  51 + }
  52 + } catch (IOException e) {
  53 + log.error("ws message can't be read");
  54 + }
37 } 55 }
38 56
39 @Override 57 @Override
40 public void onClose(int code, String reason, boolean remote) { 58 public void onClose(int code, String reason, boolean remote) {
  59 + log.info("ws is closed, due to [{}]", reason);
41 } 60 }
42 61
43 @Override 62 @Override
@@ -45,7 +64,13 @@ public class WsClient extends WebSocketClient { @@ -45,7 +64,13 @@ public class WsClient extends WebSocketClient {
45 ex.printStackTrace(); 64 ex.printStackTrace();
46 } 65 }
47 66
48 - public String getLastMessage() {  
49 - return this.message; 67 + public WsTelemetryResponse getLastMessage() {
  68 + try {
  69 + latch.await(10, TimeUnit.SECONDS);
  70 + return this.message;
  71 + } catch (InterruptedException e) {
  72 + log.error("Timeout, ws message wasn't received");
  73 + }
  74 + return null;
50 } 75 }
51 } 76 }
msa/black-box-tests/src/test/java/org/thingsboard/server/msa/connectivity/HttpClientTest.java renamed from msa/integration-tests/src/test/java/org/thingsboard/server/msa/connectivity/HttpClientTest.java
@@ -25,12 +25,10 @@ import org.thingsboard.server.msa.AbstractContainerTest; @@ -25,12 +25,10 @@ import org.thingsboard.server.msa.AbstractContainerTest;
25 import org.thingsboard.server.msa.WsClient; 25 import org.thingsboard.server.msa.WsClient;
26 import org.thingsboard.server.msa.mapper.WsTelemetryResponse; 26 import org.thingsboard.server.msa.mapper.WsTelemetryResponse;
27 27
28 -import java.util.concurrent.TimeUnit;  
29 -  
30 public class HttpClientTest extends AbstractContainerTest { 28 public class HttpClientTest extends AbstractContainerTest {
31 29
32 @Test 30 @Test
33 - public void telemetryUpdate() throws Exception { 31 + public void telemetryUpload() throws Exception {
34 restClient.login("tenant@thingsboard.org", "tenant"); 32 restClient.login("tenant@thingsboard.org", "tenant");
35 33
36 Device device = createDevice("http_"); 34 Device device = createDevice("http_");
@@ -43,8 +41,8 @@ public class HttpClientTest extends AbstractContainerTest { @@ -43,8 +41,8 @@ public class HttpClientTest extends AbstractContainerTest {
43 ResponseEntity.class, 41 ResponseEntity.class,
44 deviceCredentials.getCredentialsId()); 42 deviceCredentials.getCredentialsId());
45 Assert.assertTrue(deviceTelemetryResponse.getStatusCode().is2xxSuccessful()); 43 Assert.assertTrue(deviceTelemetryResponse.getStatusCode().is2xxSuccessful());
46 - TimeUnit.SECONDS.sleep(1);  
47 - WsTelemetryResponse actualLatestTelemetry = mapper.readValue(wsClient.getLastMessage(), WsTelemetryResponse.class); 44 + WsTelemetryResponse actualLatestTelemetry = wsClient.getLastMessage();
  45 + wsClient.closeBlocking();
48 46
49 Assert.assertEquals(Sets.newHashSet("booleanKey", "stringKey", "doubleKey", "longKey"), 47 Assert.assertEquals(Sets.newHashSet("booleanKey", "stringKey", "doubleKey", "longKey"),
50 actualLatestTelemetry.getLatestValues().keySet()); 48 actualLatestTelemetry.getLatestValues().keySet());
msa/black-box-tests/src/test/java/org/thingsboard/server/msa/connectivity/MqttClientTest.java renamed from msa/integration-tests/src/test/java/org/thingsboard/server/msa/connectivity/MqttClientTest.java
@@ -23,7 +23,9 @@ import com.google.common.util.concurrent.MoreExecutors; @@ -23,7 +23,9 @@ import com.google.common.util.concurrent.MoreExecutors;
23 import com.google.gson.JsonObject; 23 import com.google.gson.JsonObject;
24 import io.netty.buffer.ByteBuf; 24 import io.netty.buffer.ByteBuf;
25 import io.netty.buffer.Unpooled; 25 import io.netty.buffer.Unpooled;
  26 +import io.netty.handler.codec.mqtt.MqttQoS;
26 import lombok.Data; 27 import lombok.Data;
  28 +import lombok.extern.slf4j.Slf4j;
27 import org.apache.commons.lang3.RandomStringUtils; 29 import org.apache.commons.lang3.RandomStringUtils;
28 import org.junit.*; 30 import org.junit.*;
29 import org.springframework.core.ParameterizedTypeReference; 31 import org.springframework.core.ParameterizedTypeReference;
@@ -50,6 +52,7 @@ import java.nio.charset.StandardCharsets; @@ -50,6 +52,7 @@ import java.nio.charset.StandardCharsets;
50 import java.util.*; 52 import java.util.*;
51 import java.util.concurrent.*; 53 import java.util.concurrent.*;
52 54
  55 +@Slf4j
53 public class MqttClientTest extends AbstractContainerTest { 56 public class MqttClientTest extends AbstractContainerTest {
54 57
55 @Test 58 @Test
@@ -61,8 +64,8 @@ public class MqttClientTest extends AbstractContainerTest { @@ -61,8 +64,8 @@ public class MqttClientTest extends AbstractContainerTest {
61 WsClient wsClient = subscribeToWebSocket(device.getId(), "LATEST_TELEMETRY", CmdsType.TS_SUB_CMDS); 64 WsClient wsClient = subscribeToWebSocket(device.getId(), "LATEST_TELEMETRY", CmdsType.TS_SUB_CMDS);
62 MqttClient mqttClient = getMqttClient(deviceCredentials, null); 65 MqttClient mqttClient = getMqttClient(deviceCredentials, null);
63 mqttClient.publish("v1/devices/me/telemetry", Unpooled.wrappedBuffer(createPayload().toString().getBytes())); 66 mqttClient.publish("v1/devices/me/telemetry", Unpooled.wrappedBuffer(createPayload().toString().getBytes()));
64 - TimeUnit.SECONDS.sleep(1);  
65 - WsTelemetryResponse actualLatestTelemetry = mapper.readValue(wsClient.getLastMessage(), WsTelemetryResponse.class); 67 + WsTelemetryResponse actualLatestTelemetry = wsClient.getLastMessage();
  68 + wsClient.closeBlocking();
66 69
67 Assert.assertEquals(4, actualLatestTelemetry.getData().size()); 70 Assert.assertEquals(4, actualLatestTelemetry.getData().size());
68 Assert.assertEquals(Sets.newHashSet("booleanKey", "stringKey", "doubleKey", "longKey"), 71 Assert.assertEquals(Sets.newHashSet("booleanKey", "stringKey", "doubleKey", "longKey"),
@@ -87,8 +90,8 @@ public class MqttClientTest extends AbstractContainerTest { @@ -87,8 +90,8 @@ public class MqttClientTest extends AbstractContainerTest {
87 WsClient wsClient = subscribeToWebSocket(device.getId(), "LATEST_TELEMETRY", CmdsType.TS_SUB_CMDS); 90 WsClient wsClient = subscribeToWebSocket(device.getId(), "LATEST_TELEMETRY", CmdsType.TS_SUB_CMDS);
88 MqttClient mqttClient = getMqttClient(deviceCredentials, null); 91 MqttClient mqttClient = getMqttClient(deviceCredentials, null);
89 mqttClient.publish("v1/devices/me/telemetry", Unpooled.wrappedBuffer(createPayload(ts).toString().getBytes())); 92 mqttClient.publish("v1/devices/me/telemetry", Unpooled.wrappedBuffer(createPayload(ts).toString().getBytes()));
90 - TimeUnit.SECONDS.sleep(1);  
91 - WsTelemetryResponse actualLatestTelemetry = mapper.readValue(wsClient.getLastMessage(), WsTelemetryResponse.class); 93 + WsTelemetryResponse actualLatestTelemetry = wsClient.getLastMessage();
  94 + wsClient.closeBlocking();
92 95
93 Assert.assertEquals(4, actualLatestTelemetry.getData().size()); 96 Assert.assertEquals(4, actualLatestTelemetry.getData().size());
94 Assert.assertEquals(getExpectedLatestValues(ts), actualLatestTelemetry.getLatestValues()); 97 Assert.assertEquals(getExpectedLatestValues(ts), actualLatestTelemetry.getLatestValues());
@@ -116,8 +119,8 @@ public class MqttClientTest extends AbstractContainerTest { @@ -116,8 +119,8 @@ public class MqttClientTest extends AbstractContainerTest {
116 clientAttributes.addProperty("attr3", 42.0); 119 clientAttributes.addProperty("attr3", 42.0);
117 clientAttributes.addProperty("attr4", 73); 120 clientAttributes.addProperty("attr4", 73);
118 mqttClient.publish("v1/devices/me/attributes", Unpooled.wrappedBuffer(clientAttributes.toString().getBytes())); 121 mqttClient.publish("v1/devices/me/attributes", Unpooled.wrappedBuffer(clientAttributes.toString().getBytes()));
119 - TimeUnit.SECONDS.sleep(1);  
120 - WsTelemetryResponse actualLatestTelemetry = mapper.readValue(wsClient.getLastMessage(), WsTelemetryResponse.class); 122 + WsTelemetryResponse actualLatestTelemetry = wsClient.getLastMessage();
  123 + wsClient.closeBlocking();
121 124
122 Assert.assertEquals(4, actualLatestTelemetry.getData().size()); 125 Assert.assertEquals(4, actualLatestTelemetry.getData().size());
123 Assert.assertEquals(Sets.newHashSet("attr1", "attr2", "attr3", "attr4"), 126 Assert.assertEquals(Sets.newHashSet("attr1", "attr2", "attr3", "attr4"),
@@ -157,7 +160,7 @@ public class MqttClientTest extends AbstractContainerTest { @@ -157,7 +160,7 @@ public class MqttClientTest extends AbstractContainerTest {
157 Assert.assertTrue(sharedAttributesResponse.getStatusCode().is2xxSuccessful()); 160 Assert.assertTrue(sharedAttributesResponse.getStatusCode().is2xxSuccessful());
158 161
159 // Subscribe to attributes response 162 // Subscribe to attributes response
160 - mqttClient.on("v1/devices/me/attributes/response/+", listener); 163 + mqttClient.on("v1/devices/me/attributes/response/+", listener, MqttQoS.AT_LEAST_ONCE);
161 // Request attributes 164 // Request attributes
162 JsonObject request = new JsonObject(); 165 JsonObject request = new JsonObject();
163 request.addProperty("clientKeys", "clientAttr"); 166 request.addProperty("clientKeys", "clientAttr");
@@ -183,7 +186,7 @@ public class MqttClientTest extends AbstractContainerTest { @@ -183,7 +186,7 @@ public class MqttClientTest extends AbstractContainerTest {
183 186
184 MqttMessageListener listener = new MqttMessageListener(); 187 MqttMessageListener listener = new MqttMessageListener();
185 MqttClient mqttClient = getMqttClient(deviceCredentials, listener); 188 MqttClient mqttClient = getMqttClient(deviceCredentials, listener);
186 - mqttClient.on("v1/devices/me/attributes", listener); 189 + mqttClient.on("v1/devices/me/attributes", listener, MqttQoS.AT_LEAST_ONCE);
187 190
188 String sharedAttributeName = "sharedAttr"; 191 String sharedAttributeName = "sharedAttr";
189 192
@@ -226,13 +229,12 @@ public class MqttClientTest extends AbstractContainerTest { @@ -226,13 +229,12 @@ public class MqttClientTest extends AbstractContainerTest {
226 229
227 MqttMessageListener listener = new MqttMessageListener(); 230 MqttMessageListener listener = new MqttMessageListener();
228 MqttClient mqttClient = getMqttClient(deviceCredentials, listener); 231 MqttClient mqttClient = getMqttClient(deviceCredentials, listener);
229 - mqttClient.on("v1/devices/me/rpc/request/+", listener); 232 + mqttClient.on("v1/devices/me/rpc/request/+", listener, MqttQoS.AT_LEAST_ONCE);
230 233
231 // Send an RPC from the server 234 // Send an RPC from the server
232 JsonObject serverRpcPayload = new JsonObject(); 235 JsonObject serverRpcPayload = new JsonObject();
233 serverRpcPayload.addProperty("method", "getValue"); 236 serverRpcPayload.addProperty("method", "getValue");
234 serverRpcPayload.addProperty("params", true); 237 serverRpcPayload.addProperty("params", true);
235 - serverRpcPayload.addProperty("timeout", 1000);  
236 ListeningExecutorService service = MoreExecutors.listeningDecorator(Executors.newSingleThreadExecutor()); 238 ListeningExecutorService service = MoreExecutors.listeningDecorator(Executors.newSingleThreadExecutor());
237 ListenableFuture<ResponseEntity> future = service.submit(() -> { 239 ListenableFuture<ResponseEntity> future = service.submit(() -> {
238 try { 240 try {
@@ -271,7 +273,7 @@ public class MqttClientTest extends AbstractContainerTest { @@ -271,7 +273,7 @@ public class MqttClientTest extends AbstractContainerTest {
271 273
272 MqttMessageListener listener = new MqttMessageListener(); 274 MqttMessageListener listener = new MqttMessageListener();
273 MqttClient mqttClient = getMqttClient(deviceCredentials, listener); 275 MqttClient mqttClient = getMqttClient(deviceCredentials, listener);
274 - mqttClient.on("v1/devices/me/rpc/request/+", listener); 276 + mqttClient.on("v1/devices/me/rpc/request/+", listener, MqttQoS.AT_LEAST_ONCE);
275 277
276 // Get the default rule chain id to make it root again after test finished 278 // Get the default rule chain id to make it root again after test finished
277 RuleChainId defaultRuleChainId = getDefaultRuleChainId(); 279 RuleChainId defaultRuleChainId = getDefaultRuleChainId();
@@ -377,6 +379,7 @@ public class MqttClientTest extends AbstractContainerTest { @@ -377,6 +379,7 @@ public class MqttClientTest extends AbstractContainerTest {
377 379
378 @Override 380 @Override
379 public void onMessage(String topic, ByteBuf message) { 381 public void onMessage(String topic, ByteBuf message) {
  382 + log.info("MQTT message [{}], topic [{}]", message.toString(StandardCharsets.UTF_8), topic);
380 events.add(new MqttEvent(topic, message.toString(StandardCharsets.UTF_8))); 383 events.add(new MqttEvent(topic, message.toString(StandardCharsets.UTF_8)));
381 } 384 }
382 } 385 }
msa/black-box-tests/src/test/java/org/thingsboard/server/msa/mapper/AttributesResponse.java renamed from msa/integration-tests/src/test/java/org/thingsboard/server/msa/mapper/AttributesResponse.java
msa/black-box-tests/src/test/java/org/thingsboard/server/msa/mapper/WsTelemetryResponse.java renamed from msa/integration-tests/src/test/java/org/thingsboard/server/msa/mapper/WsTelemetryResponse.java
msa/black-box-tests/src/test/resources/RpcResponseRuleChainMetadata.json renamed from msa/integration-tests/src/test/resources/RpcResponseRuleChainMetadata.json
1 -  
2 -## Integration tests execution  
3 -To run the integration tests with using Docker, the local Docker images of Thingsboard's microservices should be built. <br />  
4 -- Build the local Docker images in the directory with the Thingsboard's main [pom.xml](./../../pom.xml):  
5 -  
6 - mvn clean install -Ddockerfile.skip=false  
7 -- Verify that the new local images were built:  
8 -  
9 - docker image ls  
10 -As result, in REPOSITORY column, next images should be present:  
11 -  
12 - local-maven-build/tb-node  
13 - local-maven-build/tb-web-ui  
14 - local-maven-build/tb-web-ui  
15 -  
16 -- Run the integration tests in the [msa/integration-tests](../integration-tests) directory:  
17 -  
18 - mvn clean install -DintegrationTests.skip=false  
@@ -16,7 +16,7 @@ @@ -16,7 +16,7 @@
16 16
17 --> 17 -->
18 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 18 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
19 - xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 19 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
20 <modelVersion>4.0.0</modelVersion> 20 <modelVersion>4.0.0</modelVersion>
21 <parent> 21 <parent>
22 <groupId>org.thingsboard</groupId> 22 <groupId>org.thingsboard</groupId>
@@ -41,7 +41,7 @@ @@ -41,7 +41,7 @@
41 <module>web-ui</module> 41 <module>web-ui</module>
42 <module>tb-node</module> 42 <module>tb-node</module>
43 <module>transport</module> 43 <module>transport</module>
44 - <module>integration-tests</module> 44 + <module>black-box-tests</module>
45 </modules> 45 </modules>
46 46
47 <build> 47 <build>