Add REST support for deleting links and removing orphaned links (#2970)
* add link remove for item to registry Signed-off-by: Jan N. Klug <github@klug.nrw>pull/3053/head
parent
b6acaf7887
commit
ae3d7c749c
|
@ -16,6 +16,7 @@ import java.util.ArrayList;
|
|||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
@ -614,6 +615,21 @@ public class ItemResource implements RESTResource {
|
|||
return Response.ok(null, MediaType.TEXT_PLAIN).build();
|
||||
}
|
||||
|
||||
@POST
|
||||
@RolesAllowed({ Role.ADMIN })
|
||||
@Path("/metadata/purge")
|
||||
@Operation(operationId = "purgeDatabase", summary = "Remove unused/orphaned metadata.", security = {
|
||||
@SecurityRequirement(name = "oauth2", scopes = { "admin" }) }, responses = {
|
||||
@ApiResponse(responseCode = "200", description = "OK") })
|
||||
public Response purge() {
|
||||
Collection<String> itemNames = itemRegistry.stream().map(Item::getName)
|
||||
.collect(Collectors.toCollection(HashSet::new));
|
||||
|
||||
metadataRegistry.getAll().stream().filter(md -> !itemNames.contains(md.getUID().getItemName()))
|
||||
.forEach(md -> metadataRegistry.remove(md.getUID()));
|
||||
return Response.ok().build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create or Update an item by supplying an item bean.
|
||||
*
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
package org.openhab.core.io.rest.core.internal.link;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
|
@ -20,6 +21,7 @@ import javax.annotation.security.RolesAllowed;
|
|||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.DELETE;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.PUT;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
|
@ -47,6 +49,7 @@ import org.openhab.core.thing.Channel;
|
|||
import org.openhab.core.thing.ChannelUID;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.ThingRegistry;
|
||||
import org.openhab.core.thing.ThingUID;
|
||||
import org.openhab.core.thing.link.AbstractLink;
|
||||
import org.openhab.core.thing.link.ItemChannelLink;
|
||||
import org.openhab.core.thing.link.ItemChannelLinkRegistry;
|
||||
|
@ -141,6 +144,24 @@ public class ItemChannelLinkResource implements RESTResource {
|
|||
return Response.ok(new Stream2JSONInputStream(linkStream)).build();
|
||||
}
|
||||
|
||||
@DELETE
|
||||
@RolesAllowed({ Role.ADMIN })
|
||||
@Path("/{object}")
|
||||
@Operation(operationId = "removeAllLinksForObject", summary = "Delete all links that refer to an item or thing.", security = {
|
||||
@SecurityRequirement(name = "oauth2", scopes = { "admin" }) }, responses = {
|
||||
@ApiResponse(responseCode = "200", description = "OK") })
|
||||
public Response removeAllLinksForObject(
|
||||
@PathParam("object") @Parameter(description = "item name or thing UID") String object) {
|
||||
int removedLinks;
|
||||
try {
|
||||
ThingUID thingUID = new ThingUID(object);
|
||||
removedLinks = itemChannelLinkRegistry.removeLinksForThing(thingUID);
|
||||
} catch (IllegalArgumentException e) {
|
||||
removedLinks = itemChannelLinkRegistry.removeLinksForItem(object);
|
||||
}
|
||||
return Response.ok(Map.of("count", removedLinks)).build();
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("/{itemName}/{channelUID}")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
|
@ -273,6 +294,17 @@ public class ItemChannelLinkResource implements RESTResource {
|
|||
return Response.ok(null, MediaType.TEXT_PLAIN).build();
|
||||
}
|
||||
|
||||
@POST
|
||||
@RolesAllowed({ Role.ADMIN })
|
||||
@Path("/purge")
|
||||
@Operation(operationId = "purgeDatabase", summary = "Remove unused/orphaned links.", security = {
|
||||
@SecurityRequirement(name = "oauth2", scopes = { "admin" }) }, responses = {
|
||||
@ApiResponse(responseCode = "200", description = "OK") })
|
||||
public Response purge() {
|
||||
itemChannelLinkRegistry.purge();
|
||||
return Response.ok().build();
|
||||
}
|
||||
|
||||
private boolean isEditable(String linkId) {
|
||||
return managedItemChannelLinkProvider.get(linkId) != null;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
/**
|
||||
* Copyright (c) 2010-2022 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.core.io.rest.core.internal.link;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.instanceOf;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import javax.ws.rs.core.Response;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.mockito.junit.jupiter.MockitoSettings;
|
||||
import org.mockito.quality.Strictness;
|
||||
import org.openhab.core.items.ItemRegistry;
|
||||
import org.openhab.core.thing.ThingRegistry;
|
||||
import org.openhab.core.thing.ThingUID;
|
||||
import org.openhab.core.thing.link.ItemChannelLinkRegistry;
|
||||
import org.openhab.core.thing.link.ManagedItemChannelLinkProvider;
|
||||
import org.openhab.core.thing.profiles.ProfileTypeRegistry;
|
||||
import org.openhab.core.thing.type.ChannelTypeRegistry;
|
||||
|
||||
/**
|
||||
* The {@link ItemChannelLinkResourceTest} tests the {@link ItemChannelLinkResource}
|
||||
*
|
||||
* @author Jan N. Klug - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
@MockitoSettings(strictness = Strictness.LENIENT)
|
||||
public class ItemChannelLinkResourceTest {
|
||||
|
||||
private static final int EXPECTED_REMOVED_LINKS = 5;
|
||||
|
||||
private @Mock @NonNullByDefault({}) ItemRegistry itemRegistryMock;
|
||||
private @Mock @NonNullByDefault({}) ThingRegistry thingRegistryMock;
|
||||
private @Mock @NonNullByDefault({}) ChannelTypeRegistry channelTypeRegistryMock;
|
||||
private @Mock @NonNullByDefault({}) ProfileTypeRegistry profileTypeRegistryMock;
|
||||
private @Mock @NonNullByDefault({}) ItemChannelLinkRegistry itemChannelLinkRegistryMock;
|
||||
private @Mock @NonNullByDefault({}) ManagedItemChannelLinkProvider managedItemChannelLinkProviderMock;
|
||||
private @NonNullByDefault({}) ItemChannelLinkResource itemChannelLinkResource;
|
||||
|
||||
@BeforeEach
|
||||
public void setup() {
|
||||
itemChannelLinkResource = new ItemChannelLinkResource(itemRegistryMock, thingRegistryMock,
|
||||
channelTypeRegistryMock, profileTypeRegistryMock, itemChannelLinkRegistryMock,
|
||||
managedItemChannelLinkProviderMock);
|
||||
when(itemChannelLinkRegistryMock.removeLinksForItem(any())).thenReturn(EXPECTED_REMOVED_LINKS);
|
||||
when(itemChannelLinkRegistryMock.removeLinksForThing(any())).thenReturn(EXPECTED_REMOVED_LINKS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveAllLinksForItem() {
|
||||
try (Response response = itemChannelLinkResource.removeAllLinksForObject("testItem")) {
|
||||
assertThat(response.getStatus(), is(200));
|
||||
Object responseEntity = response.getEntity();
|
||||
assertThat(responseEntity, instanceOf(Map.class));
|
||||
assertThat(((Map<?, ?>) responseEntity).get("count"), is(EXPECTED_REMOVED_LINKS));
|
||||
}
|
||||
|
||||
verify(itemChannelLinkRegistryMock).removeLinksForItem(eq("testItem"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveAllLinksForThing() {
|
||||
try (Response response = itemChannelLinkResource.removeAllLinksForObject("binding:type:thing")) {
|
||||
assertThat(response.getStatus(), is(200));
|
||||
Object responseEntity = response.getEntity();
|
||||
assertThat(responseEntity, instanceOf(Map.class));
|
||||
assertThat(((Map<?, ?>) responseEntity).get("count"), is(EXPECTED_REMOVED_LINKS));
|
||||
}
|
||||
|
||||
verify(itemChannelLinkRegistryMock).removeLinksForThing(eq(new ThingUID("binding:type:thing")));
|
||||
}
|
||||
}
|
|
@ -12,16 +12,19 @@
|
|||
*/
|
||||
package org.openhab.core.thing.link;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.core.common.registry.ManagedProvider;
|
||||
import org.openhab.core.events.EventPublisher;
|
||||
import org.openhab.core.items.Item;
|
||||
import org.openhab.core.items.ItemRegistry;
|
||||
import org.openhab.core.service.ReadyService;
|
||||
import org.openhab.core.thing.Channel;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.ThingRegistry;
|
||||
|
@ -127,10 +130,50 @@ public class ItemChannelLinkRegistry extends AbstractLinkRegistry<ItemChannelLin
|
|||
super.unsetEventPublisher(eventPublisher);
|
||||
}
|
||||
|
||||
public void removeLinksForThing(final ThingUID thingUID) {
|
||||
((ManagedItemChannelLinkProvider) getManagedProvider()
|
||||
.orElseThrow(() -> new IllegalStateException("ManagedProvider is not available")))
|
||||
.removeLinksForThing(thingUID);
|
||||
/**
|
||||
* Remove all links related to a thing
|
||||
*
|
||||
* @param thingUID the UID of the thing
|
||||
* @return the number of removed links
|
||||
*/
|
||||
public int removeLinksForThing(final ThingUID thingUID) {
|
||||
ManagedItemChannelLinkProvider managedProvider = (ManagedItemChannelLinkProvider) getManagedProvider()
|
||||
.orElseThrow(() -> new IllegalStateException("ManagedProvider is not available"));
|
||||
return managedProvider.removeLinksForThing(thingUID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all links related to an item
|
||||
*
|
||||
* @param itemName the name of the item
|
||||
* @return the number of removed links
|
||||
*/
|
||||
public int removeLinksForItem(final String itemName) {
|
||||
ManagedItemChannelLinkProvider managedProvider = (ManagedItemChannelLinkProvider) getManagedProvider()
|
||||
.orElseThrow(() -> new IllegalStateException("ManagedProvider is not available"));
|
||||
return managedProvider.removeLinksForItem(itemName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all orphaned (item or channel missing) links
|
||||
*
|
||||
* @return the number of removed links
|
||||
*/
|
||||
public int purge() {
|
||||
ManagedProvider<ItemChannelLink, String> managedProvider = getManagedProvider()
|
||||
.orElseThrow(() -> new IllegalStateException("ManagedProvider is not available"));
|
||||
|
||||
Set<String> allItems = itemRegistry.stream().map(Item::getName).collect(Collectors.toSet());
|
||||
Set<ChannelUID> allChannels = thingRegistry.stream().map(Thing::getChannels).flatMap(List::stream)
|
||||
.map(Channel::getUID).collect(Collectors.toSet());
|
||||
|
||||
Set<String> toRemove = managedProvider.getAll().stream()
|
||||
.filter(link -> !allItems.contains(link.getItemName()) || !allChannels.contains(link.getLinkedUID()))
|
||||
.map(ItemChannelLink::getUID).collect(Collectors.toSet());
|
||||
|
||||
toRemove.forEach(managedProvider::remove);
|
||||
|
||||
return toRemove.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -48,12 +48,27 @@ public class ManagedItemChannelLinkProvider extends DefaultAbstractManagedProvid
|
|||
return key;
|
||||
}
|
||||
|
||||
public void removeLinksForThing(ThingUID thingUID) {
|
||||
public int removeLinksForThing(ThingUID thingUID) {
|
||||
int removedLinks = 0;
|
||||
Collection<ItemChannelLink> itemChannelLinks = getAll();
|
||||
for (ItemChannelLink itemChannelLink : itemChannelLinks) {
|
||||
if (itemChannelLink.getLinkedUID().getThingUID().equals(thingUID)) {
|
||||
this.remove(itemChannelLink.getUID());
|
||||
removedLinks++;
|
||||
}
|
||||
}
|
||||
return removedLinks;
|
||||
}
|
||||
|
||||
public int removeLinksForItem(String itemName) {
|
||||
int removedLinks = 0;
|
||||
Collection<ItemChannelLink> itemChannelLinks = getAll();
|
||||
for (ItemChannelLink itemChannelLink : itemChannelLinks) {
|
||||
if (itemChannelLink.getItemName().equals(itemName)) {
|
||||
this.remove(itemChannelLink.getUID());
|
||||
removedLinks++;
|
||||
}
|
||||
}
|
||||
return removedLinks;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,17 +12,27 @@
|
|||
*/
|
||||
package org.openhab.core.thing.link;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.hasItem;
|
||||
import static org.hamcrest.Matchers.hasSize;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Hashtable;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.openhab.core.items.ManagedItemProvider;
|
||||
import org.openhab.core.library.CoreItemFactory;
|
||||
import org.openhab.core.library.items.ColorItem;
|
||||
import org.openhab.core.test.java.JavaOSGiTest;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
import org.openhab.core.thing.ManagedThingProvider;
|
||||
|
@ -42,6 +52,12 @@ import org.osgi.service.component.ComponentContext;
|
|||
@NonNullByDefault
|
||||
public class ItemChannelLinkOSGiTest extends JavaOSGiTest {
|
||||
|
||||
private static final String BULK_BASE_THING_UID = "binding:type:thing";
|
||||
private static final String BULK_BASE_ITEM_NAME = "item";
|
||||
private static int BULK_ITEM_COUNT = 3;
|
||||
private static int BULK_THING_COUNT = 3;
|
||||
private static int BULK_CHANNEL_COUNT = 3;
|
||||
|
||||
private static final String ITEM = "item";
|
||||
private static final ThingTypeUID THING_TYPE_UID = new ThingTypeUID("binding:thing");
|
||||
private static final ThingUID THING_UID = new ThingUID(THING_TYPE_UID, "thing");
|
||||
|
@ -51,6 +67,7 @@ public class ItemChannelLinkOSGiTest extends JavaOSGiTest {
|
|||
private @NonNullByDefault({}) ManagedItemChannelLinkProvider managedItemChannelLinkProvider;
|
||||
private @NonNullByDefault({}) ItemChannelLinkRegistry itemChannelLinkRegistry;
|
||||
private @NonNullByDefault({}) ManagedThingProvider managedThingProvider;
|
||||
private @NonNullByDefault({}) ManagedItemProvider managedItemProvider;
|
||||
|
||||
@BeforeEach
|
||||
public void setup() {
|
||||
|
@ -58,6 +75,8 @@ public class ItemChannelLinkOSGiTest extends JavaOSGiTest {
|
|||
managedThingProvider = getService(ManagedThingProvider.class);
|
||||
managedThingProvider.add(ThingBuilder.create(THING_TYPE_UID, THING_UID)
|
||||
.withChannel(ChannelBuilder.create(CHANNEL_UID, CoreItemFactory.COLOR).build()).build());
|
||||
managedItemProvider = getService(ManagedItemProvider.class);
|
||||
|
||||
itemChannelLinkRegistry = getService(ItemChannelLinkRegistry.class);
|
||||
managedItemChannelLinkProvider = getService(ManagedItemChannelLinkProvider.class);
|
||||
assertNotNull(managedItemChannelLinkProvider);
|
||||
|
@ -125,8 +144,94 @@ public class ItemChannelLinkOSGiTest extends JavaOSGiTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void assertThatgetBoundThingsReturnsEmptySet() {
|
||||
public void assertThatGetBoundThingsReturnsEmptySet() {
|
||||
Set<Thing> boundThings = itemChannelLinkRegistry.getBoundThings("notExistingItem");
|
||||
assertTrue(boundThings.isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void assertThatAllLinksForItemCanBeDeleted() {
|
||||
fillRegistryForBulkTests();
|
||||
|
||||
String itemToRemove = BULK_BASE_ITEM_NAME + "_0_1_1";
|
||||
int removed = itemChannelLinkRegistry.removeLinksForItem(itemToRemove);
|
||||
assertThat(removed, is(1));
|
||||
|
||||
assertThat(itemChannelLinkRegistry.stream().map(ItemChannelLink::getItemName).collect(Collectors.toList()),
|
||||
not(hasItem(itemToRemove)));
|
||||
assertThat(itemChannelLinkRegistry.getAll(),
|
||||
hasSize(BULK_ITEM_COUNT * BULK_THING_COUNT * BULK_CHANNEL_COUNT - 1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void assertThatAllLinksForThingCanBeDeleted() {
|
||||
fillRegistryForBulkTests();
|
||||
|
||||
ThingUID thingToRemove = new ThingUID(BULK_BASE_THING_UID + "_0_0");
|
||||
int removed = itemChannelLinkRegistry.removeLinksForThing(thingToRemove);
|
||||
assertThat(removed, is(BULK_CHANNEL_COUNT));
|
||||
|
||||
assertThat(itemChannelLinkRegistry.stream().map(ItemChannelLink::getLinkedUID).map(ChannelUID::getThingUID)
|
||||
.collect(Collectors.toList()), not(hasItem(thingToRemove)));
|
||||
assertThat(itemChannelLinkRegistry.getAll(),
|
||||
hasSize((BULK_ITEM_COUNT * BULK_THING_COUNT - 1) * BULK_CHANNEL_COUNT));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void assertThatCompressOnlyRemovesInvalidLinks() {
|
||||
fillRegistryForBulkTests();
|
||||
|
||||
int expected = BULK_ITEM_COUNT * BULK_THING_COUNT * BULK_CHANNEL_COUNT;
|
||||
|
||||
int removed = itemChannelLinkRegistry.purge();
|
||||
assertThat(removed, is(0));
|
||||
assertThat(itemChannelLinkRegistry.getAll(), hasSize(expected));
|
||||
|
||||
managedItemProvider.remove(BULK_BASE_ITEM_NAME + "_0_0_0");
|
||||
removed = itemChannelLinkRegistry.purge();
|
||||
expected -= removed;
|
||||
assertThat(removed, is(1));
|
||||
assertThat(itemChannelLinkRegistry.getAll(), hasSize(expected));
|
||||
|
||||
managedThingProvider.remove(new ThingUID(BULK_BASE_THING_UID + "_1_0"));
|
||||
removed = itemChannelLinkRegistry.purge();
|
||||
expected -= removed;
|
||||
assertThat(removed, is(BULK_CHANNEL_COUNT));
|
||||
assertThat(itemChannelLinkRegistry.getAll(), hasSize(expected));
|
||||
|
||||
managedItemProvider.remove(BULK_BASE_ITEM_NAME + "_2_0_0");
|
||||
managedThingProvider.remove(new ThingUID(BULK_BASE_THING_UID + "_2_0"));
|
||||
removed = itemChannelLinkRegistry.purge();
|
||||
expected -= removed;
|
||||
assertThat(removed, is(BULK_CHANNEL_COUNT));
|
||||
assertThat(itemChannelLinkRegistry.getAll(), hasSize(expected));
|
||||
}
|
||||
|
||||
private void fillRegistryForBulkTests() {
|
||||
// clear all old links and things
|
||||
managedItemChannelLinkProvider.getAll().forEach(it -> managedItemChannelLinkProvider.remove(it.getUID()));
|
||||
managedThingProvider.getAll().forEach(it -> managedThingProvider.remove(it.getUID()));
|
||||
|
||||
for (int i = 0; i < BULK_ITEM_COUNT; i++) {
|
||||
for (int j = 0; j < BULK_THING_COUNT; j++) {
|
||||
ThingUID thingUID = new ThingUID(BULK_BASE_THING_UID + "_" + i + "_" + j);
|
||||
ThingBuilder thingBuilder = ThingBuilder.create(THING_TYPE_UID, thingUID);
|
||||
List<ItemChannelLink> links = new ArrayList<>();
|
||||
for (int k = 0; k < BULK_CHANNEL_COUNT; k++) {
|
||||
String itemName = BULK_BASE_ITEM_NAME + "_" + i + "_" + j + "_" + k;
|
||||
managedItemProvider.add(new ColorItem(itemName));
|
||||
|
||||
ChannelUID channelUID = new ChannelUID(thingUID, "channel" + k);
|
||||
thingBuilder.withChannel(ChannelBuilder.create(channelUID, CoreItemFactory.COLOR).build());
|
||||
links.add(new ItemChannelLink(itemName, channelUID));
|
||||
}
|
||||
managedThingProvider.add(thingBuilder.build());
|
||||
links.forEach(managedItemChannelLinkProvider::add);
|
||||
}
|
||||
}
|
||||
|
||||
waitForAssert(() -> assertThat(itemChannelLinkRegistry.getAll(),
|
||||
hasSize(BULK_ITEM_COUNT * BULK_THING_COUNT * BULK_CHANNEL_COUNT)));
|
||||
assertThat(managedThingProvider.getAll(), hasSize(BULK_ITEM_COUNT * BULK_THING_COUNT));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue