Author: rombert Date: Tue Jul 16 15:59:57 2013 New Revision: 1503771 URL: http://svn.apache.org/r1503771 Log: SLING-2969 - IT failure: ClassloadingTest.testSimpleClassloading fails intermitently
Try to stabilize tests by using conditions and allowing for larger timeouts. Added: sling/trunk/bundles/extensions/event/src/test/java/org/apache/sling/event/it/Conditions.java (with props) Modified: sling/trunk/bundles/extensions/event/pom.xml sling/trunk/bundles/extensions/event/src/test/java/org/apache/sling/event/it/ClassloadingTest.java Modified: sling/trunk/bundles/extensions/event/pom.xml URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/event/pom.xml?rev=1503771&r1=1503770&r2=1503771&view=diff ============================================================================== --- sling/trunk/bundles/extensions/event/pom.xml (original) +++ sling/trunk/bundles/extensions/event/pom.xml Tue Jul 16 15:59:57 2013 @@ -266,6 +266,13 @@ <scope>test</scope> </dependency> + <dependency> + <groupId>org.apache.sling</groupId> + <artifactId>org.apache.sling.testing.tools</artifactId> + <version>1.0.2</version> + <scope>test</scope> + <type>bundle</type> + </dependency> <dependency> <groupId>org.ops4j.pax.exam</groupId> Modified: sling/trunk/bundles/extensions/event/src/test/java/org/apache/sling/event/it/ClassloadingTest.java URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/event/src/test/java/org/apache/sling/event/it/ClassloadingTest.java?rev=1503771&r1=1503770&r2=1503771&view=diff ============================================================================== --- sling/trunk/bundles/extensions/event/src/test/java/org/apache/sling/event/it/ClassloadingTest.java (original) +++ sling/trunk/bundles/extensions/event/src/test/java/org/apache/sling/event/it/ClassloadingTest.java Tue Jul 16 15:59:57 2013 @@ -39,8 +39,10 @@ import org.apache.sling.event.jobs.JobMa import org.apache.sling.event.jobs.JobUtil; import org.apache.sling.event.jobs.QueueConfiguration; import org.apache.sling.event.jobs.consumer.JobConsumer; +import org.apache.sling.testing.tools.retry.RetryLoop; import org.junit.After; import org.junit.Before; +import org.junit.Test; import org.junit.runner.RunWith; import org.ops4j.pax.exam.junit.ExamReactorStrategy; import org.ops4j.pax.exam.junit.JUnit4TestRunner; @@ -53,6 +55,9 @@ import org.osgi.service.event.EventHandl @ExamReactorStrategy(AllConfinedStagedReactorFactory.class) public class ClassloadingTest extends AbstractJobHandlingTest { + private static final int CONDITION_INTERVAL_MILLIS = 50; + private static final int CONDITION_TIMEOUT_SECONDS = 5; + private static final String QUEUE_NAME = "cltest"; private static final String TOPIC = "sling/cltest"; @@ -82,15 +87,15 @@ public class ClassloadingTest extends Ab } - @org.junit.Test public void testSimpleClassloading() throws Exception { - final AtomicInteger count = new AtomicInteger(0); + @Test + public void testSimpleClassloading() throws Exception { + final AtomicInteger processedJobsCount = new AtomicInteger(0); final List<Event> finishedEvents = Collections.synchronizedList(new ArrayList<Event>()); final ServiceRegistration jcReg = this.registerJobConsumer(TOPIC, new JobConsumer() { - @Override public JobResult process(Job job) { - count.incrementAndGet(); + processedJobsCount.incrementAndGet(); return JobResult.OK; } }); @@ -123,16 +128,25 @@ public class ClassloadingTest extends Ab jobManager.addJob(TOPIC, null, props); - while ( finishedEvents.size() < 1 ) { - // we wait a little bit - Thread.sleep(100); - } - Thread.sleep(100); + new RetryLoop(Conditions.collectionIsNotEmptyCondition(finishedEvents, + "Waiting for finishedEvents to have at least one element"), 5, 50); // no jobs queued, none processed and no available - assertEquals(0, jobManager.getStatistics().getNumberOfQueuedJobs()); - assertEquals(1, count.get()); - assertEquals(0, jobManager.findJobs(JobManager.QueryType.ALL, TOPIC, -1, (Map<String, Object>[])null).size()); + new RetryLoop(new RetryLoop.Condition() { + + @Override + public String getDescription() { + return "Waiting for job to be processed"; + } + + @Override + public boolean isTrue() throws Exception { + return jobManager.getStatistics().getNumberOfQueuedJobs() == 0 + && processedJobsCount.get() == 0 + && jobManager.findJobs(JobManager.QueryType.ALL, TOPIC, -1, (Map<String, Object>[]) null) + .size() == 0; + } + }, CONDITION_TIMEOUT_SECONDS, CONDITION_INTERVAL_MILLIS); final String jobTopic = (String)finishedEvents.get(0).getProperty(JobUtil.NOTIFICATION_PROPERTY_JOB_TOPIC); assertNotNull(jobTopic); @@ -147,15 +161,16 @@ public class ClassloadingTest extends Ab } } - @org.junit.Test public void testFailedClassloading() throws Exception { - final AtomicInteger count = new AtomicInteger(0); + @Test + public void testFailedClassloading() throws Exception { + final AtomicInteger failedJobsCount = new AtomicInteger(0); final List<Event> finishedEvents = Collections.synchronizedList(new ArrayList<Event>()); final ServiceRegistration jcReg = this.registerJobConsumer(TOPIC + "/failed", new JobConsumer() { @Override public JobResult process(Job job) { - count.incrementAndGet(); + failedJobsCount.incrementAndGet(); return JobResult.OK; } }); @@ -180,14 +195,24 @@ public class ClassloadingTest extends Ab final String id = jobManager.addJob(TOPIC + "/failed", null, props).getId(); - // we simply wait a little bit - sleep(2000); - - assertEquals(0, count.get()); - assertEquals(0, finishedEvents.size()); - assertEquals(1, jobManager.findJobs(JobManager.QueryType.ALL, TOPIC + "/failed", -1, (Map<String, Object>[])null).size()); - assertEquals(0, jobManager.getStatistics().getNumberOfQueuedJobs()); - assertEquals(0, jobManager.getStatistics().getNumberOfActiveJobs()); + // wait until the conditions are met + new RetryLoop(new RetryLoop.Condition() { + + @Override + public boolean isTrue() throws Exception { + return failedJobsCount.get() == 0 + && finishedEvents.size() == 0 + && jobManager.findJobs(JobManager.QueryType.ALL, TOPIC + "/failed", -1, + (Map<String, Object>[]) null).size() == 1 + && jobManager.getStatistics().getNumberOfQueuedJobs() == 0 + && jobManager.getStatistics().getNumberOfActiveJobs() == 0; + } + + @Override + public String getDescription() { + return "Waiting for job failure to be recorded"; + } + }, CONDITION_TIMEOUT_SECONDS, CONDITION_INTERVAL_MILLIS); jobManager.removeJobById(id); assertEquals(0, jobManager.findJobs(JobManager.QueryType.ALL, TOPIC + "/failed", -1, (Map<String, Object>[])null).size()); Added: sling/trunk/bundles/extensions/event/src/test/java/org/apache/sling/event/it/Conditions.java URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/event/src/test/java/org/apache/sling/event/it/Conditions.java?rev=1503771&view=auto ============================================================================== --- sling/trunk/bundles/extensions/event/src/test/java/org/apache/sling/event/it/Conditions.java (added) +++ sling/trunk/bundles/extensions/event/src/test/java/org/apache/sling/event/it/Conditions.java Tue Jul 16 15:59:57 2013 @@ -0,0 +1,65 @@ +/* + * 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.it; + +import java.util.Collection; + +import org.apache.sling.testing.tools.retry.RetryLoop.Condition; + +/** + * The <tt>Conditions</tt> class references commonly-used conditions + * + */ +public abstract class Conditions { + + /** + * Creates a condition which expects the collection to not be empty + * + * @param collection the collection to verify + * @param description the description to use for the condition + * @return the condition + */ + public static Condition collectionIsNotEmptyCondition(final Collection<?> collection, String description) { + return new DescribedCondition(description) { + @Override + public boolean isTrue() throws Exception { + return collection.size() > 0; + } + }; + } + + private Conditions() { + // prevent instantiation + } + + static abstract class DescribedCondition implements Condition { + + private final String description; + + public DescribedCondition(String description) { + this.description = description; + } + + @Override + public String getDescription() { + return description; + } + + } +} Propchange: sling/trunk/bundles/extensions/event/src/test/java/org/apache/sling/event/it/Conditions.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: sling/trunk/bundles/extensions/event/src/test/java/org/apache/sling/event/it/Conditions.java ------------------------------------------------------------------------------ svn:keywords = Author Date Id Revision Rev URL