1 /*
2  * Copyright (c) 2007 Mockito contributors
3  * This program is made available under the terms of the MIT License.
4  */
5 package org.mockitousage.bugs;
6 
7 import org.junit.Before;
8 import org.junit.Test;
9 import org.mockito.Mockito;
10 
11 import java.util.concurrent.Callable;
12 import java.util.concurrent.ExecutionException;
13 import java.util.concurrent.ExecutorService;
14 import java.util.concurrent.Executors;
15 
16 import static org.mockito.Mockito.*;
17 
18 // issue 322
19 // the only evidence of this failing test was shown on a RHEL with IBM J9 JVM 64bits
20 //
21 // details
22 // java.fullversion=JRE 1.6.0 IBM J9 2.6 Linux amd64-64 20111113_94967  (JIT enabled, AOT enabled)
23 // Linux2.6.32-220.4.2.el6.x86_64 #1SMP Mon Feb 6 16:39:28EST 2012x86_64 x86_64 x86_64 GNU/Linux
24 public class ConcurrentModificationExceptionOnMultiThreadedVerificationTest {
25 
26     int nThreads = 1;
27 
28     static final int TIMES = 100;
29     static final int INTERVAL_MILLIS = 10;
30 
31     ITarget target = Mockito.mock(ITarget.class);
32     ExecutorService fixedThreadPool;
33 
34     @Before
setUp()35     public void setUp() {
36         target = Mockito.mock(ITarget.class);
37         fixedThreadPool = Executors.newFixedThreadPool(nThreads);
38     }
39 
40     @Test
shouldSuccessfullyVerifyConcurrentInvocationsWithTimeout()41     public void shouldSuccessfullyVerifyConcurrentInvocationsWithTimeout() throws Exception {
42         int potentialOverhead = 1000; // Leave 1000ms extra before timing out as leeway for test overheads
43         int expectedMaxTestLength = TIMES * INTERVAL_MILLIS + potentialOverhead;
44 
45         reset(target);
46         startInvocations();
47 
48         verify(target, timeout(expectedMaxTestLength).times(TIMES * nThreads)).targetMethod("arg");
49         verifyNoMoreInteractions(target);
50     }
51 
startInvocations()52     private void startInvocations() throws InterruptedException,
53             ExecutionException {
54 
55         for(int i=0; i<nThreads; i++) {
56             fixedThreadPool.submit(new TargetInvoker(i));
57         }
58 
59     }
60 
61     public class TargetInvoker implements Callable<Object> {
62         private final int seq;
63 
TargetInvoker(int seq)64         TargetInvoker(int seq) {
65             this.seq = seq;
66         }
67 
call()68         public Object call() throws Exception {
69             System.err.println("started " + seq);
70             for (int i = 0; i < TIMES; i++) {
71                 Thread.yield();
72                 target.targetMethod("arg");
73                 Thread.sleep((long) INTERVAL_MILLIS);
74             }
75             System.err.println("finished" + seq);
76             return seq;
77         }
78 
79     }
80 
81     public interface ITarget {
targetMethod(String arg)82         String targetMethod(String arg);
83     }
84 
85 }
86