Browse Source

refactoring coap-tests-speed-up

pull/6603/head
Yuriy Lytvynchuk 4 years ago
parent
commit
7ed34c16eb
  1. 17
      application/src/test/java/org/thingsboard/server/transport/coap/AbstractCoapIntegrationTest.java
  2. 53
      application/src/test/java/org/thingsboard/server/transport/coap/CoapTestCallback.java
  3. 22
      application/src/test/java/org/thingsboard/server/transport/coap/CoapTestClient.java
  4. 220
      application/src/test/java/org/thingsboard/server/transport/coap/attributes/AbstractCoapAttributesIntegrationTest.java
  5. 14
      application/src/test/java/org/thingsboard/server/transport/coap/attributes/request/CoapAttributesRequestIntegrationTest.java
  6. 114
      application/src/test/java/org/thingsboard/server/transport/coap/attributes/request/CoapAttributesRequestProtoIntegrationTest.java
  7. 170
      application/src/test/java/org/thingsboard/server/transport/coap/attributes/updates/CoapAttributesUpdatesIntegrationTest.java
  8. 7
      application/src/test/java/org/thingsboard/server/transport/coap/attributes/updates/CoapAttributesUpdatesJsonIntegrationTest.java
  9. 91
      application/src/test/java/org/thingsboard/server/transport/coap/attributes/updates/CoapAttributesUpdatesProtoIntegrationTest.java
  10. 10
      application/src/test/java/org/thingsboard/server/transport/coap/claim/CoapClaimDeviceTest.java
  11. 3
      application/src/test/java/org/thingsboard/server/transport/coap/claim/CoapClaimProtoDeviceTest.java
  12. 80
      application/src/test/java/org/thingsboard/server/transport/coap/provision/CoapProvisionJsonDeviceTest.java
  13. 57
      application/src/test/java/org/thingsboard/server/transport/coap/provision/CoapProvisionProtoDeviceTest.java
  14. 216
      application/src/test/java/org/thingsboard/server/transport/coap/rpc/AbstractCoapServerSideRpcIntegrationTest.java
  15. 7
      application/src/test/java/org/thingsboard/server/transport/coap/rpc/CoapServerSideRpcDefaultIntegrationTest.java
  16. 4
      application/src/test/java/org/thingsboard/server/transport/coap/rpc/CoapServerSideRpcJsonIntegrationTest.java
  17. 87
      application/src/test/java/org/thingsboard/server/transport/coap/rpc/CoapServerSideRpcProtoIntegrationTest.java
  18. 50
      application/src/test/java/org/thingsboard/server/transport/coap/telemetry/attributes/CoapAttributesIntegrationTest.java
  19. 54
      application/src/test/java/org/thingsboard/server/transport/coap/telemetry/timeseries/AbstractCoapTimeseriesIntegrationTest.java
  20. 1
      application/src/test/java/org/thingsboard/server/transport/coap/telemetry/timeseries/AbstractCoapTimeseriesProtoIntegrationTest.java

17
application/src/test/java/org/thingsboard/server/transport/coap/AbstractCoapIntegrationTest.java

@ -55,12 +55,7 @@ public abstract class AbstractCoapIntegrationTest extends AbstractTransportInteg
protected final byte[] EMPTY_PAYLOAD = new byte[0];
protected CoapClient client;
protected void processAfterTest() throws Exception {
if (client != null) {
client.shutdown();
}
}
protected void processBeforeTest(CoapTestConfigProperties config) throws Exception {
@ -156,16 +151,4 @@ public abstract class AbstractCoapIntegrationTest extends AbstractTransportInteg
device.setType(type);
return doPost("/api/device", device, Device.class);
}
protected CoapClient getCoapClient(FeatureType featureType) {
return new CoapClient(getFeatureTokenUrl(accessToken, featureType));
}
protected CoapClient getCoapClient(String featureTokenUrl) {
return new CoapClient(featureTokenUrl);
}
protected String getFeatureTokenUrl(String token, FeatureType featureType) {
return COAP_BASE_URL + token + "/" + featureType.name().toLowerCase();
}
}

53
application/src/test/java/org/thingsboard/server/transport/coap/CoapTestCallback.java

@ -0,0 +1,53 @@
package org.thingsboard.server.transport.coap;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.californium.core.CoapHandler;
import org.eclipse.californium.core.CoapResponse;
import org.eclipse.californium.core.coap.CoAP;
import java.util.concurrent.CountDownLatch;
@Slf4j
@Data
public class CoapTestCallback implements CoapHandler {
protected final CountDownLatch latch;
protected Integer observe;
protected byte[] payloadBytes;
protected CoAP.ResponseCode responseCode;
public CoapTestCallback() {
this.latch = new CountDownLatch(1);
}
public CoapTestCallback(int subscribeCount) {
this.latch = new CountDownLatch(subscribeCount);
}
public Integer getObserve() {
return observe;
}
public byte[] getPayloadBytes() {
return payloadBytes;
}
public CoAP.ResponseCode getResponseCode() {
return responseCode;
}
@Override
public void onLoad(CoapResponse response) {
observe = response.getOptions().getObserve();
payloadBytes = response.getPayload();
responseCode = response.getCode();
latch.countDown();
}
@Override
public void onError() {
log.warn("Command Response Ack Error, No connect");
}
}

22
application/src/test/java/org/thingsboard/server/transport/coap/CoapTestClient.java

@ -1,8 +1,12 @@
package org.thingsboard.server.transport.coap;
import org.eclipse.californium.core.CoapClient;
import org.eclipse.californium.core.CoapHandler;
import org.eclipse.californium.core.CoapObserveRelation;
import org.eclipse.californium.core.CoapResponse;
import org.eclipse.californium.core.coap.CoAP;
import org.eclipse.californium.core.coap.MediaTypeRegistry;
import org.eclipse.californium.core.coap.Request;
import org.eclipse.californium.elements.exception.ConnectorException;
import org.thingsboard.server.common.msg.session.FeatureType;
@ -49,10 +53,24 @@ public class CoapTestClient {
return client.setTimeout(CLIENT_REQUEST_TIMEOUT).post(requestBodyBytes, MediaTypeRegistry.APPLICATION_JSON);
}
public void postMethod(CoapHandler handler, String payload, int format) {
client.post(handler, payload, format);
}
public void postMethod(CoapHandler handler, byte[] payload, int format) {
client.post(handler, payload, format);
}
public CoapResponse getMethod() throws ConnectorException, IOException {
return client.setTimeout(CLIENT_REQUEST_TIMEOUT).get();
}
public CoapObserveRelation getObserveRelation(CoapTestCallback callback){
Request request = Request.newGet().setObserve();
request.setType(CoAP.Type.CON);
return client.observe(request, callback);
}
public void setURI(String featureTokenUrl) {
if (client == null) {
throw new RuntimeException("Failed to connect! CoapClient is not initialized!");
@ -78,4 +96,8 @@ public class CoapTestClient {
public static String getFeatureTokenUrl(String token, FeatureType featureType) {
return COAP_BASE_URL + token + "/" + featureType.name().toLowerCase();
}
public static String getFeatureTokenUrl(String token, FeatureType featureType, int requestId) {
return COAP_BASE_URL + token + "/" + featureType.name().toLowerCase() + "/" + requestId;
}
}

220
application/src/test/java/org/thingsboard/server/transport/coap/attributes/AbstractCoapAttributesIntegrationTest.java

@ -23,9 +23,12 @@ import com.google.protobuf.InvalidProtocolBufferException;
import com.squareup.wire.schema.internal.parser.ProtoFileElement;
import io.netty.handler.codec.mqtt.MqttQoS;
import lombok.extern.slf4j.Slf4j;
import org.awaitility.Awaitility;
import org.eclipse.californium.core.CoapObserveRelation;
import org.eclipse.californium.core.CoapResponse;
import org.eclipse.californium.core.coap.CoAP;
import org.eclipse.californium.core.coap.MediaTypeRegistry;
import org.springframework.beans.factory.annotation.Autowired;
import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.server.common.data.device.profile.*;
import org.thingsboard.server.common.data.query.DeviceTypeFilter;
@ -33,16 +36,20 @@ import org.thingsboard.server.common.data.query.EntityKey;
import org.thingsboard.server.common.data.query.EntityKeyType;
import org.thingsboard.server.common.data.query.SingleEntityFilter;
import org.thingsboard.server.common.msg.session.FeatureType;
import org.thingsboard.server.common.transport.service.DefaultTransportService;
import org.thingsboard.server.gen.transport.TransportApiProtos;
import org.thingsboard.server.gen.transport.TransportProtos;
import org.thingsboard.server.transport.coap.AbstractCoapIntegrationTest;
import org.thingsboard.server.transport.coap.CoapTestCallback;
import org.thingsboard.server.transport.coap.CoapTestClient;
import org.thingsboard.server.transport.coap.attributes.updates.CoapAttributesUpdatesIntegrationTest;
import org.thingsboard.server.transport.mqtt.MqttTestCallback;
import org.thingsboard.server.transport.mqtt.MqttTestClient;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
@ -56,10 +63,8 @@ import static org.thingsboard.server.common.data.query.EntityKeyType.SHARED_ATTR
@Slf4j
public abstract class AbstractCoapAttributesIntegrationTest extends AbstractCoapIntegrationTest {
protected static final long CLIENT_REQUEST_TIMEOUT = 60000L;
protected static final String POST_ATTRIBUTES_PAYLOAD = "{\"attribute1\":\"value1\",\"attribute2\":true,\"attribute3\":42.0,\"attribute4\":73," +
"\"attribute5\":{\"someNumber\":42,\"someArray\":[1,2,3],\"someNestedObject\":{\"key\":\"value\"}}}";
@Autowired
DefaultTransportService defaultTransportService;
public static final String ATTRIBUTES_SCHEMA_STR = "syntax =\"proto3\";\n" +
"\n" +
@ -88,7 +93,12 @@ public abstract class AbstractCoapAttributesIntegrationTest extends AbstractCoap
private static final String SHARED_ATTRIBUTES_PAYLOAD = "{\"sharedStr\":\"value1\",\"sharedBool\":true,\"sharedDbl\":42.0,\"sharedLong\":73," +
"\"sharedJson\":{\"someNumber\":42,\"someArray\":[1,2,3],\"someNestedObject\":{\"key\":\"value\"}}}";
private List<TransportProtos.TsKvProto> getTsKvProtoList(String attributePrefix) {
protected static final String SHARED_ATTRIBUTES_PAYLOAD_ON_CURRENT_STATE_NOTIFICATION = "{\"sharedStr\":\"value\",\"sharedBool\":false,\"sharedDbl\":41.0,\"sharedLong\":72," +
"\"sharedJson\":{\"someNumber\":41,\"someArray\":[],\"someNestedObject\":{\"key\":\"value\"}}}";
private static final String SHARED_ATTRIBUTES_DELETED_RESPONSE = "{\"deleted\":[\"sharedJson\"]}";
private List<TransportProtos.TsKvProto> getTsKvProtoList(String attributePrefix) {
TransportProtos.TsKvProto tsKvProtoAttribute1 = getTsKvProto(attributePrefix + "Str", "value1", TransportProtos.KeyValueType.STRING_V);
TransportProtos.TsKvProto tsKvProtoAttribute2 = getTsKvProto(attributePrefix + "Bool", "true", TransportProtos.KeyValueType.BOOLEAN_V);
TransportProtos.TsKvProto tsKvProtoAttribute3 = getTsKvProto(attributePrefix + "Dbl", "42.0", TransportProtos.KeyValueType.DOUBLE_V);
@ -103,21 +113,6 @@ public abstract class AbstractCoapAttributesIntegrationTest extends AbstractCoap
return tsKvProtoList;
}
public List<TransportProtos.TsKvProto> getTsKvProtoList() {
TransportProtos.TsKvProto tsKvProtoAttribute1 = getTsKvProto("Str", "value1", TransportProtos.KeyValueType.STRING_V);
TransportProtos.TsKvProto tsKvProtoAttribute2 = getTsKvProto("Bool", "true", TransportProtos.KeyValueType.BOOLEAN_V);
TransportProtos.TsKvProto tsKvProtoAttribute3 = getTsKvProto("Dbl", "42.0", TransportProtos.KeyValueType.DOUBLE_V);
TransportProtos.TsKvProto tsKvProtoAttribute4 = getTsKvProto("Long", "73", TransportProtos.KeyValueType.LONG_V);
TransportProtos.TsKvProto tsKvProtoAttribute5 = getTsKvProto("Json", "{\"someNumber\":42,\"someArray\":[1,2,3],\"someNestedObject\":{\"key\":\"value\"}}", TransportProtos.KeyValueType.JSON_V);
List<TransportProtos.TsKvProto> tsKvProtoList = new ArrayList<>();
tsKvProtoList.add(tsKvProtoAttribute1);
tsKvProtoList.add(tsKvProtoAttribute2);
tsKvProtoList.add(tsKvProtoAttribute3);
tsKvProtoList.add(tsKvProtoAttribute4);
tsKvProtoList.add(tsKvProtoAttribute5);
return tsKvProtoList;
}
protected TransportProtos.TsKvProto getTsKvProto(String key, String value, TransportProtos.KeyValueType keyValueType) {
TransportProtos.TsKvProto.Builder tsKvProtoBuilder = TransportProtos.TsKvProto.newBuilder();
TransportProtos.KeyValueProto keyValueProto = getKeyValueProto(key, value, keyValueType);
@ -225,43 +220,86 @@ public abstract class AbstractCoapAttributesIntegrationTest extends AbstractCoap
CoapResponse coapResponse = client.postMethod(getAttributesProtoPayloadBytes());
assertEquals(CoAP.ResponseCode.CREATED, coapResponse.getCode());
//validateProtoResponse(callback, getExpectedAttributeResponseMsg());
// client.publishAndWait(attrPubTopic, getAttributesProtoPayloadBytes());
// client.subscribeAndWait(attrSubTopic, MqttQoS.AT_MOST_ONCE);
String update = getWsClient().waitForUpdate();
assertThat(update).as("ws update received").isNotBlank();
// MqttTestCallback callback = new MqttTestCallback(attrSubTopic.replace("+", "1"));
// client.setCallback(callback);
TransportApiProtos.AttributesRequest.Builder attributesRequestBuilder = TransportApiProtos.AttributesRequest.newBuilder();
attributesRequestBuilder.setClientKeys(clientKeysStr);
attributesRequestBuilder.setSharedKeys(sharedKeysStr);
TransportApiProtos.AttributesRequest attributesRequest = attributesRequestBuilder.build();
// client.publishAndWait(attrReqTopicPrefix + "1", attributesRequest.toByteArray());
String featureTokenUrl = CoapTestClient.getFeatureTokenUrl(accessToken, FeatureType.ATTRIBUTES) + "?clientKeys=" + clientKeysStr + "&sharedKeys=" + sharedKeysStr;
client.setURI(featureTokenUrl);
validateProtoResponse(client.getMethod());
client.disconnect();
}
protected void postAttributes() throws Exception {
// //doPostAsync("/api/plugins/telemetry/DEVICE/" + savedDevice.getId().getId() + "/attributes/SHARED_SCOPE", POST_ATTRIBUTES_PAYLOAD, String.class, status().isOk());
//
// doPostAsync("/api/plugins/telemetry/DEVICE/" + savedDevice.getId().getId() + "/attributes/SHARED_SCOPE",
// SHARED_ATTRIBUTES_PAYLOAD, String.class, status().isOk());
//
//
//
// //client = getCoapClient(FeatureType.ATTRIBUTES);
// //CoapResponse coapResponse = client.setTimeout(CLIENT_REQUEST_TIMEOUT).post(POST_ATTRIBUTES_PAYLOAD.getBytes(), MediaTypeRegistry.APPLICATION_JSON);
//
// CoapTestClient client = new CoapTestClient(accessToken, FeatureType.ATTRIBUTES);
// CoapResponse coapResponse = client.postMethod(CLIENT_ATTRIBUTES_PAYLOAD);
// assertEquals(CoAP.ResponseCode.CREATED, coapResponse.getCode());
}
protected void processJsonTestSubscribeToAttributesUpdates(boolean emptyCurrentStateNotification) throws Exception {
if (!emptyCurrentStateNotification) {
doPostAsync("/api/plugins/telemetry/DEVICE/" + savedDevice.getId().getId() + "/attributes/SHARED_SCOPE", SHARED_ATTRIBUTES_PAYLOAD_ON_CURRENT_STATE_NOTIFICATION, String.class, status().isOk());
}
CoapTestClient client = new CoapTestClient(accessToken, FeatureType.ATTRIBUTES);
CoapTestCallback callbackCoap = new CoapTestCallback(1);
CoapObserveRelation observeRelation = client.getObserveRelation(callbackCoap);
callbackCoap.getLatch().await(3, TimeUnit.SECONDS);
if (emptyCurrentStateNotification) {
validateUpdateAttributesJsonResponse(callbackCoap, "{}", 0);
} else {
validateUpdateAttributesJsonResponse(callbackCoap, SHARED_ATTRIBUTES_PAYLOAD_ON_CURRENT_STATE_NOTIFICATION, 0);
}
CountDownLatch latch = new CountDownLatch(1);
int expectedObserveCnt = callbackCoap.getObserve().intValue() + 1;
doPostAsync("/api/plugins/telemetry/DEVICE/" + savedDevice.getId().getId() + "/attributes/SHARED_SCOPE", SHARED_ATTRIBUTES_PAYLOAD, String.class, status().isOk());
latch.await(3, TimeUnit.SECONDS);
validateUpdateAttributesJsonResponse(callbackCoap, SHARED_ATTRIBUTES_PAYLOAD, expectedObserveCnt);
latch = new CountDownLatch(1);
int expectedObserveBeforeDeleteCnt = callbackCoap.getObserve().intValue() + 1;
doDelete("/api/plugins/telemetry/DEVICE/" + savedDevice.getId().getId() + "/SHARED_SCOPE?keys=sharedJson", String.class);
latch.await(3, TimeUnit.SECONDS);
validateUpdateAttributesJsonResponse(callbackCoap, SHARED_ATTRIBUTES_DELETED_RESPONSE, expectedObserveBeforeDeleteCnt);
observeRelation.proactiveCancel();
assertTrue(observeRelation.isCanceled());
awaitClientAfterCancelObserve();
client.disconnect();
}
protected void processProtoTestSubscribeToAttributesUpdates(boolean emptyCurrentStateNotification) throws Exception {
if (!emptyCurrentStateNotification) {
doPostAsync("/api/plugins/telemetry/DEVICE/" + savedDevice.getId().getId() + "/attributes/SHARED_SCOPE", SHARED_ATTRIBUTES_PAYLOAD_ON_CURRENT_STATE_NOTIFICATION, String.class, status().isOk());
}
CoapTestClient client = new CoapTestClient(accessToken, FeatureType.ATTRIBUTES);
CoapTestCallback callbackCoap = new CoapTestCallback(1);
CoapObserveRelation observeRelation = client.getObserveRelation(callbackCoap);
callbackCoap.getLatch().await(3, TimeUnit.SECONDS);
if (emptyCurrentStateNotification) {
validateEmptyCurrentStateAttributesProtoResponse(callbackCoap);
} else {
validateCurrentStateAttributesProtoResponse(callbackCoap);
}
CountDownLatch latch = new CountDownLatch(1);
int expectedObserveCnt = callbackCoap.getObserve().intValue() + 1;
doPostAsync("/api/plugins/telemetry/DEVICE/" + savedDevice.getId().getId() + "/attributes/SHARED_SCOPE", SHARED_ATTRIBUTES_PAYLOAD, String.class, status().isOk());
latch.await(3, TimeUnit.SECONDS);
validateUpdateProtoAttributesResponse(callbackCoap, expectedObserveCnt);
latch = new CountDownLatch(1);
int expectedObserveBeforeDeleteCnt = callbackCoap.getObserve().intValue() + 1;
doDelete("/api/plugins/telemetry/DEVICE/" + savedDevice.getId().getId() + "/SHARED_SCOPE?keys=sharedJson", String.class);
latch.await(3, TimeUnit.SECONDS);
validateDeleteProtoAttributesResponse(callbackCoap, expectedObserveBeforeDeleteCnt);
observeRelation.proactiveCancel();
assertTrue(observeRelation.isCanceled());
awaitClientAfterCancelObserve();
client.disconnect();
}
protected void validateJsonResponse(CoapResponse getAttributesResponse) throws InvalidProtocolBufferException {
assertEquals(CoAP.ResponseCode.CONTENT, getAttributesResponse.getCode());
@ -281,6 +319,92 @@ public abstract class AbstractCoapAttributesIntegrationTest extends AbstractCoap
assertTrue(actualSharedKeyValueProtos.containsAll(expectedSharedKeyValueProtos));
}
protected void validateUpdateAttributesJsonResponse(CoapTestCallback callback, String expectedResponse, int expectedObserveCnt) {
assertNotNull(callback.getPayloadBytes());
assertNotNull(callback.getObserve());
assertEquals(CoAP.ResponseCode.CONTENT, callback.getResponseCode());
assertEquals(expectedObserveCnt, callback.getObserve().intValue());
String response = new String(callback.getPayloadBytes(), StandardCharsets.UTF_8);
assertEquals(JacksonUtil.toJsonNode(expectedResponse), JacksonUtil.toJsonNode(response));
}
protected void validateEmptyCurrentStateAttributesProtoResponse(CoapTestCallback callback) throws InvalidProtocolBufferException {
assertArrayEquals(EMPTY_PAYLOAD, callback.getPayloadBytes());
assertNotNull(callback.getObserve());
assertEquals(CoAP.ResponseCode.CONTENT, callback.getResponseCode());
assertEquals(0, callback.getObserve().intValue());
}
protected void validateCurrentStateAttributesProtoResponse(CoapTestCallback callback) throws InvalidProtocolBufferException {
assertNotNull(callback.getPayloadBytes());
assertNotNull(callback.getObserve());
assertEquals(CoAP.ResponseCode.CONTENT, callback.getResponseCode());
assertEquals(0, callback.getObserve().intValue());
TransportProtos.AttributeUpdateNotificationMsg.Builder expectedCurrentStateNotificationMsgBuilder = TransportProtos.AttributeUpdateNotificationMsg.newBuilder();
TransportProtos.TsKvProto tsKvProtoAttribute1 = getTsKvProto("sharedStr", "value", TransportProtos.KeyValueType.STRING_V);
TransportProtos.TsKvProto tsKvProtoAttribute2 = getTsKvProto("sharedBool", "false", TransportProtos.KeyValueType.BOOLEAN_V);
TransportProtos.TsKvProto tsKvProtoAttribute3 = getTsKvProto("sharedDbl", "41.0", TransportProtos.KeyValueType.DOUBLE_V);
TransportProtos.TsKvProto tsKvProtoAttribute4 = getTsKvProto("sharedLong", "72", TransportProtos.KeyValueType.LONG_V);
TransportProtos.TsKvProto tsKvProtoAttribute5 = getTsKvProto("sharedJson", "{\"someNumber\":41,\"someArray\":[],\"someNestedObject\":{\"key\":\"value\"}}", TransportProtos.KeyValueType.JSON_V);
List<TransportProtos.TsKvProto> tsKvProtoList = new ArrayList<>();
tsKvProtoList.add(tsKvProtoAttribute1);
tsKvProtoList.add(tsKvProtoAttribute2);
tsKvProtoList.add(tsKvProtoAttribute3);
tsKvProtoList.add(tsKvProtoAttribute4);
tsKvProtoList.add(tsKvProtoAttribute5);
TransportProtos.AttributeUpdateNotificationMsg expectedCurrentStateNotificationMsg = expectedCurrentStateNotificationMsgBuilder.addAllSharedUpdated(tsKvProtoList).build();
TransportProtos.AttributeUpdateNotificationMsg actualCurrentStateNotificationMsg = TransportProtos.AttributeUpdateNotificationMsg.parseFrom(callback.getPayloadBytes());
List<TransportProtos.KeyValueProto> expectedSharedUpdatedList = expectedCurrentStateNotificationMsg.getSharedUpdatedList().stream().map(TransportProtos.TsKvProto::getKv).collect(Collectors.toList());
List<TransportProtos.KeyValueProto> actualSharedUpdatedList = actualCurrentStateNotificationMsg.getSharedUpdatedList().stream().map(TransportProtos.TsKvProto::getKv).collect(Collectors.toList());
assertEquals(expectedSharedUpdatedList.size(), actualSharedUpdatedList.size());
assertTrue(actualSharedUpdatedList.containsAll(expectedSharedUpdatedList));
}
protected void validateUpdateProtoAttributesResponse(CoapTestCallback callback, int expectedObserveCnt) throws InvalidProtocolBufferException {
assertNotNull(callback.getPayloadBytes());
assertNotNull(callback.getObserve());
assertEquals(CoAP.ResponseCode.CONTENT, callback.getResponseCode());
assertEquals(expectedObserveCnt, callback.getObserve().intValue());
TransportProtos.AttributeUpdateNotificationMsg.Builder attributeUpdateNotificationMsgBuilder = TransportProtos.AttributeUpdateNotificationMsg.newBuilder();
List<TransportProtos.TsKvProto> tsKvProtoList = getTsKvProtoList("shared");
attributeUpdateNotificationMsgBuilder.addAllSharedUpdated(tsKvProtoList);
TransportProtos.AttributeUpdateNotificationMsg expectedAttributeUpdateNotificationMsg = attributeUpdateNotificationMsgBuilder.build();
TransportProtos.AttributeUpdateNotificationMsg actualAttributeUpdateNotificationMsg = TransportProtos.AttributeUpdateNotificationMsg.parseFrom(callback.getPayloadBytes());
List<TransportProtos.KeyValueProto> actualSharedUpdatedList = actualAttributeUpdateNotificationMsg.getSharedUpdatedList().stream().map(TransportProtos.TsKvProto::getKv).collect(Collectors.toList());
List<TransportProtos.KeyValueProto> expectedSharedUpdatedList = expectedAttributeUpdateNotificationMsg.getSharedUpdatedList().stream().map(TransportProtos.TsKvProto::getKv).collect(Collectors.toList());
assertEquals(expectedSharedUpdatedList.size(), actualSharedUpdatedList.size());
assertTrue(actualSharedUpdatedList.containsAll(expectedSharedUpdatedList));
}
protected void validateDeleteProtoAttributesResponse(CoapTestCallback callback, int expectedObserveCnt) throws InvalidProtocolBufferException {
assertNotNull(callback.getPayloadBytes());
assertNotNull(callback.getObserve());
assertEquals(CoAP.ResponseCode.CONTENT, callback.getResponseCode());
assertEquals(expectedObserveCnt, callback.getObserve().intValue());
TransportProtos.AttributeUpdateNotificationMsg.Builder attributeUpdateNotificationMsgBuilder = TransportProtos.AttributeUpdateNotificationMsg.newBuilder();
attributeUpdateNotificationMsgBuilder.addSharedDeleted("sharedJson");
TransportProtos.AttributeUpdateNotificationMsg expectedAttributeUpdateNotificationMsg = attributeUpdateNotificationMsgBuilder.build();
TransportProtos.AttributeUpdateNotificationMsg actualAttributeUpdateNotificationMsg = TransportProtos.AttributeUpdateNotificationMsg.parseFrom(callback.getPayloadBytes());
assertEquals(expectedAttributeUpdateNotificationMsg.getSharedDeletedList().size(), actualAttributeUpdateNotificationMsg.getSharedDeletedList().size());
assertEquals("sharedJson", actualAttributeUpdateNotificationMsg.getSharedDeletedList().get(0));
}
private void awaitClientAfterCancelObserve() {
Awaitility.await("awaitClientAfterCancelObserve")
.pollInterval(10, TimeUnit.MILLISECONDS)
.atMost(5, TimeUnit.SECONDS)
.until(()->{
log.trace("awaiting defaultTransportService.sessions is empty");
return defaultTransportService.sessions.isEmpty();});
}
private TransportProtos.GetAttributeResponseMsg getExpectedAttributeResponseMsg() {
TransportProtos.GetAttributeResponseMsg.Builder result = TransportProtos.GetAttributeResponseMsg.newBuilder();
List<TransportProtos.TsKvProto> csTsKvProtoList = getTsKvProtoList("client");

14
application/src/test/java/org/thingsboard/server/transport/coap/attributes/request/CoapAttributesRequestIntegrationTest.java

@ -15,27 +15,13 @@
*/
package org.thingsboard.server.transport.coap.attributes.request;
import com.fasterxml.jackson.core.type.TypeReference;
import com.google.protobuf.InvalidProtocolBufferException;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.californium.core.CoapResponse;
import org.eclipse.californium.core.coap.CoAP;
import org.eclipse.californium.core.coap.MediaTypeRegistry;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.server.dao.service.DaoSqlTest;
import org.thingsboard.server.transport.coap.CoapTestConfigProperties;
import org.thingsboard.server.transport.coap.attributes.AbstractCoapAttributesIntegrationTest;
import org.thingsboard.server.common.msg.session.FeatureType;
import java.nio.charset.StandardCharsets;
import java.util.List;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@Slf4j
@DaoSqlTest

114
application/src/test/java/org/thingsboard/server/transport/coap/attributes/request/CoapAttributesRequestProtoIntegrationTest.java

@ -15,64 +15,18 @@
*/
package org.thingsboard.server.transport.coap.attributes.request;
import com.github.os72.protobuf.dynamic.DynamicSchema;
import com.google.protobuf.Descriptors;
import com.google.protobuf.DynamicMessage;
import com.google.protobuf.InvalidProtocolBufferException;
import com.squareup.wire.schema.internal.parser.ProtoFileElement;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.californium.core.CoapResponse;
import org.eclipse.californium.core.coap.CoAP;
import org.eclipse.californium.core.coap.MediaTypeRegistry;
import org.junit.Before;
import org.junit.Test;
import org.thingsboard.server.common.data.CoapDeviceType;
import org.thingsboard.server.common.data.DeviceProfileProvisionType;
import org.thingsboard.server.common.data.TransportPayloadType;
import org.thingsboard.server.common.data.device.profile.CoapDeviceProfileTransportConfiguration;
import org.thingsboard.server.common.data.device.profile.CoapDeviceTypeConfiguration;
import org.thingsboard.server.common.data.device.profile.DefaultCoapDeviceTypeConfiguration;
import org.thingsboard.server.common.data.device.profile.DeviceProfileTransportConfiguration;
import org.thingsboard.server.common.data.device.profile.ProtoTransportPayloadConfiguration;
import org.thingsboard.server.common.data.device.profile.TransportPayloadTypeConfiguration;
import org.thingsboard.server.common.msg.session.FeatureType;
import org.thingsboard.server.dao.service.DaoSqlTest;
import org.thingsboard.server.gen.transport.TransportProtos;
import org.thingsboard.server.transport.coap.CoapTestConfigProperties;
import java.util.List;
import java.util.stream.Collectors;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@Slf4j
@DaoSqlTest
public class CoapAttributesRequestProtoIntegrationTest extends CoapAttributesRequestIntegrationTest {
public static final String ATTRIBUTES_SCHEMA_STR = "syntax =\"proto3\";\n" +
"\n" +
"package test;\n" +
"\n" +
"message PostAttributes {\n" +
" string attribute1 = 1;\n" +
" bool attribute2 = 2;\n" +
" double attribute3 = 3;\n" +
" int32 attribute4 = 4;\n" +
" JsonObject attribute5 = 5;\n" +
"\n" +
" message JsonObject {\n" +
" int32 someNumber = 6;\n" +
" repeated int32 someArray = 7;\n" +
" NestedJsonObject someNestedObject = 8;\n" +
" message NestedJsonObject {\n" +
" string key = 9;\n" +
" }\n" +
" }\n" +
"}";
@Before
@Override
public void beforeTest() throws Exception {
@ -89,72 +43,4 @@ public class CoapAttributesRequestProtoIntegrationTest extends CoapAttributesReq
public void testRequestAttributesValuesFromTheServer() throws Exception {
processProtoTestRequestAttributesValuesFromTheServer();
}
protected void postAttributes() throws Exception {
doPostAsync("/api/plugins/telemetry/DEVICE/" + savedDevice.getId().getId() + "/attributes/SHARED_SCOPE", POST_ATTRIBUTES_PAYLOAD, String.class, status().isOk());
DeviceProfileTransportConfiguration transportConfiguration = deviceProfile.getProfileData().getTransportConfiguration();
assertTrue(transportConfiguration instanceof CoapDeviceProfileTransportConfiguration);
CoapDeviceProfileTransportConfiguration coapTransportConfiguration = (CoapDeviceProfileTransportConfiguration) transportConfiguration;
CoapDeviceTypeConfiguration coapDeviceTypeConfiguration = coapTransportConfiguration.getCoapDeviceTypeConfiguration();
assertTrue(coapDeviceTypeConfiguration instanceof DefaultCoapDeviceTypeConfiguration);
DefaultCoapDeviceTypeConfiguration defaultCoapDeviceTypeConfiguration = (DefaultCoapDeviceTypeConfiguration) coapDeviceTypeConfiguration;
TransportPayloadTypeConfiguration transportPayloadTypeConfiguration = defaultCoapDeviceTypeConfiguration.getTransportPayloadTypeConfiguration();
assertTrue(transportPayloadTypeConfiguration instanceof ProtoTransportPayloadConfiguration);
ProtoTransportPayloadConfiguration protoTransportPayloadConfiguration = (ProtoTransportPayloadConfiguration) transportPayloadTypeConfiguration;
ProtoFileElement transportProtoSchema = protoTransportPayloadConfiguration.getTransportProtoSchema(ATTRIBUTES_SCHEMA_STR);
DynamicSchema attributesSchema = protoTransportPayloadConfiguration.getDynamicSchema(transportProtoSchema, ProtoTransportPayloadConfiguration.ATTRIBUTES_PROTO_SCHEMA);
DynamicMessage.Builder nestedJsonObjectBuilder = attributesSchema.newMessageBuilder("PostAttributes.JsonObject.NestedJsonObject");
Descriptors.Descriptor nestedJsonObjectBuilderDescriptor = nestedJsonObjectBuilder.getDescriptorForType();
assertNotNull(nestedJsonObjectBuilderDescriptor);
DynamicMessage nestedJsonObject = nestedJsonObjectBuilder.setField(nestedJsonObjectBuilderDescriptor.findFieldByName("key"), "value").build();
DynamicMessage.Builder jsonObjectBuilder = attributesSchema.newMessageBuilder("PostAttributes.JsonObject");
Descriptors.Descriptor jsonObjectBuilderDescriptor = jsonObjectBuilder.getDescriptorForType();
assertNotNull(jsonObjectBuilderDescriptor);
DynamicMessage jsonObject = jsonObjectBuilder
.setField(jsonObjectBuilderDescriptor.findFieldByName("someNumber"), 42)
.addRepeatedField(jsonObjectBuilderDescriptor.findFieldByName("someArray"), 1)
.addRepeatedField(jsonObjectBuilderDescriptor.findFieldByName("someArray"), 2)
.addRepeatedField(jsonObjectBuilderDescriptor.findFieldByName("someArray"), 3)
.setField(jsonObjectBuilderDescriptor.findFieldByName("someNestedObject"), nestedJsonObject)
.build();
DynamicMessage.Builder postAttributesBuilder = attributesSchema.newMessageBuilder("PostAttributes");
Descriptors.Descriptor postAttributesMsgDescriptor = postAttributesBuilder.getDescriptorForType();
assertNotNull(postAttributesMsgDescriptor);
DynamicMessage postAttributesMsg = postAttributesBuilder
.setField(postAttributesMsgDescriptor.findFieldByName("attribute1"), "value1")
.setField(postAttributesMsgDescriptor.findFieldByName("attribute2"), true)
.setField(postAttributesMsgDescriptor.findFieldByName("attribute3"), 42.0)
.setField(postAttributesMsgDescriptor.findFieldByName("attribute4"), 73)
.setField(postAttributesMsgDescriptor.findFieldByName("attribute5"), jsonObject)
.build();
byte[] payload = postAttributesMsg.toByteArray();
client = getCoapClient(FeatureType.ATTRIBUTES);
CoapResponse coapResponse = client.setTimeout(CLIENT_REQUEST_TIMEOUT).post(payload, MediaTypeRegistry.APPLICATION_JSON);
assertEquals(CoAP.ResponseCode.CREATED, coapResponse.getCode());
}
protected void validateJsonResponse(CoapResponse getAttributesResponse) throws InvalidProtocolBufferException {
// TransportProtos.GetAttributeResponseMsg expectedAttributesResponse = getExpectedAttributeResponseMsg();
// TransportProtos.GetAttributeResponseMsg actualAttributesResponse = TransportProtos.GetAttributeResponseMsg.parseFrom(getAttributesResponse.getPayload());
// assertEquals(expectedAttributesResponse.getRequestId(), actualAttributesResponse.getRequestId());
// List<TransportProtos.KeyValueProto> expectedClientKeyValueProtos = expectedAttributesResponse.getClientAttributeListList().stream().map(TransportProtos.TsKvProto::getKv).collect(Collectors.toList());
// List<TransportProtos.KeyValueProto> expectedSharedKeyValueProtos = expectedAttributesResponse.getSharedAttributeListList().stream().map(TransportProtos.TsKvProto::getKv).collect(Collectors.toList());
// List<TransportProtos.KeyValueProto> actualClientKeyValueProtos = actualAttributesResponse.getClientAttributeListList().stream().map(TransportProtos.TsKvProto::getKv).collect(Collectors.toList());
// List<TransportProtos.KeyValueProto> actualSharedKeyValueProtos = actualAttributesResponse.getSharedAttributeListList().stream().map(TransportProtos.TsKvProto::getKv).collect(Collectors.toList());
// assertTrue(actualClientKeyValueProtos.containsAll(expectedClientKeyValueProtos));
// assertTrue(actualSharedKeyValueProtos.containsAll(expectedSharedKeyValueProtos));
}
private TransportProtos.GetAttributeResponseMsg getExpectedAttributeResponseMsg() {
TransportProtos.GetAttributeResponseMsg.Builder result = TransportProtos.GetAttributeResponseMsg.newBuilder();
//List<TransportProtos.TsKvProto> tsKvProtoList = getTsKvProtoList();
//result.addAllClientAttributeList(tsKvProtoList);
//result.addAllSharedAttributeList(tsKvProtoList);
result.setRequestId(0);
return result.build();
}
}

170
application/src/test/java/org/thingsboard/server/transport/coap/attributes/updates/CoapAttributesUpdatesIntegrationTest.java

@ -15,61 +15,20 @@
*/
package org.thingsboard.server.transport.coap.attributes.updates;
import com.google.protobuf.InvalidProtocolBufferException;
import lombok.extern.slf4j.Slf4j;
import org.awaitility.Awaitility;
import org.eclipse.californium.core.CoapHandler;
import org.eclipse.californium.core.CoapObserveRelation;
import org.eclipse.californium.core.CoapResponse;
import org.eclipse.californium.core.coap.CoAP;
import org.eclipse.californium.core.coap.Request;
import org.eclipse.californium.core.server.resources.Resource;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.server.coapserver.DefaultCoapServerService;
import org.thingsboard.server.common.msg.session.FeatureType;
import org.thingsboard.server.common.transport.service.DefaultTransportService;
import org.thingsboard.server.dao.service.DaoSqlTest;
import org.thingsboard.server.transport.coap.CoapTestConfigProperties;
import org.thingsboard.server.transport.coap.CoapTransportResource;
import org.thingsboard.server.transport.coap.attributes.AbstractCoapAttributesIntegrationTest;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.spy;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@Slf4j
@DaoSqlTest
public class CoapAttributesUpdatesIntegrationTest extends AbstractCoapAttributesIntegrationTest {
private static final String RESPONSE_ATTRIBUTES_PAYLOAD_DELETED = "{\"deleted\":[\"attribute5\"]}";
protected static final String POST_ATTRIBUTES_PAYLOAD_ON_CURRENT_STATE_NOTIFICATION = "{\"attribute1\":\"value\",\"attribute2\":false,\"attribute3\":41.0,\"attribute4\":72," +
"\"attribute5\":{\"someNumber\":41,\"someArray\":[],\"someNestedObject\":{\"key\":\"value\"}}}";
CoapTransportResource coapTransportResource;
@Autowired
DefaultCoapServerService defaultCoapServerService;
@Autowired
DefaultTransportService defaultTransportService;
@Before
public void beforeTest() throws Exception {
Resource api = defaultCoapServerService.getCoapServer().getRoot().getChild("api");
coapTransportResource = spy( (CoapTransportResource) api.getChild("v1") );
api.delete(api.getChild("v1") );
api.add(coapTransportResource);
CoapTestConfigProperties configProperties = CoapTestConfigProperties.builder()
.deviceName("Test Subscribe to attribute updates")
.build();
@ -83,136 +42,11 @@ public class CoapAttributesUpdatesIntegrationTest extends AbstractCoapAttributes
@Test
public void testSubscribeToAttributesUpdatesFromTheServer() throws Exception {
processTestSubscribeToAttributesUpdates(false);
processJsonTestSubscribeToAttributesUpdates(false);
}
@Test
public void testSubscribeToAttributesUpdatesFromTheServerWithEmptyCurrentStateNotification() throws Exception {
processTestSubscribeToAttributesUpdates(true);
}
protected void processTestSubscribeToAttributesUpdates(boolean emptyCurrentStateNotification) throws Exception {
if (!emptyCurrentStateNotification) {
doPostAsync("/api/plugins/telemetry/DEVICE/" + savedDevice.getId().getId() + "/attributes/SHARED_SCOPE", POST_ATTRIBUTES_PAYLOAD_ON_CURRENT_STATE_NOTIFICATION, String.class, status().isOk());
}
client = getCoapClient(FeatureType.ATTRIBUTES);
CountDownLatch latch = new CountDownLatch(1);
TestCoapCallback callback = new TestCoapCallback(latch);
Request request = Request.newGet().setObserve();
request.setType(CoAP.Type.CON);
CoapObserveRelation observeRelation = client.observe(request, callback);
latch.await(3, TimeUnit.SECONDS);
if (emptyCurrentStateNotification) {
validateEmptyCurrentStateAttributesResponse(callback);
} else {
validateCurrentStateAttributesResponse(callback);
}
latch = new CountDownLatch(1);
int expectedObserveCnt = callback.getObserve().intValue() + 1;
doPostAsync("/api/plugins/telemetry/DEVICE/" + savedDevice.getId().getId() + "/attributes/SHARED_SCOPE", POST_ATTRIBUTES_PAYLOAD, String.class, status().isOk());
latch.await(3, TimeUnit.SECONDS);
validateUpdateAttributesResponse(callback, expectedObserveCnt);
latch = new CountDownLatch(1);
int expectedObserveBeforeDeleteCnt = callback.getObserve().intValue() + 1;
doDelete("/api/plugins/telemetry/DEVICE/" + savedDevice.getId().getId() + "/SHARED_SCOPE?keys=attribute5", String.class);
latch.await(3, TimeUnit.SECONDS);
validateDeleteAttributesResponse(callback, expectedObserveBeforeDeleteCnt);
observeRelation.proactiveCancel();
assertTrue(observeRelation.isCanceled());
awaitClientAfterCancelObserve();
}
protected void validateCurrentStateAttributesResponse(TestCoapCallback callback) throws InvalidProtocolBufferException {
assertNotNull(callback.getPayloadBytes());
assertNotNull(callback.getObserve());
assertEquals(CoAP.ResponseCode.CONTENT, callback.getResponseCode());
assertEquals(0, callback.getObserve().intValue());
String response = new String(callback.getPayloadBytes(), StandardCharsets.UTF_8);
assertEquals(JacksonUtil.toJsonNode(POST_ATTRIBUTES_PAYLOAD_ON_CURRENT_STATE_NOTIFICATION), JacksonUtil.toJsonNode(response));
}
protected void validateEmptyCurrentStateAttributesResponse(TestCoapCallback callback) throws InvalidProtocolBufferException {
assertNotNull(callback.getPayloadBytes());
assertNotNull(callback.getObserve());
assertEquals(CoAP.ResponseCode.CONTENT, callback.getResponseCode());
assertEquals(0, callback.getObserve().intValue());
String response = new String(callback.getPayloadBytes(), StandardCharsets.UTF_8);
assertEquals("{}", response);
}
protected void validateUpdateAttributesResponse(TestCoapCallback callback, int expectedObserveCnt) throws InvalidProtocolBufferException {
assertNotNull(callback.getPayloadBytes());
assertNotNull(callback.getObserve());
assertEquals(CoAP.ResponseCode.CONTENT, callback.getResponseCode());
assertEquals(expectedObserveCnt, callback.getObserve().intValue());
String response = new String(callback.getPayloadBytes(), StandardCharsets.UTF_8);
assertEquals(JacksonUtil.toJsonNode(POST_ATTRIBUTES_PAYLOAD), JacksonUtil.toJsonNode(response));
}
protected void validateDeleteAttributesResponse(TestCoapCallback callback, int expectedObserveCnt) throws InvalidProtocolBufferException {
assertNotNull(callback.getPayloadBytes());
assertNotNull(callback.getObserve());
assertEquals(CoAP.ResponseCode.CONTENT, callback.getResponseCode());
assertEquals(expectedObserveCnt, callback.getObserve().intValue());
String response = new String(callback.getPayloadBytes(), StandardCharsets.UTF_8);
assertEquals(JacksonUtil.toJsonNode(RESPONSE_ATTRIBUTES_PAYLOAD_DELETED), JacksonUtil.toJsonNode(response));
}
protected static class TestCoapCallback implements CoapHandler {
private final CountDownLatch latch;
private Integer observe;
private byte[] payloadBytes;
private CoAP.ResponseCode responseCode;
public Integer getObserve() {
return observe;
}
public byte[] getPayloadBytes() {
return payloadBytes;
}
public CoAP.ResponseCode getResponseCode() {
return responseCode;
}
private TestCoapCallback(CountDownLatch latch) {
this.latch = latch;
}
@Override
public void onLoad(CoapResponse response) {
observe = response.getOptions().getObserve();
payloadBytes = response.getPayload();
responseCode = response.getCode();
latch.countDown();
}
@Override
public void onError() {
log.warn("Command Response Ack Error, No connect");
}
}
private void awaitClientAfterCancelObserve() {
Awaitility.await("awaitClientAfterCancelObserve")
.pollInterval(10, TimeUnit.MILLISECONDS)
.atMost(5, TimeUnit.SECONDS)
.until(()->{
log.trace("awaiting defaultTransportService.sessions is empty");
return defaultTransportService.sessions.isEmpty();});
processJsonTestSubscribeToAttributesUpdates(true);
}
}

7
application/src/test/java/org/thingsboard/server/transport/coap/attributes/updates/CoapAttributesUpdatesJsonIntegrationTest.java

@ -23,10 +23,11 @@ import org.thingsboard.server.common.data.CoapDeviceType;
import org.thingsboard.server.common.data.TransportPayloadType;
import org.thingsboard.server.dao.service.DaoSqlTest;
import org.thingsboard.server.transport.coap.CoapTestConfigProperties;
import org.thingsboard.server.transport.coap.attributes.AbstractCoapAttributesIntegrationTest;
@Slf4j
@DaoSqlTest
public class CoapAttributesUpdatesJsonIntegrationTest extends CoapAttributesUpdatesIntegrationTest {
public class CoapAttributesUpdatesJsonIntegrationTest extends AbstractCoapAttributesIntegrationTest {
@Before
public void beforeTest() throws Exception {
@ -45,11 +46,11 @@ public class CoapAttributesUpdatesJsonIntegrationTest extends CoapAttributesUpda
@Test
public void testSubscribeToAttributesUpdatesFromTheServer() throws Exception {
super.testSubscribeToAttributesUpdatesFromTheServer();
processJsonTestSubscribeToAttributesUpdates(false);
}
@Test
public void testSubscribeToAttributesUpdatesFromTheServerWithEmptyCurrentStateNotification() throws Exception {
super.testSubscribeToAttributesUpdatesFromTheServerWithEmptyCurrentStateNotification();
processJsonTestSubscribeToAttributesUpdates(true);
}
}

91
application/src/test/java/org/thingsboard/server/transport/coap/attributes/updates/CoapAttributesUpdatesProtoIntegrationTest.java

@ -15,30 +15,19 @@
*/
package org.thingsboard.server.transport.coap.attributes.updates;
import com.google.protobuf.InvalidProtocolBufferException;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.californium.core.coap.CoAP;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.thingsboard.server.common.data.CoapDeviceType;
import org.thingsboard.server.common.data.TransportPayloadType;
import org.thingsboard.server.dao.service.DaoSqlTest;
import org.thingsboard.server.gen.transport.TransportProtos;
import org.thingsboard.server.transport.coap.CoapTestConfigProperties;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertTrue;
import org.thingsboard.server.transport.coap.attributes.AbstractCoapAttributesIntegrationTest;
@Slf4j
@DaoSqlTest
public class CoapAttributesUpdatesProtoIntegrationTest extends CoapAttributesUpdatesIntegrationTest {
public class CoapAttributesUpdatesProtoIntegrationTest extends AbstractCoapAttributesIntegrationTest {
@Before
public void beforeTest() throws Exception {
@ -57,83 +46,11 @@ public class CoapAttributesUpdatesProtoIntegrationTest extends CoapAttributesUpd
@Test
public void testSubscribeToAttributesUpdatesFromTheServer() throws Exception {
processTestSubscribeToAttributesUpdates(false);
processProtoTestSubscribeToAttributesUpdates(false);
}
@Test
public void testSubscribeToAttributesUpdatesFromTheServerWithEmptyCurrentStateNotification() throws Exception {
processTestSubscribeToAttributesUpdates(true);
processProtoTestSubscribeToAttributesUpdates(true);
}
protected void validateCurrentStateAttributesResponse(TestCoapCallback callback) throws InvalidProtocolBufferException {
assertNotNull(callback.getPayloadBytes());
assertNotNull(callback.getObserve());
assertEquals(CoAP.ResponseCode.CONTENT, callback.getResponseCode());
assertEquals(0, callback.getObserve().intValue());
TransportProtos.AttributeUpdateNotificationMsg.Builder expectedCurrentStateNotificationMsgBuilder = TransportProtos.AttributeUpdateNotificationMsg.newBuilder();
TransportProtos.TsKvProto tsKvProtoAttribute1 = getTsKvProto("attribute1", "value", TransportProtos.KeyValueType.STRING_V);
TransportProtos.TsKvProto tsKvProtoAttribute2 = getTsKvProto("attribute2", "false", TransportProtos.KeyValueType.BOOLEAN_V);
TransportProtos.TsKvProto tsKvProtoAttribute3 = getTsKvProto("attribute3", "41.0", TransportProtos.KeyValueType.DOUBLE_V);
TransportProtos.TsKvProto tsKvProtoAttribute4 = getTsKvProto("attribute4", "72", TransportProtos.KeyValueType.LONG_V);
TransportProtos.TsKvProto tsKvProtoAttribute5 = getTsKvProto("attribute5", "{\"someNumber\":41,\"someArray\":[],\"someNestedObject\":{\"key\":\"value\"}}", TransportProtos.KeyValueType.JSON_V);
List<TransportProtos.TsKvProto> tsKvProtoList = new ArrayList<>();
tsKvProtoList.add(tsKvProtoAttribute1);
tsKvProtoList.add(tsKvProtoAttribute2);
tsKvProtoList.add(tsKvProtoAttribute3);
tsKvProtoList.add(tsKvProtoAttribute4);
tsKvProtoList.add(tsKvProtoAttribute5);
TransportProtos.AttributeUpdateNotificationMsg expectedCurrentStateNotificationMsg = expectedCurrentStateNotificationMsgBuilder.addAllSharedUpdated(tsKvProtoList).build();
TransportProtos.AttributeUpdateNotificationMsg actualCurrentStateNotificationMsg = TransportProtos.AttributeUpdateNotificationMsg.parseFrom(callback.getPayloadBytes());
List<TransportProtos.KeyValueProto> expectedSharedUpdatedList = expectedCurrentStateNotificationMsg.getSharedUpdatedList().stream().map(TransportProtos.TsKvProto::getKv).collect(Collectors.toList());
List<TransportProtos.KeyValueProto> actualSharedUpdatedList = actualCurrentStateNotificationMsg.getSharedUpdatedList().stream().map(TransportProtos.TsKvProto::getKv).collect(Collectors.toList());
assertEquals(expectedSharedUpdatedList.size(), actualSharedUpdatedList.size());
assertTrue(actualSharedUpdatedList.containsAll(expectedSharedUpdatedList));
}
protected void validateEmptyCurrentStateAttributesResponse(TestCoapCallback callback) throws InvalidProtocolBufferException {
assertArrayEquals(EMPTY_PAYLOAD, callback.getPayloadBytes());
assertNotNull(callback.getObserve());
assertEquals(CoAP.ResponseCode.CONTENT, callback.getResponseCode());
assertEquals(0, callback.getObserve().intValue());
}
protected void validateUpdateAttributesResponse(TestCoapCallback callback, int expectedObserveCnt) throws InvalidProtocolBufferException {
assertNotNull(callback.getPayloadBytes());
assertNotNull(callback.getObserve());
assertEquals(CoAP.ResponseCode.CONTENT, callback.getResponseCode());
assertEquals(expectedObserveCnt, callback.getObserve().intValue());
TransportProtos.AttributeUpdateNotificationMsg.Builder attributeUpdateNotificationMsgBuilder = TransportProtos.AttributeUpdateNotificationMsg.newBuilder();
List<TransportProtos.TsKvProto> tsKvProtoList = getTsKvProtoList();
attributeUpdateNotificationMsgBuilder.addAllSharedUpdated(tsKvProtoList);
TransportProtos.AttributeUpdateNotificationMsg expectedAttributeUpdateNotificationMsg = attributeUpdateNotificationMsgBuilder.build();
TransportProtos.AttributeUpdateNotificationMsg actualAttributeUpdateNotificationMsg = TransportProtos.AttributeUpdateNotificationMsg.parseFrom(callback.getPayloadBytes());
List<TransportProtos.KeyValueProto> actualSharedUpdatedList = actualAttributeUpdateNotificationMsg.getSharedUpdatedList().stream().map(TransportProtos.TsKvProto::getKv).collect(Collectors.toList());
List<TransportProtos.KeyValueProto> expectedSharedUpdatedList = expectedAttributeUpdateNotificationMsg.getSharedUpdatedList().stream().map(TransportProtos.TsKvProto::getKv).collect(Collectors.toList());
assertEquals(expectedSharedUpdatedList.size(), actualSharedUpdatedList.size());
assertTrue(actualSharedUpdatedList.containsAll(expectedSharedUpdatedList));
}
protected void validateDeleteAttributesResponse(TestCoapCallback callback, int expectedObserveCnt) throws InvalidProtocolBufferException {
assertNotNull(callback.getPayloadBytes());
assertNotNull(callback.getObserve());
assertEquals(CoAP.ResponseCode.CONTENT, callback.getResponseCode());
assertEquals(expectedObserveCnt, callback.getObserve().intValue());
TransportProtos.AttributeUpdateNotificationMsg.Builder attributeUpdateNotificationMsgBuilder = TransportProtos.AttributeUpdateNotificationMsg.newBuilder();
attributeUpdateNotificationMsgBuilder.addSharedDeleted("attribute5");
TransportProtos.AttributeUpdateNotificationMsg expectedAttributeUpdateNotificationMsg = attributeUpdateNotificationMsgBuilder.build();
TransportProtos.AttributeUpdateNotificationMsg actualAttributeUpdateNotificationMsg = TransportProtos.AttributeUpdateNotificationMsg.parseFrom(callback.getPayloadBytes());
assertEquals(expectedAttributeUpdateNotificationMsg.getSharedDeletedList().size(), actualAttributeUpdateNotificationMsg.getSharedDeletedList().size());
assertEquals("attribute5", actualAttributeUpdateNotificationMsg.getSharedDeletedList().get(0));
}
}

10
application/src/test/java/org/thingsboard/server/transport/coap/claim/CoapClaimDeviceTest.java

@ -34,6 +34,7 @@ import org.thingsboard.server.dao.device.claim.ClaimResponse;
import org.thingsboard.server.dao.device.claim.ClaimResult;
import org.thingsboard.server.dao.service.DaoSqlTest;
import org.thingsboard.server.transport.coap.AbstractCoapIntegrationTest;
import org.thingsboard.server.transport.coap.CoapTestClient;
import org.thingsboard.server.transport.coap.CoapTestConfigProperties;
import java.io.IOException;
@ -96,7 +97,7 @@ public class CoapClaimDeviceTest extends AbstractCoapIntegrationTest {
protected void processTestClaimingDevice(boolean emptyPayload) throws Exception {
log.warn("[testClaimingDevice] Device: {}, Transport type: {}", savedDevice.getName(), savedDevice.getType());
client = getCoapClient(FeatureType.CLAIM);
CoapTestClient client = new CoapTestClient(accessToken, FeatureType.CLAIM);
byte[] payloadBytes;
byte[] failurePayloadBytes;
if (emptyPayload) {
@ -109,7 +110,7 @@ public class CoapClaimDeviceTest extends AbstractCoapIntegrationTest {
validateClaimResponse(emptyPayload, client, payloadBytes, failurePayloadBytes);
}
protected void validateClaimResponse(boolean emptyPayload, CoapClient client, byte[] payloadBytes, byte[] failurePayloadBytes) throws Exception {
protected void validateClaimResponse(boolean emptyPayload, CoapTestClient client, byte[] payloadBytes, byte[] failurePayloadBytes) throws Exception {
postClaimRequest(client, failurePayloadBytes);
loginUser(customerAdmin.getName(), CUSTOMER_USER_PASSWORD);
@ -143,10 +144,11 @@ public class CoapClaimDeviceTest extends AbstractCoapIntegrationTest {
claimResponse = doPostClaimAsync("/api/customer/device/" + savedDevice.getName() + "/claim", claimRequest, ClaimResponse.class, status().isBadRequest());
assertEquals(claimResponse, ClaimResponse.CLAIMED);
client.disconnect();
}
private void postClaimRequest(CoapClient client, byte[] payload) throws IOException, ConnectorException {
CoapResponse coapResponse = client.setTimeout((long) 60000).post(payload, MediaTypeRegistry.APPLICATION_JSON);
private void postClaimRequest(CoapTestClient client, byte[] payload) throws IOException, ConnectorException {
CoapResponse coapResponse = client.postMethod(payload);
assertEquals(CoAP.ResponseCode.CREATED, coapResponse.getCode());
}

3
application/src/test/java/org/thingsboard/server/transport/coap/claim/CoapClaimProtoDeviceTest.java

@ -24,6 +24,7 @@ import org.thingsboard.server.common.data.TransportPayloadType;
import org.thingsboard.server.common.msg.session.FeatureType;
import org.thingsboard.server.dao.service.DaoSqlTest;
import org.thingsboard.server.gen.transport.TransportApiProtos;
import org.thingsboard.server.transport.coap.CoapTestClient;
import org.thingsboard.server.transport.coap.CoapTestConfigProperties;
@Slf4j
@ -56,7 +57,7 @@ public class CoapClaimProtoDeviceTest extends CoapClaimDeviceTest {
@Override
protected void processTestClaimingDevice(boolean emptyPayload) throws Exception {
client = getCoapClient(FeatureType.CLAIM);
CoapTestClient client = new CoapTestClient(accessToken, FeatureType.CLAIM);
byte[] payloadBytes;
if (emptyPayload) {
TransportApiProtos.ClaimDevice claimDevice = getClaimDevice(0, emptyPayload);

80
application/src/test/java/org/thingsboard/server/transport/coap/provision/CoapProvisionJsonDeviceTest.java

@ -15,16 +15,13 @@
*/
package org.thingsboard.server.transport.coap.provision;
import com.google.gson.JsonObject;
import com.fasterxml.jackson.databind.JsonNode;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.californium.core.CoapClient;
import org.eclipse.californium.core.CoapResponse;
import org.eclipse.californium.core.coap.MediaTypeRegistry;
import org.eclipse.californium.elements.exception.ConnectorException;
import org.junit.After;
import org.junit.Assert;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.server.dao.service.DaoSqlTest;
import org.thingsboard.server.transport.coap.AbstractCoapIntegrationTest;
import org.thingsboard.server.common.data.CoapDeviceType;
@ -34,14 +31,12 @@ import org.thingsboard.server.common.data.TransportPayloadType;
import org.thingsboard.server.common.data.security.DeviceCredentials;
import org.thingsboard.server.common.msg.EncryptionUtil;
import org.thingsboard.server.common.msg.session.FeatureType;
import org.thingsboard.server.common.transport.util.JsonUtils;
import org.thingsboard.server.dao.device.DeviceCredentialsService;
import org.thingsboard.server.dao.device.DeviceService;
import org.thingsboard.server.dao.device.provision.ProvisionResponseStatus;
import org.thingsboard.server.transport.coap.CoapTestClient;
import org.thingsboard.server.transport.coap.CoapTestConfigProperties;
import java.io.IOException;
@Slf4j
@DaoSqlTest
public class CoapProvisionJsonDeviceTest extends AbstractCoapIntegrationTest {
@ -95,10 +90,11 @@ public class CoapProvisionJsonDeviceTest extends AbstractCoapIntegrationTest {
.transportPayloadType(TransportPayloadType.JSON)
.build();
processBeforeTest(configProperties);
byte[] result = createCoapClientAndPublish().getPayload();
JsonObject response = JsonUtils.parse(new String(result)).getAsJsonObject();
Assert.assertEquals("Provision data was not found!", response.get("errorMsg").getAsString());
Assert.assertEquals(ProvisionResponseStatus.NOT_FOUND.name(), response.get("status").getAsString());
JsonNode response = JacksonUtil.fromBytes(createCoapClientAndPublish());
Assert.assertTrue(response.hasNonNull("errorMsg"));
Assert.assertTrue(response.hasNonNull("status"));
Assert.assertEquals("Provision data was not found!", response.get("errorMsg").asText());
Assert.assertEquals(ProvisionResponseStatus.NOT_FOUND.name(), response.get("status").asText());
}
@ -112,8 +108,9 @@ public class CoapProvisionJsonDeviceTest extends AbstractCoapIntegrationTest {
.provisionSecret("testProvisionSecret")
.build();
processBeforeTest(configProperties);
byte[] result = createCoapClientAndPublish().getPayload();
JsonObject response = JsonUtils.parse(new String(result)).getAsJsonObject();
JsonNode response = JacksonUtil.fromBytes(createCoapClientAndPublish());
Assert.assertTrue(response.hasNonNull("credentialsType"));
Assert.assertTrue(response.hasNonNull("status"));
Device createdDevice = deviceService.findDeviceByTenantIdAndName(tenantId, "Test Provision device");
@ -121,8 +118,8 @@ public class CoapProvisionJsonDeviceTest extends AbstractCoapIntegrationTest {
DeviceCredentials deviceCredentials = deviceCredentialsService.findDeviceCredentialsByDeviceId(tenantId, createdDevice.getId());
Assert.assertEquals(deviceCredentials.getCredentialsType().name(), response.get("credentialsType").getAsString());
Assert.assertEquals(ProvisionResponseStatus.SUCCESS.name(), response.get("status").getAsString());
Assert.assertEquals(deviceCredentials.getCredentialsType().name(), response.get("credentialsType").asText());
Assert.assertEquals(ProvisionResponseStatus.SUCCESS.name(), response.get("status").asText());
}
@ -137,8 +134,9 @@ public class CoapProvisionJsonDeviceTest extends AbstractCoapIntegrationTest {
.build();
processBeforeTest(configProperties);
String requestCredentials = ",\"credentialsType\": \"ACCESS_TOKEN\",\"token\": \"test_token\"";
byte[] result = createCoapClientAndPublish(requestCredentials).getPayload();
JsonObject response = JsonUtils.parse(new String(result)).getAsJsonObject();
JsonNode response = JacksonUtil.fromBytes(createCoapClientAndPublish(requestCredentials));
Assert.assertTrue(response.hasNonNull("credentialsType"));
Assert.assertTrue(response.hasNonNull("status"));
Device createdDevice = deviceService.findDeviceByTenantIdAndName(tenantId, "Test Provision device");
@ -146,10 +144,10 @@ public class CoapProvisionJsonDeviceTest extends AbstractCoapIntegrationTest {
DeviceCredentials deviceCredentials = deviceCredentialsService.findDeviceCredentialsByDeviceId(tenantId, createdDevice.getId());
Assert.assertEquals(deviceCredentials.getCredentialsType().name(), response.get("credentialsType").getAsString());
Assert.assertEquals(deviceCredentials.getCredentialsType().name(), response.get("credentialsType").asText());
Assert.assertEquals(deviceCredentials.getCredentialsType().name(), "ACCESS_TOKEN");
Assert.assertEquals(deviceCredentials.getCredentialsId(), "test_token");
Assert.assertEquals(ProvisionResponseStatus.SUCCESS.name(), response.get("status").getAsString());
Assert.assertEquals(ProvisionResponseStatus.SUCCESS.name(), response.get("status").asText());
}
@ -164,8 +162,9 @@ public class CoapProvisionJsonDeviceTest extends AbstractCoapIntegrationTest {
.build();
processBeforeTest(configProperties);
String requestCredentials = ",\"credentialsType\": \"X509_CERTIFICATE\",\"hash\": \"testHash\"";
byte[] result = createCoapClientAndPublish(requestCredentials).getPayload();
JsonObject response = JsonUtils.parse(new String(result)).getAsJsonObject();
JsonNode response = JacksonUtil.fromBytes(createCoapClientAndPublish(requestCredentials));
Assert.assertTrue(response.hasNonNull("credentialsType"));
Assert.assertTrue(response.hasNonNull("status"));
Device createdDevice = deviceService.findDeviceByTenantIdAndName(tenantId, "Test Provision device");
@ -173,7 +172,7 @@ public class CoapProvisionJsonDeviceTest extends AbstractCoapIntegrationTest {
DeviceCredentials deviceCredentials = deviceCredentialsService.findDeviceCredentialsByDeviceId(tenantId, createdDevice.getId());
Assert.assertEquals(deviceCredentials.getCredentialsType().name(), response.get("credentialsType").getAsString());
Assert.assertEquals(deviceCredentials.getCredentialsType().name(), response.get("credentialsType").asText());
Assert.assertEquals(deviceCredentials.getCredentialsType().name(), "X509_CERTIFICATE");
String cert = EncryptionUtil.certTrimNewLines(deviceCredentials.getCredentialsValue());
@ -182,7 +181,7 @@ public class CoapProvisionJsonDeviceTest extends AbstractCoapIntegrationTest {
Assert.assertEquals(deviceCredentials.getCredentialsId(), sha3Hash);
Assert.assertEquals(deviceCredentials.getCredentialsValue(), "testHash");
Assert.assertEquals(ProvisionResponseStatus.SUCCESS.name(), response.get("status").getAsString());
Assert.assertEquals(ProvisionResponseStatus.SUCCESS.name(), response.get("status").asText());
}
private void processTestProvisioningCheckPreProvisionedDevice() throws Exception {
@ -195,13 +194,14 @@ public class CoapProvisionJsonDeviceTest extends AbstractCoapIntegrationTest {
.provisionSecret("testProvisionSecret")
.build();
processBeforeTest(configProperties);
byte[] result = createCoapClientAndPublish().getPayload();
JsonObject response = JsonUtils.parse(new String(result)).getAsJsonObject();
JsonNode response = JacksonUtil.fromBytes(createCoapClientAndPublish());
Assert.assertTrue(response.hasNonNull("credentialsType"));
Assert.assertTrue(response.hasNonNull("status"));
DeviceCredentials deviceCredentials = deviceCredentialsService.findDeviceCredentialsByDeviceId(tenantId, savedDevice.getId());
Assert.assertEquals(deviceCredentials.getCredentialsType().name(), response.get("credentialsType").getAsString());
Assert.assertEquals(ProvisionResponseStatus.SUCCESS.name(), response.get("status").getAsString());
Assert.assertEquals(deviceCredentials.getCredentialsType().name(), response.get("credentialsType").asText());
Assert.assertEquals(ProvisionResponseStatus.SUCCESS.name(), response.get("status").asText());
}
private void processTestProvisioningWithBadKeyDevice() throws Exception {
@ -214,25 +214,23 @@ public class CoapProvisionJsonDeviceTest extends AbstractCoapIntegrationTest {
.provisionSecret("testProvisionSecret")
.build();
processBeforeTest(configProperties);
byte[] result = createCoapClientAndPublish().getPayload();
JsonObject response = JsonUtils.parse(new String(result)).getAsJsonObject();
Assert.assertEquals("Provision data was not found!", response.get("errorMsg").getAsString());
Assert.assertEquals(ProvisionResponseStatus.NOT_FOUND.name(), response.get("status").getAsString());
JsonNode response = JacksonUtil.fromBytes(createCoapClientAndPublish());
Assert.assertTrue(response.hasNonNull("errorMsg"));
Assert.assertTrue(response.hasNonNull("status"));
Assert.assertEquals("Provision data was not found!", response.get("errorMsg").asText());
Assert.assertEquals(ProvisionResponseStatus.NOT_FOUND.name(), response.get("status").asText());
}
private CoapResponse createCoapClientAndPublish() throws Exception {
private byte[] createCoapClientAndPublish() throws Exception {
return createCoapClientAndPublish("");
}
private CoapResponse createCoapClientAndPublish(String deviceCredentials) throws Exception {
private byte[] createCoapClientAndPublish(String deviceCredentials) throws Exception {
String provisionRequestMsg = createTestProvisionMessage(deviceCredentials);
client = getCoapClient(FeatureType.PROVISION);
return postProvision(client, provisionRequestMsg.getBytes());
}
private CoapResponse postProvision(CoapClient client, byte[] payload) throws IOException, ConnectorException {
return client.setTimeout((long) 60000).post(payload, MediaTypeRegistry.APPLICATION_JSON);
CoapTestClient client = new CoapTestClient(accessToken, FeatureType.PROVISION);
byte[] responseByte = client.postMethod(provisionRequestMsg.getBytes()).getPayload();
client.disconnect();
return responseByte;
}
private String createTestProvisionMessage(String deviceCredentials) {

57
application/src/test/java/org/thingsboard/server/transport/coap/provision/CoapProvisionProtoDeviceTest.java

@ -44,6 +44,7 @@ import org.thingsboard.server.gen.transport.TransportProtos.ProvisionDeviceReque
import org.thingsboard.server.gen.transport.TransportProtos.ProvisionDeviceResponseMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceTokenRequestMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceX509CertRequestMsg;
import org.thingsboard.server.transport.coap.CoapTestClient;
import org.thingsboard.server.transport.coap.CoapTestConfigProperties;
import java.io.IOException;
@ -101,9 +102,9 @@ public class CoapProvisionProtoDeviceTest extends AbstractCoapIntegrationTest {
.transportPayloadType(TransportPayloadType.PROTOBUF)
.build();
processBeforeTest(configProperties);
ProvisionDeviceResponseMsg result = ProvisionDeviceResponseMsg.parseFrom(createCoapClientAndPublish().getPayload());
ProvisionDeviceResponseMsg result = ProvisionDeviceResponseMsg.parseFrom(createCoapClientAndPublish());
Assert.assertNotNull(result);
Assert.assertEquals(ProvisionResponseStatus.NOT_FOUND.name(), result.getStatus().toString());
Assert.assertEquals(ProvisionResponseStatus.NOT_FOUND.name(), result.getStatus().name());
}
private void processTestProvisioningCreateNewDeviceWithoutCredentials() throws Exception {
@ -116,7 +117,7 @@ public class CoapProvisionProtoDeviceTest extends AbstractCoapIntegrationTest {
.provisionSecret("testProvisionSecret")
.build();
processBeforeTest(configProperties);
ProvisionDeviceResponseMsg response = ProvisionDeviceResponseMsg.parseFrom(createCoapClientAndPublish().getPayload());
ProvisionDeviceResponseMsg response = ProvisionDeviceResponseMsg.parseFrom(createCoapClientAndPublish());
Device createdDevice = deviceService.findDeviceByTenantIdAndName(tenantId, "Test Provision device");
@ -124,8 +125,8 @@ public class CoapProvisionProtoDeviceTest extends AbstractCoapIntegrationTest {
DeviceCredentials deviceCredentials = deviceCredentialsService.findDeviceCredentialsByDeviceId(tenantId, createdDevice.getId());
Assert.assertEquals(deviceCredentials.getCredentialsType().name(), response.getCredentialsType().toString());
Assert.assertEquals(ProvisionResponseStatus.SUCCESS.name(), response.getStatus().toString());
Assert.assertEquals(deviceCredentials.getCredentialsType().name(), response.getCredentialsType().name());
Assert.assertEquals(ProvisionResponseStatus.SUCCESS.name(), response.getStatus().name());
}
private void processTestProvisioningCreateNewDeviceWithAccessToken() throws Exception {
@ -138,9 +139,12 @@ public class CoapProvisionProtoDeviceTest extends AbstractCoapIntegrationTest {
.provisionSecret("testProvisionSecret")
.build();
processBeforeTest(configProperties);
CredentialsDataProto requestCredentials = CredentialsDataProto.newBuilder().setValidateDeviceTokenRequestMsg(ValidateDeviceTokenRequestMsg.newBuilder().setToken("test_token").build()).build();
CredentialsDataProto requestCredentials = CredentialsDataProto.newBuilder()
.setValidateDeviceTokenRequestMsg(ValidateDeviceTokenRequestMsg.newBuilder().setToken("test_token").build())
.build();
ProvisionDeviceResponseMsg response = ProvisionDeviceResponseMsg.parseFrom(createCoapClientAndPublish(createTestsProvisionMessage(CredentialsType.ACCESS_TOKEN, requestCredentials)).getPayload());
ProvisionDeviceResponseMsg response = ProvisionDeviceResponseMsg.parseFrom(
createCoapClientAndPublish(createTestsProvisionMessage(CredentialsType.ACCESS_TOKEN, requestCredentials)));
Device createdDevice = deviceService.findDeviceByTenantIdAndName(tenantId, "Test Provision device");
@ -164,9 +168,13 @@ public class CoapProvisionProtoDeviceTest extends AbstractCoapIntegrationTest {
.provisionSecret("testProvisionSecret")
.build();
processBeforeTest(configProperties);
CredentialsDataProto requestCredentials = CredentialsDataProto.newBuilder().setValidateDeviceX509CertRequestMsg(ValidateDeviceX509CertRequestMsg.newBuilder().setHash("testHash").build()).build();
CredentialsDataProto requestCredentials = CredentialsDataProto.newBuilder()
.setValidateDeviceX509CertRequestMsg(
ValidateDeviceX509CertRequestMsg.newBuilder().setHash("testHash").build())
.build();
ProvisionDeviceResponseMsg response = ProvisionDeviceResponseMsg.parseFrom(createCoapClientAndPublish(createTestsProvisionMessage(CredentialsType.X509_CERTIFICATE, requestCredentials)).getPayload());
ProvisionDeviceResponseMsg response = ProvisionDeviceResponseMsg.parseFrom(
createCoapClientAndPublish(createTestsProvisionMessage(CredentialsType.X509_CERTIFICATE, requestCredentials)));
Device createdDevice = deviceService.findDeviceByTenantIdAndName(tenantId, "Test Provision device");
@ -196,12 +204,12 @@ public class CoapProvisionProtoDeviceTest extends AbstractCoapIntegrationTest {
.provisionSecret("testProvisionSecret")
.build();
processBeforeTest(configProperties);
ProvisionDeviceResponseMsg response = ProvisionDeviceResponseMsg.parseFrom(createCoapClientAndPublish().getPayload());
ProvisionDeviceResponseMsg response = ProvisionDeviceResponseMsg.parseFrom(createCoapClientAndPublish());
DeviceCredentials deviceCredentials = deviceCredentialsService.findDeviceCredentialsByDeviceId(tenantId, savedDevice.getId());
Assert.assertEquals(deviceCredentials.getCredentialsType().name(), response.getCredentialsType().toString());
Assert.assertEquals(ProvisionResponseStatus.SUCCESS.name(), response.getStatus().toString());
Assert.assertEquals(deviceCredentials.getCredentialsType().name(), response.getCredentialsType().name());
Assert.assertEquals(ProvisionResponseStatus.SUCCESS.name(), response.getStatus().name());
}
private void processTestProvisioningWithBadKeyDevice() throws Exception {
@ -214,24 +222,20 @@ public class CoapProvisionProtoDeviceTest extends AbstractCoapIntegrationTest {
.provisionSecret("testProvisionSecret")
.build();
processBeforeTest(configProperties);
ProvisionDeviceResponseMsg response = ProvisionDeviceResponseMsg.parseFrom(createCoapClientAndPublish().getPayload());
Assert.assertEquals(ProvisionResponseStatus.NOT_FOUND.name(), response.getStatus().toString());
ProvisionDeviceResponseMsg response = ProvisionDeviceResponseMsg.parseFrom(createCoapClientAndPublish());
Assert.assertEquals(ProvisionResponseStatus.NOT_FOUND.name(), response.getStatus().name());
}
private CoapResponse createCoapClientAndPublish() throws Exception {
byte[] provisionRequestMsg = createTestProvisionMessage();
CoapResponse coapResponse = createCoapClientAndPublish(provisionRequestMsg);
Assert.assertNotNull("COAP response", coapResponse);
return coapResponse;
}
private CoapResponse createCoapClientAndPublish(byte[] provisionRequestMsg) throws Exception {
client = getCoapClient(FeatureType.PROVISION);
return postProvision(client, provisionRequestMsg);
private byte[] createCoapClientAndPublish() throws Exception {
return createCoapClientAndPublish(createTestProvisionMessage());
}
private CoapResponse postProvision(CoapClient client, byte[] payload) throws IOException, ConnectorException {
return client.setTimeout((long) 60000).post(payload, MediaTypeRegistry.APPLICATION_JSON);
private byte[] createCoapClientAndPublish(byte[] provisionRequestMsg) throws Exception {
CoapTestClient client = new CoapTestClient(accessToken, FeatureType.PROVISION);
CoapResponse coapResponse = client.postMethod(provisionRequestMsg);
Assert.assertNotNull("COAP response", coapResponse);
client.disconnect();
return coapResponse.getPayload();
}
private byte[] createTestsProvisionMessage(CredentialsType credentialsType, CredentialsDataProto credentialsData) throws Exception {
@ -247,7 +251,6 @@ public class CoapProvisionProtoDeviceTest extends AbstractCoapIntegrationTest {
.toByteArray();
}
private byte[] createTestProvisionMessage() throws Exception {
return createTestsProvisionMessage(null, null);
}

216
application/src/test/java/org/thingsboard/server/transport/coap/rpc/AbstractCoapServerSideRpcIntegrationTest.java

@ -16,18 +16,29 @@
package org.thingsboard.server.transport.coap.rpc;
import com.fasterxml.jackson.databind.JsonNode;
import com.github.os72.protobuf.dynamic.DynamicSchema;
import com.google.protobuf.Descriptors;
import com.google.protobuf.DynamicMessage;
import com.google.protobuf.InvalidProtocolBufferException;
import com.squareup.wire.schema.internal.parser.ProtoFileElement;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.eclipse.californium.core.CoapClient;
import org.eclipse.californium.core.CoapHandler;
import org.eclipse.californium.core.CoapObserveRelation;
import org.eclipse.californium.core.CoapResponse;
import org.eclipse.californium.core.coap.CoAP;
import org.eclipse.californium.core.coap.MediaTypeRegistry;
import org.eclipse.californium.core.coap.Request;
import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.server.common.data.device.profile.CoapDeviceProfileTransportConfiguration;
import org.thingsboard.server.common.data.device.profile.CoapDeviceTypeConfiguration;
import org.thingsboard.server.common.data.device.profile.DefaultCoapDeviceTypeConfiguration;
import org.thingsboard.server.common.data.device.profile.DeviceProfileTransportConfiguration;
import org.thingsboard.server.common.data.device.profile.ProtoTransportPayloadConfiguration;
import org.thingsboard.server.common.data.device.profile.TransportPayloadTypeConfiguration;
import org.thingsboard.server.common.msg.session.FeatureType;
import org.thingsboard.server.transport.coap.AbstractCoapIntegrationTest;
import org.thingsboard.server.transport.coap.CoapTestCallback;
import org.thingsboard.server.transport.coap.CoapTestClient;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@ -41,76 +52,76 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
@Slf4j
public abstract class AbstractCoapServerSideRpcIntegrationTest extends AbstractCoapIntegrationTest {
public static final String RPC_REQUEST_PROTO_SCHEMA = "syntax =\"proto3\";\n" +
"package rpc;\n" +
"\n" +
"message RpcRequestMsg {\n" +
" optional string method = 1;\n" +
" optional int32 requestId = 2;\n" +
" Params params = 3;\n" +
"\n" +
" message Params {\n" +
" optional string pin = 1;\n" +
" optional int32 value = 2;\n" +
" }\n" +
"}";
protected static final String DEVICE_RESPONSE = "{\"value1\":\"A\",\"value2\":\"B\"}";
protected static final Long asyncContextTimeoutToUseRpcPlugin = 10000L;
protected void processOneWayRpcTest() throws Exception {
client = getCoapClient(FeatureType.RPC);
client.useCONs();
CountDownLatch latch = new CountDownLatch(1);
TestCoapCallback callback = new TestCoapCallback(client, latch, true);
protected void processOneWayRpcTest(boolean protobuf) throws Exception {
CoapTestClient client = new CoapTestClient(accessToken, FeatureType.RPC);
CoapTestCallback callbackCoap = new TestCoapCallbackForRPC(client, 1, true, protobuf);
Request request = Request.newGet().setObserve();
CoapObserveRelation observeRelation = client.observe(request, callback);
latch.await(3, TimeUnit.SECONDS);
validateCurrentStateNotification(callback);
latch = new CountDownLatch(1);
CoapObserveRelation observeRelation = client.getObserveRelation(callbackCoap);
callbackCoap.getLatch().await(3, TimeUnit.SECONDS);
validateCurrentStateNotification(callbackCoap);
CountDownLatch latch = new CountDownLatch(1);
String setGpioRequest = "{\"method\":\"setGpio\",\"params\":{\"pin\": \"23\",\"value\": 1}}";
String deviceId = savedDevice.getId().getId().toString();
String result = doPostAsync("/api/rpc/oneway/" + deviceId, setGpioRequest, String.class, status().isOk());
latch.await(3, TimeUnit.SECONDS);
validateOneWayStateChangedNotification(callback, result);
validateOneWayStateChangedNotification(callbackCoap, result);
observeRelation.proactiveCancel();
assertTrue(observeRelation.isCanceled());
client.disconnect();
}
protected void processTwoWayRpcTest(String expectedResponseResult) throws Exception {
client = getCoapClient(FeatureType.RPC);
client.useCONs();
CountDownLatch latch = new CountDownLatch(1);
TestCoapCallback callback = new TestCoapCallback(client, latch, false);
protected void processTwoWayRpcTest(String expectedResponseResult, boolean protobuf) throws Exception {
CoapTestClient client = new CoapTestClient(accessToken, FeatureType.RPC);
CoapTestCallback callbackCoap = new TestCoapCallbackForRPC(client, 1, false, protobuf);
Request request = Request.newGet().setObserve();
request.setType(CoAP.Type.CON);
CoapObserveRelation observeRelation = client.observe(request, callback);
latch.await(3, TimeUnit.SECONDS);
CoapObserveRelation observeRelation = client.getObserveRelation(callbackCoap);
callbackCoap.getLatch().await(3, TimeUnit.SECONDS);
validateCurrentStateNotification(callback);
validateCurrentStateNotification(callbackCoap);
String setGpioRequest = "{\"method\":\"setGpio\",\"params\":{\"pin\": \"26\",\"value\": 1}}";
String deviceId = savedDevice.getId().getId().toString();
String actualResult = doPostAsync("/api/rpc/twoway/" + deviceId, setGpioRequest, String.class, status().isOk());
latch.await(3, TimeUnit.SECONDS);
validateTwoWayStateChangedNotification(callback, 1, expectedResponseResult, actualResult);
callbackCoap.getLatch().await(3, TimeUnit.SECONDS);
latch = new CountDownLatch(1);
validateTwoWayStateChangedNotification(callbackCoap, 1, expectedResponseResult, actualResult);
CountDownLatch latch = new CountDownLatch(1);
actualResult = doPostAsync("/api/rpc/twoway/" + deviceId, setGpioRequest, String.class, status().isOk());
latch.await(3, TimeUnit.SECONDS);
callbackCoap.getLatch().await(3, TimeUnit.SECONDS);
validateTwoWayStateChangedNotification(callback, 2, expectedResponseResult, actualResult);
validateTwoWayStateChangedNotification(callbackCoap, 2, expectedResponseResult, actualResult);
observeRelation.proactiveCancel();
assertTrue(observeRelation.isCanceled());
client.disconnect();
}
protected void processOnLoadResponse(CoapResponse response, CoapClient client, Integer observe, CountDownLatch latch) {
protected void processOnLoadResponse(CoapResponse response, CoapTestClient client, Integer observe, CountDownLatch latch) {
JsonNode responseJson = JacksonUtil.fromBytes(response.getPayload());
client.setURI(getRpcResponseFeatureTokenUrl(accessToken, responseJson.get("id").asInt()));
client.post(new CoapHandler() {
client.setURI(CoapTestClient.getFeatureTokenUrl(accessToken, FeatureType.RPC, responseJson.get("id").asInt()));
client.postMethod(new CoapHandler() {
@Override
public void onLoad(CoapResponse response) {
log.warn("Command Response Ack: {}, {}", response.getCode(), response.getResponseText());
@ -124,36 +135,89 @@ public abstract class AbstractCoapServerSideRpcIntegrationTest extends AbstractC
}, DEVICE_RESPONSE, MediaTypeRegistry.APPLICATION_JSON);
}
protected String getRpcResponseFeatureTokenUrl(String token, int requestId) {
return COAP_BASE_URL + token + "/" + FeatureType.RPC.name().toLowerCase() + "/" + requestId;
protected void processOnLoadProtoResponse(CoapResponse response, CoapTestClient client, Integer observe, CountDownLatch latch) {
ProtoTransportPayloadConfiguration protoTransportPayloadConfiguration = getProtoTransportPayloadConfiguration();
ProtoFileElement rpcRequestProtoSchemaFile = protoTransportPayloadConfiguration.getTransportProtoSchema(RPC_REQUEST_PROTO_SCHEMA);
DynamicSchema rpcRequestProtoSchema = protoTransportPayloadConfiguration.getDynamicSchema(rpcRequestProtoSchemaFile, ProtoTransportPayloadConfiguration.RPC_REQUEST_PROTO_SCHEMA);
byte[] requestPayload = response.getPayload();
DynamicMessage.Builder rpcRequestMsg = rpcRequestProtoSchema.newMessageBuilder("RpcRequestMsg");
Descriptors.Descriptor rpcRequestMsgDescriptor = rpcRequestMsg.getDescriptorForType();
try {
DynamicMessage dynamicMessage = DynamicMessage.parseFrom(rpcRequestMsgDescriptor, requestPayload);
Descriptors.FieldDescriptor requestIdDescriptor = rpcRequestMsgDescriptor.findFieldByName("requestId");
int requestId = (int) dynamicMessage.getField(requestIdDescriptor);
ProtoFileElement rpcResponseProtoSchemaFile = protoTransportPayloadConfiguration.getTransportProtoSchema(DEVICE_RPC_RESPONSE_PROTO_SCHEMA);
DynamicSchema rpcResponseProtoSchema = protoTransportPayloadConfiguration.getDynamicSchema(rpcResponseProtoSchemaFile, ProtoTransportPayloadConfiguration.RPC_RESPONSE_PROTO_SCHEMA);
DynamicMessage.Builder rpcResponseBuilder = rpcResponseProtoSchema.newMessageBuilder("RpcResponseMsg");
Descriptors.Descriptor rpcResponseMsgDescriptor = rpcResponseBuilder.getDescriptorForType();
DynamicMessage rpcResponseMsg = rpcResponseBuilder
.setField(rpcResponseMsgDescriptor.findFieldByName("payload"), DEVICE_RESPONSE)
.build();
client.setURI(CoapTestClient.getFeatureTokenUrl(accessToken, FeatureType.RPC, requestId));
client.postMethod(new CoapHandler() {
@Override
public void onLoad(CoapResponse response) {
log.warn("Command Response Ack: {}", response.getCode());
latch.countDown();
}
@Override
public void onError() {
log.warn("Command Response Ack Error, No connect");
}
}, rpcResponseMsg.toByteArray(), MediaTypeRegistry.APPLICATION_JSON);
} catch (InvalidProtocolBufferException e) {
log.warn("Command Response Ack Error, Invalid response received: ", e);
}
}
protected class TestCoapCallback implements CoapHandler {
private ProtoTransportPayloadConfiguration getProtoTransportPayloadConfiguration() {
DeviceProfileTransportConfiguration transportConfiguration = deviceProfile.getProfileData().getTransportConfiguration();
assertTrue(transportConfiguration instanceof CoapDeviceProfileTransportConfiguration);
CoapDeviceProfileTransportConfiguration coapDeviceProfileTransportConfiguration = (CoapDeviceProfileTransportConfiguration) transportConfiguration;
CoapDeviceTypeConfiguration coapDeviceTypeConfiguration = coapDeviceProfileTransportConfiguration.getCoapDeviceTypeConfiguration();
assertTrue(coapDeviceTypeConfiguration instanceof DefaultCoapDeviceTypeConfiguration);
DefaultCoapDeviceTypeConfiguration defaultCoapDeviceTypeConfiguration = (DefaultCoapDeviceTypeConfiguration) coapDeviceTypeConfiguration;
TransportPayloadTypeConfiguration transportPayloadTypeConfiguration = defaultCoapDeviceTypeConfiguration.getTransportPayloadTypeConfiguration();
assertTrue(transportPayloadTypeConfiguration instanceof ProtoTransportPayloadConfiguration);
return (ProtoTransportPayloadConfiguration) transportPayloadTypeConfiguration;
}
private final CoapClient client;
private final CountDownLatch latch;
private final boolean isOneWayRpc;
private void validateCurrentStateNotification(CoapTestCallback callback) {
assertArrayEquals(EMPTY_PAYLOAD, callback.getPayloadBytes());
assertNotNull(callback.getObserve());
assertEquals(callback.getResponseCode(), CoAP.ResponseCode.VALID);
assertEquals(0, callback.getObserve().intValue());
}
private Integer observe;
private byte[] payloadBytes;
private CoAP.ResponseCode responseCode;
private void validateOneWayStateChangedNotification(CoapTestCallback callback, String result) {
assertTrue(StringUtils.isEmpty(result));
assertNotNull(callback.getPayloadBytes());
assertNotNull(callback.getObserve());
assertEquals(CoAP.ResponseCode.CONTENT, callback.getResponseCode());
assertEquals(1, callback.getObserve().intValue());
}
public Integer getObserve() {
return observe;
}
private void validateTwoWayStateChangedNotification(CoapTestCallback callback, int expectedObserveNumber, String expectedResult, String actualResult) {
assertEquals(expectedResult, actualResult);
assertNotNull(callback.getPayloadBytes());
assertNotNull(callback.getObserve());
assertEquals(CoAP.ResponseCode.CONTENT, callback.getResponseCode());
assertEquals(expectedObserveNumber, callback.getObserve().intValue());
}
public byte[] getPayloadBytes() {
return payloadBytes;
}
protected class TestCoapCallbackForRPC extends CoapTestCallback {
public CoAP.ResponseCode getResponseCode() {
return responseCode;
}
private final CoapTestClient client;
private final boolean isOneWayRpc;
private final boolean protobuf;
TestCoapCallback(CoapClient client, CountDownLatch latch, boolean isOneWayRpc) {
TestCoapCallbackForRPC(CoapTestClient client, int subscribeCount, boolean isOneWayRpc, boolean protobuf) {
super(subscribeCount);
this.client = client;
this.latch = latch;
this.isOneWayRpc = isOneWayRpc;
this.protobuf = protobuf;
}
@Override
@ -163,7 +227,11 @@ public abstract class AbstractCoapServerSideRpcIntegrationTest extends AbstractC
observe = response.getOptions().getObserve();
if (observe != null) {
if (!isOneWayRpc && observe > 0) {
processOnLoadResponse(response, client, observe, latch);
if (!protobuf){
processOnLoadResponse(response, client, observe, latch);
} else {
processOnLoadProtoResponse(response, client, observe, latch);
}
} else {
latch.countDown();
}
@ -174,31 +242,5 @@ public abstract class AbstractCoapServerSideRpcIntegrationTest extends AbstractC
public void onError() {
log.warn("Command Response Ack Error, No connect");
}
}
private void validateCurrentStateNotification(TestCoapCallback callback) {
assertArrayEquals(EMPTY_PAYLOAD, callback.getPayloadBytes());
assertNotNull(callback.getObserve());
assertEquals(callback.getResponseCode(), CoAP.ResponseCode.VALID);
assertEquals(0, callback.getObserve().intValue());
}
private void validateOneWayStateChangedNotification(TestCoapCallback callback, String result) {
assertTrue(StringUtils.isEmpty(result));
assertNotNull(callback.getPayloadBytes());
assertNotNull(callback.getObserve());
assertEquals(CoAP.ResponseCode.CONTENT, callback.getResponseCode());
assertEquals(1, callback.getObserve().intValue());
}
private void validateTwoWayStateChangedNotification(TestCoapCallback callback, int expectedObserveNumber, String expectedResult, String actualResult) {
assertEquals(expectedResult, actualResult);
assertNotNull(callback.getPayloadBytes());
assertNotNull(callback.getObserve());
assertEquals(CoAP.ResponseCode.CONTENT, callback.getResponseCode());
assertEquals(expectedObserveNumber, callback.getObserve().intValue());
}
}

7
application/src/test/java/org/thingsboard/server/transport/coap/rpc/CoapServerSideRpcDefaultIntegrationTest.java

@ -21,9 +21,6 @@ import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.thingsboard.server.common.data.CoapDeviceType;
import org.thingsboard.server.common.data.DeviceProfileProvisionType;
import org.thingsboard.server.common.data.TransportPayloadType;
import org.thingsboard.server.dao.service.DaoSqlTest;
import org.thingsboard.server.service.security.AccessValidator;
import org.thingsboard.server.transport.coap.CoapTestConfigProperties;
@ -87,12 +84,12 @@ public class CoapServerSideRpcDefaultIntegrationTest extends AbstractCoapServerS
@Test
public void testServerCoapOneWayRpc() throws Exception {
processOneWayRpcTest();
processOneWayRpcTest(false);
}
@Test
public void testServerCoapTwoWayRpc() throws Exception {
processTwoWayRpcTest("{\"value1\":\"A\",\"value2\":\"B\"}");
processTwoWayRpcTest("{\"value1\":\"A\",\"value2\":\"B\"}", false);
}
}

4
application/src/test/java/org/thingsboard/server/transport/coap/rpc/CoapServerSideRpcJsonIntegrationTest.java

@ -45,12 +45,12 @@ public class CoapServerSideRpcJsonIntegrationTest extends AbstractCoapServerSide
@Test
public void testServerCoapOneWayRpc() throws Exception {
processOneWayRpcTest();
processOneWayRpcTest(false);
}
@Test
public void testServerCoapTwoWayRpc() throws Exception {
processTwoWayRpcTest("{\"value1\":\"A\",\"value2\":\"B\"}");
processTwoWayRpcTest("{\"value1\":\"A\",\"value2\":\"B\"}", false);
}
}

87
application/src/test/java/org/thingsboard/server/transport/coap/rpc/CoapServerSideRpcProtoIntegrationTest.java

@ -15,52 +15,19 @@
*/
package org.thingsboard.server.transport.coap.rpc;
import com.github.os72.protobuf.dynamic.DynamicSchema;
import com.google.protobuf.Descriptors;
import com.google.protobuf.DynamicMessage;
import com.google.protobuf.InvalidProtocolBufferException;
import com.squareup.wire.schema.internal.parser.ProtoFileElement;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.californium.core.CoapClient;
import org.eclipse.californium.core.CoapHandler;
import org.eclipse.californium.core.CoapResponse;
import org.eclipse.californium.core.coap.MediaTypeRegistry;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.thingsboard.server.common.data.CoapDeviceType;
import org.thingsboard.server.common.data.TransportPayloadType;
import org.thingsboard.server.common.data.device.profile.CoapDeviceProfileTransportConfiguration;
import org.thingsboard.server.common.data.device.profile.CoapDeviceTypeConfiguration;
import org.thingsboard.server.common.data.device.profile.DefaultCoapDeviceTypeConfiguration;
import org.thingsboard.server.common.data.device.profile.DeviceProfileTransportConfiguration;
import org.thingsboard.server.common.data.device.profile.ProtoTransportPayloadConfiguration;
import org.thingsboard.server.common.data.device.profile.TransportPayloadTypeConfiguration;
import org.thingsboard.server.dao.service.DaoSqlTest;
import org.thingsboard.server.transport.coap.CoapTestConfigProperties;
import java.util.concurrent.CountDownLatch;
import static org.junit.Assert.assertTrue;
@Slf4j
@DaoSqlTest
public class CoapServerSideRpcProtoIntegrationTest extends AbstractCoapServerSideRpcIntegrationTest {
private static final String RPC_REQUEST_PROTO_SCHEMA = "syntax =\"proto3\";\n" +
"package rpc;\n" +
"\n" +
"message RpcRequestMsg {\n" +
" optional string method = 1;\n" +
" optional int32 requestId = 2;\n" +
" Params params = 3;\n" +
"\n" +
" message Params {\n" +
" optional string pin = 1;\n" +
" optional int32 value = 2;\n" +
" }\n" +
"}";
@Before
public void beforeTest() throws Exception {
CoapTestConfigProperties configProperties = CoapTestConfigProperties.builder()
@ -79,61 +46,11 @@ public class CoapServerSideRpcProtoIntegrationTest extends AbstractCoapServerSid
@Test
public void testServerCoapOneWayRpc() throws Exception {
processOneWayRpcTest();
processOneWayRpcTest(true);
}
@Test
public void testServerCoapTwoWayRpc() throws Exception {
processTwoWayRpcTest("{\"payload\":\"{\\\"value1\\\":\\\"A\\\",\\\"value2\\\":\\\"B\\\"}\"}");
}
@Override
protected void processOnLoadResponse(CoapResponse response, CoapClient client, Integer observe, CountDownLatch latch) {
ProtoTransportPayloadConfiguration protoTransportPayloadConfiguration = getProtoTransportPayloadConfiguration();
ProtoFileElement rpcRequestProtoSchemaFile = protoTransportPayloadConfiguration.getTransportProtoSchema(RPC_REQUEST_PROTO_SCHEMA);
DynamicSchema rpcRequestProtoSchema = protoTransportPayloadConfiguration.getDynamicSchema(rpcRequestProtoSchemaFile, ProtoTransportPayloadConfiguration.RPC_REQUEST_PROTO_SCHEMA);
byte[] requestPayload = response.getPayload();
DynamicMessage.Builder rpcRequestMsg = rpcRequestProtoSchema.newMessageBuilder("RpcRequestMsg");
Descriptors.Descriptor rpcRequestMsgDescriptor = rpcRequestMsg.getDescriptorForType();
try {
DynamicMessage dynamicMessage = DynamicMessage.parseFrom(rpcRequestMsgDescriptor, requestPayload);
Descriptors.FieldDescriptor requestIdDescriptor = rpcRequestMsgDescriptor.findFieldByName("requestId");
int requestId = (int) dynamicMessage.getField(requestIdDescriptor);
ProtoFileElement rpcResponseProtoSchemaFile = protoTransportPayloadConfiguration.getTransportProtoSchema(DEVICE_RPC_RESPONSE_PROTO_SCHEMA);
DynamicSchema rpcResponseProtoSchema = protoTransportPayloadConfiguration.getDynamicSchema(rpcResponseProtoSchemaFile, ProtoTransportPayloadConfiguration.RPC_RESPONSE_PROTO_SCHEMA);
DynamicMessage.Builder rpcResponseBuilder = rpcResponseProtoSchema.newMessageBuilder("RpcResponseMsg");
Descriptors.Descriptor rpcResponseMsgDescriptor = rpcResponseBuilder.getDescriptorForType();
DynamicMessage rpcResponseMsg = rpcResponseBuilder
.setField(rpcResponseMsgDescriptor.findFieldByName("payload"), DEVICE_RESPONSE)
.build();
client.setURI(getRpcResponseFeatureTokenUrl(accessToken, requestId));
client.post(new CoapHandler() {
@Override
public void onLoad(CoapResponse response) {
log.warn("Command Response Ack: {}", response.getCode());
latch.countDown();
}
@Override
public void onError() {
log.warn("Command Response Ack Error, No connect");
}
}, rpcResponseMsg.toByteArray(), MediaTypeRegistry.APPLICATION_JSON);
} catch (InvalidProtocolBufferException e) {
log.warn("Command Response Ack Error, Invalid response received: ", e);
}
}
private ProtoTransportPayloadConfiguration getProtoTransportPayloadConfiguration() {
DeviceProfileTransportConfiguration transportConfiguration = deviceProfile.getProfileData().getTransportConfiguration();
assertTrue(transportConfiguration instanceof CoapDeviceProfileTransportConfiguration);
CoapDeviceProfileTransportConfiguration coapDeviceProfileTransportConfiguration = (CoapDeviceProfileTransportConfiguration) transportConfiguration;
CoapDeviceTypeConfiguration coapDeviceTypeConfiguration = coapDeviceProfileTransportConfiguration.getCoapDeviceTypeConfiguration();
assertTrue(coapDeviceTypeConfiguration instanceof DefaultCoapDeviceTypeConfiguration);
DefaultCoapDeviceTypeConfiguration defaultCoapDeviceTypeConfiguration = (DefaultCoapDeviceTypeConfiguration) coapDeviceTypeConfiguration;
TransportPayloadTypeConfiguration transportPayloadTypeConfiguration = defaultCoapDeviceTypeConfiguration.getTransportPayloadTypeConfiguration();
assertTrue(transportPayloadTypeConfiguration instanceof ProtoTransportPayloadConfiguration);
return (ProtoTransportPayloadConfiguration) transportPayloadTypeConfiguration;
processTwoWayRpcTest("{\"payload\":\"{\\\"value1\\\":\\\"A\\\",\\\"value2\\\":\\\"B\\\"}\"}", true);
}
}

50
application/src/test/java/org/thingsboard/server/transport/coap/telemetry/attributes/CoapAttributesIntegrationTest.java

@ -17,11 +17,8 @@ package org.thingsboard.server.transport.coap.telemetry.attributes;
import com.fasterxml.jackson.core.type.TypeReference;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.californium.core.CoapClient;
import org.eclipse.californium.core.CoapResponse;
import org.eclipse.californium.core.coap.CoAP;
import org.eclipse.californium.core.coap.MediaTypeRegistry;
import org.eclipse.californium.elements.exception.ConnectorException;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@ -29,9 +26,9 @@ import org.thingsboard.server.dao.service.DaoSqlTest;
import org.thingsboard.server.transport.coap.AbstractCoapIntegrationTest;
import org.thingsboard.server.common.data.id.DeviceId;
import org.thingsboard.server.common.msg.session.FeatureType;
import org.thingsboard.server.transport.coap.CoapTestClient;
import org.thingsboard.server.transport.coap.CoapTestConfigProperties;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedHashMap;
@ -74,30 +71,17 @@ public class CoapAttributesIntegrationTest extends AbstractCoapIntegrationTest {
}
protected void processAttributesTest(List<String> expectedKeys, byte[] payload, boolean presenceFieldsTest) throws Exception {
client = getCoapClient(FeatureType.ATTRIBUTES);
postAttributes(client, payload);
CoapTestClient client = new CoapTestClient(accessToken, FeatureType.ATTRIBUTES);
CoapResponse coapResponse = client.postMethod(payload);
assertEquals(CoAP.ResponseCode.CREATED, coapResponse.getCode());
DeviceId deviceId = savedDevice.getId();
long start = System.currentTimeMillis();
long end = System.currentTimeMillis() + 5000;
List<String> actualKeys = null;
while (start <= end) {
actualKeys = doGetAsyncTyped("/api/plugins/telemetry/DEVICE/" + deviceId + "/keys/attributes/CLIENT_SCOPE", new TypeReference<>() {});
if (actualKeys.size() == expectedKeys.size()) {
break;
}
Thread.sleep(100);
start += 100;
}
List<String> actualKeys = getActualKeysList(deviceId, expectedKeys);
assertNotNull(actualKeys);
Set<String> actualKeySet = new HashSet<>(actualKeys);
Set<String> expectedKeySet = new HashSet<>(expectedKeys);
assertEquals(expectedKeySet, actualKeySet);
String getAttributesValuesUrl = getAttributesValuesUrl(deviceId, actualKeySet);
@ -111,14 +95,6 @@ public class CoapAttributesIntegrationTest extends AbstractCoapIntegrationTest {
doDelete(deleteAttributesUrl);
}
private void postAttributes(CoapClient client, byte[] payload) throws IOException, ConnectorException {
if (payload == null) {
payload = PAYLOAD_VALUES_STR.getBytes();
}
CoapResponse coapResponse = client.setTimeout((long) 60000).post(payload, MediaTypeRegistry.APPLICATION_JSON);
assertEquals(CoAP.ResponseCode.CREATED, coapResponse.getCode());
}
@SuppressWarnings({"unchecked", "rawtypes"})
protected void assertAttributesValues(List<Map<String, Object>> deviceValues, Set<String> keySet) {
for (Map<String, Object> map : deviceValues) {
@ -171,6 +147,22 @@ public class CoapAttributesIntegrationTest extends AbstractCoapIntegrationTest {
}
}
private List<String> getActualKeysList(DeviceId deviceId, List<String> expectedKeys) throws Exception {
long start = System.currentTimeMillis();
long end = System.currentTimeMillis() + 5000;
List<String> actualKeys = null;
while (start <= end) {
actualKeys = doGetAsyncTyped("/api/plugins/telemetry/DEVICE/" + deviceId + "/keys/attributes/CLIENT_SCOPE", new TypeReference<>() {});
if (actualKeys.size() == expectedKeys.size()) {
break;
}
Thread.sleep(100);
start += 100;
}
return actualKeys;
}
private String getAttributesValuesUrl(DeviceId deviceId, Set<String> actualKeySet) {
return "/api/plugins/telemetry/DEVICE/" + deviceId + "/values/attributes/CLIENT_SCOPE?keys=" + String.join(",", actualKeySet);
}

54
application/src/test/java/org/thingsboard/server/transport/coap/telemetry/timeseries/AbstractCoapTimeseriesIntegrationTest.java

@ -17,19 +17,17 @@ package org.thingsboard.server.transport.coap.telemetry.timeseries;
import com.fasterxml.jackson.core.type.TypeReference;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.californium.core.CoapClient;
import org.eclipse.californium.core.CoapResponse;
import org.eclipse.californium.core.coap.CoAP;
import org.eclipse.californium.core.coap.MediaTypeRegistry;
import org.eclipse.californium.elements.exception.ConnectorException;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.thingsboard.server.common.data.id.DeviceId;
import org.thingsboard.server.common.msg.session.FeatureType;
import org.thingsboard.server.transport.coap.AbstractCoapIntegrationTest;
import org.thingsboard.server.transport.coap.CoapTestClient;
import org.thingsboard.server.transport.coap.CoapTestConfigProperties;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
@ -75,28 +73,16 @@ public abstract class AbstractCoapTimeseriesIntegrationTest extends AbstractCoap
}
protected void processTestPostTelemetry(byte[] payloadBytes, List<String> expectedKeys, boolean withTs, boolean presenceFieldsTest) throws Exception {
client = getCoapClient(FeatureType.TELEMETRY);
postTelemetry(client, payloadBytes);
String deviceId = savedDevice.getId().getId().toString();
long start = System.currentTimeMillis();
long end = System.currentTimeMillis() + 5000;
CoapTestClient client = new CoapTestClient(accessToken, FeatureType.TELEMETRY);
CoapResponse coapResponse = client.postMethod(payloadBytes);
assertEquals(CoAP.ResponseCode.CREATED, coapResponse.getCode());
List<String> actualKeys = null;
while (start <= end) {
actualKeys = doGetAsyncTyped("/api/plugins/telemetry/DEVICE/" + deviceId + "/keys/timeseries", new TypeReference<>() {});
if (actualKeys.size() == expectedKeys.size()) {
break;
}
Thread.sleep(100);
start += 100;
}
DeviceId deviceId = savedDevice.getId();
List<String> actualKeys = getActualKeysList(deviceId, expectedKeys);
assertNotNull(actualKeys);
Set<String> actualKeySet = new HashSet<>(actualKeys);
Set<String> expectedKeySet = new HashSet<>(expectedKeys);
assertEquals(expectedKeySet, actualKeySet);
String getTelemetryValuesUrl;
@ -105,8 +91,8 @@ public abstract class AbstractCoapTimeseriesIntegrationTest extends AbstractCoap
} else {
getTelemetryValuesUrl = "/api/plugins/telemetry/DEVICE/" + deviceId + "/values/timeseries?keys=" + String.join(",", actualKeySet);
}
start = System.currentTimeMillis();
end = System.currentTimeMillis() + 5000;
long start = System.currentTimeMillis();
long end = System.currentTimeMillis() + 5000;
Map<String, List<Map<String, Object>>> values = null;
while (start <= end) {
values = doGetAsyncTyped(getTelemetryValuesUrl, new TypeReference<>() {});
@ -142,11 +128,7 @@ public abstract class AbstractCoapTimeseriesIntegrationTest extends AbstractCoap
} else {
assertValues(values, 0);
}
}
private void postTelemetry(CoapClient client, byte[] payload) throws IOException, ConnectorException {
CoapResponse coapResponse = client.setTimeout((long) 60000).post(payload, MediaTypeRegistry.APPLICATION_JSON);
assertEquals(CoAP.ResponseCode.CREATED, coapResponse.getCode());
client.disconnect();
}
private void assertTs(Map<String, List<Map<String, Object>>> deviceValues, List<String> expectedKeys, int ts, int arrayIndex) {
@ -207,4 +189,20 @@ public abstract class AbstractCoapTimeseriesIntegrationTest extends AbstractCoap
}
}
private List<String> getActualKeysList(DeviceId deviceId, List<String> expectedKeys) throws Exception {
long start = System.currentTimeMillis();
long end = System.currentTimeMillis() + 5000;
List<String> actualKeys = null;
while (start <= end) {
actualKeys = doGetAsyncTyped("/api/plugins/telemetry/DEVICE/" + deviceId + "/keys/timeseries", new TypeReference<>() {});
if (actualKeys.size() == expectedKeys.size()) {
break;
}
Thread.sleep(100);
start += 100;
}
return actualKeys;
}
}

1
application/src/test/java/org/thingsboard/server/transport/coap/telemetry/timeseries/AbstractCoapTimeseriesProtoIntegrationTest.java

@ -23,7 +23,6 @@ import lombok.extern.slf4j.Slf4j;
import org.junit.Before;
import org.junit.Test;
import org.thingsboard.server.common.data.CoapDeviceType;
import org.thingsboard.server.common.data.DeviceProfileProvisionType;
import org.thingsboard.server.common.data.TransportPayloadType;
import org.thingsboard.server.common.data.device.profile.CoapDeviceProfileTransportConfiguration;
import org.thingsboard.server.common.data.device.profile.CoapDeviceTypeConfiguration;

Loading…
Cancel
Save