From e99d5e1ffc828871c20c232bdb00fdc4ea09bbac Mon Sep 17 00:00:00 2001 From: David Pace Date: Sun, 31 Mar 2024 21:19:25 +0200 Subject: [PATCH] [boschshc] Boost unit test coverage (#16500) Boosts the unit test coverage for the `boschshc` binding in `src/main/java` to 94%. Signed-off-by: David Pace Signed-off-by: Ciprian Pascu --- .../devices/bridge/BridgeHandler.java | 4 +- .../devices/bridge/ScenarioHandler.java | 2 +- .../console/BoschShcCommandExtensionTest.java | 27 +- ...stractBatteryPoweredDeviceHandlerTest.java | 22 +- .../AbstractBoschSHCDeviceHandlerTest.java | 37 ++ .../devices/AbstractBoschSHCHandlerTest.java | 24 +- .../AbstractPowerSwitchHandlerTest.java | 54 ++- ...tPowerSwitchHandlerWithPowerMeterTest.java | 25 +- .../devices/bridge/BridgeHandlerTest.java | 442 +++++++++++++++++- .../devices/bridge/LongPollingTest.java | 39 +- .../devices/bridge/ScenarioHandlerTest.java | 62 +-- .../devices/bridge/dto/ScenarioTest.java | 47 ++ .../IntrusionDetectionHandlerTest.java | 36 ++ .../ShutterControl2HandlerTest.java | 11 + .../UserStateHandlerTest.java | 53 ++- .../BridgeDiscoveryParticipantTest.java | 21 + .../discovery/ThingDiscoveryServiceTest.java | 35 ++ .../dto/UserStateServiceStateTest.java | 5 + .../tests/common/CommonTestUtils.java | 67 +++ 19 files changed, 919 insertions(+), 94 deletions(-) create mode 100644 bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/devices/bridge/dto/ScenarioTest.java create mode 100644 bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/tests/common/CommonTestUtils.java diff --git a/bundles/org.openhab.binding.boschshc/src/main/java/org/openhab/binding/boschshc/internal/devices/bridge/BridgeHandler.java b/bundles/org.openhab.binding.boschshc/src/main/java/org/openhab/binding/boschshc/internal/devices/bridge/BridgeHandler.java index 1bae6c86d13..0e277048cc1 100644 --- a/bundles/org.openhab.binding.boschshc/src/main/java/org/openhab/binding/boschshc/internal/devices/bridge/BridgeHandler.java +++ b/bundles/org.openhab.binding.boschshc/src/main/java/org/openhab/binding/boschshc/internal/devices/bridge/BridgeHandler.java @@ -657,7 +657,7 @@ public class BridgeHandler extends BaseBridgeHandler { * * @param e error during long polling */ - private void handleLongPollFailure(Throwable e) { + void handleLongPollFailure(Throwable e) { logger.warn("Long polling failed, will try to reconnect", e); @Nullable BoschHttpClient localHttpClient = this.httpClient; @@ -722,7 +722,7 @@ public class BridgeHandler extends BaseBridgeHandler { return new BoschSHCException("@text/offline.conf-error.invalid-state-id"); } else { return new BoschSHCException(String.format( - "Request for info of user-defines state %s failed with status code %d and error code %s", + "Request for info of user-defined state %s failed with status code %d and error code %s", stateId, errorResponse.statusCode, errorResponse.errorCode)); } } else { diff --git a/bundles/org.openhab.binding.boschshc/src/main/java/org/openhab/binding/boschshc/internal/devices/bridge/ScenarioHandler.java b/bundles/org.openhab.binding.boschshc/src/main/java/org/openhab/binding/boschshc/internal/devices/bridge/ScenarioHandler.java index 5d3bfe450a2..e69114041d8 100644 --- a/bundles/org.openhab.binding.boschshc/src/main/java/org/openhab/binding/boschshc/internal/devices/bridge/ScenarioHandler.java +++ b/bundles/org.openhab.binding.boschshc/src/main/java/org/openhab/binding/boschshc/internal/devices/bridge/ScenarioHandler.java @@ -96,7 +96,7 @@ public class ScenarioHandler { } } - private String prettyLogScenarios(final Scenario[] scenarios) { + String prettyLogScenarios(final Scenario[] scenarios) { final StringBuilder builder = new StringBuilder(); builder.append("["); for (Scenario scenario : scenarios) { diff --git a/bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/console/BoschShcCommandExtensionTest.java b/bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/console/BoschShcCommandExtensionTest.java index 85f7ea3a431..425c528d325 100644 --- a/bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/console/BoschShcCommandExtensionTest.java +++ b/bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/console/BoschShcCommandExtensionTest.java @@ -17,7 +17,12 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.allOf; import static org.hamcrest.Matchers.containsString; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.*; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.atLeastOnce; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; import java.io.IOException; import java.nio.file.Files; @@ -35,6 +40,8 @@ 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.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import org.openhab.binding.boschshc.internal.devices.bridge.BridgeHandler; @@ -89,6 +96,24 @@ class BoschShcCommandExtensionTest { verify(consoleMock, atLeastOnce()).print(any()); } + @ParameterizedTest + @MethodSource("org.openhab.binding.boschshc.internal.tests.common.CommonTestUtils#getBoschShcAndExecutionAndTimeoutExceptionArguments()") + void executeHandleExceptions(Exception exception) + throws InterruptedException, BoschSHCException, ExecutionException, TimeoutException { + Console console = mock(Console.class); + Bridge bridge = mock(Bridge.class); + BridgeHandler bridgeHandler = mock(BridgeHandler.class); + when(bridgeHandler.getThing()).thenReturn(bridge); + when(bridgeHandler.getPublicInformation()).thenThrow(exception); + when(bridge.getHandler()).thenReturn(bridgeHandler); + List things = List.of(bridge); + when(thingRegistry.getAll()).thenReturn(things); + + fixture.execute(new String[] { BoschShcCommandExtension.GET_BRIDGEINFO }, console); + + verify(console).print(anyString()); + } + @Test void getCompleter() { assertThat(fixture.getCompleter(), is(fixture)); diff --git a/bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/devices/AbstractBatteryPoweredDeviceHandlerTest.java b/bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/devices/AbstractBatteryPoweredDeviceHandlerTest.java index d01b3721b05..098bd46a8a8 100644 --- a/bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/devices/AbstractBatteryPoweredDeviceHandlerTest.java +++ b/bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/devices/AbstractBatteryPoweredDeviceHandlerTest.java @@ -46,13 +46,13 @@ public abstract class AbstractBatteryPoweredDeviceHandlerTest status.getStatus().equals(ThingStatus.OFFLINE) + && status.getStatusDetail().equals(ThingStatusDetail.CONFIGURATION_ERROR))); + } + + @ParameterizedTest + @MethodSource("org.openhab.binding.boschshc.internal.tests.common.CommonTestUtils#getExecutionExceptionAndInterruptedExceptionArguments()") + void initializeHandleExceptionDuringDeviceInfoRestCall(Exception exception) + throws BoschSHCException, InterruptedException, TimeoutException, ExecutionException { + when(getBridgeHandler().getDeviceInfo(getDeviceID())).thenThrow(exception); + + getFixture().initialize(); + + verify(getCallback()).statusUpdated(eq(getThing()), + argThat(status -> status.getStatus().equals(ThingStatus.OFFLINE) + && status.getStatusDetail().equals(ThingStatusDetail.CONFIGURATION_ERROR))); + } } diff --git a/bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/devices/AbstractBoschSHCHandlerTest.java b/bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/devices/AbstractBoschSHCHandlerTest.java index c8efb9c9b31..1c754d6d32c 100644 --- a/bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/devices/AbstractBoschSHCHandlerTest.java +++ b/bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/devices/AbstractBoschSHCHandlerTest.java @@ -12,6 +12,9 @@ */ package org.openhab.binding.boschshc.internal.devices; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.sameInstance; +import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; @@ -60,7 +63,7 @@ public abstract class AbstractBoschSHCHandlerTest { private @Mock @NonNullByDefault({}) Bridge bridge; - protected @Mock @NonNullByDefault({}) BridgeHandler bridgeHandler; + private @Mock @NonNullByDefault({}) BridgeHandler bridgeHandler; private @Mock @NonNullByDefault({}) ThingHandlerCallback callback; @@ -128,8 +131,25 @@ public abstract class AbstractBoschSHCHandlerTest { } @Test - public void testInitialize() { + void testInitialize() { ThingStatusInfo expectedStatusInfo = new ThingStatusInfo(ThingStatus.ONLINE, ThingStatusDetail.NONE, null); verify(callback).statusUpdated(same(thing), eq(expectedStatusInfo)); } + + @Test + void testGetBridgeHandler() throws BoschSHCException { + assertThat(fixture.getBridgeHandler(), sameInstance(bridgeHandler)); + } + + @Test + void testGetBridgeHandlerThrowExceptionIfBridgeIsNull() throws BoschSHCException { + when(callback.getBridge(any())).thenReturn(null); + assertThrows(BoschSHCException.class, () -> fixture.getBridgeHandler()); + } + + @Test + void testGetBridgeHandlerThrowExceptionIfBridgeHandlerIsNull() throws BoschSHCException { + when(bridge.getHandler()).thenReturn(null); + assertThrows(BoschSHCException.class, () -> fixture.getBridgeHandler()); + } } diff --git a/bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/devices/AbstractPowerSwitchHandlerTest.java b/bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/devices/AbstractPowerSwitchHandlerTest.java index 49be02c8286..a634f0c4c27 100644 --- a/bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/devices/AbstractPowerSwitchHandlerTest.java +++ b/bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/devices/AbstractPowerSwitchHandlerTest.java @@ -13,12 +13,14 @@ package org.openhab.binding.boschshc.internal.devices; import static org.junit.jupiter.api.Assertions.assertSame; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.same; -import static org.mockito.Mockito.lenient; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeoutException; @@ -26,12 +28,16 @@ import java.util.concurrent.TimeoutException; import org.eclipse.jdt.annotation.NonNullByDefault; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; import org.mockito.ArgumentCaptor; import org.mockito.Captor; import org.openhab.binding.boschshc.internal.exceptions.BoschSHCException; import org.openhab.binding.boschshc.internal.services.powerswitch.PowerSwitchState; import org.openhab.binding.boschshc.internal.services.powerswitch.dto.PowerSwitchServiceState; import org.openhab.core.library.types.OnOffType; +import org.openhab.core.thing.ThingStatus; +import org.openhab.core.thing.ThingStatusDetail; import org.openhab.core.types.RefreshType; import com.google.gson.JsonElement; @@ -53,12 +59,12 @@ public abstract class AbstractPowerSwitchHandlerTest status.getStatus().equals(ThingStatus.OFFLINE) + && status.getStatusDetail().equals(ThingStatusDetail.COMMUNICATION_ERROR))); + } + @Test public void testUpdateChannelPowerSwitchState() { JsonElement jsonObject = JsonParser .parseString("{\n" + " \"@type\": \"powerSwitchState\",\n" + " \"switchState\": \"ON\"\n" + "}"); + getFixture().processUpdate("PowerSwitch", jsonObject); - verify(getCallback()).stateUpdated(getChannelUID(BoschSHCBindingConstants.CHANNEL_POWER_SWITCH), OnOffType.ON); + + // state is updated twice: via short poll in initialize() and via long poll result in this test + verify(getCallback(), times(2)).stateUpdated(getChannelUID(BoschSHCBindingConstants.CHANNEL_POWER_SWITCH), + OnOffType.ON); jsonObject = JsonParser .parseString("{\n" + " \"@type\": \"powerSwitchState\",\n" + " \"switchState\": \"OFF\"\n" + "}"); + getFixture().processUpdate("PowerSwitch", jsonObject); + verify(getCallback()).stateUpdated(getChannelUID(BoschSHCBindingConstants.CHANNEL_POWER_SWITCH), OnOffType.OFF); } @Test public void testHandleCommandRefreshPowerSwitchChannel() { getFixture().handleCommand(getChannelUID(BoschSHCBindingConstants.CHANNEL_POWER_SWITCH), RefreshType.REFRESH); - verify(getCallback()).stateUpdated(getChannelUID(BoschSHCBindingConstants.CHANNEL_POWER_SWITCH), OnOffType.ON); + + // state is updated twice: via short poll in initialize() and via long poll result in this test + verify(getCallback(), times(2)).stateUpdated(getChannelUID(BoschSHCBindingConstants.CHANNEL_POWER_SWITCH), + OnOffType.ON); + } + + @ParameterizedTest + @MethodSource("org.openhab.binding.boschshc.internal.tests.common.CommonTestUtils#getBoschShcAndExecutionAndTimeoutAndInterruptedExceptionArguments()") + public void testHandleCommandRefreshPowerSwitchChannelHandleExceptions(Exception e) + throws InterruptedException, TimeoutException, ExecutionException, BoschSHCException { + when(getBridgeHandler().getState(anyString(), eq("PowerSwitch"), same(PowerSwitchServiceState.class))) + .thenThrow(e); + + getFixture().handleCommand(getChannelUID(BoschSHCBindingConstants.CHANNEL_POWER_SWITCH), RefreshType.REFRESH); + + verify(getCallback()).statusUpdated(same(getThing()), + argThat(status -> status.getStatus().equals(ThingStatus.OFFLINE) + && status.getStatusDetail().equals(ThingStatusDetail.COMMUNICATION_ERROR))); } } diff --git a/bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/devices/AbstractPowerSwitchHandlerWithPowerMeterTest.java b/bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/devices/AbstractPowerSwitchHandlerWithPowerMeterTest.java index 3ce2da12834..2fdb8e5e88c 100644 --- a/bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/devices/AbstractPowerSwitchHandlerWithPowerMeterTest.java +++ b/bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/devices/AbstractPowerSwitchHandlerWithPowerMeterTest.java @@ -17,6 +17,7 @@ import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.same; import static org.mockito.Mockito.lenient; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import java.util.concurrent.ExecutionException; @@ -56,13 +57,13 @@ public abstract class AbstractPowerSwitchHandlerWithPowerMeterTest powerValue = powerCaptor.getValue(); assertEquals(23, powerValue.intValue()); - verify(getCallback()).stateUpdated(eq(getChannelUID(BoschSHCBindingConstants.CHANNEL_ENERGY_CONSUMPTION)), - energyCaptor.capture()); + // state is updated twice: via short poll in initialize() and via long poll result in this test + verify(getCallback(), times(2)).stateUpdated( + eq(getChannelUID(BoschSHCBindingConstants.CHANNEL_ENERGY_CONSUMPTION)), energyCaptor.capture()); QuantityType energyValue = energyCaptor.getValue(); assertEquals(42, energyValue.intValue()); } @@ -91,7 +94,9 @@ public abstract class AbstractPowerSwitchHandlerWithPowerMeterTest(12.34d, Units.WATT)); } @@ -99,7 +104,9 @@ public abstract class AbstractPowerSwitchHandlerWithPowerMeterTest(56.78d, Units.WATT_HOUR)); } } diff --git a/bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/devices/bridge/BridgeHandlerTest.java b/bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/devices/bridge/BridgeHandlerTest.java index 4bfde88740b..734551a7784 100644 --- a/bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/devices/bridge/BridgeHandlerTest.java +++ b/bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/devices/bridge/BridgeHandlerTest.java @@ -12,7 +12,10 @@ */ package org.openhab.binding.boschshc.internal.devices.bridge; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.collection.IsCollectionWithSize.hasSize; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertSame; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -22,9 +25,11 @@ import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.ArgumentMatchers.contains; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.isNull; import static org.mockito.ArgumentMatchers.same; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoInteractions; import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; @@ -50,16 +55,23 @@ import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; import org.mockito.ArgumentCaptor; +import org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants; import org.openhab.binding.boschshc.internal.devices.BoschSHCHandler; import org.openhab.binding.boschshc.internal.devices.bridge.dto.Device; import org.openhab.binding.boschshc.internal.devices.bridge.dto.DeviceServiceData; import org.openhab.binding.boschshc.internal.devices.bridge.dto.DeviceTest; import org.openhab.binding.boschshc.internal.devices.bridge.dto.Faults; import org.openhab.binding.boschshc.internal.devices.bridge.dto.LongPollResult; +import org.openhab.binding.boschshc.internal.devices.bridge.dto.PublicInformation; +import org.openhab.binding.boschshc.internal.devices.bridge.dto.Room; +import org.openhab.binding.boschshc.internal.devices.bridge.dto.Scenario; import org.openhab.binding.boschshc.internal.devices.bridge.dto.SubscribeResult; import org.openhab.binding.boschshc.internal.devices.bridge.dto.UserDefinedState; import org.openhab.binding.boschshc.internal.devices.bridge.dto.UserDefinedStateTest; +import org.openhab.binding.boschshc.internal.discovery.ThingDiscoveryService; import org.openhab.binding.boschshc.internal.exceptions.BoschSHCException; import org.openhab.binding.boschshc.internal.serialization.GsonUtils; import org.openhab.binding.boschshc.internal.services.binaryswitch.dto.BinarySwitchServiceState; @@ -70,15 +82,21 @@ import org.openhab.binding.boschshc.internal.services.intrusion.dto.IntrusionDet import org.openhab.binding.boschshc.internal.services.shuttercontact.ShutterContactState; import org.openhab.binding.boschshc.internal.services.shuttercontact.dto.ShutterContactServiceState; import org.openhab.core.config.core.Configuration; +import org.openhab.core.library.types.OnOffType; +import org.openhab.core.library.types.StringType; import org.openhab.core.thing.Bridge; +import org.openhab.core.thing.Channel; +import org.openhab.core.thing.ChannelUID; import org.openhab.core.thing.Thing; import org.openhab.core.thing.ThingStatus; import org.openhab.core.thing.ThingStatusDetail; +import org.openhab.core.thing.ThingStatusInfo; import org.openhab.core.thing.binding.ThingHandlerCallback; import org.openhab.core.thing.binding.builder.ThingStatusInfoBuilder; import com.google.gson.JsonElement; import com.google.gson.JsonParser; +import com.google.gson.JsonPrimitive; /** * Unit tests for the {@link BridgeHandler}. @@ -92,13 +110,9 @@ class BridgeHandlerTest { private @NonNullByDefault({}) BridgeHandler fixture; private @NonNullByDefault({}) BoschHttpClient httpClient; - private @NonNullByDefault({}) ThingHandlerCallback thingHandlerCallback; - - /** - * A mocked bridge instance - */ private @NonNullByDefault({}) Bridge thing; + private @NonNullByDefault({}) Configuration bridgeConfiguration; @BeforeAll static void beforeAll() throws IOException { @@ -119,7 +133,7 @@ class BridgeHandlerTest { thingHandlerCallback = mock(ThingHandlerCallback.class); fixture.setCallback(thingHandlerCallback); - Configuration bridgeConfiguration = new Configuration(); + bridgeConfiguration = new Configuration(); Map<@Nullable String, @Nullable Object> properties = new HashMap<>(); properties.put("ipAddress", "localhost"); properties.put("password", "test"); @@ -155,6 +169,19 @@ class BridgeHandlerTest { verify(mockRequest).send(); } + @Test + void postActionWithoutRequestBody() throws InterruptedException, TimeoutException, ExecutionException { + String endpoint = "/intrusion/actions/disarm"; + String url = "https://127.0.0.1:8444/smarthome/intrusion/actions/disarm"; + when(httpClient.getBoschSmartHomeUrl(endpoint)).thenReturn(url); + Request mockRequest = mock(Request.class); + when(httpClient.createRequest(anyString(), any(), any())).thenReturn(mockRequest); + + fixture.postAction(endpoint); + verify(httpClient).createRequest(eq(url), same(HttpMethod.POST), isNull()); + verify(mockRequest).send(); + } + @Test void initialAccessHttpClientOffline() { fixture.initialAccess(httpClient); @@ -212,9 +239,31 @@ class BridgeHandlerTest { when(httpClient.createRequest(anyString(), same(HttpMethod.POST), argThat((JsonRpcRequest r) -> "RE/longPoll".equals(r.method)))).thenReturn(longPollRequest); + ThingDiscoveryService thingDiscoveryListener = mock(ThingDiscoveryService.class); + fixture.registerDiscoveryListener(thingDiscoveryListener); + fixture.initialAccess(httpClient); + verify(thingHandlerCallback).statusUpdated(any(), eq(ThingStatusInfoBuilder.create(ThingStatus.ONLINE, ThingStatusDetail.NONE).build())); + verify(thingDiscoveryListener).doScan(); + } + + @Test + void initialAccessNoBridgeAccess() throws InterruptedException, TimeoutException, ExecutionException { + when(httpClient.isOnline()).thenReturn(true); + when(httpClient.isAccessPossible()).thenReturn(true); + Request request = mock(Request.class); + when(httpClient.createRequest(any(), same(HttpMethod.GET))).thenReturn(request); + ContentResponse response = mock(ContentResponse.class); + when(request.send()).thenReturn(response); + when(response.getStatus()).thenReturn(400); + + fixture.initialAccess(httpClient); + + verify(thingHandlerCallback).statusUpdated(same(thing), + argThat(status -> status.getStatus().equals(ThingStatus.OFFLINE) + && status.getStatusDetail().equals(ThingStatusDetail.COMMUNICATION_ERROR))); } @Test @@ -468,6 +517,44 @@ class BridgeHandlerTest { assertEquals(stateId, userState.getId()); } + @Test + void getUserStateInfoErrorCases() + throws InterruptedException, TimeoutException, ExecutionException, BoschSHCException { + when(httpClient.getBoschSmartHomeUrl(anyString())).thenCallRealMethod(); + when(httpClient.getBoschShcUrl(anyString())).thenCallRealMethod(); + + Request request = mock(Request.class); + when(request.header(anyString(), anyString())).thenReturn(request); + ContentResponse response = mock(ContentResponse.class); + when(response.getStatus()).thenReturn(200); + when(request.send()).thenReturn(response); + when(httpClient.createRequest(anyString(), same(HttpMethod.GET))).thenReturn(request); + + @SuppressWarnings("unchecked") + ArgumentCaptor> errorResponseHandlerCaptor = ArgumentCaptor + .forClass(BiFunction.class); + + String stateId = "abcdef"; + when(httpClient.sendRequest(same(request), same(UserDefinedState.class), any(), + errorResponseHandlerCaptor.capture())).thenReturn(UserDefinedStateTest.createTestState(stateId)); + + fixture.getUserStateInfo(stateId); + + BiFunction errorResponseHandler = errorResponseHandlerCaptor.getValue(); + Exception e = errorResponseHandler.apply(500, + "{\"@type\":\"JsonRestExceptionResponseEntity\",\"errorCode\": \"testErrorCode\",\"statusCode\": 500}"); + assertEquals( + "Request for info of user-defined state abcdef failed with status code 500 and error code testErrorCode", + e.getMessage()); + + e = errorResponseHandler.apply(404, + "{\"@type\":\"JsonRestExceptionResponseEntity\",\"errorCode\": \"ENTITY_NOT_FOUND\",\"statusCode\": 404}"); + assertNotNull(e); + + e = errorResponseHandler.apply(500, ""); + assertEquals("Request for info of user-defined state abcdef failed with status code 500", e.getMessage()); + } + @Test void getUserStates() throws InterruptedException, TimeoutException, ExecutionException, BoschSHCException { when(httpClient.getBoschSmartHomeUrl(anyString())).thenCallRealMethod(); @@ -650,4 +737,347 @@ class BridgeHandlerTest { verify(thingHandler).processChildUpdate("hdm:ZigBee:70ac08fffefead2d#3", "PowerSwitch", expectedState); } + + @Test + void handleLongPollResultScenarioTriggered() { + Channel channel = mock(Channel.class); + when(thing.getChannel(BoschSHCBindingConstants.CHANNEL_SCENARIO_TRIGGERED)).thenReturn(channel); + when(thingHandlerCallback.isChannelLinked(any())).thenReturn(true); + + String json = """ + { + "result": [{ + "@type": "scenarioTriggered", + "name": "My Scenario", + "id": "509bd737-eed0-40b7-8caa-e8686a714399", + "lastTimeTriggered": "1693758693032" + }], + "jsonrpc": "2.0" + } + """; + LongPollResult longPollResult = GsonUtils.DEFAULT_GSON_INSTANCE.fromJson(json, LongPollResult.class); + assertNotNull(longPollResult); + + fixture.handleLongPollResult(longPollResult); + + verify(thingHandlerCallback).stateUpdated(any(), eq(new StringType("My Scenario"))); + } + + @Test + void handleLongPollResultUserDefinedState() { + List things = new ArrayList(); + when(thing.getThings()).thenReturn(things); + + Thing thing = mock(Thing.class); + things.add(thing); + + BoschSHCHandler thingHandler = mock(BoschSHCHandler.class); + when(thing.getHandler()).thenReturn(thingHandler); + + when(thingHandler.getBoschID()).thenReturn("3d8023d6-69ca-4e79-89dd-7090295cefbf"); + + String json = """ + { + "result": [{ + "deleted": false, + "@type": "userDefinedState", + "name": "Test State", + "id": "3d8023d6-69ca-4e79-89dd-7090295cefbf", + "state": true + }], + "jsonrpc": "2.0" + } + """; + LongPollResult longPollResult = GsonUtils.DEFAULT_GSON_INSTANCE.fromJson(json, LongPollResult.class); + assertNotNull(longPollResult); + + fixture.handleLongPollResult(longPollResult); + + JsonElement expectedState = new JsonPrimitive(true); + + verify(thingHandler).processUpdate("3d8023d6-69ca-4e79-89dd-7090295cefbf", expectedState); + } + + @Test + void handleLongPollFailure() { + Throwable e = new RuntimeException("Test exception"); + fixture.handleLongPollFailure(e); + + ThingStatusInfo expectedStatus = ThingStatusInfoBuilder + .create(ThingStatus.UNKNOWN, ThingStatusDetail.UNKNOWN.NONE).build(); + verify(thingHandlerCallback).statusUpdated(thing, expectedStatus); + } + + @Test + void getDevices() throws InterruptedException, TimeoutException, ExecutionException { + Request request = mock(Request.class); + when(httpClient.createRequest(any(), eq(HttpMethod.GET))).thenReturn(request); + ContentResponse contentResponse = mock(ContentResponse.class); + when(request.send()).thenReturn(contentResponse); + when(contentResponse.getStatus()).thenReturn(200); + String devicesJson = """ + [ + { + "@type": "device", + "rootDeviceId": "64-da-a0-3e-81-0c", + "id": "hdm:ZigBee:0c4314fffea15de7", + "deviceServiceIds": [ + "CommunicationQuality", + "PowerMeter", + "PowerSwitch", + "PowerSwitchConfiguration", + "PowerSwitchProgram" + ], + "manufacturer": "BOSCH", + "roomId": "hz_1", + "deviceModel": "PLUG_COMPACT", + "serial": "0C4314FFFE802BE2", + "profile": "LIGHT", + "iconId": "icon_plug_lamp_table", + "name": "My Lamp Plug", + "status": "AVAILABLE", + "childDeviceIds": [], + "supportedProfiles": [ + "LIGHT", + "GENERIC", + "HEATING_RCC" + ] + }, + { + "@type": "device", + "rootDeviceId": "64-da-a0-3e-81-0c", + "id": "hdm:ZigBee:000d6f0012f13bfa", + "deviceServiceIds": [ + "LatestMotion", + "CommunicationQuality", + "WalkTest", + "BatteryLevel", + "MultiLevelSensor", + "DeviceDefect" + ], + "manufacturer": "BOSCH", + "roomId": "hz_5", + "deviceModel": "MD", + "serial": "000D6F0012F0da96", + "profile": "GENERIC", + "name": "My Motion Detector", + "status": "AVAILABLE", + "childDeviceIds": [], + "supportedProfiles": [] + } + ] + """; + when(contentResponse.getContentAsString()).thenReturn(devicesJson); + + List devices = fixture.getDevices(); + + assertEquals(2, devices.size()); + + Device plugDevice = devices.get(0); + assertEquals("hdm:ZigBee:0c4314fffea15de7", plugDevice.id); + assertEquals(5, plugDevice.deviceServiceIds.size()); + assertEquals(0, plugDevice.childDeviceIds.size()); + + Device motionDetectorDevice = devices.get(1); + assertEquals("hdm:ZigBee:000d6f0012f13bfa", motionDetectorDevice.id); + assertEquals(6, motionDetectorDevice.deviceServiceIds.size()); + assertEquals(0, motionDetectorDevice.childDeviceIds.size()); + } + + @Test + void getDevicesErrorRestResponse() throws InterruptedException, TimeoutException, ExecutionException { + Request request = mock(Request.class); + when(httpClient.createRequest(any(), eq(HttpMethod.GET))).thenReturn(request); + ContentResponse contentResponse = mock(ContentResponse.class); + when(request.send()).thenReturn(contentResponse); + when(contentResponse.getStatus()).thenReturn(400); // bad request + + List devices = fixture.getDevices(); + + assertThat(devices, hasSize(0)); + } + + @ParameterizedTest + @MethodSource("org.openhab.binding.boschshc.internal.tests.common.CommonTestUtils#getExecutionAndTimeoutExceptionArguments()") + void getDevicesHandleExceptions() throws InterruptedException, TimeoutException, ExecutionException { + Request request = mock(Request.class); + when(httpClient.createRequest(any(), eq(HttpMethod.GET))).thenReturn(request); + when(request.send()).thenThrow(new ExecutionException(new RuntimeException("Test Exception"))); + + List devices = fixture.getDevices(); + + assertThat(devices, hasSize(0)); + } + + @Test + void getRooms() throws InterruptedException, TimeoutException, ExecutionException { + Request request = mock(Request.class); + when(httpClient.createRequest(any(), eq(HttpMethod.GET))).thenReturn(request); + ContentResponse contentResponse = mock(ContentResponse.class); + when(request.send()).thenReturn(contentResponse); + when(contentResponse.getStatus()).thenReturn(200); + String roomsJson = """ + [ + { + "@type": "room", + "id": "hz_1", + "iconId": "icon_room_living_room", + "name": "Living Room" + }, + { + "@type": "room", + "id": "hz_2", + "iconId": "icon_room_dining_room", + "name": "Dining Room" + } + ] + """; + when(contentResponse.getContentAsString()).thenReturn(roomsJson); + + List rooms = fixture.getRooms(); + + assertEquals(2, rooms.size()); + + Room livingRoom = rooms.get(0); + assertEquals("hz_1", livingRoom.id); + assertEquals("Living Room", livingRoom.name); + + Room diningRoom = rooms.get(1); + assertEquals("hz_2", diningRoom.id); + assertEquals("Dining Room", diningRoom.name); + } + + @Test + void getRoomsErrorRestResponse() throws InterruptedException, TimeoutException, ExecutionException { + Request request = mock(Request.class); + when(httpClient.createRequest(any(), eq(HttpMethod.GET))).thenReturn(request); + ContentResponse contentResponse = mock(ContentResponse.class); + when(request.send()).thenReturn(contentResponse); + when(contentResponse.getStatus()).thenReturn(400); // bad request + + List rooms = fixture.getRooms(); + + assertThat(rooms, hasSize(0)); + } + + @ParameterizedTest + @MethodSource("org.openhab.binding.boschshc.internal.tests.common.CommonTestUtils#getExecutionAndTimeoutExceptionArguments()") + void getRoomsHandleExceptions() throws InterruptedException, TimeoutException, ExecutionException { + Request request = mock(Request.class); + when(httpClient.createRequest(any(), eq(HttpMethod.GET))).thenReturn(request); + when(request.send()).thenThrow(new ExecutionException(new RuntimeException("Test Exception"))); + + List rooms = fixture.getRooms(); + + assertThat(rooms, hasSize(0)); + } + + @Test + void getServices() { + assertTrue(fixture.getServices().contains(ThingDiscoveryService.class)); + } + + @Test + void handleCommandIrrelevantChannel() { + ChannelUID channelUID = mock(ChannelUID.class); + when(channelUID.getId()).thenReturn(BoschSHCBindingConstants.CHANNEL_POWER_SWITCH); + + fixture.handleCommand(channelUID, OnOffType.ON); + + verifyNoInteractions(httpClient); + } + + @Test + void handleCommandTriggerScenario() + throws InterruptedException, TimeoutException, ExecutionException, BoschSHCException { + ChannelUID channelUID = mock(ChannelUID.class); + when(channelUID.getId()).thenReturn(BoschSHCBindingConstants.CHANNEL_TRIGGER_SCENARIO); + + // required to prevent NPE + when(httpClient.sendRequest(any(), eq(Scenario[].class), any(), any())).thenReturn(new Scenario[] {}); + + fixture.handleCommand(channelUID, OnOffType.ON); + + verify(httpClient).sendRequest(any(), eq(Scenario[].class), any(), any()); + } + + @Test + void registerDiscoveryListener() { + ThingDiscoveryService listener = mock(ThingDiscoveryService.class); + assertTrue(fixture.registerDiscoveryListener(listener)); + assertFalse(fixture.registerDiscoveryListener(listener)); + } + + @Test + void unregisterDiscoveryListener() { + assertFalse(fixture.unregisterDiscoveryListener()); + fixture.registerDiscoveryListener(mock(ThingDiscoveryService.class)); + assertTrue(fixture.unregisterDiscoveryListener()); + } + + @Test + void initializeNoIpAddress() { + bridgeConfiguration.setProperties(new HashMap()); + + fixture.initialize(); + + ThingStatusInfo expectedStatus = ThingStatusInfoBuilder + .create(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR) + .withDescription("@text/offline.conf-error-empty-ip").build(); + verify(thingHandlerCallback).statusUpdated(thing, expectedStatus); + } + + @Test + void initializeNoPassword() { + HashMap properties = new HashMap(); + properties.put("ipAddress", "localhost"); + bridgeConfiguration.setProperties(properties); + + fixture.initialize(); + + ThingStatusInfo expectedStatus = ThingStatusInfoBuilder + .create(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR) + .withDescription("@text/offline.conf-error-empty-password").build(); + verify(thingHandlerCallback).statusUpdated(thing, expectedStatus); + } + + @Test + void checkBridgeAccess() throws InterruptedException, TimeoutException, ExecutionException { + Request request = mock(Request.class); + when(httpClient.createRequest(any(), eq(HttpMethod.GET))).thenReturn(request); + ContentResponse contentResponse = mock(ContentResponse.class); + when(request.send()).thenReturn(contentResponse); + when(contentResponse.getStatus()).thenReturn(200); + + assertTrue(fixture.checkBridgeAccess()); + } + + @Test + void checkBridgeAccessRestResponseError() throws InterruptedException, TimeoutException, ExecutionException { + Request request = mock(Request.class); + when(httpClient.createRequest(any(), eq(HttpMethod.GET))).thenReturn(request); + ContentResponse contentResponse = mock(ContentResponse.class); + when(request.send()).thenReturn(contentResponse); + when(contentResponse.getStatus()).thenReturn(400); + + assertFalse(fixture.checkBridgeAccess()); + } + + @ParameterizedTest + @MethodSource("org.openhab.binding.boschshc.internal.tests.common.CommonTestUtils#getExecutionAndTimeoutExceptionArguments()") + void checkBridgeAccessRestException(Exception e) throws InterruptedException, TimeoutException, ExecutionException { + Request request = mock(Request.class); + when(httpClient.createRequest(any(), eq(HttpMethod.GET))).thenReturn(request); + when(request.send()).thenThrow(e); + + assertFalse(fixture.checkBridgeAccess()); + } + + @Test + void getPublicInformation() throws InterruptedException, BoschSHCException, ExecutionException, TimeoutException { + fixture.getPublicInformation(); + + verify(httpClient).createRequest(any(), same(HttpMethod.GET)); + verify(httpClient).sendRequest(any(), same(PublicInformation.class), any(), isNull()); + } } 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 596ea19dad0..6ae48498252 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 @@ -12,9 +12,21 @@ */ package org.openhab.binding.boschshc.internal.devices.bridge; -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.ArgumentMatchers.*; -import static org.mockito.Mockito.*; +import static org.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.CoreMatchers.instanceOf; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertSame; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.argThat; +import static org.mockito.ArgumentMatchers.same; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; @@ -43,6 +55,8 @@ 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.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; @@ -53,6 +67,7 @@ import org.openhab.binding.boschshc.internal.devices.bridge.dto.SubscribeResult; import org.openhab.binding.boschshc.internal.devices.bridge.dto.UserDefinedState; 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 com.google.gson.JsonObject; import com.google.gson.JsonSyntaxException; @@ -332,18 +347,21 @@ class LongPollingTest { assertTrue(longPollResultItem.isState()); } - @Test - void startSubscriptionFailure() + @ParameterizedTest + @MethodSource("org.openhab.binding.boschshc.internal.tests.common.CommonTestUtils#getBoschShcAndExecutionAndTimeoutAndInterruptedExceptionArguments()") + void startSubscriptionFailureHandleExceptions(Exception exception) throws InterruptedException, TimeoutException, ExecutionException, BoschSHCException { - when(httpClient.sendRequest(any(), same(SubscribeResult.class), any(), any())) - .thenThrow(new ExecutionException("Subscription failed.", null)); + when(httpClient.sendRequest(any(), same(SubscribeResult.class), any(), any())).thenThrow(exception); LongPollingFailedException e = assertThrows(LongPollingFailedException.class, () -> fixture.start(httpClient)); - assertTrue(e.getMessage().contains("Subscription failed.")); + assertThat(e.getCause(), instanceOf(exception.getClass())); + assertThat(e.getMessage(), containsString(CommonTestUtils.TEST_EXCEPTION_MESSAGE)); } - @Test - void startLongPollFailure() throws InterruptedException, TimeoutException, ExecutionException, BoschSHCException { + @ParameterizedTest + @MethodSource("org.openhab.binding.boschshc.internal.tests.common.CommonTestUtils#getExceutionExceptionAndRuntimeExceptionArguments()") + void startLongPollFailure(Exception exception) + throws InterruptedException, TimeoutException, ExecutionException, BoschSHCException { when(httpClient.getBoschShcUrl(anyString())).thenCallRealMethod(); Request request = mock(Request.class); @@ -364,7 +382,6 @@ class LongPollingTest { BufferingResponseListener bufferingResponseListener = (BufferingResponseListener) completeListener.getValue(); Result result = mock(Result.class); - ExecutionException exception = new ExecutionException("test exception", null); when(result.getFailure()).thenReturn(exception); bufferingResponseListener.onComplete(result); diff --git a/bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/devices/bridge/ScenarioHandlerTest.java b/bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/devices/bridge/ScenarioHandlerTest.java index 5ca0f3b8e52..044b6358337 100644 --- a/bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/devices/bridge/ScenarioHandlerTest.java +++ b/bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/devices/bridge/ScenarioHandlerTest.java @@ -12,7 +12,13 @@ */ package org.openhab.binding.boschshc.internal.devices.bridge; -import static org.mockito.Mockito.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; import java.util.List; import java.util.UUID; @@ -24,10 +30,12 @@ import org.eclipse.jetty.client.api.ContentResponse; import org.eclipse.jetty.client.api.Request; import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.HttpStatus; +import org.junit.jupiter.api.BeforeEach; 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.MethodSource; +import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import org.openhab.binding.boschshc.internal.devices.bridge.dto.Scenario; import org.openhab.binding.boschshc.internal.exceptions.BoschSHCException; @@ -61,11 +69,19 @@ class ScenarioHandlerTest { .toArray(Exception[]::new); } + private @NonNullByDefault({}) ScenarioHandler fixture; + + private @NonNullByDefault({}) @Mock BoschHttpClient httpClient; + private @NonNullByDefault({}) @Mock Request request; + + @BeforeEach + void beforeEach() { + fixture = new ScenarioHandler(); + } + @Test void triggerScenarioShouldSendPOSTToBoschAPI() throws Exception { // GIVEN - final var httpClient = mock(BoschHttpClient.class); - final var request = mock(Request.class); final var contentResponse = mock(ContentResponse.class); when(httpClient.getBoschSmartHomeUrl(anyString())).thenReturn("http://localhost/smartHome/scenarios") .thenReturn("http://localhost/smartHome/scenarios/1234/triggers"); @@ -74,10 +90,8 @@ class ScenarioHandlerTest { when(request.send()).thenReturn(contentResponse); when(contentResponse.getStatus()).thenReturn(HttpStatus.OK_200); - final var handler = new ScenarioHandler(); - // WHEN - handler.triggerScenario(httpClient, "Scenario 1"); + fixture.triggerScenario(httpClient, "Scenario 1"); // THEN verify(httpClient).getBoschSmartHomeUrl("scenarios"); @@ -85,19 +99,15 @@ class ScenarioHandlerTest { } @Test - void triggerScenarioShouldNoSendPOSTToScenarioNameDoesNotExist() throws Exception { + void triggerScenarioShouldNotSendPOSTToScenarioNameDoesNotExist() throws Exception { // GIVEN - final var httpClient = mock(BoschHttpClient.class); - final var request = mock(Request.class); when(httpClient.getBoschSmartHomeUrl(anyString())).thenReturn("http://localhost/smartHome/scenarios") .thenReturn("http://localhost/smartHome/scenarios/1234/triggers"); when(httpClient.createRequest(anyString(), any(HttpMethod.class))).thenReturn(request).thenReturn(request); when(httpClient.sendRequest(any(Request.class), any(), any(), any())).thenReturn(existingScenarios); - final var handler = new ScenarioHandler(); - // WHEN - handler.triggerScenario(httpClient, "not existing Scenario"); + fixture.triggerScenario(httpClient, "not existing Scenario"); // THEN verify(httpClient).getBoschSmartHomeUrl("scenarios"); @@ -108,17 +118,13 @@ class ScenarioHandlerTest { @MethodSource("exceptionData") void triggerScenarioShouldNotPanicIfBoschAPIThrowsException(final Exception exception) throws Exception { // GIVEN - final var httpClient = mock(BoschHttpClient.class); - final var request = mock(Request.class); when(httpClient.getBoschSmartHomeUrl(anyString())).thenReturn("http://localhost/smartHome/scenarios") .thenReturn("http://localhost/smartHome/scenarios/1234/triggers"); when(httpClient.createRequest(anyString(), any(HttpMethod.class))).thenReturn(request); when(httpClient.sendRequest(any(Request.class), any(), any(), any())).thenThrow(exception); - final var handler = new ScenarioHandler(); - // WHEN - handler.triggerScenario(httpClient, "Scenario 1"); + fixture.triggerScenario(httpClient, "Scenario 1"); // THEN verify(httpClient).getBoschSmartHomeUrl("scenarios"); @@ -128,8 +134,6 @@ class ScenarioHandlerTest { @Test void triggerScenarioShouldNotPanicIfPOSTIsNotSuccessful() throws Exception { // GIVEN - final var httpClient = mock(BoschHttpClient.class); - final var request = mock(Request.class); final var contentResponse = mock(ContentResponse.class); when(httpClient.getBoschSmartHomeUrl(anyString())).thenReturn("http://localhost/smartHome/scenarios") .thenReturn("http://localhost/smartHome/scenarios/1234/triggers"); @@ -138,10 +142,8 @@ class ScenarioHandlerTest { when(request.send()).thenReturn(contentResponse); when(contentResponse.getStatus()).thenReturn(HttpStatus.METHOD_NOT_ALLOWED_405); - final var handler = new ScenarioHandler(); - // WHEN - handler.triggerScenario(httpClient, "Scenario 1"); + fixture.triggerScenario(httpClient, "Scenario 1"); // THEN verify(httpClient).getBoschSmartHomeUrl("scenarios"); @@ -152,21 +154,27 @@ class ScenarioHandlerTest { @MethodSource("httpExceptionData") void triggerScenarioShouldNotPanicIfPOSTThrowsException(final Exception exception) throws Exception { // GIVEN - final var httpClient = mock(BoschHttpClient.class); - final var request = mock(Request.class); when(httpClient.getBoschSmartHomeUrl(anyString())).thenReturn("http://localhost/smartHome/scenarios") .thenReturn("http://localhost/smartHome/scenarios/1234/triggers"); when(httpClient.createRequest(anyString(), any(HttpMethod.class))).thenReturn(request).thenReturn(request); when(httpClient.sendRequest(any(Request.class), any(), any(), any())).thenReturn(existingScenarios); when(request.send()).thenThrow(exception); - final var handler = new ScenarioHandler(); - // WHEN - handler.triggerScenario(httpClient, "Scenario 1"); + fixture.triggerScenario(httpClient, "Scenario 1"); // THEN verify(httpClient).getBoschSmartHomeUrl("scenarios"); verify(request).send(); } + + @Test + void prettyLogScenarios() { + Scenario scenario1 = Scenario.createScenario("id1", "Scenario 1", "1708619045411"); + Scenario scenario2 = Scenario.createScenario("id2", "Scenario 2", "1708619065445"); + assertEquals( + "[\n" + " Scenario{name='Scenario 1', id='id1', lastTimeTriggered='1708619045411'}\n" + + " Scenario{name='Scenario 2', id='id2', lastTimeTriggered='1708619065445'}\n" + "]", + fixture.prettyLogScenarios(new Scenario[] { scenario1, scenario2 })); + } } diff --git a/bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/devices/bridge/dto/ScenarioTest.java b/bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/devices/bridge/dto/ScenarioTest.java new file mode 100644 index 00000000000..ebf574d9839 --- /dev/null +++ b/bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/devices/bridge/dto/ScenarioTest.java @@ -0,0 +1,47 @@ +/** + * Copyright (c) 2010-2024 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.binding.boschshc.internal.devices.bridge.dto; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +/** + * Unit tests for {@link Scenario}. + * + * @author David Pace - Initial contribution + * + */ +class ScenarioTest { + + private Scenario fixture; + + @BeforeEach + protected void setUp() throws Exception { + fixture = Scenario.createScenario("abc", "My Scenario", "1708845918493"); + } + + @Test + void isValid() { + assertTrue(Scenario.isValid(new Scenario[] { fixture })); + assertFalse(Scenario.isValid(new Scenario[] { fixture, new Scenario() })); + } + + @Test + void testToString() { + assertEquals("Scenario{name='My Scenario', id='abc', lastTimeTriggered='1708845918493'}", fixture.toString()); + } +} diff --git a/bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/devices/intrusion/IntrusionDetectionHandlerTest.java b/bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/devices/intrusion/IntrusionDetectionHandlerTest.java index 3a3152e91ef..36dca5c7ace 100644 --- a/bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/devices/intrusion/IntrusionDetectionHandlerTest.java +++ b/bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/devices/intrusion/IntrusionDetectionHandlerTest.java @@ -13,14 +13,20 @@ package org.openhab.binding.boschshc.internal.devices.intrusion; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.same; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeoutException; import org.eclipse.jdt.annotation.NonNullByDefault; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; import org.mockito.ArgumentCaptor; import org.mockito.Captor; import org.openhab.binding.boschshc.internal.devices.AbstractBoschSHCHandlerTest; @@ -29,6 +35,8 @@ import org.openhab.binding.boschshc.internal.services.intrusion.actions.arm.dto. import org.openhab.core.library.types.OnOffType; import org.openhab.core.library.types.StringType; import org.openhab.core.thing.ChannelUID; +import org.openhab.core.thing.ThingStatus; +import org.openhab.core.thing.ThingStatusDetail; import org.openhab.core.thing.ThingTypeUID; import com.google.gson.JsonElement; @@ -64,6 +72,20 @@ class IntrusionDetectionHandlerTest extends AbstractBoschSHCHandlerTest status.getStatus().equals(ThingStatus.OFFLINE) + && status.getStatusDetail().equals(ThingStatusDetail.COMMUNICATION_ERROR))); + } + @Test void testHandleCommandMuteAction() throws InterruptedException, TimeoutException, ExecutionException { getFixture().handleCommand(new ChannelUID(getThing().getUID(), BoschSHCBindingConstants.CHANNEL_MUTE_ACTION), diff --git a/bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/devices/shuttercontrol/ShutterControl2HandlerTest.java b/bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/devices/shuttercontrol/ShutterControl2HandlerTest.java index b5a21927b9e..1d5e873f05f 100644 --- a/bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/devices/shuttercontrol/ShutterControl2HandlerTest.java +++ b/bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/devices/shuttercontrol/ShutterControl2HandlerTest.java @@ -15,6 +15,7 @@ package org.openhab.binding.boschshc.internal.devices.shuttercontrol; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import java.util.concurrent.ExecutionException; @@ -140,4 +141,14 @@ class ShutterControl2HandlerTest extends ShutterControlHandlerTest { ChildProtectionServiceState state = childProtectionServiceStateCaptor.getValue(); assertTrue(state.childLockActive); } + + @Test + void testHandleCommandChildProtectionInvalidCommand() + throws InterruptedException, TimeoutException, ExecutionException, BoschSHCException { + getFixture().handleCommand( + new ChannelUID(getThing().getUID(), BoschSHCBindingConstants.CHANNEL_CHILD_PROTECTION), + DecimalType.ZERO); + verify(getBridgeHandler(), times(0)).putState(eq(getDeviceID()), eq("ChildProtection"), + childProtectionServiceStateCaptor.capture()); + } } diff --git a/bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/devices/userdefinedstate/UserStateHandlerTest.java b/bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/devices/userdefinedstate/UserStateHandlerTest.java index 1b489f898ab..f2bbd46d84b 100644 --- a/bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/devices/userdefinedstate/UserStateHandlerTest.java +++ b/bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/devices/userdefinedstate/UserStateHandlerTest.java @@ -17,22 +17,19 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.ArgumentMatchers.same; -import static org.mockito.Mockito.lenient; -import static org.mockito.Mockito.reset; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; import java.util.Map; import java.util.UUID; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeoutException; -import java.util.stream.Stream; import org.eclipse.jdt.annotation.NonNullByDefault; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; import org.mockito.ArgumentCaptor; import org.openhab.binding.boschshc.internal.devices.AbstractBoschSHCHandlerTest; @@ -44,9 +41,7 @@ import org.openhab.core.library.types.OnOffType; import org.openhab.core.thing.ChannelUID; import org.openhab.core.thing.ThingStatus; import org.openhab.core.thing.ThingStatusDetail; -import org.openhab.core.thing.ThingStatusInfo; import org.openhab.core.thing.ThingTypeUID; -import org.openhab.core.thing.ThingUID; /** * Unit tests for UserStateHandlerTest @@ -94,25 +89,41 @@ class UserStateHandlerTest extends AbstractBoschSHCHandlerTest } @ParameterizedTest() - @MethodSource("provideExceptions") - void testHandleCommandSetStateUpdatesThingStatusOnException(Exception mockException) + @MethodSource("org.openhab.binding.boschshc.internal.tests.common.CommonTestUtils#getExecutionExceptionAndInterruptedExceptionArguments()") + void testHandleCommandSetStateUpdatesThingStatusOnException(Exception exception) throws InterruptedException, TimeoutException, ExecutionException { - reset(getCallback()); - lenient().when(getBridgeHandler().putState(anyString(), anyString(), any(UserStateServiceState.class))) - .thenThrow(mockException); + when(getBridgeHandler().putState(anyString(), anyString(), any(UserStateServiceState.class))) + .thenThrow(exception); var channel = new ChannelUID(getThing().getUID(), BoschSHCBindingConstants.CHANNEL_USER_DEFINED_STATE); + getFixture().handleCommand(channel, OnOffType.ON); - verify(getCallback()).getBridge(any(ThingUID.class)); - - ThingStatusInfo expectedStatusInfo = new ThingStatusInfo(ThingStatus.OFFLINE, - ThingStatusDetail.COMMUNICATION_ERROR, - String.format("Error while putting user-defined state for %s", channel.getThingUID().getId())); - verify(getCallback()).statusUpdated(same(getThing()), eq(expectedStatusInfo)); + verify(getCallback()).statusUpdated(same(getThing()), + argThat(status -> status.getStatus().equals(ThingStatus.OFFLINE) + && status.getStatusDetail().equals(ThingStatusDetail.COMMUNICATION_ERROR))); } - private static Stream provideExceptions() { - return Stream.of(Arguments.of(new TimeoutException("test exception")), - Arguments.of(new InterruptedException("test exception"))); + @Test + void initializeWithoutId() { + when(getThing().getConfiguration()).thenReturn(new Configuration()); + + getFixture().initialize(); + + verify(getCallback()).statusUpdated(same(getThing()), + argThat(status -> status.getStatus().equals(ThingStatus.OFFLINE) + && status.getStatusDetail().equals(ThingStatusDetail.CONFIGURATION_ERROR))); + } + + @ParameterizedTest + @MethodSource("org.openhab.binding.boschshc.internal.tests.common.CommonTestUtils#getBoschShcAndExecutionAndTimeoutAndInterruptedExceptionArguments()") + void initializeHandleExceptions(Exception e) + throws BoschSHCException, InterruptedException, TimeoutException, ExecutionException { + when(getBridgeHandler().getUserStateInfo(anyString())).thenThrow(e); + + getFixture().initialize(); + + verify(getCallback()).statusUpdated(same(getThing()), + argThat(status -> status.getStatus().equals(ThingStatus.OFFLINE) + && status.getStatusDetail().equals(ThingStatusDetail.CONFIGURATION_ERROR))); } } diff --git a/bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/discovery/BridgeDiscoveryParticipantTest.java b/bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/discovery/BridgeDiscoveryParticipantTest.java index c98d24142f0..e145d9e7cd1 100644 --- a/bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/discovery/BridgeDiscoveryParticipantTest.java +++ b/bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/discovery/BridgeDiscoveryParticipantTest.java @@ -22,7 +22,9 @@ import static org.junit.jupiter.api.Assertions.assertSame; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import java.net.ConnectException; @@ -48,6 +50,7 @@ import org.mockito.quality.Strictness; import org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants; import org.openhab.binding.boschshc.internal.devices.bridge.dto.PublicInformation; import org.openhab.core.config.discovery.DiscoveryResult; +import org.openhab.core.io.net.http.HttpClientFactory; import org.openhab.core.thing.ThingUID; /** @@ -128,6 +131,7 @@ class BridgeDiscoveryParticipantTest { @Test void testCreateResult() throws Exception { DiscoveryResult result = fixture.createResult(shcBridge); + assertNotNull(result); assertThat(result.getBindingId(), is(BoschSHCBindingConstants.BINDING_ID)); assertThat(result.getThingUID().getId(), is("192-168-0-123")); @@ -138,19 +142,23 @@ class BridgeDiscoveryParticipantTest { @Test void testCreateResultOtherDevice() throws Exception { DiscoveryResult result = fixture.createResult(otherDevice); + assertNull(result); } @Test void testCreateResultNoIPAddress() throws Exception { when(shcBridge.getHostAddresses()).thenReturn(new String[] { "" }); + DiscoveryResult result = fixture.createResult(shcBridge); + assertNull(result); } @Test void testGetThingUID() throws Exception { ThingUID thingUID = fixture.getThingUID(shcBridge); + assertNotNull(thingUID); assertThat(thingUID.getBindingId(), is(BoschSHCBindingConstants.BINDING_ID)); assertThat(thingUID.getId(), is("192-168-0-123")); @@ -165,6 +173,7 @@ class BridgeDiscoveryParticipantTest { void testGetBridgeAddress() throws Exception { @Nullable PublicInformation bridgeInformation = fixture.discoverBridge("192.168.0.123"); + assertThat(bridgeInformation, not(nullValue())); assertThat(bridgeInformation.shcIpAddress, is("192.168.0.123")); } @@ -178,6 +187,7 @@ class BridgeDiscoveryParticipantTest { void testGetPublicInformationFromPossibleBridgeAddress() throws Exception { @Nullable PublicInformation bridgeInformation = fixture.getPublicInformationFromPossibleBridgeAddress("192.168.0.123"); + assertThat(bridgeInformation, not(nullValue())); assertThat(bridgeInformation.shcIpAddress, is("192.168.0.123")); } @@ -187,6 +197,7 @@ class BridgeDiscoveryParticipantTest { when(contentResponse.getContentAsString()).thenReturn("{\"nothing\":\"useful\"}"); fixture = new BridgeDiscoveryParticipant(mockHttpClient); + assertThat(fixture.getPublicInformationFromPossibleBridgeAddress("192.168.0.123"), is(nullValue())); } @@ -195,6 +206,7 @@ class BridgeDiscoveryParticipantTest { when(contentResponse.getStatus()).thenReturn(HttpStatus.BAD_REQUEST_400); fixture = new BridgeDiscoveryParticipant(mockHttpClient); + assertThat(fixture.getPublicInformationFromPossibleBridgeAddress("192.168.0.123"), is(nullValue())); } @@ -207,4 +219,13 @@ class BridgeDiscoveryParticipantTest { PublicInformation result2 = fixture.getOrComputePublicInformation("192.168.0.123"); assertSame(result, result2); } + + @Test + void testPublicConstructor() { + HttpClientFactory httpClientFactory = mock(HttpClientFactory.class); + + fixture = new BridgeDiscoveryParticipant(httpClientFactory); + + verify(httpClientFactory).createHttpClient(eq(BoschSHCBindingConstants.BINDING_ID), any()); + } } 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 92ce5dd4a13..cc5f5d58b4e 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 @@ -25,6 +25,7 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import java.util.ArrayList; +import java.util.List; import java.util.UUID; import org.eclipse.jdt.annotation.NonNullByDefault; @@ -77,10 +78,35 @@ class ThingDiscoveryServiceTest { when(bridgeHandler.getThing()).thenReturn(mockBridge); } + @Test + void initialize() { + fixture.initialize(); + verify(bridgeHandler).registerDiscoveryListener(fixture); + } + @Test void testStartScan() throws InterruptedException { mockBridgeCalls(); + Device device = new Device(); + device.name = "My Smart Plug"; + device.deviceModel = "PSM"; + device.id = "hdm:HomeMaticIP:3014F711A00004953859F31B"; + device.deviceServiceIds = List.of("PowerMeter", "PowerSwitch", "PowerSwitchProgram", "Routing"); + + List devices = new ArrayList<>(); + devices.add(device); + when(bridgeHandler.getDevices()).thenReturn(devices); + + UserDefinedState userDefinedState = new UserDefinedState(); + userDefinedState.setName("My State"); + userDefinedState.setId("23d34fa6-382a-444d-8aae-89c706e22158"); + userDefinedState.setState(true); + + List userDefinedStates = new ArrayList<>(); + userDefinedStates.add(userDefinedState); + when(bridgeHandler.getUserStates()).thenReturn(userDefinedStates); + fixture.activate(); fixture.startScan(); @@ -268,6 +294,15 @@ class ThingDiscoveryServiceTest { verify(discoveryListener, times(2)).thingDiscovered(any(), any()); } + @Test + void dispose() { + Bridge thing = mock(Bridge.class); + when(thing.getUID()).thenReturn(new ThingUID(BoschSHCBindingConstants.THING_TYPE_SHC, "shc123456")); + when(bridgeHandler.getThing()).thenReturn(thing); + fixture.dispose(); + verify(bridgeHandler).unregisterDiscoveryListener(); + } + @Test void getThingTypeUIDLightControl2ChildDevice() { Device device = new Device(); diff --git a/bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/services/userstate/dto/UserStateServiceStateTest.java b/bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/services/userstate/dto/UserStateServiceStateTest.java index 7d21e34eafe..f2e70ad55fc 100644 --- a/bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/services/userstate/dto/UserStateServiceStateTest.java +++ b/bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/services/userstate/dto/UserStateServiceStateTest.java @@ -71,4 +71,9 @@ class UserStateServiceStateTest { subject.setState(true); assertEquals(OnOffType.ON, subject.toOnOffType()); } + + @Test + void testToString() { + assertEquals("UserStateServiceState{state=false, type='userdefinedstates'}", subject.toString()); + } } diff --git a/bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/tests/common/CommonTestUtils.java b/bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/tests/common/CommonTestUtils.java new file mode 100644 index 00000000000..8298f9ea1f6 --- /dev/null +++ b/bundles/org.openhab.binding.boschshc/src/test/java/org/openhab/binding/boschshc/internal/tests/common/CommonTestUtils.java @@ -0,0 +1,67 @@ +/** + * Copyright (c) 2010-2024 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.binding.boschshc.internal.tests.common; + +import java.util.List; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeoutException; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.binding.boschshc.internal.exceptions.BoschSHCException; + +/** + * Common utilities used in unit tests. + * + * @author David Pace - Initial contribution + * + */ +@NonNullByDefault +public final class CommonTestUtils { + + public static final String TEST_EXCEPTION_MESSAGE = "Test exception"; + + private CommonTestUtils() { + // Utility Class + } + + public static List getExecutionExceptionAndInterruptedExceptionArguments() { + return List.of(new ExecutionException(TEST_EXCEPTION_MESSAGE, null), + new InterruptedException(TEST_EXCEPTION_MESSAGE)); + } + + public static List getExceutionExceptionAndRuntimeExceptionArguments() { + return List.of(new ExecutionException(TEST_EXCEPTION_MESSAGE, null), + new RuntimeException(TEST_EXCEPTION_MESSAGE)); + } + + public static List getBoschShcAndExecutionAndTimeoutExceptionArguments() { + return List.of(new BoschSHCException(TEST_EXCEPTION_MESSAGE), + new ExecutionException(TEST_EXCEPTION_MESSAGE, null), new TimeoutException(TEST_EXCEPTION_MESSAGE)); + } + + public static List getBoschShcAndExecutionAndTimeoutAndInterruptedExceptionArguments() { + return List.of(new BoschSHCException(TEST_EXCEPTION_MESSAGE), + new ExecutionException(TEST_EXCEPTION_MESSAGE, null), new TimeoutException(TEST_EXCEPTION_MESSAGE), + new InterruptedException(TEST_EXCEPTION_MESSAGE)); + } + + public static List getExecutionAndTimeoutAndInterruptedExceptionArguments() { + return List.of(new ExecutionException(TEST_EXCEPTION_MESSAGE, null), + new TimeoutException(TEST_EXCEPTION_MESSAGE), new InterruptedException(TEST_EXCEPTION_MESSAGE)); + } + + public static List getExecutionAndTimeoutExceptionArguments() { + return List.of(new ExecutionException(TEST_EXCEPTION_MESSAGE, null), + new TimeoutException(TEST_EXCEPTION_MESSAGE)); + } +}