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