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