diff --git a/.travis.yml b/.travis.yml index 420cb1783..b2dfe28f4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,10 +7,7 @@ jdk: env: # Travis has slow VMs? -- blitzerThreads=1 blitzerActions=1 blitzerTimeout=1000 - -secure: "XBIyEF5RxH/zKjh0gle5ce/FRe9pP5b46LXKNOfwlau5QYvn8WXC41Sb6yYC8VW3vI9S930BnVGZONiDXsSWuylLezdu2g88nwJ2CsTxHU0Yg2GAzKwaorBQqyK/6w2foRRXtz69NJccfdIdPuDZSEhJtTKWSmMMQ7U65KH+zzQ=" -secure: "SSlAKOg8QLEAkZX1ehy9c6FR5R6gMzLhc6u2Smq9tm8JsWVz4EtS6NnTQaosthrNEfLJwVVCfmOh2dzvYZfhtbKAUMdkox45tem4+LZfgkSaQAGjSvsC6geioa4Alo6AKyR8foc5Y7P34f9ujYSZHNyRG9F6E0Qq2zj/hzHhstU=" - -after_success: - - mvn deploy --settings settings.xml -DskipTests=true -B + global: + - blitzerThreads=1 blitzerActions=1 blitzerTimeout=1000 + - secure: "XBIyEF5RxH/zKjh0gle5ce/FRe9pP5b46LXKNOfwlau5QYvn8WXC41Sb6yYC8VW3vI9S930BnVGZONiDXsSWuylLezdu2g88nwJ2CsTxHU0Yg2GAzKwaorBQqyK/6w2foRRXtz69NJccfdIdPuDZSEhJtTKWSmMMQ7U65KH+zzQ=" + - secure: "SSlAKOg8QLEAkZX1ehy9c6FR5R6gMzLhc6u2Smq9tm8JsWVz4EtS6NnTQaosthrNEfLJwVVCfmOh2dzvYZfhtbKAUMdkox45tem4+LZfgkSaQAGjSvsC6geioa4Alo6AKyR8foc5Y7P34f9ujYSZHNyRG9F6E0Qq2zj/hzHhstU=" diff --git a/README.md b/README.md index 2971e74df..4af5a7d0d 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,11 @@ [![Build Status](https://travis-ci.org/jmock-developers/jmock-library.svg?branch=jmock2)](https://travis-ci.org/jmock-developers/jmock-library) +# Recent Changes +## 2.9.0 +* Dropped JDK 6 compliance. +* Exposed the InvocationDispatcher so that ThreadingPolicies -Upgrading to 2.8.X -================== +## Upgrading to 2.8.X Are you seeing NPEs? We have had to make a breaking change to `with()`. Tests using `with(any(matcher))` for method signatures that require native types will throw `NullPointerException`. @@ -17,8 +20,7 @@ to the following This is due to a compiler change in Java 1.7. The 2.6.0 release was compiled with Java 1.6 so it did not suffer this problem. -Advantages of jMock 2 over jMock 1 -================================== +# Advantages of jMock 2 over jMock 1 * Uses real method calls, not strings, so you can refactor more easily and autocomplete in the IDE. * Customisation by delegation, not by inheritance. @@ -33,8 +35,7 @@ Advantages of jMock 2 over jMock 1 -How to get up and running -========================= +# How to get up and running ## Automatic Dependency Management @@ -54,16 +55,14 @@ testCompile( Add the `jmock-.jar` to your classpath. (For example: `jmock-2.8.2.jar`.) Also add the integration JAR to your classpath for the test library ou're using. (For example: `jmock-junit4-2.8.2.jar`.) You also need `hamcrest-api-.jar` and `hamcrest-lib-.jar`. -Package Structure -================= +# Package Structure [jMock]() 2 is organised into published and internal packages. We guarantee backwards compatability of types in published packages within the same major version of jMock. There are no guarantees about backward compatability for types in internal packages. Types defined in published packages may themselves define public methods that accept or return types from internal packages or inherit methods from types in internal packages. Such methods have no compatability guarantees and should not be considered as part of the published interface. -Published packages ------------------- +## Published packages ### org.jmock @@ -80,16 +79,14 @@ Convenient classes that implement the APIs in the core, are used by the DSL-sty Classes integrating jMock with different testing APIs, such as JUnit 3.x, JUnit 4.x and TestNG. -Packages of example code ------------------------- +## Packages of example code ### org.jmock.lib.nonstd Lib classes that rely on clever hacks or otherwise cannot be guaranteed to always work in all JVMs. There are no compatability guarantees with these classes. Use at your own risk. -Internal packages ------------------ +## Internal packages ### org.jmock.internal @@ -100,8 +97,7 @@ Internal implementation details Tests for jMock itself -Plug-in Points -============== +## Plug-in Points ### Matcher diff --git a/jmock-example/pom.xml b/jmock-example/pom.xml index e1bdc1787..d8ccb4dc3 100644 --- a/jmock-example/pom.xml +++ b/jmock-example/pom.xml @@ -5,14 +5,14 @@ org.jmock jmock-example - 2.8.4 + 2.9.0-SNAPSHOT jar jMock Examples org.jmock jmock-parent - 2.8.4 + 2.9.0-SNAPSHOT ../pom.xml diff --git a/jmock-junit3/pom.xml b/jmock-junit3/pom.xml index c0cd85498..482f88969 100644 --- a/jmock-junit3/pom.xml +++ b/jmock-junit3/pom.xml @@ -5,7 +5,7 @@ org.jmock jmock-parent - 2.8.4 + 2.9.0-SNAPSHOT jmock-junit3 diff --git a/jmock-junit4/pom.xml b/jmock-junit4/pom.xml index d16e3dd99..c73b8b58e 100644 --- a/jmock-junit4/pom.xml +++ b/jmock-junit4/pom.xml @@ -8,7 +8,7 @@ org.jmock jmock-parent - 2.8.4 + 2.9.0-SNAPSHOT diff --git a/jmock-legacy/pom.xml b/jmock-legacy/pom.xml index e4edaad47..cdd8553b9 100644 --- a/jmock-legacy/pom.xml +++ b/jmock-legacy/pom.xml @@ -8,7 +8,7 @@ org.jmock jmock-parent - 2.8.4 + 2.9.0-SNAPSHOT diff --git a/jmock/pom.xml b/jmock/pom.xml index ee709fba4..1b952e530 100644 --- a/jmock/pom.xml +++ b/jmock/pom.xml @@ -9,7 +9,7 @@ org.jmock jmock-parent - 2.8.4 + 2.9.0-SNAPSHOT ../pom.xml diff --git a/jmock/src/main/java/org/jmock/AbstractExpectations.java b/jmock/src/main/java/org/jmock/AbstractExpectations.java index 1a0584a7a..6f9285c0c 100644 --- a/jmock/src/main/java/org/jmock/AbstractExpectations.java +++ b/jmock/src/main/java/org/jmock/AbstractExpectations.java @@ -4,6 +4,7 @@ import org.hamcrest.Matcher; import org.hamcrest.core.*; import org.jmock.api.Action; +import org.jmock.api.ExpectationCollector; import org.jmock.internal.*; import org.jmock.lib.action.*; import org.jmock.syntax.*; diff --git a/jmock/src/main/java/org/jmock/ExpectationsCreator.java b/jmock/src/main/java/org/jmock/ExpectationsCreator.java index cc91704a9..c7a83abfe 100644 --- a/jmock/src/main/java/org/jmock/ExpectationsCreator.java +++ b/jmock/src/main/java/org/jmock/ExpectationsCreator.java @@ -1,6 +1,5 @@ package org.jmock; -import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; @@ -10,7 +9,6 @@ import org.objectweb.asm.ClassReader; import org.objectweb.asm.ClassWriter; import org.objectweb.asm.FieldVisitor; -import org.objectweb.asm.Label; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; diff --git a/jmock/src/main/java/org/jmock/Mockery.java b/jmock/src/main/java/org/jmock/Mockery.java index a4cdd064e..88f03a5ff 100644 --- a/jmock/src/main/java/org/jmock/Mockery.java +++ b/jmock/src/main/java/org/jmock/Mockery.java @@ -1,20 +1,36 @@ package org.jmock; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + import org.hamcrest.Description; import org.hamcrest.SelfDescribing; -import org.jmock.api.*; -import org.jmock.internal.*; +import org.jmock.api.Expectation; +import org.jmock.api.ExpectationError; +import org.jmock.api.ExpectationErrorTranslator; +import org.jmock.api.Imposteriser; +import org.jmock.api.Invocation; +import org.jmock.api.InvocationDispatcher; +import org.jmock.api.Invokable; +import org.jmock.api.MockObjectNamingScheme; +import org.jmock.api.ThreadingPolicy; +import org.jmock.internal.CaptureControl; +import org.jmock.internal.ExpectationBuilder; +import org.jmock.internal.ExpectationCapture; +import org.jmock.internal.InvocationDiverter; +import org.jmock.internal.InvocationToExpectationTranslator; +import org.jmock.internal.NamedSequence; +import org.jmock.internal.ObjectMethodExpectationBouncer; +import org.jmock.internal.ProxiedObjectIdentity; +import org.jmock.internal.ReturnDefaultValueAction; +import org.jmock.internal.SingleThreadedPolicy; import org.jmock.lib.CamelCaseNamingScheme; import org.jmock.lib.IdentityExpectationErrorTranslator; import org.jmock.lib.JavaReflectionImposteriser; import org.jmock.lib.concurrent.Synchroniser; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.concurrent.CopyOnWriteArrayList; - /** * A Mockery represents the context, or neighbourhood, of the object(s) under test. @@ -37,7 +53,7 @@ public class Mockery implements SelfDescribing { private final Set mockNames = new HashSet(); private final ReturnDefaultValueAction defaultAction = new ReturnDefaultValueAction(imposteriser); private final List actualInvocations = new ArrayList(); - private final InvocationDispatcher dispatcher = new InvocationDispatcher(new CopyOnWriteArrayList(), new CopyOnWriteArrayList()); + private final InvocationDispatcher dispatcher = threadingPolicy.dispatcher(); private Error firstError = null; diff --git a/jmock/src/main/java/org/jmock/internal/ExpectationCollector.java b/jmock/src/main/java/org/jmock/api/ExpectationCollector.java similarity index 56% rename from jmock/src/main/java/org/jmock/internal/ExpectationCollector.java rename to jmock/src/main/java/org/jmock/api/ExpectationCollector.java index 50fca03a0..c6de0e7a0 100644 --- a/jmock/src/main/java/org/jmock/internal/ExpectationCollector.java +++ b/jmock/src/main/java/org/jmock/api/ExpectationCollector.java @@ -1,6 +1,4 @@ -package org.jmock.internal; - -import org.jmock.api.Expectation; +package org.jmock.api; public interface ExpectationCollector { void add(Expectation expectation); diff --git a/jmock/src/main/java/org/jmock/api/InvocationDispatcher.java b/jmock/src/main/java/org/jmock/api/InvocationDispatcher.java new file mode 100644 index 000000000..3427bf1ad --- /dev/null +++ b/jmock/src/main/java/org/jmock/api/InvocationDispatcher.java @@ -0,0 +1,20 @@ +package org.jmock.api; + +import org.hamcrest.Description; +import org.hamcrest.SelfDescribing; +import org.jmock.internal.StateMachine; + +public interface InvocationDispatcher extends SelfDescribing, ExpectationCollector { + + StateMachine newStateMachine(String name); + + void add(Expectation expectation); + + void describeTo(Description description); + + void describeMismatch(Invocation invocation, Description description); + + boolean isSatisfied(); + + Object dispatch(Invocation invocation) throws Throwable; +} \ No newline at end of file diff --git a/jmock/src/main/java/org/jmock/api/ThreadingPolicy.java b/jmock/src/main/java/org/jmock/api/ThreadingPolicy.java index ada69782f..7ed5c02b8 100644 --- a/jmock/src/main/java/org/jmock/api/ThreadingPolicy.java +++ b/jmock/src/main/java/org/jmock/api/ThreadingPolicy.java @@ -1,7 +1,7 @@ package org.jmock.api; -import org.jmock.internal.InvocationDispatcher; - public interface ThreadingPolicy { Invokable synchroniseAccessTo(Invokable mockObject); + + InvocationDispatcher dispatcher(); } diff --git a/jmock/src/main/java/org/jmock/internal/ExpectationBuilder.java b/jmock/src/main/java/org/jmock/internal/ExpectationBuilder.java index a44997fa4..daafab7ef 100644 --- a/jmock/src/main/java/org/jmock/internal/ExpectationBuilder.java +++ b/jmock/src/main/java/org/jmock/internal/ExpectationBuilder.java @@ -1,6 +1,7 @@ package org.jmock.internal; import org.jmock.api.Action; +import org.jmock.api.ExpectationCollector; public interface ExpectationBuilder { void buildExpectations(Action defaultAction, ExpectationCollector collector); diff --git a/jmock/src/main/java/org/jmock/internal/SingleThreadedPolicy.java b/jmock/src/main/java/org/jmock/internal/SingleThreadedPolicy.java index a1192fa75..de8ca81a2 100644 --- a/jmock/src/main/java/org/jmock/internal/SingleThreadedPolicy.java +++ b/jmock/src/main/java/org/jmock/internal/SingleThreadedPolicy.java @@ -3,9 +3,11 @@ import java.util.ConcurrentModificationException; import org.jmock.api.Invocation; +import org.jmock.api.InvocationDispatcher; import org.jmock.api.Invokable; import org.jmock.api.ThreadingPolicy; import org.jmock.lib.concurrent.Synchroniser; +import org.jmock.lib.concurrent.UnsynchronisedInvocationDispatcher; public class SingleThreadedPolicy implements ThreadingPolicy { private final Thread testThread; @@ -34,4 +36,9 @@ private void reportError(String error) { System.err.println(error); throw new ConcurrentModificationException(error); } + + @Override + public InvocationDispatcher dispatcher() { + return new UnsynchronisedInvocationDispatcher(); + } } diff --git a/jmock/src/main/java/org/jmock/lib/concurrent/Synchroniser.java b/jmock/src/main/java/org/jmock/lib/concurrent/Synchroniser.java index 1d35d8d19..fa174b66b 100644 --- a/jmock/src/main/java/org/jmock/lib/concurrent/Synchroniser.java +++ b/jmock/src/main/java/org/jmock/lib/concurrent/Synchroniser.java @@ -5,20 +5,21 @@ import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.TimeoutException; +import org.jmock.api.Expectation; import org.jmock.api.Invocation; +import org.jmock.api.InvocationDispatcher; import org.jmock.api.Invokable; import org.jmock.api.ThreadingPolicy; -import org.jmock.internal.InvocationDispatcher; +import org.jmock.internal.StateMachine; import org.jmock.internal.StatePredicate; import org.jmock.lib.concurrent.internal.FixedTimeout; import org.jmock.lib.concurrent.internal.InfiniteTimeout; import org.jmock.lib.concurrent.internal.Timeout; import org.junit.Assert; - /** - * A ThreadingPolicy that makes the Mockery thread-safe and - * helps tests synchronise with background threads. + * A ThreadingPolicy that makes the Mockery thread-safe and helps tests + * synchronise with background threads. * * @author Nat Pryce * @author olibye @@ -26,51 +27,62 @@ public class Synchroniser implements ThreadingPolicy { private final Object sync = new Object(); private Error firstError = null; - - - /** - * Waits for a StatePredicate to become active. + private InvocationDispatcher invocationDispatcher; + + public Synchroniser() { + invocationDispatcher = new UnsynchronisedInvocationDispatcher( + new CopyOnWriteArrayList(), + new CopyOnWriteArrayList()); + } + + public Synchroniser(InvocationDispatcher dispatcher) { + invocationDispatcher = dispatcher; + } + + /** + * Waits for a StatePredicate to become active. * * Warning: this will wait forever unless the test itself has a timeout. - * - * @param p the StatePredicate to wait for + * + * @param p + * the StatePredicate to wait for * @throws InterruptedException */ public void waitUntil(StatePredicate p) throws InterruptedException { waitUntil(p, new InfiniteTimeout()); } - - /** - * Waits up to a timeout for a StatePredicate to become active. Fails the - * test if the timeout expires. - * - * @param p the StatePredicate to wait for - * @param timeoutMs the timeout in milliseconds + + /** + * Waits up to a timeout for a StatePredicate to become active. Fails the test + * if the timeout expires. + * + * @param p + * the StatePredicate to wait for + * @param timeoutMs + * the timeout in milliseconds * @throws InterruptedException */ public void waitUntil(StatePredicate p, long timeoutMs) throws InterruptedException { waitUntil(p, new FixedTimeout(timeoutMs)); } - + private void waitUntil(StatePredicate p, Timeout timeout) throws InterruptedException { - synchronized(sync) { + synchronized (sync) { while (!p.isActive()) { try { sync.wait(timeout.timeRemaining()); - } - catch (TimeoutException e) { + } catch (TimeoutException e) { if (firstError != null) { throw firstError; - } - else { + } else { Assert.fail("timed out waiting for " + asString(p)); } } } } - + } - + public Invokable synchroniseAccessTo(final Invokable mockObject) { return new Invokable() { public Object invoke(Invocation invocation) throws Throwable { @@ -83,16 +95,19 @@ private Object synchroniseInvocation(Invokable mockObject, Invocation invocation synchronized (sync) { try { return mockObject.invoke(invocation); - } - catch (Error e) { + } catch (Error e) { if (firstError == null) { firstError = e; } throw e; - } - finally { + } finally { sync.notifyAll(); } } } + + @Override + public InvocationDispatcher dispatcher() { + return invocationDispatcher; + } } diff --git a/jmock/src/main/java/org/jmock/lib/concurrent/SynchronisingInvocationDispatcherWrapper.java b/jmock/src/main/java/org/jmock/lib/concurrent/SynchronisingInvocationDispatcherWrapper.java new file mode 100644 index 000000000..c65117c8b --- /dev/null +++ b/jmock/src/main/java/org/jmock/lib/concurrent/SynchronisingInvocationDispatcherWrapper.java @@ -0,0 +1,46 @@ +package org.jmock.lib.concurrent; + +import org.hamcrest.Description; +import org.jmock.api.Expectation; +import org.jmock.api.Invocation; +import org.jmock.api.InvocationDispatcher; +import org.jmock.internal.StateMachine; + +/** + * I synchronise my delegate. + * This serialises access to the internal Expectation and StateMachine collections. + * @author oliverbye + * + */ +public class SynchronisingInvocationDispatcherWrapper implements InvocationDispatcher { + + private final InvocationDispatcher delegate; + + public SynchronisingInvocationDispatcherWrapper(InvocationDispatcher dispatcher) { + delegate = dispatcher; + } + + public synchronized StateMachine newStateMachine(String name) { + return delegate.newStateMachine(name); + } + + public synchronized void add(Expectation expectation) { + delegate.add(expectation); + } + + public synchronized void describeTo(Description description) { + delegate.describeTo(description); + } + + public synchronized void describeMismatch(Invocation invocation, Description description) { + delegate.describeMismatch(invocation, description); + } + + public synchronized boolean isSatisfied() { + return delegate.isSatisfied(); + } + + public synchronized Object dispatch(Invocation invocation) throws Throwable { + return delegate.dispatch(invocation); + } +} diff --git a/jmock/src/main/java/org/jmock/internal/InvocationDispatcher.java b/jmock/src/main/java/org/jmock/lib/concurrent/UnsynchronisedInvocationDispatcher.java similarity index 74% rename from jmock/src/main/java/org/jmock/internal/InvocationDispatcher.java rename to jmock/src/main/java/org/jmock/lib/concurrent/UnsynchronisedInvocationDispatcher.java index 1da7da248..179227580 100644 --- a/jmock/src/main/java/org/jmock/internal/InvocationDispatcher.java +++ b/jmock/src/main/java/org/jmock/lib/concurrent/UnsynchronisedInvocationDispatcher.java @@ -1,4 +1,4 @@ -package org.jmock.internal; +package org.jmock.lib.concurrent; import java.util.ArrayList; import java.util.Collection; @@ -9,35 +9,53 @@ import org.jmock.api.Expectation; import org.jmock.api.ExpectationError; import org.jmock.api.Invocation; +import org.jmock.api.InvocationDispatcher; +import org.jmock.internal.StateMachine; -public class InvocationDispatcher implements ExpectationCollector, SelfDescribing { +public class UnsynchronisedInvocationDispatcher implements InvocationDispatcher { private final Collection expectations; private final Collection stateMachines; - public InvocationDispatcher() { + public UnsynchronisedInvocationDispatcher() { expectations = new ArrayList(); stateMachines = new ArrayList(); } - public InvocationDispatcher(Collection theExpectations, Collection theStateMachines) { + public UnsynchronisedInvocationDispatcher(Collection theExpectations, Collection theStateMachines) { expectations = theExpectations; stateMachines = theStateMachines; } + /* (non-Javadoc) + * @see org.jmock.internal.InvocationDispatcher#newStateMachine(java.lang.String) + */ + @Override public StateMachine newStateMachine(String name) { StateMachine stateMachine = new StateMachine(name); stateMachines.add(stateMachine); return stateMachine; } + /* (non-Javadoc) + * @see org.jmock.internal.InvocationDispatcher#add(org.jmock.api.Expectation) + */ + @Override public void add(Expectation expectation) { expectations.add(expectation); } + /* (non-Javadoc) + * @see org.jmock.internal.InvocationDispatcher#describeTo(org.hamcrest.Description) + */ + @Override public void describeTo(Description description) { describe(description, expectations); } + /* (non-Javadoc) + * @see org.jmock.internal.InvocationDispatcher#describeMismatch(org.jmock.api.Invocation, org.hamcrest.Description) + */ + @Override public void describeMismatch(Invocation invocation, Description description) { describe(description, describedWith(expectations, invocation)); } @@ -80,6 +98,10 @@ private void describe(Description description, Iterable exceptionsOnBackgroundThreads = new LinkedBlockingQueue(); diff --git a/jmock/src/test/java/org/jmock/test/unit/internal/InvocationDispatcherTests.java b/jmock/src/test/java/org/jmock/test/unit/internal/InvocationDispatcherTests.java index 5ad92324f..4a645b3d5 100644 --- a/jmock/src/test/java/org/jmock/test/unit/internal/InvocationDispatcherTests.java +++ b/jmock/src/test/java/org/jmock/test/unit/internal/InvocationDispatcherTests.java @@ -12,20 +12,22 @@ import org.jmock.api.Expectation; import org.jmock.api.ExpectationError; import org.jmock.api.Invocation; -import org.jmock.internal.InvocationDispatcher; +import org.jmock.api.InvocationDispatcher; import org.jmock.internal.StateMachine; +import org.jmock.lib.concurrent.SynchronisingInvocationDispatcherWrapper; +import org.jmock.lib.concurrent.UnsynchronisedInvocationDispatcher; import org.jmock.test.unit.support.MethodFactory; import org.jmock.test.unit.support.MockExpectation; import junit.framework.TestCase; public class InvocationDispatcherTests extends TestCase { - + // Avoid multi threaeding tests deadlocking // Adjust timeout for debugging private static final TimeUnit TIMEOUT_UNIT = TimeUnit.SECONDS; private static final int TIMEOUT = 2; - + MethodFactory methodFactory = new MethodFactory(); Invocation invocation = new Invocation( "invokedObject", @@ -39,7 +41,7 @@ public void testInvokesFirstMatchingExpectationInGroup() throws Throwable { MockExpectation expectation2 = new MockExpectation(true, NOT_RELEVANT, NOT_RELEVANT); MockExpectation expectation3 = new MockExpectation(true, NOT_RELEVANT, NOT_RELEVANT); - InvocationDispatcher dispatcher = new InvocationDispatcher(); + UnsynchronisedInvocationDispatcher dispatcher = new UnsynchronisedInvocationDispatcher(); dispatcher.add(expectation1); dispatcher.add(expectation2); dispatcher.add(expectation3); @@ -59,7 +61,7 @@ public void testThrowsExpectationErrorIfNoExpectationsMatchAnInvocation() throws MockExpectation expectation2 = new MockExpectation(false, NOT_RELEVANT, NOT_RELEVANT); MockExpectation expectation3 = new MockExpectation(false, NOT_RELEVANT, NOT_RELEVANT); - InvocationDispatcher dispatcher = new InvocationDispatcher(); + UnsynchronisedInvocationDispatcher dispatcher = new UnsynchronisedInvocationDispatcher(); dispatcher.add(expectation1); dispatcher.add(expectation2); dispatcher.add(expectation3); @@ -77,25 +79,25 @@ public void testThrowsExpectationErrorIfNoExpectationsMatchAnInvocation() throws } public void testIsSatisfiedOnlyIfAllExpectationsAreSatisfied() { - InvocationDispatcher dispatcherAll = new InvocationDispatcher(); + UnsynchronisedInvocationDispatcher dispatcherAll = new UnsynchronisedInvocationDispatcher(); dispatcherAll.add(new MockExpectation(NOT_RELEVANT, true, NOT_RELEVANT)); dispatcherAll.add(new MockExpectation(NOT_RELEVANT, true, NOT_RELEVANT)); assertTrue("should be satisfied if all expectations are satisfied", dispatcherAll.isSatisfied()); - InvocationDispatcher dispatcher1 = new InvocationDispatcher(); + UnsynchronisedInvocationDispatcher dispatcher1 = new UnsynchronisedInvocationDispatcher(); dispatcher1.add(new MockExpectation(NOT_RELEVANT, true, NOT_RELEVANT)); dispatcher1.add(new MockExpectation(NOT_RELEVANT, false, NOT_RELEVANT)); assertFalse("should not be satisfied if first expectation is not satisfied", dispatcher1.isSatisfied()); - InvocationDispatcher dispatcher2 = new InvocationDispatcher(); + UnsynchronisedInvocationDispatcher dispatcher2 = new UnsynchronisedInvocationDispatcher(); dispatcher2.add(new MockExpectation(NOT_RELEVANT, false, NOT_RELEVANT)); dispatcher2.add(new MockExpectation(NOT_RELEVANT, true, NOT_RELEVANT)); assertFalse("should not be satisfied if second expectation is not satisfied", dispatcher2.isSatisfied()); - InvocationDispatcher dispatcherNone = new InvocationDispatcher(); + UnsynchronisedInvocationDispatcher dispatcherNone = new UnsynchronisedInvocationDispatcher(); dispatcherNone.add(new MockExpectation(NOT_RELEVANT, false, NOT_RELEVANT)); dispatcherNone.add(new MockExpectation(NOT_RELEVANT, true, NOT_RELEVANT)); assertFalse("should not be satisfied if no expectations are satisfied", @@ -107,19 +109,20 @@ public void testIsSatisfiedOnlyIfAllExpectationsAreSatisfied() { * * @throws Throwable */ - @SuppressWarnings({ "rawtypes", "unchecked" }) - public void testHandlesAddingExpectationsWhileOtherTestsDispatch() throws Throwable { + public void testUnsynchronisedInvocationDispatcherHandlesAddingExpectationsWhileOtherTestsDispatch() + throws Throwable { final CyclicBarrier barrier = new CyclicBarrier(2); MockExpectation expectation1 = new MockExpectation(true, NOT_RELEVANT, NOT_RELEVANT); MockExpectation expectation2 = new MockExpectation(false, NOT_RELEVANT, NOT_RELEVANT); - CriticalSectionForcingCollectionWrapper expectations = new CriticalSectionForcingCollectionWrapper( - new CopyOnWriteArrayList(), barrier); - CriticalSectionForcingCollectionWrapper stateMachines = new CriticalSectionForcingCollectionWrapper( - new ArrayList(), barrier); - final InvocationDispatcher dispatcher = new InvocationDispatcher(expectations, stateMachines); + Collection expectations = new CriticalSectionForcingCollectionWrapper<>( + new CopyOnWriteArrayList(), barrier); + Collection stateMachines = new CriticalSectionForcingCollectionWrapper<>( + new ArrayList(), barrier); + final UnsynchronisedInvocationDispatcher dispatcher = new UnsynchronisedInvocationDispatcher(expectations, + stateMachines); new Thread(new Runnable() { @Override @@ -128,7 +131,7 @@ public void run() { barrier.await(TIMEOUT, TIMEOUT_UNIT); barrier.await(TIMEOUT, TIMEOUT_UNIT); // now the expectation one has been added - + dispatcher.dispatch(invocation); barrier.await(TIMEOUT, TIMEOUT_UNIT); } catch (Throwable e) { @@ -151,6 +154,43 @@ public void run() { expectation1.wasInvoked); } + public void testSynchronisedInvocationDispatcherBlocksAddingExpectationsWhileOtherTestsDispatch() + throws Throwable { + + final CyclicBarrier barrier = new CyclicBarrier(2); + + MockExpectation expectation1 = new MockExpectation(true, NOT_RELEVANT, NOT_RELEVANT); + MockExpectation expectation2 = new MockExpectation(false, NOT_RELEVANT, NOT_RELEVANT); + + // intentionally use array list as the wrapper should synchronise access + final InvocationDispatcher dispatcher = new SynchronisingInvocationDispatcherWrapper( + new UnsynchronisedInvocationDispatcher(new ArrayList(), new ArrayList())); + + // expect dispatch + dispatcher.add(expectation1); + + new Thread(new Runnable() { + @Override + public void run() { + try { + dispatcher.dispatch(invocation); + barrier.await(); + } catch (Throwable e) { + throw new RuntimeException(e); + } + } + }, "Concurrent Dispatch").start(); + + // await until dispatch + barrier.await(); + + dispatcher.add(expectation2); + + expectation1.shouldBeInvokedWith(invocation); + assertTrue("expectation1 should have been invoked", + expectation1.wasInvoked); + } + private class CriticalSectionForcingCollectionWrapper implements Collection { private final Collection delegate; private final CyclicBarrier barrier; @@ -197,7 +237,7 @@ public Object[] toArray() { return delegate.toArray(); } - public T[] toArray(T[] a) { + public U[] toArray(U[] a) { return delegate.toArray(a); } diff --git a/jmock/src/test/java/org/jmock/test/unit/lib/concurrent/BlitzerTests.java b/jmock/src/test/java/org/jmock/test/unit/lib/concurrent/BlitzerTests.java index 1368505b1..4eeda2791 100644 --- a/jmock/src/test/java/org/jmock/test/unit/lib/concurrent/BlitzerTests.java +++ b/jmock/src/test/java/org/jmock/test/unit/lib/concurrent/BlitzerTests.java @@ -1,17 +1,17 @@ package org.jmock.test.unit.lib.concurrent; -import junit.framework.TestCase; -import org.jmock.lib.concurrent.Blitzer; -import org.junit.After; -import org.junit.Before; +import static java.lang.System.getenv; +import static org.hamcrest.Matchers.equalTo; +import static org.junit.Assert.assertThat; import java.util.concurrent.ThreadFactory; import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicInteger; -import static java.lang.System.getenv; -import static org.hamcrest.Matchers.equalTo; -import static org.junit.Assert.assertThat; +import org.jmock.lib.concurrent.Blitzer; +import org.junit.After; + +import junit.framework.TestCase; public class BlitzerTests extends TestCase { private static final String BLITZER_THREADS = "blitzerThreads"; diff --git a/jmock/src/test/java/org/jmock/test/unit/support/MockExpectation.java b/jmock/src/test/java/org/jmock/test/unit/support/MockExpectation.java index 8d76e3141..e523a537f 100644 --- a/jmock/src/test/java/org/jmock/test/unit/support/MockExpectation.java +++ b/jmock/src/test/java/org/jmock/test/unit/support/MockExpectation.java @@ -1,13 +1,12 @@ package org.jmock.test.unit.support; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; + import org.hamcrest.Description; import org.jmock.api.Expectation; import org.jmock.api.Invocation; -import org.junit.Assert; - -import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertTrue; public class MockExpectation implements Expectation { public boolean matches; diff --git a/pom.xml b/pom.xml index e0b6a90af..da115e082 100644 --- a/pom.xml +++ b/pom.xml @@ -6,11 +6,12 @@ org.jmock jmock-parent - 2.8.4 + 2.9.0-SNAPSHOT pom jMock 2 Parent - + @@ -101,8 +102,8 @@ maven-compiler-plugin - 1.6 - 1.6 + 1.7 + 1.7 @@ -203,25 +204,29 @@ ossrh https://oss.sonatype.org/content/repositories/snapshots + + ossrh + https://oss.sonatype.org/service/local/staging/deploy/maven2/ + - + - - - org.codehaus.mojo - versions-maven-plugin - 2.5 - - - - dependency-updates-report - plugin-updates-report - property-updates-report - - - - - + + + org.codehaus.mojo + versions-maven-plugin + 2.5 + + + + dependency-updates-report + plugin-updates-report + property-updates-report + + + + + diff --git a/settings.xml b/settings.xml index 5c24361b9..7f700b222 100644 --- a/settings.xml +++ b/settings.xml @@ -1,4 +1,5 @@ + diff --git a/testjar/.gitignore b/testjar/.gitignore index 7262129d8..827a4ac18 100644 --- a/testjar/.gitignore +++ b/testjar/.gitignore @@ -2,3 +2,5 @@ random_seed trustdb.gpg *~ +.gpg-v21-migrated +private-keys-v1.d diff --git a/testjar/pom.xml b/testjar/pom.xml index 51e9d88fd..fe3c531dc 100644 --- a/testjar/pom.xml +++ b/testjar/pom.xml @@ -1,73 +1,74 @@ - + - 4.0.0 + 4.0.0 - jmock-testjar - jar - jMock 2 Test Jar - Source for jar files used in jmock core tests + jmock-testjar + jar + jMock 2 Test Jar + Source for jar files used in jmock core tests - - org.jmock - jmock-parent - 2.8.4 - ../pom.xml - + + org.jmock + jmock-parent + 2.9.0-SNAPSHOT + ../pom.xml + - - signed - - - - org.apache.maven.plugins - maven-dependency-plugin - 2.9 - - - copy - package - - copy - - - - - ${project.groupId} - ${project.artifactId} - ${project.version} - jar - true - ${project.build.directory} - unsigned.jar - - - - - - + + signed + + + + org.apache.maven.plugins + maven-dependency-plugin + 2.9 + + + copy + package + + copy + + + + + ${project.groupId} + ${project.artifactId} + ${project.version} + jar + true + ${project.build.directory} + unsigned.jar + + + + + + - - org.apache.maven.plugins - maven-gpg-plugin - 1.6 - - - sign-artifacts - verify - - sign - - - 899FD4CB - ${basedir}/secring.gpg - ${basedir}/pubring.gpg - secret - - - - + + org.apache.maven.plugins + maven-gpg-plugin + 1.6 + + + sign-artifacts + verify + + sign + + + 899FD4CB + ${basedir} + secret + false + + + + - - + +