1 | from datetime import datetime
|
---|
2 | import json
|
---|
3 | from typing import List
|
---|
4 | import unittest
|
---|
5 | from unittest.mock import Mock
|
---|
6 |
|
---|
7 | from pyson.ObjectMapper import ObjectMapper
|
---|
8 | from unitpy.GeneralTests import GeneralTests
|
---|
9 |
|
---|
10 | from geniusweb.actions.Action import Action
|
---|
11 | from geniusweb.actions.PartyId import PartyId
|
---|
12 | from geniusweb.progress.Progress import Progress
|
---|
13 | from geniusweb.progress.ProgressTime import ProgressTime
|
---|
14 | from geniusweb.protocol.ProtocolException import ProtocolException
|
---|
15 | from geniusweb.protocol.session.TeamInfo import TeamInfo
|
---|
16 | from geniusweb.protocol.session.mopac.MOPACSettings import MOPACSettings
|
---|
17 | from geniusweb.protocol.session.mopac.MOPACState import MOPACState
|
---|
18 | from geniusweb.protocol.session.mopac.PartyStates import PartyStates
|
---|
19 | from geniusweb.protocol.session.mopac.phase.OfferPhase import OfferPhase
|
---|
20 | from geniusweb.protocol.session.mopac.phase.Phase import PHASE_MAXTIME, Phase, \
|
---|
21 | PHASE_MINTIME
|
---|
22 | from geniusweb.references.Parameters import Parameters
|
---|
23 | from geniusweb.references.PartyWithParameters import PartyWithParameters
|
---|
24 | from geniusweb.references.PartyWithProfile import PartyWithProfile
|
---|
25 | from geniusweb.references.ProfileRef import ProfileRef
|
---|
26 | from geniusweb.voting.votingevaluators.LargestAgreement import LargestAgreement
|
---|
27 |
|
---|
28 |
|
---|
29 | class MOPACStateTest (unittest.TestCase, GeneralTests[MOPACState]):
|
---|
30 | maxDiff=None
|
---|
31 |
|
---|
32 | NOW = datetime.fromtimestamp(1001/1000.)
|
---|
33 |
|
---|
34 | jackson = ObjectMapper()
|
---|
35 |
|
---|
36 | settings = Mock(MOPACSettings)
|
---|
37 |
|
---|
38 | state = MOPACState(None,[],None, settings, {})
|
---|
39 |
|
---|
40 | PARTY1 = PartyId("party1");
|
---|
41 | PARTY2 = PartyId("party2")
|
---|
42 | PARTY3 = PartyId("party3")
|
---|
43 |
|
---|
44 |
|
---|
45 | # copy from MopacSettingsTest. We need settings here but don't want to mock
|
---|
46 | # this large structure.
|
---|
47 | mopacsettingstr = "{\"MOPACSettings\":{\"participants\":[{\"TeamInfo\":{\"parties\":[{\"party\":{\"partyref\":\"http://party1\",\"parameters\":{}},\"profile\":\"http://profile1\"}]}},{\"TeamInfo\":{\"parties\":[{\"party\":{\"partyref\":\"http://party2\",\"parameters\":{}},\"profile\":\"http://profile2\"}]}}],\"deadline\":{\"DeadlineTime\":{\"durationms\":100}},\"votingevaluator\":{\"LargestAgreement\":{}}}}";
|
---|
48 | # create real objects for the GeneralTests and for serialization tests
|
---|
49 | progress1 = ProgressTime(100, NOW)
|
---|
50 | progress2 = ProgressTime(200, NOW)
|
---|
51 |
|
---|
52 |
|
---|
53 | serialized = "{\"MOPACState\":{\"phase\":{\"OfferPhase\":{\"partyStates\":{\"powers\":{},\"notYetActed\":[],\"actions\":[],\"agreements\":{},\"walkedAway\":[],\"exceptions\":{}},\"deadline\":100,\"evaluator\":{\"LargestAgreement\":{}}}},\"actions\":[],\"progress\":{\"ProgressTime\":{\"duration\":100,\"start\":1001}},\"settings\":{\"MOPACSettings\":{\"participants\":[{\"TeamInfo\":{\"parties\":[{\"party\":{\"partyref\":\"http://party1\",\"parameters\":{}},\"profile\":\"http://profile1\"}]}},{\"TeamInfo\":{\"parties\":[{\"party\":{\"partyref\":\"http://party2\",\"parameters\":{}},\"profile\":\"http://profile2\"}]}}],\"deadline\":{\"DeadlineTime\":{\"durationms\":100}},\"votingevaluator\":{\"LargestAgreement\":{}}}},\"partyprofiles\":{}}}"
|
---|
54 |
|
---|
55 | def setUp(self):
|
---|
56 | self.partyparams1 = Mock(PartyWithParameters)
|
---|
57 | self.profile1 = PartyWithProfile(self.partyparams1,Mock(ProfileRef))
|
---|
58 | self.partyStates = PartyStates({})
|
---|
59 | self.phase1 = OfferPhase(self.partyStates, 100, LargestAgreement())
|
---|
60 | self.phase2 = OfferPhase(self.partyStates, 200, LargestAgreement())
|
---|
61 | self.params1 = Parameters().With("power", 2);
|
---|
62 | self.partyparams1.getParameters=Mock(return_value=self.params1)
|
---|
63 |
|
---|
64 | realsettings = self.jackson.parse(json.loads(self.mopacsettingstr), MOPACSettings)
|
---|
65 | party = Mock(TeamInfo)
|
---|
66 | pwithp = Mock(PartyWithParameters)
|
---|
67 | pwithp.getParameters=Mock(return_value= Parameters())
|
---|
68 | party.getParties=Mock(
|
---|
69 | return_value=[PartyWithProfile(pwithp, Mock(ProfileRef))])
|
---|
70 | party.getSize=Mock(return_value=1)
|
---|
71 | realsettings2 = realsettings.With(party)
|
---|
72 |
|
---|
73 | self.state1 = MOPACState(self.phase1, [], self.progress1, realsettings, {})
|
---|
74 | self.state1a = MOPACState(self.phase1, [], self.progress1, realsettings, {})
|
---|
75 | self.state2 = MOPACState(self.phase2, [], self.progress1, realsettings, {})
|
---|
76 | self.state3 = MOPACState(self.phase1, [Mock(Action)],
|
---|
77 | self.progress1, realsettings, {})
|
---|
78 | self.state4 = MOPACState(self.phase1, [], self.progress2,realsettings, {})
|
---|
79 | self.state5 = MOPACState(self.phase1, [], self.progress1,
|
---|
80 | realsettings2, {})
|
---|
81 | self.state6 = MOPACState(self.phase1, [], self.progress1,
|
---|
82 | realsettings,
|
---|
83 | {self.PARTY1: Mock(PartyWithProfile)})
|
---|
84 |
|
---|
85 |
|
---|
86 | def getGeneralTestData(self)-> List[List[MOPACState]] :
|
---|
87 | return [[self.state1, self.state1a],
|
---|
88 | [self.state2], [self.state3],
|
---|
89 | [self.state4], [self.state5],
|
---|
90 | [self.state6]]
|
---|
91 |
|
---|
92 | def getGeneralTestStrings(self)-> List[str]:
|
---|
93 | return [
|
---|
94 | "MOPACState.*OfferPhase.*PartyStates.*,MOPACSettings.*PartyWithProfile.*ProgressTime.*",
|
---|
95 | "MOPACState.*OfferPhase.*PartyStates.*,MOPACSettings.*PartyWithProfile.*ProgressTime.*",
|
---|
96 | "MOPACState.*OfferPhase.*PartyStates.*,MOPACSettings.*PartyWithProfile.*ProgressTime.*",
|
---|
97 | "MOPACState.*OfferPhase.*PartyStates.*,MOPACSettings.*PartyWithProfile.*ProgressTime.*",
|
---|
98 | "MOPACState.*OfferPhase.*PartyStates.*,MOPACSettings.*PartyWithProfile.*ProgressTime.*",
|
---|
99 | "MOPACState.*OfferPhase.*PartyStates.*,MOPACSettings.*PartyWithProfile.*ProgressTime.*"]
|
---|
100 |
|
---|
101 | def testsmokeTest(self):
|
---|
102 | pass
|
---|
103 |
|
---|
104 | def testaddProfilesBeforeInit(self):
|
---|
105 | st = self.state.With(self.PARTY1, self.profile1)
|
---|
106 | self.assertTrue(self.PARTY1 in st.getPartyProfiles())
|
---|
107 |
|
---|
108 | def testInit(self):
|
---|
109 | # no parties were added, should throw? Go to final mode?
|
---|
110 | # Notice that it's possible to create settings with 0 participants,
|
---|
111 | # because this is needed for Tournament mechanism.
|
---|
112 | state1 = self.state.initPhase(ProgressTime(100,datetime.fromtimestamp(0)),
|
---|
113 | 1)
|
---|
114 | self.assertEqual(0, len(state1.getActions()))
|
---|
115 | self.assertEqual(0, len(state1.getAgreements().getMap()))
|
---|
116 | self.assertEqual(0, len(state1.getPartyProfiles()))
|
---|
117 | phase1 = state1.getPhase()
|
---|
118 | self.assertTrue(isinstance(phase1,OfferPhase))
|
---|
119 | offer1 = phase1
|
---|
120 | self.assertEqual(PartyStates({}), offer1.getPartyStates())
|
---|
121 |
|
---|
122 | def testgetAgreementsTest(self):
|
---|
123 | st = self.state.initPhase(ProgressTime(100, datetime.fromtimestamp(0)), 1)
|
---|
124 | self.assertEqual(0, len(st.getAgreements().getMap()))
|
---|
125 |
|
---|
126 | def testDeserialize(self):
|
---|
127 | obj = self.jackson.parse(json.loads(self.serialized), MOPACState)
|
---|
128 | print(obj)
|
---|
129 | self.assertEqual(self.state1, obj)
|
---|
130 |
|
---|
131 | def testSerialize(self):
|
---|
132 | jsonobj = self.jackson.toJson(self.state1)
|
---|
133 | print(jsonobj)
|
---|
134 | self.assertEqual(json.loads(self.serialized), jsonobj)
|
---|
135 |
|
---|
136 | def testNewPhasePossible(self):
|
---|
137 | phase = Mock(Phase)
|
---|
138 | actions = []
|
---|
139 | progress = Mock(Progress)
|
---|
140 | progress.getTerminationTime=Mock(return_value=
|
---|
141 | datetime.fromtimestamp(PHASE_MAXTIME/1000.)) # plenty for new phase
|
---|
142 | def checkargs(*args, **kwargs):
|
---|
143 | if args[0]==10 + PHASE_MINTIME:
|
---|
144 | return False
|
---|
145 | raise ValueError("unexpected arg");
|
---|
146 |
|
---|
147 |
|
---|
148 | progress.isPastDeadline.side_effect=checkargs
|
---|
149 |
|
---|
150 | partyprofiles = {}
|
---|
151 | s1 = MOPACState(phase, actions, progress, self.settings,
|
---|
152 | partyprofiles)
|
---|
153 |
|
---|
154 | states = Mock(PartyStates)
|
---|
155 | phase.getPartyStates=Mock(return_value=states)
|
---|
156 | states.getNegotiatingParties=Mock(return_value=
|
---|
157 | set([self.PARTY1, self.PARTY2]))
|
---|
158 | self.assertTrue(s1.isNewPhasePossible(10))
|
---|
159 |
|
---|
160 | def testNewPhasePossibleOnly1Party(self):
|
---|
161 | phase = Mock(Phase)
|
---|
162 | actions = []
|
---|
163 | progress = Mock(Progress)
|
---|
164 | progress.getTerminationTime=Mock(
|
---|
165 | return_value=datetime.fromtimestamp(PHASE_MAXTIME/1000.))
|
---|
166 | # plenty for new phase
|
---|
167 |
|
---|
168 | def checkargs(*args, **kwargs):
|
---|
169 | if args[0]==10 + PHASE_MINTIME:
|
---|
170 | return False
|
---|
171 | raise ValueError("unexpected arg");
|
---|
172 |
|
---|
173 |
|
---|
174 | progress.isPastDeadline.side_effect=checkargs
|
---|
175 |
|
---|
176 | partyprofiles = {}
|
---|
177 | s1 = MOPACState(phase, actions, progress, self.settings,
|
---|
178 | partyprofiles)
|
---|
179 |
|
---|
180 | states = Mock(PartyStates)
|
---|
181 | phase.getPartyStates=Mock(return_value=states)
|
---|
182 | states.getNegotiatingParties=Mock(return_value=
|
---|
183 | set([self.PARTY1]))
|
---|
184 | self.assertFalse(s1.isNewPhasePossible(10))
|
---|
185 |
|
---|
186 | def testNewPhasePossibleNotEnoughTime(self):
|
---|
187 | phase = Mock(Phase)
|
---|
188 | actions = []
|
---|
189 | progress = Mock(Progress)
|
---|
190 | progress.getTerminationTime=Mock(
|
---|
191 | return_value=datetime.fromtimestamp((PHASE_MINTIME - 10)/1000.))
|
---|
192 | partyprofiles = {}
|
---|
193 | s1 = MOPACState(phase, actions, progress, self.settings,
|
---|
194 | partyprofiles)
|
---|
195 |
|
---|
196 | states = Mock(PartyStates)
|
---|
197 | phase.getPartyStates=Mock(return_value=states)
|
---|
198 | states.getNegotiatingParties=Mock(return_value=
|
---|
199 | set([self.PARTY1]))
|
---|
200 | self.assertFalse(s1.isNewPhasePossible(10))
|
---|
201 |
|
---|
202 | def testnextPhaseTest(self):
|
---|
203 | NOW = 102;
|
---|
204 | phase = Mock(Phase)
|
---|
205 | actions = []
|
---|
206 | progress = Mock(Progress)
|
---|
207 | progress.getTerminationTime=Mock(return_value=
|
---|
208 | datetime.fromtimestamp(PHASE_MAXTIME/1000.))
|
---|
209 | partyprofiles = {}
|
---|
210 | s1 = MOPACState(phase, actions, progress, self.settings,
|
---|
211 | partyprofiles)
|
---|
212 |
|
---|
213 | # PhaseB is the next phase, with remaining time
|
---|
214 | phaseB = Mock(Phase)
|
---|
215 |
|
---|
216 | def checkargs(*args, **kwargs):
|
---|
217 | if args[0]==NOW and args[1]==PHASE_MAXTIME-NOW:
|
---|
218 | return phaseB
|
---|
219 | raise ValueError("unexpected args")
|
---|
220 |
|
---|
221 | phase.next.side_effect=checkargs
|
---|
222 |
|
---|
223 | s2 = s1.nextPhase(NOW)
|
---|
224 | self.assertEquals(phaseB, s2.getPhase())
|
---|
225 |
|
---|
226 | def testexceptionTest(self):
|
---|
227 | phase = Mock(Phase)
|
---|
228 | actions = []
|
---|
229 | progress = Mock(Progress)
|
---|
230 |
|
---|
231 | partyprofiles = {}
|
---|
232 | s1 = MOPACState(phase, actions, progress, self.settings,
|
---|
233 | partyprofiles)
|
---|
234 |
|
---|
235 | exphase = Mock(Phase); # supposed phase that contains the exception
|
---|
236 |
|
---|
237 | def checkargs(*args, **kwargs):
|
---|
238 | if isinstance(args[0], ProtocolException):
|
---|
239 | return exphase
|
---|
240 | raise ValueError("expected ProtocolException")
|
---|
241 |
|
---|
242 | phase.WithException.side_effect=checkargs
|
---|
243 |
|
---|
244 | errstate = s1.WithException(ProtocolException("test", self.PARTY1))
|
---|
245 | self.assertEqual(exphase, errstate.getPhase())
|
---|
246 | self.assertEqual(progress, errstate.getProgress())
|
---|