Added geofencing CF configuration test
This commit is contained in:
parent
4e9b5cf927
commit
d2b9e1066f
@ -135,7 +135,7 @@ public class GeofencingCalculatedFieldState implements CalculatedFieldState {
|
||||
Coordinates entityCoordinates,
|
||||
GeofencingCalculatedFieldConfiguration configuration) {
|
||||
|
||||
var geofencingZoneGroupConfigurations = configuration.getGeofencingZoneGroupConfigurations();
|
||||
var geofencingZoneGroupConfigurations = configuration.getZoneGroupConfigurations();
|
||||
|
||||
Map<EntityId, GeofencingEvent> zoneEventMap = new HashMap<>();
|
||||
ObjectNode resultNode = JacksonUtil.newObjectNode();
|
||||
@ -184,7 +184,7 @@ public class GeofencingCalculatedFieldState implements CalculatedFieldState {
|
||||
Coordinates entityCoordinates,
|
||||
GeofencingCalculatedFieldConfiguration configuration) {
|
||||
|
||||
var geofencingZoneGroupConfigurations = configuration.getGeofencingZoneGroupConfigurations();
|
||||
var geofencingZoneGroupConfigurations = configuration.getZoneGroupConfigurations();
|
||||
ObjectNode resultNode = JacksonUtil.newObjectNode();
|
||||
|
||||
getGeofencingArguments().forEach((argumentKey, argumentEntry) -> {
|
||||
|
||||
@ -32,7 +32,7 @@ import org.thingsboard.server.common.data.cf.configuration.Argument;
|
||||
import org.thingsboard.server.common.data.cf.configuration.ArgumentType;
|
||||
import org.thingsboard.server.common.data.cf.configuration.GeofencingCalculatedFieldConfiguration;
|
||||
import org.thingsboard.server.common.data.cf.configuration.GeofencingEvent;
|
||||
import org.thingsboard.server.common.data.cf.configuration.GeofencingZoneGroupConfiguration;
|
||||
import org.thingsboard.server.common.data.cf.configuration.ZoneGroupConfiguration;
|
||||
import org.thingsboard.server.common.data.cf.configuration.Output;
|
||||
import org.thingsboard.server.common.data.cf.configuration.OutputType;
|
||||
import org.thingsboard.server.common.data.cf.configuration.ReferencedEntityKey;
|
||||
@ -701,10 +701,10 @@ public class CalculatedFieldIntegrationTest extends CalculatedFieldControllerTes
|
||||
// Zone group reporting config
|
||||
List<GeofencingEvent> reportEvents = Arrays.stream(GeofencingEvent.values()).toList();
|
||||
|
||||
GeofencingZoneGroupConfiguration allowedCfg = new GeofencingZoneGroupConfiguration("allowedZone", reportEvents);
|
||||
GeofencingZoneGroupConfiguration restrictedCfg = new GeofencingZoneGroupConfiguration("restrictedZone", reportEvents);
|
||||
ZoneGroupConfiguration allowedCfg = new ZoneGroupConfiguration("allowedZone", reportEvents);
|
||||
ZoneGroupConfiguration restrictedCfg = new ZoneGroupConfiguration("restrictedZone", reportEvents);
|
||||
|
||||
cfg.setGeofencingZoneGroupConfigurations(Map.of(
|
||||
cfg.setZoneGroupConfigurations(Map.of(
|
||||
"allowedZones", allowedCfg,
|
||||
"restrictedZones", restrictedCfg
|
||||
));
|
||||
|
||||
@ -30,7 +30,7 @@ import org.thingsboard.server.common.data.cf.configuration.ArgumentType;
|
||||
import org.thingsboard.server.common.data.cf.configuration.CalculatedFieldConfiguration;
|
||||
import org.thingsboard.server.common.data.cf.configuration.GeofencingCalculatedFieldConfiguration;
|
||||
import org.thingsboard.server.common.data.cf.configuration.GeofencingEvent;
|
||||
import org.thingsboard.server.common.data.cf.configuration.GeofencingZoneGroupConfiguration;
|
||||
import org.thingsboard.server.common.data.cf.configuration.ZoneGroupConfiguration;
|
||||
import org.thingsboard.server.common.data.cf.configuration.Output;
|
||||
import org.thingsboard.server.common.data.cf.configuration.OutputType;
|
||||
import org.thingsboard.server.common.data.cf.configuration.ReferencedEntityKey;
|
||||
@ -337,9 +337,9 @@ public class GeofencingCalculatedFieldStateTest {
|
||||
config.setArguments(Map.of("latitude", argument1, "longitude", argument2, "allowedZones", argument3, "restrictedZones", argument4));
|
||||
|
||||
List<GeofencingEvent> reportEvents = Arrays.stream(GeofencingEvent.values()).toList();
|
||||
GeofencingZoneGroupConfiguration allowedZoneGroupConfiguration = new GeofencingZoneGroupConfiguration("allowedZone", reportEvents);
|
||||
GeofencingZoneGroupConfiguration restrictedZoneGroupConfiguration = new GeofencingZoneGroupConfiguration("restrictedZone", reportEvents);
|
||||
config.setGeofencingZoneGroupConfigurations(Map.of("allowedZones", allowedZoneGroupConfiguration, "restrictedZones", restrictedZoneGroupConfiguration));
|
||||
ZoneGroupConfiguration allowedZoneGroupConfiguration = new ZoneGroupConfiguration("allowedZone", reportEvents);
|
||||
ZoneGroupConfiguration restrictedZoneGroupConfiguration = new ZoneGroupConfiguration("restrictedZone", reportEvents);
|
||||
config.setZoneGroupConfigurations(Map.of("allowedZones", allowedZoneGroupConfiguration, "restrictedZones", restrictedZoneGroupConfiguration));
|
||||
|
||||
config.setCreateRelationsWithMatchedZones(true);
|
||||
config.setZoneRelationType("CurrentZone");
|
||||
|
||||
@ -30,14 +30,14 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
public class GeofencingZoneStateTest {
|
||||
|
||||
private final AssetId ZONE_ID = new AssetId(UUID.fromString("628730fd-d625-417f-9c6d-ae9fe4addbdb"));
|
||||
private final String POLYGON = """
|
||||
{"type":"POLYGON","polygonsDefinition":"[[50.472000, 30.504000], [50.472000, 30.506000], [50.474000, 30.506000], [50.474000, 30.504000]]"}
|
||||
""";
|
||||
|
||||
private GeofencingZoneState state;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
String POLYGON = """
|
||||
{"type":"POLYGON","polygonsDefinition":"[[50.472000, 30.504000], [50.472000, 30.506000], [50.474000, 30.506000], [50.474000, 30.504000]]"}
|
||||
""";
|
||||
state = new GeofencingZoneState(ZONE_ID, new BaseAttributeKvEntry(new JsonDataEntry("zone", POLYGON), 100L, 1L));
|
||||
}
|
||||
|
||||
|
||||
@ -44,7 +44,7 @@ public class GeofencingCalculatedFieldConfiguration extends BaseCalculatedFieldC
|
||||
private boolean createRelationsWithMatchedZones;
|
||||
private String zoneRelationType;
|
||||
private EntitySearchDirection zoneRelationDirection;
|
||||
private Map<String, GeofencingZoneGroupConfiguration> geofencingZoneGroupConfigurations;
|
||||
private Map<String, ZoneGroupConfiguration> zoneGroupConfigurations;
|
||||
|
||||
@Override
|
||||
public CalculatedFieldType getType() {
|
||||
@ -60,13 +60,9 @@ public class GeofencingCalculatedFieldConfiguration extends BaseCalculatedFieldC
|
||||
@Override
|
||||
public void validate() {
|
||||
if (arguments == null) {
|
||||
throw new IllegalArgumentException("Geofencing calculated field arguments are empty!");
|
||||
}
|
||||
if (arguments.size() < 3) {
|
||||
throw new IllegalArgumentException("Geofencing calculated field must contain at least 3 arguments!");
|
||||
throw new IllegalArgumentException("Geofencing calculated field arguments must be specified!");
|
||||
}
|
||||
validateCoordinateArguments();
|
||||
|
||||
Map<String, Argument> zoneGroupsArguments = getZoneGroupArguments();
|
||||
if (zoneGroupsArguments.isEmpty()) {
|
||||
throw new IllegalArgumentException("Geofencing calculated field must contain at least one geofencing zone group defined!");
|
||||
@ -81,32 +77,30 @@ public class GeofencingCalculatedFieldConfiguration extends BaseCalculatedFieldC
|
||||
return;
|
||||
}
|
||||
if (StringUtils.isBlank(zoneRelationType)) {
|
||||
throw new IllegalArgumentException("Zone relation type must be specified when to maintain relations with matched zones!");
|
||||
throw new IllegalArgumentException("Zone relation type must be specified to create relations with matched zones!");
|
||||
}
|
||||
if (zoneRelationDirection == null) {
|
||||
throw new IllegalArgumentException("Zone relation direction must be specified to maintain relations with matched zones!");
|
||||
throw new IllegalArgumentException("Zone relation direction must be specified to create relations with matched zones!");
|
||||
}
|
||||
}
|
||||
|
||||
private void validateZoneGroupConfigurations(Map<String, Argument> zoneGroupsArguments) {
|
||||
if (geofencingZoneGroupConfigurations == null) {
|
||||
throw new IllegalArgumentException("Geofencing calculated field zone group configurations are empty!");
|
||||
if (zoneGroupConfigurations == null || zoneGroupConfigurations.isEmpty()) {
|
||||
throw new IllegalArgumentException("Zone groups configuration should be specified!");
|
||||
}
|
||||
Set<String> usedPrefixes = new HashSet<>();
|
||||
geofencingZoneGroupConfigurations.forEach((zoneGroupName, config) -> {
|
||||
Argument zoneGroupArgument = zoneGroupsArguments.get(zoneGroupName);
|
||||
if (zoneGroupArgument == null) {
|
||||
throw new IllegalArgumentException("Geofencing calculated field zone group configuration is not configured for zone group: " + zoneGroupName);
|
||||
}
|
||||
|
||||
zoneGroupsArguments.forEach((zoneGroupName, zoneGroupArgument) -> {
|
||||
ZoneGroupConfiguration config = zoneGroupConfigurations.get(zoneGroupName);
|
||||
if (config == null) {
|
||||
throw new IllegalArgumentException("Zone group configuration is not configured for zone group: " + zoneGroupName);
|
||||
throw new IllegalArgumentException("Zone group configuration is not configured for '" + zoneGroupName + "' argument!");
|
||||
}
|
||||
if (CollectionsUtil.isEmpty(config.getReportEvents())) {
|
||||
throw new IllegalArgumentException("Zone group configuration report events must be specified for zone group: " + zoneGroupName);
|
||||
throw new IllegalArgumentException("Zone group configuration report events must be specified for '" + zoneGroupName + "' argument!");
|
||||
}
|
||||
String prefix = config.getReportTelemetryPrefix();
|
||||
if (StringUtils.isBlank(prefix)) {
|
||||
throw new IllegalArgumentException("Report telemetry prefix should be specified for zone group: " + zoneGroupName);
|
||||
throw new IllegalArgumentException("Report telemetry prefix should be specified for '" + zoneGroupName + "' argument!");
|
||||
}
|
||||
if (!usedPrefixes.add(prefix)) {
|
||||
throw new IllegalArgumentException("Duplicate report telemetry prefix found: '" + prefix + "'. Must be unique!");
|
||||
@ -118,26 +112,23 @@ public class GeofencingCalculatedFieldConfiguration extends BaseCalculatedFieldC
|
||||
for (String coordinateKey : coordinateKeys) {
|
||||
Argument argument = arguments.get(coordinateKey);
|
||||
if (argument == null) {
|
||||
throw new IllegalArgumentException("Missing required coordinates argument: " + coordinateKey);
|
||||
throw new IllegalArgumentException("Missing required coordinates argument: " + coordinateKey + "!");
|
||||
}
|
||||
ReferencedEntityKey refEntityKey = validateAndGetRefEntityKey(argument, coordinateKey);
|
||||
if (!ArgumentType.TS_LATEST.equals(refEntityKey.getType())) {
|
||||
throw new IllegalArgumentException("Argument '" + coordinateKey + "' must be of type TS_LATEST.");
|
||||
throw new IllegalArgumentException("Argument '" + coordinateKey + "' must be of type TS_LATEST!");
|
||||
}
|
||||
if (argument.hasDynamicSource()) {
|
||||
throw new IllegalArgumentException("Dynamic source is not allowed for argument: '" + coordinateKey + "'.");
|
||||
throw new IllegalArgumentException("Dynamic source is not allowed for '" + coordinateKey + "' argument!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void validateZoneGroupAruguments(Map<String, Argument> zoneGroupsArguments) {
|
||||
zoneGroupsArguments.forEach((argumentKey, argument) -> {
|
||||
if (argument == null) {
|
||||
throw new IllegalArgumentException("Zone group argument is not configured: " + argumentKey);
|
||||
}
|
||||
ReferencedEntityKey refEntityKey = validateAndGetRefEntityKey(argument, argumentKey);
|
||||
if (!ArgumentType.ATTRIBUTE.equals(refEntityKey.getType())) {
|
||||
throw new IllegalArgumentException("Argument '" + argumentKey + "' must be of type ATTRIBUTE.");
|
||||
throw new IllegalArgumentException("Argument '" + argumentKey + "' must be of type ATTRIBUTE!");
|
||||
}
|
||||
if (argument.hasDynamicSource()) {
|
||||
argument.getRefDynamicSourceConfiguration().validate();
|
||||
@ -148,6 +139,7 @@ public class GeofencingCalculatedFieldConfiguration extends BaseCalculatedFieldC
|
||||
private Map<String, Argument> getZoneGroupArguments() {
|
||||
return arguments.entrySet()
|
||||
.stream()
|
||||
.filter(entry -> entry.getValue() != null)
|
||||
.filter(entry -> !coordinateKeys.contains(entry.getKey()))
|
||||
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
|
||||
}
|
||||
|
||||
@ -20,7 +20,7 @@ import lombok.Data;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class GeofencingZoneGroupConfiguration {
|
||||
public class ZoneGroupConfiguration {
|
||||
|
||||
private final String reportTelemetryPrefix;
|
||||
private final List<GeofencingEvent> reportEvents;
|
||||
@ -0,0 +1,472 @@
|
||||
/**
|
||||
* Copyright © 2016-2025 The Thingsboard Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.thingsboard.server.common.data.cf.configuration;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.NullAndEmptySource;
|
||||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.thingsboard.server.common.data.cf.CalculatedFieldType;
|
||||
import org.thingsboard.server.common.data.relation.EntitySearchDirection;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.thingsboard.server.common.data.cf.configuration.GeofencingCalculatedFieldConfiguration.ENTITY_ID_LATITUDE_ARGUMENT_KEY;
|
||||
import static org.thingsboard.server.common.data.cf.configuration.GeofencingCalculatedFieldConfiguration.ENTITY_ID_LONGITUDE_ARGUMENT_KEY;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
public class GeofencingCalculatedFieldConfigurationTest {
|
||||
|
||||
@Test
|
||||
void typeShouldBeGeofencing() {
|
||||
var cfg = new GeofencingCalculatedFieldConfiguration();
|
||||
assertThat(cfg.getType()).isEqualTo(CalculatedFieldType.GEOFENCING);
|
||||
}
|
||||
|
||||
@Test
|
||||
void validateShouldThrowWhenArgumentsNull() {
|
||||
var cfg = new GeofencingCalculatedFieldConfiguration();
|
||||
cfg.setArguments(null);
|
||||
|
||||
assertThatThrownBy(cfg::validate)
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("Geofencing calculated field arguments must be specified!");
|
||||
}
|
||||
|
||||
@Test
|
||||
void validateShouldThrowWhenLatitudeArgIsMissing() {
|
||||
var cfg = new GeofencingCalculatedFieldConfiguration();
|
||||
var arguments = new HashMap<String, Argument>();
|
||||
arguments.put(ENTITY_ID_LATITUDE_ARGUMENT_KEY, null);
|
||||
arguments.put(ENTITY_ID_LONGITUDE_ARGUMENT_KEY, toArgument("longitude", ArgumentType.TS_LATEST));
|
||||
cfg.setArguments(arguments);
|
||||
|
||||
assertThatThrownBy(cfg::validate)
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("Missing required coordinates argument: " + ENTITY_ID_LATITUDE_ARGUMENT_KEY + "!");
|
||||
}
|
||||
|
||||
@Test
|
||||
void validateShouldThrowWhenLongitudeArgIsMissing() {
|
||||
var cfg = new GeofencingCalculatedFieldConfiguration();
|
||||
var arguments = new HashMap<String, Argument>();
|
||||
arguments.put(ENTITY_ID_LATITUDE_ARGUMENT_KEY, toArgument("latitude", ArgumentType.TS_LATEST));
|
||||
arguments.put(ENTITY_ID_LONGITUDE_ARGUMENT_KEY, null);
|
||||
cfg.setArguments(arguments);
|
||||
|
||||
assertThatThrownBy(cfg::validate)
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("Missing required coordinates argument: " + ENTITY_ID_LONGITUDE_ARGUMENT_KEY + "!");
|
||||
}
|
||||
|
||||
@Test
|
||||
void validateShouldThrowWhenLatitudeReferenceKeyIsNull() {
|
||||
var cfg = new GeofencingCalculatedFieldConfiguration();
|
||||
cfg.setArguments(Map.of(
|
||||
ENTITY_ID_LATITUDE_ARGUMENT_KEY, toArgument(null),
|
||||
ENTITY_ID_LONGITUDE_ARGUMENT_KEY, toArgument("longitude", ArgumentType.TS_LATEST))
|
||||
);
|
||||
|
||||
assertThatThrownBy(cfg::validate)
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("Missing or invalid reference entity key for argument: " + ENTITY_ID_LATITUDE_ARGUMENT_KEY);
|
||||
}
|
||||
|
||||
@Test
|
||||
void validateShouldThrowWhenLongitudeReferenceKeyIsNull() {
|
||||
var cfg = new GeofencingCalculatedFieldConfiguration();
|
||||
cfg.setArguments(Map.of(
|
||||
ENTITY_ID_LATITUDE_ARGUMENT_KEY, toArgument("latitude", ArgumentType.TS_LATEST),
|
||||
ENTITY_ID_LONGITUDE_ARGUMENT_KEY, toArgument(null))
|
||||
);
|
||||
|
||||
assertThatThrownBy(cfg::validate)
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("Missing or invalid reference entity key for argument: " + ENTITY_ID_LONGITUDE_ARGUMENT_KEY);
|
||||
}
|
||||
|
||||
@Test
|
||||
void validateShouldThrowWhenLatitudeReferenceKeyTypeIsNull() {
|
||||
var cfg = new GeofencingCalculatedFieldConfiguration();
|
||||
cfg.setArguments(Map.of(
|
||||
ENTITY_ID_LATITUDE_ARGUMENT_KEY, toArgument(new ReferencedEntityKey("latitude", null, null)),
|
||||
ENTITY_ID_LONGITUDE_ARGUMENT_KEY, toArgument("longitude", ArgumentType.TS_LATEST))
|
||||
);
|
||||
|
||||
assertThatThrownBy(cfg::validate)
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("Missing or invalid reference entity key for argument: " + ENTITY_ID_LATITUDE_ARGUMENT_KEY);
|
||||
}
|
||||
|
||||
@Test
|
||||
void validateShouldThrowWhenReferenceKeyTypeIsNull() {
|
||||
var cfg = new GeofencingCalculatedFieldConfiguration();
|
||||
cfg.setArguments(Map.of(
|
||||
ENTITY_ID_LATITUDE_ARGUMENT_KEY, toArgument("latitude", ArgumentType.TS_LATEST),
|
||||
ENTITY_ID_LONGITUDE_ARGUMENT_KEY, toArgument(new ReferencedEntityKey("longitude", null, null)))
|
||||
);
|
||||
|
||||
assertThatThrownBy(cfg::validate)
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("Missing or invalid reference entity key for argument: " + ENTITY_ID_LONGITUDE_ARGUMENT_KEY);
|
||||
}
|
||||
|
||||
@Test
|
||||
void validateShouldThrowWhenLatitudeArgHasWrongArgumentType() {
|
||||
var cfg = new GeofencingCalculatedFieldConfiguration();
|
||||
cfg.setArguments(Map.of(
|
||||
ENTITY_ID_LATITUDE_ARGUMENT_KEY, toArgument("latitude", ArgumentType.ATTRIBUTE),
|
||||
ENTITY_ID_LONGITUDE_ARGUMENT_KEY, toArgument("longitude", ArgumentType.TS_LATEST)
|
||||
));
|
||||
|
||||
assertThatThrownBy(cfg::validate)
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("Argument '" + ENTITY_ID_LATITUDE_ARGUMENT_KEY + "' must be of type TS_LATEST!");
|
||||
}
|
||||
|
||||
@Test
|
||||
void validateShouldThrowWhenLongitudeArgHasWrongArgumentType() {
|
||||
var cfg = new GeofencingCalculatedFieldConfiguration();
|
||||
cfg.setArguments(Map.of(
|
||||
ENTITY_ID_LATITUDE_ARGUMENT_KEY, toArgument("latitude", ArgumentType.TS_LATEST),
|
||||
ENTITY_ID_LONGITUDE_ARGUMENT_KEY, toArgument("longitude", ArgumentType.ATTRIBUTE)
|
||||
));
|
||||
|
||||
assertThatThrownBy(cfg::validate)
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("Argument '" + ENTITY_ID_LONGITUDE_ARGUMENT_KEY + "' must be of type TS_LATEST!");
|
||||
}
|
||||
|
||||
@Test
|
||||
void validateShouldThrowWhenLatitudeArgHasDynamicSource() {
|
||||
var cfg = new GeofencingCalculatedFieldConfiguration();
|
||||
|
||||
Argument latitudeArg = toArgument("latitude", ArgumentType.TS_LATEST);
|
||||
var refDynamicSourceConfiguration = new RelationQueryDynamicSourceConfiguration();
|
||||
latitudeArg.setRefDynamicSourceConfiguration(refDynamicSourceConfiguration);
|
||||
|
||||
Argument longitudeArg = toArgument("longitude", ArgumentType.TS_LATEST);
|
||||
|
||||
cfg.setArguments(Map.of(ENTITY_ID_LATITUDE_ARGUMENT_KEY, latitudeArg, ENTITY_ID_LONGITUDE_ARGUMENT_KEY, longitudeArg));
|
||||
|
||||
assertThatThrownBy(cfg::validate)
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("Dynamic source is not allowed for '" + ENTITY_ID_LATITUDE_ARGUMENT_KEY + "' argument!");
|
||||
}
|
||||
|
||||
@Test
|
||||
void validateShouldThrowWhenLongitudeArgHasDynamicSource() {
|
||||
var cfg = new GeofencingCalculatedFieldConfiguration();
|
||||
|
||||
Argument latitudeArg = toArgument("latitude", ArgumentType.TS_LATEST);
|
||||
Argument longitudeArg = toArgument("longitude", ArgumentType.TS_LATEST);
|
||||
var refDynamicSourceConfiguration = new RelationQueryDynamicSourceConfiguration();
|
||||
longitudeArg.setRefDynamicSourceConfiguration(refDynamicSourceConfiguration);
|
||||
|
||||
cfg.setArguments(Map.of(ENTITY_ID_LATITUDE_ARGUMENT_KEY, latitudeArg, ENTITY_ID_LONGITUDE_ARGUMENT_KEY, longitudeArg));
|
||||
|
||||
assertThatThrownBy(cfg::validate)
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("Dynamic source is not allowed for '" + ENTITY_ID_LONGITUDE_ARGUMENT_KEY + "' argument!");
|
||||
}
|
||||
|
||||
@Test
|
||||
void validateShouldThrowWhenGeofencingArgumentsMissing() {
|
||||
var cfg = new GeofencingCalculatedFieldConfiguration();
|
||||
cfg.setArguments(Map.of(
|
||||
ENTITY_ID_LATITUDE_ARGUMENT_KEY, toArgument("latitude", ArgumentType.TS_LATEST),
|
||||
ENTITY_ID_LONGITUDE_ARGUMENT_KEY, toArgument("longitude", ArgumentType.TS_LATEST)
|
||||
));
|
||||
|
||||
assertThatThrownBy(cfg::validate)
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("Geofencing calculated field must contain at least one geofencing zone group defined!");
|
||||
}
|
||||
|
||||
@Test
|
||||
void validateShouldThrowWhenZoneGroupArgumentIsNull() {
|
||||
var cfg = new GeofencingCalculatedFieldConfiguration();
|
||||
var arguments = new HashMap<String, Argument>();
|
||||
arguments.put(ENTITY_ID_LATITUDE_ARGUMENT_KEY, toArgument("latitude", ArgumentType.TS_LATEST));
|
||||
arguments.put(ENTITY_ID_LONGITUDE_ARGUMENT_KEY, toArgument("longitude", ArgumentType.TS_LATEST));
|
||||
arguments.put("someZones", null);
|
||||
|
||||
cfg.setArguments(arguments);
|
||||
|
||||
assertThatThrownBy(cfg::validate)
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("Geofencing calculated field must contain at least one geofencing zone group defined!");
|
||||
}
|
||||
|
||||
@Test
|
||||
void validateShouldThrowWhenZoneGroupArgumentHasInvalidArgumentType() {
|
||||
var cfg = new GeofencingCalculatedFieldConfiguration();
|
||||
var arguments = new HashMap<String, Argument>();
|
||||
arguments.put(ENTITY_ID_LATITUDE_ARGUMENT_KEY, toArgument("latitude", ArgumentType.TS_LATEST));
|
||||
arguments.put(ENTITY_ID_LONGITUDE_ARGUMENT_KEY, toArgument("longitude", ArgumentType.TS_LATEST));
|
||||
arguments.put("allowedZones", toArgument("allowedZone", ArgumentType.TS_LATEST));
|
||||
|
||||
cfg.setArguments(arguments);
|
||||
|
||||
assertThatThrownBy(cfg::validate)
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("Argument 'allowedZones' must be of type ATTRIBUTE!");
|
||||
}
|
||||
|
||||
@Test
|
||||
void validateShouldCallDynamicSourceConfigValidationWhenZoneGroupArgumentHasDynamicSourceConfiguration() {
|
||||
var cfg = new GeofencingCalculatedFieldConfiguration();
|
||||
var arguments = new HashMap<String, Argument>();
|
||||
arguments.put(ENTITY_ID_LATITUDE_ARGUMENT_KEY, toArgument("latitude", ArgumentType.TS_LATEST));
|
||||
arguments.put(ENTITY_ID_LONGITUDE_ARGUMENT_KEY, toArgument("longitude", ArgumentType.TS_LATEST));
|
||||
Argument allowedZonesArg = toArgument("allowedZone", ArgumentType.ATTRIBUTE);
|
||||
var refDynamicSourceConfigurationMock = mock(RelationQueryDynamicSourceConfiguration.class);
|
||||
allowedZonesArg.setRefDynamicSourceConfiguration(refDynamicSourceConfigurationMock);
|
||||
arguments.put("allowedZones", allowedZonesArg);
|
||||
|
||||
ZoneGroupConfiguration allowedZoneConfiguration = new ZoneGroupConfiguration("allowedZone", Arrays.asList(GeofencingEvent.values()));
|
||||
Map<String, ZoneGroupConfiguration> zoneGroupConfigurations = Map.of("allowedZones", allowedZoneConfiguration);
|
||||
|
||||
cfg.setArguments(arguments);
|
||||
cfg.setZoneGroupConfigurations(zoneGroupConfigurations);
|
||||
|
||||
cfg.validate();
|
||||
|
||||
verify(refDynamicSourceConfigurationMock).validate();
|
||||
}
|
||||
|
||||
@Test
|
||||
void validateShouldThrowWhenZoneGroupConfigurationIsMissing() {
|
||||
var cfg = new GeofencingCalculatedFieldConfiguration();
|
||||
var arguments = new HashMap<String, Argument>();
|
||||
arguments.put(ENTITY_ID_LATITUDE_ARGUMENT_KEY, toArgument("latitude", ArgumentType.TS_LATEST));
|
||||
arguments.put(ENTITY_ID_LONGITUDE_ARGUMENT_KEY, toArgument("longitude", ArgumentType.TS_LATEST));
|
||||
Argument allowedZonesArg = toArgument("allowedZone", ArgumentType.ATTRIBUTE);
|
||||
var refDynamicSourceConfigurationMock = mock(RelationQueryDynamicSourceConfiguration.class);
|
||||
allowedZonesArg.setRefDynamicSourceConfiguration(refDynamicSourceConfigurationMock);
|
||||
arguments.put("allowedZones", allowedZonesArg);
|
||||
|
||||
cfg.setArguments(arguments);
|
||||
cfg.setZoneGroupConfigurations(null);
|
||||
cfg.setCreateRelationsWithMatchedZones(false);
|
||||
|
||||
assertThatThrownBy(cfg::validate)
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("Zone groups configuration should be specified!");
|
||||
}
|
||||
|
||||
@Test
|
||||
void validateShouldThrowWhenReportTelemetryPrefixDuplicate() {
|
||||
var cfg = new GeofencingCalculatedFieldConfiguration();
|
||||
var arguments = new HashMap<String, Argument>();
|
||||
arguments.put(ENTITY_ID_LATITUDE_ARGUMENT_KEY, toArgument("latitude", ArgumentType.TS_LATEST));
|
||||
arguments.put(ENTITY_ID_LONGITUDE_ARGUMENT_KEY, toArgument("longitude", ArgumentType.TS_LATEST));
|
||||
Argument allowedZonesArg = toArgument("allowedZone", ArgumentType.ATTRIBUTE);
|
||||
Argument restrictedZonesArg = toArgument("restrictedZone", ArgumentType.ATTRIBUTE);
|
||||
var refDynamicSourceConfigurationMock = mock(RelationQueryDynamicSourceConfiguration.class);
|
||||
allowedZonesArg.setRefDynamicSourceConfiguration(refDynamicSourceConfigurationMock);
|
||||
arguments.put("allowedZones", allowedZonesArg);
|
||||
arguments.put("restrictedZones", restrictedZonesArg);
|
||||
|
||||
ZoneGroupConfiguration allowedZoneConfiguration = new ZoneGroupConfiguration("theSamePrefixTest", Arrays.asList(GeofencingEvent.values()));
|
||||
ZoneGroupConfiguration restrictedZoneConfiguration = new ZoneGroupConfiguration("theSamePrefixTest", Arrays.asList(GeofencingEvent.values()));
|
||||
Map<String, ZoneGroupConfiguration> zoneGroupConfigurations = Map.of("allowedZones", allowedZoneConfiguration, "restrictedZones", restrictedZoneConfiguration);
|
||||
|
||||
cfg.setArguments(arguments);
|
||||
cfg.setZoneGroupConfigurations(zoneGroupConfigurations);
|
||||
cfg.setCreateRelationsWithMatchedZones(false);
|
||||
|
||||
assertThatThrownBy(cfg::validate)
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("Duplicate report telemetry prefix found: 'theSamePrefixTest'. Must be unique!");
|
||||
}
|
||||
|
||||
@Test
|
||||
void validateShouldThrowWhenZoneGroupArgumentConfigurationIsMissing() {
|
||||
var cfg = new GeofencingCalculatedFieldConfiguration();
|
||||
var arguments = new HashMap<String, Argument>();
|
||||
arguments.put(ENTITY_ID_LATITUDE_ARGUMENT_KEY, toArgument("latitude", ArgumentType.TS_LATEST));
|
||||
arguments.put(ENTITY_ID_LONGITUDE_ARGUMENT_KEY, toArgument("longitude", ArgumentType.TS_LATEST));
|
||||
Argument allowedZonesArg = toArgument("allowedZone", ArgumentType.ATTRIBUTE);
|
||||
var refDynamicSourceConfigurationMock = mock(RelationQueryDynamicSourceConfiguration.class);
|
||||
allowedZonesArg.setRefDynamicSourceConfiguration(refDynamicSourceConfigurationMock);
|
||||
arguments.put("allowedZones", allowedZonesArg);
|
||||
|
||||
ZoneGroupConfiguration allowedZoneConfiguration = new ZoneGroupConfiguration("allowedZone", Arrays.asList(GeofencingEvent.values()));
|
||||
Map<String, ZoneGroupConfiguration> zoneGroupConfigurations = Map.of("someOtherZones", allowedZoneConfiguration);
|
||||
|
||||
cfg.setArguments(arguments);
|
||||
cfg.setZoneGroupConfigurations(zoneGroupConfigurations);
|
||||
cfg.setCreateRelationsWithMatchedZones(false);
|
||||
|
||||
assertThatThrownBy(cfg::validate)
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("Zone group configuration is not configured for 'allowedZones' argument!");
|
||||
}
|
||||
|
||||
@Test
|
||||
void validateShouldThrowWhenZoneGroupConfigurationReportEventsAreNotSpecified() {
|
||||
var cfg = new GeofencingCalculatedFieldConfiguration();
|
||||
var arguments = new HashMap<String, Argument>();
|
||||
arguments.put(ENTITY_ID_LATITUDE_ARGUMENT_KEY, toArgument("latitude", ArgumentType.TS_LATEST));
|
||||
arguments.put(ENTITY_ID_LONGITUDE_ARGUMENT_KEY, toArgument("longitude", ArgumentType.TS_LATEST));
|
||||
Argument allowedZonesArg = toArgument("allowedZone", ArgumentType.ATTRIBUTE);
|
||||
var refDynamicSourceConfigurationMock = mock(RelationQueryDynamicSourceConfiguration.class);
|
||||
allowedZonesArg.setRefDynamicSourceConfiguration(refDynamicSourceConfigurationMock);
|
||||
arguments.put("allowedZones", allowedZonesArg);
|
||||
|
||||
ZoneGroupConfiguration allowedZoneConfiguration = new ZoneGroupConfiguration("allowedZone", null);
|
||||
Map<String, ZoneGroupConfiguration> zoneGroupConfigurations = Map.of("allowedZones", allowedZoneConfiguration);
|
||||
|
||||
cfg.setArguments(arguments);
|
||||
cfg.setZoneGroupConfigurations(zoneGroupConfigurations);
|
||||
cfg.setCreateRelationsWithMatchedZones(false);
|
||||
|
||||
assertThatThrownBy(cfg::validate)
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("Zone group configuration report events must be specified for 'allowedZones' argument!");
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@NullAndEmptySource
|
||||
@ValueSource(strings = " ")
|
||||
void validateShouldThrowWhenZoneGroupConfigurationTelemetryPrefixIsBlankOrNull(String reportTelemetryPrefix) {
|
||||
var cfg = new GeofencingCalculatedFieldConfiguration();
|
||||
var arguments = new HashMap<String, Argument>();
|
||||
arguments.put(ENTITY_ID_LATITUDE_ARGUMENT_KEY, toArgument("latitude", ArgumentType.TS_LATEST));
|
||||
arguments.put(ENTITY_ID_LONGITUDE_ARGUMENT_KEY, toArgument("longitude", ArgumentType.TS_LATEST));
|
||||
Argument allowedZonesArg = toArgument("allowedZone", ArgumentType.ATTRIBUTE);
|
||||
var refDynamicSourceConfigurationMock = mock(RelationQueryDynamicSourceConfiguration.class);
|
||||
allowedZonesArg.setRefDynamicSourceConfiguration(refDynamicSourceConfigurationMock);
|
||||
arguments.put("allowedZones", allowedZonesArg);
|
||||
|
||||
ZoneGroupConfiguration allowedZoneConfiguration = new ZoneGroupConfiguration(reportTelemetryPrefix, Arrays.asList(GeofencingEvent.values()));
|
||||
Map<String, ZoneGroupConfiguration> zoneGroupConfigurations = Map.of("allowedZones", allowedZoneConfiguration);
|
||||
|
||||
cfg.setArguments(arguments);
|
||||
cfg.setZoneGroupConfigurations(zoneGroupConfigurations);
|
||||
cfg.setCreateRelationsWithMatchedZones(false);
|
||||
|
||||
assertThatThrownBy(cfg::validate)
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("Report telemetry prefix should be specified for 'allowedZones' argument!");
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@NullAndEmptySource
|
||||
@ValueSource(strings = " ")
|
||||
void validateShouldThrowWhenHasBlankOrNullZoneRelationType(String zoneRelationType) {
|
||||
var cfg = new GeofencingCalculatedFieldConfiguration();
|
||||
var arguments = new HashMap<String, Argument>();
|
||||
arguments.put(ENTITY_ID_LATITUDE_ARGUMENT_KEY, toArgument("latitude", ArgumentType.TS_LATEST));
|
||||
arguments.put(ENTITY_ID_LONGITUDE_ARGUMENT_KEY, toArgument("longitude", ArgumentType.TS_LATEST));
|
||||
Argument allowedZonesArg = toArgument("allowedZone", ArgumentType.ATTRIBUTE);
|
||||
var refDynamicSourceConfigurationMock = mock(RelationQueryDynamicSourceConfiguration.class);
|
||||
allowedZonesArg.setRefDynamicSourceConfiguration(refDynamicSourceConfigurationMock);
|
||||
arguments.put("allowedZones", allowedZonesArg);
|
||||
|
||||
ZoneGroupConfiguration allowedZoneConfiguration = new ZoneGroupConfiguration("allowedZone", Arrays.asList(GeofencingEvent.values()));
|
||||
Map<String, ZoneGroupConfiguration> zoneGroupConfigurations = Map.of("allowedZones", allowedZoneConfiguration);
|
||||
|
||||
cfg.setArguments(arguments);
|
||||
cfg.setZoneGroupConfigurations(zoneGroupConfigurations);
|
||||
cfg.setCreateRelationsWithMatchedZones(true);
|
||||
cfg.setZoneRelationType(zoneRelationType);
|
||||
cfg.setZoneRelationDirection(EntitySearchDirection.TO);
|
||||
|
||||
assertThatThrownBy(cfg::validate)
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("Zone relation type must be specified to create relations with matched zones!");
|
||||
}
|
||||
|
||||
@Test
|
||||
void validateShouldThrowWhenNoZoneRelationDirectionSpecified() {
|
||||
var cfg = new GeofencingCalculatedFieldConfiguration();
|
||||
var arguments = new HashMap<String, Argument>();
|
||||
arguments.put(ENTITY_ID_LATITUDE_ARGUMENT_KEY, toArgument("latitude", ArgumentType.TS_LATEST));
|
||||
arguments.put(ENTITY_ID_LONGITUDE_ARGUMENT_KEY, toArgument("longitude", ArgumentType.TS_LATEST));
|
||||
Argument allowedZonesArg = toArgument("allowedZone", ArgumentType.ATTRIBUTE);
|
||||
var refDynamicSourceConfigurationMock = mock(RelationQueryDynamicSourceConfiguration.class);
|
||||
allowedZonesArg.setRefDynamicSourceConfiguration(refDynamicSourceConfigurationMock);
|
||||
arguments.put("allowedZones", allowedZonesArg);
|
||||
|
||||
ZoneGroupConfiguration allowedZoneConfiguration = new ZoneGroupConfiguration("allowedZone", Arrays.asList(GeofencingEvent.values()));
|
||||
Map<String, ZoneGroupConfiguration> zoneGroupConfigurations = Map.of("allowedZones", allowedZoneConfiguration);
|
||||
|
||||
cfg.setArguments(arguments);
|
||||
cfg.setZoneGroupConfigurations(zoneGroupConfigurations);
|
||||
cfg.setCreateRelationsWithMatchedZones(true);
|
||||
cfg.setZoneRelationType("SomeRelationType");
|
||||
|
||||
assertThatThrownBy(cfg::validate)
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("Zone relation direction must be specified to create relations with matched zones!");
|
||||
}
|
||||
|
||||
@Test
|
||||
void scheduledUpdateDisabledWhenIntervalIsZero() {
|
||||
var cfg = new GeofencingCalculatedFieldConfiguration();
|
||||
cfg.setScheduledUpdateIntervalSec(0);
|
||||
assertThat(cfg.isScheduledUpdateEnabled()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
void scheduledUpdateDisabledWhenIntervalIsGreaterThanZeroButArgumentsAreEmpty() {
|
||||
var cfg = new GeofencingCalculatedFieldConfiguration();
|
||||
cfg.setArguments(Map.of());
|
||||
cfg.setScheduledUpdateIntervalSec(60);
|
||||
assertThat(cfg.isScheduledUpdateEnabled()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
void scheduledUpdateDisabledWhenIntervalIsGreaterThanZeroButDynamicArgumentsAreMissing() {
|
||||
var cfg = new GeofencingCalculatedFieldConfiguration();
|
||||
cfg.setArguments(Map.of(ENTITY_ID_LATITUDE_ARGUMENT_KEY, toArgument("latitude", ArgumentType.TS_LATEST)));
|
||||
cfg.setScheduledUpdateIntervalSec(60);
|
||||
assertThat(cfg.isScheduledUpdateEnabled()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
void scheduledUpdateEnabledWhenIntervalIsGreaterThanZeroAndDynamicArgumentsPresent() {
|
||||
var cfg = new GeofencingCalculatedFieldConfiguration();
|
||||
Argument someDynamicArgument = toArgument("someDynamicArgument", ArgumentType.ATTRIBUTE);
|
||||
someDynamicArgument.setRefDynamicSourceConfiguration(new RelationQueryDynamicSourceConfiguration());
|
||||
cfg.setArguments(Map.of("someDynamicArugument", someDynamicArgument));
|
||||
cfg.setScheduledUpdateIntervalSec(60);
|
||||
assertThat(cfg.isScheduledUpdateEnabled()).isTrue();
|
||||
}
|
||||
|
||||
|
||||
private Argument toArgument(String key, ArgumentType type) {
|
||||
var referencedEntityKey = new ReferencedEntityKey(key, type, null);
|
||||
return toArgument(referencedEntityKey);
|
||||
}
|
||||
|
||||
private Argument toArgument(ReferencedEntityKey referencedEntityKey) {
|
||||
Argument argument = new Argument();
|
||||
argument.setRefEntityKey(referencedEntityKey);
|
||||
return argument;
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user