incubator-sling-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From bdelacre...@apache.org
Subject svn commit: r1066470 - in /sling/whiteboard/bdelacretaz/junit: core/ core/src/main/java/org/apache/sling/junit/ core/src/main/java/org/apache/sling/junit/annotations/ core/src/main/java/org/apache/sling/junit/impl/ testbundle/src/main/java/org/apache/s...
Date Wed, 02 Feb 2011 14:06:15 GMT
Author: bdelacretaz
Date: Wed Feb  2 14:06:15 2011
New Revision: 1066470

URL: http://svn.apache.org/viewvc?rev=1066470&view=rev
Log:
SLING-1963 - modularize TestsProvider, in preparation for scriptable tests

Added:
    sling/whiteboard/bdelacretaz/junit/core/src/main/java/org/apache/sling/junit/TestsProvider.java
  (with props)
    sling/whiteboard/bdelacretaz/junit/core/src/main/java/org/apache/sling/junit/annotations/
    sling/whiteboard/bdelacretaz/junit/core/src/main/java/org/apache/sling/junit/annotations/AutoDetect.java
      - copied, changed from r1066422, sling/whiteboard/bdelacretaz/junit/core/src/main/java/org/apache/sling/junit/AutoDetect.java
    sling/whiteboard/bdelacretaz/junit/core/src/main/java/org/apache/sling/junit/annotations/SlingAnnotationsTestRunner.java
      - copied, changed from r1066422, sling/whiteboard/bdelacretaz/junit/core/src/main/java/org/apache/sling/junit/SlingAnnotationsTestRunner.java
    sling/whiteboard/bdelacretaz/junit/core/src/main/java/org/apache/sling/junit/annotations/TestReference.java
      - copied, changed from r1066422, sling/whiteboard/bdelacretaz/junit/core/src/main/java/org/apache/sling/junit/TestReference.java
    sling/whiteboard/bdelacretaz/junit/core/src/main/java/org/apache/sling/junit/impl/BundleTestsProvider.java
  (with props)
Removed:
    sling/whiteboard/bdelacretaz/junit/core/src/main/java/org/apache/sling/junit/AutoDetect.java
    sling/whiteboard/bdelacretaz/junit/core/src/main/java/org/apache/sling/junit/JUnitConstants.java
    sling/whiteboard/bdelacretaz/junit/core/src/main/java/org/apache/sling/junit/SlingAnnotationsTestRunner.java
    sling/whiteboard/bdelacretaz/junit/core/src/main/java/org/apache/sling/junit/TestReference.java
Modified:
    sling/whiteboard/bdelacretaz/junit/core/pom.xml
    sling/whiteboard/bdelacretaz/junit/core/src/main/java/org/apache/sling/junit/Activator.java
    sling/whiteboard/bdelacretaz/junit/core/src/main/java/org/apache/sling/junit/JUnitTestsManager.java
    sling/whiteboard/bdelacretaz/junit/core/src/main/java/org/apache/sling/junit/impl/AnnotationsProcessor.java
    sling/whiteboard/bdelacretaz/junit/core/src/main/java/org/apache/sling/junit/impl/JUnitServlet.java
    sling/whiteboard/bdelacretaz/junit/core/src/main/java/org/apache/sling/junit/impl/JUnitTestsManagerImpl.java
    sling/whiteboard/bdelacretaz/junit/testbundle/src/main/java/org/apache/sling/junit/testbundle/tests/OsgiAwareTest.java

Modified: sling/whiteboard/bdelacretaz/junit/core/pom.xml
URL: http://svn.apache.org/viewvc/sling/whiteboard/bdelacretaz/junit/core/pom.xml?rev=1066470&r1=1066469&r2=1066470&view=diff
==============================================================================
--- sling/whiteboard/bdelacretaz/junit/core/pom.xml (original)
+++ sling/whiteboard/bdelacretaz/junit/core/pom.xml Wed Feb  2 14:06:15 2011
@@ -60,6 +60,7 @@
                         <Bundle-Activator>org.apache.sling.junit.Activator</Bundle-Activator>
                         <Export-Package>
                             org.apache.sling.junit;version=${project.version},
+                            org.apache.sling.junit.annotations;version=${project.version},
                             junit.framework;version=${junit.version},
                             org.junit;version=${junit.version},
                             org.junit.matchers.*;version=${junit.version},

Modified: sling/whiteboard/bdelacretaz/junit/core/src/main/java/org/apache/sling/junit/Activator.java
URL: http://svn.apache.org/viewvc/sling/whiteboard/bdelacretaz/junit/core/src/main/java/org/apache/sling/junit/Activator.java?rev=1066470&r1=1066469&r2=1066470&view=diff
==============================================================================
--- sling/whiteboard/bdelacretaz/junit/core/src/main/java/org/apache/sling/junit/Activator.java
(original)
+++ sling/whiteboard/bdelacretaz/junit/core/src/main/java/org/apache/sling/junit/Activator.java
Wed Feb  2 14:06:15 2011
@@ -19,13 +19,23 @@ package org.apache.sling.junit;
 import org.osgi.framework.BundleActivator;
 import org.osgi.framework.BundleContext;
 
+/** Used to make our BundleContext available to
+ *  JUnit classes that need it but have no
+ *  OSGi context.
+ */
 public class Activator implements BundleActivator {
 
+    private static BundleContext bundleContext;
+    
+    public static BundleContext getBundleContext() {
+        return bundleContext;
+    }
+    
     public void start(BundleContext context) throws Exception {
-        SlingAnnotationsTestRunner.setBundleContext(context);
+        bundleContext = context;
     }
 
     public void stop(BundleContext context) throws Exception {
-        SlingAnnotationsTestRunner.setBundleContext(null);
+        bundleContext = null;
     }
 }

Modified: sling/whiteboard/bdelacretaz/junit/core/src/main/java/org/apache/sling/junit/JUnitTestsManager.java
URL: http://svn.apache.org/viewvc/sling/whiteboard/bdelacretaz/junit/core/src/main/java/org/apache/sling/junit/JUnitTestsManager.java?rev=1066470&r1=1066469&r2=1066470&view=diff
==============================================================================
--- sling/whiteboard/bdelacretaz/junit/core/src/main/java/org/apache/sling/junit/JUnitTestsManager.java
(original)
+++ sling/whiteboard/bdelacretaz/junit/core/src/main/java/org/apache/sling/junit/JUnitTestsManager.java
Wed Feb  2 14:06:15 2011
@@ -16,13 +16,13 @@
  */
 package org.apache.sling.junit;
 
-import java.util.List;
+import java.util.Collection;
 
 /** Service that gives access to JUnit test classes */
 public interface JUnitTestsManager {
-    /** Return the names of all currently registered test classes */
-    public List<String> getTestClasses();
+    /** Return the names of all currently available tests */
+    public Collection<String> getTestNames();
     
-    /** Instantiate specified test class from the appropriate bundle */
-    public Class<?> getTestClass(String className) throws ClassNotFoundException;
+    /** Instantiate test class for specified test */
+    public Class<?> getTestClass(String testName) throws ClassNotFoundException;
 }

Added: sling/whiteboard/bdelacretaz/junit/core/src/main/java/org/apache/sling/junit/TestsProvider.java
URL: http://svn.apache.org/viewvc/sling/whiteboard/bdelacretaz/junit/core/src/main/java/org/apache/sling/junit/TestsProvider.java?rev=1066470&view=auto
==============================================================================
--- sling/whiteboard/bdelacretaz/junit/core/src/main/java/org/apache/sling/junit/TestsProvider.java
(added)
+++ sling/whiteboard/bdelacretaz/junit/core/src/main/java/org/apache/sling/junit/TestsProvider.java
Wed Feb  2 14:06:15 2011
@@ -0,0 +1,38 @@
+/*
+ * 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.junit;
+
+import java.util.List;
+
+/** Provides tests, for example by scanning bundles, 
+ *  finding test resources in a content repository, etc.
+ */
+public interface TestsProvider {
+    /** Return this service's PID, client might use it later
+     *  to instantiate a specific test. 
+     */
+    String getServicePid();
+    
+    /** Return the list of available tests */
+    List<String> getTestNames();
+    
+    /** Create a test class to execute the specified test */
+    Class<?> createTestClass(String testName) throws ClassNotFoundException;
+    
+    /** Return the timestamp at which our list of tests was last modified */
+    long lastModified();
+}

Propchange: sling/whiteboard/bdelacretaz/junit/core/src/main/java/org/apache/sling/junit/TestsProvider.java
------------------------------------------------------------------------------
    svn:eol-style = native

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

Copied: sling/whiteboard/bdelacretaz/junit/core/src/main/java/org/apache/sling/junit/annotations/AutoDetect.java
(from r1066422, sling/whiteboard/bdelacretaz/junit/core/src/main/java/org/apache/sling/junit/AutoDetect.java)
URL: http://svn.apache.org/viewvc/sling/whiteboard/bdelacretaz/junit/core/src/main/java/org/apache/sling/junit/annotations/AutoDetect.java?p2=sling/whiteboard/bdelacretaz/junit/core/src/main/java/org/apache/sling/junit/annotations/AutoDetect.java&p1=sling/whiteboard/bdelacretaz/junit/core/src/main/java/org/apache/sling/junit/AutoDetect.java&r1=1066422&r2=1066470&rev=1066470&view=diff
==============================================================================
--- sling/whiteboard/bdelacretaz/junit/core/src/main/java/org/apache/sling/junit/AutoDetect.java
(original)
+++ sling/whiteboard/bdelacretaz/junit/core/src/main/java/org/apache/sling/junit/annotations/AutoDetect.java
Wed Feb  2 14:06:15 2011
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.sling.junit;
+package org.apache.sling.junit.annotations;
 
 /**
  * Placeholder class for default value of annotation 

Copied: sling/whiteboard/bdelacretaz/junit/core/src/main/java/org/apache/sling/junit/annotations/SlingAnnotationsTestRunner.java
(from r1066422, sling/whiteboard/bdelacretaz/junit/core/src/main/java/org/apache/sling/junit/SlingAnnotationsTestRunner.java)
URL: http://svn.apache.org/viewvc/sling/whiteboard/bdelacretaz/junit/core/src/main/java/org/apache/sling/junit/annotations/SlingAnnotationsTestRunner.java?p2=sling/whiteboard/bdelacretaz/junit/core/src/main/java/org/apache/sling/junit/annotations/SlingAnnotationsTestRunner.java&p1=sling/whiteboard/bdelacretaz/junit/core/src/main/java/org/apache/sling/junit/SlingAnnotationsTestRunner.java&r1=1066422&r2=1066470&rev=1066470&view=diff
==============================================================================
--- sling/whiteboard/bdelacretaz/junit/core/src/main/java/org/apache/sling/junit/SlingAnnotationsTestRunner.java
(original)
+++ sling/whiteboard/bdelacretaz/junit/core/src/main/java/org/apache/sling/junit/annotations/SlingAnnotationsTestRunner.java
Wed Feb  2 14:06:15 2011
@@ -14,8 +14,10 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.sling.junit;
+package org.apache.sling.junit.annotations;
 
+import org.apache.sling.junit.Activator;
+import org.apache.sling.junit.TestObjectProcessor;
 import org.junit.runners.BlockJUnit4ClassRunner;
 import org.junit.runners.model.InitializationError;
 import org.osgi.framework.BundleContext;
@@ -31,24 +33,19 @@ import org.slf4j.LoggerFactory;
 public class SlingAnnotationsTestRunner extends BlockJUnit4ClassRunner {
     private static final Logger log = LoggerFactory.getLogger(SlingAnnotationsTestRunner.class);
 
-    private static BundleContext bundleContext;
     private static TestObjectProcessor testObjectProcessor;  
     
     public SlingAnnotationsTestRunner(Class<?> clazz) throws InitializationError {
         super(clazz);
     }
     
-    static void setBundleContext(BundleContext ctx) {
-        bundleContext = ctx;
-        testObjectProcessor = null;
-    }
-    
     @Override
     protected Object createTest() throws Exception {
-        if(testObjectProcessor == null && bundleContext != null) {
-            final ServiceReference ref = bundleContext.getServiceReference(TestObjectProcessor.class.getName());
+        final BundleContext ctx = Activator.getBundleContext();
+        if(testObjectProcessor == null && ctx != null) {
+            final ServiceReference ref = ctx.getServiceReference(TestObjectProcessor.class.getName());
             if(ref != null) {
-                testObjectProcessor = (TestObjectProcessor)bundleContext.getService(ref);
+                testObjectProcessor = (TestObjectProcessor)ctx.getService(ref);
             }
             log.info("Got TestObjectProcessor {}", testObjectProcessor);
         }

Copied: sling/whiteboard/bdelacretaz/junit/core/src/main/java/org/apache/sling/junit/annotations/TestReference.java
(from r1066422, sling/whiteboard/bdelacretaz/junit/core/src/main/java/org/apache/sling/junit/TestReference.java)
URL: http://svn.apache.org/viewvc/sling/whiteboard/bdelacretaz/junit/core/src/main/java/org/apache/sling/junit/annotations/TestReference.java?p2=sling/whiteboard/bdelacretaz/junit/core/src/main/java/org/apache/sling/junit/annotations/TestReference.java&p1=sling/whiteboard/bdelacretaz/junit/core/src/main/java/org/apache/sling/junit/TestReference.java&r1=1066422&r2=1066470&rev=1066470&view=diff
==============================================================================
--- sling/whiteboard/bdelacretaz/junit/core/src/main/java/org/apache/sling/junit/TestReference.java
(original)
+++ sling/whiteboard/bdelacretaz/junit/core/src/main/java/org/apache/sling/junit/annotations/TestReference.java
Wed Feb  2 14:06:15 2011
@@ -14,13 +14,14 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.sling.junit;
+package org.apache.sling.junit.annotations;
 
 import java.lang.annotation.ElementType;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.lang.annotation.Target;
 
+
 /** Annotation used to inject services in test classes. Similar
  *  to the Felix @Reference annotation, but we need RetentionPolicy.RUNTIME
  *  so we cannot use that one. 

Modified: sling/whiteboard/bdelacretaz/junit/core/src/main/java/org/apache/sling/junit/impl/AnnotationsProcessor.java
URL: http://svn.apache.org/viewvc/sling/whiteboard/bdelacretaz/junit/core/src/main/java/org/apache/sling/junit/impl/AnnotationsProcessor.java?rev=1066470&r1=1066469&r2=1066470&view=diff
==============================================================================
--- sling/whiteboard/bdelacretaz/junit/core/src/main/java/org/apache/sling/junit/impl/AnnotationsProcessor.java
(original)
+++ sling/whiteboard/bdelacretaz/junit/core/src/main/java/org/apache/sling/junit/impl/AnnotationsProcessor.java
Wed Feb  2 14:06:15 2011
@@ -21,7 +21,7 @@ import java.lang.reflect.Field;
 import org.apache.felix.scr.annotations.Component;
 import org.apache.felix.scr.annotations.Service;
 import org.apache.sling.junit.TestObjectProcessor;
-import org.apache.sling.junit.TestReference;
+import org.apache.sling.junit.annotations.TestReference;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceReference;
 import org.osgi.service.component.ComponentContext;

Added: sling/whiteboard/bdelacretaz/junit/core/src/main/java/org/apache/sling/junit/impl/BundleTestsProvider.java
URL: http://svn.apache.org/viewvc/sling/whiteboard/bdelacretaz/junit/core/src/main/java/org/apache/sling/junit/impl/BundleTestsProvider.java?rev=1066470&view=auto
==============================================================================
--- sling/whiteboard/bdelacretaz/junit/core/src/main/java/org/apache/sling/junit/impl/BundleTestsProvider.java
(added)
+++ sling/whiteboard/bdelacretaz/junit/core/src/main/java/org/apache/sling/junit/impl/BundleTestsProvider.java
Wed Feb  2 14:06:15 2011
@@ -0,0 +1,234 @@
+/*
+ * 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.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 java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
+
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Service;
+import org.apache.sling.junit.TestsProvider;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleEvent;
+import org.osgi.framework.BundleListener;
+import org.osgi.framework.Constants;
+import org.osgi.service.component.ComponentContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/** A TestProvider that gets test classes from bundles
+ *  that have a Sling-Test-Regexp header and corresponding
+ *  exported classes.
+ */
+@Component
+@Service
+public class BundleTestsProvider implements TestsProvider, BundleListener {
+    private final Logger log = LoggerFactory.getLogger(getClass());
+    private long lastModified;
+    private BundleContext bundleContext;
+    private String pid;
+    
+    public static final String SLING_TEST_REGEXP = "Sling-Test-Regexp";
+    
+    /** 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>>();
+
+    protected void activate(ComponentContext ctx) {
+        bundleContext = ctx.getBundleContext();
+        bundleContext.addBundleListener(this);
+        
+        // Initially consider all bundles as "changed"
+        for(Bundle b : bundleContext.getBundles()) {
+            if(getSlingTestRegexp(b) != null) {
+                changedBundles.add(b.getSymbolicName());
+                log.debug("Will look for test classes inside bundle {}", b.getSymbolicName());
+            }
+        }
+        
+        lastModified = System.currentTimeMillis();
+        pid = (String)ctx.getProperties().get(Constants.SERVICE_PID);
+    }
+    
+    protected void deactivate(ComponentContext ctx) {
+        bundleContext.removeBundleListener(this);
+        bundleContext = null;
+        changedBundles.clear();
+    }
+    
+    @Override
+    public String toString() {
+        return getClass().getSimpleName() + ", pid=" + pid;
+    }
+
+    /** 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());
+                }
+            }
+        }
+    }
+
+    /** Called when a bundle changes state */
+    public void bundleChanged(BundleEvent event) {
+        // Only consider bundles which contain tests
+        final Bundle b = event.getBundle();
+        if(getSlingTestRegexp(b) == null) {
+            log.debug("Bundle {} does not have {} header, ignored", 
+                    b.getSymbolicName(), SLING_TEST_REGEXP);
+            return;
+        }
+        synchronized (changedBundles) {
+            log.debug("Got BundleEvent for Bundle {}, will rebuild its lists of tests");
+            changedBundles.add(b.getSymbolicName());
+        }
+        lastModified = System.currentTimeMillis();
+    }
+    
+    private String getSlingTestRegexp(Bundle b) {
+        return (String)b.getHeaders().get(SLING_TEST_REGEXP);
+    }
+    
+    /** 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>();
+        Pattern testClassRegexp = null;
+        final String headerValue = getSlingTestRegexp(b); 
+        try {
+            testClassRegexp = Pattern.compile(headerValue);
+        } catch(PatternSyntaxException pse) {
+            log.warn(
+                    "Invalid pattern '" + headerValue 
+                    + "' for bundle " + b.getSymbolicName() + ", ignored", 
+                    pse);
+        }
+        
+        if(testClassRegexp == null) {
+            log.info("Bundle {} does not have {} header, not looking for test classes", SLING_TEST_REGEXP);
+        } 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(testClassRegexp.matcher(name).matches()) {
+                    result.add(name);
+                } else {
+                    log.debug("Class {} does not match {} pattern {} of bundle {}, ignored",
+                            new Object[] { name, SLING_TEST_REGEXP, testClassRegexp, 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<?> createTestClass(String testName) 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(testName)) {
+                b = findBundle(e.getKey());
+                break;
+            }
+        }
+        
+        if(b == null) {
+            throw new IllegalArgumentException("No Bundle found that supplies test class
" + testName);
+        }
+        return b.loadClass(testName);
+    }
+
+    /** @inheritDoc */
+    public long lastModified() {
+        return lastModified;
+    }
+
+    /** @inheritDoc */
+    public String getServicePid() {
+        return pid;
+    }
+
+    /** @inheritDoc */
+    public List<String> getTestNames() {
+        maybeUpdateTestClasses();
+        final List<String> result = new ArrayList<String>();
+        for(List<String> list : testClassesMap.values()) {
+            result.addAll(list);
+        }
+        return result;
+    }
+}
\ No newline at end of file

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

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

Modified: sling/whiteboard/bdelacretaz/junit/core/src/main/java/org/apache/sling/junit/impl/JUnitServlet.java
URL: http://svn.apache.org/viewvc/sling/whiteboard/bdelacretaz/junit/core/src/main/java/org/apache/sling/junit/impl/JUnitServlet.java?rev=1066470&r1=1066469&r2=1066470&view=diff
==============================================================================
--- sling/whiteboard/bdelacretaz/junit/core/src/main/java/org/apache/sling/junit/impl/JUnitServlet.java
(original)
+++ sling/whiteboard/bdelacretaz/junit/core/src/main/java/org/apache/sling/junit/impl/JUnitServlet.java
Wed Feb  2 14:06:15 2011
@@ -18,7 +18,7 @@ package org.apache.sling.junit.impl;
 
 import java.io.IOException;
 import java.io.PrintWriter;
-import java.util.List;
+import java.util.Collection;
 
 import javax.servlet.ServletException;
 
@@ -29,7 +29,6 @@ import org.apache.felix.scr.annotations.
 import org.apache.sling.api.SlingHttpServletRequest;
 import org.apache.sling.api.SlingHttpServletResponse;
 import org.apache.sling.api.servlets.SlingAllMethodsServlet;
-import org.apache.sling.junit.JUnitConstants;
 import org.apache.sling.junit.JUnitTestsManager;
 import org.junit.runner.JUnitCore;
 
@@ -54,18 +53,17 @@ public class JUnitServlet extends SlingA
         pw.println();
         
         // Any test classes?
-        final List<String> testClasses = testsManager.getTestClasses();
+        final Collection<String> testClasses = testsManager.getTestNames();
         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 "
-                    + JUnitConstants.SLING_TEST_REGEXP + " header."
+                    "No test classes found, check the requirements of the active " +
+                    "TestsProvider services for how to supply tests." 
                     );
             return;
         }
         
         // List test classes
-        pw.println("TEST CLASSES (found in bundles that have a " + JUnitConstants.SLING_TEST_REGEXP
+ " header):");
+        pw.println("TEST CLASSES");
         for(String className : testClasses) {
             pw.println(className);
         }

Modified: sling/whiteboard/bdelacretaz/junit/core/src/main/java/org/apache/sling/junit/impl/JUnitTestsManagerImpl.java
URL: http://svn.apache.org/viewvc/sling/whiteboard/bdelacretaz/junit/core/src/main/java/org/apache/sling/junit/impl/JUnitTestsManagerImpl.java?rev=1066470&r1=1066469&r2=1066470&view=diff
==============================================================================
--- sling/whiteboard/bdelacretaz/junit/core/src/main/java/org/apache/sling/junit/impl/JUnitTestsManagerImpl.java
(original)
+++ sling/whiteboard/bdelacretaz/junit/core/src/main/java/org/apache/sling/junit/impl/JUnitTestsManagerImpl.java
Wed Feb  2 14:06:15 2011
@@ -16,193 +16,131 @@
  */
 package org.apache.sling.junit.impl;
 
-import static org.apache.sling.junit.JUnitConstants.SLING_TEST_REGEXP;
-
-import java.net.URL;
 import java.util.ArrayList;
-import java.util.Enumeration;
+import java.util.Collection;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.regex.Pattern;
-import java.util.regex.PatternSyntaxException;
 
 import org.apache.felix.scr.annotations.Component;
 import org.apache.felix.scr.annotations.Service;
 import org.apache.sling.junit.JUnitTestsManager;
-import org.osgi.framework.Bundle;
+import org.apache.sling.junit.TestsProvider;
 import org.osgi.framework.BundleContext;
-import org.osgi.framework.BundleEvent;
-import org.osgi.framework.BundleListener;
+import org.osgi.framework.ServiceReference;
 import org.osgi.service.component.ComponentContext;
+import org.osgi.util.tracker.ServiceTracker;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 @Component
 @Service
-public class JUnitTestsManagerImpl implements BundleListener,JUnitTestsManager {
+public class JUnitTestsManagerImpl implements JUnitTestsManager {
     private final Logger log = LoggerFactory.getLogger(getClass());
+    private ServiceTracker tracker;
+    private int lastTrackingCount = -1;
     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 getSlingTestRegexp(Bundle b) {
-        return (String)b.getHeaders().get(SLING_TEST_REGEXP);
-    }
+    // List of providers
+    private List<TestsProvider> providers = new ArrayList<TestsProvider>();
+    
+    // Map of test names to their provider's PID
+    private Map<String, String> tests = new HashMap<String, String>();
+    
+    // Last-modified values for each provider
+    private Map<String, Long> lastModified = new HashMap<String, Long>();
     
     protected void activate(ComponentContext ctx) {
         bundleContext = ctx.getBundleContext();
-        bundleContext.addBundleListener(this);
-        
-        // Initially consider all bundles as "changed"
-        for(Bundle b : bundleContext.getBundles()) {
-            if(getSlingTestRegexp(b) != null) {
-                changedBundles.add(b.getSymbolicName());
-                log.debug("Will look for test classes inside bundle {}", b.getSymbolicName());
-            }
-        }
+        tracker = new ServiceTracker(bundleContext, TestsProvider.class.getName(), null);
+        tracker.open();
     }
-    
+
     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(getSlingTestRegexp(b) == null) {
-            log.debug("Bundle {} does not have {} header, ignored", 
-                    b.getSymbolicName(), SLING_TEST_REGEXP);
-            return;
-        }
-        synchronized (changedBundles) {
-            log.debug("Got BundleEvent for Bundle {}, will rebuild its lists of tests");
-            changedBundles.add(b.getSymbolicName());
+        if(tracker != null) {
+            tracker.close();
         }
+        tracker = null;
+        bundleContext = null;
     }
     
-    /** 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);
+    /** inheritDoc */
+    public Class<?> getTestClass(String testName) throws ClassNotFoundException {
+        maybeUpdateProviders();
+
+        // find TestsProvider that can instantiate testName
+        final String providerPid = tests.get(testName);
+        if(providerPid == null) {
+            throw new IllegalStateException("Provider PID not found for test " + testName);
+        }
+        TestsProvider provider = null;
+        for(TestsProvider p : providers) {
+            if(p.getServicePid().equals(providerPid)) {
+                provider = p;
+                break;
+            }
         }
         
-        // 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());
-                }
-            }
+        if(provider == null) {
+            throw new IllegalStateException("No TestsProvider found for PID " + providerPid);
         }
-    }
 
-    /** @inheritDoc */
-    public List<String> getTestClasses() {
-        maybeUpdateTestClasses();
-        final List<String> result = new ArrayList<String>();
-        for(List<String> list : testClassesMap.values()) {
-            result.addAll(list);
-        }
-        return result;
+        log.debug("Using provider {} to create test class {}", testName);
+        return provider.createTestClass(testName);
     }
 
-    /** 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>();
-        Pattern testClassRegexp = null;
-        final String headerValue = getSlingTestRegexp(b); 
-        try {
-            testClassRegexp = Pattern.compile(headerValue);
-        } catch(PatternSyntaxException pse) {
-            log.warn(
-                    "Invalid pattern '" + headerValue 
-                    + "' for bundle " + b.getSymbolicName() + ", ignored", 
-                    pse);
+    /** inheritDoc */
+    public Collection<String> getTestNames() {
+        maybeUpdateProviders();
+        
+        // If any provider has changes, reload the whole list
+        // of test names (to keep things simple)
+        boolean reload = false;
+        for(TestsProvider p : providers) {
+            final Long lastMod = lastModified.get(p.getServicePid());
+            if(lastMod == null || lastMod.longValue() != p.lastModified()) {
+                reload = true;
+                log.debug("{} updated, will reload test names from all providers", p);
+                break;
+            }
         }
         
-        if(testClassRegexp == null) {
-            log.info("Bundle {} does not have {} header, not looking for test classes", SLING_TEST_REGEXP);
-        } 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(testClassRegexp.matcher(name).matches()) {
-                    result.add(name);
-                } else {
-                    log.debug("Class {} does not match {} pattern {} of bundle {}, ignored",
-                            new Object[] { name, SLING_TEST_REGEXP, testClassRegexp, b.getSymbolicName()
});
+        if(reload) {
+            tests.clear();
+            for(TestsProvider p : providers) {
+                final String pid = p.getServicePid();
+                if(pid == null) {
+                    log.warn("{} has null PID, ignored", p);
+                    continue;
+                }
+                lastModified.put(pid, new Long(p.lastModified()));
+                final List<String> names = p.getTestNames(); 
+                for(String name : names) {
+                    tests.put(name, pid);
                 }
+                log.debug("Added {} test names from provider {}", names.size(), p);
             }
-            log.info("{} test classes found in bundle {}", result.size(), b.getSymbolicName());
+            log.info("Test names reloaded, total {} names from {} providers", tests.size(),
providers.size());
         }
         
-        return result;
+        return tests.keySet();
     }
     
-    /** 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;
+    /** Update our list of providers if tracker changed */
+    private void maybeUpdateProviders() {
+        if(tracker.getTrackingCount() != lastTrackingCount) {
+            // List of providers changed, need to reload everything
+            lastModified.clear();
+            List<TestsProvider> newList = new ArrayList<TestsProvider>();
+            for(ServiceReference ref : tracker.getServiceReferences()) {
+                newList.add((TestsProvider)bundleContext.getService(ref));
             }
-        }
-        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;
+            synchronized (providers) {
+                providers.clear();
+                providers.addAll(newList);
             }
+            log.info("Updated list of TestsProvider: {}", providers);
         }
-        
-        if(b == null) {
-            throw new IllegalArgumentException("No Bundle found that supplies test class
" + className);
-        }
-        return b.loadClass(className);
+        lastTrackingCount = tracker.getTrackingCount();
     }
 }
\ No newline at end of file

Modified: sling/whiteboard/bdelacretaz/junit/testbundle/src/main/java/org/apache/sling/junit/testbundle/tests/OsgiAwareTest.java
URL: http://svn.apache.org/viewvc/sling/whiteboard/bdelacretaz/junit/testbundle/src/main/java/org/apache/sling/junit/testbundle/tests/OsgiAwareTest.java?rev=1066470&r1=1066469&r2=1066470&view=diff
==============================================================================
--- sling/whiteboard/bdelacretaz/junit/testbundle/src/main/java/org/apache/sling/junit/testbundle/tests/OsgiAwareTest.java
(original)
+++ sling/whiteboard/bdelacretaz/junit/testbundle/src/main/java/org/apache/sling/junit/testbundle/tests/OsgiAwareTest.java
Wed Feb  2 14:06:15 2011
@@ -18,8 +18,8 @@ package org.apache.sling.junit.testbundl
 
 import static org.junit.Assert.assertNotNull;
 
-import org.apache.sling.junit.SlingAnnotationsTestRunner;
-import org.apache.sling.junit.TestReference;
+import org.apache.sling.junit.annotations.SlingAnnotationsTestRunner;
+import org.apache.sling.junit.annotations.TestReference;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.osgi.framework.BundleContext;



Mime
View raw message