thingsboard-memoizeit
Changes
msa/integration-tests/pom.xml 98(+98 -0)
msa/integration-tests/README.md 18(+18 -0)
msa/integration-tests/src/test/java/org/thingsboard/server/msa/AbstractContainerTest.java 112(+112 -0)
msa/integration-tests/src/test/java/org/thingsboard/server/msa/connectivity/HttpClientTest.java 57(+57 -0)
msa/integration-tests/src/test/java/org/thingsboard/server/msa/connectivity/MqttClientTest.java 111(+111 -0)
msa/pom.xml 1(+1 -0)
Details
msa/integration-tests/pom.xml 98(+98 -0)
diff --git a/msa/integration-tests/pom.xml b/msa/integration-tests/pom.xml
new file mode 100644
index 0000000..a1c24f3
--- /dev/null
+++ b/msa/integration-tests/pom.xml
@@ -0,0 +1,98 @@
+<!--
+
+ Copyright © 2016-2018 The Thingsboard Authors
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+<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/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.thingsboard</groupId>
+ <version>2.2.0-SNAPSHOT</version>
+ <artifactId>msa</artifactId>
+ </parent>
+ <groupId>org.thingsboard.msa</groupId>
+ <artifactId>integration-tests</artifactId>
+
+ <name>ThingsBoard Integration Tests</name>
+ <url>https://thingsboard.io</url>
+ <description>Project for ThingsBoard integration tests with using Docker</description>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ <main.dir>${basedir}/../..</main.dir>
+ <integrationtests.skip>true</integrationtests.skip>
+ <testcontainers.version>1.9.1</testcontainers.version>
+ <java-websocket.version>1.3.9</java-websocket.version>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.testcontainers</groupId>
+ <artifactId>testcontainers</artifactId>
+ <version>${testcontainers.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.java-websocket</groupId>
+ <artifactId>Java-WebSocket</artifactId>
+ <version>${java-websocket.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>io.takari.junit</groupId>
+ <artifactId>takari-cpsuite</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>ch.qos.logback</groupId>
+ <artifactId>logback-classic</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.google.code.gson</groupId>
+ <artifactId>gson</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-lang3</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.thingsboard</groupId>
+ <artifactId>netty-mqtt</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.thingsboard</groupId>
+ <artifactId>tools</artifactId>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <includes>
+ <include>**/*TestSuite.java</include>
+ </includes>
+ <skipTests>${integrationtests.skip}</skipTests>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
msa/integration-tests/README.md 18(+18 -0)
diff --git a/msa/integration-tests/README.md b/msa/integration-tests/README.md
new file mode 100644
index 0000000..5ae6354
--- /dev/null
+++ b/msa/integration-tests/README.md
@@ -0,0 +1,18 @@
+
+## 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
\ No newline at end of file
diff --git a/msa/integration-tests/src/test/java/org/thingsboard/server/msa/AbstractContainerTest.java b/msa/integration-tests/src/test/java/org/thingsboard/server/msa/AbstractContainerTest.java
new file mode 100644
index 0000000..ab7f101
--- /dev/null
+++ b/msa/integration-tests/src/test/java/org/thingsboard/server/msa/AbstractContainerTest.java
@@ -0,0 +1,112 @@
+/**
+ * Copyright © 2016-2018 The Thingsboard Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.thingsboard.server.msa;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.common.collect.ImmutableMap;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonObject;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.RandomStringUtils;
+import org.junit.*;
+import org.thingsboard.client.tools.RestClient;
+import org.thingsboard.server.common.data.Device;
+import org.thingsboard.server.common.data.EntityType;
+import org.thingsboard.server.common.data.id.DeviceId;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+import java.util.concurrent.TimeUnit;
+
+@Slf4j
+public abstract class AbstractContainerTest {
+ protected static String httpUrl;
+ protected static String wsUrl;
+ protected static RestClient restClient;
+ protected ObjectMapper mapper = new ObjectMapper();
+
+ @BeforeClass
+ public static void before() {
+ httpUrl = "http://localhost:" + ContainerTestSuite.composeContainer.getServicePort("tb-web-ui1", ContainerTestSuite.EXPOSED_PORT);
+ wsUrl = "ws://localhost:" + ContainerTestSuite.composeContainer.getServicePort("tb-web-ui1", ContainerTestSuite.EXPOSED_PORT);
+ restClient = new RestClient(httpUrl);
+ }
+
+ protected Device createDevice(String name) {
+ return restClient.createDevice(name + RandomStringUtils.randomAlphanumeric(7), "DEFAULT");
+ }
+
+ protected WsClient subscribeToTelemetryWebSocket(DeviceId deviceId) throws URISyntaxException, InterruptedException {
+ WsClient mWs = new WsClient(new URI(wsUrl + "/api/ws/plugins/telemetry?token=" + restClient.getToken()));
+ mWs.connectBlocking(1, TimeUnit.SECONDS);
+
+ JsonObject tsSubCmd = new JsonObject();
+ tsSubCmd.addProperty("entityType", EntityType.DEVICE.name());
+ tsSubCmd.addProperty("entityId", deviceId.toString());
+ tsSubCmd.addProperty("scope", "LATEST_TELEMETRY");
+ tsSubCmd.addProperty("cmdId", new Random().nextInt(100));
+ tsSubCmd.addProperty("unsubscribe", false);
+ JsonArray wsTsSubCmds = new JsonArray();
+ wsTsSubCmds.add(tsSubCmd);
+ JsonObject wsRequest = new JsonObject();
+ wsRequest.add("tsSubCmds", wsTsSubCmds);
+ wsRequest.add("historyCmds", new JsonArray());
+ wsRequest.add("attrSubCmds", new JsonArray());
+ mWs.send(wsRequest.toString());
+ return mWs;
+ }
+
+ protected Map<String, Long> getExpectedLatestValues(long ts) {
+ return ImmutableMap.<String, Long>builder()
+ .put("booleanKey", ts)
+ .put("stringKey", ts)
+ .put("doubleKey", ts)
+ .put("longKey", ts)
+ .build();
+ }
+
+ protected boolean verify(WsTelemetryResponse wsTelemetryResponse, String key, Long expectedTs, String expectedValue) {
+ List<Object> list = wsTelemetryResponse.getDataValuesByKey(key);
+ return expectedTs.equals(list.get(0)) && expectedValue.equals(list.get(1));
+ }
+
+ protected boolean verify(WsTelemetryResponse wsTelemetryResponse, String key, String expectedValue) {
+ List<Object> list = wsTelemetryResponse.getDataValuesByKey(key);
+ return expectedValue.equals(list.get(1));
+ }
+
+ protected JsonObject createPayload(long ts) {
+ JsonObject values = createPayload();
+ JsonObject payload = new JsonObject();
+ payload.addProperty("ts", ts);
+ payload.add("values", values);
+ return payload;
+ }
+
+ protected JsonObject createPayload() {
+ JsonObject values = new JsonObject();
+ values.addProperty("stringKey", "value1");
+ values.addProperty("booleanKey", true);
+ values.addProperty("doubleKey", 42.0);
+ values.addProperty("longKey", 73L);
+
+ return values;
+ }
+
+}
diff --git a/msa/integration-tests/src/test/java/org/thingsboard/server/msa/connectivity/HttpClientTest.java b/msa/integration-tests/src/test/java/org/thingsboard/server/msa/connectivity/HttpClientTest.java
new file mode 100644
index 0000000..7cc0a0f
--- /dev/null
+++ b/msa/integration-tests/src/test/java/org/thingsboard/server/msa/connectivity/HttpClientTest.java
@@ -0,0 +1,57 @@
+/**
+ * Copyright © 2016-2018 The Thingsboard Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.thingsboard.server.msa.connectivity;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.springframework.http.ResponseEntity;
+import org.thingsboard.server.common.data.Device;
+import org.thingsboard.server.common.data.security.DeviceCredentials;
+import org.thingsboard.server.msa.AbstractContainerTest;
+import org.thingsboard.server.msa.WsClient;
+import org.thingsboard.server.msa.WsTelemetryResponse;
+
+import java.util.concurrent.TimeUnit;
+
+public class HttpClientTest extends AbstractContainerTest {
+
+ @Test
+ public void telemetryUpdate() throws Exception {
+ restClient.login("tenant@thingsboard.org", "tenant");
+
+ Device device = createDevice("http_");
+ DeviceCredentials deviceCredentials = restClient.getCredentials(device.getId());
+
+ WsClient mWs = subscribeToTelemetryWebSocket(device.getId());
+ ResponseEntity deviceTelemetryResponse = restClient.getRestTemplate()
+ .postForEntity(httpUrl + "/api/v1/{credentialsId}/telemetry",
+ mapper.readTree(createPayload().toString()),
+ ResponseEntity.class,
+ deviceCredentials.getCredentialsId());
+ Assert.assertTrue(deviceTelemetryResponse.getStatusCode().is2xxSuccessful());
+ TimeUnit.SECONDS.sleep(1);
+ WsTelemetryResponse actualLatestTelemetry = mapper.readValue(mWs.getLastMessage(), WsTelemetryResponse.class);
+
+ Assert.assertEquals(getExpectedLatestValues(123456789L).keySet(), actualLatestTelemetry.getLatestValues().keySet());
+
+ Assert.assertTrue(verify(actualLatestTelemetry, "booleanKey", Boolean.TRUE.toString()));
+ Assert.assertTrue(verify(actualLatestTelemetry, "stringKey", "value1"));
+ Assert.assertTrue(verify(actualLatestTelemetry, "doubleKey", Double.toString(42.0)));
+ Assert.assertTrue(verify(actualLatestTelemetry, "longKey", Long.toString(73)));
+
+ restClient.getRestTemplate().delete(httpUrl + "/api/device/" + device.getId());
+ }
+}
diff --git a/msa/integration-tests/src/test/java/org/thingsboard/server/msa/connectivity/MqttClientTest.java b/msa/integration-tests/src/test/java/org/thingsboard/server/msa/connectivity/MqttClientTest.java
new file mode 100644
index 0000000..4ad638e
--- /dev/null
+++ b/msa/integration-tests/src/test/java/org/thingsboard/server/msa/connectivity/MqttClientTest.java
@@ -0,0 +1,111 @@
+/**
+ * Copyright © 2016-2018 The Thingsboard Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.thingsboard.server.msa.connectivity;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
+import lombok.Data;
+import org.junit.*;
+import org.thingsboard.mqtt.MqttClient;
+import org.thingsboard.mqtt.MqttClientConfig;
+import org.thingsboard.mqtt.MqttHandler;
+import org.thingsboard.server.common.data.Device;
+import org.thingsboard.server.common.data.security.DeviceCredentials;
+import org.thingsboard.server.msa.AbstractContainerTest;
+import org.thingsboard.server.msa.WsClient;
+import org.thingsboard.server.msa.WsTelemetryResponse;
+
+import java.nio.charset.StandardCharsets;
+import java.util.concurrent.*;
+
+public class MqttClientTest extends AbstractContainerTest {
+
+ @Test
+ public void telemetryUpload() throws Exception {
+ restClient.login("tenant@thingsboard.org", "tenant");
+ Device device = createDevice("mqtt_");
+ DeviceCredentials deviceCredentials = restClient.getCredentials(device.getId());
+
+ WsClient mWs = subscribeToTelemetryWebSocket(device.getId());
+ MqttClient mqttClient = getMqttClient(deviceCredentials);
+ mqttClient.publish("v1/devices/me/telemetry", Unpooled.wrappedBuffer(createPayload().toString().getBytes()));
+ TimeUnit.SECONDS.sleep(1);
+ WsTelemetryResponse actualLatestTelemetry = mapper.readValue(mWs.getLastMessage(), WsTelemetryResponse.class);
+
+ Assert.assertEquals(getExpectedLatestValues(123456789L).keySet(), actualLatestTelemetry.getLatestValues().keySet());
+
+ Assert.assertTrue(verify(actualLatestTelemetry, "booleanKey", Boolean.TRUE.toString()));
+ Assert.assertTrue(verify(actualLatestTelemetry, "stringKey", "value1"));
+ Assert.assertTrue(verify(actualLatestTelemetry, "doubleKey", Double.toString(42.0)));
+ Assert.assertTrue(verify(actualLatestTelemetry, "longKey", Long.toString(73)));
+
+ restClient.getRestTemplate().delete(httpUrl + "/api/device/" + device.getId());
+ }
+
+ @Test
+ public void telemetryUploadWithTs() throws Exception {
+ long ts = 1451649600512L;
+
+ restClient.login("tenant@thingsboard.org", "tenant");
+ Device device = createDevice("mqtt_");
+ DeviceCredentials deviceCredentials = restClient.getCredentials(device.getId());
+
+ WsClient mWs = subscribeToTelemetryWebSocket(device.getId());
+ MqttClient mqttClient = getMqttClient(deviceCredentials);
+ mqttClient.publish("v1/devices/me/telemetry", Unpooled.wrappedBuffer(createPayload(ts).toString().getBytes()));
+ TimeUnit.SECONDS.sleep(1);
+ WsTelemetryResponse actualLatestTelemetry = mapper.readValue(mWs.getLastMessage(), WsTelemetryResponse.class);
+
+ Assert.assertEquals(getExpectedLatestValues(ts), actualLatestTelemetry.getLatestValues());
+
+ Assert.assertTrue(verify(actualLatestTelemetry, "booleanKey", ts, Boolean.TRUE.toString()));
+ Assert.assertTrue(verify(actualLatestTelemetry, "stringKey", ts, "value1"));
+ Assert.assertTrue(verify(actualLatestTelemetry, "doubleKey", ts, Double.toString(42.0)));
+ Assert.assertTrue(verify(actualLatestTelemetry, "longKey", ts, Long.toString(73)));
+
+ restClient.getRestTemplate().delete(httpUrl + "/api/device/" + device.getId());
+ }
+
+ private MqttClient getMqttClient(DeviceCredentials deviceCredentials) throws InterruptedException {
+ MqttMessageListener queue = new MqttMessageListener();
+ MqttClientConfig clientConfig = new MqttClientConfig();
+ clientConfig.setClientId("MQTT client from test");
+ clientConfig.setUsername(deviceCredentials.getCredentialsId());
+ MqttClient mqttClient = MqttClient.create(clientConfig, queue);
+ mqttClient.connect("localhost", 1883).sync();
+ return mqttClient;
+ }
+
+ @Data
+ private class MqttMessageListener implements MqttHandler {
+ private final BlockingQueue<MqttEvent> events;
+
+ private MqttMessageListener() {
+ events = new ArrayBlockingQueue<>(100);
+ }
+
+ @Override
+ public void onMessage(String topic, ByteBuf message) {
+ events.add(new MqttEvent(topic, message.toString(StandardCharsets.UTF_8)));
+ }
+ }
+
+ @Data
+ private class MqttEvent {
+ private final String topic;
+ private final String message;
+ }
+}
diff --git a/msa/integration-tests/src/test/java/org/thingsboard/server/msa/ContainerTestSuite.java b/msa/integration-tests/src/test/java/org/thingsboard/server/msa/ContainerTestSuite.java
new file mode 100644
index 0000000..fd2de22
--- /dev/null
+++ b/msa/integration-tests/src/test/java/org/thingsboard/server/msa/ContainerTestSuite.java
@@ -0,0 +1,37 @@
+/**
+ * Copyright © 2016-2018 The Thingsboard Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.thingsboard.server.msa;
+
+import org.junit.ClassRule;
+import org.junit.extensions.cpsuite.ClasspathSuite;
+import org.junit.runner.RunWith;
+import org.testcontainers.containers.DockerComposeContainer;
+import org.testcontainers.containers.wait.strategy.Wait;
+
+import java.io.File;
+
+@RunWith(ClasspathSuite.class)
+@ClasspathSuite.ClassnameFilters({"org.thingsboard.server.msa.*"})
+public class ContainerTestSuite {
+ static final int EXPOSED_PORT = 8080;
+
+ @ClassRule
+ public static DockerComposeContainer composeContainer = new DockerComposeContainer(new File("./../docker/docker-compose.yml"))
+ .withPull(false)
+ .withLocalCompose(true)
+ .withTailChildContainers(true)
+ .withExposedService("tb-web-ui1", EXPOSED_PORT, Wait.forHttp("/login"));
+}
diff --git a/msa/integration-tests/src/test/java/org/thingsboard/server/msa/WsClient.java b/msa/integration-tests/src/test/java/org/thingsboard/server/msa/WsClient.java
new file mode 100644
index 0000000..2f05eee
--- /dev/null
+++ b/msa/integration-tests/src/test/java/org/thingsboard/server/msa/WsClient.java
@@ -0,0 +1,57 @@
+/**
+ * Copyright © 2016-2018 The Thingsboard Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.thingsboard.server.msa;
+
+import org.java_websocket.client.WebSocketClient;
+import org.java_websocket.handshake.ServerHandshake;
+
+import java.net.URI;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.BlockingQueue;
+
+public class WsClient extends WebSocketClient {
+ private final BlockingQueue<String> events;
+ private String message;
+
+ public WsClient(URI serverUri) {
+ super(serverUri);
+ events = new ArrayBlockingQueue<>(100);
+ }
+
+ @Override
+ public void onOpen(ServerHandshake serverHandshake) {
+ }
+
+ @Override
+ public void onMessage(String message) {
+ events.add(message);
+ this.message = message;
+ }
+
+ @Override
+ public void onClose(int code, String reason, boolean remote) {
+ events.clear();
+ }
+
+ @Override
+ public void onError(Exception ex) {
+ ex.printStackTrace();
+ }
+
+ public String getLastMessage() {
+ return this.message;
+ }
+}
\ No newline at end of file
diff --git a/msa/integration-tests/src/test/java/org/thingsboard/server/msa/WsTelemetryResponse.java b/msa/integration-tests/src/test/java/org/thingsboard/server/msa/WsTelemetryResponse.java
new file mode 100644
index 0000000..834c5d1
--- /dev/null
+++ b/msa/integration-tests/src/test/java/org/thingsboard/server/msa/WsTelemetryResponse.java
@@ -0,0 +1,40 @@
+/**
+ * Copyright © 2016-2018 The Thingsboard Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.thingsboard.server.msa;
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+@Data
+public class WsTelemetryResponse implements Serializable {
+ private int subscriptionId;
+ private int errorCode;
+ private String errorMsg;
+ private Map<String, List<List<Object>>> data;
+ private Map<String, Object> latestValues;
+
+ public List<Object> getDataValuesByKey(String key) {
+ return data.entrySet().stream()
+ .filter(e -> e.getKey().equals(key))
+ .flatMap(e -> e.getValue().stream().flatMap(Collection::stream))
+ .collect(Collectors.toList());
+ }
+}
msa/pom.xml 1(+1 -0)
diff --git a/msa/pom.xml b/msa/pom.xml
index 21ddb4d..dd4c365 100644
--- a/msa/pom.xml
+++ b/msa/pom.xml
@@ -40,6 +40,7 @@
<module>js-executor</module>
<module>web-ui</module>
<module>tb-node</module>
+ <module>integration-tests</module>
</modules>
<build>