Introduce features-test 45/12045/3
authorRobert Varga <rovarga@cisco.com>
Fri, 17 Oct 2014 10:06:53 +0000 (12:06 +0200)
committerRobert Varga <rovarga@cisco.com>
Tue, 2 Dec 2014 15:51:08 +0000 (15:51 +0000)
This patch introduces the features-test from yangtools. It validates
that a project's feature is self-contained.

Change-Id: I7e6275ea465b79b2dc3cee5b105d8ca36c728cbc
Signed-off-by: Robert Varga <rovarga@cisco.com>
.gitignore
features-test/pom.xml [new file with mode: 0644]
features-test/src/main/java/org/opendaylight/odlparent/featuretest/Constants.java [new file with mode: 0644]
features-test/src/main/java/org/opendaylight/odlparent/featuretest/PerFeatureRunNotifier.java [new file with mode: 0644]
features-test/src/main/java/org/opendaylight/odlparent/featuretest/PerFeatureRunner.java [new file with mode: 0644]
features-test/src/main/java/org/opendaylight/odlparent/featuretest/PerRepoTestRunner.java [new file with mode: 0644]
features-test/src/main/java/org/opendaylight/odlparent/featuretest/SingleFeatureTest.java [new file with mode: 0644]
features-test/src/main/java/org/opendaylight/odlparent/featuretest/Util.java [new file with mode: 0644]
pom.xml

index bd7d934c3940075a5383a6d29bf57095078025bd..09918bc3d8f5835d75ab2e0d64a859b24bf04abf 100644 (file)
@@ -64,4 +64,6 @@ atlassian-ide-plugin.xml
 # generated by Crashlytics plugin (for Android Studio and Intellij)
 com_crashlytics_export_strings.xml
 
+# maven
+target
 
diff --git a/features-test/pom.xml b/features-test/pom.xml
new file mode 100644 (file)
index 0000000..0e3ac28
--- /dev/null
@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+ Copyright (c) 2014 Cisco Systems, Inc. and others.  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
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+    <parent>
+        <groupId>org.opendaylight.odlparent</groupId>
+        <artifactId>bundle-parent</artifactId>
+        <version>1.5.0-SNAPSHOT</version>
+        <relativePath>../bundle-parent</relativePath>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>features-test</artifactId>
+    <packaging>bundle</packaging>
+
+    <properties>
+        <pax.exam.version>3.5.0</pax.exam.version>
+    </properties>
+
+    <dependencies>
+        <!-- Dependencies for pax exam karaf container -->
+        <dependency>
+            <groupId>org.ops4j.pax.exam</groupId>
+            <artifactId>pax-exam-container-karaf</artifactId>
+            <version>${pax.exam.version}</version>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.ops4j.pax.exam</groupId>
+            <artifactId>pax-exam-junit4</artifactId>
+            <version>${pax.exam.version}</version>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.ops4j.pax.exam</groupId>
+            <artifactId>pax-exam</artifactId>
+            <version>${pax.exam.version}</version>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.ops4j.pax.url</groupId>
+            <artifactId>pax-url-aether</artifactId>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>javax.inject</groupId>
+            <artifactId>javax.inject</artifactId>
+            <version>1</version>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.karaf.features</groupId>
+            <artifactId>org.apache.karaf.features.core</artifactId>
+            <version>${karaf.version}</version>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.core</artifactId>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>commons-io</groupId>
+            <artifactId>commons-io</artifactId>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.karaf.tooling</groupId>
+            <artifactId>karaf-maven-plugin</artifactId>
+            <version>${karaf.version}</version>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/features-test/src/main/java/org/opendaylight/odlparent/featuretest/Constants.java b/features-test/src/main/java/org/opendaylight/odlparent/featuretest/Constants.java
new file mode 100644 (file)
index 0000000..1debbd5
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  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.opendaylight.odlparent.featuretest;
+
+public final class Constants {
+
+    private Constants() {
+        // Noop constructor
+    }
+
+    /*
+     * Named of System Properties we need to set in PerFeatureRunner and read in SingleFeatureTest
+     */
+    public static final String ORG_OPENDAYLIGHT_FEATURETEST_URI_PROP = "org.opendaylight.featuretest.uri";
+    public static final String ORG_OPENDAYLIGHT_FEATURETEST_FEATURENAME_PROP = "org.opendaylight.featuretest.featurename";
+    public static final String ORG_OPENDAYLIGHT_FEATURETEST_FEATUREVERSION_PROP = "org.opendaylight.featuretest.featureversion";
+}
diff --git a/features-test/src/main/java/org/opendaylight/odlparent/featuretest/PerFeatureRunNotifier.java b/features-test/src/main/java/org/opendaylight/odlparent/featuretest/PerFeatureRunNotifier.java
new file mode 100644 (file)
index 0000000..1e9cb45
--- /dev/null
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  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.opendaylight.odlparent.featuretest;
+
+import java.net.URL;
+
+import org.junit.runner.Description;
+import org.junit.runner.Result;
+import org.junit.runner.notification.Failure;
+import org.junit.runner.notification.RunListener;
+import org.junit.runner.notification.RunNotifier;
+import org.junit.runner.notification.StoppedByUserException;
+
+import com.google.common.base.Preconditions;
+
+public class PerFeatureRunNotifier extends RunNotifier {
+    private final RunNotifier delegate;
+    private final URL repoURL;
+    private final String featureName;
+    private  final String featureVersion;
+
+    public PerFeatureRunNotifier(final URL repoURL, final String featureName, final String featureVersion,final RunNotifier delegate) {
+        Preconditions.checkNotNull(repoURL);
+        Preconditions.checkNotNull(featureName);
+        Preconditions.checkNotNull(featureVersion);
+        Preconditions.checkNotNull(delegate);
+        this.delegate = delegate;
+        this.repoURL = repoURL;
+        this.featureName = featureName;
+        this.featureVersion = featureVersion;
+    }
+
+    private Failure convertFailure(final Failure failure) {
+        return new Failure(Util.convertDescription(repoURL,featureName,featureVersion,failure.getDescription()),failure.getException());
+    }
+
+    /**
+     * @param listener
+     * @see org.junit.runner.notification.RunNotifier#addListener(org.junit.runner.notification.RunListener)
+     */
+    @Override
+    public void addListener(RunListener listener) {
+        delegate.addListener(listener);
+    }
+
+    /**
+     * @param listener
+     * @see org.junit.runner.notification.RunNotifier#removeListener(org.junit.runner.notification.RunListener)
+     */
+    @Override
+    public void removeListener(RunListener listener) {
+        delegate.removeListener(listener);
+    }
+
+    /**
+     * @return
+     * @see java.lang.Object#hashCode()
+     */
+    @Override
+    public int hashCode() {
+        return delegate.hashCode();
+    }
+
+    /**
+     * @param description
+     * @see org.junit.runner.notification.RunNotifier#fireTestRunStarted(org.junit.runner.Description)
+     */
+    @Override
+    public void fireTestRunStarted(Description description) {
+        delegate.fireTestRunStarted(Util.convertDescription(repoURL,featureName,featureVersion,description));
+    }
+
+    /**
+     * @param result
+     * @see org.junit.runner.notification.RunNotifier#fireTestRunFinished(org.junit.runner.Result)
+     */
+    @Override
+    public void fireTestRunFinished(Result result) {
+        delegate.fireTestRunFinished(result);
+    }
+
+    /**
+     * @param description
+     * @throws StoppedByUserException
+     * @see org.junit.runner.notification.RunNotifier#fireTestStarted(org.junit.runner.Description)
+     */
+    @Override
+    public void fireTestStarted(Description description)
+            throws StoppedByUserException {
+        delegate.fireTestStarted(Util.convertDescription(repoURL,featureName,featureVersion,description));
+    }
+
+    /**
+     * @param obj
+     * @return
+     * @see java.lang.Object#equals(java.lang.Object)
+     */
+    @Override
+    public boolean equals(Object obj) {
+        return delegate.equals(obj);
+    }
+
+    /**
+     * @param failure
+     * @see org.junit.runner.notification.RunNotifier#fireTestFailure(org.junit.runner.notification.Failure)
+     */
+    @Override
+    public void fireTestFailure(Failure failure) {
+        delegate.fireTestFailure(convertFailure(failure));
+    }
+
+    /**
+     * @param failure
+     * @see org.junit.runner.notification.RunNotifier#fireTestAssumptionFailed(org.junit.runner.notification.Failure)
+     */
+    @Override
+    public void fireTestAssumptionFailed(Failure failure) {
+        delegate.fireTestAssumptionFailed(convertFailure(failure));
+    }
+
+    /**
+     * @param description
+     * @see org.junit.runner.notification.RunNotifier#fireTestIgnored(org.junit.runner.Description)
+     */
+    @Override
+    public void fireTestIgnored(Description description) {
+        delegate.fireTestIgnored(Util.convertDescription(repoURL,featureName,featureVersion,description));
+    }
+
+    /**
+     * @param description
+     * @see org.junit.runner.notification.RunNotifier#fireTestFinished(org.junit.runner.Description)
+     */
+    @Override
+    public void fireTestFinished(Description description) {
+        delegate.fireTestFinished(Util.convertDescription(repoURL,featureName,featureVersion,description));
+    }
+
+    /**
+     *
+     * @see org.junit.runner.notification.RunNotifier#pleaseStop()
+     */
+    @Override
+    public void pleaseStop() {
+        delegate.pleaseStop();
+    }
+
+    /**
+     * @param listener
+     * @see org.junit.runner.notification.RunNotifier#addFirstListener(org.junit.runner.notification.RunListener)
+     */
+    @Override
+    public void addFirstListener(RunListener listener) {
+        delegate.addFirstListener(listener);
+    }
+
+    /**
+     * @return
+     * @see java.lang.Object#toString()
+     */
+    @Override
+    public String toString() {
+        return delegate.toString();
+    }
+
+
+}
diff --git a/features-test/src/main/java/org/opendaylight/odlparent/featuretest/PerFeatureRunner.java b/features-test/src/main/java/org/opendaylight/odlparent/featuretest/PerFeatureRunner.java
new file mode 100644 (file)
index 0000000..a7df172
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  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.opendaylight.odlparent.featuretest;
+
+import static org.opendaylight.odlparent.featuretest.Constants.ORG_OPENDAYLIGHT_FEATURETEST_FEATURENAME_PROP;
+import static org.opendaylight.odlparent.featuretest.Constants.ORG_OPENDAYLIGHT_FEATURETEST_FEATUREVERSION_PROP;
+import static org.opendaylight.odlparent.featuretest.Constants.ORG_OPENDAYLIGHT_FEATURETEST_URI_PROP;
+
+import java.net.URL;
+
+import org.junit.runner.Description;
+import org.junit.runner.Runner;
+import org.junit.runner.manipulation.Filter;
+import org.junit.runner.manipulation.NoTestsRemainException;
+import org.junit.runner.manipulation.Sorter;
+import org.junit.runner.notification.RunNotifier;
+import org.junit.runners.model.InitializationError;
+import org.ops4j.pax.exam.junit.PaxExam;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Preconditions;
+
+
+
+public class PerFeatureRunner extends Runner {
+    private static final Logger LOG = LoggerFactory.getLogger(PerFeatureRunner.class);
+    final PaxExam delegate;
+    final URL repoURL;
+    final private String featureName;
+    final private String featureVersion;
+
+    public PerFeatureRunner(final URL repoURL, final String featureName, final String featureVersion, final Class<?> testClass) throws InitializationError {
+        Preconditions.checkNotNull(repoURL);
+        Preconditions.checkNotNull(featureName);
+        Preconditions.checkNotNull(featureVersion);
+        Preconditions.checkNotNull(testClass);
+        System.setProperty(ORG_OPENDAYLIGHT_FEATURETEST_URI_PROP, repoURL.toString());
+        System.setProperty(ORG_OPENDAYLIGHT_FEATURETEST_FEATURENAME_PROP, featureName);
+        System.setProperty(ORG_OPENDAYLIGHT_FEATURETEST_FEATUREVERSION_PROP,featureVersion);
+        this.delegate = new PaxExam(testClass);
+        this.featureName = featureName;
+        this.featureVersion = featureVersion;
+        this.repoURL = repoURL;
+    }
+
+    @Override
+    public Description getDescription() {
+        return Util.convertDescription(repoURL,featureName,featureVersion,delegate.getDescription());
+    }
+
+    @Override
+    public void run(RunNotifier notifier) {
+        LOG.info("About to run test for feature: {} {}", featureName, featureVersion);
+        System.setProperty(ORG_OPENDAYLIGHT_FEATURETEST_URI_PROP, repoURL.toString());
+        System.setProperty(ORG_OPENDAYLIGHT_FEATURETEST_FEATURENAME_PROP, featureName);
+        System.setProperty(ORG_OPENDAYLIGHT_FEATURETEST_FEATUREVERSION_PROP,featureVersion);
+        delegate.run(new PerFeatureRunNotifier(repoURL,featureName, featureVersion,notifier));
+    }
+
+    /**
+     * @return
+     * @see org.junit.runner.Runner#testCount()
+     */
+    @Override
+    public int testCount() {
+        return delegate.testCount();
+    }
+
+    /**
+     * @param filter
+     * @throws NoTestsRemainException
+     * @see org.ops4j.pax.exam.junit.PaxExam#filter(org.junit.runner.manipulation.Filter)
+     */
+    public void filter(Filter filter) throws NoTestsRemainException {
+        delegate.filter(filter);
+    }
+
+    /**
+     * @param sorter
+     * @see org.ops4j.pax.exam.junit.PaxExam#sort(org.junit.runner.manipulation.Sorter)
+     */
+    public void sort(Sorter sorter) {
+        delegate.sort(sorter);
+    }
+
+    /**
+     * @return
+     * @see java.lang.Object#toString()
+     */
+    public String toString() {
+        return delegate.toString();
+    }
+
+    /**
+     * @return the repoURL
+     */
+    public URL getRepoURL() {
+        return repoURL;
+    }
+
+    /**
+     * @return the featureName
+     */
+    public String getFeatureName() {
+        return featureName;
+    }
+
+    /**
+     * @return the featureVersion
+     */
+    public String getFeatureVersion() {
+        return featureVersion;
+    }
+
+
+
+}
diff --git a/features-test/src/main/java/org/opendaylight/odlparent/featuretest/PerRepoTestRunner.java b/features-test/src/main/java/org/opendaylight/odlparent/featuretest/PerRepoTestRunner.java
new file mode 100644 (file)
index 0000000..9bb593c
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  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.opendaylight.odlparent.featuretest;
+
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Unmarshaller;
+
+import org.apache.karaf.features.internal.model.Feature;
+import org.apache.karaf.features.internal.model.Features;
+import org.apache.karaf.tooling.url.CustomBundleURLStreamHandlerFactory;
+import org.junit.runner.Description;
+import org.junit.runner.notification.RunNotifier;
+import org.junit.runners.ParentRunner;
+import org.junit.runners.model.InitializationError;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+
+public class PerRepoTestRunner extends ParentRunner<PerFeatureRunner> {
+    private static final String REPO_RECURSE = "repo.recurse";
+    private static final Logger LOG = LoggerFactory.getLogger(PerRepoTestRunner.class);
+    private static final String FEATURES_FILENAME = "features.xml";
+    protected final List<PerFeatureRunner> children = new ArrayList<PerFeatureRunner>();
+
+
+    public PerRepoTestRunner(final Class<?> testClass) throws InitializationError {
+        super(testClass);
+        try {
+            URL.setURLStreamHandlerFactory(new CustomBundleURLStreamHandlerFactory());
+            URL repoURL = getClass().getClassLoader().getResource(FEATURES_FILENAME);
+            boolean recursive = Boolean.getBoolean(REPO_RECURSE);
+            LOG.info("Creating test runners for repoURL {} recursive {}",repoURL,recursive);
+            children.addAll(runnersFromRepoURL(repoURL,testClass,recursive));
+        } catch (Exception e) {
+            throw new InitializationError(e);
+        }
+    }
+
+    protected List<PerFeatureRunner> runnersFromRepoURL(final URL repoURL,final Class<?> testClass,boolean recursive) throws JAXBException, IOException, InitializationError {
+        if(recursive) {
+            return recursiveRunnersFromRepoURL(repoURL,testClass);
+        } else {
+            return runnersFromRepoURL(repoURL,testClass);
+        }
+    }
+
+    protected List<PerFeatureRunner> runnersFromRepoURL(final URL repoURL,final Class<?> testClass) throws JAXBException, IOException, InitializationError {
+        List<PerFeatureRunner> runners = new ArrayList<PerFeatureRunner>();
+        Features features = getFeatures(repoURL);
+        runners.addAll(runnersFromFeatures(repoURL,features,testClass));
+        return runners;
+    }
+
+    protected List<PerFeatureRunner> recursiveRunnersFromRepoURL(final URL repoURL,final Class<?> testClass) throws JAXBException, IOException, InitializationError {
+        List<PerFeatureRunner> runners = new ArrayList<PerFeatureRunner>();
+        Features features = getFeatures(repoURL);
+        runners.addAll(runnersFromRepoURL(repoURL,testClass));
+        for(String repoString: features.getRepository()) {
+            URL subRepoURL = new URL(repoString);
+            runners.addAll(recursiveRunnersFromRepoURL(subRepoURL,testClass));
+        }
+        return runners;
+    }
+
+    protected List<PerFeatureRunner> runnersFromFeatures(final URL repoURL, final Features features,final Class<?> testClass) throws InitializationError {
+        final List<PerFeatureRunner> runners = new ArrayList<>();
+        final List<Feature> featureList = features.getFeature();
+        for(final Feature f : featureList) {
+            runners.add(new PerFeatureRunner(repoURL, f.getName(), f.getVersion(),testClass));
+        }
+        return runners;
+    }
+
+    /**
+     * @param repoURL
+     * @return
+     * @throws JAXBException
+     * @throws IOException
+     */
+    protected Features getFeatures(final URL repoURL) throws JAXBException,
+            IOException {
+        JAXBContext context;
+        context = JAXBContext.newInstance(Features.class);
+        Unmarshaller unmarshaller = context.createUnmarshaller();
+        Object obj = unmarshaller.unmarshal(repoURL.openStream());
+        Features features =(Features)  obj;
+        return features;
+    }
+
+    @Override
+    protected List<PerFeatureRunner> getChildren() {
+        return children;
+    }
+
+    @Override
+    protected Description describeChild(final PerFeatureRunner child) {
+        return child.getDescription();
+    }
+
+    @Override
+    protected void runChild(PerFeatureRunner child, RunNotifier notifier) {
+        LOG.info("About to run test for {}",child.repoURL);
+        child.run(notifier);
+    }
+
+    /* (non-Javadoc)
+     * @see org.junit.runner.Runner#testCount()
+     */
+    @Override
+    public int testCount() {
+        return super.testCount()*children.size();
+    }
+
+
+
+}
diff --git a/features-test/src/main/java/org/opendaylight/odlparent/featuretest/SingleFeatureTest.java b/features-test/src/main/java/org/opendaylight/odlparent/featuretest/SingleFeatureTest.java
new file mode 100644 (file)
index 0000000..f277309
--- /dev/null
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  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.opendaylight.odlparent.featuretest;
+
+import static org.opendaylight.odlparent.featuretest.Constants.ORG_OPENDAYLIGHT_FEATURETEST_FEATURENAME_PROP;
+import static org.opendaylight.odlparent.featuretest.Constants.ORG_OPENDAYLIGHT_FEATURETEST_FEATUREVERSION_PROP;
+import static org.opendaylight.odlparent.featuretest.Constants.ORG_OPENDAYLIGHT_FEATURETEST_URI_PROP;
+import static org.ops4j.pax.exam.CoreOptions.maven;
+import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.configureConsole;
+import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.editConfigurationFilePut;
+//import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.debugConfiguration;
+import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.karafDistributionConfiguration;
+import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.keepRuntimeFolder;
+import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.logLevel;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+
+import javax.inject.Inject;
+
+import org.apache.karaf.features.Feature;
+import org.apache.karaf.features.FeaturesService;
+import org.apache.karaf.features.Repository;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.ops4j.pax.exam.Configuration;
+import org.ops4j.pax.exam.CoreOptions;
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.karaf.options.LogLevelOption.LogLevel;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+@RunWith(PerRepoTestRunner.class)
+public class SingleFeatureTest {
+    private static final String MAVEN_REPO_LOCAL = "maven.repo.local";
+    private static final String ORG_OPS4J_PAX_URL_MVN_LOCAL_REPOSITORY = "org.ops4j.pax.url.mvn.localRepository";
+    private static final String ETC_ORG_OPS4J_PAX_URL_MVN_CFG = "etc/org.ops4j.pax.url.mvn.cfg";
+    private static final String LOG4J_LOGGER_ORG_OPENDAYLIGHT_YANGTOOLS_FEATURETEST = "log4j.logger.org.opendaylight.odlparent.featuretest";
+    private static final Logger LOG = LoggerFactory.getLogger(SingleFeatureTest.class);
+
+    /*
+     * File name to add our logging config property too.
+     */
+    private static final String ORG_OPS4J_PAX_LOGGING_CFG = "etc/org.ops4j.pax.logging.cfg";
+
+    /*
+     * Default values for karaf distro version, type, groupId, and artifactId
+     */
+    private static final String KARAF_DISTRO_VERSION = "3.0.1";
+    private static final String KARAF_DISTRO_TYPE = "zip";
+    private static final String KARAF_DISTRO_ARTIFACTID = "apache-karaf";
+    private static final String KARAF_DISTRO_GROUPID = "org.apache.karaf";
+
+    /*
+     * Property names to override defaults for karaf distro artifactId, groupId, version, and type
+     */
+    private static final String KARAF_DISTRO_VERSION_PROP = "karaf.distro.version";
+    private static final String KARAF_DISTRO_TYPE_PROP = "karaf.distro.type";
+    private static final String KARAF_DISTRO_ARTIFACTID_PROP = "karaf.distro.artifactId";
+    private static final String KARAF_DISTRO_GROUPID_PROP = "karaf.distro.groupId";
+
+
+   @Inject
+   private FeaturesService featuresService;
+
+    @Configuration
+    public Option[] config() throws IOException {
+       return new Option[] {
+             getKarafDistroOption(),
+             keepRuntimeFolder(),
+             configureConsole().ignoreLocalConsole(),
+             logLevel(LogLevel.WARN),
+             mvnLocalRepoOption(),
+             editConfigurationFilePut(ORG_OPS4J_PAX_LOGGING_CFG,LOG4J_LOGGER_ORG_OPENDAYLIGHT_YANGTOOLS_FEATURETEST,LogLevel.INFO.name()),
+             CoreOptions.systemProperty(ORG_OPENDAYLIGHT_FEATURETEST_URI_PROP).value(System.getProperty(ORG_OPENDAYLIGHT_FEATURETEST_URI_PROP)),
+             CoreOptions.systemProperty(ORG_OPENDAYLIGHT_FEATURETEST_FEATURENAME_PROP).value(System.getProperty(ORG_OPENDAYLIGHT_FEATURETEST_FEATURENAME_PROP)),
+             CoreOptions.systemProperty(ORG_OPENDAYLIGHT_FEATURETEST_FEATUREVERSION_PROP).value(System.getProperty(ORG_OPENDAYLIGHT_FEATURETEST_FEATUREVERSION_PROP)),
+       };
+    }
+
+    protected Option mvnLocalRepoOption() {
+        String mvnRepoLocal = System.getProperty(MAVEN_REPO_LOCAL, "");
+        LOG.info("mvnLocalRepo \"{}\"",mvnRepoLocal);
+        Option option =
+                editConfigurationFilePut(ETC_ORG_OPS4J_PAX_URL_MVN_CFG,ORG_OPS4J_PAX_URL_MVN_LOCAL_REPOSITORY,mvnRepoLocal);
+        return option;
+    }
+
+    protected Option getKarafDistroOption() {
+        String groupId = System.getProperty(KARAF_DISTRO_GROUPID_PROP,KARAF_DISTRO_GROUPID);
+        String artifactId = System.getProperty(KARAF_DISTRO_ARTIFACTID_PROP,KARAF_DISTRO_ARTIFACTID);
+        String version = System.getProperty(KARAF_DISTRO_VERSION_PROP,KARAF_DISTRO_VERSION);
+        String type = System.getProperty(KARAF_DISTRO_TYPE_PROP,KARAF_DISTRO_TYPE);
+        LOG.info("Using karaf distro {} {} {} {}",groupId,artifactId,version,type);
+        return karafDistributionConfiguration()
+                .frameworkUrl(
+                        maven()
+                                .groupId(groupId)
+                                .artifactId(artifactId)
+                                .type(type)
+                                .version(version))
+               .name("OpenDaylight")
+               .unpackDirectory(new File("target/pax"))
+               .useDeployFolder(false);
+    }
+
+    private URI getRepoURI() throws URISyntaxException {
+        return new URI(getProperty(ORG_OPENDAYLIGHT_FEATURETEST_URI_PROP));
+    }
+
+    private String getFeatureName() {
+        return getProperty(ORG_OPENDAYLIGHT_FEATURETEST_FEATURENAME_PROP);
+    }
+
+    public String getFeatureVersion() {
+        return getProperty(ORG_OPENDAYLIGHT_FEATURETEST_FEATUREVERSION_PROP);
+    }
+
+    private String getProperty(final String propName) {
+        String prop = System.getProperty(propName);
+        Assert.assertTrue("Missing property :" +propName, prop!=null);
+        return prop;
+    }
+
+    private void checkRepository(final URI repoURI) {
+        Repository repo = null;
+        for(Repository r: featuresService.listRepositories()) {
+            if(r.getURI().equals(repoURI)){
+                repo = r;
+                break;
+            }
+        }
+        Assert.assertNotNull("Repository not found: " + repoURI,repo);
+    }
+
+    @Before
+    public void installRepo() throws Exception {
+        LOG.info("Attempting to add repository {}", getRepoURI());
+        featuresService.addRepository(getRepoURI());
+        checkRepository(getRepoURI());
+        LOG.info("Successfully loaded repository {}", getRepoURI());
+    }
+
+    @Test
+    public void installFeature() throws Exception {
+      LOG.info("Attempting to install feature {} {}", getFeatureName(),getFeatureVersion());
+      featuresService.installFeature(getFeatureName(), getFeatureVersion());
+      Feature f = featuresService.getFeature(getFeatureName(), getFeatureVersion());
+      Assert.assertNotNull("Attempt to get feature "+ getFeatureName() + " " + getFeatureVersion() + "resulted in null" , f);
+      Assert.assertTrue("Failed to install Feature: " + getFeatureName() + " " + getFeatureVersion(),featuresService.isInstalled(f));
+      LOG.info("Successfull installed feature {} {}", getFeatureName(),getFeatureVersion());
+    }
+}
\ No newline at end of file
diff --git a/features-test/src/main/java/org/opendaylight/odlparent/featuretest/Util.java b/features-test/src/main/java/org/opendaylight/odlparent/featuretest/Util.java
new file mode 100644 (file)
index 0000000..1b91e8c
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  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.opendaylight.odlparent.featuretest;
+
+import java.lang.annotation.Annotation;
+import java.net.URL;
+import java.util.Collection;
+
+import org.junit.runner.Description;
+
+public final class Util {
+
+    private  Util() {
+        // Noop constructure
+    }
+
+    /*
+     * Convert a Description to a Description that includes information about repoURL, featureName, and featureVersion
+     *
+     * This is done so that when a test fails, we can get information about which repoURL, featureName, and featureVersion
+     * can come back with the Failure.
+     */
+
+    public static final Description convertDescription(URL repoURL, String featureName, String featureVersion,Description description) {
+        String delegateDisplayName = description.getDisplayName();
+        delegateDisplayName = delegateDisplayName + "[repoUrl: " + repoURL+ ", Feature: " + featureName + " " +featureVersion + "]";
+        Collection<Annotation> annotations = description.getAnnotations();
+        Annotation[] annotationArray = annotations.toArray(new Annotation[annotations.size()]);
+        Description newDescription = Description.createSuiteDescription(delegateDisplayName,annotationArray);
+        return newDescription;
+    }
+}
diff --git a/pom.xml b/pom.xml
index 51c917f73e2d8862b47d62ef2d5ed6096f8b014d..4bfecd0d4af665ed55405e579bb9992c66e8626f 100644 (file)
--- a/pom.xml
+++ b/pom.xml
@@ -42,6 +42,7 @@
 
     <modules>
         <module>bundle-parent</module>
+        <module>features-test</module>
         <module>odlparent</module>
     </modules>
 </project>