You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by cz...@apache.org on 2010/10/11 08:54:14 UTC

svn commit: r1021247 [6/6] - in /sling/branches/eventing-3.0: ./ .settings/ src/ src/main/ src/main/java/ src/main/java/org/ src/main/java/org/apache/ src/main/java/org/apache/sling/ src/main/java/org/apache/sling/event/ src/main/java/org/apache/sling/...

Added: sling/branches/eventing-3.0/src/test/java/org/apache/sling/event/impl/DistributingEventHandlerTest.java
URL: http://svn.apache.org/viewvc/sling/branches/eventing-3.0/src/test/java/org/apache/sling/event/impl/DistributingEventHandlerTest.java?rev=1021247&view=auto
==============================================================================
--- sling/branches/eventing-3.0/src/test/java/org/apache/sling/event/impl/DistributingEventHandlerTest.java (added)
+++ sling/branches/eventing-3.0/src/test/java/org/apache/sling/event/impl/DistributingEventHandlerTest.java Mon Oct 11 06:54:12 2010
@@ -0,0 +1,111 @@
+/*
+ * 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.event.impl;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Calendar;
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import javax.jcr.Node;
+import javax.jcr.NodeIterator;
+import javax.jcr.RepositoryException;
+import javax.jcr.observation.EventListenerIterator;
+
+import org.apache.jackrabbit.util.ISO9075;
+import org.apache.sling.event.EventUtil;
+import org.apache.sling.event.impl.jobs.jcr.JCRHelper;
+import org.apache.sling.event.impl.support.Environment;
+import org.jmock.Mockery;
+import org.jmock.integration.junit4.JMock;
+import org.jmock.integration.junit4.JUnit4Mockery;
+import org.junit.runner.RunWith;
+import org.osgi.service.event.Event;
+
+@RunWith(JMock.class)
+public class DistributingEventHandlerTest extends AbstractRepositoryEventHandlerTest {
+
+    protected Mockery context;
+
+    public DistributingEventHandlerTest() {
+        this.context = new JUnit4Mockery();
+    }
+
+    @Override
+    protected AbstractRepositoryEventHandler createHandler() {
+        return new DistributingEventHandler();
+    }
+
+    @Override
+    protected Mockery getMockery() {
+        return this.context;
+    }
+
+    @org.junit.Test public void testSetup() throws RepositoryException {
+        assertEquals(Environment.APPLICATION_ID, SLING_ID);
+        assertEquals(this.handler.repositoryPath, REPO_PATH);
+        assertNotNull(this.handler.writerSession);
+        final EventListenerIterator iter = this.handler.writerSession.getWorkspace().getObservationManager().getRegisteredEventListeners();
+        boolean found = false;
+        while ( !found && iter.hasNext() ) {
+            final javax.jcr.observation.EventListener listener = iter.nextEventListener();
+            found = (listener == this.handler);
+        }
+        assertTrue("Handler is not registered as event listener.", found);
+    }
+
+    @org.junit.Test public void testWriteEvent() throws Exception {
+        final String topic = "write/event/test";
+        final Dictionary<String, Object> props = new Hashtable<String, Object>();
+        props.put("a property", "some value");
+        final Event e = new Event(topic, props);
+        this.handler.writeEvent(e, null);
+
+        final Node rootNode = (Node) session.getItem(this.handler.repositoryPath);
+        final NodeIterator iter = rootNode.getNodes();
+        iter.hasNext();
+        final Node eventNode = iter.nextNode();
+        assertEquals(topic, eventNode.getProperty(JCRHelper.NODE_PROPERTY_TOPIC).getString());
+        assertEquals(Environment.APPLICATION_ID, eventNode.getProperty(JCRHelper.NODE_PROPERTY_APPLICATION).getString());
+        assertTrue(Calendar.getInstance().compareTo(eventNode.getProperty(JCRHelper.NODE_PROPERTY_CREATED).getDate()) >= 0);
+        // as a starting point we just check if the properties property exists
+        assertTrue(eventNode.hasProperty(ISO9075.encode("a property")));
+    }
+
+    @org.junit.Test public void testWriteEventPlusAppId() throws Exception {
+        final String topic = "write/event/test";
+        final Dictionary<String, Object> props = new Hashtable<String, Object>();
+        props.put("a property", "some value");
+        // now we check if the application id is handled correctly
+        props.put(EventUtil.PROPERTY_APPLICATION, "foo");
+        this.handler.writeEvent(new Event(topic, props), null);
+        final Node rootNode = (Node) session.getItem(this.handler.repositoryPath);
+        final NodeIterator iter = rootNode.getNodes();
+        iter.hasNext();
+        final Node eventNode = iter.nextNode();
+        assertEquals(topic, eventNode.getProperty(JCRHelper.NODE_PROPERTY_TOPIC).getString());
+        assertEquals(Environment.APPLICATION_ID, eventNode.getProperty(JCRHelper.NODE_PROPERTY_APPLICATION).getString());
+        assertTrue(Calendar.getInstance().compareTo(eventNode.getProperty(JCRHelper.NODE_PROPERTY_CREATED).getDate()) >= 0);
+        // as a starting point we just check if the properties property exists
+        assertTrue(eventNode.hasProperty(ISO9075.encode("a property")));
+    }
+}

Propchange: sling/branches/eventing-3.0/src/test/java/org/apache/sling/event/impl/DistributingEventHandlerTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/branches/eventing-3.0/src/test/java/org/apache/sling/event/impl/DistributingEventHandlerTest.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Propchange: sling/branches/eventing-3.0/src/test/java/org/apache/sling/event/impl/DistributingEventHandlerTest.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/branches/eventing-3.0/src/test/java/org/apache/sling/event/impl/RepositoryTestUtil.java
URL: http://svn.apache.org/viewvc/sling/branches/eventing-3.0/src/test/java/org/apache/sling/event/impl/RepositoryTestUtil.java?rev=1021247&view=auto
==============================================================================
--- sling/branches/eventing-3.0/src/test/java/org/apache/sling/event/impl/RepositoryTestUtil.java (added)
+++ sling/branches/eventing-3.0/src/test/java/org/apache/sling/event/impl/RepositoryTestUtil.java Mon Oct 11 06:54:12 2010
@@ -0,0 +1,148 @@
+/*
+ * 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.event.impl;
+
+import java.io.File;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+import javax.jcr.Credentials;
+import javax.jcr.LoginException;
+import javax.jcr.NoSuchWorkspaceException;
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.SimpleCredentials;
+import javax.jcr.Value;
+
+import org.apache.jackrabbit.commons.JcrUtils;
+import org.apache.jackrabbit.commons.cnd.CndImporter;
+import org.apache.sling.jcr.api.SlingRepository;
+
+public class RepositoryTestUtil {
+
+    /** We hold an admin session the whole time. */
+    private static Session adminSession;
+
+    private static Repository repository;
+
+    private static void init() throws RepositoryException {
+        if ( repository == null ) {
+            final File f = new File("target/repository");
+            repository = JcrUtils.getRepository(f.toURI().toString());
+
+            final SimpleCredentials cred = new SimpleCredentials("admin", "admin".toCharArray());
+            adminSession = repository.login(cred);
+        }
+    }
+
+    public static void startRepository() throws RepositoryException {
+        init();
+    }
+
+    public static void stopRepository() {
+        if ( adminSession != null ) {
+            adminSession.logout();
+            adminSession = null;
+        }
+        repository = null;
+    }
+
+    public static Session getAdminSession() {
+        return adminSession;
+    }
+
+    public static SlingRepository getSlingRepository() {
+        return new RepositoryWrapper(repository);
+    }
+
+    public static boolean registerNodeType(Session session, InputStream resourceAsStream) {
+        try {
+            CndImporter.registerNodeTypes(new InputStreamReader(resourceAsStream, "UTF-8"), session);
+            return true;
+        } catch (Exception e) {
+            // ignore
+            return false;
+        }
+    }
+
+    public static final class RepositoryWrapper implements SlingRepository {
+
+        protected final Repository wrapped;
+
+        public RepositoryWrapper(Repository r) {
+            wrapped = r;
+        }
+
+        public String getDescriptor(String key) {
+            return wrapped.getDescriptor(key);
+        }
+
+        public String[] getDescriptorKeys() {
+            return wrapped.getDescriptorKeys();
+        }
+
+        public Session login() throws LoginException, RepositoryException {
+            return wrapped.login();
+        }
+
+        public Session login(Credentials credentials, String workspaceName)
+                throws LoginException, NoSuchWorkspaceException,
+                RepositoryException {
+            return wrapped.login(credentials, workspaceName);
+        }
+
+        public Session login(Credentials credentials) throws LoginException,
+                RepositoryException {
+            return wrapped.login(credentials);
+        }
+
+        public Session login(String workspaceName) throws LoginException,
+                NoSuchWorkspaceException, RepositoryException {
+            return wrapped.login(workspaceName);
+        }
+
+        public String getDefaultWorkspace() {
+            return "default";
+        }
+
+        public Session loginAdministrative(String workspace)
+                throws RepositoryException {
+            final Credentials credentials = new SimpleCredentials("admin",
+                    "admin".toCharArray());
+            return this.login(credentials, workspace);
+        }
+
+        public Value getDescriptorValue(String key) {
+            return wrapped.getDescriptorValue(key);
+        }
+
+        public Value[] getDescriptorValues(String key) {
+            return wrapped.getDescriptorValues(key);
+        }
+
+        public boolean isSingleValueDescriptor(String key) {
+            return wrapped.isSingleValueDescriptor(key);
+        }
+
+        public boolean isStandardDescriptor(String key) {
+            return wrapped.isStandardDescriptor(key);
+        }
+    }
+}
\ No newline at end of file

Propchange: sling/branches/eventing-3.0/src/test/java/org/apache/sling/event/impl/RepositoryTestUtil.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/branches/eventing-3.0/src/test/java/org/apache/sling/event/impl/RepositoryTestUtil.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Propchange: sling/branches/eventing-3.0/src/test/java/org/apache/sling/event/impl/RepositoryTestUtil.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/branches/eventing-3.0/src/test/java/org/apache/sling/event/impl/SimpleEventAdmin.java
URL: http://svn.apache.org/viewvc/sling/branches/eventing-3.0/src/test/java/org/apache/sling/event/impl/SimpleEventAdmin.java?rev=1021247&view=auto
==============================================================================
--- sling/branches/eventing-3.0/src/test/java/org/apache/sling/event/impl/SimpleEventAdmin.java (added)
+++ sling/branches/eventing-3.0/src/test/java/org/apache/sling/event/impl/SimpleEventAdmin.java Mon Oct 11 06:54:12 2010
@@ -0,0 +1,61 @@
+/*
+ * 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.event.impl;
+
+import org.osgi.service.event.Event;
+import org.osgi.service.event.EventAdmin;
+import org.osgi.service.event.EventHandler;
+
+/**
+ * Simple event admin implementation for testing.
+ */
+public class SimpleEventAdmin implements EventAdmin {
+
+    private final String[] topics;
+    private final EventHandler[] handler;
+
+    public SimpleEventAdmin(final String[] topics, final EventHandler[] handler) {
+        this.topics = topics;
+        this.handler = handler;
+        if ( topics == null && handler != null ) {
+            throw new IllegalArgumentException("If topics is null, handler must be null as well");
+        }
+        if ( topics.length != handler.length ) {
+            throw new IllegalArgumentException("Topics and handler must have the same size.");
+        }
+    }
+
+    public void postEvent(final Event event) {
+        new Thread() {
+            public void run() {
+                sendEvent(event);
+            }
+        }.start();
+    }
+
+    public void sendEvent(Event event) {
+        if ( topics != null ) {
+            for(int i=0; i<topics.length; i++) {
+                if ( topics[i].equals(event.getTopic()) ) {
+                    handler[i].handleEvent(event);
+                }
+            }
+        }
+    }
+}

Propchange: sling/branches/eventing-3.0/src/test/java/org/apache/sling/event/impl/SimpleEventAdmin.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/branches/eventing-3.0/src/test/java/org/apache/sling/event/impl/SimpleEventAdmin.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Propchange: sling/branches/eventing-3.0/src/test/java/org/apache/sling/event/impl/SimpleEventAdmin.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/branches/eventing-3.0/src/test/java/org/apache/sling/event/impl/SimpleScheduler.java
URL: http://svn.apache.org/viewvc/sling/branches/eventing-3.0/src/test/java/org/apache/sling/event/impl/SimpleScheduler.java?rev=1021247&view=auto
==============================================================================
--- sling/branches/eventing-3.0/src/test/java/org/apache/sling/event/impl/SimpleScheduler.java (added)
+++ sling/branches/eventing-3.0/src/test/java/org/apache/sling/event/impl/SimpleScheduler.java Mon Oct 11 06:54:12 2010
@@ -0,0 +1,80 @@
+/*
+ * 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.event.impl;
+
+import java.io.Serializable;
+import java.util.Date;
+import java.util.Map;
+import java.util.NoSuchElementException;
+
+import org.apache.sling.commons.scheduler.Scheduler;
+
+/**
+ * Simple scheduler implementation for testing.
+ */
+public class SimpleScheduler implements Scheduler {
+
+    public void addJob(String name, Object job,
+            Map<String, Serializable> config, String schedulingExpression,
+            boolean canRunConcurrently) throws Exception {
+        throw new IllegalArgumentException();
+    }
+
+    public void addPeriodicJob(String name, Object job,
+            Map<String, Serializable> config, long period,
+            boolean canRunConcurrently) throws Exception {
+        throw new IllegalAccessException();
+    }
+
+    public boolean fireJob(Object job, Map<String, Serializable> config,
+            int times, long period) {
+        throw new IllegalArgumentException();
+    }
+
+    public void fireJob(Object job, Map<String, Serializable> config)
+            throws Exception {
+        throw new IllegalAccessException();
+    }
+
+    public boolean fireJobAt(String name, Object job,
+            Map<String, Serializable> config, Date date, int times, long period) {
+        throw new IllegalArgumentException();
+    }
+
+    public void fireJobAt(String name, final Object job,
+            Map<String, Serializable> config, final Date date) throws Exception {
+        new Thread() {
+            public void run() {
+                final long sleepTime = date.getTime() - System.currentTimeMillis();
+                if ( sleepTime > 0 ) {
+                    try {
+                        Thread.sleep(sleepTime);
+                    } catch (InterruptedException e) {
+                        // ignore
+                    }
+                }
+                ((Runnable)job).run();
+            }
+        }.start();
+    }
+
+    public void removeJob(String name) throws NoSuchElementException {
+        // ignore this
+    }
+}

Propchange: sling/branches/eventing-3.0/src/test/java/org/apache/sling/event/impl/SimpleScheduler.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/branches/eventing-3.0/src/test/java/org/apache/sling/event/impl/SimpleScheduler.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Propchange: sling/branches/eventing-3.0/src/test/java/org/apache/sling/event/impl/SimpleScheduler.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/branches/eventing-3.0/src/test/java/org/apache/sling/event/impl/jobs/AbstractJobEventHandlerTest.java
URL: http://svn.apache.org/viewvc/sling/branches/eventing-3.0/src/test/java/org/apache/sling/event/impl/jobs/AbstractJobEventHandlerTest.java?rev=1021247&view=auto
==============================================================================
--- sling/branches/eventing-3.0/src/test/java/org/apache/sling/event/impl/jobs/AbstractJobEventHandlerTest.java (added)
+++ sling/branches/eventing-3.0/src/test/java/org/apache/sling/event/impl/jobs/AbstractJobEventHandlerTest.java Mon Oct 11 06:54:12 2010
@@ -0,0 +1,110 @@
+/*
+ * 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.event.impl.jobs;
+
+import java.util.Hashtable;
+
+import junitx.util.PrivateAccessor;
+
+import org.apache.sling.event.impl.AbstractTest;
+import org.apache.sling.event.impl.SimpleScheduler;
+import org.apache.sling.event.impl.jobs.config.QueueConfigurationManager;
+import org.apache.sling.event.impl.jobs.jcr.PersistenceHandler;
+import org.jmock.Expectations;
+import org.jmock.integration.junit4.JMock;
+import org.junit.runner.RunWith;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceListener;
+import org.osgi.service.component.ComponentContext;
+import org.osgi.service.event.EventAdmin;
+
+@RunWith(JMock.class)
+public abstract class AbstractJobEventHandlerTest extends AbstractTest {
+
+    protected volatile PersistenceHandler handler;
+
+    protected volatile DefaultJobManager jobManager;
+
+    protected volatile QueueConfigurationManager configManager;
+
+    protected void activate(final EventAdmin ea) throws Throwable {
+        super.activate(ea);
+        this.jobManager = new DefaultJobManager();
+        this.configManager = new QueueConfigurationManager();
+        PrivateAccessor.setField(this.jobManager, "configManager", this.configManager);
+        PrivateAccessor.setField(this.jobManager, "environment", this.environment);
+        PrivateAccessor.setField(this.jobManager, "scheduler", new SimpleScheduler());
+        this.handler = new PersistenceHandler();
+        PrivateAccessor.setField(this.handler, "environment", this.environment);
+        PrivateAccessor.setField(this.handler, "jobManager", this.jobManager);
+
+        // lets set up the bundle context
+        final BundleContext bundleContext = this.getMockery().mock(BundleContext.class, "beforeBundleContext" + activateCount);
+
+        // lets set up the component configuration
+        final Hashtable<String, Object> componentConfig = this.getComponentConfig();
+
+        // lets set up the compnent context
+        final ComponentContext componentContext = this.getMockery().mock(ComponentContext.class, "beforeComponentContext" + activateCount);
+        this.getMockery().checking(new Expectations() {{
+            allowing(componentContext).getBundleContext();
+            will(returnValue(bundleContext));
+            allowing(componentContext).getProperties();
+            will(returnValue(componentConfig));
+            allowing(bundleContext).createFilter(with(any(String.class)));
+            allowing(bundleContext).addServiceListener(with(any(ServiceListener.class)));
+            allowing(bundleContext).addServiceListener(with(any(ServiceListener.class)), with(any(String.class)));
+            allowing(bundleContext).removeServiceListener(with(any(ServiceListener.class)));
+            allowing(bundleContext).getServiceReferences(with(any(String.class)), with(aNull(String.class)));
+            allowing(bundleContext).getServiceReferences(with(aNull(String.class)), with(aNull(String.class)));
+            allowing(bundleContext).getServiceReferences(with(any(String.class)), with(any(String.class)));
+            allowing(bundleContext).getServiceReferences(with(aNull(String.class)), with(any(String.class)));
+        }});
+
+        PrivateAccessor.invoke(this.handler, "activate", new Class[] {ComponentContext.class}, new Object[] {componentContext});
+        this.jobManager.activate(componentConfig);
+        PrivateAccessor.invoke(this.configManager, "activate", new Class[] {BundleContext.class}, new Object[] {bundleContext});
+
+        // the session is initialized in the background, so let's sleep some seconds
+        try {
+            Thread.sleep(2 * 1000);
+        } catch (InterruptedException e) {
+            // ignore
+        }
+    }
+
+
+    protected void deactivate() throws Throwable {
+        // lets set up the bundle context with the sling id
+        final BundleContext bundleContext = this.getMockery().mock(BundleContext.class, "afterBundleContext" + activateCount);
+
+        final ComponentContext componentContext = this.getMockery().mock(ComponentContext.class, "afterComponentContext" + activateCount);
+        this.getMockery().checking(new Expectations() {{
+            allowing(componentContext).getBundleContext();
+            will(returnValue(bundleContext));
+        }});
+        PrivateAccessor.invoke(this.configManager, "deactivate", null, null);
+        PrivateAccessor.invoke(this.handler, "deactivate", new Class[] {ComponentContext.class}, new Object[] {componentContext});
+        this.handler = null;
+        this.jobManager.deactivate();
+        this.jobManager = null;
+        this.configManager = null;
+        super.deactivate();
+    }
+}

Propchange: sling/branches/eventing-3.0/src/test/java/org/apache/sling/event/impl/jobs/AbstractJobEventHandlerTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/branches/eventing-3.0/src/test/java/org/apache/sling/event/impl/jobs/AbstractJobEventHandlerTest.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Propchange: sling/branches/eventing-3.0/src/test/java/org/apache/sling/event/impl/jobs/AbstractJobEventHandlerTest.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/branches/eventing-3.0/src/test/java/org/apache/sling/event/impl/jobs/JobEventHandlerTest.java
URL: http://svn.apache.org/viewvc/sling/branches/eventing-3.0/src/test/java/org/apache/sling/event/impl/jobs/JobEventHandlerTest.java?rev=1021247&view=auto
==============================================================================
--- sling/branches/eventing-3.0/src/test/java/org/apache/sling/event/impl/jobs/JobEventHandlerTest.java (added)
+++ sling/branches/eventing-3.0/src/test/java/org/apache/sling/event/impl/jobs/JobEventHandlerTest.java Mon Oct 11 06:54:12 2010
@@ -0,0 +1,606 @@
+/*
+ * 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.event.impl.jobs;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Collections;
+import java.util.Dictionary;
+import java.util.Hashtable;
+import java.util.List;
+
+import javax.jcr.Node;
+import javax.jcr.Session;
+import javax.jcr.observation.EventListenerIterator;
+
+import junitx.util.PrivateAccessor;
+
+import org.apache.sling.event.impl.Barrier;
+import org.apache.sling.event.impl.RepositoryTestUtil;
+import org.apache.sling.event.impl.SimpleEventAdmin;
+import org.apache.sling.event.impl.jobs.jcr.JCRHelper;
+import org.apache.sling.event.impl.jobs.jcr.PersistenceHandler;
+import org.apache.sling.event.impl.support.Environment;
+import org.apache.sling.event.jobs.JobManager.QueryType;
+import org.apache.sling.event.jobs.JobUtil;
+import org.apache.sling.event.jobs.JobsIterator;
+import org.jmock.Mockery;
+import org.jmock.integration.junit4.JMock;
+import org.jmock.integration.junit4.JUnit4Mockery;
+import org.junit.runner.RunWith;
+import org.osgi.service.event.Event;
+import org.osgi.service.event.EventAdmin;
+import org.osgi.service.event.EventHandler;
+
+@RunWith(JMock.class)
+public class JobEventHandlerTest extends AbstractJobEventHandlerTest {
+
+    protected Mockery context;
+
+    public JobEventHandlerTest() {
+        this.context = new JUnit4Mockery();
+    }
+
+    @Override
+    protected Mockery getMockery() {
+        return this.context;
+    }
+
+    @Override
+    protected Hashtable<String, Object> getComponentConfig() {
+        final Hashtable<String, Object> config =  super.getComponentConfig();
+        config.put("cleanup.period", 1); // set clean up to 1 minute
+        config.put("load.delay", 1); // load delay to 1 sec
+        return config;
+    }
+
+    /**
+     * Simple setup test which checks if the session and the session listener
+     * is registered.
+     */
+    @org.junit.Test public void testSetup() throws Exception {
+        assertEquals(Environment.APPLICATION_ID, SLING_ID);
+        assertEquals(PrivateAccessor.getField(this.handler, "repositoryPath"), REPO_PATH);
+        assertNotNull(PrivateAccessor.getField(this.handler, "backgroundSession"));
+        final EventListenerIterator iter = ((Session)PrivateAccessor.getField(this.handler, "backgroundSession")).getWorkspace().getObservationManager().getRegisteredEventListeners();
+        boolean found = false;
+        while ( !found && iter.hasNext() ) {
+            final javax.jcr.observation.EventListener listener = iter.nextEventListener();
+            found = (listener == this.handler);
+        }
+        assertTrue("Handler is not registered as event listener.", found);
+    }
+
+    /**
+     * Helper method to create a job event.
+     */
+    private Event getJobEvent(String queueName, String id, String parallel) {
+        final Dictionary<String, Object> props = new Hashtable<String, Object>();
+        props.put(JobUtil.PROPERTY_JOB_TOPIC, "sling/test");
+        if ( id != null ) {
+            props.put(JobUtil.PROPERTY_JOB_NAME, id);
+        }
+        props.put(JobUtil.PROPERTY_JOB_RETRY_DELAY, 2000L);
+        props.put(JobUtil.PROPERTY_JOB_RETRIES, 2);
+        if ( queueName != null ) {
+            props.put(JobUtil.PROPERTY_JOB_QUEUE_NAME, queueName);
+        }
+        if ( parallel != null ) {
+            props.put(JobUtil.PROPERTY_JOB_PARALLEL, parallel);
+        }
+        return getJobEvent(queueName, id, parallel, false);
+    }
+
+    /**
+     * Helper method to create a job event.
+     */
+    private Event getJobEvent(String queueName, String id, String parallel, boolean runlocal) {
+        final Dictionary<String, Object> props = new Hashtable<String, Object>();
+        props.put(JobUtil.PROPERTY_JOB_TOPIC, "sling/test");
+        if ( id != null ) {
+            props.put(JobUtil.PROPERTY_JOB_NAME, id);
+        }
+        props.put(JobUtil.PROPERTY_JOB_RETRY_DELAY, 2000L);
+        props.put(JobUtil.PROPERTY_JOB_RETRIES, 2);
+        if ( queueName != null ) {
+            props.put(JobUtil.PROPERTY_JOB_QUEUE_NAME, queueName);
+        }
+        if ( parallel != null ) {
+            props.put(JobUtil.PROPERTY_JOB_PARALLEL, parallel);
+        }
+        if ( runlocal ) {
+            props.put(JobUtil.PROPERTY_JOB_RUN_LOCAL, "true");
+        }
+        return new Event(JobUtil.TOPIC_JOB, props);
+    }
+
+    /**
+     * Test simple job execution.
+     * The job is executed once and finished successfully.
+     */
+    @org.junit.Test public void testSimpleJobExecution() throws Exception {
+        final PersistenceHandler jeh = this.handler;
+        final Barrier cb = new Barrier(2);
+        setEventAdmin(new SimpleEventAdmin(new String[] {"sling/test"},
+                new EventHandler[] {
+                    new EventHandler() {
+                        public void handleEvent(Event event) {
+                            JobUtil.acknowledgeJob(event);
+                            JobUtil.finishedJob(event);
+                            cb.block();
+                        }
+
+                    }
+                }));
+        jeh.handleEvent(getJobEvent(null, null, null));
+        assertTrue("No event received in the given time.", cb.block(5));
+        cb.reset();
+        assertFalse("Unexpected event received in the given time.", cb.block(5));
+    }
+
+    private long getSize(final JobsIterator i) {
+        long size = i.getSize();
+        if ( size == - 1 ) {
+            size = 0;
+            while ( i.hasNext() ) {
+                i.next();
+                size++;
+            }
+        }
+        return size;
+    }
+    /**
+     * Test simple job execution with job id.
+     * The job is executed once and finished successfully.
+     */
+    @org.junit.Test public void testSimpleJobWithIdExecution() throws Exception {
+        final PersistenceHandler jeh = this.handler;
+        final Barrier cb = new Barrier(2);
+        setEventAdmin(new SimpleEventAdmin(new String[] {"sling/test"},
+                new EventHandler[] {
+                    new EventHandler() {
+                        public void handleEvent(Event event) {
+                            JobUtil.acknowledgeJob(event);
+                            JobUtil.finishedJob(event);
+                            cb.block();
+                        }
+
+                    }
+                }));
+        jeh.handleEvent(getJobEvent(null, "myid", null));
+        assertTrue("No event received in the given time.", cb.block(5));
+        cb.reset();
+        assertFalse("Unexpected event received in the given time.", cb.block(5));
+    }
+
+    /**
+     * Test cancelling a job
+     * The job execution always fails
+     */
+    @org.junit.Test public void testCancelJob() throws Exception {
+        final PersistenceHandler jeh = this.handler;
+        final Barrier cb = new Barrier(2);
+        setEventAdmin(new SimpleEventAdmin(new String[] {"sling/test"},
+                new EventHandler[] {
+                    new EventHandler() {
+                        public void handleEvent(Event event) {
+                            JobUtil.acknowledgeJob(event);
+                            cb.block();
+                            try {
+                                Thread.sleep(500);
+                            } catch (InterruptedException e) {
+                                // ignore
+                            }
+                            JobUtil.rescheduleJob(event);
+                        }
+
+                    }
+                }));
+        jeh.handleEvent(getJobEvent(null, "myid", null));
+        cb.block();
+        assertEquals(1, this.getSize(this.jobManager.queryJobs(QueryType.ALL, "sling/test")));
+        // job is currently sleeping, therefore cancel fails
+        final Event e1 = this.jobManager.findJob("sling/test", Collections.singletonMap(JobUtil.PROPERTY_JOB_NAME, (Object)"myid"));
+        assertNotNull(e1);
+        assertFalse(this.jobManager.removeJob((String)e1.getProperty(JobUtil.JOB_ID)));
+        try {
+            Thread.sleep(900);
+        } catch (InterruptedException e) {
+            // ignore
+        }
+        // the job is now in the queue again
+        final Event e2 = this.jobManager.findJob("sling/test", Collections.singletonMap(JobUtil.PROPERTY_JOB_NAME, (Object)"myid"));
+        assertNotNull(e2);
+        assertTrue(this.jobManager.removeJob((String)e2.getProperty(JobUtil.JOB_ID)));
+        assertEquals(0, this.getSize(this.jobManager.queryJobs(QueryType.ALL, "sling/test")));
+    }
+
+    /**
+     * Test force cancelling a job
+     * The job execution always fails
+     */
+    @org.junit.Test public void testForceCancelJob() throws Exception {
+        final PersistenceHandler jeh = this.handler;
+        final Barrier cb = new Barrier(2);
+        setEventAdmin(new SimpleEventAdmin(new String[] {"sling/test"},
+                new EventHandler[] {
+                    new EventHandler() {
+                        public void handleEvent(Event event) {
+                            JobUtil.acknowledgeJob(event);
+                            cb.block();
+                            try {
+                                Thread.sleep(1000);
+                            } catch (InterruptedException e) {
+                                // ignore
+                            }
+                            JobUtil.rescheduleJob(event);
+                        }
+
+                    }
+                }));
+        jeh.handleEvent(getJobEvent(null, "myid", null));
+        cb.block();
+        assertEquals(1, this.getSize(this.jobManager.queryJobs(QueryType.ALL, "sling/test")));
+        // job is currently sleeping, but force cancel always waits!
+        final Event e = this.jobManager.findJob("sling/test", Collections.singletonMap(JobUtil.PROPERTY_JOB_NAME, (Object)"myid"));
+        assertNotNull(e);
+        this.jobManager.forceRemoveJob((String)e.getProperty(JobUtil.JOB_ID));
+        // the job is now removed
+        assertEquals(0, this.getSize(this.jobManager.queryJobs(QueryType.ALL, "sling/test")));
+    }
+
+    /**
+     * Reschedule test.
+     * The job is rescheduled two times before it fails.
+     */
+    @org.junit.Test public void testStartJobAndReschedule() throws Exception {
+        final List<Integer> retryCountList = new ArrayList<Integer>();
+        final PersistenceHandler jeh = this.handler;
+        final Barrier cb = new Barrier(2);
+        setEventAdmin(new SimpleEventAdmin(new String[] {"sling/test"},
+                new EventHandler[] {
+                    new EventHandler() {
+                        int retryCount;
+                        public void handleEvent(Event event) {
+                            JobUtil.acknowledgeJob(event);
+                            int retry = 0;
+                            if ( event.getProperty(JobUtil.PROPERTY_JOB_RETRY_COUNT) != null ) {
+                                retry = (Integer)event.getProperty(JobUtil.PROPERTY_JOB_RETRY_COUNT);
+                            }
+                            if ( retry == retryCount ) {
+                                retryCountList.add(retry);
+                            }
+                            retryCount++;
+                            JobUtil.rescheduleJob(event);
+                            cb.block();
+                        }
+                    }
+                }));
+        jeh.handleEvent(getJobEvent(null, null, null));
+        assertTrue("No event received in the given time.", cb.block(5));
+        cb.reset();
+        // the job is retried after two seconds, so we wait again
+        assertTrue("No event received in the given time.", cb.block(5));
+        cb.reset();
+        // the job is retried after two seconds, so we wait again
+        assertTrue("No event received in the given time.", cb.block(5));
+        // we have reached the retry so we expect to not get an event
+        cb.reset();
+        assertFalse("Unexpected event received in the given time.", cb.block(5));
+        assertEquals("Unexpected number of retries", 3, retryCountList.size());
+    }
+
+    /**
+     * Reschedule test.
+     * The job is rescheduled two times before it fails.
+     */
+    @org.junit.Test public void testStartJobAndRescheduleInJobQueue() throws Exception {
+        final List<Integer> retryCountList = new ArrayList<Integer>();
+        final Barrier cb = new Barrier(2);
+        final PersistenceHandler jeh = this.handler;
+        setEventAdmin(new SimpleEventAdmin(new String[] {"sling/test"},
+                new EventHandler[] {
+                    new EventHandler() {
+                        int retryCount;
+                        public void handleEvent(Event event) {
+                            JobUtil.acknowledgeJob(event);
+                            int retry = 0;
+                            if ( event.getProperty(JobUtil.PROPERTY_JOB_RETRY_COUNT) != null ) {
+                                retry = (Integer)event.getProperty(JobUtil.PROPERTY_JOB_RETRY_COUNT);
+                            }
+                            if ( retry == retryCount ) {
+                                retryCountList.add(retry);
+                            }
+                            retryCount++;
+                            JobUtil.rescheduleJob(event);
+                            cb.block();
+                        }
+                    }
+                }));
+        jeh.handleEvent(getJobEvent("testqueue", null, null));
+        assertTrue("No event received in the given time.", cb.block(5));
+        cb.reset();
+        // the job is retried after two seconds, so we wait again
+        assertTrue("No event received in the given time.", cb.block(5));
+        cb.reset();
+        // the job is retried after two seconds, so we wait again
+        assertTrue("No event received in the given time.", cb.block(5));
+        // we have reached the retry so we expect to not get an event
+        cb.reset();
+        assertFalse("Unexpected event received in the given time.", cb.block(5));
+        assertEquals("Unexpected number of retries", 3, retryCountList.size());
+    }
+
+    /**
+     * Notifications.
+     * We send several jobs which are treated different and then see
+     * how many invocations have been sent.
+     */
+    @org.junit.Test public void testNotifications() throws Exception {
+        final List<String> cancelled = Collections.synchronizedList(new ArrayList<String>());
+        final List<String> failed = Collections.synchronizedList(new ArrayList<String>());
+        final List<String> finished = Collections.synchronizedList(new ArrayList<String>());
+        final List<String> started = Collections.synchronizedList(new ArrayList<String>());
+        final PersistenceHandler jeh = this.handler;
+        setEventAdmin(new SimpleEventAdmin(new String[] {"sling/test",
+                JobUtil.TOPIC_JOB_CANCELLED,
+                JobUtil.TOPIC_JOB_FAILED,
+                JobUtil.TOPIC_JOB_FINISHED,
+                JobUtil.TOPIC_JOB_STARTED},
+                new EventHandler[] {
+                    new EventHandler() {
+                        public void handleEvent(final Event event) {
+                            JobUtil.acknowledgeJob(event);
+                            // events 1 and 4 finish the first time
+                            final String id = (String)event.getProperty(JobUtil.PROPERTY_JOB_NAME);
+                            if ( "1".equals(id) || "4".equals(id) ) {
+                                JobUtil.finishedJob(event);
+                            } else
+                            // 5 fails always
+                            if ( "5".equals(id) ) {
+                                JobUtil.rescheduleJob(event);
+                            }
+                            int retry = 0;
+                            if ( event.getProperty(JobUtil.PROPERTY_JOB_RETRY_COUNT) != null ) {
+                                retry = (Integer)event.getProperty(JobUtil.PROPERTY_JOB_RETRY_COUNT);
+                            }
+                            // 2 fails the first time
+                            if ( "2".equals(id) ) {
+                                if ( retry == 0 ) {
+                                    JobUtil.rescheduleJob(event);
+                                } else {
+                                    JobUtil.finishedJob(event);
+                                }
+                            }
+                            // 3 fails the first and second time
+                            if ( "3".equals(id) ) {
+                                if ( retry == 0 || retry == 1 ) {
+                                    JobUtil.rescheduleJob(event);
+                                } else {
+                                    JobUtil.finishedJob(event);
+                                }
+                            }
+                        }
+                    },
+                    new EventHandler() {
+                        public void handleEvent(final Event event) {
+                            final Event job = (Event) event.getProperty(JobUtil.PROPERTY_NOTIFICATION_JOB);
+                            final String id = (String)job.getProperty(JobUtil.PROPERTY_JOB_NAME);
+                            cancelled.add(id);
+                        }
+                    },
+                    new EventHandler() {
+                        public void handleEvent(final Event event) {
+                            final Event job = (Event) event.getProperty(JobUtil.PROPERTY_NOTIFICATION_JOB);
+                            final String id = (String)job.getProperty(JobUtil.PROPERTY_JOB_NAME);
+                            failed.add(id);
+                        }
+                    },
+                    new EventHandler() {
+                        public void handleEvent(final Event event) {
+                            final Event job = (Event) event.getProperty(JobUtil.PROPERTY_NOTIFICATION_JOB);
+                            final String id = (String)job.getProperty(JobUtil.PROPERTY_JOB_NAME);
+                            finished.add(id);
+                        }
+                    },
+                    new EventHandler() {
+                        public void handleEvent(final Event event) {
+                            final Event job = (Event) event.getProperty(JobUtil.PROPERTY_NOTIFICATION_JOB);
+                            final String id = (String)job.getProperty(JobUtil.PROPERTY_JOB_NAME);
+                            started.add(id);
+                        }
+                    }
+                }));
+        jeh.handleEvent(getJobEvent(null, "1", "true"));
+        jeh.handleEvent(getJobEvent(null, "2", "true"));
+        jeh.handleEvent(getJobEvent(null, "3", "true"));
+        jeh.handleEvent(getJobEvent(null, "4", "true"));
+        jeh.handleEvent(getJobEvent(null, "5", "true"));
+        int count = 0;
+        final long startTime = System.currentTimeMillis();
+        do {
+            count = finished.size() + cancelled.size();
+            // after 25 seconds we cancel the test
+            if ( System.currentTimeMillis() - startTime > 25000 ) {
+                throw new Exception("Timeout during notification test.");
+            }
+        } while ( count < 5 || started.size() < 10 );
+        assertEquals("Finished count", 4, finished.size());
+        assertEquals("Cancelled count", 1, cancelled.size());
+        assertEquals("Started count", 10, started.size());
+        assertEquals("Failed count", 5, failed.size());
+    }
+
+    private void writeEvent(final Calendar finished, final String name) throws Exception {
+        final Node eventNode = RepositoryTestUtil.getAdminSession().getNode(REPO_PATH).addNode(name, JCRHelper.JOB_NODE_TYPE);
+        eventNode.setProperty(JCRHelper.NODE_PROPERTY_TOPIC, "test");
+        eventNode.setProperty(JobUtil.PROPERTY_JOB_TOPIC, "test");
+        eventNode.setProperty(JCRHelper.NODE_PROPERTY_CREATED, Calendar.getInstance());
+        eventNode.setProperty(JCRHelper.NODE_PROPERTY_APPLICATION, Environment.APPLICATION_ID);
+        if ( finished != null ) {
+            eventNode.setProperty(JCRHelper.NODE_PROPERTY_FINISHED, finished);
+        }
+    }
+
+    @org.junit.Test public void testCleanup() throws Exception {
+        final Calendar obsolete = Calendar.getInstance();
+        obsolete.add(Calendar.MINUTE, -10);
+
+        writeEvent(obsolete, "1");
+        writeEvent(obsolete, "2");
+        writeEvent(obsolete, "3");
+        writeEvent(obsolete, "4");
+
+        final Calendar future = Calendar.getInstance();
+        future.add(Calendar.MINUTE, +10);
+
+        writeEvent(future, "5");
+        writeEvent(future, "6");
+        writeEvent(null, "7");
+        writeEvent(null, "8");
+
+        RepositoryTestUtil.getAdminSession().save();
+        assertEquals(obsolete, RepositoryTestUtil.getAdminSession().getNode(REPO_PATH).getNode("1").getProperty(JCRHelper.NODE_PROPERTY_FINISHED).getDate());
+        assertTrue(RepositoryTestUtil.getAdminSession().getNode(REPO_PATH).hasNode("2"));
+        assertTrue(RepositoryTestUtil.getAdminSession().getNode(REPO_PATH).hasNode("3"));
+        assertTrue(RepositoryTestUtil.getAdminSession().getNode(REPO_PATH).hasNode("4"));
+        assertTrue(RepositoryTestUtil.getAdminSession().getNode(REPO_PATH).hasNode("5"));
+        assertTrue(RepositoryTestUtil.getAdminSession().getNode(REPO_PATH).hasNode("6"));
+        assertTrue(RepositoryTestUtil.getAdminSession().getNode(REPO_PATH).hasNode("7"));
+        assertTrue(RepositoryTestUtil.getAdminSession().getNode(REPO_PATH).hasNode("8"));
+
+        handler.run();
+
+        assertFalse(RepositoryTestUtil.getAdminSession().getNode(REPO_PATH).hasNode("1"));
+        assertFalse(RepositoryTestUtil.getAdminSession().getNode(REPO_PATH).hasNode("2"));
+        assertFalse(RepositoryTestUtil.getAdminSession().getNode(REPO_PATH).hasNode("3"));
+        assertFalse(RepositoryTestUtil.getAdminSession().getNode(REPO_PATH).hasNode("4"));
+        assertTrue(RepositoryTestUtil.getAdminSession().getNode(REPO_PATH).hasNode("5"));
+        assertTrue(RepositoryTestUtil.getAdminSession().getNode(REPO_PATH).hasNode("6"));
+        assertTrue(RepositoryTestUtil.getAdminSession().getNode(REPO_PATH).hasNode("7"));
+        assertTrue(RepositoryTestUtil.getAdminSession().getNode(REPO_PATH).hasNode("8"));
+    }
+
+    @org.junit.Test public void testLoad() throws Throwable {
+        final List<Integer> retryCountList = new ArrayList<Integer>();
+        final PersistenceHandler jeh = this.handler;
+        final Barrier cb = new Barrier(2);
+        final EventAdmin ea = new SimpleEventAdmin(new String[] {"sling/test"},
+                new EventHandler[] {
+                    new EventHandler() {
+                        int retryCount;
+                        public void handleEvent(Event event) {
+                            retryCountList.add(retryCount);
+                            JobUtil.acknowledgeJob(event);
+                            if ( retryCount == 0 ) {
+                                JobUtil.rescheduleJob(event);
+                            } else {
+                                JobUtil.finishedJob(event);
+                            }
+                            retryCount++;
+                            cb.block();
+                        }
+                    }
+                });
+        setEventAdmin(ea);
+        jeh.handleEvent(getJobEvent(null, null, null));
+        assertTrue("No event received in the given time.", cb.block(5));
+        cb.reset();
+        this.deactivate();
+        assertEquals("Unexpected number of retries", 1, retryCountList.size());
+        Thread.sleep(3000);
+        assertEquals("Unexpected number of retries", 1, retryCountList.size());
+        this.activate(ea);
+        // the job is retried after loading, so we wait again
+        assertTrue("No event received in the given time.", cb.block(5));
+        cb.reset();
+        assertFalse("Unexpected event received in the given time.", cb.block(5));
+        assertEquals("Unexpected number of retries", 2, retryCountList.size());
+    }
+
+    @org.junit.Test public void testRunLocal() throws Throwable {
+        final List<Integer> retryCountList = new ArrayList<Integer>();
+        final List<String> sessionPath = new ArrayList<String>();
+        PersistenceHandler jeh = this.handler;
+        final Barrier cb = new Barrier(2);
+        final EventAdmin ea = new SimpleEventAdmin(new String[] {"sling/test"},
+                new EventHandler[] {
+                    new EventHandler() {
+                        int retryCount;
+                        public void handleEvent(Event event) {
+                            retryCountList.add(retryCount);
+                            JobUtil.acknowledgeJob(event);
+                            if ( retryCount == 0 || retryCount == 1) {
+                                // get the job node from the context
+                                sessionPath.add((String)event.getProperty(JobUtil.JOB_ID));
+                                JobUtil.rescheduleJob(event);
+                            } else {
+                                JobUtil.finishedJob(event);
+                            }
+                            retryCount++;
+                            cb.block();
+                        }
+                    }
+                });
+        setEventAdmin(ea);
+        // first test: local event and we change the application id
+        jeh.handleEvent(getJobEvent(null, null, null, true));
+        assertTrue("No event received in the given time.", cb.block(5));
+        cb.reset();
+        this.deactivate();
+        assertEquals("Unexpected number of retries", 1, retryCountList.size());
+        Thread.sleep(3000);
+        assertEquals("Unexpected number of retries", 1, retryCountList.size());
+        assertEquals("Unexpected number of paths", 1, sessionPath.size());
+        // change app id
+        final String nodePath = REPO_PATH + '/' + sessionPath.get(0);
+        session.getNode(nodePath).setProperty(JCRHelper.NODE_PROPERTY_APPLICATION, "unknown");
+        session.save();
+
+        this.activate(ea);
+        jeh = this.handler;
+        // the job is not retried after loading, so we wait again
+        assertFalse("Unexpected event received in the given time.", cb.block(5));
+        cb.reset();
+        assertEquals("Unexpected number of retries", 1, retryCountList.size());
+
+        // second test: local event and we don't change the application id
+        jeh.handleEvent(getJobEvent(null, null, null, true));
+        assertTrue("No event received in the given time.", cb.block(5));
+        cb.reset();
+        this.deactivate();
+        assertEquals("Unexpected number of retries", 2, retryCountList.size());
+        Thread.sleep(3000);
+        assertEquals("Unexpected number of retries", 2, retryCountList.size());
+        assertEquals("Unexpected number of paths", 2, sessionPath.size());
+
+        this.activate(ea);
+        // the job is retried after loading, so we wait again
+        assertTrue("No event received in the given time.", cb.block(5));
+        cb.reset();
+        assertFalse("Unexpected event received in the given time.", cb.block(5));
+        cb.reset();
+        assertEquals("Unexpected number of retries", 3, retryCountList.size());
+    }
+}

Propchange: sling/branches/eventing-3.0/src/test/java/org/apache/sling/event/impl/jobs/JobEventHandlerTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/branches/eventing-3.0/src/test/java/org/apache/sling/event/impl/jobs/JobEventHandlerTest.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Propchange: sling/branches/eventing-3.0/src/test/java/org/apache/sling/event/impl/jobs/JobEventHandlerTest.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/branches/eventing-3.0/src/test/java/org/apache/sling/event/impl/jobs/StatisticsImplTest.java
URL: http://svn.apache.org/viewvc/sling/branches/eventing-3.0/src/test/java/org/apache/sling/event/impl/jobs/StatisticsImplTest.java?rev=1021247&view=auto
==============================================================================
--- sling/branches/eventing-3.0/src/test/java/org/apache/sling/event/impl/jobs/StatisticsImplTest.java (added)
+++ sling/branches/eventing-3.0/src/test/java/org/apache/sling/event/impl/jobs/StatisticsImplTest.java Mon Oct 11 06:54:12 2010
@@ -0,0 +1,264 @@
+/*
+ * 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.event.impl.jobs;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+public class StatisticsImplTest {
+
+    protected StatisticsImpl stat;
+
+    static long START_TIME = System.currentTimeMillis();
+
+    @org.junit.Before public void setup() {
+        this.stat = new StatisticsImpl();
+    }
+
+    @org.junit.Test public void testInitial() {
+        assertTrue(this.stat.getStartTime() >= START_TIME);
+        assertEquals(0, this.stat.getAverageProcessingTime());
+        assertEquals(0, this.stat.getAverageWaitingTime());
+        assertEquals(0, this.stat.getNumberOfActiveJobs());
+        assertEquals(0, this.stat.getNumberOfCancelledJobs());
+        assertEquals(0, this.stat.getNumberOfFailedJobs());
+        assertEquals(0, this.stat.getNumberOfFinishedJobs());
+        assertEquals(0, this.stat.getNumberOfJobs());
+        assertEquals(0, this.stat.getNumberOfProcessedJobs());
+        assertEquals(0, this.stat.getNumberOfQueuedJobs());
+        assertEquals(-1, this.stat.getLastActivatedJobTime());
+        assertEquals(-1, this.stat.getLastFinishedJobTime());
+    }
+
+    @org.junit.Test public void testIncDecQueued() {
+        this.stat.incQueued();
+        assertTrue(this.stat.getStartTime() >= START_TIME);
+        assertEquals(0, this.stat.getAverageProcessingTime());
+        assertEquals(0, this.stat.getAverageWaitingTime());
+        assertEquals(0, this.stat.getNumberOfActiveJobs());
+        assertEquals(0, this.stat.getNumberOfCancelledJobs());
+        assertEquals(0, this.stat.getNumberOfFailedJobs());
+        assertEquals(0, this.stat.getNumberOfFinishedJobs());
+        assertEquals(1, this.stat.getNumberOfJobs());
+        assertEquals(0, this.stat.getNumberOfProcessedJobs());
+        assertEquals(1, this.stat.getNumberOfQueuedJobs());
+        assertEquals(-1, this.stat.getLastActivatedJobTime());
+        assertEquals(-1, this.stat.getLastFinishedJobTime());
+
+        this.stat.incQueued();
+        assertTrue(this.stat.getStartTime() >= START_TIME);
+        assertEquals(0, this.stat.getAverageProcessingTime());
+        assertEquals(0, this.stat.getAverageWaitingTime());
+        assertEquals(0, this.stat.getNumberOfActiveJobs());
+        assertEquals(0, this.stat.getNumberOfCancelledJobs());
+        assertEquals(0, this.stat.getNumberOfFailedJobs());
+        assertEquals(0, this.stat.getNumberOfFinishedJobs());
+        assertEquals(2, this.stat.getNumberOfJobs());
+        assertEquals(0, this.stat.getNumberOfProcessedJobs());
+        assertEquals(2, this.stat.getNumberOfQueuedJobs());
+        assertEquals(-1, this.stat.getLastActivatedJobTime());
+        assertEquals(-1, this.stat.getLastFinishedJobTime());
+
+        this.stat.decQueued();
+        assertTrue(this.stat.getStartTime() >= START_TIME);
+        assertEquals(0, this.stat.getAverageProcessingTime());
+        assertEquals(0, this.stat.getAverageWaitingTime());
+        assertEquals(0, this.stat.getNumberOfActiveJobs());
+        assertEquals(0, this.stat.getNumberOfCancelledJobs());
+        assertEquals(0, this.stat.getNumberOfFailedJobs());
+        assertEquals(0, this.stat.getNumberOfFinishedJobs());
+        assertEquals(1, this.stat.getNumberOfJobs());
+        assertEquals(0, this.stat.getNumberOfProcessedJobs());
+        assertEquals(1, this.stat.getNumberOfQueuedJobs());
+        assertEquals(-1, this.stat.getLastActivatedJobTime());
+        assertEquals(-1, this.stat.getLastFinishedJobTime());
+    }
+
+    @org.junit.Test public void testFinished() {
+        long now = System.currentTimeMillis();
+        this.stat.incQueued();
+        this.stat.addActive(100);
+        this.stat.finishedJob(200);
+        this.stat.incQueued();
+        this.stat.addActive(300);
+        this.stat.finishedJob(800);
+
+        assertTrue(this.stat.getStartTime() >= START_TIME);
+        assertEquals(500, this.stat.getAverageProcessingTime());
+        assertEquals(200, this.stat.getAverageWaitingTime());
+        assertEquals(0, this.stat.getNumberOfActiveJobs());
+        assertEquals(0, this.stat.getNumberOfCancelledJobs());
+        assertEquals(0, this.stat.getNumberOfFailedJobs());
+        assertEquals(2, this.stat.getNumberOfFinishedJobs());
+        assertEquals(0, this.stat.getNumberOfJobs());
+        assertEquals(2, this.stat.getNumberOfProcessedJobs());
+        assertEquals(0, this.stat.getNumberOfQueuedJobs());
+        assertTrue(this.stat.getLastActivatedJobTime() >= now);
+        assertTrue(this.stat.getLastFinishedJobTime() >= now);
+
+        now = System.currentTimeMillis();
+        this.stat.incQueued();
+        this.stat.addActive(200);
+        assertTrue(this.stat.getStartTime() >= START_TIME);
+        assertEquals(500, this.stat.getAverageProcessingTime());
+        assertEquals(200, this.stat.getAverageWaitingTime());
+        assertEquals(1, this.stat.getNumberOfActiveJobs());
+        assertEquals(0, this.stat.getNumberOfCancelledJobs());
+        assertEquals(0, this.stat.getNumberOfFailedJobs());
+        assertEquals(2, this.stat.getNumberOfFinishedJobs());
+        assertEquals(1, this.stat.getNumberOfJobs());
+        assertEquals(2, this.stat.getNumberOfProcessedJobs());
+        assertEquals(0, this.stat.getNumberOfQueuedJobs());
+        assertTrue(this.stat.getLastActivatedJobTime() >= now);
+        assertTrue(this.stat.getLastFinishedJobTime() <= now);
+
+        now = System.currentTimeMillis();
+        this.stat.finishedJob(200);
+        assertTrue(this.stat.getStartTime() >= START_TIME);
+        assertEquals(400, this.stat.getAverageProcessingTime());
+        assertEquals(200, this.stat.getAverageWaitingTime());
+        assertEquals(0, this.stat.getNumberOfActiveJobs());
+        assertEquals(0, this.stat.getNumberOfCancelledJobs());
+        assertEquals(0, this.stat.getNumberOfFailedJobs());
+        assertEquals(3, this.stat.getNumberOfFinishedJobs());
+        assertEquals(0, this.stat.getNumberOfJobs());
+        assertEquals(3, this.stat.getNumberOfProcessedJobs());
+        assertEquals(0, this.stat.getNumberOfQueuedJobs());
+        assertTrue(this.stat.getLastActivatedJobTime() <= now);
+        assertTrue(this.stat.getLastFinishedJobTime() >= now);
+    }
+
+    @org.junit.Test public void testFailAndCancel() {
+        // we start with the results from the previous test!
+        this.testFinished();
+
+        long now = System.currentTimeMillis();
+        this.stat.incQueued();
+        this.stat.addActive(200);
+        this.stat.failedJob();
+        assertTrue(this.stat.getStartTime() >= START_TIME);
+        assertEquals(400, this.stat.getAverageProcessingTime());
+        assertEquals(200, this.stat.getAverageWaitingTime());
+        assertEquals(0, this.stat.getNumberOfActiveJobs());
+        assertEquals(0, this.stat.getNumberOfCancelledJobs());
+        assertEquals(1, this.stat.getNumberOfFailedJobs());
+        assertEquals(3, this.stat.getNumberOfFinishedJobs());
+        assertEquals(1, this.stat.getNumberOfJobs());
+        assertEquals(4, this.stat.getNumberOfProcessedJobs());
+        assertEquals(1, this.stat.getNumberOfQueuedJobs());
+        assertTrue(this.stat.getLastActivatedJobTime() >= now);
+        assertTrue(this.stat.getLastFinishedJobTime() <= now);
+
+        now = System.currentTimeMillis();
+        this.stat.addActive(200);
+        this.stat.cancelledJob();
+        assertTrue(this.stat.getStartTime() >= START_TIME);
+        assertEquals(400, this.stat.getAverageProcessingTime());
+        assertEquals(200, this.stat.getAverageWaitingTime());
+        assertEquals(0, this.stat.getNumberOfActiveJobs());
+        assertEquals(1, this.stat.getNumberOfCancelledJobs());
+        assertEquals(1, this.stat.getNumberOfFailedJobs());
+        assertEquals(3, this.stat.getNumberOfFinishedJobs());
+        assertEquals(0, this.stat.getNumberOfJobs());
+        assertEquals(5, this.stat.getNumberOfProcessedJobs());
+        assertEquals(0, this.stat.getNumberOfQueuedJobs());
+        assertTrue(this.stat.getLastActivatedJobTime() >= now);
+        assertTrue(this.stat.getLastFinishedJobTime() <= now);
+    }
+
+    @org.junit.Test public void  testMisc() {
+        final StatisticsImpl stat2 = new StatisticsImpl(200);
+        assertEquals(200, stat2.getStartTime());
+
+        // update stat
+        this.testFailAndCancel();
+
+        long now = System.currentTimeMillis();
+        final StatisticsImpl copy = this.stat.copy();
+        assertTrue(copy.getStartTime() >= now);
+        assertEquals(400, copy.getAverageProcessingTime());
+        assertEquals(200, copy.getAverageWaitingTime());
+        assertEquals(0, copy.getNumberOfActiveJobs());
+        assertEquals(1, copy.getNumberOfCancelledJobs());
+        assertEquals(1, copy.getNumberOfFailedJobs());
+        assertEquals(3, copy.getNumberOfFinishedJobs());
+        assertEquals(0, copy.getNumberOfJobs());
+        assertEquals(5, copy.getNumberOfProcessedJobs());
+        assertEquals(0, copy.getNumberOfQueuedJobs());
+        assertTrue(copy.getLastActivatedJobTime() >= now);
+        assertTrue(copy.getLastFinishedJobTime() <= now);
+
+        now = System.currentTimeMillis();
+        this.stat.incQueued();
+        this.stat.addActive(200);
+        this.stat.finishedJob(400);
+        assertEquals(400, this.stat.getAverageProcessingTime());
+        assertEquals(200, this.stat.getAverageWaitingTime());
+        assertEquals(0, this.stat.getNumberOfActiveJobs());
+        assertEquals(1, this.stat.getNumberOfCancelledJobs());
+        assertEquals(1, this.stat.getNumberOfFailedJobs());
+        assertEquals(4, this.stat.getNumberOfFinishedJobs());
+        assertEquals(0, this.stat.getNumberOfJobs());
+        assertEquals(6, this.stat.getNumberOfProcessedJobs());
+        assertEquals(0, this.stat.getNumberOfQueuedJobs());
+        assertTrue(this.stat.getLastActivatedJobTime() >= now);
+        assertTrue(this.stat.getLastFinishedJobTime() >= now);
+
+        copy.add(this.stat);
+        assertTrue(copy.getStartTime() <= now);
+        assertEquals(400, copy.getAverageProcessingTime());
+        assertEquals(200, copy.getAverageWaitingTime());
+        assertEquals(0, copy.getNumberOfActiveJobs());
+        assertEquals(2, copy.getNumberOfCancelledJobs());
+        assertEquals(2, copy.getNumberOfFailedJobs());
+        assertEquals(7, copy.getNumberOfFinishedJobs());
+        assertEquals(0, copy.getNumberOfJobs());
+        assertEquals(11, copy.getNumberOfProcessedJobs());
+        assertEquals(0, copy.getNumberOfQueuedJobs());
+        assertTrue(copy.getLastActivatedJobTime() >= now);
+        assertTrue(copy.getLastFinishedJobTime() >= now);
+
+        this.stat.incQueued();
+        this.stat.incQueued();
+        assertEquals(400, this.stat.getAverageProcessingTime());
+        assertEquals(200, this.stat.getAverageWaitingTime());
+        assertEquals(0, this.stat.getNumberOfActiveJobs());
+        assertEquals(1, this.stat.getNumberOfCancelledJobs());
+        assertEquals(1, this.stat.getNumberOfFailedJobs());
+        assertEquals(4, this.stat.getNumberOfFinishedJobs());
+        assertEquals(2, this.stat.getNumberOfJobs());
+        assertEquals(6, this.stat.getNumberOfProcessedJobs());
+        assertEquals(2, this.stat.getNumberOfQueuedJobs());
+        assertTrue(this.stat.getLastActivatedJobTime() >= now);
+        assertTrue(this.stat.getLastFinishedJobTime() >= now);
+
+        this.stat.clearQueued();
+        assertEquals(400, this.stat.getAverageProcessingTime());
+        assertEquals(200, this.stat.getAverageWaitingTime());
+        assertEquals(0, this.stat.getNumberOfActiveJobs());
+        assertEquals(1, this.stat.getNumberOfCancelledJobs());
+        assertEquals(1, this.stat.getNumberOfFailedJobs());
+        assertEquals(4, this.stat.getNumberOfFinishedJobs());
+        assertEquals(0, this.stat.getNumberOfJobs());
+        assertEquals(6, this.stat.getNumberOfProcessedJobs());
+        assertEquals(0, this.stat.getNumberOfQueuedJobs());
+        assertTrue(this.stat.getLastActivatedJobTime() >= now);
+        assertTrue(this.stat.getLastFinishedJobTime() >= now);
+    }
+}

Propchange: sling/branches/eventing-3.0/src/test/java/org/apache/sling/event/impl/jobs/StatisticsImplTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/branches/eventing-3.0/src/test/java/org/apache/sling/event/impl/jobs/StatisticsImplTest.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Propchange: sling/branches/eventing-3.0/src/test/java/org/apache/sling/event/impl/jobs/StatisticsImplTest.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/branches/eventing-3.0/src/test/java/org/apache/sling/event/impl/jobs/config/InternalQueueConfigurationTest.java
URL: http://svn.apache.org/viewvc/sling/branches/eventing-3.0/src/test/java/org/apache/sling/event/impl/jobs/config/InternalQueueConfigurationTest.java?rev=1021247&view=auto
==============================================================================
--- sling/branches/eventing-3.0/src/test/java/org/apache/sling/event/impl/jobs/config/InternalQueueConfigurationTest.java (added)
+++ sling/branches/eventing-3.0/src/test/java/org/apache/sling/event/impl/jobs/config/InternalQueueConfigurationTest.java Mon Oct 11 06:54:12 2010
@@ -0,0 +1,132 @@
+/*
+ * 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.event.impl.jobs.config;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Map;
+
+import org.apache.sling.event.impl.jobs.JobEvent;
+import org.apache.sling.event.jobs.JobUtil;
+import org.osgi.service.event.Event;
+
+public class InternalQueueConfigurationTest {
+
+    private JobEvent getJobEvent(final String topic) {
+        final Dictionary<String, Object> dict = new Hashtable<String, Object>();
+        dict.put(JobUtil.PROPERTY_JOB_TOPIC, topic);
+        return new JobEvent(new Event(topic, dict), topic) {
+            public void unlock() {
+                // dummy
+            }
+            public boolean reschedule() {
+                return false;
+            }
+            public boolean remove() {
+                return false;
+            }
+            public boolean lock() {
+                return false;
+            }
+            public void finished() {
+                // dummy
+            }
+        };
+    }
+    @org.junit.Test public void testMaxParallel() {
+        final Map<String, Object> p = new HashMap<String, Object>();
+        p.put(ConfigurationConstants.PROP_MAX_PARALLEL, -1);
+
+        InternalQueueConfiguration c = InternalQueueConfiguration.fromConfiguration(p);
+        assertEquals(Runtime.getRuntime().availableProcessors(), c.getMaxParallel());
+    }
+
+    @org.junit.Test public void testTopicMatchersDot() {
+        final Map<String, Object> p = new HashMap<String, Object>();
+        p.put(ConfigurationConstants.PROP_TOPICS, new String[] {"a."});
+        p.put(ConfigurationConstants.PROP_NAME, "test");
+
+        InternalQueueConfiguration c = InternalQueueConfiguration.fromConfiguration(p);
+        assertTrue(c.isValid());
+        assertTrue(c.match(getJobEvent("a/b")));
+        assertTrue(c.match(getJobEvent("a/c")));
+        assertFalse(c.match(getJobEvent("a")));
+        assertFalse(c.match(getJobEvent("a/b/c")));
+        assertFalse(c.match(getJobEvent("t")));
+        assertFalse(c.match(getJobEvent("t/x")));
+    }
+
+    @org.junit.Test public void testTopicMatchersStart() {
+        final Map<String, Object> p = new HashMap<String, Object>();
+        p.put(ConfigurationConstants.PROP_TOPICS, new String[] {"a*"});
+        p.put(ConfigurationConstants.PROP_NAME, "test");
+
+        InternalQueueConfiguration c = InternalQueueConfiguration.fromConfiguration(p);
+        assertTrue(c.isValid());
+        assertTrue(c.match(getJobEvent("a/b")));
+        assertTrue(c.match(getJobEvent("a/c")));
+        assertFalse(c.match(getJobEvent("a")));
+        assertTrue(c.match(getJobEvent("a/b/c")));
+        assertFalse(c.match(getJobEvent("t")));
+        assertFalse(c.match(getJobEvent("t/x")));
+    }
+
+    @org.junit.Test public void testTopicMatchers() {
+        final Map<String, Object> p = new HashMap<String, Object>();
+        p.put(ConfigurationConstants.PROP_TOPICS, new String[] {"a"});
+        p.put(ConfigurationConstants.PROP_NAME, "test");
+
+        InternalQueueConfiguration c = InternalQueueConfiguration.fromConfiguration(p);
+        assertTrue(c.isValid());
+        assertFalse(c.match(getJobEvent("a/b")));
+        assertFalse(c.match(getJobEvent("a/c")));
+        assertTrue(c.match(getJobEvent("a")));
+        assertFalse(c.match(getJobEvent("a/b/c")));
+        assertFalse(c.match(getJobEvent("t")));
+        assertFalse(c.match(getJobEvent("t/x")));
+    }
+
+    @org.junit.Test public void testTopicMatcherAndReplacement() {
+        final Map<String, Object> p = new HashMap<String, Object>();
+        p.put(ConfigurationConstants.PROP_TOPICS, new String[] {"a."});
+        p.put(ConfigurationConstants.PROP_NAME, "test-queue-{0}");
+
+        InternalQueueConfiguration c = InternalQueueConfiguration.fromConfiguration(p);
+        assertTrue(c.isValid());
+        final JobEvent b = getJobEvent("a/b");
+        assertTrue(c.match(b));
+        assertEquals("test-queue-b", b.queueName);
+        final JobEvent d = getJobEvent("a/d");
+        assertTrue(c.match(d));
+        assertEquals("test-queue-d", d.queueName);
+    }
+
+    @org.junit.Test public void testNoTopicMatchers() {
+        final Map<String, Object> p = new HashMap<String, Object>();
+        p.put(ConfigurationConstants.PROP_NAME, "test");
+
+        InternalQueueConfiguration c = InternalQueueConfiguration.fromConfiguration(p);
+        assertFalse(c.isValid());
+    }
+}

Propchange: sling/branches/eventing-3.0/src/test/java/org/apache/sling/event/impl/jobs/config/InternalQueueConfigurationTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/branches/eventing-3.0/src/test/java/org/apache/sling/event/impl/jobs/config/InternalQueueConfigurationTest.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Propchange: sling/branches/eventing-3.0/src/test/java/org/apache/sling/event/impl/jobs/config/InternalQueueConfigurationTest.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain