• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 static org.junit.Assert.fail;
8 
9 import org.junit.Test;
10 import org.mockito.Mockito;
11 import org.mockito.invocation.InvocationOnMock;
12 import org.mockito.stubbing.Answer;
13 
14 import java.util.concurrent.ExecutorService;
15 import java.util.concurrent.Executors;
16 import java.util.concurrent.TimeUnit;
17 import java.util.concurrent.atomic.AtomicInteger;
18 
19 //see bug 190
20 public class ShouldNotDeadlockAnswerExecutionTest {
21 
22     @Test
failIfMockIsSharedBetweenThreads()23     public void failIfMockIsSharedBetweenThreads() throws Exception {
24         Service service = Mockito.mock(Service.class);
25         ExecutorService threads = Executors.newCachedThreadPool();
26         AtomicInteger counter = new AtomicInteger(2);
27 
28         // registed answer on verySlowMethod
29 
30         Mockito.when(service.verySlowMethod()).thenAnswer(new LockingAnswer(counter));
31 
32         // execute verySlowMethod twice in separate threads
33 
34         threads.execute(new ServiceRunner(service));
35         threads.execute(new ServiceRunner(service));
36 
37         // waiting for threads to finish
38 
39         threads.shutdown();
40 
41         if (!threads.awaitTermination(1000, TimeUnit.MILLISECONDS)) {
42             // threads were timed-out
43             fail();
44         }
45     }
46 
47     @Test
successIfEveryThreadHasItsOwnMock()48     public void successIfEveryThreadHasItsOwnMock() throws Exception {
49         Service service1 = Mockito.mock(Service.class);
50         Service service2 = Mockito.mock(Service.class);
51         ExecutorService threads = Executors.newCachedThreadPool();
52         AtomicInteger counter = new AtomicInteger(2);
53 
54         // registed answer on verySlowMethod
55 
56         Mockito.when(service1.verySlowMethod()).thenAnswer(new LockingAnswer(counter));
57         Mockito.when(service2.verySlowMethod()).thenAnswer(new LockingAnswer(counter));
58 
59         // execute verySlowMethod twice in separate threads
60 
61         threads.execute(new ServiceRunner(service1));
62         threads.execute(new ServiceRunner(service2));
63 
64         // waiting for threads to finish
65 
66         threads.shutdown();
67 
68         if (!threads.awaitTermination(500, TimeUnit.MILLISECONDS)) {
69             // threads were timed-out
70             fail();
71         }
72     }
73 
74     static class LockingAnswer implements Answer<String> {
75 
76         private AtomicInteger counter;
77 
LockingAnswer(AtomicInteger counter)78         public LockingAnswer(AtomicInteger counter) {
79             this.counter = counter;
80         }
81 
82         /**
83          * Decrement counter and wait until counter has value 0
84          */
answer(InvocationOnMock invocation)85         public String answer(InvocationOnMock invocation) throws Throwable {
86             counter.decrementAndGet();
87 
88             while (counter.get() != 0) {
89                 Thread.sleep(10);
90             }
91 
92             return null;
93         }
94 
95     }
96 
97     static class ServiceRunner implements Runnable {
98 
99         private Service service;
100 
ServiceRunner(Service service)101         public ServiceRunner(Service service) {
102             this.service = service;
103         }
104 
run()105         public void run() {
106             service.verySlowMethod();
107         }
108 
109     }
110 
111     interface Service {
112 
verySlowMethod()113         String verySlowMethod();
114 
115     }
116 
117 }
118 
119