Commit 44e614c249f0605308316e054b0b505b763af932

Authored by Valerii Sosliuk
1 parent c7f55666

MQTT RPC Client test

... ... @@ -86,6 +86,12 @@
86 86 <scope>test</scope>
87 87 </dependency>
88 88 <dependency>
  89 + <groupId>org.eclipse.paho</groupId>
  90 + <artifactId>org.eclipse.paho.client.mqttv3</artifactId>
  91 + <version>1.1.0</version>
  92 + <scope>test</scope>
  93 + </dependency>
  94 + <dependency>
89 95 <groupId>org.cassandraunit</groupId>
90 96 <artifactId>cassandra-unit</artifactId>
91 97 <exclusions>
... ... @@ -212,6 +218,12 @@
212 218 <groupId>io.grpc</groupId>
213 219 <artifactId>grpc-stub</artifactId>
214 220 </dependency>
  221 + <dependency>
  222 + <groupId>org.thingsboard.server</groupId>
  223 + <artifactId>tools</artifactId>
  224 + <version>0.0.1-SNAPSHOT</version>
  225 + <scope>test</scope>
  226 + </dependency>
215 227 </dependencies>
216 228
217 229 <build>
... ...
  1 +/**
  2 + * Copyright © 2016 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.rpc;
  17 +
  18 +import org.junit.runner.RunWith;
  19 +import org.springframework.beans.factory.annotation.Autowired;
  20 +import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
  21 +import org.springframework.boot.test.IntegrationTest;
  22 +import org.springframework.boot.test.SpringApplicationContextLoader;
  23 +import org.springframework.context.annotation.ComponentScan;
  24 +import org.springframework.context.annotation.Configuration;
  25 +import org.springframework.http.converter.HttpMessageConverter;
  26 +import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
  27 +import org.springframework.test.annotation.DirtiesContext;
  28 +import org.springframework.test.context.ActiveProfiles;
  29 +import org.springframework.test.context.ContextConfiguration;
  30 +import org.springframework.test.context.TestPropertySource;
  31 +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
  32 +import org.springframework.test.context.web.WebAppConfiguration;
  33 +import org.springframework.web.context.WebApplicationContext;
  34 +import org.thingsboard.server.rpc.mqtt.MqttRpcIntergrationTest;
  35 +
  36 +import java.util.Arrays;
  37 +
  38 +import static org.junit.Assert.assertNotNull;
  39 +
  40 +/**
  41 + * @author Valerii Sosliuk
  42 + */
  43 +@ActiveProfiles("default")
  44 +@RunWith(SpringJUnit4ClassRunner.class)
  45 +@ContextConfiguration(classes=MqttRpcIntergrationTest.class, loader=SpringApplicationContextLoader.class)
  46 +@TestPropertySource("classpath:cassandra-test.properties")
  47 +@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
  48 +@Configuration
  49 +@EnableAutoConfiguration
  50 +@ComponentScan({"org.thingsboard.server"})
  51 +@WebAppConfiguration
  52 +@IntegrationTest("server.port:8080")
  53 +public class AbstractRpcIntegrationTest {
  54 +
  55 + @SuppressWarnings("rawtypes")
  56 + private HttpMessageConverter mappingJackson2HttpMessageConverter;
  57 +
  58 + @Autowired
  59 + private WebApplicationContext webApplicationContext;
  60 +
  61 + @Autowired
  62 + void setConverters(HttpMessageConverter<?>[] converters) {
  63 +
  64 + this.mappingJackson2HttpMessageConverter = Arrays.asList(converters).stream().filter(
  65 + hmc -> hmc instanceof MappingJackson2HttpMessageConverter).findAny().get();
  66 +
  67 + assertNotNull("the JSON message converter must not be null",
  68 + this.mappingJackson2HttpMessageConverter);
  69 + }
  70 +
  71 +}
... ...
  1 +/**
  2 + * Copyright © 2016 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.rpc.mqtt;
  17 +
  18 +import lombok.extern.slf4j.Slf4j;
  19 +import org.eclipse.paho.client.mqttv3.MqttAsyncClient;
  20 +import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
  21 +import org.eclipse.paho.client.mqttv3.MqttMessage;
  22 +import org.junit.Before;
  23 +import org.junit.Test;
  24 +import org.springframework.web.util.UriComponentsBuilder;
  25 +import org.thingsboard.client.tools.RestClient;
  26 +import org.thingsboard.server.common.data.Device;
  27 +import org.thingsboard.server.common.data.security.DeviceCredentials;
  28 +import org.thingsboard.server.rpc.AbstractRpcIntegrationTest;
  29 +
  30 +import java.net.URI;
  31 +import java.util.Arrays;
  32 +import java.util.List;
  33 +import java.util.Map;
  34 +
  35 +import static org.junit.Assert.assertEquals;
  36 +import static org.junit.Assert.assertNotNull;
  37 +
  38 +/**
  39 + * @author Valerii Sosliuk
  40 + */
  41 +@Slf4j
  42 +public class MqttRpcIntergrationTest extends AbstractRpcIntegrationTest {
  43 +
  44 + private static final String MQTT_URL = "tcp://localhost:1883";
  45 + private static final String BASE_URL = "http://localhost:8080";
  46 +
  47 + private static final String USERNAME = "tenant@thingsboard.org";
  48 + private static final String PASSWORD = "tenant";
  49 +
  50 + private Device savedDevice;
  51 +
  52 + private String accessToken;
  53 + private RestClient restClient;
  54 +
  55 + @Before
  56 + public void beforeTest() throws Exception {
  57 + restClient = new RestClient(BASE_URL);
  58 + restClient.login(USERNAME, PASSWORD);
  59 +
  60 + Device device = new Device();
  61 + device.setName("Test device");
  62 + savedDevice = restClient.getRestTemplate().postForEntity(BASE_URL + "/api/device", device, Device.class).getBody();
  63 + DeviceCredentials deviceCredentials =
  64 + restClient.getRestTemplate().getForEntity(BASE_URL + "/api/device/" + savedDevice.getId().getId().toString() + "/credentials", DeviceCredentials.class).getBody();
  65 + assertEquals(savedDevice.getId(), deviceCredentials.getDeviceId());
  66 + accessToken = deviceCredentials.getCredentialsId();
  67 + assertNotNull(accessToken);
  68 + }
  69 +
  70 + @Test
  71 + public void testPushMqttRpcData() throws Exception {
  72 + String clientId = MqttAsyncClient.generateClientId();
  73 + MqttAsyncClient client = new MqttAsyncClient(MQTT_URL, clientId);
  74 +
  75 + MqttConnectOptions options = new MqttConnectOptions();
  76 + options.setUserName(accessToken);
  77 + client.connect(options);
  78 + Thread.sleep(3000);
  79 + MqttMessage message = new MqttMessage();
  80 + message.setPayload("{\"key1\":\"value1\", \"key2\":true, \"key3\": 3.0, \"key4\": 4}".getBytes());
  81 + client.publish("v1/devices/me/telemetry", message);
  82 +
  83 + String deviceId = savedDevice.getId().getId().toString();
  84 +
  85 + Thread.sleep(1000);
  86 + List keys = restClient.getRestTemplate().getForEntity(BASE_URL + "/api/plugins/telemetry/" + deviceId + "/keys/timeseries", List.class).getBody();
  87 + assertEquals(Arrays.asList("key1", "key2", "key3", "key4"), keys);
  88 +
  89 + UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(BASE_URL + "/api/plugins/telemetry/" + deviceId + "/values/timeseries")
  90 + .queryParam("keys", String.join(",", keys));
  91 + URI uri = builder.build().encode().toUri();
  92 + Map<String, List<Map<String, String>>> values = restClient.getRestTemplate().getForEntity(uri, Map.class).getBody();
  93 +
  94 + assertEquals("value1", values.get("key1").get(0).get("value"));
  95 + assertEquals("true", values.get("key2").get(0).get("value"));
  96 + assertEquals("3.0", values.get("key3").get(0).get("value"));
  97 + assertEquals("4", values.get("key4").get(0).get("value"));
  98 + }
  99 +}
... ...
  1 +/**
  2 + * Copyright © 2016 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.rpc.mqtt;
  17 +
  18 +import org.cassandraunit.dataset.cql.ClassPathCQLDataSet;
  19 +import org.junit.ClassRule;
  20 +import org.junit.extensions.cpsuite.ClasspathSuite;
  21 +import org.junit.runner.RunWith;
  22 +import org.thingsboard.server.dao.CustomCassandraCQLUnit;
  23 +
  24 +import java.util.Arrays;
  25 +
  26 +/**
  27 + * @author Valerii Sosliuk
  28 + */
  29 +@RunWith(ClasspathSuite.class)
  30 +@ClasspathSuite.ClassnameFilters({"org.thingsboard.server.rpc.mqtt.*Test"})
  31 +public class MqttRpcSuite {
  32 +
  33 + @ClassRule
  34 + public static CustomCassandraCQLUnit cassandraUnit =
  35 + new CustomCassandraCQLUnit(
  36 + Arrays.asList(new ClassPathCQLDataSet("schema.cql", false, false),
  37 + new ClassPathCQLDataSet("system-data.cql", false, false),
  38 + new ClassPathCQLDataSet("demo-data.cql", false, false)),
  39 + "cassandra-test.yaml", 30000l);
  40 +
  41 +}
... ...
1   -/**
  1 +package org.thingsboard.client.tools; /**
2 2 * Copyright © 2016 The Thingsboard Authors
3 3 *
4 4 * Licensed under the Apache License, Version 2.0 (the "License");
... ...
1   -/**
  1 +package org.thingsboard.client.tools; /**
2 2 * Copyright © 2016 The Thingsboard Authors
3 3 *
4 4 * Licensed under the Apache License, Version 2.0 (the "License");
... ...
1   -/**
  1 +package org.thingsboard.client.tools; /**
2 2 * Copyright © 2016 The Thingsboard Authors
3 3 *
4 4 * Licensed under the Apache License, Version 2.0 (the "License");
... ... @@ -62,6 +62,10 @@ public class RestClient implements ClientHttpRequestInterceptor {
62 62 return restTemplate.getForEntity(baseURL + "/api/device/" + id.getId().toString() + "/credentials", DeviceCredentials.class).getBody();
63 63 }
64 64
  65 + public RestTemplate getRestTemplate() {
  66 + return restTemplate;
  67 + }
  68 +
65 69 @Override
66 70 public ClientHttpResponse intercept(HttpRequest request, byte[] bytes, ClientHttpRequestExecution execution) throws IOException {
67 71 HttpRequest wrapper = new HttpRequestWrapper(request);
... ...
1   -/**
  1 +package org.thingsboard.client.tools; /**
2 2 * Copyright © 2016 The Thingsboard Authors
3 3 *
4 4 * Licensed under the Apache License, Version 2.0 (the "License");
... ... @@ -73,7 +73,7 @@ public class ResultAccumulator {
73 73
74 74 @Override
75 75 public String toString() {
76   - return "ResultAccumulator{" +
  76 + return "org.thingsboard.client.tools.ResultAccumulator{" +
77 77 "successCount=" + getSuccessCount() +
78 78 ", errorCount=" + getErrorCount() +
79 79 ", totalTime=" + getTimeSpent() +
... ...