1/*
2 * Copyright (c) 2007 Mockito contributors
3 * This program is made available under the terms of the MIT License.
4 */
5package org.mockito.internal.stubbing;
6
7import static org.junit.Assert.assertEquals;
8import static org.junit.Assert.assertFalse;
9import static org.junit.Assert.assertTrue;
10
11import java.util.LinkedList;
12import java.util.concurrent.CountDownLatch;
13import org.junit.Test;
14import org.mockito.internal.creation.MockSettingsImpl;
15import org.mockito.internal.invocation.InvocationBuilder;
16import org.mockito.internal.invocation.InvocationMatcher;
17import org.mockito.internal.stubbing.answers.Returns;
18import org.mockito.internal.stubbing.defaultanswers.ReturnsEmptyValues;
19import org.mockito.invocation.Invocation;
20import org.mockito.mock.MockCreationSettings;
21
22/**
23 * Author: Szczepan Faber
24 */
25public class InvocationContainerImplTest {
26
27    InvocationContainerImpl container = new InvocationContainerImpl( new MockSettingsImpl());
28    InvocationContainerImpl containerStubOnly =
29      new InvocationContainerImpl( (MockCreationSettings) new MockSettingsImpl().stubOnly());
30    Invocation invocation = new InvocationBuilder().toInvocation();
31    LinkedList<Throwable> exceptions = new LinkedList<Throwable>();
32
33    @Test
34    public void should_be_thread_safe() throws Throwable {
35        doShouldBeThreadSafe(container);
36    }
37
38    @Test
39    public void should_be_thread_safe_stub_only() throws Throwable {
40        doShouldBeThreadSafe(containerStubOnly);
41    }
42
43    //works 50% of the time
44    private void doShouldBeThreadSafe(final InvocationContainerImpl c) throws Throwable {
45        //given
46        Thread[] t = new Thread[200];
47        final CountDownLatch starter = new CountDownLatch(200);
48        for (int i = 0; i < t.length; i++ ) {
49            t[i] = new Thread() {
50                public void run() {
51                    try {
52                        starter.await(); //NOPMD
53                    } catch (InterruptedException e) {
54                        throw new RuntimeException(e);
55                    }
56                    c.setInvocationForPotentialStubbing(new InvocationMatcher(invocation));
57                    c.addAnswer(new Returns("foo"));
58                    c.findAnswerFor(invocation);
59                }
60            };
61            t[i].setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
62                public void uncaughtException(Thread t, Throwable e) {
63                    exceptions.add(e);
64                }
65            });
66            t[i].start();
67
68            starter.countDown();
69        }
70
71        //when
72        for (Thread aT : t) {
73            aT.join();
74        }
75
76        //then
77        if (exceptions.size() != 0) {
78            throw exceptions.getFirst();
79        }
80    }
81
82    @Test
83    public void should_return_invoked_mock() throws Exception {
84        container.setInvocationForPotentialStubbing(new InvocationMatcher(invocation));
85
86        assertEquals(invocation.getMock(), container.invokedMock());
87    }
88
89    @Test
90    public void should_return_invoked_mock_stub_only() throws Exception {
91        containerStubOnly.setInvocationForPotentialStubbing(new InvocationMatcher(invocation));
92
93        assertEquals(invocation.getMock(), containerStubOnly.invokedMock());
94    }
95
96    @Test
97    public void should_tell_if_has_invocation_for_potential_stubbing() throws Exception {
98        container.setInvocationForPotentialStubbing(new InvocationBuilder().toInvocationMatcher());
99        assertTrue(container.hasInvocationForPotentialStubbing());
100
101        container.addAnswer(new ReturnsEmptyValues());
102        assertFalse(container.hasInvocationForPotentialStubbing());
103    }
104
105    @Test
106    public void should_tell_if_has_invocation_for_potential_stubbing_stub_only() throws Exception {
107        containerStubOnly.setInvocationForPotentialStubbing(new InvocationBuilder().toInvocationMatcher());
108        assertTrue(containerStubOnly.hasInvocationForPotentialStubbing());
109
110        containerStubOnly.addAnswer(new ReturnsEmptyValues());
111        assertFalse(containerStubOnly.hasInvocationForPotentialStubbing());
112    }
113}
114