diff --git a/bundles/org.openhab.binding.boschshc/src/main/java/org/openhab/binding/boschshc/internal/discovery/ThingDiscoveryService.java b/bundles/org.openhab.binding.boschshc/src/main/java/org/openhab/binding/boschshc/internal/discovery/ThingDiscoveryService.java
index bf4d0f7cd4129..cedba1759e92e 100644
--- a/bundles/org.openhab.binding.boschshc/src/main/java/org/openhab/binding/boschshc/internal/discovery/ThingDiscoveryService.java
+++ b/bundles/org.openhab.binding.boschshc/src/main/java/org/openhab/binding/boschshc/internal/discovery/ThingDiscoveryService.java
@@ -18,6 +18,7 @@
import java.util.Map;
import java.util.Objects;
import java.util.Set;
+import java.util.concurrent.ScheduledExecutorService;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
@@ -117,6 +118,15 @@ public ThingDiscoveryService() {
super(BridgeHandler.class, SUPPORTED_THING_TYPES, SEARCH_TIME);
}
+ /**
+ * Constructor for tests only.
+ *
+ * @param scheduler the {@link ScheduledExecutorService} to use during testing.
+ */
+ ThingDiscoveryService(ScheduledExecutorService scheduler) {
+ super(scheduler, BridgeHandler.class, SUPPORTED_THING_TYPES, SEARCH_TIME, true, null, null);
+ }
+
@Override
public void initialize() {
logger.trace("initialize");
@@ -255,7 +265,7 @@ protected void addDevice(Device device, String roomName) {
* Translates a Bosch device ID to an openHAB-compliant thing ID.
*
* Characters that are not allowed in thing IDs are replaced by underscores.
- *
+ *
* @param deviceId the Bosch device ID
* @return the translated openHAB-compliant thing ID
*/
diff --git a/bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/devices/bridge/LongPollingTest.java b/bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/devices/bridge/LongPollingTest.java
index da303f6cdb592..ab4ed1d78d535 100644
--- a/bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/devices/bridge/LongPollingTest.java
+++ b/bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/devices/bridge/LongPollingTest.java
@@ -21,21 +21,12 @@
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
-import java.util.Collections;
-import java.util.List;
-import java.util.concurrent.AbstractExecutorService;
-import java.util.concurrent.Callable;
-import java.util.concurrent.Delayed;
import java.util.concurrent.ExecutionException;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.ScheduledFuture;
-import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.function.Consumer;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.jetty.client.api.Request;
import org.eclipse.jetty.client.api.Response;
import org.eclipse.jetty.client.api.Response.CompleteListener;
@@ -58,6 +49,7 @@
import org.openhab.binding.boschshc.internal.exceptions.BoschSHCException;
import org.openhab.binding.boschshc.internal.exceptions.LongPollingFailedException;
import org.openhab.binding.boschshc.internal.tests.common.CommonTestUtils;
+import org.openhab.core.util.SameThreadExecutorService;
import com.google.gson.JsonObject;
import com.google.gson.JsonSyntaxException;
@@ -72,131 +64,6 @@
@ExtendWith(MockitoExtension.class)
class LongPollingTest {
- /**
- * A dummy implementation of {@link ScheduledFuture}.
- *
- * This is required because we can not return null in the executor service test implementation (see
- * below).
- *
- * @author David Pace - Initial contribution
- *
- * @param The result type returned by this Future
- */
- private static class NullScheduledFuture implements ScheduledFuture {
-
- @Override
- public long getDelay(@Nullable TimeUnit unit) {
- return 0;
- }
-
- @Override
- public int compareTo(@Nullable Delayed o) {
- return 0;
- }
-
- @Override
- public boolean cancel(boolean mayInterruptIfRunning) {
- return false;
- }
-
- @Override
- public boolean isCancelled() {
- return false;
- }
-
- @Override
- public boolean isDone() {
- return false;
- }
-
- @Override
- public T get() throws InterruptedException, ExecutionException {
- return null;
- }
-
- @Override
- public T get(long timeout, @Nullable TimeUnit unit)
- throws InterruptedException, ExecutionException, TimeoutException {
- return null;
- }
- }
-
- /**
- * Executor service implementation that runs all runnables in the same thread in order to enable deterministic
- * testing.
- *
- * @author David Pace - Initial contribution
- *
- */
- private static class SameThreadExecutorService extends AbstractExecutorService implements ScheduledExecutorService {
-
- private volatile boolean terminated;
-
- @Override
- public void shutdown() {
- terminated = true;
- }
-
- @NonNullByDefault({})
- @Override
- public List shutdownNow() {
- return Collections.emptyList();
- }
-
- @Override
- public boolean isShutdown() {
- return terminated;
- }
-
- @Override
- public boolean isTerminated() {
- return terminated;
- }
-
- @Override
- public boolean awaitTermination(long timeout, @Nullable TimeUnit unit) throws InterruptedException {
- shutdown();
- return terminated;
- }
-
- @Override
- public void execute(@Nullable Runnable command) {
- if (command != null) {
- // execute in the same thread in unit tests
- command.run();
- }
- }
-
- @Override
- public ScheduledFuture> schedule(@Nullable Runnable command, long delay, @Nullable TimeUnit unit) {
- // not used in this tests
- return new NullScheduledFuture<>();
- }
-
- @Override
- public ScheduledFuture schedule(@Nullable Callable callable, long delay, @Nullable TimeUnit unit) {
- return new NullScheduledFuture<>();
- }
-
- @Override
- public ScheduledFuture> scheduleAtFixedRate(@Nullable Runnable command, long initialDelay, long period,
- @Nullable TimeUnit unit) {
- if (command != null) {
- command.run();
- }
- return new NullScheduledFuture<>();
- }
-
- @Override
- public ScheduledFuture> scheduleWithFixedDelay(@Nullable Runnable command, long initialDelay, long delay,
- @Nullable TimeUnit unit) {
- if (command != null) {
- command.run();
- }
- return new NullScheduledFuture<>();
- }
- }
-
private @NonNullByDefault({}) LongPolling fixture;
private @NonNullByDefault({}) BoschHttpClient httpClient;
diff --git a/bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/discovery/ThingDiscoveryServiceTest.java b/bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/discovery/ThingDiscoveryServiceTest.java
index 80eec46a59969..4ada102672272 100644
--- a/bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/discovery/ThingDiscoveryServiceTest.java
+++ b/bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/discovery/ThingDiscoveryServiceTest.java
@@ -20,7 +20,6 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -47,6 +46,7 @@
import org.openhab.core.config.discovery.DiscoveryService;
import org.openhab.core.thing.Bridge;
import org.openhab.core.thing.ThingUID;
+import org.openhab.core.util.SameThreadExecutorService;
/**
* Unit tests for {@link ThingDiscoveryService}.
@@ -66,7 +66,7 @@ class ThingDiscoveryServiceTest {
@BeforeEach
void beforeEach() {
- fixture = new ThingDiscoveryService();
+ fixture = new ThingDiscoveryService(new SameThreadExecutorService());
fixture.addDiscoveryListener(discoveryListener);
fixture.setThingHandler(bridgeHandler);
}
@@ -160,7 +160,7 @@ void testAddDevices() {
fixture.addDevices(devices, emptyRooms);
// two calls for the two devices expected
- verify(discoveryListener, timeout(1000L).times(2)).thingDiscovered(any(), any());
+ verify(discoveryListener, times(2)).thingDiscovered(any(), any());
}
@Test
@@ -186,8 +186,7 @@ void testAddDevice() {
device.name = "Test Name";
fixture.addDevice(device, "TestRoom");
- verify(discoveryListener, timeout(1000L)).thingDiscovered(discoveryServiceCaptor.capture(),
- discoveryResultCaptor.capture());
+ verify(discoveryListener).thingDiscovered(discoveryServiceCaptor.capture(), discoveryResultCaptor.capture());
assertThat(discoveryServiceCaptor.getValue().getClass(), is(ThingDiscoveryService.class));
DiscoveryResult result = discoveryResultCaptor.getValue();
@@ -228,8 +227,7 @@ private void assertDeviceNiceName(String deviceName, String roomName, String exp
device.id = "testDevice:ID";
device.name = deviceName;
fixture.addDevice(device, roomName);
- verify(discoveryListener, timeout(1000L)).thingDiscovered(discoveryServiceCaptor.capture(),
- discoveryResultCaptor.capture());
+ verify(discoveryListener).thingDiscovered(discoveryServiceCaptor.capture(), discoveryResultCaptor.capture());
assertThat(discoveryServiceCaptor.getValue().getClass(), is(ThingDiscoveryService.class));
DiscoveryResult result = discoveryResultCaptor.getValue();
assertThat(result.getLabel(), is(expectedNiceName));
diff --git a/bundles/org.openhab.binding.deconz/src/main/java/org/openhab/binding/deconz/internal/discovery/ThingDiscoveryService.java b/bundles/org.openhab.binding.deconz/src/main/java/org/openhab/binding/deconz/internal/discovery/ThingDiscoveryService.java
index 96b18c7a834e6..10e5066765458 100644
--- a/bundles/org.openhab.binding.deconz/src/main/java/org/openhab/binding/deconz/internal/discovery/ThingDiscoveryService.java
+++ b/bundles/org.openhab.binding.deconz/src/main/java/org/openhab/binding/deconz/internal/discovery/ThingDiscoveryService.java
@@ -18,6 +18,7 @@
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
+import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
@@ -72,6 +73,15 @@ public ThingDiscoveryService() {
super(DeconzBridgeHandler.class, SUPPORTED_THING_TYPES_UIDS, 30);
}
+ /**
+ * Constructor for tests only.
+ *
+ * @param scheduler the {@link ScheduledExecutorService} to use during testing.
+ */
+ public ThingDiscoveryService(ScheduledExecutorService scheduler) {
+ super(scheduler, DeconzBridgeHandler.class, SUPPORTED_THING_TYPES_UIDS, 30, true, null, null);
+ }
+
@Override
public void startScan() {
thingHandler.getBridgeFullState().thenAccept(fullState -> {
diff --git a/bundles/org.openhab.binding.deconz/src/test/java/org/openhab/binding/deconz/DeconzTest.java b/bundles/org.openhab.binding.deconz/src/test/java/org/openhab/binding/deconz/DeconzTest.java
index 269a1ff5bae72..a9db97cd58c02 100644
--- a/bundles/org.openhab.binding.deconz/src/test/java/org/openhab/binding/deconz/DeconzTest.java
+++ b/bundles/org.openhab.binding.deconz/src/test/java/org/openhab/binding/deconz/DeconzTest.java
@@ -14,7 +14,7 @@
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.*;
+import static org.mockito.Mockito.times;
import java.io.IOException;
import java.io.InputStream;
@@ -51,6 +51,7 @@
import org.openhab.core.library.types.DateTimeType;
import org.openhab.core.thing.Bridge;
import org.openhab.core.thing.ThingUID;
+import org.openhab.core.util.SameThreadExecutorService;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
@@ -92,13 +93,13 @@ public void discoveryTest() throws IOException {
Mockito.doAnswer(answer -> CompletableFuture.completedFuture(Optional.of(bridgeFullState))).when(bridgeHandler)
.getBridgeFullState();
- ThingDiscoveryService discoveryService = new ThingDiscoveryService();
+ ThingDiscoveryService discoveryService = new ThingDiscoveryService(new SameThreadExecutorService());
discoveryService.modified(Map.of(DiscoveryService.CONFIG_PROPERTY_BACKGROUND_DISCOVERY, false));
discoveryService.setThingHandler(bridgeHandler);
discoveryService.initialize();
discoveryService.addDiscoveryListener(discoveryListener);
discoveryService.startScan();
- Mockito.verify(discoveryListener, timeout(1000L).times(20)).thingDiscovered(any(), any());
+ Mockito.verify(discoveryListener, times(20)).thingDiscovered(any(), any());
}
public static T getObjectFromJson(String filename, Class clazz, Gson gson) throws IOException {
diff --git a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/discovery/HomematicDeviceDiscoveryService.java b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/discovery/HomematicDeviceDiscoveryService.java
index fc92c1eb1f9f3..a3f17fde9d470 100644
--- a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/discovery/HomematicDeviceDiscoveryService.java
+++ b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/discovery/HomematicDeviceDiscoveryService.java
@@ -17,6 +17,7 @@
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
+import java.util.concurrent.ScheduledExecutorService;
import org.eclipse.jdt.annotation.NonNull;
import org.openhab.binding.homematic.internal.common.HomematicConfig;
@@ -55,6 +56,11 @@ public HomematicDeviceDiscoveryService() {
super(HomematicBridgeHandler.class, Set.of(new ThingTypeUID(BINDING_ID, "-")), DISCOVER_TIMEOUT_SECONDS, false);
}
+ HomematicDeviceDiscoveryService(ScheduledExecutorService scheduler) {
+ super(scheduler, HomematicBridgeHandler.class, Set.of(new ThingTypeUID(BINDING_ID, "-")),
+ DISCOVER_TIMEOUT_SECONDS, false, null, null);
+ }
+
@Override
public void initialize() {
thingHandler.setDiscoveryService(this);
@@ -149,7 +155,7 @@ private void waitForInstallModeFinished(int timeout) throws InterruptedException
private void waitForLoadDevicesFinished() throws InterruptedException, ExecutionException {
Future> loadFuture;
if ((loadFuture = loadDevicesFuture) != null) {
- loadFuture.get(); // TODO: Bug - doesn't always complete
+ loadFuture.get();
}
}
diff --git a/bundles/org.openhab.binding.homematic/src/test/java/org/openhab/binding/homematic/internal/discovery/HomematicDeviceDiscoveryServiceTest.java b/bundles/org.openhab.binding.homematic/src/test/java/org/openhab/binding/homematic/internal/discovery/HomematicDeviceDiscoveryServiceTest.java
index a218dfd703492..7a60d104d8d5d 100644
--- a/bundles/org.openhab.binding.homematic/src/test/java/org/openhab/binding/homematic/internal/discovery/HomematicDeviceDiscoveryServiceTest.java
+++ b/bundles/org.openhab.binding.homematic/src/test/java/org/openhab/binding/homematic/internal/discovery/HomematicDeviceDiscoveryServiceTest.java
@@ -22,7 +22,6 @@
import java.io.IOException;
import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.openhab.binding.homematic.internal.communicator.HomematicGateway;
import org.openhab.binding.homematic.internal.handler.HomematicBridgeHandler;
@@ -35,6 +34,7 @@
import org.openhab.core.thing.ThingStatus;
import org.openhab.core.thing.ThingStatusDetail;
import org.openhab.core.thing.ThingStatusInfo;
+import org.openhab.core.util.SameThreadExecutorService;
/**
* Tests for {@link HomematicDeviceDiscoveryServiceTest}.
@@ -50,7 +50,7 @@ public class HomematicDeviceDiscoveryServiceTest extends JavaTest {
@BeforeEach
public void setup() throws IOException {
this.homematicBridgeHandler = mockHomematicBridgeHandler();
- this.homematicDeviceDiscoveryService = new HomematicDeviceDiscoveryService();
+ this.homematicDeviceDiscoveryService = new HomematicDeviceDiscoveryService(new SameThreadExecutorService());
this.homematicDeviceDiscoveryService.setThingHandler(homematicBridgeHandler);
}
@@ -79,7 +79,6 @@ private HomematicTypeGenerator mockHomematicTypeGenerator() {
return mock(HomematicTypeGenerator.class);
}
- @Disabled
@Test
public void testDiscoveryResultIsReportedForNewDevice() {
SimpleDiscoveryListener discoveryListener = new SimpleDiscoveryListener();
@@ -92,7 +91,6 @@ public void testDiscoveryResultIsReportedForNewDevice() {
discoveryResultMatchesHmDevice(discoveryListener.discoveredResults.element(), hmDevice);
}
- @Disabled
@Test
public void testDevicesAreLoadedFromBridgeDuringDiscovery() throws IOException {
startScanAndWaitForLoadedDevices();
@@ -100,7 +98,6 @@ public void testDevicesAreLoadedFromBridgeDuringDiscovery() throws IOException {
verify(homematicBridgeHandler.getGateway()).loadAllDeviceMetadata();
}
- @Disabled
@Test
public void testInstallModeIsNotActiveDuringInitialDiscovery() throws IOException {
startScanAndWaitForLoadedDevices();
@@ -108,7 +105,6 @@ public void testInstallModeIsNotActiveDuringInitialDiscovery() throws IOExceptio
verify(homematicBridgeHandler.getGateway(), never()).setInstallMode(eq(true), anyInt());
}
- @Disabled
@Test
public void testInstallModeIsActiveDuringSubsequentDiscovery() throws IOException {
homematicBridgeHandler.getThing()
@@ -116,26 +112,23 @@ public void testInstallModeIsActiveDuringSubsequentDiscovery() throws IOExceptio
startScanAndWaitForLoadedDevices();
- verify(homematicBridgeHandler.getGateway(), after(500L)).setInstallMode(true, 60);
+ verify(homematicBridgeHandler.getGateway()).setInstallMode(true, 60);
}
- @Disabled
@Test
- public void testStoppingDiscoveryDisablesInstallMode() throws IOException, InterruptedException {
+ public void testStoppingDiscoveryDisablesInstallMode() throws IOException {
homematicBridgeHandler.getThing()
.setStatusInfo(new ThingStatusInfo(ThingStatus.ONLINE, ThingStatusDetail.NONE, ""));
homematicDeviceDiscoveryService.startScan();
- Thread.sleep(500L);
-
homematicDeviceDiscoveryService.stopScan();
- verify(homematicBridgeHandler.getGateway(), after(500L)).setInstallMode(false, 0);
+ verify(homematicBridgeHandler.getGateway()).setInstallMode(false, 0);
}
private void startScanAndWaitForLoadedDevices() {
homematicDeviceDiscoveryService.startScan();
- waitForAssert(() -> verify(homematicBridgeHandler, after(500L)).setOfflineStatus(), 1000, 50);
+ waitForAssert(() -> verify(homematicBridgeHandler).setOfflineStatus(), 1000, 50);
}
private void discoveryResultMatchesHmDevice(DiscoveryResult result, HmDevice device) {
diff --git a/bundles/org.openhab.binding.mspa/src/main/java/org/openhab/binding/mspa/internal/discovery/MSpaDiscoveryService.java b/bundles/org.openhab.binding.mspa/src/main/java/org/openhab/binding/mspa/internal/discovery/MSpaDiscoveryService.java
index 3c3ed61ae3ba8..8735b101ee5de 100644
--- a/bundles/org.openhab.binding.mspa/src/main/java/org/openhab/binding/mspa/internal/discovery/MSpaDiscoveryService.java
+++ b/bundles/org.openhab.binding.mspa/src/main/java/org/openhab/binding/mspa/internal/discovery/MSpaDiscoveryService.java
@@ -18,6 +18,7 @@
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.concurrent.ScheduledExecutorService;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.binding.mspa.internal.MSpaConstants;
@@ -44,6 +45,15 @@ public MSpaDiscoveryService() {
super(Set.of(MSpaConstants.THING_TYPE_POOL), 0, false);
}
+ /**
+ * Constructor for tests only.
+ *
+ * @param scheduler the {@link ScheduledExecutorService} to use during testing.
+ */
+ public MSpaDiscoveryService(ScheduledExecutorService scheduler) {
+ super(scheduler, Set.of(MSpaConstants.THING_TYPE_POOL), 0, false, null, null);
+ }
+
@Override
protected void startScan() {
accountList.forEach(account -> {
diff --git a/bundles/org.openhab.binding.mspa/src/test/java/org/openhab/binding/mspa/TestMessages.java b/bundles/org.openhab.binding.mspa/src/test/java/org/openhab/binding/mspa/TestMessages.java
index 524af41831a33..d2676f7af8399 100644
--- a/bundles/org.openhab.binding.mspa/src/test/java/org/openhab/binding/mspa/TestMessages.java
+++ b/bundles/org.openhab.binding.mspa/src/test/java/org/openhab/binding/mspa/TestMessages.java
@@ -47,6 +47,7 @@
import org.openhab.core.thing.internal.BridgeImpl;
import org.openhab.core.thing.internal.ThingImpl;
import org.openhab.core.types.State;
+import org.openhab.core.util.SameThreadExecutorService;
/**
* {@link TestMessages} tests some generic use cases
@@ -87,10 +88,10 @@ void testToken() {
}
@Test
- void testDiscovery() throws InterruptedException {
+ void testDiscovery() {
Bridge thing = new BridgeImpl(THING_TYPE_OWNER_ACCOUNT, new ThingUID("mspa", "account"));
Map configMap = new HashMap<>();
- MSpaDiscoveryService discovery = new MSpaDiscoveryService();
+ MSpaDiscoveryService discovery = new MSpaDiscoveryService(new SameThreadExecutorService());
DiscoveryListenerMock discoveryListener = new DiscoveryListenerMock();
discovery.addDiscoveryListener(discoveryListener);
configMap.put("email", "a@b.c");
@@ -102,7 +103,6 @@ void testDiscovery() throws InterruptedException {
try {
String content = new String(Files.readAllBytes(Paths.get(fileName)));
account.decodeDevices(content);
- Thread.sleep(500L);
List results = discoveryListener.getResults();
assertEquals(1, results.size(), "Number of discovery results");
DiscoveryResult result = results.get(0);
diff --git a/bundles/org.openhab.binding.network/src/test/java/org/openhab/binding/network/internal/PresenceDetectionTest.java b/bundles/org.openhab.binding.network/src/test/java/org/openhab/binding/network/internal/PresenceDetectionTest.java
index c38ee49461f87..8aab5692db5ed 100644
--- a/bundles/org.openhab.binding.network/src/test/java/org/openhab/binding/network/internal/PresenceDetectionTest.java
+++ b/bundles/org.openhab.binding.network/src/test/java/org/openhab/binding/network/internal/PresenceDetectionTest.java
@@ -21,9 +21,6 @@
import java.io.IOException;
import java.time.Duration;
import java.util.Set;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
import java.util.function.Consumer;
import org.eclipse.jdt.annotation.NonNullByDefault;
@@ -40,6 +37,7 @@
import org.openhab.binding.network.internal.utils.NetworkUtils.ArpPingUtilEnum;
import org.openhab.binding.network.internal.utils.NetworkUtils.IpPingMethodEnum;
import org.openhab.binding.network.internal.utils.PingResult;
+import org.openhab.core.util.SameThreadExecutorService;
/**
* Tests cases for {@see PresenceDetectionValue}
@@ -55,9 +53,6 @@ public class PresenceDetectionTest {
private @NonNullByDefault({}) PresenceDetection asyncSubject;
private @Mock @NonNullByDefault({}) Consumer callback;
- private @Mock @NonNullByDefault({}) ExecutorService detectionExecutorService;
- private @Mock @NonNullByDefault({}) ExecutorService waitForResultExecutorService;
- private @Mock @NonNullByDefault({}) ScheduledExecutorService scheduledExecutorService;
private @Mock @NonNullByDefault({}) PresenceDetectionListener listener;
private @Mock @NonNullByDefault({}) NetworkUtils networkUtils;
@@ -81,7 +76,7 @@ public void setUp() {
subject.setUseArpPing(true, "arping", ArpPingUtilEnum.IPUTILS_ARPING);
subject.setUseIcmpPing(true);
- asyncSubject = spy(new PresenceDetection(listener, Duration.ofSeconds(2), Executors.newSingleThreadExecutor()));
+ asyncSubject = spy(new PresenceDetection(listener, Duration.ofSeconds(2), new SameThreadExecutorService()));
asyncSubject.networkUtils = networkUtils;
asyncSubject.setHostname("127.0.0.1");
@@ -174,7 +169,6 @@ public void cacheTest() throws InterruptedException, IOException {
// Get value will issue a PresenceDetection internally.
asyncSubject.getValue(callback);
verify(asyncSubject).performPresenceDetection();
- Thread.sleep(200); // give it some time to execute
// Callback should be called once with the result (since we use direct executor)
verify(callback, times(1)).accept(any());
@@ -182,9 +176,9 @@ public void cacheTest() throws InterruptedException, IOException {
asyncSubject.getValue(callback);
verify(callback, times(2)).accept(any());
- // Invalidate value, we should not get a new callback immediately again
+ // Invalidate value, we should get a new callback immediately
asyncSubject.cache.invalidateValue();
asyncSubject.getValue(callback);
- verify(callback, times(2)).accept(any());
+ verify(callback, times(3)).accept(any());
}
}
diff --git a/bundles/org.openhab.binding.salus/src/main/java/org/openhab/binding/salus/internal/discovery/SalusDiscovery.java b/bundles/org.openhab.binding.salus/src/main/java/org/openhab/binding/salus/internal/discovery/SalusDiscovery.java
index 18254c87dbb3c..512d2461488f7 100644
--- a/bundles/org.openhab.binding.salus/src/main/java/org/openhab/binding/salus/internal/discovery/SalusDiscovery.java
+++ b/bundles/org.openhab.binding.salus/src/main/java/org/openhab/binding/salus/internal/discovery/SalusDiscovery.java
@@ -17,6 +17,7 @@
import java.util.Locale;
import java.util.Map;
+import java.util.concurrent.ScheduledExecutorService;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.binding.salus.internal.handler.CloudApi;
@@ -46,6 +47,18 @@ public SalusDiscovery(CloudApi cloudApi, ThingUID bridgeUid) throws IllegalArgum
this.bridgeUid = bridgeUid;
}
+ /**
+ * Constructor for tests only.
+ *
+ * @param scheduler the {@link ScheduledExecutorService} to use during testing.
+ */
+ SalusDiscovery(ScheduledExecutorService scheduler, CloudApi cloudApi, ThingUID bridgeUid)
+ throws IllegalArgumentException {
+ super(scheduler, SUPPORTED_THING_TYPES_UIDS, 10, true, null, null);
+ this.cloudApi = cloudApi;
+ this.bridgeUid = bridgeUid;
+ }
+
@Override
protected void startScan() {
try {
diff --git a/bundles/org.openhab.binding.salus/src/test/java/org/openhab/binding/salus/internal/discovery/SalusDiscoveryTest.java b/bundles/org.openhab.binding.salus/src/test/java/org/openhab/binding/salus/internal/discovery/SalusDiscoveryTest.java
index cff407c941231..eff9a720a405c 100644
--- a/bundles/org.openhab.binding.salus/src/test/java/org/openhab/binding/salus/internal/discovery/SalusDiscoveryTest.java
+++ b/bundles/org.openhab.binding.salus/src/test/java/org/openhab/binding/salus/internal/discovery/SalusDiscoveryTest.java
@@ -28,7 +28,6 @@
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
-import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.openhab.binding.salus.internal.handler.CloudApi;
@@ -36,6 +35,7 @@
import org.openhab.binding.salus.internal.rest.exceptions.SalusApiException;
import org.openhab.core.config.discovery.DiscoveryListener;
import org.openhab.core.thing.ThingUID;
+import org.openhab.core.util.SameThreadExecutorService;
/**
* @author Martin GrzeĊlowski - Initial contribution
@@ -43,14 +43,13 @@
@NonNullByDefault
public class SalusDiscoveryTest {
- @Disabled
@Test
@DisplayName("Method filters out disconnected devices and adds connected devices as things using addThing method")
void testFiltersOutDisconnectedDevicesAndAddsConnectedDevicesAsThings() throws Exception {
// Given
var cloudApi = mock(CloudApi.class);
var bridgeUid = new ThingUID("salus", "salus-device", "boo");
- var discoveryService = new SalusDiscovery(cloudApi, bridgeUid);
+ var discoveryService = new SalusDiscovery(new SameThreadExecutorService(), cloudApi, bridgeUid);
var discoveryListener = mock(DiscoveryListener.class);
discoveryService.addDiscoveryListener(discoveryListener);
var device1 = randomDevice(true);
@@ -76,14 +75,13 @@ void testFiltersOutDisconnectedDevicesAndAddsConnectedDevicesAsThings() throws E
argThat(discoveryResult -> discoveryResult.getLabel().equals(device4.name())));
}
- @Disabled
@Test
@DisplayName("Cloud API throws an exception during device retrieval, method logs the error")
void testLogsErrorWhenCloudApiThrowsException() throws Exception {
// Given
var cloudApi = mock(CloudApi.class);
var bridgeUid = mock(ThingUID.class);
- var discoveryService = new SalusDiscovery(cloudApi, bridgeUid);
+ var discoveryService = new SalusDiscovery(new SameThreadExecutorService(), cloudApi, bridgeUid);
given(cloudApi.findDevices()).willThrow(new SalusApiException("API error"));
diff --git a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/discovery/SatelDeviceDiscoveryService.java b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/discovery/SatelDeviceDiscoveryService.java
index 4f1c039adfdb1..b2114b3c9f2f4 100644
--- a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/discovery/SatelDeviceDiscoveryService.java
+++ b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/discovery/SatelDeviceDiscoveryService.java
@@ -20,6 +20,7 @@
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
+import java.util.concurrent.ScheduledExecutorService;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -68,6 +69,18 @@ public SatelDeviceDiscoveryService(SatelBridgeHandler bridgeHandler,
this.thingTypeProvider = thingTypeProvider;
}
+ /**
+ * Constructor for tests only.
+ *
+ * @param scheduler the {@link ScheduledExecutorService} to use during testing.
+ */
+ SatelDeviceDiscoveryService(ScheduledExecutorService scheduler, SatelBridgeHandler bridgeHandler,
+ Function thingTypeProvider) {
+ super(SUPPORTED_THING_TYPES, 60, false);
+ this.bridgeHandler = bridgeHandler;
+ this.thingTypeProvider = thingTypeProvider;
+ }
+
@Override
protected void startScan() {
scanStopped = false;
diff --git a/bundles/org.openhab.binding.satel/src/test/java/org/openhab/binding/satel/internal/discovery/SatelDeviceDiscoveryServiceTest.java b/bundles/org.openhab.binding.satel/src/test/java/org/openhab/binding/satel/internal/discovery/SatelDeviceDiscoveryServiceTest.java
index d6972ba27c053..bc46dca980c3c 100644
--- a/bundles/org.openhab.binding.satel/src/test/java/org/openhab/binding/satel/internal/discovery/SatelDeviceDiscoveryServiceTest.java
+++ b/bundles/org.openhab.binding.satel/src/test/java/org/openhab/binding/satel/internal/discovery/SatelDeviceDiscoveryServiceTest.java
@@ -22,16 +22,15 @@
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
-import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.function.Function;
-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.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.openhab.binding.satel.internal.command.ReadDeviceInfoCommand;
@@ -39,10 +38,12 @@
import org.openhab.binding.satel.internal.handler.SatelBridgeHandler;
import org.openhab.binding.satel.internal.protocol.SatelMessage;
import org.openhab.binding.satel.internal.types.IntegraType;
+import org.openhab.core.config.discovery.DiscoveryListener;
import org.openhab.core.config.discovery.DiscoveryResult;
import org.openhab.core.thing.ThingTypeUID;
import org.openhab.core.thing.internal.BridgeImpl;
import org.openhab.core.thing.type.ThingType;
+import org.openhab.core.util.SameThreadExecutorService;
/**
* @author Krzysztof Goworek - Initial contribution
@@ -61,27 +62,20 @@ class SatelDeviceDiscoveryServiceTest {
@Mock
private EventDispatcher eventDispatcher;
- private final List results = new ArrayList<>();
+ @Mock
+ private DiscoveryListener listener;
+
+ @Mock
+ private SameThreadExecutorService scheduler;
+ @InjectMocks
private SatelDeviceDiscoveryService testSubject;
@BeforeEach
void setUp() {
when(bridgeHandler.getIntegraType()).thenReturn(IntegraType.I24);
when(bridgeHandler.getEncoding()).thenReturn(bridgeEncoding);
-
- testSubject = new SatelDeviceDiscoveryService(bridgeHandler, thingTypeProvider) {
- @NonNullByDefault
- @Override
- protected void thingDiscovered(DiscoveryResult discoveryResult) {
- results.add(discoveryResult);
- }
- };
- }
-
- @AfterEach
- void tearDown() {
- results.clear();
+ testSubject.addDiscoveryListener(listener);
}
@Test
@@ -90,7 +84,7 @@ void startScanShouldNotAddAnyThingWhenBridgeIsNotInitialized() {
testSubject.startScan();
- assertEquals(0, results.size());
+ verifyNoInteractions(listener);
}
@Test
@@ -102,6 +96,10 @@ void startScanShouldAddVirtualThingsWhenBridgeIsInitialized() {
testSubject.startScan();
+ ArgumentCaptor resultCaptor = ArgumentCaptor.forClass(DiscoveryResult.class);
+ verify(listener, atLeastOnce()).thingDiscovered(any(), resultCaptor.capture());
+ List results = resultCaptor.getAllValues();
+
assertEquals(2, results.size());
assertEquals(THING_TYPE_SYSTEM, results.get(0).getThingTypeUID());
assertEquals(THING_TYPE_EVENTLOG, results.get(1).getThingTypeUID());
@@ -113,7 +111,7 @@ void startScanShouldContinueWhenFailureOccurred() {
testSubject.startScan();
- assertEquals(0, results.size());
+ verifyNoInteractions(listener);
verify(bridgeHandler, times(52)).sendCommand(any(), eq(false));
}
@@ -125,6 +123,9 @@ void startScanShouldAddAllDevices() {
testSubject.startScan();
+ ArgumentCaptor resultCaptor = ArgumentCaptor.forClass(DiscoveryResult.class);
+ verify(listener, atLeastOnce()).thingDiscovered(any(), resultCaptor.capture());
+ List results = resultCaptor.getAllValues();
assertEquals(4,
results.stream().filter(result -> THING_TYPE_PARTITION.equals(result.getThingTypeUID())).count());
assertEquals(24, results.stream().filter(result -> THING_TYPE_ZONE.equals(result.getThingTypeUID())).count());
@@ -145,10 +146,12 @@ void startScanShouldAddShutters() {
testSubject.startScan();
- List shutterResults = results.stream()
+ ArgumentCaptor resultCaptor = ArgumentCaptor.forClass(DiscoveryResult.class);
+ verify(listener, atLeastOnce()).thingDiscovered(any(), resultCaptor.capture());
+ List results = resultCaptor.getAllValues().stream()
.filter(result -> THING_TYPE_SHUTTER.equals(result.getThingTypeUID())).toList();
- assertEquals(24, shutterResults.size());
- for (DiscoveryResult result : shutterResults) {
+ assertEquals(24, results.size());
+ for (DiscoveryResult result : results) {
assertEquals("Device", result.getLabel());
assertEquals(bridge.getUID(), result.getBridgeUID());
assertEquals(2, result.getProperties().size());
@@ -162,6 +165,9 @@ void startScanShouldSkipUnusedOutput() {
testSubject.startScan();
+ ArgumentCaptor resultCaptor = ArgumentCaptor.forClass(DiscoveryResult.class);
+ verify(listener, atLeastOnce()).thingDiscovered(any(), resultCaptor.capture());
+ List results = resultCaptor.getAllValues();
assertEquals(0, results.stream().filter(result -> THING_TYPE_OUTPUT.equals(result.getThingTypeUID())).count());
assertEquals(0, results.stream().filter(result -> THING_TYPE_SHUTTER.equals(result.getThingTypeUID())).count());
}
@@ -173,6 +179,9 @@ void startScanShouldSkipSecondShutterOutput() {
testSubject.startScan();
+ ArgumentCaptor resultCaptor = ArgumentCaptor.forClass(DiscoveryResult.class);
+ verify(listener, atLeastOnce()).thingDiscovered(any(), resultCaptor.capture());
+ List results = resultCaptor.getAllValues();
assertEquals(0, results.stream().filter(result -> THING_TYPE_OUTPUT.equals(result.getThingTypeUID())).count());
assertEquals(0, results.stream().filter(result -> THING_TYPE_SHUTTER.equals(result.getThingTypeUID())).count());
}
@@ -198,7 +207,7 @@ void stopScanShouldSkipDiscovery() throws InterruptedException {
thread.join();
verifyNoMoreInteractions(bridgeHandler);
- assertEquals(0, results.size());
+ verifyNoInteractions(listener);
}
private void setUpCommandResponse(int deviceKind) {
diff --git a/bundles/org.openhab.binding.tplinksmarthome/src/main/java/org/openhab/binding/tplinksmarthome/internal/TPLinkSmartHomeDiscoveryService.java b/bundles/org.openhab.binding.tplinksmarthome/src/main/java/org/openhab/binding/tplinksmarthome/internal/TPLinkSmartHomeDiscoveryService.java
index 6772dd9f78f6c..1dbd79dbe85e2 100644
--- a/bundles/org.openhab.binding.tplinksmarthome/src/main/java/org/openhab/binding/tplinksmarthome/internal/TPLinkSmartHomeDiscoveryService.java
+++ b/bundles/org.openhab.binding.tplinksmarthome/src/main/java/org/openhab/binding/tplinksmarthome/internal/TPLinkSmartHomeDiscoveryService.java
@@ -25,6 +25,7 @@
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
@@ -75,6 +76,19 @@ public TPLinkSmartHomeDiscoveryService() throws UnknownHostException {
Connection.TP_LINK_SMART_HOME_PORT);
}
+ /**
+ * Constructor for tests only.
+ *
+ * @param scheduler the {@link ScheduledExecutorService} to use during testing.
+ */
+ TPLinkSmartHomeDiscoveryService(ScheduledExecutorService scheduler) throws UnknownHostException {
+ super(scheduler, SUPPORTED_THING_TYPES, DISCOVERY_TIMEOUT_SECONDS, true, null, null);
+ final InetAddress broadcast = InetAddress.getByName(BROADCAST_IP);
+ final byte[] discoverbuffer = CryptUtil.encrypt(Commands.getSysinfo());
+ discoverPacket = new DatagramPacket(discoverbuffer, discoverbuffer.length, broadcast,
+ Connection.TP_LINK_SMART_HOME_PORT);
+ }
+
@Override
public @Nullable String getLastKnownIpAddress(String deviceId) {
return idInetAddressCache.get(deviceId);
diff --git a/bundles/org.openhab.binding.tplinksmarthome/src/test/java/org/openhab/binding/tplinksmarthome/internal/TPLinkSmartHomeDiscoveryServiceTest.java b/bundles/org.openhab.binding.tplinksmarthome/src/test/java/org/openhab/binding/tplinksmarthome/internal/TPLinkSmartHomeDiscoveryServiceTest.java
index a6e802357da18..e2754dd10006b 100644
--- a/bundles/org.openhab.binding.tplinksmarthome/src/test/java/org/openhab/binding/tplinksmarthome/internal/TPLinkSmartHomeDiscoveryServiceTest.java
+++ b/bundles/org.openhab.binding.tplinksmarthome/src/test/java/org/openhab/binding/tplinksmarthome/internal/TPLinkSmartHomeDiscoveryServiceTest.java
@@ -35,6 +35,7 @@
import org.openhab.binding.tplinksmarthome.internal.model.ModelTestUtil;
import org.openhab.core.config.discovery.DiscoveryListener;
import org.openhab.core.config.discovery.DiscoveryResult;
+import org.openhab.core.util.SameThreadExecutorService;
/**
* Test class for {@link TPLinkSmartHomeDiscoveryService} class.
@@ -57,7 +58,7 @@ public static List