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

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

some minor fixes

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