1 | from datetime import datetime, timedelta
|
---|
2 | import time
|
---|
3 | import unittest
|
---|
4 | from unittest.mock import Mock
|
---|
5 |
|
---|
6 | from tudelft.utilities.listener.Listener import Listener
|
---|
7 | from tudelft.utilities.repository.NoResourcesNowException import NoResourcesNowException
|
---|
8 | from tudelft_utilities_logging.ReportToLogger import ReportToLogger
|
---|
9 | from uri.uri import URI
|
---|
10 |
|
---|
11 | from geniusweb.actions.Accept import Accept
|
---|
12 | from geniusweb.actions.Action import Action
|
---|
13 | from geniusweb.actions.EndNegotiation import EndNegotiation
|
---|
14 | from geniusweb.actions.Offer import Offer
|
---|
15 | from geniusweb.actions.PartyId import PartyId
|
---|
16 | from geniusweb.deadline.Deadline import Deadline
|
---|
17 | from geniusweb.deadline.DeadlineTime import DeadlineTime
|
---|
18 | from geniusweb.events.CurrentState import CurrentState
|
---|
19 | from geniusweb.inform.ActionDone import ActionDone
|
---|
20 | from geniusweb.inform.Agreements import Agreements
|
---|
21 | from geniusweb.inform.Finished import Finished
|
---|
22 | from geniusweb.inform.Inform import Inform
|
---|
23 | from geniusweb.inform.Settings import Settings
|
---|
24 | from geniusweb.inform.YourTurn import YourTurn
|
---|
25 | from geniusweb.progress.Progress import Progress
|
---|
26 | from geniusweb.protocol.ProtocolException import ProtocolException
|
---|
27 | from geniusweb.protocol.partyconnection.ProtocolToPartyConn import ProtocolToPartyConn
|
---|
28 | from geniusweb.protocol.partyconnection.ProtocolToPartyConnFactory import ProtocolToPartyConnFactory
|
---|
29 | from geniusweb.protocol.partyconnection.ProtocolToPartyConnections import ProtocolToPartyConnections
|
---|
30 | from geniusweb.protocol.session.TeamInfo import TeamInfo
|
---|
31 | from geniusweb.protocol.session.saop.SAOP import SAOP
|
---|
32 | from geniusweb.protocol.session.saop.SAOPSettings import SAOPSettings
|
---|
33 | from geniusweb.protocol.session.saop.SAOPState import SAOPState
|
---|
34 | from geniusweb.references.Parameters import Parameters
|
---|
35 | from geniusweb.references.PartyRef import PartyRef
|
---|
36 | from geniusweb.references.PartyWithParameters import PartyWithParameters
|
---|
37 | from geniusweb.references.PartyWithProfile import PartyWithProfile
|
---|
38 | from geniusweb.references.ProfileRef import ProfileRef
|
---|
39 | from geniusweb.references.ProtocolRef import ProtocolRef
|
---|
40 |
|
---|
41 |
|
---|
42 | class SAOPTest(unittest.TestCase):
|
---|
43 | '''
|
---|
44 | This test tests inner workings of the SAOP protocol, AKA 'white box' testing.
|
---|
45 | This adds brittleness to this test, because these internal workings may be
|
---|
46 | modified as long as the public API remains working. This approach was
|
---|
47 | necessary because fully testing the public API directly would lead to
|
---|
48 | excessive amounts of Mocking and unfocused tests. (with "focused test" we
|
---|
49 | mean that a junit test should test a small part of the code and thus aid in
|
---|
50 | locating the actual issue).
|
---|
51 | '''
|
---|
52 | PARTY2ID = PartyId("party2")
|
---|
53 | PARTY1ID = PartyId("party1")
|
---|
54 | parameters = Parameters()
|
---|
55 | SAOPPROTOCOL = ProtocolRef(URI("SAOP"))
|
---|
56 |
|
---|
57 | NOW = 1000
|
---|
58 | DEADLINE =1000
|
---|
59 | party1ref = PartyRef(URI("party1"))
|
---|
60 | party2ref = PartyRef(URI("party2"))
|
---|
61 | partywithparam1 = PartyWithParameters(party1ref, parameters)
|
---|
62 | partywithparam2 = PartyWithParameters(party2ref, parameters)
|
---|
63 |
|
---|
64 |
|
---|
65 | def setUp(self):
|
---|
66 | self.state = Mock(SAOPState)
|
---|
67 | self.connectedstate = Mock(SAOPState)
|
---|
68 | self.failstate = Mock(SAOPState)
|
---|
69 | self.finalstate = Mock(SAOPState)
|
---|
70 |
|
---|
71 | self.settings = Mock(SAOPSettings)
|
---|
72 | self.team1 = Mock(TeamInfo)
|
---|
73 | self.team2 = Mock(TeamInfo)
|
---|
74 | self.conn1 = Mock(ProtocolToPartyConn)
|
---|
75 | self.conn2 = Mock(ProtocolToPartyConn);
|
---|
76 | self.progress = Mock(Progress)
|
---|
77 | self.testlistener = Mock(Listener)
|
---|
78 |
|
---|
79 | self.deadlinetime = Mock(DeadlineTime)
|
---|
80 |
|
---|
81 |
|
---|
82 | self.profile1 = Mock(ProfileRef)
|
---|
83 | self.profile2 = Mock(ProfileRef)
|
---|
84 |
|
---|
85 | pwp1 = PartyWithProfile(self.partywithparam1, self.profile1);
|
---|
86 | pwp2 = PartyWithProfile(self.partywithparam2, self.profile2);
|
---|
87 | self.team1.getParties=Mock(return_value=[pwp1])
|
---|
88 | self.team2.getParties=Mock(return_value=[pwp2])
|
---|
89 |
|
---|
90 | partyprofiles = {}
|
---|
91 | partyprofiles[self.PARTY1ID]= self.team1
|
---|
92 | partyprofiles[self.PARTY2ID]= self.team2
|
---|
93 |
|
---|
94 |
|
---|
95 | self.pwpmap = {}
|
---|
96 | self.pwpmap[self.PARTY1ID]=pwp1
|
---|
97 | self.pwpmap[self.PARTY2ID]=pwp2
|
---|
98 | self.deadlinetime.getDuration=Mock(return_value=self.DEADLINE)
|
---|
99 |
|
---|
100 | teams = []
|
---|
101 | teams.append(self.team1);
|
---|
102 | teams.append(self.team2);
|
---|
103 | self.settings.getTeams=Mock(return_value=teams)
|
---|
104 | self.settings.getAllParties=Mock(return_value=[pwp1, pwp2])
|
---|
105 | self.settings.getDeadline=Mock(return_value=self.deadlinetime)
|
---|
106 |
|
---|
107 | self.factory = Mock(ProtocolToPartyConnFactory)
|
---|
108 | # connections = Mock(List);
|
---|
109 | connections = [self.conn1, self.conn2]
|
---|
110 | self.factory.connectAll=Mock(return_value=connections)
|
---|
111 |
|
---|
112 | # hack the state.with(connection) stuff simplistically
|
---|
113 |
|
---|
114 | self.conn1.getParty=Mock(return_value=self.PARTY1ID)
|
---|
115 | self.conn2.getParty=Mock(return_value=self.PARTY2ID)
|
---|
116 |
|
---|
117 | self.MockState(self.connectedstate, "connected state", True)
|
---|
118 | self.MockState(self.state, "running state",True);
|
---|
119 |
|
---|
120 | self.MockState(self.finalstate, "final state",True);
|
---|
121 | self.finalstate.isFinal=Mock(return_value=True)
|
---|
122 | self.MockState(self.failstate, "fail state", True);
|
---|
123 | self.failstate.isFinal=Mock(return_value=True)
|
---|
124 |
|
---|
125 | self.connectionswithparties = ProtocolToPartyConnections([self.conn1, self.conn2])
|
---|
126 |
|
---|
127 | # HACK thenReturn twice, so that 2nd call to iterator() returns new
|
---|
128 | # iterator instead of the old one
|
---|
129 | profilesmap = {}
|
---|
130 | profilesmap[self.PARTY1ID]= pwp1
|
---|
131 | profilesmap[self.PARTY2ID]= pwp2
|
---|
132 | self.state.getPartyProfiles=Mock(return_value=profilesmap)
|
---|
133 |
|
---|
134 | self.saop = SAOP(self.state, ReportToLogger("test"),
|
---|
135 | self.connectionswithparties)
|
---|
136 | self.saop.addListener(self.testlistener)
|
---|
137 |
|
---|
138 |
|
---|
139 | def MockState(self, state:SAOPState , asText:str, isConnected:bool ) :
|
---|
140 | '''
|
---|
141 | All states are more or less the same, but are slightly modified
|
---|
142 |
|
---|
143 | @param state the state to Mock (must be already
|
---|
144 | @param asText short name for the state, for debugging
|
---|
145 | @param bool true if parties are connected
|
---|
146 | '''
|
---|
147 | state.getSettings=Mock(return_value=self.settings) #type:ignore
|
---|
148 | if isConnected:
|
---|
149 | state.getConnections=Mock(return_value=[self.PARTY1ID, self.PARTY2ID]) #type:ignore
|
---|
150 | else:
|
---|
151 | state.getConnections=Mock(return_value=[]) #type:ignore
|
---|
152 | # when(state.getConnections()).thenReturn(connectionswithparties);
|
---|
153 |
|
---|
154 | state.getProgress=Mock(return_value=self.progress) #type:ignore
|
---|
155 | state.WithParty=Mock(return_value=self.connectedstate) #type:ignore
|
---|
156 | state._getNextActor=Mock(return_value=self.PARTY1ID) #type:ignore
|
---|
157 | state.WithAction= Mock(side_effect=lambda pid, act: #type:ignore
|
---|
158 | self.finalstate if isinstance(act, EndNegotiation) else\
|
---|
159 | state )
|
---|
160 |
|
---|
161 | state.WithProgress=Mock(return_value=state) #type:ignore
|
---|
162 | state.__repr__=Mock(return_value=asText) #type:ignore
|
---|
163 | state.WithException=Mock(return_value=self.failstate) #type:ignore
|
---|
164 | state.getAgreements=Mock(return_value=Agreements()) #type:ignore
|
---|
165 |
|
---|
166 | #explicit default. This differs from Java, where default bools to false
|
---|
167 | state.isFinal=Mock(return_value=False) #type:ignore
|
---|
168 | state.getPartyProfiles = Mock(return_value=self.pwpmap) #type:ignore
|
---|
169 |
|
---|
170 | def testConstructor(self):
|
---|
171 | state1 = Mock(SAOPState)
|
---|
172 | dl = Mock(Deadline)
|
---|
173 | set = Mock(SAOPSettings)
|
---|
174 | state1.getSettings=Mock(return_value=set)
|
---|
175 | set.getDeadline=Mock(return_value=dl)
|
---|
176 | dl.getDuration=Mock(return_value=1000)
|
---|
177 | SAOP(state1, ReportToLogger("test"), self.connectionswithparties)
|
---|
178 | self.assertEqual([], self.state.WithException.call_args_list)
|
---|
179 | self.assertEqual([], self. testlistener.notifyChange.call_args_list)
|
---|
180 |
|
---|
181 |
|
---|
182 | def testConnect(self):
|
---|
183 | self.saop._connect(self.factory)
|
---|
184 |
|
---|
185 | self.assertEqual(self.connectedstate, self.saop.getState())
|
---|
186 | self.assertEqual([], self.state.WithException.call_args_list)
|
---|
187 | self.assertEqual([], self.testlistener.notifyChange.call_args_list)
|
---|
188 |
|
---|
189 |
|
---|
190 | def testConnectFailingConnection(self):
|
---|
191 | # override the factory connect to throw IOException. This exception
|
---|
192 | # should boil up and cause the connect to fail.
|
---|
193 | def __raise(refs):
|
---|
194 | raise ConnectionError("Refusing connection")
|
---|
195 | self.factory.connectAll=Mock(side_effect=__raise)
|
---|
196 | this=self
|
---|
197 | self.assertRaises(ConnectionError, lambda:this.saop._connect(this.factory))
|
---|
198 | # following was never reached?
|
---|
199 | #verify(state, times(0)).with(any(ProtocolException));
|
---|
200 | #verify(testlistener, times(0)).notifyChange(any(CurrentState));
|
---|
201 |
|
---|
202 | def testConnectRetry(self):
|
---|
203 | # override the factory connect to throw NoResourcesNowException and
|
---|
204 | # then succeed 2nd time.
|
---|
205 | this=self
|
---|
206 |
|
---|
207 | firsttime=True
|
---|
208 | def __throwsThenSucceeds():
|
---|
209 | if firsttime:
|
---|
210 | firsttime=False
|
---|
211 | raise NoResourcesNowException("Refusing connection",\
|
---|
212 | datetime.now() + timedelta(seconds=0.5))
|
---|
213 | return this.connections
|
---|
214 | self.factory.connect=Mock(side_effect=__throwsThenSucceeds)
|
---|
215 |
|
---|
216 | self.saop._connect(self.factory)
|
---|
217 |
|
---|
218 | self.assertEqual(self.connectedstate, self.saop.getState())
|
---|
219 | #verify(state, times(0)).with(any(ProtocolException));
|
---|
220 | self.assertEqual([], [e \
|
---|
221 | for e in self.state.WithException.call_args_list\
|
---|
222 | if not isinstance( e,ProtocolException)])
|
---|
223 | self.assertEqual([],self.testlistener.notifyChange.call_args_list)
|
---|
224 |
|
---|
225 | def testSetup(self) :
|
---|
226 | self.saop._setupParties()
|
---|
227 |
|
---|
228 | # were the connections attached properly?
|
---|
229 | self.assertEqual(1, len(self.conn1.addListener.call_args_list))
|
---|
230 | self.assertEqual(1, len(self.conn2.addListener.call_args_list))
|
---|
231 |
|
---|
232 | # were the settings send to each party?
|
---|
233 | self.assertEqual(1, len([call for call in self.conn1.send.call_args_list \
|
---|
234 | if isinstance(call[0][0],Settings)]))
|
---|
235 | self.assertEqual(
|
---|
236 | Settings(self.PARTY1ID, self.profile1, self.SAOPPROTOCOL, self.progress, self.parameters),
|
---|
237 | self.conn1.send.call_args_list[0][0][0])
|
---|
238 |
|
---|
239 | self.assertEqual(1, len([call for call in self.conn2.send.call_args_list \
|
---|
240 | if isinstance(call[0][0],Settings)]))
|
---|
241 | self.assertEqual(
|
---|
242 | Settings(self.PARTY2ID, self.profile2, self.SAOPPROTOCOL, self.progress, self.parameters),
|
---|
243 | self.conn2.send.call_args_list[0][0][0])
|
---|
244 |
|
---|
245 | self.assertEqual([], self.state.WithException.call_args_list)
|
---|
246 | self.assertEqual([], [v for v in self.testlistener.notifyChange.call_args_list if isinstance(v, CurrentState)])
|
---|
247 |
|
---|
248 |
|
---|
249 | def testActionRequestWrongActor(self):
|
---|
250 | self.saop._actionRequest(self.conn2, Mock(EndNegotiation))
|
---|
251 | self.assertEqual(1, len([call for call in self.state.WithException.call_args_list\
|
---|
252 | if isinstance(call[0][0], ProtocolException) ]))
|
---|
253 | self.assertEqual(1, len([call for call in self.testlistener.notifyChange.call_args_list
|
---|
254 | if isinstance(call[0][0], CurrentState)]))
|
---|
255 |
|
---|
256 | def testActionRequest(self):
|
---|
257 | self.saop._nextTurn()
|
---|
258 |
|
---|
259 | self.state._getNextActor=Mock(return_value=self.PARTY1ID)
|
---|
260 | self.state.withAction = Mock(return_value=self.finalstate)
|
---|
261 |
|
---|
262 | self.saop._actionRequest(self.conn1, Mock(EndNegotiation))
|
---|
263 |
|
---|
264 | self.assertEqual([] , [call for call in self.state.WithException.call_args_list
|
---|
265 | if isinstance(call[0][0], ProtocolException)])
|
---|
266 | #verify(state, times(1)).with(eq(PARTY1ID), any(EndNegotiation));
|
---|
267 | self.assertEqual(1, len([call for call in self.state.WithAction.call_args_list
|
---|
268 | if call[0][0]==self.PARTY1ID and\
|
---|
269 | isinstance(call[0][1], EndNegotiation)]))
|
---|
270 | # verify broadcast
|
---|
271 | self.assertEqual(1, len([call for call in self.conn1.send.call_args_list
|
---|
272 | if isinstance(call[0][0], ActionDone)]))
|
---|
273 | self.assertEqual(1, len([call for call in self.conn2.send.call_args_list
|
---|
274 | if isinstance(call[0][0], ActionDone)]))
|
---|
275 |
|
---|
276 | # state.getNextActor() is frozen to PARTY1 by our Mocking
|
---|
277 | #verify(conn1, times(1)).send(isA(YourTurn));
|
---|
278 | self.assertEqual(1, len([call for call in self.conn1.send.call_args_list
|
---|
279 | if isinstance(call[0][0], YourTurn)]))
|
---|
280 | #verify(conn2, times(0)).send(isA(YourTurn));
|
---|
281 | self.assertEqual(0, len([call for call in self.conn2.send.call_args_list
|
---|
282 | if isinstance(call[0][0], YourTurn)]))
|
---|
283 | #listener should be informed about final state.
|
---|
284 | #verify(testlistener, times(0)).notifyChange(any(CurrentState));
|
---|
285 | self.assertEqual(1, len([call for call in self.testlistener.notifyChange.call_args_list
|
---|
286 | if isinstance(call[0][0], CurrentState)]))
|
---|
287 |
|
---|
288 | def testFinalActionRequest(self):
|
---|
289 | this=self
|
---|
290 | #FIXME double mock??
|
---|
291 | #self.state.getNextActor=Mock(return_value=self.PARTY1ID)
|
---|
292 | def __nextstate(pid:PartyId, act:Action):
|
---|
293 | if isinstance(act, EndNegotiation):
|
---|
294 | return this.finalstate
|
---|
295 |
|
---|
296 | self.state.withAction=Mock(side_effect=__nextstate)
|
---|
297 | # when(finalstate.getAgreements()).thenReturn(Mock(Agreements));
|
---|
298 |
|
---|
299 | self.saop._nextTurn() # ensure we send YourTurn to party1.
|
---|
300 | self.saop._actionRequest(self.conn1, Mock(EndNegotiation))
|
---|
301 |
|
---|
302 | #verify(state, times(0)).with(any(ProtocolException));
|
---|
303 | self.assertEqual([], [call for call in self.state.WithException.call_args_list
|
---|
304 | if isinstance(call[0][0], ProtocolException) ])
|
---|
305 | #verify(state, times(1)).with(eq(PARTY1ID), any(EndNegotiation));
|
---|
306 | self.assertEqual(1, len([call for call in self.state.WithAction.call_args_list\
|
---|
307 | if isinstance(call[0][1], EndNegotiation)]))
|
---|
308 |
|
---|
309 | # verify broadcast
|
---|
310 | #erify(conn1, times(1)).send(isA(Finished));
|
---|
311 | self.assertEqual(1, len([call for call in self.conn1.send.call_args_list
|
---|
312 | if isinstance(call[0][0], Finished)]))
|
---|
313 |
|
---|
314 | #verify(conn2, times(1)).send(isA(Finished));
|
---|
315 | self.assertEqual(1, len([call for call in self.conn2.send.call_args_list
|
---|
316 | if isinstance(call[0][0], Finished)]))
|
---|
317 |
|
---|
318 | #verify(testlistener, times(1)).notifyChange(any(CurrentState));
|
---|
319 | self.assertEqual(1, len([call for call in self.testlistener.notifyChange.call_args_list
|
---|
320 | if isinstance(call[0][0], CurrentState)]))
|
---|
321 |
|
---|
322 | #verify(conn1, times(1)).send(isA(YourTurn));
|
---|
323 | self.assertEqual(1, len([call for call in self.conn1.send.call_args_list
|
---|
324 | if isinstance(call[0][0], YourTurn)]))
|
---|
325 | #verify(conn2, times(0)).send(isA(YourTurn));
|
---|
326 | self.assertEqual( [] , [call for call in self.conn2.send.call_args_list
|
---|
327 | if isinstance(call[0][0], YourTurn)])
|
---|
328 |
|
---|
329 | def testStart(self):
|
---|
330 | self.saop.start(self.factory)
|
---|
331 |
|
---|
332 | def testActionFailNextYourturn(self):
|
---|
333 | this=self
|
---|
334 | def __throwExc(inf:Inform):
|
---|
335 | if isinstance(inf, YourTurn):
|
---|
336 | raise ConnectionError("fail sending yourturn")
|
---|
337 | self.conn1.send=Mock(side_effect=__throwExc)
|
---|
338 | # CHECK is the state really final after an exception?
|
---|
339 | self.state.WithException=Mock(return_value=this.finalstate)
|
---|
340 | # when(state.getAgreements()).thenReturn(Mock(Agreements));
|
---|
341 | self.saop._actionRequest(self.conn1, Mock(Accept))
|
---|
342 |
|
---|
343 |
|
---|
344 | #verify(state, times(1)).with(any(ProtocolException));
|
---|
345 | self.assertEqual( 1, len([call for call in self.state.WithException.call_args_list
|
---|
346 | if isinstance(call[0][0], ProtocolException) ]))
|
---|
347 | #verify(testlistener, times(1)).notifyChange(any(CurrentState));
|
---|
348 | self.assertEqual(1, len([call for call in self.testlistener.notifyChange.call_args_list
|
---|
349 | if isinstance(call[0][0], CurrentState)]))
|
---|
350 |
|
---|
351 | def testActionNotTheTurn(self) :
|
---|
352 | def __throwExc(inf:Inform):
|
---|
353 | if isinstance(inf, YourTurn):
|
---|
354 | raise ConnectionError("fail sending yourturn")
|
---|
355 | self.conn1.send=Mock(side_effect=__throwExc)
|
---|
356 |
|
---|
357 | # when(failstate.getAgreements()).thenReturn(Mock(Agreements));
|
---|
358 | # not turn of conn2.
|
---|
359 | self.saop._actionRequest(self.conn2, Mock(EndNegotiation))
|
---|
360 |
|
---|
361 | #verify(state, times(1)).with(any(ProtocolException));
|
---|
362 | self.assertEqual( 1, len([call for call in self.state.WithException.call_args_list
|
---|
363 | if isinstance(call[0][0], ProtocolException) ]))
|
---|
364 | #verify(testlistener, times(1)).notifyChange(any(CurrentState));
|
---|
365 | self.assertEqual(1, len([call for call in self.testlistener.notifyChange.call_args_list
|
---|
366 | if isinstance(call[0][0], CurrentState)]))
|
---|
367 |
|
---|
368 |
|
---|
369 | def testActionInFinalState(self):
|
---|
370 | saop = SAOP(self.finalstate, ReportToLogger("test"),
|
---|
371 | self.connectionswithparties);
|
---|
372 | # when(finalstate.getAgreements()).thenReturn(Mock(Agreements));
|
---|
373 |
|
---|
374 | saop._actionRequest(self.conn1, Mock(Offer))
|
---|
375 |
|
---|
376 | #verify(finalstate, times(0)).with(any(ProtocolException));
|
---|
377 | self.assertEqual( [], [call for call in self.state.WithException.call_args_list
|
---|
378 | if isinstance(call[0][0], ProtocolException) ])
|
---|
379 | #verify(testlistener, times(0)).notifyChange(any());
|
---|
380 | self.assertEqual([], self.testlistener.notifyChange.call_args_list)
|
---|
381 |
|
---|
382 | def testDescription(self):
|
---|
383 | self.assertNotEquals(None,self.saop.getDescription())
|
---|
384 |
|
---|
385 | def testAddParticipant(self):
|
---|
386 | self.assertRaises(ValueError, lambda:self.saop.addParticipant(None))
|
---|
387 |
|
---|
388 | def testDeadlineTimer(self):
|
---|
389 | unconnectedstate = Mock(SAOPState)
|
---|
390 | self.MockState(unconnectedstate, "unconnected state", False)
|
---|
391 | saopempty = SAOP(unconnectedstate, ReportToLogger("test"),
|
---|
392 | ProtocolToPartyConnections([]))
|
---|
393 | saopempty.addListener(self.testlistener)
|
---|
394 |
|
---|
395 | saopempty.start(self.factory);
|
---|
396 | # verify(testlistener, times(0)).notifyChange(any(CurrentState.class));
|
---|
397 | self.assertEqual([], [call for call in self.testlistener.notifyChange.call_args_list
|
---|
398 | if isinstance(call[0][0], CurrentState) ])
|
---|
399 |
|
---|
400 | #verify(conn1, times(1)).send(isA(YourTurn.class));
|
---|
401 | self.assertEqual(1, len([call for call in self.conn1.send.call_args_list
|
---|
402 | if isinstance(call[0][0], YourTurn)]))
|
---|
403 | time.sleep( (self.DEADLINE + SAOP._TIME_MARGIN + 100)/1000.)
|
---|
404 | #verify(testlistener, times(1)).notifyChange(any(CurrentState.class));
|
---|
405 | self.assertEqual(1, len([call for call in self.testlistener.notifyChange.call_args_list
|
---|
406 | if isinstance(call[0][0], CurrentState)]))
|
---|
407 | #verify(conn1, times(1)).send(isA(Finished.class));
|
---|
408 | self.assertEqual(1, len([call for call in self.conn1.send.call_args_list
|
---|
409 | if isinstance(call[0][0], Finished)]))
|
---|
410 |
|
---|
411 |
|
---|