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

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

Multiple learns with repeated tournament, maven use https.

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