From fcc0754f1b12e9a1af99ee4edf7a375c28b2acfa Mon Sep 17 00:00:00 2001 From: Kai Kreuzer Date: Tue, 24 Jun 2014 18:40:46 +0200 Subject: [PATCH] Added some initial documentation structure Signed-off-by: Kai Kreuzer --- docs/sources/.project | 11 ++ docs/sources/architecture/Overview.md | 59 ++++++++++ docs/sources/development/Unit-Testing.md | 125 +++++++++++++++++++++ docs/sources/howtos/Binding-Development.md | 6 + 4 files changed, 201 insertions(+) create mode 100644 docs/sources/.project create mode 100644 docs/sources/architecture/Overview.md create mode 100644 docs/sources/development/Unit-Testing.md create mode 100644 docs/sources/howtos/Binding-Development.md diff --git a/docs/sources/.project b/docs/sources/.project new file mode 100644 index 00000000..e248a4fa --- /dev/null +++ b/docs/sources/.project @@ -0,0 +1,11 @@ + + + docs + + + + + + + + diff --git a/docs/sources/architecture/Overview.md b/docs/sources/architecture/Overview.md new file mode 100644 index 00000000..2c339975 --- /dev/null +++ b/docs/sources/architecture/Overview.md @@ -0,0 +1,59 @@ +# Overview + +Eclipse SmartHome is a framework for building smart home solutions. As such, it consists of a rich set of OSGi bundles that serve different purposes. Not all solutions that build on top of Eclipse SmartHome will require all of those bundles - instead they can choose what parts are interesting for them. + +There are the following categories of bundles: + + - `config`: everything that is concerned with general configuration of the system like config files, xml parsing, etc. + - `core`: the main bundles for the logical operation of the system - based on the abstract item and event concepts. + - `io`: all kinds of optional functionality that have to do with i/o like console commands, audio support or http/rest communication + - `model`: support for domain specific languages (DSLs) + - `designer`: Eclipse RCP support for DSLs and other configuration files + - `ui`: user interface related bundles that provide services that can be used by different UIs, such as charting or icons + +# General Concepts + +## Items and Events + +Eclipse SmartHome has a strict separation between the physical world (the "things", see below) and the application, which is built around the notion of "items" (also called the virtual layer). + +Items represent functionality that is used by the application (mainly user interfaces or automation logic). Items have a state and are used through events. + +The event bus is THE base service of Eclipse SmartHome. All bundles that do not require stateful behaviour should use it to inform other bundles about events and to be updated by other bundles on external events. + +There are mainly two types of events: + + - Commands, which trigger an action or a state change of some item. + - State updates, which inform about a state change of some item (often as a response to a command) + +The following item types are currently available (alphabetical order): + + + + + + + + + + + + +
ItemnameDescriptionCommand Types
ColorColor information (RGB)OnOff, IncreaseDecrease, Percent, HSB
ContactItem storing status of e.g. door/window contactsOpenClose
DateTimeStores date and time
DimmerItem carrying a percentage value for dimmersOnOff, IncreaseDecrease, Percent
GroupItem to nest other items / collect them in groups-
NumberStores values in number formatDecimal
RollershutterTypically used for blindsUpDown, StopMove, Percent
StringStores textsString
SwitchTypically used for lights (on/off)OnOff
+ +Group Items can derive their own state depending on their member items. + + - AVG displays the average of the item states in the group. + - OR displays an OR of the group, typically used to display whether any item in a group has been set. + - other aggregations: AND, SUM, MIN, MAX, NAND, NOR + +It is important to note that Eclipse SmartHome is not meant to reside on (or near) actual hardware devices which would then have to remotely communicate with many other distributed instances. Instead, solutions based on Eclipse SmartHome serve as an integration hub between such devices and as a mediator between different protocols that are spoken between these devices. In a typical installation there will therefore be usually just one instance of Eclipse SmartHome running on some central server. Nonetheless, the events can also be exported through appropriate protocols such as MQTT, so that it is possible to connect several distributed Eclipse SmartHome instances. + + +## Things + +t.b.d. + +## Bindings + +t.b.d. \ No newline at end of file diff --git a/docs/sources/development/Unit-Testing.md b/docs/sources/development/Unit-Testing.md new file mode 100644 index 00000000..62ab6e54 --- /dev/null +++ b/docs/sources/development/Unit-Testing.md @@ -0,0 +1,125 @@ +Testing Eclipse SmartHome +=== +There are two different kinds of approaches for testing Eclipse SmartHome. One is to use plain JUnit tests for testing simple classes. The other is to execute JUnit tests within the OSGi environment to test OSGi services and dynamic behaviour. Both approaches are supported through a simple infrastructure, which allows to easily write and execute tests. + +Test fragment +--- + +In OSGi tests are implemented in a separate fragment bundle, which host is the bundle, that should be tested. The name of the test fragment bundle should be the same as the bundle to test with a ".test" suffix. The MANIFEST.MF file must contain a `Fragment-Host` entry. Fragment bundles inherit all imported packages from the host bundle. In addition the fragment bundle must import the `org.junit` package with a minimum version of 4.0.0 specified. The following code snippet shows a manifest file of the test fragment for the `org.eclipse.smarthome.core.library` bundle. + + Manifest-Version: 1.0 + Bundle-ManifestVersion: 2 + Bundle-Name: Tests for the Eclipse SmartHome Core Library + Bundle-SymbolicName: org.eclipse.smarthome.core.library.test + Bundle-Version: 0.7.0.qualifier + Bundle-Vendor: Eclipse.org/SmartHome + Fragment-Host: org.eclipse.smarthome.core.library + Bundle-RequiredExecutionEnvironment: JavaSE-1.7 + Import-Package: org.junit;version="4.0.0" + +Tests are typically placed inside the folder `src/test/java`. + +Unit tests +--- + +Each class inside the test folder, which has a public method with a `@Test` annotation will automatically be executed as a test. Inside the class one can refer to all classes from the host bundle and all imported classes. The following code snippet shows a simple JUnit test which tests the `toString` conversation of a PercentType. + + public class PercentTypeTest { + @Test + public void DoubleValue() { + PercentType pt = new PercentType("0.0001"); + assertEquals("0.0001", pt.toString()); + } + } + +Using the the [https://code.google.com/p/hamcrest/ hamcrest] matcher library is a good way to write expressive assertions. In contrast to the original assertion statements from JUnit the hamcrest matcher library allows to define the assertion in a more natural order: + + PercentType pt = new PercentType("0.0001"); + assertThat pt.toString(), is(equalTo("0.0001")) + +To use the hamcrest library in your test project, you just have to add the following entry to the list of imported packages: + + org.hamcrest;core=split + +Tests can be executed from Eclipse by right-clicking the test file and clicking on `Run As => JUnit Test`. From maven one can execute the test with `mvn test` command in the folder of the test fragment bundle. + +Groovy +--- + +Using the JVM language Groovy tests are very easy and efficient to write. Groovy supports mocking without any frameworks. Language features like closures, type-inference and native syntax for maps and lists allow to implement short and easy to understand tests. Thus Eclipse SmartHome comes with a out-of-the-boc-support for Groovy-testing in Eclipse and maven. Each test file which is placed under `src/test/groovy` will be automatically compiled and executed in Eclipse and maven. Moreover the Eclipse SmartHome Yoxos profile contains the Groovy-Eclipse-Plugin. + +Even the following examples are presented in Groovy, unit and OSGi tests can also be implemented in Java. If the default mocking capabilities of Groovy do not fulfil the requirements, Groovy can also be combined with Java mocking frameworks like [https://code.google.com/p/mockito/ mockito]. + +== OSGi-Tests == + +Some components of Eclipse SmartHome are heavily bound to the OSGi runtime, because they use OSGi core services like the EventAdmin or the ConfigurationAdmin. That makes it hard to test those components outside of the OSGi container. Equinox provides a possibility to execute a JUnit tests inside the OSGi environment, where the test has access to OSGi services. + +Eclipse SmartHome comes with an abstract base class `OSGiTest` for OSGi tests. The base class sets up a bundle context and has convenience methods for registering mocks as OSGi services and the retrieval of registered OSGi services. The following Groovy test class shows how to test the `ItemRegistry` by providing a mocked `ItemProvider`. + + class ItemRegistryOSGiTest extends OSGiTest { + + ItemRegistry itemRegistry + ItemProvider itemProvider + def ITEM_NAME = "switchItem" + + @Before + void setUp() { + itemRegistry = getService(ItemRegistry) + itemProvider = [ + getItems: {[new SwitchItem(ITEM_NAME)]}, + addItemChangeListener: {def itemCHangeListener -> }, + removeItemChangeListener: {def itemCHangeListener -> }] as ItemProvider + } + + @Test + void 'assert getItems returns item from registered ItemProvider'() { + + assertThat itemRegistry.getItems().size, is(0) + + registerService itemProvider + + def items = itemRegistry.getItems() + assertThat items.size, is(1) + assertThat items.first().name, is(equalTo(ITEM_NAME)) + + unregisterService itemProvider + + assertThat itemRegistry.getItems().size, is(0) + } + } + +In the `setUp` method the `ItemRegistry` OSGi service is retrieved through the method `getService` from the base class `OSGiTest` and assigned to a private variable. After it a new `ItemProvider` mock is created, which returns one item. The test method first checks that no item is inside the registry. Afterwards it registers the mocked `ItemProvider` as OSGi service with the method `registerService` and checks if the `ItemRegistry` returns one item now. At the end the mock is unregistered again. + +In Eclipse the tests can be executed by right-clicking the test file and clicking on `Run As => JUnit Plug-In Test`. The launch config must be adapted, by selecting the bundle to test under the `Plug-Ins` tab and by clicking on `Add Required Plug-Ins`. Moreover you have to set the Auto-Start option to `true`. If the bundle that should be tested makes use of declarative services (has xml files in OSGI-INF folder), the bundle `org.eclipse.equinox.ds` must also be selected and also the required Plug-Ins of it. The `Validate Plug-Ins` button can be used to check if the launch config is valid. To avoid the manual selection of bundles, one can also choose `all workspace and enabled target plug-ins` with default `Default Auto-Start` set to `true`. The disadvantage is, that this will start all bundles, which makes the test execution really slow and will prodcue a lot of errors on the OSGi console. It is a good practice to store a launch configuration file, that launches all test cases for a test fragment. + +From maven the test can be executed by calling `mvn integration-test`. For executing the test in maven, tycho calculates the list of depended bundles automatically from package imports. Only if there is no dependency to a bundle, the bundle must be added manually to the test execution environment. For example Eclipse SmartHome makes use of OSGi declarative services. That allows to define service components through XML files. In order to support declarative services in the test environment the according bundle must be added in the pom file within the `tycho-surefire-plugin` configuration section as followed: + + ... + + + + org.eclipse.tycho + tycho-surefire-plugin + ${tycho-version} + + + + eclipse-plugin + org.eclipse.equinox.ds + 0.0.0 + + + + + org.eclipse.equinox.ds + 1 + true + + + + + + + ... + +In the dependency definition the `artifactId` is the name of the required bundle, where the version can always be `0.0.0`. Within the `bundleStartLevel` definition the start level and auto start of the depended bundles can be configured. The `org.eclipse.equinox.ds` bundle must have level 1 and must be started automatically. diff --git a/docs/sources/howtos/Binding-Development.md b/docs/sources/howtos/Binding-Development.md new file mode 100644 index 00000000..8addf5ba --- /dev/null +++ b/docs/sources/howtos/Binding-Development.md @@ -0,0 +1,6 @@ +# Introduction + +This page gives you a starting point, if you intent to implement (and hopefully contribute) your own binding. +It guides you step by step through the implementation and explains the relevant concepts. + +t.b.c.