Index: protocol/src/test/java/geniusweb/protocol/session/amop/WillBeCalledTest.java
===================================================================
--- protocol/src/test/java/geniusweb/protocol/session/amop/WillBeCalledTest.java	(revision 24)
+++ protocol/src/test/java/geniusweb/protocol/session/amop/WillBeCalledTest.java	(revision 24)
@@ -0,0 +1,37 @@
+package geniusweb.protocol.session.amop;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+
+public class WillBeCalledTest {
+	int counter;
+
+	@Test
+	public void testDeadline() throws InterruptedException {
+		counter = 0;
+		new WillBeCalled(() -> {
+			counter++;
+		}, 100l);
+		assertEquals(0, counter);
+		Thread.sleep(200);
+		assertEquals(1, counter);
+		Thread.sleep(200);
+		assertEquals(1, counter);
+
+	}
+
+	@Test
+	public void testManual() throws InterruptedException {
+		counter = 0;
+		WillBeCalled w = new WillBeCalled(() -> {
+			counter++;
+		}, 100l);
+		assertEquals(0, counter);
+		w.complete();
+		assertEquals(1, counter);
+		Thread.sleep(200);
+		assertEquals(1, counter);
+
+	}
+}
Index: protocol/src/test/java/geniusweb/protocol/session/mopac/MOPACStateTest.java
===================================================================
--- protocol/src/test/java/geniusweb/protocol/session/mopac/MOPACStateTest.java	(revision 24)
+++ protocol/src/test/java/geniusweb/protocol/session/mopac/MOPACStateTest.java	(revision 24)
@@ -0,0 +1,275 @@
+package geniusweb.protocol.session.mopac;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonMappingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import geniusweb.actions.Action;
+import geniusweb.actions.PartyId;
+import geniusweb.progress.Progress;
+import geniusweb.progress.ProgressTime;
+import geniusweb.protocol.ProtocolException;
+import geniusweb.protocol.session.OnePartyTeam;
+import geniusweb.protocol.session.mopac.phase.OfferPhase;
+import geniusweb.protocol.session.mopac.phase.Phase;
+import geniusweb.references.Parameters;
+import geniusweb.references.PartyWithParameters;
+import geniusweb.references.PartyWithProfile;
+import geniusweb.references.ProfileRef;
+import geniusweb.voting.votingevaluators.LargestAgreement;
+import tudelft.utilities.junit.GeneralTests;
+
+public class MOPACStateTest extends GeneralTests<MOPACState> {
+	private static final Date NOW = new Date(1001);
+
+	private final ObjectMapper jackson = new ObjectMapper();
+
+	private final MOPACSettings settings = mock(MOPACSettings.class);
+
+	private final MOPACState state = new MOPACState(settings);
+
+	private PartyId PARTY1 = new PartyId("party1");
+	private PartyId PARTY2 = new PartyId("party2");
+	private PartyId PARTY3 = new PartyId("party3");
+
+	private PartyWithParameters partyparams1 = mock(PartyWithParameters.class);
+	private Parameters params1 = new Parameters();
+
+	private PartyWithProfile profile1 = new PartyWithProfile(partyparams1,
+			mock(ProfileRef.class));
+
+	private final String mopacsettingstr = "{\"MOPACSettings\":{\"participants\":[{\"party\":{\"partyref\":\"http://party1\",\"parameters\":{}},\"profile\":\"http://profile1\"},{\"party\":{\"partyref\":\"http://party2\",\"parameters\":{}},\"profile\":\"http://profile2\"}],\"deadline\":{\"deadlinetime\":{\"durationms\":100}},\"votingevaluator\":{\"LargestAgreement\":{}}}}";
+	// create real objects for the GeneralTests and for serialization tests
+	private PartyStates partyStates = new PartyStates(Collections.emptyMap());
+	private Phase phase1 = new OfferPhase(partyStates, 100l,
+			new LargestAgreement());
+	private Phase phase2 = new OfferPhase(partyStates, 200l,
+			new LargestAgreement());
+	private Progress progress1 = new ProgressTime(100l, NOW);
+	private Progress progress2 = new ProgressTime(200l, NOW);
+
+	private MOPACState state1, state1a, state2, state3, state4, state5, state6;
+
+	private String serialized = "{\"MOPACState\":{\"phase\":{\"OfferPhase\":{\"partyStates\":{\"notYetActed\":[],\"actions\":[],\"agreements\":{},\"walkedAway\":[],\"exceptions\":{},\"powers\":{}},\"evaluator\":{\"LargestAgreement\":{}},\"deadline\":100}},\"actions\":[],\"progress\":{\"time\":{\"duration\":100,\"start\":1001}},\"settings\":{\"MOPACSettings\":{\"participants\":[{\"party\":{\"partyref\":\"http://party1\",\"parameters\":{}},\"profile\":\"http://profile1\"},{\"party\":{\"partyref\":\"http://party2\",\"parameters\":{}},\"profile\":\"http://profile2\"}],\"deadline\":{\"deadlinetime\":{\"durationms\":100}},\"votingevaluator\":{\"LargestAgreement\":{}}}},\"partyprofiles\":{}}}";
+
+	@Before
+	public void before()
+			throws JsonParseException, JsonMappingException, IOException {
+		params1.put("power", 2);
+		when(partyparams1.getParameters()).thenReturn(params1);
+
+		MOPACSettings realsettings = jackson.readValue(mopacsettingstr,
+				MOPACSettings.class);
+		OnePartyTeam party = mock(OnePartyTeam.class);
+		PartyWithParameters pwithp = mock(PartyWithParameters.class);
+		when(pwithp.getParameters()).thenReturn(new Parameters());
+		when(party.getParty()).thenReturn(pwithp);
+		MOPACSettings realsettings2 = realsettings.with(party);
+
+		state1 = new MOPACState(phase1, Collections.emptyList(), progress1,
+				realsettings, Collections.emptyMap());
+		state1a = new MOPACState(phase1, Collections.emptyList(), progress1,
+				realsettings, Collections.emptyMap());
+		state2 = new MOPACState(phase2, Collections.emptyList(), progress1,
+				realsettings, Collections.emptyMap());
+		state3 = new MOPACState(phase1, Arrays.asList(mock(Action.class)),
+				progress1, realsettings, Collections.emptyMap());
+		state4 = new MOPACState(phase1, Collections.emptyList(), progress2,
+				realsettings, Collections.emptyMap());
+		state5 = new MOPACState(phase1, Collections.emptyList(), progress1,
+				realsettings2, Collections.emptyMap());
+		state6 = new MOPACState(phase1, Collections.emptyList(), progress1,
+				realsettings,
+				Collections.singletonMap(PARTY1, mock(PartyWithProfile.class)));
+
+	}
+
+	@Override
+	public List<List<MOPACState>> getGeneralTestData() {
+		return Arrays.asList(Arrays.asList(state1, state1a),
+				Arrays.asList(state2), Arrays.asList(state3),
+				Arrays.asList(state4), Arrays.asList(state5),
+				Arrays.asList(state6));
+	}
+
+	@Override
+	public List<String> getGeneralTestStrings() {
+		return Arrays.asList(
+				"MOPACState.*OfferPhase.*PartyStates.*,MOPACSettings.*PartyWithProfile.*ProgressTime.*",
+				"MOPACState.*OfferPhase.*PartyStates.*,MOPACSettings.*PartyWithProfile.*ProgressTime.*",
+				"MOPACState.*OfferPhase.*PartyStates.*,MOPACSettings.*PartyWithProfile.*ProgressTime.*",
+				"MOPACState.*OfferPhase.*PartyStates.*,MOPACSettings.*PartyWithProfile.*ProgressTime.*",
+				"MOPACState.*OfferPhase.*PartyStates.*,MOPACSettings.*PartyWithProfile.*ProgressTime.*",
+				"MOPACState.*OfferPhase.*PartyStates.*,MOPACSettings.*PartyWithProfile.*ProgressTime.*");
+	}
+
+	@Test
+	public void smokeTest() {
+	}
+
+	@Test
+	public void addProfilesBeforeInit() {
+		MOPACState st = state.with(PARTY1, profile1);
+		assertTrue(st.getPartyProfiles().containsKey(PARTY1));
+	}
+
+	@Test
+	public void testInit() {
+		// no parties were added, should throw? Go to final mode?
+		// Notice that it's possible to create settings with 0 participants,
+		// because this is needed for Tournament mechanism.
+		MOPACState state1 = state.initPhase(new ProgressTime(100l, new Date(0)),
+				1);
+		assertTrue(state1.getActions().isEmpty());
+		assertTrue(state1.getAgreements().getMap().isEmpty());
+		assertTrue(state1.getPartyProfiles().isEmpty());
+		Phase phase1 = state1.getPhase();
+		assertTrue(phase1 instanceof OfferPhase);
+		OfferPhase offer1 = (OfferPhase) phase1;
+		assertEquals(new PartyStates(Collections.emptyMap()),
+				offer1.getPartyStates());
+	}
+
+	@Test
+	public void getAgreementsTest() {
+		MOPACState st = state.initPhase(new ProgressTime(100l, new Date(0)), 1);
+		assertTrue(st.getAgreements().getMap().isEmpty());
+	}
+
+	@Test
+	public void testDeserialize() throws IOException {
+		MOPACState obj = jackson.readValue(serialized, MOPACState.class);
+		System.out.println(obj);
+		assertEquals(state1, obj);
+	}
+
+	@Test
+	public void testSerialize()
+			throws JsonProcessingException, URISyntaxException {
+
+		String string = jackson.writeValueAsString(state1);
+		System.out.println(string);
+		assertEquals(serialized, string);
+	}
+
+	@Test
+	public void testNewPhasePossible() {
+
+		Phase phase = mock(Phase.class);
+		List<Action> actions = Collections.emptyList();
+		Progress progress = mock(Progress.class);
+		when(progress.getTerminationTime())
+				.thenReturn(new Date(Phase.PHASE_MAXTIME)); // plenty for new
+															// phase
+		Map<PartyId, PartyWithProfile> partyprofiles = mock(Map.class);
+		MOPACState s1 = new MOPACState(phase, actions, progress, settings,
+				partyprofiles);
+
+		PartyStates states = mock(PartyStates.class);
+		when(phase.getPartyStates()).thenReturn(states);
+		when(states.getNegotiatingParties())
+				.thenReturn(new HashSet<>(Arrays.asList(PARTY1, PARTY2)));
+		assertTrue(s1.isNewPhasePossible(10));
+	}
+
+	@Test
+	public void testNewPhasePossibleOnly1Party() {
+
+		Phase phase = mock(Phase.class);
+		List<Action> actions = Collections.emptyList();
+		Progress progress = mock(Progress.class);
+		when(progress.getTerminationTime())
+				.thenReturn(new Date(Phase.PHASE_MAXTIME)); // plenty for new
+															// phase
+		Map<PartyId, PartyWithProfile> partyprofiles = mock(Map.class);
+		MOPACState s1 = new MOPACState(phase, actions, progress, settings,
+				partyprofiles);
+
+		PartyStates states = mock(PartyStates.class);
+		when(phase.getPartyStates()).thenReturn(states);
+		when(states.getNegotiatingParties())
+				.thenReturn(new HashSet<>(Arrays.asList(PARTY1)));
+		assertFalse(s1.isNewPhasePossible(10));
+	}
+
+	@Test
+	public void testNewPhasePossibleNotEnoughTime() {
+
+		Phase phase = mock(Phase.class);
+		List<Action> actions = Collections.emptyList();
+		Progress progress = mock(Progress.class);
+		when(progress.getTerminationTime())
+				.thenReturn(new Date(Phase.PHASE_MINTIME - 10));
+		Map<PartyId, PartyWithProfile> partyprofiles = mock(Map.class);
+		MOPACState s1 = new MOPACState(phase, actions, progress, settings,
+				partyprofiles);
+
+		PartyStates states = mock(PartyStates.class);
+		when(phase.getPartyStates()).thenReturn(states);
+		when(states.getNegotiatingParties())
+				.thenReturn(new HashSet<>(Arrays.asList(PARTY1)));
+		assertFalse(s1.isNewPhasePossible(10));
+	}
+
+	@Test
+	public void nextPhaseTest() {
+		long NOW = 102;
+		Phase phase = mock(Phase.class);
+		List<Action> actions = Collections.emptyList();
+		Progress progress = mock(Progress.class);
+		when(progress.getTerminationTime())
+				.thenReturn(new Date(Phase.PHASE_MAXTIME));
+		Map<PartyId, PartyWithProfile> partyprofiles = mock(Map.class);
+		MOPACState s1 = new MOPACState(phase, actions, progress, settings,
+				partyprofiles);
+
+		// PhaseB is the next phase, with remaining time
+		Phase phaseB = mock(Phase.class);
+		when(phase.next(eq(NOW), eq(Phase.PHASE_MAXTIME - NOW)))
+				.thenReturn(phaseB);
+
+		MOPACState s2 = s1.nextPhase(NOW);
+		assertEquals(phaseB, s2.getPhase());
+	}
+
+	@Test
+	public void exceptionTest() {
+		Phase phase = mock(Phase.class);
+		List<Action> actions = Collections.emptyList();
+		Progress progress = mock(Progress.class);
+		Map<PartyId, PartyWithProfile> partyprofiles = mock(Map.class);
+		MOPACState s1 = new MOPACState(phase, actions, progress, settings,
+				partyprofiles);
+
+		Phase exphase = mock(Phase.class); // supposed phase that contains the
+											// exception
+		when(phase.with(any(ProtocolException.class))).thenReturn(exphase);
+
+		MOPACState errstate = s1.with(new ProtocolException("test", PARTY1));
+		assertEquals(exphase, errstate.getPhase());
+		assertEquals(progress, errstate.getProgress());
+
+	}
+
+}
Index: protocol/src/test/java/geniusweb/protocol/session/mopac/MOPACTest.java
===================================================================
--- protocol/src/test/java/geniusweb/protocol/session/mopac/MOPACTest.java	(revision 23)
+++ protocol/src/test/java/geniusweb/protocol/session/mopac/MOPACTest.java	(revision 24)
@@ -2,7 +2,9 @@
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyLong;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.times;
@@ -12,8 +14,8 @@
 import java.io.IOException;
 import java.util.Arrays;
+import java.util.Date;
 import java.util.List;
 
 import org.junit.Before;
-import org.junit.Ignore;
 import org.junit.Test;
 
@@ -28,4 +30,7 @@
 import geniusweb.protocol.partyconnection.ProtocolToPartyConn;
 import geniusweb.protocol.partyconnection.ProtocolToPartyConnFactory;
+import geniusweb.protocol.session.mopac.phase.OfferPhase;
+import geniusweb.protocol.session.mopac.phase.Phase;
+import geniusweb.protocol.session.mopac.phase.VotingPhase;
 import tudelft.utilities.logging.Reporter;
 import tudelft.utilities.repository.NoResourcesNowException;
@@ -57,4 +62,6 @@
 			conn3 = mock(ProtocolToPartyConn.class);
 
+	private List<ProtocolToPartyConn> connections;
+
 	@Before
 	public void before() throws JsonParseException, JsonMappingException,
@@ -63,5 +70,5 @@
 		mopac = settings.getProtocol(logger);
 
-		List connections = Arrays.asList(conn1, conn2, conn3);
+		connections = Arrays.asList(conn1, conn2, conn3);
 		when(factory.connect(any(List.class))).thenReturn(connections);
 
@@ -94,5 +101,4 @@
 	}
 
-	@Ignore
 	@Test
 	public void testWorkingCheckDeadline()
@@ -101,14 +107,10 @@
 		mopac.start(factory);
 
-		System.out.println(mopac.getState());
-
+		assertFalse(mopac.getState().isFinal(System.currentTimeMillis()));
 		// we have deadline in 100ms so check
 		Thread.sleep(200);
-
-		System.out.println(mopac.getState());
 		assertTrue(mopac.getState().isFinal(System.currentTimeMillis()));
 	}
 
-	@Ignore
 	@Test
 	public void testSubscribedToConnections() {
@@ -119,5 +121,4 @@
 	}
 
-	@Ignore
 	@Test
 	public void testActionIsBroadcast()
@@ -134,7 +135,81 @@
 	}
 
-	@Test
-	public void testAgreementTerminates() {
-
-	}
+	/**
+	 * Fatal error occurs, run should fail
+	 */
+	@Test(expected = RuntimeException.class)
+	public void testPartyFailsConnect()
+			throws IOException, NoResourcesNowException {
+		ProtocolToPartyConnFactory factory1 = mock(
+				ProtocolToPartyConnFactory.class);
+		// irrecoverable fail test
+		when(factory1.connect(any(List.class)))
+				.thenThrow(new IOException("Failed to connect to parties"));
+
+		mopac.start(factory1);
+
+	}
+
+	/**
+	 * Nonfatal error occurs, protocol should retry till success
+	 */
+	@Test
+	public void testPartyFailsConnect2ndtimeOK()
+			throws IOException, NoResourcesNowException {
+		long now = System.currentTimeMillis();
+		ProtocolToPartyConnFactory factory1 = mock(
+				ProtocolToPartyConnFactory.class);
+		// recoverable fail, and then success.
+		when(factory1.connect(any(List.class)))
+				.thenThrow(new NoResourcesNowException("try again later",
+						new Date(now + 100)))
+				.thenReturn(connections);
+
+		mopac.start(factory1);
+
+	}
+
+	/**
+	 * Test that in Offer phase, and party does action, the next phase is
+	 * entered.
+	 */
+	@Test
+	public void testProceedsNextPhase() {
+		// the state before the last party makes the offer
+		MOPACState offerstate = mock(MOPACState.class);
+		when(offerstate.getSettings()).thenReturn(settings);
+		OfferPhase offerphase = mock(OfferPhase.class);
+		when(offerphase.isFinal(anyLong())).thenReturn(false);
+		when(offerstate.getPhase()).thenReturn(offerphase);
+
+		// the phase where all parties placed an offer
+		OfferPhase finalofferphase = mock(OfferPhase.class);
+		when(finalofferphase.isFinal(anyLong())).thenReturn(true);
+		MOPACState finalofferstate = mock(MOPACState.class);
+		when(finalofferstate.getPhase()).thenReturn(finalofferphase);
+		when(finalofferstate.finishPhase()).thenReturn(finalofferstate);
+
+		when(offerstate.with(any(PartyId.class), any(Action.class), anyLong()))
+				.thenReturn(finalofferstate);
+
+		// the phase where all parties can start voting.
+		// this is the state to be reached.
+		long now = System.currentTimeMillis();
+		MOPACState votingstate = mock(MOPACState.class);
+		Phase votingphase = mock(VotingPhase.class);
+		PartyStates votingpartystates = mock(PartyStates.class);
+		when(votingphase.getDeadline()).thenReturn(now + 100);
+		when(votingphase.getPartyStates()).thenReturn(votingpartystates);
+		when(votingstate.getPhase()).thenReturn(votingphase);
+
+		when(finalofferstate.nextPhase(anyLong())).thenReturn(votingstate);
+
+		mopac = new MOPAC(offerstate, logger);
+		Offer action = mock(Offer.class);
+		mopac.actionRequest(conn3, action, now);
+
+		// check that the action result in reaching the voting phase
+		assertEquals(votingstate, mopac.getState());
+	}
+
 }
Index: protocol/src/test/java/geniusweb/protocol/session/mopac/PartyStatesTest.java
===================================================================
--- protocol/src/test/java/geniusweb/protocol/session/mopac/PartyStatesTest.java	(revision 23)
+++ protocol/src/test/java/geniusweb/protocol/session/mopac/PartyStatesTest.java	(revision 24)
@@ -3,17 +3,25 @@
 import static org.junit.Assert.assertEquals;
 
+import java.io.IOException;
+import java.net.URISyntaxException;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Map;
 
 import org.junit.Test;
 
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
 import geniusweb.actions.PartyId;
 import geniusweb.inform.Agreements;
 import geniusweb.protocol.ProtocolException;
+import tudelft.utilities.junit.GeneralTests;
 
-public class PartyStatesTest {
+public class PartyStatesTest extends GeneralTests<PartyStates> {
+	private final ObjectMapper jackson = new ObjectMapper();
 
 	private final PartyId party1 = new PartyId("party1");
@@ -22,26 +30,49 @@
 
 	private final Map<PartyId, Integer> powers = new HashMap<>();
-	private final PartyStates states;
+	private final PartyStates states1, states1a, states2;
+	private final String serialized = "{\"notYetActed\":[\"party2\",\"party1\",\"party3\"],\"actions\":[],\"agreements\":{},\"walkedAway\":[],\"exceptions\":{},\"powers\":{\"party2\":3,\"party1\":2,\"party3\":3}}";
 
 	public PartyStatesTest() {
+
+		// FIXME use the other constructor to really test this.
+//		PartyStates(Set<PartyId> notYetActed, List<Action> actions,
+//				Agreements agreements, List<PartyId> walkedAway,
+//				Map<PartyId, ProtocolException> exceptions,
+//				Map<PartyId, Integer> powers)
+//		
 		powers.put(party1, 2);
 		powers.put(party2, 3);
+		states2 = new PartyStates(powers);
 		powers.put(party3, 3);
-		states = new PartyStates(powers);
+		states1 = new PartyStates(powers);
+		states1a = new PartyStates(powers);
+	}
+
+	@Override
+	public List<List<PartyStates>> getGeneralTestData() {
+		return Arrays.asList(Arrays.asList(states1, states1a),
+				Arrays.asList(states2));
+	}
+
+	@Override
+	public List<String> getGeneralTestStrings() {
+		return Arrays.asList(
+				"PartyStates.*\\[party2, party1, party3\\],\\[\\],Agreements\\{\\},\\[\\],\\{\\}.*",
+				"PartyStates.*\\[party2, party1\\],\\[\\],Agreements\\{\\},\\[\\],\\{\\}.*");
 	}
 
 	@Test
 	public void testBasics() {
-		assertEquals(powers.keySet(), states.getNegotiatingParties());
-		assertEquals(powers.keySet(), states.getNotYetActed());
-		assertEquals(0, states.getExceptions().size());
+		assertEquals(powers.keySet(), states1.getNegotiatingParties());
+		assertEquals(powers.keySet(), states1.getNotYetActed());
+		assertEquals(0, states1.getExceptions().size());
 	}
 
 	@Test
 	public void testException() {
-		PartyStates newstates = states
+		PartyStates newstates = states1
 				.with(new ProtocolException("bla", party1));
 		assertEquals(new Agreements(), newstates.getAgreements());
-		assertEquals(powers.keySet(), states.getNegotiatingParties());
+		assertEquals(powers.keySet(), states1.getNegotiatingParties());
 		assertEquals(new HashSet<>(Arrays.asList(party2, party3)),
 				newstates.getNotYetActed());
@@ -50,8 +81,32 @@
 	@Test
 	public void testFinish() {
-		PartyStates newstates = states.finish();
+		PartyStates newstates = states1.finish();
 		assertEquals(new Agreements(), newstates.getAgreements());
-		assertEquals(powers.keySet(), states.getNegotiatingParties());
+		assertEquals(powers.keySet(), states1.getNegotiatingParties());
 		assertEquals(Collections.emptySet(), newstates.getNotYetActed());
 	}
+
+	@Test
+	public void testDeserialize() throws IOException {
+		PartyStates obj = jackson.readValue(serialized, PartyStates.class);
+		System.out.println(obj);
+		assertEquals(states1, obj);
+	}
+
+	@Test
+	public void testSerialize()
+			throws JsonProcessingException, URISyntaxException {
+
+		String string = jackson.writeValueAsString(states1);
+		System.out.println(string);
+		assertEquals(serialized, string);
+	}
+
+	@Test
+	public void testWalkAway() {
+		PartyStates walkawaystate = states1.withWalkAway(party2);
+		assertEquals(new HashSet<>(Arrays.asList(party1, party3)),
+				walkawaystate.getNotYetActed());
+		assertEquals(Arrays.asList(party2), walkawaystate.getWalkedAway());
+	}
 }
Index: protocol/src/test/java/geniusweb/protocol/session/mopac/phase/OfferPhaseTest.java
===================================================================
--- protocol/src/test/java/geniusweb/protocol/session/mopac/phase/OfferPhaseTest.java	(revision 23)
+++ protocol/src/test/java/geniusweb/protocol/session/mopac/phase/OfferPhaseTest.java	(revision 24)
@@ -4,24 +4,43 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 import static org.mockito.Mockito.mock;
-
+import static org.mockito.Mockito.when;
+
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 
 import org.junit.Test;
 
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import geniusweb.actions.Accept;
 import geniusweb.actions.EndNegotiation;
+import geniusweb.actions.Offer;
 import geniusweb.actions.PartyId;
 import geniusweb.actions.Votes;
+import geniusweb.inform.YourTurn;
+import geniusweb.issuevalue.Bid;
+import geniusweb.issuevalue.DiscreteValue;
 import geniusweb.protocol.ProtocolException;
 import geniusweb.protocol.session.mopac.PartyStates;
 import geniusweb.voting.VotingEvaluator;
+import geniusweb.voting.votingevaluators.LargestAgreement;
+import geniusweb.voting.votingevaluators.LargestAgreementsLoop;
+import tudelft.utilities.junit.GeneralTests;
 
 /**
  * We also test defaultPhase here.
  */
-public class OfferPhaseTest {
-
+public class OfferPhaseTest extends GeneralTests<OfferPhase> {
+	private final ObjectMapper jackson = new ObjectMapper();
+
+	private static final long DEADLINE = 10l;
 	private final PartyId party1 = new PartyId("party1");
 	private final PartyId party2 = new PartyId("party2");
@@ -29,20 +48,82 @@
 
 	private final Map<PartyId, Integer> powers = new HashMap<>();
-	private final PartyStates states;
-	private final VotingEvaluator evaluator = mock(VotingEvaluator.class);
-	private final OfferPhase phase;
+	private final PartyStates states, states2;
+	private final VotingEvaluator evaluator = new LargestAgreement();
+	private final VotingEvaluator evaluator2 = new LargestAgreementsLoop();
+	private final OfferPhase phase, phase1, phase1a, phase2, phase3, phase4;
+
+	// just a test bid
+	private final Bid bid = new Bid("issue", new DiscreteValue("yes"));
+	private final Offer offer = new Offer(party1, bid);
+
+	private final String serialized = "{\"OfferPhase\":{\"partyStates\":{\"notYetActed\":[\"party2\",\"party1\",\"party3\"],\"actions\":[],\"agreements\":{},\"walkedAway\":[],\"exceptions\":{},\"powers\":{\"party2\":3,\"party1\":2,\"party3\":3}},\"evaluator\":{\"LargestAgreement\":{}},\"deadline\":10}}";
 
 	public OfferPhaseTest() {
 		powers.put(party1, 2);
 		powers.put(party2, 3);
+		states2 = new PartyStates(powers);
 		powers.put(party3, 3);
 		states = new PartyStates(powers);
-		phase = new OfferPhase(null, states, 10l, evaluator);
-	}
-
-	@Test
-	public void isInitFinalTest() {
+		phase = new OfferPhase(states, DEADLINE, evaluator);
+
+		phase1 = new OfferPhase(states, 10l, evaluator);
+		phase1a = new OfferPhase(states, 10l, evaluator);
+		phase2 = new OfferPhase(states2, 10l, evaluator);
+		phase3 = new OfferPhase(states, 20l, evaluator);
+		phase4 = new OfferPhase(states, 10l, evaluator2);
+
+	}
+
+	@Override
+	public List<List<OfferPhase>> getGeneralTestData() {
+		return Arrays.asList(Arrays.asList(phase1, phase1a),
+				Arrays.asList(phase2), Arrays.asList(phase3),
+				Arrays.asList(phase4));
+	}
+
+	@Override
+	public List<String> getGeneralTestStrings() {
+		return Arrays.asList(
+				"OfferPhase.*PartyStates.*party2, party1, party3.*\\[\\],Agreements.*\\[\\],\\{\\}.*],10,LargestAgreement.*",
+				"OfferPhase.*PartyStates.*party2, party1.*\\[\\],Agreements.*\\[\\],\\{\\}.*],10,LargestAgreement.*",
+				"OfferPhase.*PartyStates.*party2, party1, party3.*\\[\\],Agreements.*\\[\\],\\{\\}.*],20,LargestAgreement.*",
+				"OfferPhase.*PartyStates.*party2, party1, party3.*\\[\\],Agreements.*\\[\\],\\{\\}.*],10,LargestAgreementsLoop.*");
+	}
+
+	@Test
+	public void smokeTest() {
+	}
+
+	@Test
+	public void testInitState() {
+		assertEquals(3, phase.getPartyStates().getNotYetActed().size());
+	}
+
+	@Test
+	public void testInform() {
+		assertEquals(new YourTurn(), phase.getInform());
+	}
+
+	@Test
+	public void isFinalTest() {
 		assertFalse(phase.isFinal(1l));
 		assertTrue(phase.isFinal(10l));
+	}
+
+	@Test
+	public void isFinalTestActorNotYetActed() {
+		PartyStates actedstate = mock(PartyStates.class);
+		when(actedstate.getNotYetActed())
+				.thenReturn(Collections.singleton(party1));
+		OfferPhase testphase = new OfferPhase(actedstate, 10l, evaluator);
+		assertFalse(testphase.isFinal(1l));
+	}
+
+	@Test
+	public void isFinalTestAllActorsActed() {
+		PartyStates actedstate = mock(PartyStates.class);
+		when(actedstate.getNotYetActed()).thenReturn(Collections.emptySet());
+		OfferPhase testphase = new OfferPhase(actedstate, 10l, evaluator);
+		assertTrue(testphase.isFinal(1l));
 	}
 
@@ -65,3 +146,132 @@
 	}
 
+	@Test
+	public void testFinish() {
+		Phase ph = phase.finish();
+		assertTrue(ph.getPartyStates().getNotYetActed().isEmpty());
+		assertEquals(3, ph.getPartyStates().getExceptions().size());
+		assertTrue(phase.getPartyStates().getAgreements().getMap().isEmpty());
+	}
+
+	@Test(expected = IllegalStateException.class)
+	public void testNextWrong() {
+		// state is not final, should not work
+		phase.next(1, 1000);
+	}
+
+	@Test
+	public void testNextNoParties() {
+		Phase ph = phase.finish();
+		// no parties are left now, all failed
+		// but this is not part of the next() check.
+		Phase next = ph.next(1, 1000);
+		assertTrue(next instanceof VotingPhase);
+		// no remaining parties, since finish kicked all
+		assertTrue(next.getPartyStates().getNotYetActed().isEmpty());
+	}
+
+	@Test
+	public void testAllowed() {
+		phase.with(party1, offer, 1);
+	}
+
+	@Test
+	public void testAllowedWrongClass() {
+		try {
+			phase.checkAction(party1, new Accept(party1, bid), 1);
+		} catch (ProtocolException e) {
+			assertTrue(e.getMessage().contains("not allowed in OfferPhase"));
+			return;
+		}
+		fail("checkAction did not throw as expected");
+	}
+
+	@Test
+	public void testAllowedWrongActor() {
+		try {
+			phase.checkAction(party1, new Accept(party2, bid), 1);
+		} catch (ProtocolException e) {
+			assertTrue(
+					e.getMessage().contains("Incorrect actor info in action"));
+			return;
+		}
+		fail("checkAction did not throw as expected");
+	}
+
+	@Test
+	public void testAllowedActorAlreadyActed() {
+		OfferPhase testphase = phase.with(party1, offer, 1);
+
+		try {
+			testphase.checkAction(party1, offer, 2);
+		} catch (ProtocolException e) {
+			assertTrue(e.getMessage().contains("can not act anymore"));
+			return;
+		}
+		fail("checkAction did not throw as expected");
+	}
+
+	@Test
+	public void testAllowedActorAlreadyActed1() {
+		// as theoprevious test, but using with() instead of checkAction
+		OfferPhase testphase = phase.with(party1, offer, 1);
+
+		OfferPhase newphase = testphase.with(party1, offer, 2);
+		// the party must remain as acted, because we can't retract his
+		// action...
+		assertEquals(1, newphase.getPartyStates().getActions().size());
+		assertEquals(offer, newphase.getPartyStates().getActions().get(0));
+		assertFalse(
+				newphase.getPartyStates().getExceptions().containsKey(party1));
+	}
+
+	@Test
+	public void testAllowedActingTooLate() {
+
+		try {
+			phase.checkAction(party1, offer, DEADLINE + 1);
+		} catch (ProtocolException e) {
+			assertTrue(e.getMessage().contains("passed deadline"));
+			return;
+		}
+		fail("checkAction did not throw as expected");
+	}
+
+	@Test
+	public void getOffersTest() {
+		assertEquals(Collections.emptyList(), phase.getOffers());
+		List<Bid> offs = phase.with(party1, offer, 1).getOffers();
+		assertEquals(Arrays.asList(bid), offs);
+	}
+
+	@Test(expected = IllegalArgumentException.class)
+	public void testNextTooShortDuration() {
+		phase.next(1, Phase.PHASE_MINTIME - 1);
+	}
+
+	@Test(expected = IllegalStateException.class)
+	public void testNextNotFinished() {
+		phase.next(1, Phase.PHASE_MINTIME + 1);
+	}
+
+	@Test(expected = IllegalStateException.class)
+	public void testNext() {
+		phase.next(11, Phase.PHASE_MINTIME + 1);
+	}
+
+	@Test
+	public void testDeserialize() throws IOException {
+		Phase obj = jackson.readValue(serialized, Phase.class);
+		System.out.println(obj);
+		assertEquals(phase1, obj);
+	}
+
+	@Test
+	public void testSerialize()
+			throws JsonProcessingException, URISyntaxException {
+
+		String string = jackson.writeValueAsString(phase1);
+		System.out.println(string);
+		assertEquals(serialized, string);
+	}
 }
Index: protocol/src/test/java/geniusweb/protocol/session/mopac/phase/OptInPhaseTest.java
===================================================================
--- protocol/src/test/java/geniusweb/protocol/session/mopac/phase/OptInPhaseTest.java	(revision 24)
+++ protocol/src/test/java/geniusweb/protocol/session/mopac/phase/OptInPhaseTest.java	(revision 24)
@@ -0,0 +1,203 @@
+package geniusweb.protocol.session.mopac.phase;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.junit.Test;
+
+import geniusweb.actions.EndNegotiation;
+import geniusweb.actions.PartyId;
+import geniusweb.actions.Vote;
+import geniusweb.actions.Votes;
+import geniusweb.inform.OptIn;
+import geniusweb.issuevalue.Bid;
+import geniusweb.issuevalue.DiscreteValue;
+import geniusweb.protocol.ProtocolException;
+import geniusweb.protocol.session.mopac.PartyStates;
+import geniusweb.voting.VotingEvaluator;
+import geniusweb.voting.votingevaluators.LargestAgreement;
+import geniusweb.voting.votingevaluators.LargestAgreementsLoop;
+import tudelft.utilities.junit.GeneralTests;
+
+/**
+ * We also test defaultPhase here.
+ */
+public class OptInPhaseTest extends GeneralTests<OptInPhase> {
+
+	private static final long DEADLINE = 10l;
+	private final PartyId party1 = new PartyId("party1");
+	private final PartyId party2 = new PartyId("party2");
+	private final PartyId party3 = new PartyId("party3");
+
+	// private final VotingPhase prevPhase = mock(VotingPhase.class);
+
+	private final Map<PartyId, Integer> powers = new HashMap<>();
+	private final PartyStates states, states2;
+	private final VotingEvaluator evaluator = new LargestAgreement();
+	private final VotingEvaluator evaluator2 = new LargestAgreementsLoop();
+	private final OptInPhase phase, phase1, phase1a, phase2, phase3, phase4;
+
+	// just a test bid
+	private final Bid bid = new Bid("issue", new DiscreteValue("yes"));
+	private final Vote vote = new Vote(party1, bid, 2, 3);
+	private final Votes votes = new Votes(party1, Arrays.asList(vote));
+
+	private final List<Votes> prevVotes = Arrays.asList(votes);
+
+	public OptInPhaseTest() {
+		powers.put(party1, 2);
+		powers.put(party2, 3);
+		states2 = new PartyStates(powers);
+		powers.put(party3, 3);
+		states = new PartyStates(powers);
+
+		phase = new OptInPhase(prevVotes, states, DEADLINE, evaluator);
+
+		// in these phases we just don't set prevPhase.
+		// this to avoid serialization troubles.
+		phase1 = new OptInPhase(null, states, 10l, evaluator);
+		phase1a = new OptInPhase(null, states, 10l, evaluator);
+		phase2 = new OptInPhase(null, states2, 10l, evaluator);
+		phase3 = new OptInPhase(null, states, 20l, evaluator);
+		phase4 = new OptInPhase(null, states, 10l, evaluator2);
+
+	}
+
+	@Override
+	public List<List<OptInPhase>> getGeneralTestData() {
+		return Arrays.asList(Arrays.asList(phase1, phase1a),
+				Arrays.asList(phase2), Arrays.asList(phase3),
+				Arrays.asList(phase4));
+	}
+
+	@Override
+	public List<String> getGeneralTestStrings() {
+		return Arrays.asList(
+				"OptInPhase.*PartyStates.*party2, party1, party3.*\\[\\],Agreements.*\\[\\],\\{\\}.*],10,LargestAgreement.*",
+				"OptInPhase.*PartyStates.*party2, party1.*\\[\\],Agreements.*\\[\\],\\{\\}.*],10,LargestAgreement.*",
+				"OptInPhase.*PartyStates.*party2, party1, party3.*\\[\\],Agreements.*\\[\\],\\{\\}.*],20,LargestAgreement.*",
+				"OptInPhase.*PartyStates.*party2, party1, party3.*\\[\\],Agreements.*\\[\\],\\{\\}.*],10,LargestAgreementsLoop.*");
+	}
+
+	@Test
+	public void smokeTest() {
+	}
+
+	@Test
+	public void testInitState() {
+		assertEquals(3, phase.getPartyStates().getNotYetActed().size());
+	}
+
+	@Test
+	public void testInform() {
+		// when(prevPhase.getVotes()).thenReturn(Arrays.asList(votes));
+		assertEquals(new OptIn(Arrays.asList(votes)), phase.getInform());
+
+	}
+
+	@Test
+	public void isFinalTest() {
+		assertFalse(phase.isFinal(1l));
+		assertTrue(phase.isFinal(10l));
+	}
+
+	@Test
+	public void isFinalTestActorNotYetActed() {
+		PartyStates actedstate = mock(PartyStates.class);
+		when(actedstate.getNotYetActed())
+				.thenReturn(Collections.singleton(party1));
+		OfferPhase testphase = new OfferPhase(actedstate, 10l, evaluator);
+		assertFalse(testphase.isFinal(1l));
+	}
+
+	@Test
+	public void isFinalTestAllActorsActed() {
+		PartyStates actedstate = mock(PartyStates.class);
+		when(actedstate.getNotYetActed()).thenReturn(Collections.emptySet());
+		OfferPhase testphase = new OfferPhase(actedstate, 10l, evaluator);
+		assertTrue(testphase.isFinal(1l));
+	}
+
+	@Test(expected = ProtocolException.class)
+	public void checkIncorrectActorTest() throws ProtocolException {
+		phase.checkAction(party1, new EndNegotiation(party2), 1);
+	}
+
+	@Test(expected = ProtocolException.class)
+	public void checkNotAllowedActionTest() throws ProtocolException {
+		phase.checkAction(party1, new Votes(party2, Collections.emptyList()),
+				1);
+	}
+
+	@Test
+	public void testFinish() {
+		Phase ph = phase.finish();
+		assertTrue(ph.getPartyStates().getNotYetActed().isEmpty());
+		assertEquals(3, ph.getPartyStates().getExceptions().size());
+		assertTrue(phase.getPartyStates().getAgreements().getMap().isEmpty());
+	}
+
+	@Test(expected = IllegalStateException.class)
+	public void testNextWrong() {
+		// state is not final, should not work
+		phase.next(1, 1000);
+	}
+
+	@Test
+	public void testNextNoParties() {
+		Phase ph = phase.finish();
+		// no parties are left now, all failed
+		// but this is not part of the next() check.
+		Phase next = ph.next(1, 1000);
+		assertTrue(next instanceof OfferPhase);
+		// no remaining parties, since finish kicked all
+		assertTrue(next.getPartyStates().getNotYetActed().isEmpty());
+	}
+
+	@Test
+	public void testAllowed() {
+		// when(prevPhase.getVotes()).thenReturn(Arrays.asList(votes));
+		phase.with(party1, votes, 1l);
+	}
+
+	@Test
+	public void testAllowedNarrowingVote() {
+		// the previous vote was maxPower=3,
+		// so this is an illegal narrowing of the previous vote
+		Vote newVote = new Vote(party1, bid, 2, 2);
+		Votes newVotes = new Votes(party1, Arrays.asList(newVote));
+
+		// when(prevPhase.getVotes()).thenReturn(Arrays.asList(votes));
+
+		// check that party1 was kicked
+		Phase newphase = phase.with(party1, newVotes, 1l);
+		assertTrue(
+				newphase.getPartyStates().getExceptions().containsKey(party1));
+
+	}
+
+	@Test(expected = IllegalArgumentException.class)
+	public void testNextTooShortDuration() {
+		phase.next(1, Phase.PHASE_MINTIME - 1);
+	}
+
+	@Test(expected = IllegalStateException.class)
+	public void testNextNotFinished() {
+		phase.next(1, Phase.PHASE_MINTIME + 1);
+	}
+
+	@Test(expected = IllegalStateException.class)
+	public void testNext() {
+		phase.next(11, Phase.PHASE_MINTIME + 1);
+	}
+
+}
Index: protocol/src/test/java/geniusweb/protocol/session/mopac/phase/VotingPhaseTest.java
===================================================================
--- protocol/src/test/java/geniusweb/protocol/session/mopac/phase/VotingPhaseTest.java	(revision 24)
+++ protocol/src/test/java/geniusweb/protocol/session/mopac/phase/VotingPhaseTest.java	(revision 24)
@@ -0,0 +1,193 @@
+package geniusweb.protocol.session.mopac.phase;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.junit.Test;
+
+import geniusweb.actions.EndNegotiation;
+import geniusweb.actions.PartyId;
+import geniusweb.actions.Vote;
+import geniusweb.actions.Votes;
+import geniusweb.inform.Voting;
+import geniusweb.issuevalue.Bid;
+import geniusweb.issuevalue.DiscreteValue;
+import geniusweb.protocol.ProtocolException;
+import geniusweb.protocol.session.mopac.PartyStates;
+import geniusweb.voting.VotingEvaluator;
+import geniusweb.voting.votingevaluators.LargestAgreement;
+import geniusweb.voting.votingevaluators.LargestAgreementsLoop;
+import tudelft.utilities.junit.GeneralTests;
+
+/**
+ * We also test defaultPhase here.
+ */
+public class VotingPhaseTest extends GeneralTests<VotingPhase> {
+
+	private static final long DEADLINE = 10l;
+	private final PartyId party1 = new PartyId("party1");
+	private final PartyId party2 = new PartyId("party2");
+	private final PartyId party3 = new PartyId("party3");
+
+	// private final OfferPhase prevPhase = mock(OfferPhase.class);
+
+	private final Map<PartyId, Integer> powers = new HashMap<>();
+	private final PartyStates states, states2;
+	private final VotingEvaluator evaluator = new LargestAgreement();
+	private final VotingEvaluator evaluator2 = new LargestAgreementsLoop();
+	private final VotingPhase phase, phase1, phase1a, phase2, phase3, phase4;
+
+	// just a test bid
+	private final Bid bid = new Bid("issue", new DiscreteValue("yes"));
+	private final Vote vote = new Vote(party1, bid, 2, 3);
+	private final Votes votes = new Votes(party1, Arrays.asList(vote));
+
+	private final List<Bid> prevPhase = Arrays.asList(bid);
+
+	public VotingPhaseTest() {
+		powers.put(party1, 2);
+		powers.put(party2, 3);
+		states2 = new PartyStates(powers);
+		powers.put(party3, 3);
+		states = new PartyStates(powers);
+
+		phase = new VotingPhase(prevPhase, states, DEADLINE, evaluator);
+
+		// in these phases we just don't set prevPhase.
+		// this to avoid serialization troubles.
+		phase1 = new VotingPhase(null, states, 10l, evaluator);
+		phase1a = new VotingPhase(null, states, 10l, evaluator);
+		phase2 = new VotingPhase(null, states2, 10l, evaluator);
+		phase3 = new VotingPhase(null, states, 20l, evaluator);
+		phase4 = new VotingPhase(null, states, 10l, evaluator2);
+
+	}
+
+	@Override
+	public List<List<VotingPhase>> getGeneralTestData() {
+		return Arrays.asList(Arrays.asList(phase1, phase1a),
+				Arrays.asList(phase2), Arrays.asList(phase3),
+				Arrays.asList(phase4));
+	}
+
+	@Override
+	public List<String> getGeneralTestStrings() {
+		return Arrays.asList(
+				"VotingPhase.*PartyStates.*party2, party1, party3.*\\[\\],Agreements.*\\[\\],\\{\\}.*],10,LargestAgreement.*",
+				"VotingPhase.*PartyStates.*party2, party1.*\\[\\],Agreements.*\\[\\],\\{\\}.*],10,LargestAgreement.*",
+				"VotingPhase.*PartyStates.*party2, party1, party3.*\\[\\],Agreements.*\\[\\],\\{\\}.*],20,LargestAgreement.*",
+				"VotingPhase.*PartyStates.*party2, party1, party3.*\\[\\],Agreements.*\\[\\],\\{\\}.*],10,LargestAgreementsLoop.*");
+	}
+
+	@Test
+	public void smokeTest() {
+	}
+
+	@Test
+	public void testInitState() {
+		assertEquals(3, phase.getPartyStates().getNotYetActed().size());
+	}
+
+	@Test
+	public void testInform() {
+		// when(prevPhase.getOffers()).thenReturn(Arrays.asList(bid));
+		assertEquals(new Voting(Arrays.asList(bid), powers), phase.getInform());
+
+	}
+
+	@Test
+	public void isFinalTest() {
+		assertFalse(phase.isFinal(1l));
+		assertTrue(phase.isFinal(10l));
+	}
+
+	@Test
+	public void isFinalTestActorNotYetActed() {
+		PartyStates actedstate = mock(PartyStates.class);
+		when(actedstate.getNotYetActed())
+				.thenReturn(Collections.singleton(party1));
+		OfferPhase testphase = new OfferPhase(actedstate, 10l, evaluator);
+		assertFalse(testphase.isFinal(1l));
+	}
+
+	@Test
+	public void isFinalTestAllActorsActed() {
+		PartyStates actedstate = mock(PartyStates.class);
+		when(actedstate.getNotYetActed()).thenReturn(Collections.emptySet());
+		OfferPhase testphase = new OfferPhase(actedstate, 10l, evaluator);
+		assertTrue(testphase.isFinal(1l));
+	}
+
+	@Test(expected = ProtocolException.class)
+	public void checkIncorrectActorTest() throws ProtocolException {
+		phase.checkAction(party1, new EndNegotiation(party2), 1);
+	}
+
+	@Test(expected = ProtocolException.class)
+	public void checkNotAllowedActionTest() throws ProtocolException {
+		phase.checkAction(party1, new Votes(party2, Collections.emptyList()),
+				1);
+	}
+
+	@Test
+	public void testFinish() {
+		Phase ph = phase.finish();
+		assertTrue(ph.getPartyStates().getNotYetActed().isEmpty());
+		assertEquals(3, ph.getPartyStates().getExceptions().size());
+		assertTrue(phase.getPartyStates().getAgreements().getMap().isEmpty());
+	}
+
+	@Test(expected = IllegalStateException.class)
+	public void testNextWrong() {
+		// state is not final, should not work
+		phase.next(1, 1000);
+	}
+
+	@Test
+	public void testNextNoParties() {
+		Phase ph = phase.finish();
+		// no parties are left now, all failed
+		// but this is not part of the next() check.
+		Phase next = ph.next(1, 1000);
+		assertTrue(next instanceof OptInPhase);
+		// no remaining parties, since finish kicked all
+		assertTrue(next.getPartyStates().getNotYetActed().isEmpty());
+	}
+
+	@Test
+	public void testAllowed() {
+		phase.with(party1, votes, 1);
+	}
+
+	@Test
+	public void getVotesTest() {
+		assertEquals(Collections.emptyList(), phase.getVotes());
+		List<Votes> vts = phase.with(party1, votes, 1).getVotes();
+		assertEquals(Arrays.asList(votes), vts);
+	}
+
+	@Test(expected = IllegalArgumentException.class)
+	public void testNextTooShortDuration() {
+		phase.next(1, Phase.PHASE_MINTIME - 1);
+	}
+
+	@Test(expected = IllegalStateException.class)
+	public void testNextNotFinished() {
+		phase.next(1, Phase.PHASE_MINTIME + 1);
+	}
+
+	@Test(expected = IllegalStateException.class)
+	public void testNext() {
+		phase.next(11, Phase.PHASE_MINTIME + 1);
+	}
+
+}
Index: protocol/src/test/java/geniusweb/protocol/session/saop/SAOPTest.java
===================================================================
--- protocol/src/test/java/geniusweb/protocol/session/saop/SAOPTest.java	(revision 23)
+++ protocol/src/test/java/geniusweb/protocol/session/saop/SAOPTest.java	(revision 24)
@@ -34,4 +34,5 @@
 import geniusweb.events.CurrentState;
 import geniusweb.events.ProtocolEvent;
+import geniusweb.inform.Agreements;
 import geniusweb.inform.Finished;
 import geniusweb.inform.Inform;
@@ -177,4 +178,5 @@
 		when(state.toString()).thenReturn(asText);
 		when(state.with(any(ProtocolException.class))).thenReturn(failstate);
+		when(state.getAgreements()).thenReturn(mock(Agreements.class));
 	}
 
@@ -260,5 +262,4 @@
 	@Test
 	public void testActionRequestWrongActor() {
-
 		saop.actionRequest(conn2, mock(EndNegotiation.class));
 
@@ -290,4 +291,5 @@
 		when(state.with(any(PartyId.class), any(EndNegotiation.class)))
 				.thenReturn(finalstate);
+		// when(finalstate.getAgreements()).thenReturn(mock(Agreements.class));
 
 		saop.actionRequest(conn1, mock(EndNegotiation.class));
@@ -311,5 +313,7 @@
 		doThrow(new IOException("fail sending yourturn")).when(conn1)
 				.send(any(YourTurn.class));
-
+		// CHECK is the state really final after an exception?
+		when(state.with(any(ProtocolException.class))).thenReturn(finalstate);
+		// when(state.getAgreements()).thenReturn(mock(Agreements.class));
 		saop.actionRequest(conn1, mock(Accept.class));
 
@@ -322,4 +326,5 @@
 		doThrow(new IOException("fail sending yourturn")).when(conn1)
 				.send(any(YourTurn.class));
+		// when(failstate.getAgreements()).thenReturn(mock(Agreements.class));
 		// not turn of conn2.
 		saop.actionRequest(conn2, mock(EndNegotiation.class));
@@ -332,4 +337,5 @@
 	public void testActionInFinalState() throws IOException {
 		saop = new SAOP(finalstate, new ReportToLogger("test"));
+		// when(finalstate.getAgreements()).thenReturn(mock(Agreements.class));
 
 		saop.actionRequest(conn1, mock(Offer.class));
