12637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin/* 22637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin * Copyright (c) 2007 Mockito contributors 32637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin * This program is made available under the terms of the MIT License. 42637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin */ 52637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffinpackage org.mockitousage.bugs; 62637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin 708bd32ce48b12ae751dd5c4829ff09a6fb9894f0Philip P. Moltmannimport static org.junit.Assert.fail; 808bd32ce48b12ae751dd5c4829ff09a6fb9894f0Philip P. Moltmann 92637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffinimport org.junit.Test; 102637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffinimport org.mockito.Mockito; 112637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffinimport org.mockito.invocation.InvocationOnMock; 122637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffinimport org.mockito.stubbing.Answer; 132637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin 142637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffinimport java.util.concurrent.ExecutorService; 152637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffinimport java.util.concurrent.Executors; 162637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffinimport java.util.concurrent.TimeUnit; 172637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffinimport java.util.concurrent.atomic.AtomicInteger; 182637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin 192637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin//see bug 190 202637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffinpublic class ShouldNotDeadlockAnswerExecutionTest { 212637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin 222637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin @Test 232637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin public void failIfMockIsSharedBetweenThreads() throws Exception { 242637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin Service service = Mockito.mock(Service.class); 252637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin ExecutorService threads = Executors.newCachedThreadPool(); 262637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin AtomicInteger counter = new AtomicInteger(2); 272637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin 282637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin // registed answer on verySlowMethod 292637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin 302637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin Mockito.when(service.verySlowMethod()).thenAnswer(new LockingAnswer(counter)); 312637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin 322637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin // execute verySlowMethod twice in separate threads 332637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin 342637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin threads.execute(new ServiceRunner(service)); 352637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin threads.execute(new ServiceRunner(service)); 362637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin 372637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin // waiting for threads to finish 382637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin 392637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin threads.shutdown(); 402637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin 412637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin if (!threads.awaitTermination(1000, TimeUnit.MILLISECONDS)) { 422637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin // threads were timed-out 4308bd32ce48b12ae751dd5c4829ff09a6fb9894f0Philip P. Moltmann fail(); 442637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin } 452637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin } 462637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin 472637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin @Test 482637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin public void successIfEveryThreadHasItsOwnMock() throws Exception { 492637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin Service service1 = Mockito.mock(Service.class); 502637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin Service service2 = Mockito.mock(Service.class); 512637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin ExecutorService threads = Executors.newCachedThreadPool(); 522637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin AtomicInteger counter = new AtomicInteger(2); 532637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin 542637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin // registed answer on verySlowMethod 552637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin 562637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin Mockito.when(service1.verySlowMethod()).thenAnswer(new LockingAnswer(counter)); 572637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin Mockito.when(service2.verySlowMethod()).thenAnswer(new LockingAnswer(counter)); 582637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin 592637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin // execute verySlowMethod twice in separate threads 602637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin 612637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin threads.execute(new ServiceRunner(service1)); 622637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin threads.execute(new ServiceRunner(service2)); 632637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin 642637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin // waiting for threads to finish 652637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin 662637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin threads.shutdown(); 672637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin 682637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin if (!threads.awaitTermination(500, TimeUnit.MILLISECONDS)) { 692637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin // threads were timed-out 7008bd32ce48b12ae751dd5c4829ff09a6fb9894f0Philip P. Moltmann fail(); 712637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin } 722637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin } 732637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin 742637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin static class LockingAnswer implements Answer<String> { 752637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin 762637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin private AtomicInteger counter; 772637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin 782637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin public LockingAnswer(AtomicInteger counter) { 792637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin this.counter = counter; 802637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin } 812637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin 822637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin /** 832637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin * Decrement counter and wait until counter has value 0 842637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin */ 852637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin public String answer(InvocationOnMock invocation) throws Throwable { 862637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin counter.decrementAndGet(); 872637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin 882637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin while (counter.get() != 0) { 892637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin Thread.sleep(10); 902637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin } 912637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin 922637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin return null; 932637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin } 942637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin 952637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin } 962637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin 972637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin static class ServiceRunner implements Runnable { 982637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin 992637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin private Service service; 1002637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin 1012637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin public ServiceRunner(Service service) { 1022637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin this.service = service; 1032637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin } 1042637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin 1052637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin public void run() { 1062637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin service.verySlowMethod(); 1072637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin } 1082637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin 1092637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin } 1102637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin 1112637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin interface Service { 1122637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin 1132637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin String verySlowMethod(); 1142637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin 1152637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin } 1162637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin 1172637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin} 1182637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin 119