use of org.openhab.core.thing.binding.ThingHandlerCallback in project openhab-core by openhab.
the class ThingManagerOSGiJavaTest method testCreateChannelBuilder.
@Test
public void testCreateChannelBuilder() throws Exception {
AtomicReference<ThingHandlerCallback> thc = initializeThingHandlerCallback();
ChannelBuilder channelBuilder = thc.get().createChannelBuilder(CHANNEL_UID, CHANNEL_TYPE_UID);
assertNotNull(channelBuilder);
validateChannel(channelBuilder.build());
}
use of org.openhab.core.thing.binding.ThingHandlerCallback in project openhab-core by openhab.
the class ThingManagerOSGiJavaTest method testEditChannelBuilder.
@Test
public void testEditChannelBuilder() throws Exception {
AtomicReference<ThingHandlerCallback> thc = initializeThingHandlerCallback();
ChannelBuilder channelBuilder = thc.get().editChannel(thing, CHANNEL_UID);
assertNotNull(channelBuilder);
validateChannel(channelBuilder.build());
}
use of org.openhab.core.thing.binding.ThingHandlerCallback in project openhab-core by openhab.
the class ThingManagerOSGiJavaTest method testSetEnabledWithHandler.
@Test
public void testSetEnabledWithHandler() throws Exception {
registerThingTypeProvider();
AtomicReference<ThingHandlerCallback> thingHandlerCallback = new AtomicReference<>();
AtomicReference<Boolean> initializeInvoked = new AtomicReference<>(false);
AtomicReference<Boolean> disposeInvoked = new AtomicReference<>(false);
registerThingHandlerFactory(THING_TYPE_UID, thing -> {
ThingHandler mockHandler = mock(ThingHandler.class);
doAnswer(a -> {
thingHandlerCallback.set((ThingHandlerCallback) a.getArguments()[0]);
return null;
}).when(mockHandler).setCallback(ArgumentMatchers.isA(ThingHandlerCallback.class));
doAnswer(a -> {
initializeInvoked.set(true);
// call thingUpdated() from within initialize()
thingHandlerCallback.get().thingUpdated(thing);
// hang on a little to provoke a potential dead-lock
Thread.sleep(1000);
ThingStatusInfo thingStatusInfo = ThingStatusInfoBuilder.create(ThingStatus.ONLINE, ThingStatusDetail.NONE).build();
thing.setStatusInfo(thingStatusInfo);
return null;
}).when(mockHandler).initialize();
doAnswer(a -> {
disposeInvoked.set(true);
return null;
}).when(mockHandler).dispose();
when(mockHandler.getThing()).thenReturn(thing);
return mockHandler;
});
ThingStatusInfo thingStatusInfo = ThingStatusInfoBuilder.create(ThingStatus.UNINITIALIZED, ThingStatusDetail.NONE).build();
thing.setStatusInfo(thingStatusInfo);
new Thread((Runnable) () -> managedThingProvider.add(thing)).start();
waitForAssert(() -> {
assertThat(initializeInvoked.get(), is(true));
assertThat(thing.getStatus(), is(ThingStatus.INITIALIZING));
});
// Reset the flag
initializeInvoked.set(false);
// Disable the thing
thingManager.setEnabled(THING_UID, false);
waitForAssert(() -> {
assertThat(storage.containsKey(THING_UID.getAsString()), is(true));
assertThat(disposeInvoked.get(), is(true));
assertThat(thing.getStatus(), is(ThingStatus.UNINITIALIZED));
assertThat(thing.getStatusInfo().getStatusDetail(), is(ThingStatusDetail.DISABLED));
}, SafeCaller.DEFAULT_TIMEOUT - 100, 50);
// Reset the flag
disposeInvoked.set(false);
// Enable the thing
thingManager.setEnabled(THING_UID, true);
waitForAssert(() -> {
assertThat(storage.containsKey(THING_UID.getAsString()), is(false));
assertThat(thing.getStatus(), is(ThingStatus.ONLINE));
});
}
use of org.openhab.core.thing.binding.ThingHandlerCallback in project openhab-core by openhab.
the class ThingManagerOSGiJavaTest method testInitializeNotInvokedOnAlreadyEnabledThing.
@Test
public void testInitializeNotInvokedOnAlreadyEnabledThing() {
AtomicReference<ThingHandlerCallback> thingHandlerCallback = new AtomicReference<>();
AtomicReference<Boolean> initializeInvoked = new AtomicReference<>(false);
AtomicReference<Boolean> disposeInvoked = new AtomicReference<>(false);
registerThingHandlerFactory(THING_TYPE_UID, thing -> {
ThingHandler mockHandler = mock(ThingHandler.class);
doAnswer(a -> {
thingHandlerCallback.set((ThingHandlerCallback) a.getArguments()[0]);
return null;
}).when(mockHandler).setCallback(ArgumentMatchers.isA(ThingHandlerCallback.class));
doAnswer(a -> {
initializeInvoked.set(true);
// call thingUpdated() from within initialize()
thingHandlerCallback.get().thingUpdated(thing);
// hang on a little to provoke a potential dead-lock
Thread.sleep(1000);
ThingStatusInfo thingStatusInfo = ThingStatusInfoBuilder.create(ThingStatus.ONLINE, ThingStatusDetail.NONE).build();
thing.setStatusInfo(thingStatusInfo);
return null;
}).when(mockHandler).initialize();
doAnswer(a -> {
disposeInvoked.set(true);
return null;
}).when(mockHandler).dispose();
when(mockHandler.getThing()).thenReturn(thing);
return mockHandler;
});
ThingStatusInfo enabledStatusInfo = ThingStatusInfoBuilder.create(ThingStatus.UNINITIALIZED, ThingStatusDetail.NONE).build();
thing.setStatusInfo(enabledStatusInfo);
new Thread((Runnable) () -> managedThingProvider.add(thing)).start();
waitForAssert(() -> {
assertThat(initializeInvoked.get(), is(true));
assertThat(thing.getStatus(), is(ThingStatus.INITIALIZING));
}, SafeCaller.DEFAULT_TIMEOUT - 100, 50);
initializeInvoked.set(false);
// enable the thing
new Thread((Runnable) () -> thingManager.setEnabled(thing.getUID(), true)).start();
waitForAssert(() -> {
assertThat(thing.getStatus(), is(ThingStatus.ONLINE));
assertThat(initializeInvoked.get(), is(false));
}, SafeCaller.DEFAULT_TIMEOUT - 100, 50);
}
use of org.openhab.core.thing.binding.ThingHandlerCallback in project openhab-core by openhab.
the class ThingManagerOSGiTest method thingManagerHandlesBridgeThingHandlerLifeCycleCorrectly.
@Test
@SuppressWarnings("null")
public void thingManagerHandlesBridgeThingHandlerLifeCycleCorrectly() {
initCalledCounter = 0;
disposedCalledCounter = 0;
class BridgeHandlerState {
boolean initCalled;
int initCalledOrder;
boolean disposedCalled;
int disposedCalledOrder;
@Nullable
ThingHandlerCallback callback;
boolean callbackWasNull;
}
final BridgeHandlerState bridgeState = new BridgeHandlerState();
Bridge bridge = BridgeBuilder.create(new ThingTypeUID("binding:test"), new ThingUID("binding:test:someBridgeUID-1")).build();
BridgeHandler bridgeHandler = mock(BridgeHandler.class);
doAnswer(new Answer<Void>() {
@Override
@Nullable
public Void answer(InvocationOnMock invocation) throws Throwable {
bridgeState.callback = (ThingHandlerCallback) invocation.getArgument(0);
return null;
}
}).when(bridgeHandler).setCallback(any(ThingHandlerCallback.class));
doAnswer(new Answer<Void>() {
@Override
@Nullable
public Void answer(InvocationOnMock invocation) throws Throwable {
bridgeState.initCalled = true;
bridgeState.initCalledOrder = ++initCalledCounter;
bridgeState.callback.statusUpdated(bridge, ThingStatusInfoBuilder.create(ThingStatus.ONLINE, ThingStatusDetail.NONE).build());
return null;
}
}).when(bridgeHandler).initialize();
doAnswer(new Answer<Void>() {
@Override
@Nullable
public Void answer(InvocationOnMock invocation) throws Throwable {
bridgeState.disposedCalled = true;
bridgeState.disposedCalledOrder = ++disposedCalledCounter;
bridgeState.callbackWasNull = bridgeState.callback == null;
return null;
}
}).when(bridgeHandler).dispose();
when(bridgeHandler.getThing()).thenReturn(bridge);
doAnswer(new Answer<Void>() {
@Override
@Nullable
public Void answer(InvocationOnMock invocation) throws Throwable {
bridgeState.callback.statusUpdated(bridge, ThingStatusInfoBuilder.create(ThingStatus.REMOVED).build());
return null;
}
}).when(bridgeHandler).handleRemoval();
class ThingHandlerState {
boolean initCalled;
int initCalledOrder;
boolean disposedCalled;
int disposedCalledOrder;
@Nullable
ThingHandlerCallback callback;
boolean callbackWasNull;
}
final ThingHandlerState thingState = new ThingHandlerState();
Thing thing = ThingBuilder.create(new ThingTypeUID("binding:test"), new ThingUID("binding:test:someThingUID-1")).withBridge(bridge.getUID()).build();
ThingHandler thingHandler = mock(ThingHandler.class);
doAnswer(new Answer<Void>() {
@Override
@Nullable
public Void answer(InvocationOnMock invocation) throws Throwable {
thingState.callback = (ThingHandlerCallback) invocation.getArgument(0);
return null;
}
}).when(thingHandler).setCallback(any(ThingHandlerCallback.class));
doAnswer(new Answer<Void>() {
@Override
@Nullable
public Void answer(InvocationOnMock invocation) throws Throwable {
thingState.initCalled = true;
thingState.initCalledOrder = ++initCalledCounter;
bridgeState.callback.statusUpdated(thing, ThingStatusInfoBuilder.create(ThingStatus.ONLINE, ThingStatusDetail.NONE).build());
return null;
}
}).when(thingHandler).initialize();
doAnswer(new Answer<Void>() {
@Override
@Nullable
public Void answer(InvocationOnMock invocation) throws Throwable {
thingState.disposedCalled = true;
thingState.disposedCalledOrder = ++disposedCalledCounter;
thingState.callbackWasNull = thingState.callback == null;
return null;
}
}).when(thingHandler).dispose();
when(thingHandler.getThing()).thenReturn(thing);
doAnswer(new Answer<Void>() {
@Override
@Nullable
public Void answer(InvocationOnMock invocation) throws Throwable {
bridgeState.callback.statusUpdated(thing, ThingStatusInfoBuilder.create(ThingStatus.REMOVED).build());
return null;
}
}).when(thingHandler).handleRemoval();
ThingHandlerFactory thingHandlerFactory = mock(ThingHandlerFactory.class);
when(thingHandlerFactory.supportsThingType(any(ThingTypeUID.class))).thenReturn(true);
doAnswer(new Answer<ThingHandler>() {
@Override
@Nullable
public ThingHandler answer(InvocationOnMock invocation) throws Throwable {
Thing thing = (Thing) invocation.getArgument(0);
if (thing instanceof Bridge) {
return bridgeHandler;
} else if (thing instanceof Thing) {
return thingHandler;
}
return null;
}
}).when(thingHandlerFactory).registerHandler(any(Thing.class));
registerService(thingHandlerFactory);
final ThingStatusInfo uninitializedNone = ThingStatusInfoBuilder.create(ThingStatus.UNINITIALIZED, ThingStatusDetail.NONE).build();
assertThat(thing.getStatusInfo(), is(uninitializedNone));
assertThat(bridge.getStatusInfo(), is(uninitializedNone));
assertThat(bridgeState.initCalled, is(false));
assertThat(bridgeState.initCalledOrder, is(0));
assertThat(bridgeState.disposedCalled, is(false));
assertThat(bridgeState.disposedCalledOrder, is(0));
assertThat(thingState.initCalled, is(false));
assertThat(thingState.initCalledOrder, is(0));
assertThat(thingState.disposedCalled, is(false));
assertThat(thingState.disposedCalled, is(false));
assertThat(thingState.disposedCalledOrder, is(0));
ThingRegistry thingRegistry = getService(ThingRegistry.class);
assertThat(thingRegistry, not(nullValue()));
// add thing - no thing initialization, because bridge is not available
thingRegistry.add(thing);
waitForAssert(() -> assertThat(thingState.initCalled, is(false)));
final ThingStatusInfo bridgeUninitialized = ThingStatusInfoBuilder.create(ThingStatus.UNINITIALIZED, ThingStatusDetail.BRIDGE_UNINITIALIZED).build();
waitForAssert(() -> assertThat(thing.getStatusInfo(), is(bridgeUninitialized)));
// add bridge - provokes bridge & thing initialization
thingRegistry.add(bridge);
waitForAssert(() -> assertThat(bridgeState.initCalled, is(true)));
waitForAssert(() -> assertThat(bridgeState.initCalledOrder, is(1)));
waitForAssert(() -> assertThat(thingState.initCalled, is(true)));
waitForAssert(() -> assertThat(thingState.initCalledOrder, is(2)));
bridgeState.initCalled = false;
thingState.initCalled = false;
final ThingStatusInfo onlineNone = ThingStatusInfoBuilder.create(ThingStatus.ONLINE, ThingStatusDetail.NONE).build();
waitForAssert(() -> assertThat(thing.getStatusInfo(), is(onlineNone)));
waitForAssert(() -> assertThat(bridge.getStatusInfo(), is(onlineNone)));
// remove thing - provokes thing disposal
bridgeState.callbackWasNull = false;
thingState.callbackWasNull = false;
thingRegistry.remove(thing.getUID());
waitForAssert(() -> assertThat(thingState.disposedCalled, is(true)));
waitForAssert(() -> assertThat(thingState.disposedCalledOrder, is(1)));
thingState.disposedCalled = false;
waitForAssert(() -> assertThat(bridge.getStatusInfo(), is(onlineNone)));
final ThingStatusInfo thingUninitializedHandlerMissingError = ThingStatusInfoBuilder.create(ThingStatus.UNINITIALIZED, ThingStatusDetail.HANDLER_MISSING_ERROR).build();
waitForAssert(() -> assertThat(thing.getStatusInfo(), is(thingUninitializedHandlerMissingError)));
assertThat(thingState.callbackWasNull, is(false));
// add thing again - provokes thing initialization
thingRegistry.add(thing);
waitForAssert(() -> assertThat(thingState.initCalled, is(true)));
waitForAssert(() -> assertThat(thingState.initCalledOrder, is(3)));
thingState.initCalled = false;
waitForAssert(() -> assertThat(thing.getStatusInfo(), is(onlineNone)));
// remove bridge - provokes thing & bridge disposal
bridgeState.callbackWasNull = false;
thingState.callbackWasNull = false;
thingRegistry.remove(bridge.getUID());
waitForAssert(() -> assertThat(thingState.disposedCalled, is(true)));
waitForAssert(() -> assertThat(thingState.disposedCalledOrder, is(2)));
waitForAssert(() -> assertThat(bridgeState.disposedCalled, is(true)));
waitForAssert(() -> assertThat(bridgeState.disposedCalledOrder, is(3)));
thingState.disposedCalled = false;
bridgeState.disposedCalled = false;
waitForAssert(() -> assertThat(thing.getStatusInfo(), is(thingUninitializedHandlerMissingError)));
waitForAssert(() -> assertThat(bridge.getStatusInfo(), is(thingUninitializedHandlerMissingError)));
assertThat(bridgeState.callbackWasNull, is(false));
assertThat(thingState.callbackWasNull, is(false));
// add bridge again
thingRegistry.add(bridge);
waitForAssert(() -> assertThat(bridgeState.initCalled, is(true)));
waitForAssert(() -> assertThat(bridgeState.initCalledOrder, is(4)));
waitForAssert(() -> assertThat(thingState.initCalled, is(true)));
waitForAssert(() -> assertThat(thingState.initCalledOrder, is(5)));
bridgeState.initCalled = false;
thingState.initCalled = false;
waitForAssert(() -> assertThat(thing.getStatusInfo(), is(onlineNone)));
waitForAssert(() -> assertThat(bridge.getStatusInfo(), is(onlineNone)));
// unregister factory
bridgeState.callbackWasNull = false;
thingState.callbackWasNull = false;
unregisterService(thingHandlerFactory);
waitForAssert(() -> assertThat(thingState.disposedCalled, is(true)));
waitForAssert(() -> assertThat(thingState.disposedCalledOrder, is(4)));
waitForAssert(() -> assertThat(bridgeState.disposedCalled, is(true)));
waitForAssert(() -> assertThat(bridgeState.disposedCalledOrder, is(5)));
waitForAssert(() -> assertThat(thing.getStatusInfo(), is(thingUninitializedHandlerMissingError)));
waitForAssert(() -> assertThat(bridge.getStatusInfo(), is(thingUninitializedHandlerMissingError)));
assertThat(bridgeState.callbackWasNull, is(false));
assertThat(thingState.callbackWasNull, is(false));
}
Aggregations