View Javadoc

1   // Copyright (C) 2011 Philip Aston
2   // All rights reserved.
3   //
4   // This file is part of The Grinder software distribution. Refer to
5   // the file LICENSE which is part of The Grinder distribution for
6   // licensing details. The Grinder distribution is available on the
7   // Internet at http://grinder.sourceforge.net/
8   //
9   // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
10  // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
11  // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
12  // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
13  // COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
14  // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
15  // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
16  // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
17  // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
18  // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
19  // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
20  // OF THE POSSIBILITY OF SUCH DAMAGE.
21  
22  package net.grinder.synchronisation;
23  
24  import static org.junit.Assert.assertEquals;
25  import static org.junit.Assert.assertNotSame;
26  import static org.junit.Assert.assertNull;
27  import static org.junit.Assert.assertSame;
28  import static org.junit.Assert.fail;
29  import static org.mockito.Matchers.argThat;
30  import static org.mockito.Matchers.eq;
31  import static org.mockito.Matchers.isA;
32  import static org.mockito.Mockito.mock;
33  import static org.mockito.Mockito.times;
34  import static org.mockito.Mockito.verify;
35  import static org.mockito.Mockito.verifyNoMoreInteractions;
36  import static org.mockito.Mockito.when;
37  
38  import java.util.Set;
39  
40  import net.grinder.communication.MessageDispatchRegistry;
41  import net.grinder.communication.Sender;
42  import net.grinder.communication.MessageDispatchRegistry.AbstractHandler;
43  import net.grinder.synchronisation.BarrierGroup.Listener;
44  import net.grinder.synchronisation.messages.AddBarrierMessage;
45  import net.grinder.synchronisation.messages.AddWaiterMessage;
46  import net.grinder.synchronisation.messages.BarrierIdentity;
47  import net.grinder.synchronisation.messages.CancelWaiterMessage;
48  import net.grinder.synchronisation.messages.OpenBarrierMessage;
49  import net.grinder.synchronisation.messages.RemoveBarriersMessage;
50  import net.grinder.testutility.MockingUtilities.TypedArgumentMatcher;
51  
52  import org.junit.Before;
53  import org.junit.Test;
54  import org.mockito.ArgumentCaptor;
55  import org.mockito.Captor;
56  import org.mockito.Mock;
57  import org.mockito.MockitoAnnotations;
58  
59  
60  /**
61   * Unit tests for {@link ClientBarrierGroups}.
62   *
63   * @author Philip Aston
64   * @version $Revision:$
65   */
66  public class TestClientBarrierGroups {
67  
68    private static final BarrierIdentity ID1 = new BarrierIdentity() {};
69    private static final BarrierIdentity ID2 = new BarrierIdentity() {};
70  
71    @Mock private Sender m_sender;
72    @Mock private MessageDispatchRegistry m_messageDispatch;
73    @Captor
74    private ArgumentCaptor<AbstractHandler<OpenBarrierMessage>> m_handlerCaptor;
75  
76    private int m_awakenCount = 0;
77  
78    private ClientBarrierGroups m_groups;
79  
80    @Before public void setUp() {
81      MockitoAnnotations.initMocks(this);
82  
83      m_groups = new ClientBarrierGroups(m_sender, m_messageDispatch);
84    }
85  
86    @Test public void testCreateAndRetrieve() throws Exception {
87      assertNull(m_groups.getExistingGroup("A"));
88  
89      final BarrierGroup a = m_groups.getGroup("A");
90      assertEquals("A", a.getName());
91      assertSame(a, m_groups.getGroup("A"));
92      assertNotSame(a, m_groups.getGroup("B"));
93  
94      assertSame(a, m_groups.getExistingGroup("A"));
95  
96      a.addBarrier();
97  
98      a.removeBarriers(1); // Invalidate a.
99  
100     verify(m_sender).send(isA(AddBarrierMessage.class));
101     verify(m_sender).send(isA(RemoveBarriersMessage.class));
102 
103     assertNotSame(a, m_groups.getGroup("A"));
104 
105     verifyNoMoreInteractions(m_sender);
106   }
107 
108   @Test public void testMessageHandler() throws Exception {
109 
110     verify(m_messageDispatch).set(eq(OpenBarrierMessage.class),
111                                   m_handlerCaptor.capture());
112 
113     final AbstractHandler<OpenBarrierMessage> handler =
114       m_handlerCaptor.getValue();
115 
116     final OpenBarrierMessage message = mock(OpenBarrierMessage.class);
117     when(message.getName()).thenReturn("A");
118 
119     handler.handle(message);
120     assertNull(m_groups.getExistingGroup("A"));
121     assertEquals(0, m_awakenCount);
122 
123     createBarrierGroup("A");
124     assertEquals(0, m_awakenCount);
125     handler.handle(message);
126     assertEquals(1, m_awakenCount);
127 
128     verifyNoMoreInteractions(m_messageDispatch);
129   }
130 
131   private BarrierGroup createBarrierGroup(String groupName) {
132     final BarrierGroup bg = m_groups.getGroup(groupName);
133 
134     bg.addListener(new Listener() {
135         public void awaken(Set<BarrierIdentity> waiters) {
136           ++m_awakenCount;
137         }
138       });
139 
140     return bg;
141   }
142 
143   @Test public void testBarrierGroup() {
144     final BarrierGroup bg = createBarrierGroup("Foo");
145 
146     assertEquals("Foo", bg.getName());
147     assertEquals(0, m_awakenCount);
148   }
149 
150   @Test public void testBarrierGroupAddWaiter() throws Exception {
151     final BarrierGroup bg = createBarrierGroup("Foo");
152 
153     bg.addBarrier();
154     bg.addBarrier();
155 
156     verify(m_sender, times(2)).send(isA(AddBarrierMessage.class));
157 
158     bg.addWaiter(ID1);
159 
160     bg.addWaiter(ID2);
161 
162     verify(m_sender).send(argThat(new AddWaiterMessageMatcher(ID1)));
163     verify(m_sender).send(argThat(new AddWaiterMessageMatcher(ID2)));
164 
165     assertEquals(0, m_awakenCount);
166 
167     verifyNoMoreInteractions(m_sender);
168   }
169 
170   @Test public void testBarrierGroupAddTooManyWaiters() throws Exception {
171     final BarrierGroup bg = createBarrierGroup("Foo");
172 
173     bg.addBarrier();
174     bg.addWaiter(ID1);
175 
176     try {
177       bg.addWaiter(ID2);
178       fail("Expected AssertionError");
179     }
180     catch (AssertionError e) {
181     }
182   }
183 
184   @Test public void testRemoveBarriers() throws Exception {
185     final BarrierGroup bg = createBarrierGroup("Foo");
186 
187     bg.addBarrier();
188     bg.addBarrier();
189     bg.addBarrier();
190 
191     verify(m_sender, times(3)).send(isA(AddBarrierMessage.class));
192 
193     bg.addWaiter(ID1);
194     bg.addWaiter(ID2);
195 
196     verify(m_sender).send(argThat(new AddWaiterMessageMatcher(ID1)));
197     verify(m_sender).send(argThat(new AddWaiterMessageMatcher(ID2)));
198 
199     bg.removeBarriers(1);
200 
201     verify(m_sender).send(argThat(new RemoveBarriersMessageMatcher(1)));
202 
203     assertEquals(0, m_awakenCount);
204 
205     verifyNoMoreInteractions(m_sender);
206   }
207 
208   @Test public void testRemoveTooManyBarriers() throws Exception {
209     final BarrierGroup bg = createBarrierGroup("Foo");
210 
211     bg.addBarrier();
212     bg.addBarrier();
213     bg.addBarrier();
214 
215     bg.removeBarriers(1);
216     bg.removeBarriers(1);
217 
218     try {
219       bg.removeBarriers(2);
220       fail("Expected IllegalStateException");
221     }
222     catch (IllegalStateException e) {
223     }
224 
225     assertEquals(0, m_awakenCount);
226   }
227 
228   @Test public void testInvalidGroup() throws Exception {
229     final BarrierGroup bg = createBarrierGroup("Foo");
230 
231     bg.addBarrier();
232     bg.removeBarriers(1);
233 
234     try {
235       bg.addWaiter(null);
236       fail("Expected IllegalStateException");
237     }
238     catch (IllegalStateException e) {
239     }
240 
241     try {
242       bg.addBarrier();
243       fail("Expected IllegalStateException");
244     }
245     catch (IllegalStateException e) {
246     }
247 
248     try {
249       bg.removeBarriers(1);
250       fail("Expected IllegalStateException");
251     }
252     catch (IllegalStateException e) {
253     }
254 
255     assertEquals(0, m_awakenCount);
256   }
257 
258   @Test public void addMoreWaitersThanBarriers() throws Exception {
259     final BarrierGroup bg = createBarrierGroup("Foo");
260 
261     try {
262       bg.addWaiter(ID2);
263       fail("Expected IllegalStateException");
264     }
265     catch (IllegalStateException e) {
266     }
267   }
268 
269   @Test public void testCancelWaiter() throws Exception {
270     final BarrierGroup bg = createBarrierGroup("Foo");
271 
272     bg.addBarrier();
273     bg.addBarrier();
274 
275     verify(m_sender, times(2)).send(isA(AddBarrierMessage.class));
276 
277     bg.addWaiter(ID1);
278     verify(m_sender).send(argThat(new AddWaiterMessageMatcher(ID1)));
279 
280     bg.cancelWaiter(ID2); // noop
281     verify(m_sender).send(argThat(new CancelWaiterMessageMatcher(ID2)));
282 
283     bg.cancelWaiter(ID1);
284     verify(m_sender).send(argThat(new CancelWaiterMessageMatcher(ID1)));
285 
286     bg.addWaiter(ID2);
287     verify(m_sender).send(argThat(new AddWaiterMessageMatcher(ID2)));
288 
289     bg.addWaiter(ID1);
290     verify(m_sender, times(2)).send(argThat(new AddWaiterMessageMatcher(ID1)));
291 
292     assertEquals(0, m_awakenCount);
293 
294     verifyNoMoreInteractions(m_sender);
295   }
296 
297   private static class RemoveBarriersMessageMatcher
298     extends TypedArgumentMatcher<RemoveBarriersMessage> {
299 
300     private final int m_numberOfBarriers;
301 
302     RemoveBarriersMessageMatcher(int numberOfBarriers) {
303       m_numberOfBarriers = numberOfBarriers;
304     }
305 
306     @Override protected boolean argumentMatches(RemoveBarriersMessage t) {
307       return t.getNumberOfBarriers() == m_numberOfBarriers;
308     }
309   }
310 
311   private static class AddWaiterMessageMatcher
312     extends TypedArgumentMatcher<AddWaiterMessage> {
313 
314     private final BarrierIdentity m_barrierIdentity;
315 
316     AddWaiterMessageMatcher(BarrierIdentity barrierIdentity) {
317       m_barrierIdentity = barrierIdentity;
318     }
319 
320     @Override protected boolean argumentMatches(AddWaiterMessage t) {
321       return t.getBarrierIdentity().equals(m_barrierIdentity);
322     }
323   }
324 
325   private static class CancelWaiterMessageMatcher
326     extends TypedArgumentMatcher<CancelWaiterMessage> {
327 
328     private final BarrierIdentity m_barrierIdentity;
329 
330     CancelWaiterMessageMatcher(BarrierIdentity barrierIdentity) {
331       m_barrierIdentity = barrierIdentity;
332     }
333 
334     @Override protected boolean argumentMatches(CancelWaiterMessage t) {
335       return t.getBarrierIdentity().equals(m_barrierIdentity);
336     }
337   }
338 }