<commit_before>/**
 * Copyright (c) 2014-2017 by the respective copyright holders.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 */
/**
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 */
package org.eclipse.smarthome.core.thing.firmware

import static org.eclipse.smarthome.core.thing.firmware.Constants.*
import static org.eclipse.smarthome.core.thing.firmware.FirmwareStatusInfo.*
import static org.hamcrest.CoreMatchers.*
import static org.junit.Assert.*
import static org.junit.matchers.JUnitMatchers.*

import java.util.concurrent.TimeUnit

import org.eclipse.smarthome.config.core.ConfigDescription
import org.eclipse.smarthome.config.core.ConfigDescriptionParameter
import org.eclipse.smarthome.config.core.ConfigDescriptionParameterBuilder
import org.eclipse.smarthome.config.core.ConfigDescriptionProvider
import org.eclipse.smarthome.core.common.SafeMethodCaller
import org.eclipse.smarthome.core.events.Event
import org.eclipse.smarthome.core.events.EventFilter
import org.eclipse.smarthome.core.events.EventPublisher
import org.eclipse.smarthome.core.events.EventSubscriber
import org.eclipse.smarthome.core.i18n.I18nProvider
import org.eclipse.smarthome.core.thing.ChannelUID
import org.eclipse.smarthome.core.thing.ManagedThingProvider
import org.eclipse.smarthome.core.thing.Thing
import org.eclipse.smarthome.core.thing.ThingRegistry
import org.eclipse.smarthome.core.thing.ThingStatus
import org.eclipse.smarthome.core.thing.ThingTypeUID
import org.eclipse.smarthome.core.thing.ThingUID
import org.eclipse.smarthome.core.thing.binding.BaseThingHandler
import org.eclipse.smarthome.core.thing.binding.BaseThingHandlerFactory
import org.eclipse.smarthome.core.thing.binding.ThingHandler
import org.eclipse.smarthome.core.thing.binding.ThingHandlerFactory
import org.eclipse.smarthome.core.thing.binding.ThingTypeProvider
import org.eclipse.smarthome.core.thing.binding.builder.ThingBuilder
import org.eclipse.smarthome.core.thing.binding.firmware.Firmware
import org.eclipse.smarthome.core.thing.binding.firmware.FirmwareUpdateBackgroundTransferHandler
import org.eclipse.smarthome.core.thing.binding.firmware.FirmwareUpdateHandler
import org.eclipse.smarthome.core.thing.binding.firmware.ProgressCallback
import org.eclipse.smarthome.core.thing.binding.firmware.ProgressStep
import org.eclipse.smarthome.core.thing.type.ThingType
import org.eclipse.smarthome.core.thing.type.ThingTypeRegistry
import org.eclipse.smarthome.core.types.Command
import org.eclipse.smarthome.test.OSGiTest
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.rules.ExpectedException
import org.osgi.service.cm.ConfigurationAdmin
import org.osgi.service.component.ComponentContext

import com.google.common.collect.ImmutableSet

/**
 * Testing the {@link FirmwareUpdateService}.
 *
 * @author <NAME> - Initial contribution
 */
final class FirmwareUpdateServiceOSGiTest extends OSGiTest {

    private final FirmwareStatusInfo unknownInfo = createUnknownInfo()
    private final FirmwareStatusInfo upToDateInfo = createUpToDateInfo()
    private final FirmwareStatusInfo updateAvailableInfo =  createUpdateAvailableInfo()
    private final FirmwareStatusInfo updateExecutableInfoFw112 = createUpdateExecutableInfo(FW112_EN.getUID())
    private final FirmwareStatusInfo updateExecutableInfoFw113 = createUpdateExecutableInfo(FW113_EN.getUID())
    private final FirmwareStatusInfo updateExecutableInfoFw120 = createUpdateExecutableInfo(FW120_EN.getUID())

    Locale _defaultLocale

    @Rule
    public ExpectedException thrown = ExpectedException.none()

    private ManagedThingProvider managedThingProvider
    private ThingRegistry thingRegistry
    private FirmwareRegistry firmwareRegistry
    private FirmwareUpdateService firmwareUpdateService

    def thing1
    def thing2
    def thing3

    private def firmwareProvider = [
        getFirmware: { firmwareUID, locale ->
            if(firmwareUID.equals(FW009_EN.getUID())) {
                FW009_EN
            } else if(firmwareUID.equals(FW111_EN.getUID())) {
                FW111_EN
            } else if(firmwareUID.equals(FW112_EN.getUID())) {
                FW112_EN
            } else if(firmwareUID.equals(FWALPHA_EN.getUID())) {
                FWALPHA_EN
            } else {
                null
            }
        },
        getFirmwares: { thingTypeUID, locale ->
            if(thingTypeUID.equals(THING_TYPE_UID_WITHOUT_FW) || thingTypeUID.equals(THING_TYPE_UID2) || thingTypeUID.equals(THING_TYPE_UID3)) {
                return [] as Set
            }
            [
                FW009_EN,
                FW111_EN,
                FW112_EN] as Set
        }] as FirmwareProvider

    private def firmwareStatusInfoEventSubscriber = new EventSubscriber() {

        private final def topics = ImmutableSet.of(FirmwareEventFactory.FIRMWARE_STATUS_TOPIC.replace(FirmwareEventFactory.THING_UID_TOPIC_KEY, THING1_UID.getAsString()),
        FirmwareEventFactory.FIRMWARE_STATUS_TOPIC.replace(FirmwareEventFactory.THING_UID_TOPIC_KEY, THING2_UID.getAsString()),
        FirmwareEventFactory.FIRMWARE_STATUS_TOPIC.replace(FirmwareEventFactory.THING_UID_TOPIC_KEY, THING3_UID.getAsString()),
        FirmwareEventFactory.FIRMWARE_STATUS_TOPIC.replace(FirmwareEventFactory.THING_UID_TOPIC_KEY, THING4_UID.getAsString()),
        FirmwareEventFactory.FIRMWARE_STATUS_TOPIC.replace(FirmwareEventFactory.THING_UID_TOPIC_KEY, UNKNOWN_THING_UID.getAsString()))

        def events = []

        @Override
        public Set<String> getSubscribedEventTypes() {
            return ImmutableSet.copyOf(FirmwareStatusInfoEvent.TYPE)
        }

        @Override
        public EventFilter getEventFilter() {
            return new EventFilter() {
                        @Override
                        boolean apply(Event event) {
                            topics.contains(event.getTopic())
                        };
                    };
        }

        @Override
        public void receive(Event event) {
            events.add(event);
        }
    } as EventSubscriber

    private def progressInfoEventSubscriber = new EventSubscriber() {

        private final def topics = ImmutableSet.of(FirmwareEventFactory.FIRMWARE_UPDATE_PROGRESS_TOPIC.replace(FirmwareEventFactory.THING_UID_TOPIC_KEY, THING1_UID.getAsString()))

        def events = []

        @Override
        public Set<String> getSubscribedEventTypes() {
            return ImmutableSet.copyOf(FirmwareUpdateProgressInfoEvent.TYPE)
        }

        @Override
        public EventFilter getEventFilter() {
            return new EventFilter() {
                        @Override
                        boolean apply(Event event) {
                            topics.contains(event.getTopic())
                        };
                    };
        }

        @Override
        public void receive(Event event) {
            events.add(event);
        }
    } as EventSubscriber

    private def firmwareUpdateResultInfoEventSubscriber = new EventSubscriber() {

        private final def topics = ImmutableSet.of(FirmwareEventFactory.FIRMWARE_UPDATE_RESULT_TOPIC.replace(FirmwareEventFactory.THING_UID_TOPIC_KEY, THING1_UID.getAsString()))

        def events = []

        @Override
        public Set<String> getSubscribedEventTypes() {
            return ImmutableSet.copyOf(FirmwareUpdateResultInfoEvent.TYPE)
        }

        @Override
        public EventFilter getEventFilter() {
            return new EventFilter() {
                        @Override
                        boolean apply(Event event) {
                            topics.contains(event.getTopic())
                        };
                    };
        }

        @Override
        public void receive(Event event) {
            events.add(event);
        }
    } as EventSubscriber

    @Before
    void setup() {
        _defaultLocale = Locale.getDefault()
        setDefaultLocale(Locale.ENGLISH)

        registerVolatileStorageService()
        managedThingProvider = getService ManagedThingProvider
        assertThat managedThingProvider, is(notNullValue())
        thingRegistry = getService(ThingRegistry)
        assertThat thingRegistry, is(notNullValue())

        registerThingTypeProvider()
        registerConfigDescriptionProvider()

        firmwareRegistry = getService(FirmwareRegistry)
        assertThat firmwareRegistry, is(notNullValue())

        firmwareUpdateService = getService(FirmwareUpdateService)
        assertThat firmwareUpdateService, is(notNullValue())

        registerService(firmwareProvider, FirmwareProvider.class.getName())
        registerService(firmwareStatusInfoEventSubscriber, EventSubscriber.class.getName())

        def firmwareUpdateThingHandlerFactory = new FirmwareUpdateThingHandlerFactory()
        firmwareUpdateThingHandlerFactory.activate([getBundleContext: { bundleContext }] as ComponentContext)
        registerService(firmwareUpdateThingHandlerFactory, ThingHandlerFactory.class.name)

        thing1 = ThingBuilder.create(THING_TYPE_UID1, THING1_ID).withProperties([(Thing.PROPERTY_FIRMWARE_VERSION) : V111]).build()
        thing2 = ThingBuilder.create(THING_TYPE_UID1, THING2_ID).withProperties([(Thing.PROPERTY_FIRMWARE_VERSION) : V112]).build()
        thing3 = ThingBuilder.create(THING_TYPE_UID2, THING3_ID).withProperties([(Thing.PROPERTY_FIRMWARE_VERSION) : VALPHA]).build()

        managedThingProvider.add(thing1)
        managedThingProvider.add(thing2)
        managedThingProvider.add(thing3)

        waitForAssert {
            assertThat thing1.getStatus(), is(ThingStatus.ONLINE)
            assertThat thing2.getStatus(), is(ThingStatus.ONLINE)
            assertThat thing3.getStatus(), is(ThingStatus.ONLINE)
        }

        def expectedInitializedFirmwareStatusInfoEvents = 3
        waitForAssert {
            assertThat firmwareStatusInfoEventSubscriber.events.size(), is(expectedInitializedFirmwareStatusInfoEvents)
        }
    }

    @After
    void teardown() {
        setDefaultLocale(_defaultLocale)
        managedThingProvider.getAll().each {
            managedThingProvider.remove(it.getUID())
        }
        unregisterMocks()
    }

    @Test
    void 'assert that BaseThingHandlerFactory registers firmware update handler'() {
        def handler = thing1.getHandler()
        assertThat handler, is(not(null))

        def firmwareUpdateHandler = getService(FirmwareUpdateHandler)
        assertThat firmwareUpdateHandler, is(handler)
    }

    @Test
    void 'assert that correct firmware status is provided'() {
        assertThat thing1.getProperties().get(Thing.PROPERTY_FIRMWARE_VERSION), is(V111)
        assertThat thing2.getProperties().get(Thing.PROPERTY_FIRMWARE_VERSION), is(V112)

        assertThat firmwareUpdateService.getFirmwareStatusInfo(THING1_UID), is(updateExecutableInfoFw112)
        assertFirmwareStatusInfoEvent(THING1_UID, updateExecutableInfoFw112)<commit_msg>increased timing tolerance in firmware test (#3543)<commit_after>/**
 * Copyright (c) 2014-2017 by the respective copyright holders.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 */
/**
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 */
package org.eclipse.smarthome.core.thing.firmware

import static org.eclipse.smarthome.core.thing.firmware.Constants.*
import static org.eclipse.smarthome.core.thing.firmware.FirmwareStatusInfo.*
import static org.hamcrest.CoreMatchers.*
import static org.junit.Assert.*
import static org.junit.matchers.JUnitMatchers.*

import java.util.concurrent.TimeUnit

import org.eclipse.smarthome.config.core.ConfigDescription
import org.eclipse.smarthome.config.core.ConfigDescriptionParameter
import org.eclipse.smarthome.config.core.ConfigDescriptionParameterBuilder
import org.eclipse.smarthome.config.core.ConfigDescriptionProvider
import org.eclipse.smarthome.core.common.SafeMethodCaller
import org.eclipse.smarthome.core.events.Event
import org.eclipse.smarthome.core.events.EventFilter
import org.eclipse.smarthome.core.events.EventPublisher
import org.eclipse.smarthome.core.events.EventSubscriber
import org.eclipse.smarthome.core.i18n.I18nProvider
import org.eclipse.smarthome.core.thing.ChannelUID
import org.eclipse.smarthome.core.thing.ManagedThingProvider
import org.eclipse.smarthome.core.thing.Thing
import org.eclipse.smarthome.core.thing.ThingRegistry
import org.eclipse.smarthome.core.thing.ThingStatus
import org.eclipse.smarthome.core.thing.ThingTypeUID
import org.eclipse.smarthome.core.thing.ThingUID
import org.eclipse.smarthome.core.thing.binding.BaseThingHandler
import org.eclipse.smarthome.core.thing.binding.BaseThingHandlerFactory
import org.eclipse.smarthome.core.thing.binding.ThingHandler
import org.eclipse.smarthome.core.thing.binding.ThingHandlerFactory
import org.eclipse.smarthome.core.thing.binding.ThingTypeProvider
import org.eclipse.smarthome.core.thing.binding.builder.ThingBuilder
import org.eclipse.smarthome.core.thing.binding.firmware.Firmware
import org.eclipse.smarthome.core.thing.binding.firmware.FirmwareUpdateBackgroundTransferHandler
import org.eclipse.smarthome.core.thing.binding.firmware.FirmwareUpdateHandler
import org.eclipse.smarthome.core.thing.binding.firmware.ProgressCallback
import org.eclipse.smarthome.core.thing.binding.firmware.ProgressStep
import org.eclipse.smarthome.core.thing.type.ThingType
import org.eclipse.smarthome.core.thing.type.ThingTypeRegistry
import org.eclipse.smarthome.core.types.Command
import org.eclipse.smarthome.test.OSGiTest
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.rules.ExpectedException
import org.osgi.service.cm.ConfigurationAdmin
import org.osgi.service.component.ComponentContext

import com.google.common.collect.ImmutableSet

/**
 * Testing the {@link FirmwareUpdateService}.
 *
 * @author <NAME> - Initial contribution
 */
final class FirmwareUpdateServiceOSGiTest extends OSGiTest {

    private final FirmwareStatusInfo unknownInfo = createUnknownInfo()
    private final FirmwareStatusInfo upToDateInfo = createUpToDateInfo()
    private final FirmwareStatusInfo updateAvailableInfo =  createUpdateAvailableInfo()
    private final FirmwareStatusInfo updateExecutableInfoFw112 = createUpdateExecutableInfo(FW112_EN.getUID())
    private final FirmwareStatusInfo updateExecutableInfoFw113 = createUpdateExecutableInfo(FW113_EN.getUID())
    private final FirmwareStatusInfo updateExecutableInfoFw120 = createUpdateExecutableInfo(FW120_EN.getUID())

    Locale _defaultLocale

    @Rule
    public ExpectedException thrown = ExpectedException.none()

    private ManagedThingProvider managedThingProvider
    private ThingRegistry thingRegistry
    private FirmwareRegistry firmwareRegistry
    private FirmwareUpdateService firmwareUpdateService

    def thing1
    def thing2
    def thing3

    private def firmwareProvider = [
        getFirmware: { firmwareUID, locale ->
            if(firmwareUID.equals(FW009_EN.getUID())) {
                FW009_EN
            } else if(firmwareUID.equals(FW111_EN.getUID())) {
                FW111_EN
            } else if(firmwareUID.equals(FW112_EN.getUID())) {
                FW112_EN
            } else if(firmwareUID.equals(FWALPHA_EN.getUID())) {
                FWALPHA_EN
            } else {
                null
            }
        },
        getFirmwares: { thingTypeUID, locale ->
            if(thingTypeUID.equals(THING_TYPE_UID_WITHOUT_FW) || thingTypeUID.equals(THING_TYPE_UID2) || thingTypeUID.equals(THING_TYPE_UID3)) {
                return [] as Set
            }
            [
                FW009_EN,
                FW111_EN,
                FW112_EN] as Set
        }] as FirmwareProvider

    private def firmwareStatusInfoEventSubscriber = new EventSubscriber() {

        private final def topics = ImmutableSet.of(FirmwareEventFactory.FIRMWARE_STATUS_TOPIC.replace(FirmwareEventFactory.THING_UID_TOPIC_KEY, THING1_UID.getAsString()),
        FirmwareEventFactory.FIRMWARE_STATUS_TOPIC.replace(FirmwareEventFactory.THING_UID_TOPIC_KEY, THING2_UID.getAsString()),
        FirmwareEventFactory.FIRMWARE_STATUS_TOPIC.replace(FirmwareEventFactory.THING_UID_TOPIC_KEY, THING3_UID.getAsString()),
        FirmwareEventFactory.FIRMWARE_STATUS_TOPIC.replace(FirmwareEventFactory.THING_UID_TOPIC_KEY, THING4_UID.getAsString()),
        FirmwareEventFactory.FIRMWARE_STATUS_TOPIC.replace(FirmwareEventFactory.THING_UID_TOPIC_KEY, UNKNOWN_THING_UID.getAsString()))

        def events = []

        @Override
        public Set<String> getSubscribedEventTypes() {
            return ImmutableSet.copyOf(FirmwareStatusInfoEvent.TYPE)
        }

        @Override
        public EventFilter getEventFilter() {
            return new EventFilter() {
                        @Override
                        boolean apply(Event event) {
                            topics.contains(event.getTopic())
                        };
                    };
        }

        @Override
        public void receive(Event event) {
            events.add(event);
        }
    } as EventSubscriber

    private def progressInfoEventSubscriber = new EventSubscriber() {

        private final def topics = ImmutableSet.of(FirmwareEventFactory.FIRMWARE_UPDATE_PROGRESS_TOPIC.replace(FirmwareEventFactory.THING_UID_TOPIC_KEY, THING1_UID.getAsString()))

        def events = []

        @Override
        public Set<String> getSubscribedEventTypes() {
            return ImmutableSet.copyOf(FirmwareUpdateProgressInfoEvent.TYPE)
        }

        @Override
        public EventFilter getEventFilter() {
            return new EventFilter() {
                        @Override
                        boolean apply(Event event) {
                            topics.contains(event.getTopic())
                        };
                    };
        }

        @Override
        public void receive(Event event) {
            events.add(event);
        }
    } as EventSubscriber

    private def firmwareUpdateResultInfoEventSubscriber = new EventSubscriber() {

        private final def topics = ImmutableSet.of(FirmwareEventFactory.FIRMWARE_UPDATE_RESULT_TOPIC.replace(FirmwareEventFactory.THING_UID_TOPIC_KEY, THING1_UID.getAsString()))

        def events = []

        @Override
        public Set<String> getSubscribedEventTypes() {
            return ImmutableSet.copyOf(FirmwareUpdateResultInfoEvent.TYPE)
        }

        @Override
        public EventFilter getEventFilter() {
            return new EventFilter() {
                        @Override
                        boolean apply(Event event) {
                            topics.contains(event.getTopic())
                        };
                    };
        }

        @Override
        public void receive(Event event) {
            events.add(event);
        }
    } as EventSubscriber

    @Before
    void setup() {
        _defaultLocale = Locale.getDefault()
        setDefaultLocale(Locale.ENGLISH)

        registerVolatileStorageService()
        waitForAssert {
            managedThingProvider = getService ManagedThingProvider
            assertThat managedThingProvider, is(notNullValue())
        }
        
        thingRegistry = getService(ThingRegistry)
        assertThat thingRegistry, is(notNullValue())

        registerThingTypeProvider()
        registerConfigDescriptionProvider()

        firmwareRegistry = getService(FirmwareRegistry)
        assertThat firmwareRegistry, is(notNullValue())

        firmwareUpdateService = getService(FirmwareUpdateService)
        assertThat firmwareUpdateService, is(notNullValue())

        registerService(firmwareProvider, FirmwareProvider.class.getName())
        registerService(firmwareStatusInfoEventSubscriber, EventSubscriber.class.getName())

        def firmwareUpdateThingHandlerFactory = new FirmwareUpdateThingHandlerFactory()
        firmwareUpdateThingHandlerFactory.activate([getBundleContext: { bundleContext }] as ComponentContext)
        registerService(firmwareUpdateThingHandlerFactory, ThingHandlerFactory.class.name)

        thing1 = ThingBuilder.create(THING_TYPE_UID1, THING1_ID).withProperties([(Thing.PROPERTY_FIRMWARE_VERSION) : V111]).build()
        thing2 = ThingBuilder.create(THING_TYPE_UID1, THING2_ID).withProperties([(Thing.PROPERTY_FIRMWARE_VERSION) : V112]).build()
        thing3 = ThingBuilder.create(THING_TYPE_UID2, THING3_ID).withProperties([(Thing.PROPERTY_FIRMWARE_VERSION) : VALPHA]).build()

        managedThingProvider.add(thing1)
        managedThingProvider.add(thing2)
        managedThingProvider.add(thing3)

        waitForAssert {
            assertThat thing1.getStatus(), is(ThingStatus.ONLINE)
            assertThat thing2.getStatus(), is(ThingStatus.ONLINE)
            assertThat thing3.getStatus(), is(ThingStatus.ONLINE)
        }

        def expectedInitializedFirmwareStatusInfoEvents = 3
        waitForAssert {
            assertThat firmwareStatusInfoEventSubscriber.events.size(), is(expectedInitializedFirmwareStatusInfoEvents)
        }
    }

    @After
    void teardown() {
        managedThingProvider.getAll().each {
            managedThingProvider.remove(it.getUID())
        }
        unregisterMocks()
        setDefaultLocale(_defaultLocale)
    }

    @Test
    void 'assert that BaseThingHandlerFactory registers firmware update handler'() {
        def handler = thing1.getHandler()
        assertThat handler, is(not(null))

        def firmwareUpdateHandler = getService(FirmwareUpdateHandler)
        assertThat firmwareUpdateHandler, is(handler)
    }

    @Test
    void 'assert that correct firmware status is provided'() {
        assertThat thing1.getProperties().get(Thing.PROPERTY_FIRMWARE_VERSION), is(V111)
        assertThat thing2.getProperties().get(Thing.PROPERTY_FIRMWARE_VERSION), is(V112)

        assertThat firmwareUpdateService.getFirmwareStatusInfo(THING1_UID), is(updateExecutableInfoFw112)
        assertFirmwareStatusInfoEvent(THING1_UID, updateExecutableInfoFw112)
{'fraction_non_alphanumeric': 0.07860548532435152, 'fraction_numerical': 0.01023577271335462, 'mean_word_length': 3.2788695489425415, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 4, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '540744', 'n_tokens_mistral': 6531, 'n_tokens_neox': 6219, 'n_words': 1046}