1 | package negotiator.protocol;
|
---|
2 |
|
---|
3 | import static org.junit.Assert.assertEquals;
|
---|
4 | import static org.junit.Assert.assertFalse;
|
---|
5 | import static org.junit.Assert.assertNull;
|
---|
6 | import static org.junit.Assert.assertTrue;
|
---|
7 | import static org.mockito.Mockito.mock;
|
---|
8 | import static org.mockito.Mockito.when;
|
---|
9 |
|
---|
10 | import java.util.ArrayList;
|
---|
11 | import java.util.Collection;
|
---|
12 | import java.util.List;
|
---|
13 |
|
---|
14 | import org.junit.Before;
|
---|
15 | import org.junit.Test;
|
---|
16 | import org.mockito.Mockito;
|
---|
17 |
|
---|
18 | import genius.core.AgentID;
|
---|
19 | import genius.core.Bid;
|
---|
20 | import genius.core.Vote;
|
---|
21 | import genius.core.actions.Accept;
|
---|
22 | import genius.core.actions.Action;
|
---|
23 | import genius.core.actions.InformVotingResult;
|
---|
24 | import genius.core.actions.OfferForVoting;
|
---|
25 | import genius.core.actions.Reject;
|
---|
26 | import genius.core.actions.VoteForOfferAcceptance;
|
---|
27 | import genius.core.parties.Mediator;
|
---|
28 | import genius.core.parties.NegotiationParty;
|
---|
29 | import genius.core.protocol.MediatorProtocol;
|
---|
30 | import genius.core.protocol.SimpleMediatorBasedProtocol;
|
---|
31 | import genius.core.session.Round;
|
---|
32 | import genius.core.session.Session;
|
---|
33 | import genius.core.session.Turn;
|
---|
34 |
|
---|
35 | /**
|
---|
36 | * Tests for the {@link SimpleMediatorBasedProtocol}.
|
---|
37 | *
|
---|
38 | * @author W.Pasman
|
---|
39 | *
|
---|
40 | */
|
---|
41 | public class SimpleMediatorBasedProtocolTest {
|
---|
42 |
|
---|
43 | protected MediatorProtocol protocol;
|
---|
44 | private static AgentID AGENTID = new AgentID("test");
|
---|
45 | private static Bid receivedBid = mock(Bid.class);
|
---|
46 |
|
---|
47 | protected static Action ACCEPT = new Accept(AGENTID, receivedBid);
|
---|
48 | protected static Action REJECT = new Reject(AGENTID, receivedBid);
|
---|
49 |
|
---|
50 | Session session = mock(Session.class);
|
---|
51 | protected ArrayList<NegotiationParty> parties;
|
---|
52 | private NegotiationParty party1;
|
---|
53 | private NegotiationParty party2;
|
---|
54 | private NegotiationParty party3;
|
---|
55 | private NegotiationParty mediator;
|
---|
56 | private List<Round> rounds;
|
---|
57 | private InformVotingResult informVoteAccept;
|
---|
58 | private Bid acceptedBid = mock(Bid.class);
|
---|
59 | private InformVotingResult informVoteReject;
|
---|
60 | private Bid rejectedBid = mock(Bid.class);
|
---|
61 | private OfferForVoting partyVote;
|
---|
62 |
|
---|
63 | @Before
|
---|
64 | public void init() {
|
---|
65 |
|
---|
66 | protocol = mock(getProtocol(), Mockito.CALLS_REAL_METHODS);
|
---|
67 |
|
---|
68 | parties = new ArrayList<NegotiationParty>();
|
---|
69 | party1 = mock(NegotiationParty.class);
|
---|
70 | party2 = mock(NegotiationParty.class);
|
---|
71 | party3 = mock(NegotiationParty.class);
|
---|
72 | mediator = mock(Mediator.class);
|
---|
73 |
|
---|
74 | parties.add(party1);
|
---|
75 | parties.add(party2);
|
---|
76 | parties.add(party3);
|
---|
77 | parties.add(mediator);
|
---|
78 |
|
---|
79 | rounds = new ArrayList<Round>();
|
---|
80 | when(session.getRounds()).thenReturn(rounds);
|
---|
81 |
|
---|
82 | informVoteAccept = mock(InformVotingResult.class);
|
---|
83 | when(informVoteAccept.getVotingResult()).thenReturn(Vote.ACCEPT);
|
---|
84 | when(informVoteAccept.getBid()).thenReturn(acceptedBid);
|
---|
85 |
|
---|
86 | informVoteReject = mock(InformVotingResult.class);
|
---|
87 | when(informVoteReject.getVotingResult()).thenReturn(Vote.REJECT);
|
---|
88 | when(informVoteReject.getBid()).thenReturn(rejectedBid);
|
---|
89 |
|
---|
90 | partyVote = mock(OfferForVoting.class);
|
---|
91 | }
|
---|
92 |
|
---|
93 | protected Class<? extends MediatorProtocol> getProtocol() {
|
---|
94 | return SimpleMediatorBasedProtocol.class;
|
---|
95 | }
|
---|
96 |
|
---|
97 | @Test
|
---|
98 | public void testGetMediator() {
|
---|
99 | // strictly not a function of protocol, but still kind of accessable
|
---|
100 | // through it.
|
---|
101 | assertEquals(mediator, protocol.getMediator(parties));
|
---|
102 | }
|
---|
103 |
|
---|
104 | @Test
|
---|
105 | public void testGetNonMediators() {
|
---|
106 | // strictly not a function of protocol, but still kind of accessable
|
---|
107 | // through it.
|
---|
108 | List<NegotiationParty> normalParties = protocol.getNonMediators(parties);
|
---|
109 | assertTrue(normalParties.contains(party1));
|
---|
110 | assertTrue(normalParties.contains(party2));
|
---|
111 | assertTrue(normalParties.contains(party3));
|
---|
112 | }
|
---|
113 |
|
---|
114 | @Test
|
---|
115 | public void testGetRoundStructure() {
|
---|
116 | Collection<Class<? extends Action>> acceptOrReject = new ArrayList<Class<? extends Action>>(2);
|
---|
117 | acceptOrReject.add(Accept.class);
|
---|
118 | acceptOrReject.add(Reject.class);
|
---|
119 |
|
---|
120 | Round round = protocol.getRoundStructure(parties, session);
|
---|
121 |
|
---|
122 | // check that round contains 5 turns (one offer, 3 votes, one inform)
|
---|
123 | // and that they are associated correctly to our parties.
|
---|
124 | List<Turn> turns = round.getTurns();
|
---|
125 | assertEquals(5, turns.size());
|
---|
126 | checkTurn(turns.get(0), mediator, OfferForVoting.class);
|
---|
127 | checkTurn(turns.get(1), party1, VoteForOfferAcceptance.class);
|
---|
128 | checkTurn(turns.get(2), party2, VoteForOfferAcceptance.class);
|
---|
129 | checkTurn(turns.get(3), party3, VoteForOfferAcceptance.class);
|
---|
130 | checkTurn(turns.get(4), mediator, InformVotingResult.class);
|
---|
131 | }
|
---|
132 |
|
---|
133 | /**
|
---|
134 | * check that the mediator can hear all other parties
|
---|
135 | */
|
---|
136 | @Test
|
---|
137 | public void testMediatorHearsAll() {
|
---|
138 | List<NegotiationParty> mediatorListensTo = protocol.getActionListeners(parties).get(mediator);
|
---|
139 |
|
---|
140 | for (NegotiationParty party : protocol.getNonMediators(parties)) {
|
---|
141 | assertTrue("Mediator is not listening to " + party, mediatorListensTo.contains(party));
|
---|
142 | }
|
---|
143 |
|
---|
144 | }
|
---|
145 |
|
---|
146 | /**
|
---|
147 | * check that parties can hear only the mediator.
|
---|
148 | */
|
---|
149 | @Test
|
---|
150 | public void testPartiesHearOnlyMediator() {
|
---|
151 | for (NegotiationParty party : protocol.getNonMediators(parties)) {
|
---|
152 | List<NegotiationParty> partyListensTo = protocol.getActionListeners(parties).get(party);
|
---|
153 | assertEquals("Party listens to more than just the mediator:" + partyListensTo, 1, partyListensTo.size());
|
---|
154 | assertTrue("Party is not listening to mediator", partyListensTo.contains(mediator));
|
---|
155 | }
|
---|
156 |
|
---|
157 | }
|
---|
158 |
|
---|
159 | /**
|
---|
160 | * Call isFinished when in round 0 (initial situation). The round should not
|
---|
161 | * be finished, nothing happened yet.
|
---|
162 | */
|
---|
163 | @Test
|
---|
164 | public void isFinishedTestVoting() {
|
---|
165 |
|
---|
166 | assertFalse(protocol.isFinished(session, parties));
|
---|
167 | assertNull(protocol.getCurrentAgreement(session, parties));
|
---|
168 | }
|
---|
169 |
|
---|
170 | /**
|
---|
171 | * Call isFinished when in round 1. But there is no InformVotingResult in
|
---|
172 | * that round.
|
---|
173 | */
|
---|
174 | @Test
|
---|
175 | public void isFinishedRound1() {
|
---|
176 | Round round1 = mock(Round.class);
|
---|
177 | rounds.add(round1);
|
---|
178 |
|
---|
179 | assertFalse(protocol.isFinished(session, parties));
|
---|
180 | assertNull(protocol.getCurrentAgreement(session, parties));
|
---|
181 | }
|
---|
182 |
|
---|
183 | /**
|
---|
184 | * Check agreement with a accept and a reject. Always check we're not
|
---|
185 | * finished.
|
---|
186 | */
|
---|
187 | @Test
|
---|
188 | public void isFinishedWithOneAccept() {
|
---|
189 | addRoundWithActions(informVoteAccept);
|
---|
190 |
|
---|
191 | assertEquals(acceptedBid, protocol.getCurrentAgreement(session, parties));
|
---|
192 | // check that even when we have agreement, the protocol continues
|
---|
193 | assertFalse(protocol.isFinished(session, parties));
|
---|
194 | }
|
---|
195 |
|
---|
196 | /**
|
---|
197 | * Check agreement with a accept and a rejectt.
|
---|
198 | */
|
---|
199 | @Test
|
---|
200 | public void isFinishedWithAcceptReject() {
|
---|
201 | addRoundWithActions(informVoteAccept);
|
---|
202 | addRoundWithActions(informVoteReject);
|
---|
203 |
|
---|
204 | assertEquals(acceptedBid, protocol.getCurrentAgreement(session, parties));
|
---|
205 | assertFalse(protocol.isFinished(session, parties));
|
---|
206 | }
|
---|
207 |
|
---|
208 | /**
|
---|
209 | * Check agreement with a reject and an accept.
|
---|
210 | */
|
---|
211 | @Test
|
---|
212 | public void isFinishedWithRejectAccept() {
|
---|
213 | addRoundWithActions(informVoteReject);
|
---|
214 | addRoundWithActions(informVoteAccept);
|
---|
215 |
|
---|
216 | assertEquals(acceptedBid, protocol.getCurrentAgreement(session, parties));
|
---|
217 | assertFalse(protocol.isFinished(session, parties));
|
---|
218 | }
|
---|
219 |
|
---|
220 | /**
|
---|
221 | * Check agreement with a reject and an accept that are cluttered with party
|
---|
222 | * votes.
|
---|
223 | */
|
---|
224 | @Test
|
---|
225 | public void isFinishedWithRejectAcceptAndPartyVotes() {
|
---|
226 | addRoundWithActions(partyVote, partyVote, partyVote, informVoteReject, partyVote, partyVote, partyVote);
|
---|
227 | addRoundWithActions(partyVote, partyVote, partyVote, partyVote, partyVote, informVoteAccept, partyVote);
|
---|
228 |
|
---|
229 | assertEquals(acceptedBid, protocol.getCurrentAgreement(session, parties));
|
---|
230 | assertFalse(protocol.isFinished(session, parties));
|
---|
231 | }
|
---|
232 |
|
---|
233 | /**
|
---|
234 | * Check reject with two rejects
|
---|
235 | */
|
---|
236 | @Test
|
---|
237 | public void isFinishedWithTwoRejects() {
|
---|
238 | addRoundWithActions(informVoteReject);
|
---|
239 | addRoundWithActions(informVoteReject);
|
---|
240 |
|
---|
241 | assertNull(protocol.getCurrentAgreement(session, parties));
|
---|
242 | assertFalse(protocol.isFinished(session, parties));
|
---|
243 | }
|
---|
244 |
|
---|
245 | /**
|
---|
246 | * Check that the last accept is the agreement, within a set also containing
|
---|
247 | * rejects
|
---|
248 | */
|
---|
249 | @Test
|
---|
250 | public void isLastAcceptTheAgreement() {
|
---|
251 | Bid acceptedBid2 = mock(Bid.class);
|
---|
252 | InformVotingResult informVoteAccept2 = mock(InformVotingResult.class);
|
---|
253 | when(informVoteAccept2.getVotingResult()).thenReturn(Vote.ACCEPT);
|
---|
254 | when(informVoteAccept2.getBid()).thenReturn(acceptedBid2);
|
---|
255 |
|
---|
256 | addRoundWithActions(informVoteReject);
|
---|
257 | addRoundWithActions(informVoteReject);
|
---|
258 | addRoundWithActions(informVoteAccept);
|
---|
259 | addRoundWithActions(informVoteReject);
|
---|
260 | addRoundWithActions(informVoteReject);
|
---|
261 | addRoundWithActions(informVoteReject);
|
---|
262 | addRoundWithActions(informVoteReject);
|
---|
263 | addRoundWithActions(informVoteAccept2);
|
---|
264 | addRoundWithActions(informVoteReject);
|
---|
265 | addRoundWithActions(informVoteReject);
|
---|
266 |
|
---|
267 | assertEquals(acceptedBid2, protocol.getCurrentAgreement(session, parties));
|
---|
268 | assertFalse(protocol.isFinished(session, parties));
|
---|
269 | }
|
---|
270 |
|
---|
271 | /******************** Support functions ********************/
|
---|
272 | /**
|
---|
273 | * Checks that given turn comes from given party and contains given class.
|
---|
274 | *
|
---|
275 | * @param turn
|
---|
276 | * the turn to check
|
---|
277 | * @param party
|
---|
278 | * the {@link NegotiationParty} that should be in this turn
|
---|
279 | * @param actionclass
|
---|
280 | * the action type that should be in this turn
|
---|
281 | */
|
---|
282 | private void checkTurn(Turn turn, NegotiationParty party, Class<? extends Action> actionclass) {
|
---|
283 | assertTrue("Turn " + turn + " does not contain " + actionclass, turn.getValidActions().contains(actionclass));
|
---|
284 | assertEquals(party, turn.getParty());
|
---|
285 | }
|
---|
286 |
|
---|
287 | /**
|
---|
288 | * Mock the next round with some actions.
|
---|
289 | *
|
---|
290 | * @param newturns
|
---|
291 | * a list of new turns for the next round.
|
---|
292 | */
|
---|
293 | private void addRoundWithActions(Action... newturns) {
|
---|
294 | Round round = mock(Round.class);
|
---|
295 | List<Turn> turns = new ArrayList<Turn>();
|
---|
296 | List<Action> actions = new ArrayList<Action>();
|
---|
297 |
|
---|
298 | for (Action action : newturns) {
|
---|
299 | actions.add(action);
|
---|
300 | Turn turn = mock(Turn.class);
|
---|
301 | when(turn.getAction()).thenReturn(action);
|
---|
302 | turns.add(turn);
|
---|
303 | }
|
---|
304 | when(round.getTurns()).thenReturn(turns);
|
---|
305 | when(round.getActions()).thenReturn(actions);
|
---|
306 |
|
---|
307 | rounds.add(round);
|
---|
308 | }
|
---|
309 |
|
---|
310 | }
|
---|