/* * Copyright (c) 2007 Mockito contributors * This program is made available under the terms of the MIT License. */ package org.mockitousage.bugs; import org.junit.Before; import org.junit.Test; import org.mockito.Mockito; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import static org.mockito.Mockito.*; // issue 322 // the only evidence of this failing test was shown on a RHEL with IBM J9 JVM 64bits // // details // java.fullversion=JRE 1.6.0 IBM J9 2.6 Linux amd64-64 20111113_94967 (JIT enabled, AOT enabled) // Linux2.6.32-220.4.2.el6.x86_64 #1SMP Mon Feb 6 16:39:28EST 2012x86_64 x86_64 x86_64 GNU/Linux public class ConcurrentModificationExceptionOnMultiThreadedVerificationTest { int nThreads = 1; static final int TIMES = 100; static final int INTERVAL_MILLIS = 10; ITarget target = Mockito.mock(ITarget.class); ExecutorService fixedThreadPool; @Before public void setUp() { target = Mockito.mock(ITarget.class); fixedThreadPool = Executors.newFixedThreadPool(nThreads); } @Test public void shouldSuccessfullyVerifyConcurrentInvocationsWithTimeout() throws Exception { int potentialOverhead = 1000; // Leave 1000ms extra before timing out as leeway for test overheads int expectedMaxTestLength = TIMES * INTERVAL_MILLIS + potentialOverhead; reset(target); startInvocations(); verify(target, timeout(expectedMaxTestLength).times(TIMES * nThreads)).targetMethod("arg"); verifyNoMoreInteractions(target); } private void startInvocations() throws InterruptedException, ExecutionException { for(int i=0; i<nThreads; i++) { fixedThreadPool.submit(new TargetInvoker(i)); } } public class TargetInvoker implements Callable<Object> { private final int seq; TargetInvoker(int seq) { this.seq = seq; } public Object call() throws Exception { System.err.println("started " + seq); for (int i = 0; i < TIMES; i++) { Thread.yield(); target.targetMethod("arg"); Thread.sleep((long) INTERVAL_MILLIS); } System.err.println("finished" + seq); return seq; } } public interface ITarget { String targetMethod(String arg); } }