]> git.basschouten.com Git - openhab-addons.git/blob
57b78ead6e22d95bc4f982fcb01aa2fa33550c6e
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2022 Contributors to the openHAB project
3  *
4  * See the NOTICE file(s) distributed with this work for additional
5  * information.
6  *
7  * This program and the accompanying materials are made available under the
8  * terms of the Eclipse Public License 2.0 which is available at
9  * http://www.eclipse.org/legal/epl-2.0
10  *
11  * SPDX-License-Identifier: EPL-2.0
12  */
13 package org.openhab.binding.systeminfo.test;
14
15 import static java.lang.Thread.sleep;
16 import static java.util.stream.Collectors.toList;
17 import static org.hamcrest.CoreMatchers.*;
18 import static org.hamcrest.MatcherAssert.assertThat;
19 import static org.junit.jupiter.api.Assertions.assertFalse;
20 import static org.mockito.Mockito.*;
21
22 import java.math.BigDecimal;
23 import java.net.UnknownHostException;
24 import java.util.Hashtable;
25 import java.util.List;
26
27 import org.eclipse.jdt.annotation.NonNullByDefault;
28 import org.eclipse.jdt.annotation.Nullable;
29 import org.junit.jupiter.api.AfterEach;
30 import org.junit.jupiter.api.BeforeEach;
31 import org.junit.jupiter.api.Test;
32 import org.junit.jupiter.api.extension.ExtendWith;
33 import org.mockito.Mock;
34 import org.mockito.junit.jupiter.MockitoExtension;
35 import org.openhab.binding.systeminfo.internal.SysteminfoBindingConstants;
36 import org.openhab.binding.systeminfo.internal.SysteminfoHandlerFactory;
37 import org.openhab.binding.systeminfo.internal.SysteminfoThingTypeProvider;
38 import org.openhab.binding.systeminfo.internal.discovery.SysteminfoDiscoveryService;
39 import org.openhab.binding.systeminfo.internal.handler.SysteminfoHandler;
40 import org.openhab.binding.systeminfo.internal.model.DeviceNotFoundException;
41 import org.openhab.binding.systeminfo.internal.model.OSHISysteminfo;
42 import org.openhab.binding.systeminfo.internal.model.SysteminfoInterface;
43 import org.openhab.core.config.core.Configuration;
44 import org.openhab.core.config.discovery.DiscoveryResult;
45 import org.openhab.core.config.discovery.DiscoveryService;
46 import org.openhab.core.config.discovery.inbox.Inbox;
47 import org.openhab.core.config.discovery.inbox.InboxPredicates;
48 import org.openhab.core.items.GenericItem;
49 import org.openhab.core.items.ItemNotFoundException;
50 import org.openhab.core.items.ItemRegistry;
51 import org.openhab.core.library.items.NumberItem;
52 import org.openhab.core.library.items.StringItem;
53 import org.openhab.core.library.types.DecimalType;
54 import org.openhab.core.library.types.PercentType;
55 import org.openhab.core.library.types.StringType;
56 import org.openhab.core.test.java.JavaOSGiTest;
57 import org.openhab.core.test.storage.VolatileStorageService;
58 import org.openhab.core.thing.Channel;
59 import org.openhab.core.thing.ChannelUID;
60 import org.openhab.core.thing.ManagedThingProvider;
61 import org.openhab.core.thing.Thing;
62 import org.openhab.core.thing.ThingProvider;
63 import org.openhab.core.thing.ThingRegistry;
64 import org.openhab.core.thing.ThingStatus;
65 import org.openhab.core.thing.ThingStatusDetail;
66 import org.openhab.core.thing.ThingTypeUID;
67 import org.openhab.core.thing.ThingUID;
68 import org.openhab.core.thing.binding.ThingHandler;
69 import org.openhab.core.thing.binding.ThingHandlerFactory;
70 import org.openhab.core.thing.binding.ThingTypeProvider;
71 import org.openhab.core.thing.binding.builder.ChannelBuilder;
72 import org.openhab.core.thing.binding.builder.ThingBuilder;
73 import org.openhab.core.thing.link.ItemChannelLink;
74 import org.openhab.core.thing.link.ManagedItemChannelLinkProvider;
75 import org.openhab.core.thing.type.ChannelKind;
76 import org.openhab.core.thing.type.ChannelTypeUID;
77 import org.openhab.core.types.State;
78 import org.openhab.core.types.UnDefType;
79
80 /**
81  * OSGi tests for the {@link SysteminfoHandler}
82  *
83  * @author Svilen Valkanov - Initial contribution
84  * @author Lyubomir Papazov - Created a mock systeminfo object. This way, access to the user's OS will not be required,
85  *         but mock data will be used instead, avoiding potential errors from the OS queries.
86  * @author Wouter Born - Migrate Groovy to Java tests
87  */
88 @NonNullByDefault
89 @ExtendWith(MockitoExtension.class)
90 public class SysteminfoOSGiTest extends JavaOSGiTest {
91     private static final String DEFAULT_TEST_THING_NAME = "work";
92     private static final String DEFAULT_TEST_ITEM_NAME = "test";
93     private static final String DEFAULT_CHANNEL_TEST_PRIORITY = "High";
94     private static final int DEFAULT_CHANNEL_PID = -1;
95     private static final String DEFAULT_TEST_CHANNEL_ID = SysteminfoBindingConstants.CHANNEL_CPU_LOAD;
96     private static final int DEFAULT_DEVICE_INDEX = 0;
97
98     /**
99      * Refresh time in seconds for tasks with priority High.
100      * Default value for the parameter interval_high in the thing configuration
101      */
102     private static final int DEFAULT_TEST_INTERVAL_HIGH = 1;
103
104     /**
105      * Refresh time in seconds for tasks with priority Medium.
106      */
107     private static final int DEFAULT_TEST_INTERVAL_MEDIUM = 3;
108
109     private @Nullable Thing systemInfoThing;
110     private @Nullable GenericItem testItem;
111
112     private @Mock @NonNullByDefault({}) OSHISysteminfo mockedSystemInfo;
113     private @NonNullByDefault({}) SysteminfoHandlerFactory systeminfoHandlerFactory;
114     private @NonNullByDefault({}) ThingRegistry thingRegistry;
115     private @NonNullByDefault({}) ItemRegistry itemRegistry;
116
117     @BeforeEach
118     public void setUp() {
119         VolatileStorageService volatileStorageService = new VolatileStorageService();
120         registerService(volatileStorageService);
121
122         // Preparing the mock with OS properties, that are used in the initialize method of SysteminfoHandler
123         // Make this lenient because the assertInvalidThingConfigurationValuesAreHandled test does not require them
124         lenient().when(mockedSystemInfo.getCpuLogicalCores()).thenReturn(new DecimalType(2));
125         lenient().when(mockedSystemInfo.getCpuPhysicalCores()).thenReturn(new DecimalType(2));
126         lenient().when(mockedSystemInfo.getOsFamily()).thenReturn(new StringType("Mock OS"));
127         lenient().when(mockedSystemInfo.getOsManufacturer()).thenReturn(new StringType("Mock OS Manufacturer"));
128         lenient().when(mockedSystemInfo.getOsVersion()).thenReturn(new StringType("Mock Os Version"));
129         // Following mock method returns will make sure the thing does not get recreated with extra channels
130         lenient().when(mockedSystemInfo.getNetworkIFCount()).thenReturn(1);
131         lenient().when(mockedSystemInfo.getDisplayCount()).thenReturn(1);
132         lenient().when(mockedSystemInfo.getFileOSStoreCount()).thenReturn(1);
133         lenient().when(mockedSystemInfo.getPowerSourceCount()).thenReturn(1);
134         lenient().when(mockedSystemInfo.getDriveCount()).thenReturn(1);
135         lenient().when(mockedSystemInfo.getFanCount()).thenReturn(1);
136
137         registerService(mockedSystemInfo);
138
139         waitForAssert(() -> {
140             systeminfoHandlerFactory = getService(ThingHandlerFactory.class, SysteminfoHandlerFactory.class);
141             assertThat(systeminfoHandlerFactory, is(notNullValue()));
142         });
143         if (systeminfoHandlerFactory != null) {
144             // Unbind oshiSystemInfo service and bind the mock service to make the systeminfo binding tests independent
145             // of the external OSHI library
146             SysteminfoInterface oshiSystemInfo = getService(SysteminfoInterface.class);
147             if (oshiSystemInfo != null) {
148                 systeminfoHandlerFactory.unbindSystemInfo(oshiSystemInfo);
149             }
150             systeminfoHandlerFactory.bindSystemInfo(mockedSystemInfo);
151         }
152
153         waitForAssert(() -> {
154             ThingTypeProvider thingTypeProvider = getService(ThingTypeProvider.class,
155                     SysteminfoThingTypeProvider.class);
156             assertThat(thingTypeProvider, is(notNullValue()));
157         });
158         waitForAssert(() -> {
159             SysteminfoThingTypeProvider systeminfoThingTypeProvider = getService(SysteminfoThingTypeProvider.class);
160             assertThat(systeminfoThingTypeProvider, is(notNullValue()));
161         });
162
163         waitForAssert(() -> {
164             thingRegistry = getService(ThingRegistry.class);
165             assertThat(thingRegistry, is(notNullValue()));
166         });
167
168         waitForAssert(() -> {
169             itemRegistry = getService(ItemRegistry.class);
170             assertThat(itemRegistry, is(notNullValue()));
171         });
172     }
173
174     @AfterEach
175     public void tearDown() {
176         Thing thing = systemInfoThing;
177         if (thing != null) {
178             // Remove the systeminfo thing. The handler will be also disposed automatically
179             Thing removedThing = thingRegistry.forceRemove(thing.getUID());
180             assertThat("The systeminfo thing cannot be deleted", removedThing, is(notNullValue()));
181             waitForAssert(() -> {
182                 ThingHandler systemInfoHandler = thing.getHandler();
183                 assertThat(systemInfoHandler, is(nullValue()));
184             });
185         }
186
187         if (testItem != null) {
188             itemRegistry.remove(DEFAULT_TEST_ITEM_NAME);
189         }
190
191         unregisterService(mockedSystemInfo);
192     }
193
194     private void initializeThingWithChannelAndPID(String channelID, String acceptedItemType, int pid) {
195         Configuration thingConfig = new Configuration();
196         thingConfig.put(SysteminfoBindingConstants.HIGH_PRIORITY_REFRESH_TIME,
197                 new BigDecimal(DEFAULT_TEST_INTERVAL_HIGH));
198         thingConfig.put(SysteminfoBindingConstants.MEDIUM_PRIORITY_REFRESH_TIME,
199                 new BigDecimal(DEFAULT_TEST_INTERVAL_MEDIUM));
200         String priority = DEFAULT_CHANNEL_TEST_PRIORITY;
201
202         initializeThing(thingConfig, channelID, acceptedItemType, priority, pid);
203     }
204
205     private void initializeThingWithChannelAndPriority(String channelID, String acceptedItemType, String priority) {
206         Configuration thingConfig = new Configuration();
207         thingConfig.put(SysteminfoBindingConstants.HIGH_PRIORITY_REFRESH_TIME,
208                 new BigDecimal(DEFAULT_TEST_INTERVAL_HIGH));
209         thingConfig.put(SysteminfoBindingConstants.MEDIUM_PRIORITY_REFRESH_TIME,
210                 new BigDecimal(DEFAULT_TEST_INTERVAL_MEDIUM));
211         int pid = DEFAULT_CHANNEL_PID;
212
213         initializeThing(thingConfig, channelID, acceptedItemType, priority, pid);
214     }
215
216     private void initializeThingWithConfiguration(Configuration config) {
217         String priority = DEFAULT_CHANNEL_TEST_PRIORITY;
218         String channelID = DEFAULT_TEST_CHANNEL_ID;
219         String acceptedItemType = "String";
220         int pid = DEFAULT_CHANNEL_PID;
221
222         initializeThing(config, channelID, acceptedItemType, priority, pid);
223     }
224
225     private void initializeThingWithChannel(String channelID, String acceptedItemType) {
226         Configuration thingConfig = new Configuration();
227         thingConfig.put(SysteminfoBindingConstants.HIGH_PRIORITY_REFRESH_TIME,
228                 new BigDecimal(DEFAULT_TEST_INTERVAL_HIGH));
229         thingConfig.put(SysteminfoBindingConstants.MEDIUM_PRIORITY_REFRESH_TIME,
230                 new BigDecimal(DEFAULT_TEST_INTERVAL_MEDIUM));
231
232         String priority = DEFAULT_CHANNEL_TEST_PRIORITY;
233         int pid = DEFAULT_CHANNEL_PID;
234         initializeThing(thingConfig, channelID, acceptedItemType, priority, pid);
235     }
236
237     private void initializeThing(Configuration thingConfiguration, String channelID, String acceptedItemType,
238             String priority, int pid) {
239         ThingTypeUID thingTypeUID = SysteminfoBindingConstants.THING_TYPE_COMPUTER;
240         ThingUID thingUID = new ThingUID(thingTypeUID, DEFAULT_TEST_THING_NAME);
241
242         ChannelUID channelUID = new ChannelUID(thingUID, channelID);
243         ChannelTypeUID channelTypeUID = new ChannelTypeUID(SysteminfoBindingConstants.BINDING_ID,
244                 channelUID.getIdWithoutGroup());
245         Configuration channelConfig = new Configuration();
246         channelConfig.put("priority", priority);
247         channelConfig.put("pid", new BigDecimal(pid));
248         Channel channel = ChannelBuilder.create(channelUID, acceptedItemType).withType(channelTypeUID)
249                 .withKind(ChannelKind.STATE).withConfiguration(channelConfig).build();
250
251         Thing thing = ThingBuilder.create(thingTypeUID, thingUID).withConfiguration(thingConfiguration)
252                 .withChannel(channel).build();
253         systemInfoThing = thing;
254
255         ManagedThingProvider managedThingProvider = getService(ThingProvider.class, ManagedThingProvider.class);
256         assertThat(managedThingProvider, is(notNullValue()));
257
258         if (managedThingProvider != null) {
259             managedThingProvider.add(thing);
260         }
261
262         waitForAssert(() -> {
263             SysteminfoHandler handler = (SysteminfoHandler) thing.getHandler();
264             assertThat(handler, is(notNullValue()));
265         });
266
267         waitForAssert(() -> {
268             assertThat("Thing is not initialized, before an Item is created", thing.getStatus(),
269                     anyOf(equalTo(ThingStatus.OFFLINE), equalTo(ThingStatus.ONLINE)));
270         });
271
272         intializeItem(channelUID, DEFAULT_TEST_ITEM_NAME, acceptedItemType);
273     }
274
275     private void assertItemState(String acceptedItemType, String itemName, String priority, State expectedState) {
276         Thing thing = systemInfoThing;
277         if (thing == null) {
278             throw new AssertionError("Thing is null");
279         }
280         waitForAssert(() -> {
281             ThingStatusDetail thingStatusDetail = thing.getStatusInfo().getStatusDetail();
282             String description = thing.getStatusInfo().getDescription();
283             assertThat("Thing status detail is " + thingStatusDetail + " with description " + description,
284                     thing.getStatus(), is(equalTo(ThingStatus.ONLINE)));
285         });
286         // The binding starts all refresh tasks in SysteminfoHandler.scheduleUpdates() after this delay !
287         try {
288             sleep(SysteminfoHandler.WAIT_TIME_CHANNEL_ITEM_LINK_INIT * 1000);
289         } catch (InterruptedException e) {
290             throw new AssertionError("Interrupted while sleeping");
291         }
292
293         GenericItem item;
294         try {
295             item = (GenericItem) itemRegistry.getItem(itemName);
296         } catch (ItemNotFoundException e) {
297             throw new AssertionError("Item not found in registry");
298         }
299
300         int waitTime;
301         if ("High".equals(priority)) {
302             waitTime = DEFAULT_TEST_INTERVAL_HIGH * 1000;
303         } else if ("Medium".equals(priority)) {
304             waitTime = DEFAULT_TEST_INTERVAL_MEDIUM * 1000;
305         } else {
306             waitTime = 100;
307         }
308
309         waitForAssert(() -> {
310             State itemState = item.getState();
311             assertThat(itemState, is(equalTo(expectedState)));
312         }, waitTime, DFL_SLEEP_TIME);
313     }
314
315     private void intializeItem(ChannelUID channelUID, String itemName, String acceptedItemType) {
316         GenericItem item = null;
317         if ("Number".equals(acceptedItemType)) {
318             item = new NumberItem(itemName);
319         } else if ("String".equals(acceptedItemType)) {
320             item = new StringItem(itemName);
321         }
322         if (item == null) {
323             throw new AssertionError("Item is null");
324         }
325         itemRegistry.add(item);
326         testItem = item;
327
328         ManagedItemChannelLinkProvider itemChannelLinkProvider = getService(ManagedItemChannelLinkProvider.class);
329         assertThat(itemChannelLinkProvider, is(notNullValue()));
330
331         if (itemChannelLinkProvider == null) {
332             return;
333         }
334
335         itemChannelLinkProvider.add(new ItemChannelLink(itemName, channelUID));
336     }
337
338     @Test
339     public void assertInvalidThingConfigurationValuesAreHandled() {
340         Configuration configuration = new Configuration();
341
342         // invalid value - must be positive
343         int refreshIntervalHigh = -5;
344         configuration.put(SysteminfoBindingConstants.HIGH_PRIORITY_REFRESH_TIME, new BigDecimal(refreshIntervalHigh));
345
346         int refreshIntervalMedium = 3;
347         configuration.put(SysteminfoBindingConstants.MEDIUM_PRIORITY_REFRESH_TIME,
348                 new BigDecimal(refreshIntervalMedium));
349         initializeThingWithConfiguration(configuration);
350
351         testInvalidConfiguration();
352     }
353
354     private void testInvalidConfiguration() {
355         waitForAssert(() -> {
356             Thing thing = systemInfoThing;
357             if (thing != null) {
358                 assertThat("Invalid configuration is used !", thing.getStatus(), is(equalTo(ThingStatus.OFFLINE)));
359                 assertThat(thing.getStatusInfo().getStatusDetail(),
360                         is(equalTo(ThingStatusDetail.HANDLER_INITIALIZING_ERROR)));
361                 assertThat(thing.getStatusInfo().getDescription(), is(equalTo("@text/offline.cannot-initialize")));
362             }
363         });
364     }
365
366     @Test
367     public void assertMediumPriorityChannelIsUpdated() {
368         String channnelID = DEFAULT_TEST_CHANNEL_ID;
369         String acceptedItemType = "Number";
370         String priority = "Medium";
371
372         initializeThingWithChannelAndPriority(channnelID, acceptedItemType, priority);
373         assertItemState(acceptedItemType, DEFAULT_TEST_ITEM_NAME, priority, UnDefType.UNDEF);
374     }
375
376     @Test
377     public void assertStateOfSecondDeviceIsUpdated() {
378         // This test assumes that at least 2 network interfaces are present on the test platform
379         int deviceIndex = 1;
380         String channnelID = "network" + deviceIndex + "#mac";
381         String acceptedItemType = "String";
382
383         initializeThingWithChannel(channnelID, acceptedItemType);
384         assertItemState(acceptedItemType, DEFAULT_TEST_ITEM_NAME, DEFAULT_CHANNEL_TEST_PRIORITY, UnDefType.UNDEF);
385     }
386
387     @Test
388     public void assertChannelCpuLoadIsUpdated() {
389         String channnelID = SysteminfoBindingConstants.CHANNEL_CPU_LOAD;
390         String acceptedItemType = "Number";
391
392         PercentType mockedCpuLoadValue = new PercentType(9);
393         when(mockedSystemInfo.getSystemCpuLoad()).thenReturn(mockedCpuLoadValue);
394
395         initializeThingWithChannel(channnelID, acceptedItemType);
396         assertItemState(acceptedItemType, DEFAULT_TEST_ITEM_NAME, DEFAULT_CHANNEL_TEST_PRIORITY, mockedCpuLoadValue);
397     }
398
399     @Test
400     public void assertChannelCpuLoad1IsUpdated() {
401         String channnelID = SysteminfoBindingConstants.CHANNEL_CPU_LOAD_1;
402         String acceptedItemType = "Number";
403
404         DecimalType mockedCpuLoad1Value = new DecimalType(1.1);
405         when(mockedSystemInfo.getCpuLoad1()).thenReturn(mockedCpuLoad1Value);
406
407         initializeThingWithChannel(channnelID, acceptedItemType);
408         assertItemState(acceptedItemType, DEFAULT_TEST_ITEM_NAME, DEFAULT_CHANNEL_TEST_PRIORITY, mockedCpuLoad1Value);
409     }
410
411     @Test
412     public void assertChannelCpuLoad5IsUpdated() {
413         String channnelID = SysteminfoBindingConstants.CHANNEL_CPU_LOAD_5;
414         String acceptedItemType = "Number";
415
416         DecimalType mockedCpuLoad5Value = new DecimalType(5.5);
417         when(mockedSystemInfo.getCpuLoad5()).thenReturn(mockedCpuLoad5Value);
418
419         initializeThingWithChannel(channnelID, acceptedItemType);
420         assertItemState(acceptedItemType, DEFAULT_TEST_ITEM_NAME, DEFAULT_CHANNEL_TEST_PRIORITY, mockedCpuLoad5Value);
421     }
422
423     @Test
424     public void assertChannelCpuLoad15IsUpdated() {
425         String channnelID = SysteminfoBindingConstants.CHANNEL_CPU_LOAD_15;
426         String acceptedItemType = "Number";
427
428         DecimalType mockedCpuLoad15Value = new DecimalType(15.15);
429         when(mockedSystemInfo.getCpuLoad15()).thenReturn(mockedCpuLoad15Value);
430
431         initializeThingWithChannel(channnelID, acceptedItemType);
432         assertItemState(acceptedItemType, DEFAULT_TEST_ITEM_NAME, DEFAULT_CHANNEL_TEST_PRIORITY, mockedCpuLoad15Value);
433     }
434
435     @Test
436     public void assertChannelCpuThreadsIsUpdated() {
437         String channnelID = SysteminfoBindingConstants.CHANNEL_CPU_THREADS;
438         String acceptedItemType = "Number";
439
440         DecimalType mockedCpuThreadsValue = new DecimalType(16);
441         when(mockedSystemInfo.getCpuThreads()).thenReturn(mockedCpuThreadsValue);
442
443         initializeThingWithChannel(channnelID, acceptedItemType);
444         assertItemState(acceptedItemType, DEFAULT_TEST_ITEM_NAME, DEFAULT_CHANNEL_TEST_PRIORITY, mockedCpuThreadsValue);
445     }
446
447     @Test
448     public void assertChannelCpuUptimeIsUpdated() {
449         String channnelID = SysteminfoBindingConstants.CHANNEL_CPU_UPTIME;
450         String acceptedItemType = "Number";
451
452         DecimalType mockedCpuUptimeValue = new DecimalType(100);
453         when(mockedSystemInfo.getCpuUptime()).thenReturn(mockedCpuUptimeValue);
454
455         initializeThingWithChannel(channnelID, acceptedItemType);
456         assertItemState(acceptedItemType, DEFAULT_TEST_ITEM_NAME, DEFAULT_CHANNEL_TEST_PRIORITY, mockedCpuUptimeValue);
457     }
458
459     @Test
460     public void assertChannelCpuDescriptionIsUpdated() {
461         String channnelID = SysteminfoBindingConstants.CHANNEL_CPU_DESCRIPTION;
462         String acceptedItemType = "String";
463
464         StringType mockedCpuDescriptionValue = new StringType("Mocked Cpu Descr");
465         when(mockedSystemInfo.getCpuDescription()).thenReturn(mockedCpuDescriptionValue);
466
467         initializeThingWithChannel(channnelID, acceptedItemType);
468         assertItemState(acceptedItemType, DEFAULT_TEST_ITEM_NAME, DEFAULT_CHANNEL_TEST_PRIORITY,
469                 mockedCpuDescriptionValue);
470     }
471
472     @Test
473     public void assertChannelCpuNameIsUpdated() {
474         String channnelID = SysteminfoBindingConstants.CHANNEL_CPU_NAME;
475         String acceptedItemType = "String";
476
477         StringType mockedCpuNameValue = new StringType("Mocked Cpu Name");
478         when(mockedSystemInfo.getCpuName()).thenReturn(mockedCpuNameValue);
479
480         initializeThingWithChannel(channnelID, acceptedItemType);
481         assertItemState(acceptedItemType, DEFAULT_TEST_ITEM_NAME, DEFAULT_CHANNEL_TEST_PRIORITY, mockedCpuNameValue);
482     }
483
484     @Test
485     public void assertChannelMemoryAvailableIsUpdated() {
486         String channnelID = SysteminfoBindingConstants.CHANNEL_MEMORY_AVAILABLE;
487         String acceptedItemType = "Number";
488
489         DecimalType mockedMemoryAvailableValue = new DecimalType(1000);
490         when(mockedSystemInfo.getMemoryAvailable()).thenReturn(mockedMemoryAvailableValue);
491
492         initializeThingWithChannel(channnelID, acceptedItemType);
493         assertItemState(acceptedItemType, DEFAULT_TEST_ITEM_NAME, DEFAULT_CHANNEL_TEST_PRIORITY,
494                 mockedMemoryAvailableValue);
495     }
496
497     @Test
498     public void assertChannelMemoryUsedIsUpdated() {
499         String channnelID = SysteminfoBindingConstants.CHANNEL_MEMORY_USED;
500         String acceptedItemType = "Number";
501
502         DecimalType mockedMemoryUsedValue = new DecimalType(24);
503         when(mockedSystemInfo.getMemoryUsed()).thenReturn(mockedMemoryUsedValue);
504
505         initializeThingWithChannel(channnelID, acceptedItemType);
506         assertItemState(acceptedItemType, DEFAULT_TEST_ITEM_NAME, DEFAULT_CHANNEL_TEST_PRIORITY, mockedMemoryUsedValue);
507     }
508
509     @Test
510     public void assertChannelMemoryTotalIsUpdated() {
511         String channnelID = SysteminfoBindingConstants.CHANNEL_MEMORY_TOTAL;
512         String acceptedItemType = "Number";
513
514         DecimalType mockedMemoryTotalValue = new DecimalType(1024);
515         when(mockedSystemInfo.getMemoryTotal()).thenReturn(mockedMemoryTotalValue);
516
517         initializeThingWithChannel(channnelID, acceptedItemType);
518         assertItemState(acceptedItemType, DEFAULT_TEST_ITEM_NAME, DEFAULT_CHANNEL_TEST_PRIORITY,
519                 mockedMemoryTotalValue);
520     }
521
522     @Test
523     public void assertChannelMemoryAvailablePercentIsUpdated() {
524         String channnelID = SysteminfoBindingConstants.CHANNEL_MEMORY_AVAILABLE_PERCENT;
525         String acceptedItemType = "Number";
526
527         DecimalType mockedMemoryAvailablePercentValue = new DecimalType(97);
528         when(mockedSystemInfo.getMemoryAvailablePercent()).thenReturn(mockedMemoryAvailablePercentValue);
529
530         initializeThingWithChannel(channnelID, acceptedItemType);
531         assertItemState(acceptedItemType, DEFAULT_TEST_ITEM_NAME, DEFAULT_CHANNEL_TEST_PRIORITY,
532                 mockedMemoryAvailablePercentValue);
533     }
534
535     @Test
536     public void assertChannelSwapAvailableIsUpdated() {
537         String channnelID = SysteminfoBindingConstants.CHANNEL_SWAP_AVAILABLE;
538         String acceptedItemType = "Number";
539
540         DecimalType mockedSwapAvailableValue = new DecimalType(482);
541         when(mockedSystemInfo.getSwapAvailable()).thenReturn(mockedSwapAvailableValue);
542
543         initializeThingWithChannel(channnelID, acceptedItemType);
544         assertItemState(acceptedItemType, DEFAULT_TEST_ITEM_NAME, DEFAULT_CHANNEL_TEST_PRIORITY,
545                 mockedSwapAvailableValue);
546     }
547
548     @Test
549     public void assertChannelSwapUsedIsUpdated() {
550         String channnelID = SysteminfoBindingConstants.CHANNEL_SWAP_USED;
551         String acceptedItemType = "Number";
552
553         DecimalType mockedSwapUsedValue = new DecimalType(30);
554         when(mockedSystemInfo.getSwapUsed()).thenReturn(mockedSwapUsedValue);
555
556         initializeThingWithChannel(channnelID, acceptedItemType);
557         assertItemState(acceptedItemType, DEFAULT_TEST_ITEM_NAME, DEFAULT_CHANNEL_TEST_PRIORITY, mockedSwapUsedValue);
558     }
559
560     @Test
561     public void assertChannelSwapTotalIsUpdated() {
562         String channnelID = SysteminfoBindingConstants.CHANNEL_SWAP_TOTAL;
563         String acceptedItemType = "Number";
564
565         DecimalType mockedSwapTotalValue = new DecimalType(512);
566         when(mockedSystemInfo.getSwapTotal()).thenReturn(mockedSwapTotalValue);
567
568         initializeThingWithChannel(channnelID, acceptedItemType);
569         assertItemState(acceptedItemType, DEFAULT_TEST_ITEM_NAME, DEFAULT_CHANNEL_TEST_PRIORITY, mockedSwapTotalValue);
570     }
571
572     @Test
573     public void assertChannelSwapAvailablePercentIsUpdated() {
574         String channnelID = SysteminfoBindingConstants.CHANNEL_SWAP_AVAILABLE_PERCENT;
575         String acceptedItemType = "Number";
576
577         DecimalType mockedSwapAvailablePercentValue = new DecimalType(94);
578         when(mockedSystemInfo.getSwapAvailablePercent()).thenReturn(mockedSwapAvailablePercentValue);
579
580         initializeThingWithChannel(channnelID, acceptedItemType);
581         assertItemState(acceptedItemType, DEFAULT_TEST_ITEM_NAME, DEFAULT_CHANNEL_TEST_PRIORITY,
582                 mockedSwapAvailablePercentValue);
583     }
584
585     @Test
586     public void assertChannelStorageNameIsUpdated() throws DeviceNotFoundException {
587         String channnelID = SysteminfoBindingConstants.CHANNEL_STORAGE_NAME;
588         String acceptedItemType = "String";
589
590         StringType mockedStorageName = new StringType("Mocked Storage Name");
591         when(mockedSystemInfo.getStorageName(DEFAULT_DEVICE_INDEX)).thenReturn(mockedStorageName);
592
593         initializeThingWithChannel(channnelID, acceptedItemType);
594         assertItemState(acceptedItemType, DEFAULT_TEST_ITEM_NAME, DEFAULT_CHANNEL_TEST_PRIORITY, mockedStorageName);
595     }
596
597     @Test
598     public void assertChannelStorageTypeIsUpdated() throws DeviceNotFoundException {
599         String channnelID = SysteminfoBindingConstants.CHANNEL_STORAGE_TYPE;
600         String acceptedItemType = "String";
601
602         StringType mockedStorageType = new StringType("Mocked Storage Type");
603         when(mockedSystemInfo.getStorageType(DEFAULT_DEVICE_INDEX)).thenReturn(mockedStorageType);
604
605         initializeThingWithChannel(channnelID, acceptedItemType);
606         assertItemState(acceptedItemType, DEFAULT_TEST_ITEM_NAME, DEFAULT_CHANNEL_TEST_PRIORITY, mockedStorageType);
607     }
608
609     @Test
610     public void assertChannelStorageDescriptionIsUpdated() throws DeviceNotFoundException {
611         String channnelID = SysteminfoBindingConstants.CHANNEL_STORAGE_DESCRIPTION;
612         String acceptedItemType = "String";
613
614         StringType mockedStorageDescription = new StringType("Mocked Storage Description");
615         when(mockedSystemInfo.getStorageDescription(DEFAULT_DEVICE_INDEX)).thenReturn(mockedStorageDescription);
616
617         initializeThingWithChannel(channnelID, acceptedItemType);
618         assertItemState(acceptedItemType, DEFAULT_TEST_ITEM_NAME, DEFAULT_CHANNEL_TEST_PRIORITY,
619                 mockedStorageDescription);
620     }
621
622     @Test
623     public void assertChannelStorageAvailableIsUpdated() throws DeviceNotFoundException {
624         String channnelID = SysteminfoBindingConstants.CHANNEL_STORAGE_AVAILABLE;
625         String acceptedItemType = "Number";
626
627         DecimalType mockedStorageAvailableValue = new DecimalType(2000);
628         when(mockedSystemInfo.getStorageAvailable(DEFAULT_DEVICE_INDEX)).thenReturn(mockedStorageAvailableValue);
629
630         initializeThingWithChannel(channnelID, acceptedItemType);
631         assertItemState(acceptedItemType, DEFAULT_TEST_ITEM_NAME, DEFAULT_CHANNEL_TEST_PRIORITY,
632                 mockedStorageAvailableValue);
633     }
634
635     @Test
636     public void assertChannelStorageUsedIsUpdated() throws DeviceNotFoundException {
637         String channnelID = SysteminfoBindingConstants.CHANNEL_STORAGE_USED;
638         String acceptedItemType = "Number";
639
640         DecimalType mockedStorageUsedValue = new DecimalType(500);
641         when(mockedSystemInfo.getStorageUsed(DEFAULT_DEVICE_INDEX)).thenReturn(mockedStorageUsedValue);
642
643         initializeThingWithChannel(channnelID, acceptedItemType);
644         assertItemState(acceptedItemType, DEFAULT_TEST_ITEM_NAME, DEFAULT_CHANNEL_TEST_PRIORITY,
645                 mockedStorageUsedValue);
646     }
647
648     @Test
649     public void assertChannelStorageTotalIsUpdated() throws DeviceNotFoundException {
650         String channnelID = SysteminfoBindingConstants.CHANNEL_STORAGE_TOTAL;
651         String acceptedItemType = "Number";
652
653         DecimalType mockedStorageTotalValue = new DecimalType(2500);
654         when(mockedSystemInfo.getStorageTotal(DEFAULT_DEVICE_INDEX)).thenReturn(mockedStorageTotalValue);
655
656         initializeThingWithChannel(channnelID, acceptedItemType);
657         assertItemState(acceptedItemType, DEFAULT_TEST_ITEM_NAME, DEFAULT_CHANNEL_TEST_PRIORITY,
658                 mockedStorageTotalValue);
659     }
660
661     @Test
662     public void assertChannelStorageAvailablePercentIsUpdated() throws DeviceNotFoundException {
663         String channnelID = SysteminfoBindingConstants.CHANNEL_STORAGE_AVAILABLE_PERCENT;
664         String acceptedItemType = "Number";
665
666         DecimalType mockedStorageAvailablePercent = new DecimalType(20);
667         when(mockedSystemInfo.getStorageAvailablePercent(DEFAULT_DEVICE_INDEX))
668                 .thenReturn(mockedStorageAvailablePercent);
669
670         initializeThingWithChannel(channnelID, acceptedItemType);
671         assertItemState(acceptedItemType, DEFAULT_TEST_ITEM_NAME, DEFAULT_CHANNEL_TEST_PRIORITY,
672                 mockedStorageAvailablePercent);
673     }
674
675     @Test
676     public void assertChannelDriveNameIsUpdated() throws DeviceNotFoundException {
677         String channelID = SysteminfoBindingConstants.CHANNEL_DRIVE_NAME;
678         String acceptedItemType = "String";
679
680         StringType mockedDriveNameValue = new StringType("Mocked Drive Name");
681         when(mockedSystemInfo.getDriveName(DEFAULT_DEVICE_INDEX)).thenReturn(mockedDriveNameValue);
682
683         initializeThingWithChannel(channelID, acceptedItemType);
684         assertItemState(acceptedItemType, DEFAULT_TEST_ITEM_NAME, DEFAULT_CHANNEL_TEST_PRIORITY, mockedDriveNameValue);
685     }
686
687     @Test
688     public void assertChannelDriveModelIsUpdated() throws DeviceNotFoundException {
689         String channelID = SysteminfoBindingConstants.CHANNEL_DRIVE_MODEL;
690         String acceptedItemType = "String";
691
692         StringType mockedDriveModelValue = new StringType("Mocked Drive Model");
693         when(mockedSystemInfo.getDriveModel(DEFAULT_DEVICE_INDEX)).thenReturn(mockedDriveModelValue);
694
695         initializeThingWithChannel(channelID, acceptedItemType);
696         assertItemState(acceptedItemType, DEFAULT_TEST_ITEM_NAME, DEFAULT_CHANNEL_TEST_PRIORITY, mockedDriveModelValue);
697     }
698
699     @Test
700     public void assertChannelDriveSerialIsUpdated() throws DeviceNotFoundException {
701         String channelID = SysteminfoBindingConstants.CHANNEL_DRIVE_SERIAL;
702         String acceptedItemType = "String";
703
704         StringType mockedDriveSerialNumber = new StringType("Mocked Drive Serial Number");
705         when(mockedSystemInfo.getDriveSerialNumber(DEFAULT_DEVICE_INDEX)).thenReturn(mockedDriveSerialNumber);
706
707         initializeThingWithChannel(channelID, acceptedItemType);
708         assertItemState(acceptedItemType, DEFAULT_TEST_ITEM_NAME, DEFAULT_CHANNEL_TEST_PRIORITY,
709                 mockedDriveSerialNumber);
710     }
711
712     // Re-enable this previously disabled test, as it is not relying on hardware anymore, but a mocked object
713     // There is a bug opened for this issue - https://github.com/dblock/oshi/issues/185
714     @Test
715     public void assertChannelSensorsCpuTempIsUpdated() {
716         String channnelID = SysteminfoBindingConstants.CHANNEL_SENSORS_CPU_TEMPERATURE;
717         String acceptedItemType = "Number";
718
719         DecimalType mockedSensorsCpuTemperatureValue = new DecimalType(60);
720         when(mockedSystemInfo.getSensorsCpuTemperature()).thenReturn(mockedSensorsCpuTemperatureValue);
721
722         initializeThingWithChannel(channnelID, acceptedItemType);
723         assertItemState(acceptedItemType, DEFAULT_TEST_ITEM_NAME, DEFAULT_CHANNEL_TEST_PRIORITY,
724                 mockedSensorsCpuTemperatureValue);
725     }
726
727     @Test
728     public void assertChannelSensorsCpuVoltageIsUpdated() {
729         String channnelID = SysteminfoBindingConstants.CHANNEL_SENOSRS_CPU_VOLTAGE;
730         String acceptedItemType = "Number";
731
732         DecimalType mockedSensorsCpuVoltageValue = new DecimalType(1000);
733         when(mockedSystemInfo.getSensorsCpuVoltage()).thenReturn(mockedSensorsCpuVoltageValue);
734
735         initializeThingWithChannel(channnelID, acceptedItemType);
736         assertItemState(acceptedItemType, DEFAULT_TEST_ITEM_NAME, DEFAULT_CHANNEL_TEST_PRIORITY,
737                 mockedSensorsCpuVoltageValue);
738     }
739
740     @Test
741     public void assertChannelSensorsFanSpeedIsUpdated() throws DeviceNotFoundException {
742         String channnelID = SysteminfoBindingConstants.CHANNEL_SENSORS_FAN_SPEED;
743         String acceptedItemType = "Number";
744
745         DecimalType mockedSensorsCpuFanSpeedValue = new DecimalType(180);
746         when(mockedSystemInfo.getSensorsFanSpeed(DEFAULT_DEVICE_INDEX)).thenReturn(mockedSensorsCpuFanSpeedValue);
747
748         initializeThingWithChannel(channnelID, acceptedItemType);
749         assertItemState(acceptedItemType, DEFAULT_TEST_ITEM_NAME, DEFAULT_CHANNEL_TEST_PRIORITY,
750                 mockedSensorsCpuFanSpeedValue);
751     }
752
753     @Test
754     public void assertChannelBatteryNameIsUpdated() throws DeviceNotFoundException {
755         String channnelID = SysteminfoBindingConstants.CHANNEL_BATTERY_NAME;
756         String acceptedItemType = "String";
757
758         StringType mockedBatteryName = new StringType("Mocked Battery Name");
759         when(mockedSystemInfo.getBatteryName(DEFAULT_DEVICE_INDEX)).thenReturn(mockedBatteryName);
760
761         initializeThingWithChannel(channnelID, acceptedItemType);
762         assertItemState(acceptedItemType, DEFAULT_TEST_ITEM_NAME, DEFAULT_CHANNEL_TEST_PRIORITY, mockedBatteryName);
763     }
764
765     @Test
766     public void assertChannelBatteryRemainingCapacityIsUpdated() throws DeviceNotFoundException {
767         String channnelID = SysteminfoBindingConstants.CHANNEL_BATTERY_REMAINING_CAPACITY;
768         String acceptedItemType = "Number";
769
770         DecimalType mockedBatteryRemainingCapacity = new DecimalType(200);
771         when(mockedSystemInfo.getBatteryRemainingCapacity(DEFAULT_DEVICE_INDEX))
772                 .thenReturn(mockedBatteryRemainingCapacity);
773
774         initializeThingWithChannel(channnelID, acceptedItemType);
775         assertItemState(acceptedItemType, DEFAULT_TEST_ITEM_NAME, DEFAULT_CHANNEL_TEST_PRIORITY,
776                 mockedBatteryRemainingCapacity);
777     }
778
779     @Test
780     public void assertChannelBatteryRemainingTimeIsUpdated() throws DeviceNotFoundException {
781         String channnelID = SysteminfoBindingConstants.CHANNEL_BATTERY_REMAINING_TIME;
782         String acceptedItemType = "Number";
783
784         DecimalType mockedBatteryRemainingTime = new DecimalType(3600);
785         when(mockedSystemInfo.getBatteryRemainingTime(DEFAULT_DEVICE_INDEX)).thenReturn(mockedBatteryRemainingTime);
786
787         initializeThingWithChannel(channnelID, acceptedItemType);
788         assertItemState(acceptedItemType, DEFAULT_TEST_ITEM_NAME, DEFAULT_CHANNEL_TEST_PRIORITY,
789                 mockedBatteryRemainingTime);
790     }
791
792     @Test
793     public void assertChannelDisplayInformationIsUpdated() throws DeviceNotFoundException {
794         String channnelID = SysteminfoBindingConstants.CHANNEL_DISPLAY_INFORMATION;
795         String acceptedItemType = "String";
796
797         StringType mockedDisplayInfo = new StringType("Mocked Display Information");
798         when(mockedSystemInfo.getDisplayInformation(DEFAULT_DEVICE_INDEX)).thenReturn(mockedDisplayInfo);
799
800         initializeThingWithChannel(channnelID, acceptedItemType);
801         assertItemState(acceptedItemType, DEFAULT_TEST_ITEM_NAME, DEFAULT_CHANNEL_TEST_PRIORITY, mockedDisplayInfo);
802     }
803
804     @Test
805     public void assertChannelNetworkIpIsUpdated() throws DeviceNotFoundException {
806         String channnelID = SysteminfoBindingConstants.CHANNEL_NETWORK_IP;
807         String acceptedItemType = "String";
808
809         StringType mockedNetworkIp = new StringType("192.168.1.0");
810         when(mockedSystemInfo.getNetworkIp(DEFAULT_DEVICE_INDEX)).thenReturn(mockedNetworkIp);
811
812         initializeThingWithChannel(channnelID, acceptedItemType);
813         assertItemState(acceptedItemType, DEFAULT_TEST_ITEM_NAME, DEFAULT_CHANNEL_TEST_PRIORITY, mockedNetworkIp);
814     }
815
816     @Test
817     public void assertChannelNetworkMacIsUpdated() throws DeviceNotFoundException {
818         String channnelID = SysteminfoBindingConstants.CHANNEL_NETWORK_MAC;
819         String acceptedItemType = "String";
820
821         StringType mockedNetworkMacValue = new StringType("AB-10-11-12-13-14");
822         when(mockedSystemInfo.getNetworkMac(DEFAULT_DEVICE_INDEX)).thenReturn(mockedNetworkMacValue);
823
824         initializeThingWithChannel(channnelID, acceptedItemType);
825         assertItemState(acceptedItemType, DEFAULT_TEST_ITEM_NAME, DEFAULT_CHANNEL_TEST_PRIORITY, mockedNetworkMacValue);
826     }
827
828     @Test
829     public void assertChannelNetworkDataSentIsUpdated() throws DeviceNotFoundException {
830         String channnelID = SysteminfoBindingConstants.CHANNEL_NETWORK_DATA_SENT;
831         String acceptedItemType = "Number";
832
833         DecimalType mockedNetworkDataSent = new DecimalType(1000);
834         when(mockedSystemInfo.getNetworkDataSent(DEFAULT_DEVICE_INDEX)).thenReturn(mockedNetworkDataSent);
835
836         initializeThingWithChannel(channnelID, acceptedItemType);
837         assertItemState(acceptedItemType, DEFAULT_TEST_ITEM_NAME, DEFAULT_CHANNEL_TEST_PRIORITY, mockedNetworkDataSent);
838     }
839
840     @Test
841     public void assertChannelNetworkDataReceivedIsUpdated() throws DeviceNotFoundException {
842         String channnelID = SysteminfoBindingConstants.CHANNEL_NETWORK_DATA_RECEIVED;
843         String acceptedItemType = "Number";
844
845         DecimalType mockedNetworkDataReceiveed = new DecimalType(800);
846         when(mockedSystemInfo.getNetworkDataReceived(DEFAULT_DEVICE_INDEX)).thenReturn(mockedNetworkDataReceiveed);
847
848         initializeThingWithChannel(channnelID, acceptedItemType);
849         assertItemState(acceptedItemType, DEFAULT_TEST_ITEM_NAME, DEFAULT_CHANNEL_TEST_PRIORITY,
850                 mockedNetworkDataReceiveed);
851     }
852
853     @Test
854     public void assertChannelNetworkPacketsSentIsUpdated() throws DeviceNotFoundException {
855         String channnelID = SysteminfoBindingConstants.CHANNEL_NETWORK_PACKETS_SENT;
856         String acceptedItemType = "Number";
857
858         DecimalType mockedNetworkPacketsSent = new DecimalType(50);
859         when(mockedSystemInfo.getNetworkPacketsSent(DEFAULT_DEVICE_INDEX)).thenReturn(mockedNetworkPacketsSent);
860
861         initializeThingWithChannel(channnelID, acceptedItemType);
862         assertItemState(acceptedItemType, DEFAULT_TEST_ITEM_NAME, DEFAULT_CHANNEL_TEST_PRIORITY,
863                 mockedNetworkPacketsSent);
864     }
865
866     @Test
867     public void assertChannelNetworkPacketsReceivedIsUpdated() throws DeviceNotFoundException {
868         String channnelID = SysteminfoBindingConstants.CHANNEL_NETWORK_PACKETS_RECEIVED;
869         String acceptedItemType = "Number";
870
871         DecimalType mockedNetworkPacketsReceived = new DecimalType(48);
872         when(mockedSystemInfo.getNetworkPacketsReceived(DEFAULT_DEVICE_INDEX)).thenReturn(mockedNetworkPacketsReceived);
873
874         initializeThingWithChannel(channnelID, acceptedItemType);
875         assertItemState(acceptedItemType, DEFAULT_TEST_ITEM_NAME, DEFAULT_CHANNEL_TEST_PRIORITY,
876                 mockedNetworkPacketsReceived);
877     }
878
879     @Test
880     public void assertChannelNetworkNetworkNameIsUpdated() throws DeviceNotFoundException {
881         String channnelID = SysteminfoBindingConstants.CHANNEL_NETWORK_NAME;
882         String acceptedItemType = "String";
883
884         StringType mockedNetworkName = new StringType("MockN-AQ34");
885         when(mockedSystemInfo.getNetworkName(DEFAULT_DEVICE_INDEX)).thenReturn(mockedNetworkName);
886
887         initializeThingWithChannel(channnelID, acceptedItemType);
888         assertItemState(acceptedItemType, DEFAULT_TEST_ITEM_NAME, DEFAULT_CHANNEL_TEST_PRIORITY, mockedNetworkName);
889     }
890
891     @Test
892     public void assertChannelNetworkNetworkDisplayNameIsUpdated() throws DeviceNotFoundException {
893         String channnelID = SysteminfoBindingConstants.CHANNEL_NETWORK_ADAPTER_NAME;
894         String acceptedItemType = "String";
895
896         StringType mockedNetworkAdapterName = new StringType("Mocked Network Adapter Name");
897         when(mockedSystemInfo.getNetworkDisplayName(DEFAULT_DEVICE_INDEX)).thenReturn(mockedNetworkAdapterName);
898
899         initializeThingWithChannel(channnelID, acceptedItemType);
900         assertItemState(acceptedItemType, DEFAULT_TEST_ITEM_NAME, DEFAULT_CHANNEL_TEST_PRIORITY,
901                 mockedNetworkAdapterName);
902     }
903
904     class SysteminfoDiscoveryServiceMock extends SysteminfoDiscoveryService {
905         String hostname;
906
907         SysteminfoDiscoveryServiceMock(String hostname) {
908             super();
909             this.hostname = hostname;
910         }
911
912         @Override
913         protected String getHostName() throws UnknownHostException {
914             if ("unresolved".equals(hostname)) {
915                 throw new UnknownHostException();
916             }
917             return hostname;
918         }
919
920         @Override
921         public void startScan() {
922             super.startScan();
923         }
924     }
925
926     @Test
927     public void testDiscoveryWithInvalidHostname() {
928         String hostname = "Hilo.fritz.box";
929         String expectedHostname = "Hilo_fritz_box";
930
931         testDiscoveryService(expectedHostname, hostname);
932     }
933
934     @Test
935     public void testDiscoveryWithValidHostname() {
936         String hostname = "MyComputer";
937         String expectedHostname = "MyComputer";
938
939         testDiscoveryService(expectedHostname, hostname);
940     }
941
942     @Test
943     public void testDiscoveryWithUnresolvedHostname() {
944         String hostname = "unresolved";
945         String expectedHostname = SysteminfoDiscoveryService.DEFAULT_THING_ID;
946
947         testDiscoveryService(expectedHostname, hostname);
948     }
949
950     @Test
951     public void testDiscoveryWithEmptyHostnameString() {
952         String hostname = "";
953         String expectedHostname = SysteminfoDiscoveryService.DEFAULT_THING_ID;
954
955         testDiscoveryService(expectedHostname, hostname);
956     }
957
958     private void testDiscoveryService(String expectedHostname, String hostname) {
959         SysteminfoDiscoveryService discoveryService = getService(DiscoveryService.class,
960                 SysteminfoDiscoveryService.class);
961         waitForAssert(() -> {
962             assertThat(discoveryService, is(notNullValue()));
963         });
964         SysteminfoDiscoveryServiceMock discoveryServiceMock = new SysteminfoDiscoveryServiceMock(hostname);
965         if (discoveryService != null) {
966             unregisterService(DiscoveryService.class);
967         }
968         registerService(discoveryServiceMock, DiscoveryService.class.getName(), new Hashtable<>());
969
970         ThingTypeUID computerType = SysteminfoBindingConstants.THING_TYPE_COMPUTER;
971         ThingUID computerUID = new ThingUID(computerType, expectedHostname);
972
973         discoveryServiceMock.startScan();
974
975         Inbox inbox = getService(Inbox.class);
976         assertThat(inbox, is(notNullValue()));
977
978         if (inbox == null) {
979             return;
980         }
981
982         waitForAssert(() -> {
983             List<DiscoveryResult> results = inbox.stream().filter(InboxPredicates.forThingUID(computerUID))
984                     .collect(toList());
985             assertFalse(results.isEmpty(), "No Thing with UID " + computerUID.getAsString() + " in inbox");
986         });
987
988         inbox.approve(computerUID, SysteminfoDiscoveryService.DEFAULT_THING_LABEL, null);
989
990         waitForAssert(() -> {
991             systemInfoThing = thingRegistry.get(computerUID);
992             assertThat(systemInfoThing, is(notNullValue()));
993         });
994
995         Thing thing = systemInfoThing;
996         if (thing == null) {
997             return;
998         }
999
1000         waitForAssert(() -> {
1001             assertThat("Thing is not initialized.", thing.getStatus(), is(equalTo(ThingStatus.ONLINE)));
1002         });
1003     }
1004
1005     @Test
1006     public void assertChannelProcessThreadsIsUpdatedWithPIDse() throws DeviceNotFoundException {
1007         String channnelID = SysteminfoBindingConstants.CHANNEL_PROCESS_THREADS;
1008         String acceptedItemType = "Number";
1009         // The pid of the System idle process in Windows
1010         int pid = 0;
1011
1012         DecimalType mockedProcessThreadsCount = new DecimalType(4);
1013         when(mockedSystemInfo.getProcessThreads(pid)).thenReturn(mockedProcessThreadsCount);
1014
1015         initializeThingWithChannelAndPID(channnelID, acceptedItemType, pid);
1016         assertItemState(acceptedItemType, DEFAULT_TEST_ITEM_NAME, DEFAULT_CHANNEL_TEST_PRIORITY,
1017                 mockedProcessThreadsCount);
1018     }
1019
1020     @Test
1021     public void assertChannelProcessPathIsUpdatedWithPIDset() throws DeviceNotFoundException {
1022         String channnelID = SysteminfoBindingConstants.CHANNEL_PROCESS_PATH;
1023         String acceptedItemType = "String";
1024         // The pid of the System idle process in Windows
1025         int pid = 0;
1026
1027         StringType mockedProcessPath = new StringType("C:\\Users\\MockedUser\\Process");
1028         when(mockedSystemInfo.getProcessPath(pid)).thenReturn(mockedProcessPath);
1029
1030         initializeThingWithChannelAndPID(channnelID, acceptedItemType, pid);
1031         assertItemState(acceptedItemType, DEFAULT_TEST_ITEM_NAME, DEFAULT_CHANNEL_TEST_PRIORITY, mockedProcessPath);
1032     }
1033
1034     @Test
1035     public void assertChannelProcessNameIsUpdatedWithPIDset() throws DeviceNotFoundException {
1036         String channnelID = SysteminfoBindingConstants.CHANNEL_PROCESS_NAME;
1037         String acceptedItemType = "String";
1038         // The pid of the System idle process in Windows
1039         int pid = 0;
1040
1041         StringType mockedProcessName = new StringType("MockedProcess.exe");
1042         when(mockedSystemInfo.getProcessName(pid)).thenReturn(mockedProcessName);
1043
1044         initializeThingWithChannelAndPID(channnelID, acceptedItemType, pid);
1045         assertItemState(acceptedItemType, DEFAULT_TEST_ITEM_NAME, DEFAULT_CHANNEL_TEST_PRIORITY, mockedProcessName);
1046     }
1047
1048     @Test
1049     public void assertChannelProcessMemoryIsUpdatedWithPIDset() throws DeviceNotFoundException {
1050         String channnelID = SysteminfoBindingConstants.CHANNEL_PROCESS_MEMORY;
1051         String acceptedItemType = "Number";
1052         // The pid of the System idle process in Windows
1053         int pid = 0;
1054
1055         DecimalType mockedProcessMemory = new DecimalType(450);
1056         when(mockedSystemInfo.getProcessMemoryUsage(pid)).thenReturn(mockedProcessMemory);
1057
1058         initializeThingWithChannelAndPID(channnelID, acceptedItemType, pid);
1059         assertItemState(acceptedItemType, DEFAULT_TEST_ITEM_NAME, DEFAULT_CHANNEL_TEST_PRIORITY, mockedProcessMemory);
1060     }
1061
1062     @Test
1063     public void assertChannelProcessLoadIsUpdatedWithPIDset() throws DeviceNotFoundException {
1064         String channnelID = SysteminfoBindingConstants.CHANNEL_PROCESS_LOAD;
1065         String acceptedItemType = "Number";
1066         // The pid of the System idle process in Windows
1067         int pid = 0;
1068
1069         DecimalType mockedProcessLoad = new DecimalType(3);
1070         when(mockedSystemInfo.getProcessCpuUsage(pid)).thenReturn(mockedProcessLoad);
1071
1072         initializeThingWithChannelAndPID(channnelID, acceptedItemType, pid);
1073         assertItemState(acceptedItemType, DEFAULT_TEST_ITEM_NAME, DEFAULT_CHANNEL_TEST_PRIORITY, mockedProcessLoad);
1074     }
1075
1076     @Test
1077     public void testThingHandlesChannelPriorityChange() {
1078         String priorityKey = "priority";
1079         String pidKey = "pid";
1080         String initialPriority = DEFAULT_CHANNEL_TEST_PRIORITY; // Evaluates to High
1081         String newPriority = "Low";
1082
1083         String acceptedItemType = "Number";
1084         initializeThingWithChannel(DEFAULT_TEST_CHANNEL_ID, acceptedItemType);
1085
1086         Thing thing = systemInfoThing;
1087         if (thing == null) {
1088             throw new AssertionError("Thing is null");
1089         }
1090         Channel channel = thing.getChannel(DEFAULT_TEST_CHANNEL_ID);
1091         if (channel == null) {
1092             throw new AssertionError("Channel '" + DEFAULT_TEST_CHANNEL_ID + "' is null");
1093         }
1094
1095         ThingHandler thingHandler = thing.getHandler();
1096         if (thingHandler == null) {
1097             throw new AssertionError("Thing handler is null");
1098         }
1099         if (!(thingHandler.getClass().equals(SysteminfoHandler.class))) {
1100             throw new AssertionError("Thing handler not of class SysteminfoHandler");
1101         }
1102         SysteminfoHandler handler = (SysteminfoHandler) thingHandler;
1103         waitForAssert(() -> {
1104             assertThat("The initial priority of channel " + channel.getUID() + " is not as expected.",
1105                     channel.getConfiguration().get(priorityKey), is(equalTo(initialPriority)));
1106             assertThat(handler.getHighPriorityChannels().contains(channel.getUID()), is(true));
1107         });
1108
1109         // Change the priority of a channel, keep the pid
1110         Configuration updatedConfig = new Configuration();
1111         updatedConfig.put(priorityKey, newPriority);
1112         updatedConfig.put(pidKey, channel.getConfiguration().get(pidKey));
1113         Channel updatedChannel = ChannelBuilder.create(channel.getUID(), channel.getAcceptedItemType())
1114                 .withType(channel.getChannelTypeUID()).withKind(channel.getKind()).withConfiguration(updatedConfig)
1115                 .build();
1116
1117         Thing updatedThing = ThingBuilder.create(thing.getThingTypeUID(), thing.getUID())
1118                 .withConfiguration(thing.getConfiguration()).withChannel(updatedChannel).build();
1119
1120         handler.thingUpdated(updatedThing);
1121
1122         waitForAssert(() -> {
1123             assertThat("The prority of the channel was not updated: ", channel.getConfiguration().get(priorityKey),
1124                     is(equalTo(newPriority)));
1125             assertThat(handler.getLowPriorityChannels().contains(channel.getUID()), is(true));
1126         });
1127     }
1128 }