11 changed files with 365 additions and 13 deletions
@ -0,0 +1,271 @@ |
|||||
|
/** |
||||
|
* Copyright © 2016-2020 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.controller; |
||||
|
|
||||
|
import com.fasterxml.jackson.core.type.TypeReference; |
||||
|
import org.junit.After; |
||||
|
import org.junit.Assert; |
||||
|
import org.junit.Before; |
||||
|
import org.junit.Test; |
||||
|
import org.thingsboard.server.common.data.DataConstants; |
||||
|
import org.thingsboard.server.common.data.Device; |
||||
|
import org.thingsboard.server.common.data.EntityType; |
||||
|
import org.thingsboard.server.common.data.Tenant; |
||||
|
import org.thingsboard.server.common.data.User; |
||||
|
import org.thingsboard.server.common.data.id.DeviceId; |
||||
|
import org.thingsboard.server.common.data.id.EntityId; |
||||
|
import org.thingsboard.server.common.data.page.PageData; |
||||
|
import org.thingsboard.server.common.data.query.DeviceTypeFilter; |
||||
|
import org.thingsboard.server.common.data.query.EntityCountQuery; |
||||
|
import org.thingsboard.server.common.data.query.EntityData; |
||||
|
import org.thingsboard.server.common.data.query.EntityDataPageLink; |
||||
|
import org.thingsboard.server.common.data.query.EntityDataQuery; |
||||
|
import org.thingsboard.server.common.data.query.EntityDataSortOrder; |
||||
|
import org.thingsboard.server.common.data.query.EntityKey; |
||||
|
import org.thingsboard.server.common.data.query.EntityKeyType; |
||||
|
import org.thingsboard.server.common.data.query.EntityListFilter; |
||||
|
import org.thingsboard.server.common.data.query.KeyFilter; |
||||
|
import org.thingsboard.server.common.data.query.NumericFilterPredicate; |
||||
|
import org.thingsboard.server.common.data.security.Authority; |
||||
|
|
||||
|
import java.util.ArrayList; |
||||
|
import java.util.Collections; |
||||
|
import java.util.List; |
||||
|
import java.util.stream.Collectors; |
||||
|
|
||||
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; |
||||
|
|
||||
|
public abstract class BaseEntityQueryControllerTest extends AbstractControllerTest { |
||||
|
|
||||
|
private Tenant savedTenant; |
||||
|
private User tenantAdmin; |
||||
|
|
||||
|
@Before |
||||
|
public void beforeTest() throws Exception { |
||||
|
loginSysAdmin(); |
||||
|
|
||||
|
Tenant tenant = new Tenant(); |
||||
|
tenant.setTitle("My tenant"); |
||||
|
savedTenant = doPost("/api/tenant", tenant, Tenant.class); |
||||
|
Assert.assertNotNull(savedTenant); |
||||
|
|
||||
|
tenantAdmin = new User(); |
||||
|
tenantAdmin.setAuthority(Authority.TENANT_ADMIN); |
||||
|
tenantAdmin.setTenantId(savedTenant.getId()); |
||||
|
tenantAdmin.setEmail("tenant2@thingsboard.org"); |
||||
|
tenantAdmin.setFirstName("Joe"); |
||||
|
tenantAdmin.setLastName("Downs"); |
||||
|
|
||||
|
tenantAdmin = createUserAndLogin(tenantAdmin, "testPassword1"); |
||||
|
} |
||||
|
|
||||
|
@After |
||||
|
public void afterTest() throws Exception { |
||||
|
loginSysAdmin(); |
||||
|
|
||||
|
doDelete("/api/tenant/" + savedTenant.getId().getId().toString()) |
||||
|
.andExpect(status().isOk()); |
||||
|
} |
||||
|
|
||||
|
@Test |
||||
|
public void testCountEntitiesByQuery() throws Exception { |
||||
|
List<Device> devices = new ArrayList<>(); |
||||
|
for (int i = 0; i < 97; i++) { |
||||
|
Device device = new Device(); |
||||
|
device.setName("Device" + i); |
||||
|
device.setType("default"); |
||||
|
device.setLabel("testLabel" + (int) (Math.random() * 1000)); |
||||
|
devices.add(doPost("/api/device", device, Device.class)); |
||||
|
} |
||||
|
DeviceTypeFilter filter = new DeviceTypeFilter(); |
||||
|
filter.setDeviceType("default"); |
||||
|
filter.setDeviceNameFilter(""); |
||||
|
|
||||
|
EntityCountQuery countQuery = new EntityCountQuery(filter); |
||||
|
|
||||
|
Long count = doPostWithResponse("/api/entitiesQuery/count", countQuery, Long.class); |
||||
|
Assert.assertEquals(97, count.longValue()); |
||||
|
|
||||
|
filter.setDeviceType("unknown"); |
||||
|
count = doPostWithResponse("/api/entitiesQuery/count", countQuery, Long.class); |
||||
|
Assert.assertEquals(0, count.longValue()); |
||||
|
|
||||
|
filter.setDeviceType("default"); |
||||
|
filter.setDeviceNameFilter("Device1"); |
||||
|
|
||||
|
count = doPostWithResponse("/api/entitiesQuery/count", countQuery, Long.class); |
||||
|
Assert.assertEquals(11, count.longValue()); |
||||
|
|
||||
|
EntityListFilter entityListFilter = new EntityListFilter(); |
||||
|
entityListFilter.setEntityType(EntityType.DEVICE); |
||||
|
entityListFilter.setEntityList(devices.stream().map(Device::getId).map(DeviceId::toString).collect(Collectors.toList())); |
||||
|
|
||||
|
countQuery = new EntityCountQuery(entityListFilter); |
||||
|
|
||||
|
count = doPostWithResponse("/api/entitiesQuery/count", countQuery, Long.class); |
||||
|
Assert.assertEquals(97, count.longValue()); |
||||
|
} |
||||
|
|
||||
|
@Test |
||||
|
public void testSimpleFindEntityDataByQuery() throws Exception { |
||||
|
List<Device> devices = new ArrayList<>(); |
||||
|
for (int i = 0; i < 97; i++) { |
||||
|
Device device = new Device(); |
||||
|
device.setName("Device" + i); |
||||
|
device.setType("default"); |
||||
|
device.setLabel("testLabel" + (int) (Math.random() * 1000)); |
||||
|
devices.add(doPost("/api/device", device, Device.class)); |
||||
|
} |
||||
|
|
||||
|
DeviceTypeFilter filter = new DeviceTypeFilter(); |
||||
|
filter.setDeviceType("default"); |
||||
|
filter.setDeviceNameFilter(""); |
||||
|
|
||||
|
EntityDataSortOrder sortOrder = new EntityDataSortOrder( |
||||
|
new EntityKey(EntityKeyType.ENTITY_FIELD, "createdTime"), EntityDataSortOrder.Direction.ASC |
||||
|
); |
||||
|
EntityDataPageLink pageLink = new EntityDataPageLink(10, 0, null, sortOrder); |
||||
|
List<EntityKey> entityFields = Collections.singletonList(new EntityKey(EntityKeyType.ENTITY_FIELD, "name")); |
||||
|
|
||||
|
EntityDataQuery query = new EntityDataQuery(filter, pageLink, entityFields, null, null); |
||||
|
|
||||
|
PageData<EntityData> data = |
||||
|
doPostWithTypedResponse("/api/entitiesQuery/find", query, new TypeReference<PageData<EntityData>>() { |
||||
|
}); |
||||
|
|
||||
|
Assert.assertEquals(97, data.getTotalElements()); |
||||
|
Assert.assertEquals(10, data.getTotalPages()); |
||||
|
Assert.assertTrue(data.hasNext()); |
||||
|
Assert.assertEquals(10, data.getData().size()); |
||||
|
|
||||
|
List<EntityData> loadedEntities = new ArrayList<>(data.getData()); |
||||
|
while (data.hasNext()) { |
||||
|
query = query.next(); |
||||
|
data = doPostWithTypedResponse("/api/entitiesQuery/find", query, new TypeReference<PageData<EntityData>>() { |
||||
|
}); |
||||
|
loadedEntities.addAll(data.getData()); |
||||
|
} |
||||
|
Assert.assertEquals(97, loadedEntities.size()); |
||||
|
|
||||
|
List<EntityId> loadedIds = loadedEntities.stream().map(EntityData::getEntityId).collect(Collectors.toList()); |
||||
|
List<EntityId> deviceIds = devices.stream().map(Device::getId).collect(Collectors.toList()); |
||||
|
|
||||
|
Assert.assertEquals(deviceIds, loadedIds); |
||||
|
|
||||
|
List<String> loadedNames = loadedEntities.stream().map(entityData -> |
||||
|
entityData.getLatest().get(EntityKeyType.ENTITY_FIELD).get("name").getValue()).collect(Collectors.toList()); |
||||
|
List<String> deviceNames = devices.stream().map(Device::getName).collect(Collectors.toList()); |
||||
|
|
||||
|
Assert.assertEquals(deviceNames, loadedNames); |
||||
|
|
||||
|
sortOrder = new EntityDataSortOrder( |
||||
|
new EntityKey(EntityKeyType.ENTITY_FIELD, "name"), EntityDataSortOrder.Direction.DESC |
||||
|
); |
||||
|
|
||||
|
pageLink = new EntityDataPageLink(10, 0, "device1", sortOrder); |
||||
|
query = new EntityDataQuery(filter, pageLink, entityFields, null, null); |
||||
|
data = doPostWithTypedResponse("/api/entitiesQuery/find", query, new TypeReference<PageData<EntityData>>() { |
||||
|
}); |
||||
|
Assert.assertEquals(11, data.getTotalElements()); |
||||
|
Assert.assertEquals("Device19", data.getData().get(0).getLatest().get(EntityKeyType.ENTITY_FIELD).get("name").getValue()); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
@Test |
||||
|
public void testFindEntityDataByQueryWithAttributes() throws Exception { |
||||
|
|
||||
|
List<Device> devices = new ArrayList<>(); |
||||
|
List<Long> temperatures = new ArrayList<>(); |
||||
|
List<Long> highTemperatures = new ArrayList<>(); |
||||
|
for (int i=0;i<67;i++) { |
||||
|
Device device = new Device(); |
||||
|
String name = "Device"+i; |
||||
|
device.setName(name); |
||||
|
device.setType("default"); |
||||
|
device.setLabel("testLabel"+(int)(Math.random()*1000)); |
||||
|
devices.add(doPost("/api/device?accessToken="+name, device, Device.class)); |
||||
|
long temperature = (long)(Math.random()*100); |
||||
|
temperatures.add(temperature); |
||||
|
if (temperature > 45) { |
||||
|
highTemperatures.add(temperature); |
||||
|
} |
||||
|
} |
||||
|
for (int i=0;i<devices.size();i++) { |
||||
|
Device device = devices.get(i); |
||||
|
String payload = "{\"temperature\":"+temperatures.get(i)+"}"; |
||||
|
doPost("/api/plugins/telemetry/"+device.getId()+"/"+ DataConstants.SHARED_SCOPE, payload, String.class, status().isOk()); |
||||
|
} |
||||
|
Thread.sleep(1000); |
||||
|
|
||||
|
DeviceTypeFilter filter = new DeviceTypeFilter(); |
||||
|
filter.setDeviceType("default"); |
||||
|
filter.setDeviceNameFilter(""); |
||||
|
|
||||
|
EntityDataSortOrder sortOrder = new EntityDataSortOrder( |
||||
|
new EntityKey(EntityKeyType.ENTITY_FIELD, "createdTime"), EntityDataSortOrder.Direction.ASC |
||||
|
); |
||||
|
EntityDataPageLink pageLink = new EntityDataPageLink(10, 0, null, sortOrder); |
||||
|
List<EntityKey> entityFields = Collections.singletonList(new EntityKey(EntityKeyType.ENTITY_FIELD, "name")); |
||||
|
List<EntityKey> latestValues = Collections.singletonList(new EntityKey(EntityKeyType.ATTRIBUTE, "temperature")); |
||||
|
|
||||
|
EntityDataQuery query = new EntityDataQuery(filter, pageLink, entityFields, latestValues, null); |
||||
|
PageData<EntityData> data = doPostWithTypedResponse("/api/entitiesQuery/find", query, new TypeReference<PageData<EntityData>>() { |
||||
|
}); |
||||
|
|
||||
|
List<EntityData> loadedEntities = new ArrayList<>(data.getData()); |
||||
|
while (data.hasNext()) { |
||||
|
query = query.next(); |
||||
|
data = doPostWithTypedResponse("/api/entitiesQuery/find", query, new TypeReference<PageData<EntityData>>() { |
||||
|
}); |
||||
|
loadedEntities.addAll(data.getData()); |
||||
|
} |
||||
|
Assert.assertEquals(67, loadedEntities.size()); |
||||
|
|
||||
|
List<String> loadedTemperatures = loadedEntities.stream().map(entityData -> |
||||
|
entityData.getLatest().get(EntityKeyType.ATTRIBUTE).get("temperature").getValue()).collect(Collectors.toList()); |
||||
|
List<String> deviceTemperatures = temperatures.stream().map(aLong -> Long.toString(aLong)).collect(Collectors.toList()); |
||||
|
Assert.assertEquals(deviceTemperatures, loadedTemperatures); |
||||
|
|
||||
|
pageLink = new EntityDataPageLink(10, 0, null, sortOrder); |
||||
|
KeyFilter highTemperatureFilter = new KeyFilter(); |
||||
|
highTemperatureFilter.setKey(new EntityKey(EntityKeyType.ATTRIBUTE, "temperature")); |
||||
|
NumericFilterPredicate predicate = new NumericFilterPredicate(); |
||||
|
predicate.setValue(45); |
||||
|
predicate.setOperation(NumericFilterPredicate.NumericOperation.GREATER); |
||||
|
highTemperatureFilter.setPredicate(predicate); |
||||
|
List<KeyFilter> keyFilters = Collections.singletonList(highTemperatureFilter); |
||||
|
|
||||
|
query = new EntityDataQuery(filter, pageLink, entityFields, latestValues, keyFilters); |
||||
|
|
||||
|
data = doPostWithTypedResponse("/api/entitiesQuery/find", query, new TypeReference<PageData<EntityData>>() { |
||||
|
}); |
||||
|
loadedEntities = new ArrayList<>(data.getData()); |
||||
|
while (data.hasNext()) { |
||||
|
query = query.next(); |
||||
|
data = doPostWithTypedResponse("/api/entitiesQuery/find", query, new TypeReference<PageData<EntityData>>() { |
||||
|
}); |
||||
|
loadedEntities.addAll(data.getData()); |
||||
|
} |
||||
|
Assert.assertEquals(highTemperatures.size(), loadedEntities.size()); |
||||
|
|
||||
|
List<String> loadedHighTemperatures = loadedEntities.stream().map(entityData -> |
||||
|
entityData.getLatest().get(EntityKeyType.ATTRIBUTE).get("temperature").getValue()).collect(Collectors.toList()); |
||||
|
List<String> deviceHighTemperatures = highTemperatures.stream().map(aLong -> Long.toString(aLong)).collect(Collectors.toList()); |
||||
|
|
||||
|
Assert.assertEquals(deviceHighTemperatures, loadedHighTemperatures); |
||||
|
|
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,23 @@ |
|||||
|
/** |
||||
|
* Copyright © 2016-2020 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.controller.sql; |
||||
|
|
||||
|
import org.thingsboard.server.controller.BaseEntityQueryControllerTest; |
||||
|
import org.thingsboard.server.dao.service.DaoSqlTest; |
||||
|
|
||||
|
@DaoSqlTest |
||||
|
public class EntityQueryControllerSqlTest extends BaseEntityQueryControllerTest { |
||||
|
} |
||||
Loading…
Reference in new issue