Commit 27d745f1e3a95bc2537ea6cb1b89e508bf4ede06

Authored by Sergey Matvienko
1 parent b477328d

tests added for update service for convertDeviceProfileAlarmRulesForVersion330

... ... @@ -145,35 +145,38 @@ public class DefaultDataUpdateService implements DataUpdateService {
145 145
146 146 @Override
147 147 protected void updateEntity(DeviceProfileEntity deviceProfile) {
148   - if (deviceProfile.getProfileData().has("alarms") &&
149   - !deviceProfile.getProfileData().get("alarms").isNull()) {
150   - boolean isUpdated = false;
151   - JsonNode alarms = deviceProfile.getProfileData().get("alarms");
152   - for (JsonNode alarm : alarms) {
153   - if (alarm.has("createRules")) {
154   - JsonNode createRules = alarm.get("createRules");
155   - for (AlarmSeverity severity : AlarmSeverity.values()) {
156   - if (createRules.has(severity.name())) {
157   - JsonNode spec = createRules.get(severity.name()).get("condition").get("spec");
158   - if (convertDeviceProfileAlarmRulesForVersion330(spec)) {
159   - isUpdated = true;
160   - }
161   - }
162   - }
163   - }
164   - if (alarm.has("clearRule") && !alarm.get("clearRule").isNull()) {
165   - JsonNode spec = alarm.get("clearRule").get("condition").get("spec");
166   - if (convertDeviceProfileAlarmRulesForVersion330(spec)) {
167   - isUpdated = true;
168   - }
  148 + if (convertDeviceProfileForVersion330(deviceProfile.getProfileData())) {
  149 + deviceProfileRepository.save(deviceProfile);
  150 + }
  151 + }
  152 + };
  153 +
  154 + boolean convertDeviceProfileForVersion330(JsonNode profileData) {
  155 + boolean isUpdated = false;
  156 + if (profileData.has("alarms") && !profileData.get("alarms").isNull()) {
  157 + JsonNode alarms = profileData.get("alarms");
  158 + for (JsonNode alarm : alarms) {
  159 + if (alarm.has("createRules")) {
  160 + JsonNode createRules = alarm.get("createRules");
  161 + for (AlarmSeverity severity : AlarmSeverity.values()) {
  162 + if (createRules.has(severity.name())) {
  163 + JsonNode spec = createRules.get(severity.name()).get("condition").get("spec");
  164 + if (convertDeviceProfileAlarmRulesForVersion330(spec)) {
  165 + isUpdated = true;
169 166 }
170 167 }
171   - if (isUpdated) {
172   - deviceProfileRepository.save(deviceProfile);
173   - }
174 168 }
175 169 }
176   - };
  170 + if (alarm.has("clearRule") && !alarm.get("clearRule").isNull()) {
  171 + JsonNode spec = alarm.get("clearRule").get("condition").get("spec");
  172 + if (convertDeviceProfileAlarmRulesForVersion330(spec)) {
  173 + isUpdated = true;
  174 + }
  175 + }
  176 + }
  177 + }
  178 + return isUpdated;
  179 + }
177 180
178 181 private final PaginatedUpdater<String, Tenant> tenantsDefaultRuleChainUpdater =
179 182 new PaginatedUpdater<>() {
... ... @@ -429,7 +432,7 @@ public class DefaultDataUpdateService implements DataUpdateService {
429 432 }
430 433 }
431 434
432   - private boolean convertDeviceProfileAlarmRulesForVersion330(JsonNode spec) {
  435 + boolean convertDeviceProfileAlarmRulesForVersion330(JsonNode spec) {
433 436 if (spec != null) {
434 437 if (spec.has("type") && spec.get("type").asText().equals("DURATION")) {
435 438 if (spec.has("value")) {
... ...
  1 +/**
  2 + * Copyright © 2016-2021 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.service.install.update;
  17 +
  18 +import com.fasterxml.jackson.core.JsonProcessingException;
  19 +import com.fasterxml.jackson.databind.JsonNode;
  20 +import com.fasterxml.jackson.databind.ObjectMapper;
  21 +import org.junit.jupiter.api.BeforeEach;
  22 +import org.junit.jupiter.api.Test;
  23 +import org.springframework.boot.test.context.SpringBootTest;
  24 +import org.springframework.boot.test.mock.mockito.MockBean;
  25 +import org.springframework.test.context.ActiveProfiles;
  26 +
  27 +import java.io.IOException;
  28 +
  29 +import static org.assertj.core.api.Assertions.assertThat;
  30 +import static org.mockito.ArgumentMatchers.any;
  31 +import static org.mockito.BDDMockito.willCallRealMethod;
  32 +
  33 +@ActiveProfiles("install")
  34 +@SpringBootTest(classes = DefaultDataUpdateService.class)
  35 +class DefaultDataUpdateServiceTest {
  36 +
  37 + ObjectMapper mapper = new ObjectMapper();
  38 +
  39 + @MockBean
  40 + DefaultDataUpdateService service;
  41 +
  42 + @BeforeEach
  43 + void setUp() {
  44 + willCallRealMethod().given(service).convertDeviceProfileAlarmRulesForVersion330(any());
  45 + willCallRealMethod().given(service).convertDeviceProfileForVersion330(any());
  46 + }
  47 +
  48 + JsonNode readFromResource(String resourceName) throws IOException {
  49 + return mapper.readTree(this.getClass().getClassLoader().getResourceAsStream(resourceName));
  50 + }
  51 +
  52 + @Test
  53 + void convertDeviceProfileAlarmRulesForVersion330FirstRun() throws IOException {
  54 + JsonNode spec = readFromResource("update/330/device_profile_001_in.json");
  55 + JsonNode expected = readFromResource("update/330/device_profile_001_out.json");
  56 +
  57 + assertThat(service.convertDeviceProfileForVersion330(spec.get("profileData"))).isTrue();
  58 + assertThat(spec.toPrettyString()).isEqualTo(expected.toPrettyString()); // use IDE feature <Click to see difference>
  59 + }
  60 +
  61 + @Test
  62 + void convertDeviceProfileAlarmRulesForVersion330SecondRun() throws IOException {
  63 + JsonNode spec = readFromResource("update/330/device_profile_001_out.json");
  64 + JsonNode expected = readFromResource("update/330/device_profile_001_out.json");
  65 +
  66 + assertThat(service.convertDeviceProfileForVersion330(spec.get("profileData"))).isFalse();
  67 + assertThat(spec.toPrettyString()).isEqualTo(expected.toPrettyString()); // use IDE feature <Click to see difference>
  68 + }
  69 +
  70 + @Test
  71 + void convertDeviceProfileAlarmRulesForVersion330EmptyJson() throws JsonProcessingException {
  72 + JsonNode spec = mapper.readTree("{ }");
  73 + JsonNode expected = mapper.readTree("{ }");
  74 +
  75 + assertThat(service.convertDeviceProfileForVersion330(spec)).isFalse();
  76 + assertThat(spec.toPrettyString()).isEqualTo(expected.toPrettyString());
  77 + }
  78 +
  79 + @Test
  80 + void convertDeviceProfileAlarmRulesForVersion330AlarmNodeNull() throws JsonProcessingException {
  81 + JsonNode spec = mapper.readTree("{ \"alarms\" : null }");
  82 + JsonNode expected = mapper.readTree("{ \"alarms\" : null }");
  83 +
  84 + assertThat(service.convertDeviceProfileForVersion330(spec)).isFalse();
  85 + assertThat(spec.toPrettyString()).isEqualTo(expected.toPrettyString());
  86 + }
  87 +
  88 + @Test
  89 + void convertDeviceProfileAlarmRulesForVersion330NoAlarmNode() throws JsonProcessingException {
  90 + JsonNode spec = mapper.readTree("{ \"configuration\": { \"type\": \"DEFAULT\" } }");
  91 + JsonNode expected = mapper.readTree("{ \"configuration\": { \"type\": \"DEFAULT\" } }");
  92 +
  93 + assertThat(service.convertDeviceProfileForVersion330(spec)).isFalse();
  94 + assertThat(spec.toPrettyString()).isEqualTo(expected.toPrettyString());
  95 + }
  96 +
  97 +}
... ...
  1 +To get json from live Thingsboard instance use those methods:
  2 +1. Browser: F12 -> Network -> open device profile page -> copy raw response
  3 +2. Database: SELECT * FROM public.device_profile WHERE name = 'LORAWAN 001';
\ No newline at end of file
... ...
  1 +{
  2 + "id": {
  3 + "entityType": "DEVICE_PROFILE",
  4 + "id": "b99fde7a-33dd-4d5d-a325-d0637f6acbe5"
  5 + },
  6 + "createdTime": 1627268171906,
  7 + "tenantId": {
  8 + "entityType": "TENANT",
  9 + "id": "3db30ac6-db03-4788-98fe-6e024b422a15"
  10 + },
  11 + "name": "LORAWAN 001",
  12 + "description": "Tektelic - 001",
  13 + "type": "DEFAULT",
  14 + "transportType": "DEFAULT",
  15 + "provisionType": "DISABLED",
  16 + "defaultRuleChainId": {
  17 + "entityType": "RULE_CHAIN",
  18 + "id": "9c50f4df-f41e-443f-bb7d-37b5ac97f3c3"
  19 + },
  20 + "defaultQueueName": "LORAWAN",
  21 + "profileData": {
  22 + "configuration": {
  23 + "type": "DEFAULT"
  24 + },
  25 + "transportConfiguration": {
  26 + "type": "DEFAULT"
  27 + },
  28 + "provisionConfiguration": {
  29 + "type": "DISABLED",
  30 + "provisionDeviceSecret": null
  31 + },
  32 + "alarms": [
  33 + {
  34 + "id": "b86271fd-5fee-4bd5-975c-d9c18f610cd5",
  35 + "alarmType": "LORAWAN - Battery Alarm",
  36 + "createRules": {
  37 + "CRITICAL": {
  38 + "condition": {
  39 + "condition": [
  40 + {
  41 + "key": {
  42 + "type": "TIME_SERIES",
  43 + "key": "batteryLevel"
  44 + },
  45 + "valueType": "NUMERIC",
  46 + "value": null,
  47 + "predicate": {
  48 + "type": "NUMERIC",
  49 + "operation": "LESS",
  50 + "value": {
  51 + "defaultValue": 25.0,
  52 + "userValue": null,
  53 + "dynamicValue": null
  54 + }
  55 + }
  56 + }
  57 + ],
  58 + "spec": {
  59 + "type": "DURATION",
  60 + "unit": "DAYS",
  61 + "value": 1
  62 + }
  63 + },
  64 + "schedule": null,
  65 + "alarmDetails": null
  66 + }
  67 + },
  68 + "clearRule": {
  69 + "condition": {
  70 + "condition": [
  71 + {
  72 + "key": {
  73 + "type": "TIME_SERIES",
  74 + "key": "batteryLevel"
  75 + },
  76 + "valueType": "NUMERIC",
  77 + "value": null,
  78 + "predicate": {
  79 + "type": "NUMERIC",
  80 + "operation": "GREATER_OR_EQUAL",
  81 + "value": {
  82 + "defaultValue": 25.0,
  83 + "userValue": null,
  84 + "dynamicValue": null
  85 + }
  86 + }
  87 + }
  88 + ],
  89 + "spec": {
  90 + "type": "DURATION",
  91 + "unit": "DAYS",
  92 + "value": 1
  93 + }
  94 + },
  95 + "schedule": null,
  96 + "alarmDetails": null
  97 + },
  98 + "propagate": true,
  99 + "propagateRelationTypes": [
  100 + "UC-0007 LORAWAN"
  101 + ]
  102 + },
  103 + {
  104 + "id": "c70aef4e-65cf-4578-acd9-e1927c08b469",
  105 + "alarmType": "LORAWAN - No Data",
  106 + "createRules": {
  107 + "CRITICAL": {
  108 + "condition": {
  109 + "condition": [
  110 + {
  111 + "key": {
  112 + "type": "TIME_SERIES",
  113 + "key": "active"
  114 + },
  115 + "valueType": "BOOLEAN",
  116 + "value": null,
  117 + "predicate": {
  118 + "type": "BOOLEAN",
  119 + "operation": "EQUAL",
  120 + "value": {
  121 + "defaultValue": false,
  122 + "userValue": null,
  123 + "dynamicValue": null
  124 + }
  125 + }
  126 + }
  127 + ],
  128 + "spec": {
  129 + "type": "SIMPLE"
  130 + }
  131 + },
  132 + "schedule": null,
  133 + "alarmDetails": null
  134 + }
  135 + },
  136 + "clearRule": {
  137 + "condition": {
  138 + "condition": [
  139 + {
  140 + "key": {
  141 + "type": "TIME_SERIES",
  142 + "key": "active"
  143 + },
  144 + "valueType": "BOOLEAN",
  145 + "value": null,
  146 + "predicate": {
  147 + "type": "BOOLEAN",
  148 + "operation": "EQUAL",
  149 + "value": {
  150 + "defaultValue": true,
  151 + "userValue": null,
  152 + "dynamicValue": null
  153 + }
  154 + }
  155 + }
  156 + ],
  157 + "spec": {
  158 + "type": "SIMPLE"
  159 + }
  160 + },
  161 + "schedule": null,
  162 + "alarmDetails": null
  163 + },
  164 + "propagate": true,
  165 + "propagateRelationTypes": [
  166 + "LORAWAN 001 related"
  167 + ]
  168 + }
  169 + ]
  170 + },
  171 + "provisionDeviceKey": null,
  172 + "default": false
  173 +}
... ...
  1 +{
  2 + "id": {
  3 + "entityType": "DEVICE_PROFILE",
  4 + "id": "b99fde7a-33dd-4d5d-a325-d0637f6acbe5"
  5 + },
  6 + "createdTime": 1627268171906,
  7 + "tenantId": {
  8 + "entityType": "TENANT",
  9 + "id": "3db30ac6-db03-4788-98fe-6e024b422a15"
  10 + },
  11 + "name": "LORAWAN 001",
  12 + "description": "Tektelic - 001",
  13 + "type": "DEFAULT",
  14 + "transportType": "DEFAULT",
  15 + "provisionType": "DISABLED",
  16 + "defaultRuleChainId": {
  17 + "entityType": "RULE_CHAIN",
  18 + "id": "9c50f4df-f41e-443f-bb7d-37b5ac97f3c3"
  19 + },
  20 + "defaultQueueName": "LORAWAN",
  21 + "profileData": {
  22 + "configuration": {
  23 + "type": "DEFAULT"
  24 + },
  25 + "transportConfiguration": {
  26 + "type": "DEFAULT"
  27 + },
  28 + "provisionConfiguration": {
  29 + "type": "DISABLED",
  30 + "provisionDeviceSecret": null
  31 + },
  32 + "alarms": [
  33 + {
  34 + "id": "b86271fd-5fee-4bd5-975c-d9c18f610cd5",
  35 + "alarmType": "LORAWAN - Battery Alarm",
  36 + "createRules": {
  37 + "CRITICAL": {
  38 + "condition": {
  39 + "condition": [
  40 + {
  41 + "key": {
  42 + "type": "TIME_SERIES",
  43 + "key": "batteryLevel"
  44 + },
  45 + "valueType": "NUMERIC",
  46 + "value": null,
  47 + "predicate": {
  48 + "type": "NUMERIC",
  49 + "operation": "LESS",
  50 + "value": {
  51 + "defaultValue": 25.0,
  52 + "userValue": null,
  53 + "dynamicValue": null
  54 + }
  55 + }
  56 + }
  57 + ],
  58 + "spec": {
  59 + "type": "DURATION",
  60 + "unit": "DAYS",
  61 + "predicate": {
  62 + "defaultValue": 1,
  63 + "userValue": null,
  64 + "dynamicValue": {
  65 + "sourceType": null,
  66 + "sourceAttribute": null,
  67 + "inherit": false
  68 + }
  69 + }
  70 + }
  71 + },
  72 + "schedule": null,
  73 + "alarmDetails": null
  74 + }
  75 + },
  76 + "clearRule": {
  77 + "condition": {
  78 + "condition": [
  79 + {
  80 + "key": {
  81 + "type": "TIME_SERIES",
  82 + "key": "batteryLevel"
  83 + },
  84 + "valueType": "NUMERIC",
  85 + "value": null,
  86 + "predicate": {
  87 + "type": "NUMERIC",
  88 + "operation": "GREATER_OR_EQUAL",
  89 + "value": {
  90 + "defaultValue": 25.0,
  91 + "userValue": null,
  92 + "dynamicValue": null
  93 + }
  94 + }
  95 + }
  96 + ],
  97 + "spec": {
  98 + "type": "DURATION",
  99 + "unit": "DAYS",
  100 + "predicate": {
  101 + "defaultValue": 1,
  102 + "userValue": null,
  103 + "dynamicValue": {
  104 + "sourceType": null,
  105 + "sourceAttribute": null,
  106 + "inherit": false
  107 + }
  108 + }
  109 + }
  110 + },
  111 + "schedule": null,
  112 + "alarmDetails": null
  113 + },
  114 + "propagate": true,
  115 + "propagateRelationTypes": [
  116 + "UC-0007 LORAWAN"
  117 + ]
  118 + },
  119 + {
  120 + "id": "c70aef4e-65cf-4578-acd9-e1927c08b469",
  121 + "alarmType": "LORAWAN - No Data",
  122 + "createRules": {
  123 + "CRITICAL": {
  124 + "condition": {
  125 + "condition": [
  126 + {
  127 + "key": {
  128 + "type": "TIME_SERIES",
  129 + "key": "active"
  130 + },
  131 + "valueType": "BOOLEAN",
  132 + "value": null,
  133 + "predicate": {
  134 + "type": "BOOLEAN",
  135 + "operation": "EQUAL",
  136 + "value": {
  137 + "defaultValue": false,
  138 + "userValue": null,
  139 + "dynamicValue": null
  140 + }
  141 + }
  142 + }
  143 + ],
  144 + "spec": {
  145 + "type": "SIMPLE"
  146 + }
  147 + },
  148 + "schedule": null,
  149 + "alarmDetails": null
  150 + }
  151 + },
  152 + "clearRule": {
  153 + "condition": {
  154 + "condition": [
  155 + {
  156 + "key": {
  157 + "type": "TIME_SERIES",
  158 + "key": "active"
  159 + },
  160 + "valueType": "BOOLEAN",
  161 + "value": null,
  162 + "predicate": {
  163 + "type": "BOOLEAN",
  164 + "operation": "EQUAL",
  165 + "value": {
  166 + "defaultValue": true,
  167 + "userValue": null,
  168 + "dynamicValue": null
  169 + }
  170 + }
  171 + }
  172 + ],
  173 + "spec": {
  174 + "type": "SIMPLE"
  175 + }
  176 + },
  177 + "schedule": null,
  178 + "alarmDetails": null
  179 + },
  180 + "propagate": true,
  181 + "propagateRelationTypes": [
  182 + "LORAWAN 001 related"
  183 + ]
  184 + }
  185 + ]
  186 + },
  187 + "provisionDeviceKey": null,
  188 + "default": false
  189 +}
... ...