source: protocol/src/test/java/geniusweb/protocol/session/saop/SAOPTest.java@ 30

Last change on this file since 30 was 30, checked in by bart, 3 years ago

Fixed memory leak. MOPAC2. removed jcenter build dependencies

File size: 13.2 KB
Line 
1package geniusweb.protocol.session.saop;
2
3import static org.junit.Assert.assertEquals;
4import static org.junit.Assert.assertNotNull;
5import static org.mockito.Matchers.any;
6import static org.mockito.Matchers.anyLong;
7import static org.mockito.Matchers.eq;
8import static org.mockito.Mockito.doThrow;
9import static org.mockito.Mockito.mock;
10import static org.mockito.Mockito.times;
11import static org.mockito.Mockito.verify;
12import static org.mockito.Mockito.when;
13
14import java.io.IOException;
15import java.net.URISyntaxException;
16import java.util.ArrayList;
17import java.util.Arrays;
18import java.util.Date;
19import java.util.HashMap;
20import java.util.List;
21import java.util.Map;
22
23import org.junit.Before;
24import org.junit.Test;
25import org.mockito.ArgumentCaptor;
26
27import geniusweb.actions.Accept;
28import geniusweb.actions.Action;
29import geniusweb.actions.EndNegotiation;
30import geniusweb.actions.Offer;
31import geniusweb.actions.PartyId;
32import geniusweb.deadline.Deadline;
33import geniusweb.deadline.DeadlineTime;
34import geniusweb.events.CurrentState;
35import geniusweb.events.ProtocolEvent;
36import geniusweb.inform.Agreements;
37import geniusweb.inform.Finished;
38import geniusweb.inform.Inform;
39import geniusweb.inform.Settings;
40import geniusweb.inform.YourTurn;
41import geniusweb.progress.Progress;
42import geniusweb.protocol.ProtocolException;
43import geniusweb.protocol.partyconnection.ProtocolToPartyConn;
44import geniusweb.protocol.partyconnection.ProtocolToPartyConnFactory;
45import geniusweb.protocol.partyconnection.ProtocolToPartyConnections;
46import geniusweb.protocol.session.TeamInfo;
47import geniusweb.references.Parameters;
48import geniusweb.references.PartyRef;
49import geniusweb.references.PartyWithParameters;
50import geniusweb.references.PartyWithProfile;
51import geniusweb.references.ProfileRef;
52import geniusweb.references.ProtocolRef;
53import tudelft.utilities.listener.Listener;
54import tudelft.utilities.logging.ReportToLogger;
55import tudelft.utilities.repository.NoResourcesNowException;
56
57/**
58 * This test tests inner workings of the SAOP protocol, AKA 'white box' testing.
59 * This adds brittleness to this test, because these internal workings may be
60 * modified as long as the public API remains working. This approach was
61 * necessary because fully testing the public API directly would lead to
62 * excessive amounts of mocking and unfocused tests. (with "focused test" we
63 * mean that a junit test should test a small part of the code and thus aid in
64 * locating the actual issue).
65 */
66public class SAOPTest {
67 private final SAOPState state = mock(SAOPState.class),
68 connectedstate = mock(SAOPState.class),
69 failstate = mock(SAOPState.class),
70 finalstate = mock(SAOPState.class);
71
72 private ProtocolRef SAOP;
73 private static final PartyId PARTY2ID = new PartyId("party2");
74 private static final PartyId PARTY1ID = new PartyId("party1");
75 private final PartyRef party1ref = mock(PartyRef.class);
76 private final PartyRef party2ref = mock(PartyRef.class);
77 private final SAOPSettings settings = mock(SAOPSettings.class);
78 private final TeamInfo team1 = mock(TeamInfo.class);
79 private final TeamInfo team2 = mock(TeamInfo.class);
80 private SAOP saop;
81 private ProtocolToPartyConnFactory factory;
82 private List connections;
83 private ProtocolToPartyConn conn1 = mock(ProtocolToPartyConn.class),
84 conn2 = mock(ProtocolToPartyConn.class);
85 private Map<PartyId, TeamInfo> partyprofiles;
86 private Progress progress = mock(Progress.class);
87 private ProfileRef profile1;
88 private ProfileRef profile2;
89 private ProtocolToPartyConnections connectionswithparties = mock(
90 ProtocolToPartyConnections.class);;
91 @SuppressWarnings("unchecked")
92 private final Listener<ProtocolEvent> testlistener = mock(Listener.class);
93 private final Parameters parameters = new Parameters();
94
95 private final long NOW = 1000;
96 private final PartyWithParameters partywithparam1 = new PartyWithParameters(
97 party1ref, parameters);
98 private final PartyWithParameters partywithparam2 = new PartyWithParameters(
99 party2ref, parameters);
100
101 private final Deadline deadlinetime = mock(DeadlineTime.class);
102
103 @Before
104 public void before()
105 throws URISyntaxException, IOException, NoResourcesNowException {
106 SAOP = new ProtocolRef("SAOP");
107
108 profile1 = mock(ProfileRef.class);
109 profile2 = mock(ProfileRef.class);
110
111 PartyWithProfile pwp1 = new PartyWithProfile(partywithparam1, profile1);
112 PartyWithProfile pwp2 = new PartyWithProfile(partywithparam2, profile2);
113 when(team1.getAllParties()).thenReturn(Arrays.asList(pwp1));
114 when(team2.getAllParties()).thenReturn(Arrays.asList(pwp2));
115
116 partyprofiles = new HashMap<>();
117 partyprofiles.put(PARTY1ID, team1);
118 partyprofiles.put(PARTY2ID, team2);
119
120 when(deadlinetime.getDuration()).thenReturn(1000l);
121
122 List<TeamInfo> teams = new ArrayList<>();
123 teams.add(team1);
124 teams.add(team2);
125 when(settings.getTeams()).thenReturn(teams);
126 when(settings.getAllParties()).thenReturn(Arrays.asList(pwp1, pwp2));
127 when(settings.getDeadline()).thenReturn(deadlinetime);
128
129 factory = mock(ProtocolToPartyConnFactory.class);
130 connections = mock(List.class);
131 when(factory.connect(any(List.class))).thenReturn(connections);
132
133 // hack the state.with(connection) stuff simplistically
134
135 when(conn1.getParty()).thenReturn(PARTY1ID);
136 when(conn2.getParty()).thenReturn(PARTY2ID);
137
138 mockState(connectedstate, "connected state");
139 mockState(state, "initial state");
140 mockState(finalstate, "final state");
141 when(finalstate.isFinal(anyLong())).thenReturn(true);
142 mockState(failstate, "fail state");
143 when(failstate.isFinal(anyLong())).thenReturn(true);
144
145 when(connectionswithparties.get(eq(PARTY1ID))).thenReturn(conn1);
146 when(connectionswithparties.get(eq(PARTY2ID))).thenReturn(conn2);
147 // HACK thenReturn twice, so that 2nd call to iterator() returns new
148 // iterator instead of the old one
149 when(connectionswithparties.iterator())
150 .thenReturn(Arrays.asList(conn1, conn2).iterator())
151 .thenReturn(Arrays.asList(conn1, conn2).iterator());
152 saop = new SAOP(state, new ReportToLogger("test"));
153 saop.addListener(testlistener);
154
155 Map<PartyId, PartyWithProfile> profilesmap = new HashMap<>();
156 profilesmap.put(PARTY1ID, pwp1);
157 profilesmap.put(PARTY2ID, pwp2);
158 when(state.getPartyProfiles()).thenReturn(profilesmap);
159
160 }
161
162 /**
163 * All states are more or less the same, but are slightly modified
164 *
165 * @param state the state to mock (must be already
166 * @param asText
167 */
168 private void mockState(SAOPState state, String asText) {
169 when(state.getSettings()).thenReturn(settings);
170 when(state.getConnections()).thenReturn(connectionswithparties);
171
172 when(state.getProgress()).thenReturn(progress);
173 when(state.with(any(ProtocolToPartyConn.class),
174 any(PartyWithProfile.class))).thenReturn(connectedstate);
175 when(state.getNextActor()).thenReturn(PARTY1ID);
176 when(state.with(any(PartyId.class), any(EndNegotiation.class)))
177 .thenReturn(finalstate);
178 when(state.with(any(PartyId.class), any(Accept.class)))
179 .thenReturn(state);
180 when(state.with(any(Progress.class))).thenReturn(state);
181 when(state.toString()).thenReturn(asText);
182 when(state.with(any(ProtocolException.class))).thenReturn(failstate);
183 when(state.getAgreements()).thenReturn(mock(Agreements.class));
184 }
185
186 @Test
187 public void testConstructor() {
188 SAOPState state1 = mock(SAOPState.class);
189 Deadline dl = mock(Deadline.class);
190 SAOPSettings set = mock(SAOPSettings.class);
191 when(state1.getSettings()).thenReturn(set);
192 when(set.getDeadline()).thenReturn(dl);
193 when(dl.getDuration()).thenReturn(1000l);
194 new SAOP(state1, new ReportToLogger("test"));
195 verify(state1, times(0)).with(any(ProtocolException.class));
196 verify(testlistener, times(0)).notifyChange(any(CurrentState.class));
197 }
198
199 @Test
200 public void testConnect()
201 throws InterruptedException, IOException, NoResourcesNowException {
202 saop.connect(factory);
203
204 assertEquals(connectedstate, saop.getState());
205 verify(state, times(0)).with(any(ProtocolException.class));
206 verify(testlistener, times(0)).notifyChange(any(CurrentState.class));
207 }
208
209 @Test(expected = IOException.class)
210 public void testConnectFailingConnection()
211 throws InterruptedException, IOException, NoResourcesNowException {
212 // override the factory connect to throw IOException. This exception
213 // should boil up and cause the connect to fail.
214 when(factory.connect(any(List.class)))
215 .thenThrow(new IOException("Refusing connection"));
216 saop.connect(factory);
217 verify(state, times(0)).with(any(ProtocolException.class));
218 verify(testlistener, times(0)).notifyChange(any(CurrentState.class));
219 }
220
221 @Test
222 public void testConnectRetry()
223 throws InterruptedException, IOException, NoResourcesNowException {
224 // override the factory connect to throw NoResourcesNowException and
225 // then succeed 2nd time.
226 when(factory.connect(any(List.class)))
227 .thenThrow(new NoResourcesNowException("Refusing connection",
228 new Date(System.currentTimeMillis() + 500)))
229 .thenReturn(connections);
230 saop.connect(factory);
231
232 assertEquals(connectedstate, saop.getState());
233 verify(state, times(0)).with(any(ProtocolException.class));
234 verify(testlistener, times(0)).notifyChange(any(CurrentState.class));
235 }
236
237 @Test
238 public void testSetup() throws ProtocolException, IOException {
239
240 saop.setupParties();
241
242 // were the connections attached properly?
243 verify(conn1, times(1)).addListener(any(Listener.class));
244 verify(conn2, times(1)).addListener(any(Listener.class));
245
246 // were the settings send to each party?
247 verify(conn1, times(1)).send(any(Settings.class));
248 ArgumentCaptor<Settings> actualsettings = ArgumentCaptor
249 .forClass(Settings.class);
250 verify(conn1).send(actualsettings.capture());
251 assertEquals(
252 new Settings(PARTY1ID, profile1, SAOP, progress, parameters),
253 actualsettings.getValue());
254
255 verify(conn2, times(1)).send(any(Settings.class));
256 verify(conn2).send(actualsettings.capture());
257 assertEquals(
258 new Settings(PARTY2ID, profile2, SAOP, progress, parameters),
259 actualsettings.getValue());
260 verify(state, times(0)).with(any(ProtocolException.class));
261 verify(testlistener, times(0)).notifyChange(any(CurrentState.class));
262
263 }
264
265 @Test
266 public void testActionRequestWrongActor() {
267 saop.actionRequest(conn2, mock(EndNegotiation.class));
268
269 verify(state, times(1)).with(any(ProtocolException.class));
270 verify(testlistener, times(1)).notifyChange(any(CurrentState.class));
271 }
272
273 @Test
274 public void testActionRequest() throws IOException {
275 when(state.getNextActor()).thenReturn(PARTY1ID);
276 when(state.with(any(PartyId.class), any(Action.class)))
277 .thenReturn(state);
278
279 saop.actionRequest(conn1, mock(EndNegotiation.class));
280
281 verify(state, times(0)).with(any(ProtocolException.class));
282 verify(state, times(1)).with(eq(PARTY1ID), any(EndNegotiation.class));
283 verify(connectionswithparties, times(1)).broadcast(any(Inform.class));
284
285 // state.getNextActor() is frozen to PARTY1 by our mocking
286 verify(conn1, times(1)).send(any(YourTurn.class));
287 verify(conn2, times(0)).send(any(YourTurn.class));
288 verify(testlistener, times(0)).notifyChange(any(CurrentState.class));
289 }
290
291 @Test
292 public void testFinalActionRequest() throws IOException {
293 when(state.getNextActor()).thenReturn(PARTY1ID);
294 when(state.with(any(PartyId.class), any(EndNegotiation.class)))
295 .thenReturn(finalstate);
296 // when(finalstate.getAgreements()).thenReturn(mock(Agreements.class));
297
298 saop.actionRequest(conn1, mock(EndNegotiation.class));
299
300 verify(state, times(0)).with(any(ProtocolException.class));
301 verify(state, times(1)).with(eq(PARTY1ID), any(EndNegotiation.class));
302 verify(connectionswithparties, times(1)).broadcast(any(Finished.class));
303 verify(testlistener, times(1)).notifyChange(any(CurrentState.class));
304
305 verify(conn1, times(1)).send(any(YourTurn.class));
306 verify(conn2, times(1)).send(any(YourTurn.class));
307 }
308
309 @Test
310 public void testStart() {
311 saop.start(factory);
312 }
313
314 @Test
315 public void testActionFailNextYourturn() throws IOException {
316 doThrow(new IOException("fail sending yourturn")).when(conn1)
317 .send(any(YourTurn.class));
318 // CHECK is the state really final after an exception?
319 when(state.with(any(ProtocolException.class))).thenReturn(finalstate);
320 // when(state.getAgreements()).thenReturn(mock(Agreements.class));
321 saop.actionRequest(conn1, mock(Accept.class));
322
323 verify(state, times(1)).with(any(ProtocolException.class));
324 verify(testlistener, times(1)).notifyChange(any(CurrentState.class));
325 }
326
327 @Test
328 public void testActionNotTheTurn() throws IOException {
329 doThrow(new IOException("fail sending yourturn")).when(conn1)
330 .send(any(YourTurn.class));
331 // when(failstate.getAgreements()).thenReturn(mock(Agreements.class));
332 // not turn of conn2.
333 saop.actionRequest(conn2, mock(EndNegotiation.class));
334
335 verify(state, times(1)).with(any(ProtocolException.class));
336 verify(testlistener, times(1)).notifyChange(any(CurrentState.class));
337 }
338
339 @Test
340 public void testActionInFinalState() throws IOException {
341 saop = new SAOP(finalstate, new ReportToLogger("test"));
342 // when(finalstate.getAgreements()).thenReturn(mock(Agreements.class));
343
344 saop.actionRequest(conn1, mock(Offer.class));
345
346 verify(finalstate, times(0)).with(any(ProtocolException.class));
347 verify(testlistener, times(0)).notifyChange(any());
348 }
349
350 @Test
351 public void testDescription() {
352 assertNotNull(saop.getDescription());
353 }
354
355 @Test(expected = IllegalStateException.class)
356 public void testAddParticipant() {
357 saop.addParticipant(null);
358 }
359}
Note: See TracBrowser for help on using the repository browser.