You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by bd...@apache.org on 2011/01/31 18:22:07 UTC

svn commit: r1065690 - in /sling/whiteboard/bdelacretaz/junit: ./ extension/ extension/src/ extension/src/main/ extension/src/main/java/ extension/src/main/java/org/ extension/src/main/java/org/apache/ extension/src/main/java/org/apache/sling/ extensio...

Author: bdelacretaz
Date: Mon Jan 31 17:22:06 2011
New Revision: 1065690

URL: http://svn.apache.org/viewvc?rev=1065690&view=rev
Log:
SLING-1963 - first rough prototype

Added:
    sling/whiteboard/bdelacretaz/junit/
    sling/whiteboard/bdelacretaz/junit/extension/   (with props)
    sling/whiteboard/bdelacretaz/junit/extension/pom.xml   (with props)
    sling/whiteboard/bdelacretaz/junit/extension/src/
    sling/whiteboard/bdelacretaz/junit/extension/src/main/
    sling/whiteboard/bdelacretaz/junit/extension/src/main/java/
    sling/whiteboard/bdelacretaz/junit/extension/src/main/java/org/
    sling/whiteboard/bdelacretaz/junit/extension/src/main/java/org/apache/
    sling/whiteboard/bdelacretaz/junit/extension/src/main/java/org/apache/sling/
    sling/whiteboard/bdelacretaz/junit/extension/src/main/java/org/apache/sling/extensions/
    sling/whiteboard/bdelacretaz/junit/extension/src/main/java/org/apache/sling/extensions/junit/
    sling/whiteboard/bdelacretaz/junit/extension/src/main/java/org/apache/sling/extensions/junit/Activator.java   (with props)
    sling/whiteboard/bdelacretaz/junit/extension/src/main/java/org/apache/sling/extensions/junit/JUnitTestsManager.java   (with props)
    sling/whiteboard/bdelacretaz/junit/extension/src/main/java/org/apache/sling/extensions/junit/SlingAnnotationsTestRunner.java   (with props)
    sling/whiteboard/bdelacretaz/junit/extension/src/main/java/org/apache/sling/extensions/junit/impl/
    sling/whiteboard/bdelacretaz/junit/extension/src/main/java/org/apache/sling/extensions/junit/impl/JUnitServlet.java   (with props)
    sling/whiteboard/bdelacretaz/junit/extension/src/main/java/org/apache/sling/extensions/junit/impl/JUnitTestsManagerImpl.java   (with props)
    sling/whiteboard/bdelacretaz/junit/extension/src/main/java/org/apache/sling/extensions/junit/impl/PlainTextRunListener.java   (with props)
    sling/whiteboard/bdelacretaz/junit/testbundle/   (with props)
    sling/whiteboard/bdelacretaz/junit/testbundle/pom.xml   (with props)
    sling/whiteboard/bdelacretaz/junit/testbundle/src/
    sling/whiteboard/bdelacretaz/junit/testbundle/src/main/
    sling/whiteboard/bdelacretaz/junit/testbundle/src/main/java/
    sling/whiteboard/bdelacretaz/junit/testbundle/src/main/java/org/
    sling/whiteboard/bdelacretaz/junit/testbundle/src/main/java/org/apache/
    sling/whiteboard/bdelacretaz/junit/testbundle/src/main/java/org/apache/sling/
    sling/whiteboard/bdelacretaz/junit/testbundle/src/main/java/org/apache/sling/extensions/
    sling/whiteboard/bdelacretaz/junit/testbundle/src/main/java/org/apache/sling/extensions/junit/
    sling/whiteboard/bdelacretaz/junit/testbundle/src/main/java/org/apache/sling/extensions/junit/testbundle/
    sling/whiteboard/bdelacretaz/junit/testbundle/src/main/java/org/apache/sling/extensions/junit/testbundle/tests/
    sling/whiteboard/bdelacretaz/junit/testbundle/src/main/java/org/apache/sling/extensions/junit/testbundle/tests/JUnit3Test.java   (with props)
    sling/whiteboard/bdelacretaz/junit/testbundle/src/main/java/org/apache/sling/extensions/junit/testbundle/tests/JUnit4Test.java   (with props)

Propchange: sling/whiteboard/bdelacretaz/junit/extension/
------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Mon Jan 31 17:22:06 2011
@@ -0,0 +1,13 @@
+target
+bin
+*.iml
+*.ipr
+*.iws
+.settings
+.project
+.classpath
+.externalToolBuilders
+maven-eclipse.xml
+
+
+

Added: sling/whiteboard/bdelacretaz/junit/extension/pom.xml
URL: http://svn.apache.org/viewvc/sling/whiteboard/bdelacretaz/junit/extension/pom.xml?rev=1065690&view=auto
==============================================================================
--- sling/whiteboard/bdelacretaz/junit/extension/pom.xml (added)
+++ sling/whiteboard/bdelacretaz/junit/extension/pom.xml Mon Jan 31 17:22:06 2011
@@ -0,0 +1,116 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you 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.
+-->
+<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/maven-v4_0_0.xsd">
+
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.apache.sling</groupId>
+        <artifactId>sling</artifactId>
+        <version>10</version>
+    </parent>
+
+    <artifactId>org.apache.sling.extensions.junit</artifactId>
+    <version>0.1.1-SNAPSHOT</version>
+    <packaging>bundle</packaging>
+
+    <name>Apache Sling JUnit extensions</name>
+    <description>Runs JUnit tests in a Sling instance</description>
+    
+    <properties>
+        <junit.version>4.8.2</junit.version>
+    </properties>
+
+<!-- TODO
+    <scm>
+        <connection>scm:svn:http://svn.apache.org/repos/asf/sling/trunk/installer/providers/jcr</connection>
+        <developerConnection> scm:svn:https://svn.apache.org/repos/asf/sling/trunk/installer/providers/jcr</developerConnection>
+        <url>http://svn.apache.org/viewvc/sling/trunk/installer/providers/jcr/</url>
+    </scm>
+-->
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-scr-plugin</artifactId>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <extensions>true</extensions>
+                <configuration>
+                    <instructions>
+                        <Bundle-Activator>org.apache.sling.extensions.junit.Activator</Bundle-Activator>
+                        <Export-Package>
+                            org.apache.sling.extensions.junit;version=${project.version},
+                            junit.framework;version=${junit.version},
+                            org.junit;version=${junit.version},
+                            org.junit.matchers.*;version=${junit.version},
+                            org.junit.rules.*;version=${junit.version},
+                            org.junit.runner.*;version=${junit.version},
+                            org.junit.runners.*;version=${junit.version}
+                        </Export-Package>
+                        <Private-Package>org.apache.sling.extensions.junit.impl.*</Private-Package>
+                        <Embed-Dependency>*;artifactId=junit</Embed-Dependency>
+                    </instructions>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.compendium</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.felix</groupId>
+            <artifactId>org.apache.felix.scr.annotations</artifactId>
+            <version>1.4.0</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.api</artifactId>
+            <version>2.1.0</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>javax.servlet</groupId>
+            <artifactId>servlet-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+            <version>1.5.11</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <version>4.8.2</version>
+            <scope>compile</scope>
+        </dependency>
+    </dependencies>
+</project>
\ No newline at end of file

Propchange: sling/whiteboard/bdelacretaz/junit/extension/pom.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Added: sling/whiteboard/bdelacretaz/junit/extension/src/main/java/org/apache/sling/extensions/junit/Activator.java
URL: http://svn.apache.org/viewvc/sling/whiteboard/bdelacretaz/junit/extension/src/main/java/org/apache/sling/extensions/junit/Activator.java?rev=1065690&view=auto
==============================================================================
--- sling/whiteboard/bdelacretaz/junit/extension/src/main/java/org/apache/sling/extensions/junit/Activator.java (added)
+++ sling/whiteboard/bdelacretaz/junit/extension/src/main/java/org/apache/sling/extensions/junit/Activator.java Mon Jan 31 17:22:06 2011
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.sling.extensions.junit;
+
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+
+public class Activator implements BundleActivator {
+
+    public void start(BundleContext context) throws Exception {
+        SlingAnnotationsTestRunner.bundleContext = context;
+    }
+
+    public void stop(BundleContext context) throws Exception {
+        SlingAnnotationsTestRunner.bundleContext = null;
+    }
+}

Propchange: sling/whiteboard/bdelacretaz/junit/extension/src/main/java/org/apache/sling/extensions/junit/Activator.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/whiteboard/bdelacretaz/junit/extension/src/main/java/org/apache/sling/extensions/junit/Activator.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev URL

Added: sling/whiteboard/bdelacretaz/junit/extension/src/main/java/org/apache/sling/extensions/junit/JUnitTestsManager.java
URL: http://svn.apache.org/viewvc/sling/whiteboard/bdelacretaz/junit/extension/src/main/java/org/apache/sling/extensions/junit/JUnitTestsManager.java?rev=1065690&view=auto
==============================================================================
--- sling/whiteboard/bdelacretaz/junit/extension/src/main/java/org/apache/sling/extensions/junit/JUnitTestsManager.java (added)
+++ sling/whiteboard/bdelacretaz/junit/extension/src/main/java/org/apache/sling/extensions/junit/JUnitTestsManager.java Mon Jan 31 17:22:06 2011
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.sling.extensions.junit;
+
+import java.util.List;
+
+/** Service that gives access to JUnit test classes */
+public interface JUnitTestsManager {
+    /** Return the names of all currently registered test classes */
+    public List<String> getTestClasses();
+    
+    /** Instantiate specified test class from the appropriate bundle */
+    public Class<?> getTestClass(String className) throws ClassNotFoundException;
+}

Propchange: sling/whiteboard/bdelacretaz/junit/extension/src/main/java/org/apache/sling/extensions/junit/JUnitTestsManager.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/whiteboard/bdelacretaz/junit/extension/src/main/java/org/apache/sling/extensions/junit/JUnitTestsManager.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev URL

Added: sling/whiteboard/bdelacretaz/junit/extension/src/main/java/org/apache/sling/extensions/junit/SlingAnnotationsTestRunner.java
URL: http://svn.apache.org/viewvc/sling/whiteboard/bdelacretaz/junit/extension/src/main/java/org/apache/sling/extensions/junit/SlingAnnotationsTestRunner.java?rev=1065690&view=auto
==============================================================================
--- sling/whiteboard/bdelacretaz/junit/extension/src/main/java/org/apache/sling/extensions/junit/SlingAnnotationsTestRunner.java (added)
+++ sling/whiteboard/bdelacretaz/junit/extension/src/main/java/org/apache/sling/extensions/junit/SlingAnnotationsTestRunner.java Mon Jan 31 17:22:06 2011
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.sling.extensions.junit;
+
+import org.junit.runners.BlockJUnit4ClassRunner;
+import org.junit.runners.model.InitializationError;
+import org.osgi.framework.BundleContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class SlingAnnotationsTestRunner extends BlockJUnit4ClassRunner {
+    private final Logger log = LoggerFactory.getLogger(getClass());
+    
+    // TODO better way to inject this?
+    static BundleContext bundleContext;
+    
+    public SlingAnnotationsTestRunner(Class<?> clazz) throws InitializationError {
+        super(clazz);
+    }
+    
+    @Override
+    protected Object createTest() throws Exception {
+        final Object result = super.createTest();
+        log.info("TODO handle annotations for {}, BundleContext={}", 
+                result.getClass().getName(), bundleContext);
+        return super.createTest();
+    }
+}

Propchange: sling/whiteboard/bdelacretaz/junit/extension/src/main/java/org/apache/sling/extensions/junit/SlingAnnotationsTestRunner.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/whiteboard/bdelacretaz/junit/extension/src/main/java/org/apache/sling/extensions/junit/SlingAnnotationsTestRunner.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev URL

Added: sling/whiteboard/bdelacretaz/junit/extension/src/main/java/org/apache/sling/extensions/junit/impl/JUnitServlet.java
URL: http://svn.apache.org/viewvc/sling/whiteboard/bdelacretaz/junit/extension/src/main/java/org/apache/sling/extensions/junit/impl/JUnitServlet.java?rev=1065690&view=auto
==============================================================================
--- sling/whiteboard/bdelacretaz/junit/extension/src/main/java/org/apache/sling/extensions/junit/impl/JUnitServlet.java (added)
+++ sling/whiteboard/bdelacretaz/junit/extension/src/main/java/org/apache/sling/extensions/junit/impl/JUnitServlet.java Mon Jan 31 17:22:06 2011
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.sling.extensions.junit.impl;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.List;
+
+import javax.servlet.ServletException;
+
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Property;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.Service;
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.SlingHttpServletResponse;
+import org.apache.sling.api.servlets.SlingAllMethodsServlet;
+import org.apache.sling.extensions.junit.JUnitTestsManager;
+import org.junit.runner.JUnitCore;
+
+/** Simple test runner servlet */
+@SuppressWarnings("serial")
+@Component
+@Service
+@Property(name="sling.servlet.paths",value="/system/sling/junit")
+public class JUnitServlet extends SlingAllMethodsServlet {
+    
+    @Reference
+    private JUnitTestsManager testsManager;
+    
+    @Override
+    protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response) 
+    throws ServletException, IOException {
+        
+        response.setContentType("text/plain");
+        response.setCharacterEncoding("UTF-8");
+        final PrintWriter pw = response.getWriter();
+        pw.println("This is " + getClass().getName());
+        pw.println();
+        
+        // Any test classes?
+        final List<String> testClasses = testsManager.getTestClasses();
+        if(testClasses.isEmpty()) {
+            pw.println(
+                    "No test classes found, please activate at least one bundle"
+                    + " which exports JUnit test classes and points to them using a"
+                    + " Test-Package header."
+                    );
+            return;
+        }
+        
+        // List test classes
+        pw.println("TEST CLASSES (found in bundles with Test-Package headers):");
+        for(String className : testClasses) {
+            pw.println(className);
+        }
+        pw.println();
+
+        // Run tests
+        final JUnitCore junit = new JUnitCore();
+        junit.addListener(new PlainTextRunListener(pw));
+        try {
+            for(String className : testClasses) {
+                pw.println("**** RUNNING TESTS: " + className);
+                junit.run(testsManager.getTestClass(className));
+                pw.println();
+            }
+        } catch(ClassNotFoundException cnfe) {
+            throw new ServletException("Test class not found", cnfe);
+        }
+    }
+}

Propchange: sling/whiteboard/bdelacretaz/junit/extension/src/main/java/org/apache/sling/extensions/junit/impl/JUnitServlet.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/whiteboard/bdelacretaz/junit/extension/src/main/java/org/apache/sling/extensions/junit/impl/JUnitServlet.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev URL

Added: sling/whiteboard/bdelacretaz/junit/extension/src/main/java/org/apache/sling/extensions/junit/impl/JUnitTestsManagerImpl.java
URL: http://svn.apache.org/viewvc/sling/whiteboard/bdelacretaz/junit/extension/src/main/java/org/apache/sling/extensions/junit/impl/JUnitTestsManagerImpl.java?rev=1065690&view=auto
==============================================================================
--- sling/whiteboard/bdelacretaz/junit/extension/src/main/java/org/apache/sling/extensions/junit/impl/JUnitTestsManagerImpl.java (added)
+++ sling/whiteboard/bdelacretaz/junit/extension/src/main/java/org/apache/sling/extensions/junit/impl/JUnitTestsManagerImpl.java Mon Jan 31 17:22:06 2011
@@ -0,0 +1,196 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.sling.extensions.junit.impl;
+
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Service;
+import org.apache.sling.extensions.junit.JUnitTestsManager;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleEvent;
+import org.osgi.framework.BundleListener;
+import org.osgi.service.component.ComponentContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Component
+@Service
+public class JUnitTestsManagerImpl implements BundleListener,JUnitTestsManager {
+    private final Logger log = LoggerFactory.getLogger(getClass());
+    public static final String TEST_PACKAGE_HEADER = "Test-Package";
+    private BundleContext bundleContext;
+    
+    /** Symbolic names of bundles that changed state - if not empty, need
+     *  to adjust the list of tests
+     */
+    private final List<String> changedBundles = new ArrayList<String>();
+    
+    /** List of (candidate) test classes, keyed by bundle so that we can
+     *  update them easily when bundles come and go 
+     */
+    private final Map<String, List<String>> testClassesMap = new HashMap<String, List<String>>();
+
+    private String getTestPackageName(Bundle b) {
+        return (String)b.getHeaders().get(TEST_PACKAGE_HEADER);
+    }
+    
+    protected void activate(ComponentContext ctx) {
+        bundleContext = ctx.getBundleContext();
+        bundleContext.addBundleListener(this);
+        
+        // Initially consider all bundles as "changed"
+        for(Bundle b : bundleContext.getBundles()) {
+            if(getTestPackageName(b) != null) {
+                changedBundles.add(b.getSymbolicName());
+                log.debug("Will look for test classes inside bundle {}", b.getSymbolicName());
+            }
+        }
+    }
+    
+    protected void deactivate(ComponentContext ctx) {
+        bundleContext.removeBundleListener(this);
+        bundleContext = null;
+        changedBundles.clear();
+    }
+    
+    /** Called when a bundle changes state */
+    public void bundleChanged(BundleEvent event) {
+        // Only consider bundles which contain tests
+        final Bundle b = event.getBundle();
+        if(getTestPackageName(b) == null) {
+            log.debug("Bundle {} does not have {} header, ignored", 
+                    b.getSymbolicName(), TEST_PACKAGE_HEADER);
+            return;
+        }
+        synchronized (changedBundles) {
+            log.debug("Got BundleEvent for Bundle {}, will rebuild its lists of tests");
+            changedBundles.add(b.getSymbolicName());
+        }
+    }
+    
+    /** Update testClasses if bundle changes require it */
+    private void maybeUpdateTestClasses() {
+        if(changedBundles.isEmpty()) {
+            return;
+        }
+
+        // Get the list of bundles that have changed
+        final List<String> bundlesToUpdate = new ArrayList<String>();
+        synchronized (changedBundles) {
+            bundlesToUpdate.addAll(changedBundles);
+            changedBundles.clear();
+        }
+        
+        // Remove test classes that belong to changed bundles
+        for(String symbolicName : bundlesToUpdate) {
+            testClassesMap.remove(symbolicName);
+        }
+        
+        // Get test classes from bundles that are in our list
+        for(Bundle b : bundleContext.getBundles()) {
+            if(bundlesToUpdate.contains(b.getSymbolicName())) {
+                final List<String> testClasses = getTestClasses(b);
+                if(testClasses != null) {
+                    testClassesMap.put(b.getSymbolicName(), testClasses);
+                    log.debug("{} test classes found in bundle {}, added to our list", 
+                            testClasses.size(), b.getSymbolicName());
+                } else {
+                    log.debug("No test classes found in bundle {}", b.getSymbolicName());
+                }
+            }
+        }
+    }
+
+    /** @inheritDoc */
+    public List<String> getTestClasses() {
+        maybeUpdateTestClasses();
+        final List<String> result = new ArrayList<String>();
+        for(List<String> list : testClassesMap.values()) {
+            result.addAll(list);
+        }
+        return result;
+    }
+
+    /** Get test classes that bundle b provides (as done in Felix/Sigil) */
+    private List<String> getTestClasses(Bundle b) {
+        final List<String> result = new ArrayList<String>();
+        final String testPackage = getTestPackageName(b);
+        
+        if(testPackage == null) {
+            log.info("Bundle {} does not have {} header, not looking for test classes", TEST_PACKAGE_HEADER);
+        } else if(Bundle.ACTIVE != b.getState()) {
+            log.info("Bundle {} is not active, no test classes considered", b.getSymbolicName());
+        } else {
+            @SuppressWarnings("unchecked")
+            Enumeration<URL> classUrls = b.findEntries("", "*.class", true);
+            while (classUrls.hasMoreElements()) {
+                URL url = classUrls.nextElement();
+                final String name = toClassName(url);
+                if(name.startsWith(testPackage)) {
+                    result.add(name);
+                } else {
+                    log.debug("Class {} is not in test package {} of bundle {}, ignored",
+                            new Object[] { name, testPackage, b.getSymbolicName() });
+                }
+            }
+            log.info("{} test classes found in bundle {}", result.size(), b.getSymbolicName());
+        }
+        
+        return result;
+    }
+    
+    /** Convert class URL to class name */
+    private String toClassName(URL url) {
+        final String f = url.getFile();
+        final String cn = f.substring(1, f.length() - ".class".length());
+        return cn.replace('/', '.');
+    }
+
+    /** Find bundle by symbolic name */
+    private Bundle findBundle(String symbolicName) {
+        for(Bundle b : bundleContext.getBundles()) {
+            if(b.getSymbolicName().equals(symbolicName)) {
+                return b;
+            }
+        }
+        return null;
+    }
+    
+    /** @inheritDoc */
+    public Class<?> getTestClass(String className) throws ClassNotFoundException {
+        // Find the bundle to which the class belongs
+        Bundle b = null;
+        for(Map.Entry<String, List<String>> e : testClassesMap.entrySet()) {
+            if(e.getValue().contains(className)) {
+                b = findBundle(e.getKey());
+                break;
+            }
+        }
+        
+        if(b == null) {
+            throw new IllegalArgumentException("No Bundle found that supplies test class " + className);
+        }
+        return b.loadClass(className);
+    }
+}
\ No newline at end of file

Propchange: sling/whiteboard/bdelacretaz/junit/extension/src/main/java/org/apache/sling/extensions/junit/impl/JUnitTestsManagerImpl.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/whiteboard/bdelacretaz/junit/extension/src/main/java/org/apache/sling/extensions/junit/impl/JUnitTestsManagerImpl.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev URL

Added: sling/whiteboard/bdelacretaz/junit/extension/src/main/java/org/apache/sling/extensions/junit/impl/PlainTextRunListener.java
URL: http://svn.apache.org/viewvc/sling/whiteboard/bdelacretaz/junit/extension/src/main/java/org/apache/sling/extensions/junit/impl/PlainTextRunListener.java?rev=1065690&view=auto
==============================================================================
--- sling/whiteboard/bdelacretaz/junit/extension/src/main/java/org/apache/sling/extensions/junit/impl/PlainTextRunListener.java (added)
+++ sling/whiteboard/bdelacretaz/junit/extension/src/main/java/org/apache/sling/extensions/junit/impl/PlainTextRunListener.java Mon Jan 31 17:22:06 2011
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.sling.extensions.junit.impl;
+
+import java.io.PrintWriter;
+
+import org.junit.runner.Description;
+import org.junit.runner.Result;
+import org.junit.runner.notification.Failure;
+import org.junit.runner.notification.RunListener;
+
+class PlainTextRunListener extends RunListener {
+    final PrintWriter pw;
+    
+    PlainTextRunListener(PrintWriter w) {
+        pw = w;
+    }
+    
+    @Override
+    public void testFailure(Failure failure) throws Exception {
+        super.testFailure(failure);
+        pw.println("FAILURE " + failure);
+    }
+
+    @Override
+    public void testFinished(Description description) throws Exception {
+        super.testFinished(description);
+        pw.println("FINISHED " + description);
+    }
+
+    @Override
+    public void testIgnored(Description description) throws Exception {
+        super.testIgnored(description);
+        pw.println("IGNORED " + description);
+    }
+
+    @Override
+    public void testRunFinished(Result result) throws Exception {
+        super.testRunFinished(result);
+        pw.println("TEST RUN FINISHED: "
+                + "tests:" + result.getRunCount()
+                + ", failures:" + result.getFailureCount()
+                + ", ignored:" + result.getIgnoreCount()
+        );
+    }
+
+    @Override
+    public void testRunStarted(Description description)
+            throws Exception {
+        super.testRunStarted(description);
+    }
+
+    @Override
+    public void testStarted(Description description) throws Exception {
+        super.testStarted(description);
+    }
+}
\ No newline at end of file

Propchange: sling/whiteboard/bdelacretaz/junit/extension/src/main/java/org/apache/sling/extensions/junit/impl/PlainTextRunListener.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/whiteboard/bdelacretaz/junit/extension/src/main/java/org/apache/sling/extensions/junit/impl/PlainTextRunListener.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev URL

Propchange: sling/whiteboard/bdelacretaz/junit/testbundle/
------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Mon Jan 31 17:22:06 2011
@@ -0,0 +1,13 @@
+target
+bin
+*.iml
+*.ipr
+*.iws
+.settings
+.project
+.classpath
+.externalToolBuilders
+maven-eclipse.xml
+
+
+

Added: sling/whiteboard/bdelacretaz/junit/testbundle/pom.xml
URL: http://svn.apache.org/viewvc/sling/whiteboard/bdelacretaz/junit/testbundle/pom.xml?rev=1065690&view=auto
==============================================================================
--- sling/whiteboard/bdelacretaz/junit/testbundle/pom.xml (added)
+++ sling/whiteboard/bdelacretaz/junit/testbundle/pom.xml Mon Jan 31 17:22:06 2011
@@ -0,0 +1,98 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you 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.
+-->
+<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/maven-v4_0_0.xsd">
+
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.apache.sling</groupId>
+        <artifactId>sling</artifactId>
+        <version>10</version>
+    </parent>
+
+    <artifactId>org.apache.sling.extensions.junit.testbundle</artifactId>
+    <version>0.1.1-SNAPSHOT</version>
+    <packaging>bundle</packaging>
+
+    <name>Apache Sling JUnit extensions test bundle</name>
+    <description>Contains test classes to test the Sling JUnit extensions</description>
+    
+    <properties>
+        <junit.version>4.8.2</junit.version>
+    </properties>
+
+<!-- TODO
+    <scm>
+        <connection>scm:svn:http://svn.apache.org/repos/asf/sling/trunk/installer/providers/jcr</connection>
+        <developerConnection> scm:svn:https://svn.apache.org/repos/asf/sling/trunk/installer/providers/jcr</developerConnection>
+        <url>http://svn.apache.org/viewvc/sling/trunk/installer/providers/jcr/</url>
+    </scm>
+-->
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-scr-plugin</artifactId>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <extensions>true</extensions>
+                <configuration>
+                    <instructions>
+                        <Export-Package>org.apache.sling.extensions.junit.testbundle.*</Export-Package>
+                        <Test-Package>org.apache.sling.extensions.junit.testbundle.tests</Test-Package>
+                    </instructions>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.compendium</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+            <version>1.5.11</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <version>4.8.2</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <!-- TODO create separate API package, this is just to get the special Sling test runner -->
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.extensions.junit</artifactId>
+            <version>0.1.1-SNAPSHOT</version>
+            <scope>provided</scope>
+        </dependency>
+        
+    </dependencies>
+</project>

Propchange: sling/whiteboard/bdelacretaz/junit/testbundle/pom.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Added: sling/whiteboard/bdelacretaz/junit/testbundle/src/main/java/org/apache/sling/extensions/junit/testbundle/tests/JUnit3Test.java
URL: http://svn.apache.org/viewvc/sling/whiteboard/bdelacretaz/junit/testbundle/src/main/java/org/apache/sling/extensions/junit/testbundle/tests/JUnit3Test.java?rev=1065690&view=auto
==============================================================================
--- sling/whiteboard/bdelacretaz/junit/testbundle/src/main/java/org/apache/sling/extensions/junit/testbundle/tests/JUnit3Test.java (added)
+++ sling/whiteboard/bdelacretaz/junit/testbundle/src/main/java/org/apache/sling/extensions/junit/testbundle/tests/JUnit3Test.java Mon Jan 31 17:22:06 2011
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.sling.extensions.junit.testbundle.tests;
+
+import junit.framework.TestCase;
+
+/** Example test using the JUnit3 APIs */
+public class JUnit3Test extends TestCase {
+    public void testPasses() {
+    }
+    
+    public void testFailsEveryTime() {
+        fail("This JUnit3 test fails every time");
+    }
+    
+    public void testFailsSometimes() {
+        if(Math.random() > 0.5) {
+            fail("This JUnit3 test fails 50% of the time");
+        }
+    }
+}

Propchange: sling/whiteboard/bdelacretaz/junit/testbundle/src/main/java/org/apache/sling/extensions/junit/testbundle/tests/JUnit3Test.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/whiteboard/bdelacretaz/junit/testbundle/src/main/java/org/apache/sling/extensions/junit/testbundle/tests/JUnit3Test.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev URL

Added: sling/whiteboard/bdelacretaz/junit/testbundle/src/main/java/org/apache/sling/extensions/junit/testbundle/tests/JUnit4Test.java
URL: http://svn.apache.org/viewvc/sling/whiteboard/bdelacretaz/junit/testbundle/src/main/java/org/apache/sling/extensions/junit/testbundle/tests/JUnit4Test.java?rev=1065690&view=auto
==============================================================================
--- sling/whiteboard/bdelacretaz/junit/testbundle/src/main/java/org/apache/sling/extensions/junit/testbundle/tests/JUnit4Test.java (added)
+++ sling/whiteboard/bdelacretaz/junit/testbundle/src/main/java/org/apache/sling/extensions/junit/testbundle/tests/JUnit4Test.java Mon Jan 31 17:22:06 2011
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.sling.extensions.junit.testbundle.tests;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.apache.sling.extensions.junit.SlingAnnotationsTestRunner;
+
+/** Example test using the JUnit4 annotations */
+@RunWith(SlingAnnotationsTestRunner.class)
+public class JUnit4Test {
+    private String title;
+    
+    @Before
+    public void setTitle() {
+        title = "FOO";
+    }
+    
+    @After
+    public void resetTitle() {
+        title = null;
+    }
+    
+    @Test
+    public void testPasses() {
+    }
+    
+    @Test
+    public void testRequiresBefore() {
+        assertNotNull(title);
+    }
+    
+    @Test
+    public void testFailsEveryTime() {
+        fail("This JUnit4 test fails every time");
+    }
+    
+    @Test
+    public void testFailsSometimes() {
+        if(Math.random() > 0.5) {
+            fail("This JUnit4 test fails 50% of the time");
+        }
+    }
+}
\ No newline at end of file

Propchange: sling/whiteboard/bdelacretaz/junit/testbundle/src/main/java/org/apache/sling/extensions/junit/testbundle/tests/JUnit4Test.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/whiteboard/bdelacretaz/junit/testbundle/src/main/java/org/apache/sling/extensions/junit/testbundle/tests/JUnit4Test.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev URL