//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

=== Writing integration tests

We recommend using http://team.ops4j.org/wiki/display/paxexam/Pax+Exam[PAX Exam] to write integration tests when developing applications using Karaf.

Starting with Karaf 3.0 we've also included a component briding between Karaf and Pax Exam making it easier to write integration tests
for Karaf or Karaf based distributions.

==== Introduction

Pax Exam directly supports Karaf as a test container.

To make use of this new framework simply add the following dependencies into your integration tests pom.xml:

----
<dependency>
  <groupId>org.ops4j.pax.exam</groupId>
  <artifactId>pax-exam-container-karaf</artifactId>
  <version>4.7.0</version>
  <scope>test</scope>
</dependency>
<dependency>
  <groupId>org.ops4j.pax.exam</groupId>
  <artifactId>pax-exam-junit4</artifactId>
  <version>4.7.0</version>
  <scope>test</scope>
</dependency>
<dependency>
  <groupId>org.apache.geronimo.specs</groupId>
  <artifactId>geronimo-atinject-1.0_spec</artifactId>
  <version>1.0</version>
  <scope>test</scope>
</dependency>
----

As a next step you need to reference the distribution you want to run your tests on.
For instance, if you want to run your tests on Karaf the following section would be required in the integration tests pom.xml:

----
<dependency>
  <groupId>org.apache.karaf</groupId>
  <artifactId>apache-karaf</artifactId>
  <version>4.0.0</version>
  <type>tar.gz</type>
  <scope>test</scope>
</dependency>
----

If you want to make use of Exams "versionAsInProject" feature you also need to add the following section:

----
<build>
  <plugins>
    <plugin>
      <groupId>org.apache.servicemix.tooling</groupId>
      <artifactId>depends-maven-plugin</artifactId>
      <version>1.2</version>
      <executions>
        <execution>
          <id>generate-depends-file</id>
          <goals>
            <goal>generate-depends-file</goal>
          </goals>
        </execution>
      </executions>
    </plugin>
  </plugins>
</build>
----

With this done we can start writing our first test case:

----
import static junit.framework.Assert.assertTrue;
import static org.ops4j.pax.exam.options.KarafDistributionOption.karafDistributionConfiguration;
import static org.ops4j.pax.exam.CoreOptions.maven;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.ops4j.pax.exam.Option;
import org.ops4j.pax.exam.junit.Configuration;
import org.ops4j.pax.exam.junit.ExamReactorStrategy;
import org.ops4j.pax.exam.junit.JUnit4TestRunner;
import org.ops4j.pax.exam.spi.reactors.AllConfinedStagedReactorFactory;

@RunWith(JUnit4TestRunner.class)
@ExamReactorStrategy(AllConfinedStagedReactorFactory.class)
public class VersionAsInProjectKarafTest {

    @Configuration
    public Option[] config() {
        return new Option[]{ karafDistributionConfiguration().frameworkUrl(
            maven().groupId("org.apache.karaf").artifactId("apache-karaf").type("tar.gz").versionAsInProject())
            .karafVersion("4.0.0").name("Apache Karaf")};
    }

    @Test
    public void test() throws Exception {
        assertTrue(true);
    }
}
----

==== Commands

===== KarafDistributionConfigurationOption

The framework itself is non of the typical runtimes you define normally in Pax-Exam.

Instead you define a packed distribution as zip or tar.gz. Those distributions have to follow the Karaf packaging style.
Therefore instead of Karaf you can also enter Servicemix or Geronimo.

----
new KarafDistributionConfigurationOption(
  "mvn:org.apache.karaf/apache-karaf/4.0.0/zip", // artifact to unpack and use
  "karaf", // name; display only
  "4.0.0") // the karaf version; this one is relevant since the startup script differs between versions
----

or for Servicemix e.g.

----
new KarafDistributionConfigurationOption(
  "mvn:org.apache.servicemix/apache-servicemix/4.4.0/zip", // artifact to unpack and use
  "servicemix", // name; display only
  "2.2.4") // the karaf version; this one is relevant since the startup script differs between versions
----

As an alternative you can also use the maven url resolvers.

----
...
<dependency>
  <groupId>org.apache.karaf</groupId>
  <artifactId>apache-karaf</artifactId>
  <type>zip</type>
  <classifier>bin</classifier>
  <scope>test</scope>
</dependency>
...
<plugin>
  <groupId>org.apache.servicemix.tooling</groupId>
  <artifactId>depends-maven-plugin</artifactId>
  <executions>
    <execution>
      <id>generate-depends-file</id>
      <goals>
        <goal>generate-depends-file</goal>
      </goals>
    </execution>
  </executions>
</plugin>
----

----
@Configuration
    public Option[] config() {
        return new Option[]{ karafDistributionConfiguration().frameworkUrl(
            maven().groupId("org.apache.karaf").artifactId("apache-karaf").type("zip")
                .classifier("bin").versionAsInProject()) };
    }
----

In addition to the framework specification options this option also includes various additional configuration options.
Those options are used to configure the internal properties of the runtime environment.

====== Unpack Directory

Pax-Exam Testframework extracts the distribution you specify by default into the paxexam config directory.
If you would like to unpack them into your target directory simply extend the KarafDistributionConfigurationOption with the unpackDirectoryFile like shown in the next example:

----
@Configuration
public Option[] config() {
    return new Option[]{ karafDistributionConfiguration("mvn:org.apache.karaf/apache-karaf/4.0.0/zip")
        .unpackDirectory(new File("target/paxexam/unpack/")) };
}
----

====== Use Deploy Folder

Karaf distributions come by default with a deploy folder where you can simply drop artifacts to be deployed.
In some distributions this folder might have been removed. To still be able to deploy your additional artifacts using
default Pax Exam ProvisionOptions you can configure PaxExam Karaf to use a features.xml (which is directly added to
your `etc/org.apache.karaf.features.cfg`) for those deploys. To use it instead of the deploy folder simply do the following:

----
@Configuration
public Option[] config() {
    return new Option[]{ karafDistributionConfiguration("mvn:org.apache.karaf/apache-karaf/4.0.0/zip")
        .useDeployFolder(false)) };
}
----

===== KarafDistributionKitConfigurationOption

The KarafDistributionKitConfigurationOption is almost equal to all variations of the KarafDistributionConfigurationOption
with the exception that it requires to have set a platform and optionally the executable and the files which should be
made executable additionally. By default it is bin/karaf for nix platforms and bin\karaf.bat for windows platforms.
The executable option comes in handy if you like to e.g. embed an own java runtime. You should add a windows AND a
linux Kit definition. The framework automatically takes the correct one then. The following shows a simple example for Karaf:

----
@Configuration
public Option[] config() {
    return new Option[]{
        new KarafDistributionKitConfigurationOption("mvn:org.apache.karaf/apache-karaf/4.0.0/zip",
            Platform.WINDOWS).executable("bin\\karaf.bat").filesToMakeExecutable("bin\\admin.bat"),
        new KarafDistributionKitConfigurationOption("mvn:org.apache.karaf/apache-karaf/4.0.0/tar.gz", "karaf",
            Platform.NIX).executable("bin/karaf").filesToMakeExecutable("bin/admin") };
}
----

===== KarafDistributionConfigurationFilePutOption

The option replaces or adds an option to one of Karaf's configuration files:

----
new KarafDistributionConfigurationFilePutOption(
  "etc/config.properties", // config file to modify based on karaf.base
  "karaf.framework", // key to add or change
  "equinox") // value to add or change
----

This option could also be used in "batch-mode" via a property file. Therefore use the
KarafDistributionOption#editConfigurationFilePut(final String configurationFilePath, File source, String... keysToUseFromSource) method.
This option allows you to add all properties found in the file as KarafDistributionConfigurationFilePutOption. If you configure the "keysToUseFromSource" array only the keys specified there will be used. That way you can easily put an entire range of properties.

===== KarafDistributionConfigurationFileExtendOption

This one does the same as the KarafDistributionConfigurationFilePutOption option with the one difference that it either
adds or appends a specific property. This is especially useful if you do not want to store the entire configuration in the line in your code.

This option could also be extended in "batch-mode" via a property file. Therefore use the
KarafDistributionOption#editConfigurationFileExtend(final String configurationFilePath, File source, String... keysToUseFromSource) method. This option allows you to extend all properties found in the file as KarafDistributionConfigurationFileExtendOption. If you configure the "keysToUseFromSource" array only the keys specified there will be used. That way you can easily extend an entire range of properties.

===== KarafDistributionConfigurationFileReplacementOption

The file replacement option allows you to simply replace a file in you Karaf distribution with a different file:

----
new KarafDistributionConfigurationFileReplacementOption("etc/tests.cfg", new File(
    "src/test/resources/BaseKarafDefaultFrameworkDuplicatedPropertyEntryTestSecondKey"));
----

===== ProvisionOption

The new test container fully supports the provision option. Feel free to use any option provided here by paxexam itself (e.g. Maven resolver).
All those artifacts are copied into the deploy folder of your Karaf distribution before it is started. Therefore they all will be available after startup.

===== KarafDistributionConfigurationConsoleOption

The test container supports options to configure if the localConsole and/or the remote shell should be started. Possible options to do so are shown in the following two examples:

----
@Configuration
public Option[] config() {
    return new Option[]{ karafDistributionConfiguration("mvn:org.apache.karaf/apache-karaf/4.0.0/zip"),
        configureConsole().ignoreLocalConsole().startRemoteShell() };
}
----

----
@Configuration
public Option[] config() {
    return new Option[]{ karafDistributionConfiguration("mvn:org.apache.karaf/apache-karaf/4.0.0/zip"),
        configureConsole().startLocalConsole(), configureConsole().ignoreRemoteShell() };
}
----

===== VMOption

The Karaf container passes the vmOptions now through to the Karaf environment. They are directly passed to the startup of the container.
In addition the KarafDistributionOption helper has two methods (debugConfiguration() and debugConfiguration(String port, boolean hold)) to activate debugging quickly.

===== LogLevelOption

The Paxexam-Karaf specific log-level option allows an easy way to set a specific log-level for the Karaf based distribution. For example simply add the following to your Option[] array to get TRACE logging:

----
import static org.openengsb.labs.paxexam.karaf.options.KarafDistributionOption.logLevel;
...
@Configuration
public Option[] config() {
    return new Option[]{ karafDistributionConfiguration("mvn:org.apache.karaf/apache-karaf/4.0.0/zip"),
        logLevel(LogLevel.TRACE) };
}
----

===== DoNotModifyLogOption

The option to modify the logging behavior requires that the container automatically modifies the logging configuration file.
If you would like to suppress this behavior simply set the doNotModifyLogConfiguration option as shown in the next example:

----
@Configuration
public Option[] config() {
    return new Option[]{ karafDistributionConfiguration("mvn:org.apache.karaf/apache-karaf/4.0.0/zip"),
        doNotModifyLogConfiguration() };
}
----

===== KeepRuntimeFolderOption

Per default the test container removes all test runner folders. If you want to keep them for any reasons (e.g. check why a test fails) set the following option:

----
@Configuration
public Option[] config() {
    return new Option[]{ karafDistributionConfiguration("mvn:org.apache.karaf/apache-karaf/4.0.0/zip"),
        keepRuntimeFolder() };
}
----

===== FeaturesScannerProvisionOption

The FeaturesScannerProvisionOption (e.g. CoreOption.scanFeature()) are directly supported by the Paxexam Karaf Testframework.

===== BootDelegationOption

The BootDelegationOption as known from PaxExam is also supported added the boot delegation string directly into the correct property files.

===== SystemPackageOption

The Standard Exam SystemPackageOption is implemented by adding those packages to "org.osgi.framework.system.packages.extra" of the config.properties file.

===== BootClasspathLibraryOption

The BootClasspathLibraryOption is honored by copying the urls into the lib directory where they are automatically taken and worked on.

===== ExamBundlesStartLevel

The ExamBundlesStartLevel can be used to configure the start lvl of the bundles provided by the test-frameworks features.xml. Simply use it as a new option like:

----
@Configuration
public Option[] config() {
    return new Option[]{ karafDistributionConfiguration("mvn:org.apache.karaf/apache-karaf/4.0.0/zip"),
            useOwnExamBundlesStartLevel(4) };
}
----

==== Driver

Drivers are the parts of the framework responsible for running the Karaf Based Distribution. By default the already in
the overview explained KarafDistributionConfigurationOption uses a JavaRunner starting the distribution platform independent
but not using the scripts in the distribution. If you like to test those scripts too an option is to to use the ScriptRunner via the KarafDistributionKitConfigurationOption instead.

===== JavaRunner

The JavaRunner builds the entire command itself and executes Karaf in a new JVM. This behavior is more or less exactly
what the default runner does. Simply use the KarafDistributionConfigurationOption as explained in the Commands section to use this.

===== ScriptRunner

The script runner has the disadvantage over the java runner that it is also platform dependent.
The advantage though is that you can also test your specific scripts. To use it follow the explanation of the KarafDistributionKitConfigurationOption in the Commands section.
