Index: protocol/src/test/java/geniusweb/protocol/WillBeCalledTest.java
===================================================================
--- protocol/src/test/java/geniusweb/protocol/WillBeCalledTest.java	(revision 21)
+++ protocol/src/test/java/geniusweb/protocol/WillBeCalledTest.java	(revision 21)
@@ -0,0 +1,37 @@
+package geniusweb.protocol;
+
+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/DefaultSessionStateTest.java
===================================================================
--- protocol/src/test/java/geniusweb/protocol/session/DefaultSessionStateTest.java	(revision 20)
+++ protocol/src/test/java/geniusweb/protocol/session/DefaultSessionStateTest.java	(revision 21)
@@ -23,5 +23,5 @@
 import geniusweb.actions.PartyId;
 import geniusweb.deadline.DeadlineTime;
-import geniusweb.issuevalue.Bid;
+import geniusweb.inform.Agreements;
 import geniusweb.progress.Progress;
 import geniusweb.progress.ProgressTime;
@@ -29,5 +29,4 @@
 import geniusweb.protocol.partyconnection.ProtocolToPartyConnections;
 import geniusweb.protocol.session.saop.SAOPSettings;
-import geniusweb.protocol.session.saop.SaopPartyWithProfile;
 import geniusweb.references.Parameters;
 import geniusweb.references.PartyRef;
@@ -60,10 +59,10 @@
 				new PartyRef("party2"), new Parameters());
 		ProfileRef profile2 = new ProfileRef("profile2");
-		List<SaopPartyWithProfile> participants = Arrays.asList(
-				new SaopPartyWithProfile(party1ref, profile1),
-				new SaopPartyWithProfile(party2ref, profile2));
+		List<OnePartyTeam> participants = Arrays.asList(
+				new OnePartyTeam(party1ref, profile1),
+				new OnePartyTeam(party2ref, profile2));
 		SessionSettings settings = new SAOPSettings(participants, deadline);
 		ProtocolException e = new ProtocolException("test protocol error",
-				party1.getName());
+				party1);
 		HashMap<PartyId, PartyWithProfile> partyprofiles = new HashMap<PartyId, PartyWithProfile>();
 		partyprofiles.put(party1, new PartyWithProfile(party1ref, profile1));
@@ -135,9 +134,4 @@
 
 	@Override
-	public Bid getAgreement() {
-		return null;
-	}
-
-	@Override
 	public SessionResult getResult() {
 
@@ -145,8 +139,13 @@
 		for (int n = 0; n < getConnections().size(); n++)
 			emptylist.add(0d);
-		return new SessionResult(getSettings().getAllParties(), getAgreement(),
+		return new SessionResult(getSettings().getAllParties(), getAgreements(),
 				emptylist, getError());
 
 	}
 
+	@Override
+	public Agreements getAgreements() {
+		return new Agreements();
+	}
+
 }
Index: protocol/src/test/java/geniusweb/protocol/session/SessionResultTest.java
===================================================================
--- protocol/src/test/java/geniusweb/protocol/session/SessionResultTest.java	(revision 20)
+++ protocol/src/test/java/geniusweb/protocol/session/SessionResultTest.java	(revision 21)
@@ -7,4 +7,5 @@
 import java.util.Arrays;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
@@ -16,4 +17,6 @@
 import com.fasterxml.jackson.databind.ObjectMapper;
 
+import geniusweb.actions.PartyId;
+import geniusweb.inform.Agreements;
 import geniusweb.issuevalue.Bid;
 import geniusweb.issuevalue.DiscreteValue;
@@ -32,15 +35,17 @@
 	private final String ISSUE1 = "issue1";
 	private SessionResult result1, result1a, result2, result3, result4;
-	private String errorstring; // created dynamically: eclipse and maven
-								// generate different stacktrace.
-	private String jsonstring = "{\"participants\":[{\"party\":{\"partyref\":\"party1\",\"parameters\":{}},\"profile\":\"profile1\"},{\"party\":{\"partyref\":\"party2\",\"parameters\":{}},\"profile\":\"profile2\"}],\"agreement\":{\"issuevalues\":{\"issue1\":\"a\"}},\"penalties\":[0.0,0.0],\"error\":null}";
+	private String jsonstring = "{\"participants\":[{\"party\":{\"partyref\":\"party1\",\"parameters\":{}},\"profile\":\"profile1\"},{\"party\":{\"partyref\":\"party2\",\"parameters\":{}},\"profile\":\"profile2\"}],\"agreements\":{\"party2\":{\"issuevalues\":{\"issue1\":\"a\"}},\"party1\":{\"issuevalues\":{\"issue1\":\"a\"}}},\"penalties\":[0.0,0.0],\"error\":null}";
 	private List<Double> nopenalties = Arrays.asList(0d, 0d);
 	private List<Double> penalties = Arrays.asList(0.1d, 0.2d);
 
+	private PartyId PARTY1 = new PartyId("party1");
+	private PartyId PARTY2 = new PartyId("party2");
+	private PartyId PARTY3 = new PartyId("party3");
+
 	@Before
 	public void before() throws URISyntaxException, JsonProcessingException {
-		errorstring = "\"error\":{\"java.lang.RuntimeException\":"
+		String errorstring = "\"error\":{\"java.lang.RuntimeException\":"
 				+ jackson.writeValueAsString(error) + "}";
-		System.out.println(errorstring);
+		// System.out.println(errorstring);
 
 		PartyWithParameters party1 = new PartyWithParameters(
@@ -57,4 +62,6 @@
 		issuevalues1.put(ISSUE1, new DiscreteValue("a"));
 		Bid bid1 = new Bid(issuevalues1);
+		Agreements agreement1 = new Agreements().with(bid1,
+				new HashSet<>(Arrays.asList(PARTY1, PARTY2)));
 
 		// different order but that shouldn't matter
@@ -62,16 +69,18 @@
 		issuevalues2.put(ISSUE1, new DiscreteValue("b"));
 		Bid bid2 = new Bid(issuevalues2);
+		Agreements agreement2 = new Agreements().with(bid2,
+				new HashSet<>(Arrays.asList(PARTY1, PARTY3)));
 
 		result1 = new SessionResult(Arrays.asList(partyprofile1, partyprofile2),
-				bid1, nopenalties, null);
+				agreement1, nopenalties, null);
 		result1a = new SessionResult(
-				Arrays.asList(partyprofile1, partyprofile2), bid1, nopenalties,
-				null);
+				Arrays.asList(partyprofile1, partyprofile2), agreement1,
+				nopenalties, null);
 		result2 = new SessionResult(Arrays.asList(partyprofile1, partyprofile2),
-				bid2, nopenalties, null);
+				agreement2, nopenalties, null);
 		result3 = new SessionResult(Arrays.asList(partyprofile2, partyprofile1),
-				bid2, nopenalties, null);
+				agreement1, nopenalties, null);
 		result4 = new SessionResult(Arrays.asList(partyprofile2, partyprofile1),
-				bid2, penalties, null);
+				agreement1, penalties, null);
 
 		// IGNORE ERROR for now, it fails somewhere deep in maven suddenly.
@@ -90,8 +99,8 @@
 	public List<String> getGeneralTestStrings() {
 		return Arrays.asList(
-				"SessionResult.*party1.*profile1.*,.*party2.*profile2.*Bid.*issue1=\"a\".*0\\.0.*0\\.0.*null.*",
-				"SessionResult.*party1.*profile1.*,.*party2.*profile2.*Bid.*issue1=\"b\".*0\\.0.*0\\.0.*null.*",
-				"SessionResult.*party2.*profile2.*,.*party1.*profile1.*Bid.*issue1=\"b\".*0\\.0.*0\\.0.*null.*",
-				"SessionResult.*party2.*profile2.*,.*party1.*profile1.*Bid.*issue1=\"b\".*0\\.1.*0\\.2.*null.*"
+				"SessionResult.*party1.*profile1.*,.*party2.*profile2.*Agreements.*Bid.*issue1=\"a\".*0\\.0.*0\\.0.*null.*",
+				"SessionResult.*party1.*profile1.*,.*party2.*profile2.*Agreements.*Bid.*issue1=\"b\".*0\\.0.*0\\.0.*null.*",
+				"SessionResult.*party2.*profile2.*,.*party1.*profile1.*Agreements.*Bid.*issue1=\"a\".*0\\.0.*0\\.0.*null.*",
+				"SessionResult.*party2.*profile2.*,.*party1.*profile1.*Agreements.*Bid.*issue1=\"a\".*0\\.1.*0\\.2.*null.*"
 
 		);
Index: protocol/src/test/java/geniusweb/protocol/session/amop/AMOPSettingsTest.java
===================================================================
--- protocol/src/test/java/geniusweb/protocol/session/amop/AMOPSettingsTest.java	(revision 21)
+++ protocol/src/test/java/geniusweb/protocol/session/amop/AMOPSettingsTest.java	(revision 21)
@@ -0,0 +1,149 @@
+package geniusweb.protocol.session.amop;
+
+import static org.junit.Assert.assertEquals;
+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.List;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import geniusweb.deadline.Deadline;
+import geniusweb.deadline.DeadlineRounds;
+import geniusweb.deadline.DeadlineTime;
+import geniusweb.protocol.session.OnePartyTeam;
+import geniusweb.protocol.session.SessionSettings;
+import geniusweb.references.Parameters;
+import geniusweb.references.PartyRef;
+import geniusweb.references.PartyWithParameters;
+import geniusweb.references.ProfileRef;
+import tudelft.utilities.junit.GeneralTests;
+import tudelft.utilities.logging.ReportToLogger;
+
+public class AMOPSettingsTest extends GeneralTests<AMOPSettings> {
+
+	private OnePartyTeam partyprof1 = mock(OnePartyTeam.class);
+	private OnePartyTeam partyprof2 = mock(OnePartyTeam.class);
+	private OnePartyTeam partyprof3 = mock(OnePartyTeam.class);
+	private List<OnePartyTeam> participants2 = Arrays.asList(partyprof1,
+			partyprof2);
+	private List<OnePartyTeam> participants3 = Arrays.asList(partyprof1,
+			partyprof2, partyprof3);
+
+	private DeadlineTime deadline = mock(DeadlineTime.class);
+	private Deadline deadline2 = mock(Deadline.class);
+	private AMOPSettings settings1 = new AMOPSettings(participants2, deadline);
+	private AMOPSettings settings1a = new AMOPSettings(participants2, deadline);
+	private AMOPSettings settings2 = new AMOPSettings(participants3, deadline);
+	private AMOPSettings settings3 = new AMOPSettings(participants2, deadline2);
+	private final ObjectMapper jackson = new ObjectMapper();
+
+	private AMOPSettings sersettings;
+	private final String serialized = "{\"AMOPSettings\":{\"participants\":[{\"party\":{\"partyref\":\"http://party1\",\"parameters\":{}},\"profile\":\"http://profile1\"},{\"party\":{\"partyref\":\"http://party2\",\"parameters\":{}},\"profile\":\"http://profile2\"}],\"deadline\":{\"deadlinetime\":{\"durationms\":100}}}}";
+	private List<OnePartyTeam> participants;
+
+	@Before
+	public void before() throws URISyntaxException {
+		when(deadline.getDuration()).thenReturn(1000l);
+		when(deadline.toString()).thenReturn("deadline");
+		when(deadline2.toString()).thenReturn("deadline2");
+
+		when(partyprof1.toString()).thenReturn("party and profile 1");
+		when(partyprof2.toString()).thenReturn("party and profile 2");
+		when(partyprof3.toString()).thenReturn("party and profile 3");
+
+		// SERIALIZABLE version with REAL objects. Still no workaround for
+		// this...
+		PartyWithParameters party1 = new PartyWithParameters(
+				new PartyRef("http://party1"), new Parameters());
+		ProfileRef profile1 = new ProfileRef("http://profile1");
+		PartyWithParameters party2 = new PartyWithParameters(
+				new PartyRef("http://party2"), new Parameters());
+		ProfileRef profile2 = new ProfileRef("http://profile2");
+		OnePartyTeam partywithprof1 = new OnePartyTeam(party1, profile1);
+		OnePartyTeam partywithprof2 = new OnePartyTeam(party2, profile2);
+		participants = Arrays.asList(partywithprof1, partywithprof2);
+
+		Deadline deadlinetime = new DeadlineTime(100);
+		sersettings = new AMOPSettings(participants, deadlinetime);
+
+	}
+
+	@Override
+	public List<List<AMOPSettings>> getGeneralTestData() {
+		return Arrays.asList(Arrays.asList(settings1, settings1a),
+				Arrays.asList(settings2), Arrays.asList(settings3));
+	}
+
+	@Override
+	public List<String> getGeneralTestStrings() {
+		return Arrays.asList(
+				"AMOPSettings.party and profile 1, party and profile 2.,deadline.",
+				"AMOPSettings.party and profile 1, party and profile 2, party and profile 3.,deadline.",
+				"AMOPSettings.party and profile 1, party and profile 2.,deadline2.");
+	}
+
+	@Test
+	public void getProtocolTest() {
+		assertEquals("AMOP", settings1.getProtocol(new ReportToLogger("test"))
+				.getRef().getURI().toString());
+	}
+
+	@Test(expected = IllegalArgumentException.class)
+	public void constructorNoDeadlineTest() {
+		new AMOPSettings(participants2, null);
+	}
+
+	@Test
+	public void testMaxRuntime() {
+		when(deadline.getDuration()).thenReturn(234l);
+		assertEquals((Double) .234d, settings1.getMaxRunTime());
+	}
+
+	@Test
+	public void testMaxRuntimeRounds() {
+		deadline = mock(DeadlineRounds.class);
+		when(deadline.getDuration()).thenReturn(12000l);
+
+		AMOPSettings settings = new AMOPSettings(participants2, deadline);
+
+		assertEquals((Double) 12d, settings.getMaxRunTime());
+	}
+
+	@Test
+	public void testDeserialize() throws IOException {
+		SessionSettings obj = jackson.readValue(serialized,
+				SessionSettings.class);
+		System.out.println(obj);
+		assertEquals(sersettings, obj);
+	}
+
+	@Test
+	public void testSerialize()
+			throws JsonProcessingException, URISyntaxException {
+
+		String string = jackson.writeValueAsString(sersettings);
+		System.out.println(string);
+		assertEquals(serialized, string);
+	}
+
+	@Test
+	public void testWith() {
+		AMOPSettings saop = new AMOPSettings(participants2, deadline);
+		SessionSettings saop2 = saop.with(partyprof3);
+		assertEquals(3, saop2.getTeams().size());
+	}
+
+	@Test
+	public void testGetAllParties() {
+		assertEquals(participants, sersettings.getAllParties());
+	}
+
+}
Index: protocol/src/test/java/geniusweb/protocol/session/amop/AMOPStateTest.java
===================================================================
--- protocol/src/test/java/geniusweb/protocol/session/amop/AMOPStateTest.java	(revision 21)
+++ protocol/src/test/java/geniusweb/protocol/session/amop/AMOPStateTest.java	(revision 21)
@@ -0,0 +1,436 @@
+package geniusweb.protocol.session.amop;
+
+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.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import geniusweb.actions.Accept;
+import geniusweb.actions.Action;
+import geniusweb.actions.EndNegotiation;
+import geniusweb.actions.Offer;
+import geniusweb.actions.PartyId;
+import geniusweb.actions.Vote;
+import geniusweb.actions.Votes;
+import geniusweb.inform.Agreements;
+import geniusweb.issuevalue.Bid;
+import geniusweb.progress.Progress;
+import geniusweb.progress.ProgressRounds;
+import geniusweb.progress.ProgressTime;
+import geniusweb.protocol.ProtocolException;
+import geniusweb.protocol.partyconnection.ProtocolToPartyConn;
+import geniusweb.protocol.partyconnection.ProtocolToPartyConnections;
+import geniusweb.protocol.session.amop.AMOPState.Phase;
+import geniusweb.references.PartyWithProfile;
+import tudelft.utilities.junit.GeneralTests;
+
+public class AMOPStateTest extends GeneralTests<AMOPState> {
+	private final long NOW = 1000;
+	Bid a = mock(Bid.class), b = mock(Bid.class), c = mock(Bid.class),
+			d = mock(Bid.class);
+
+	private final PartyId party1 = new PartyId("party1");
+	private final PartyId party2 = new PartyId("party2");
+	private final PartyId party3 = new PartyId("party3");
+	private final PartyId party4 = new PartyId("party4");
+	private final List<Action> actions = new LinkedList<>();
+	private final Action action = mock(Action.class);
+	private final List<Action> actions2 = Arrays.asList(action);
+
+	private final ProtocolToPartyConn party1conn = mock(
+			ProtocolToPartyConn.class);
+	private final ProtocolToPartyConn party2conn = mock(
+			ProtocolToPartyConn.class);
+	private final ProtocolToPartyConn party3conn = mock(
+			ProtocolToPartyConn.class);
+
+	private final ProtocolToPartyConnections connections = new ProtocolToPartyConnections(
+			Arrays.asList(party1conn, party2conn));
+	private final ProtocolToPartyConnections connections2 = new ProtocolToPartyConnections(
+			Arrays.asList(party1conn, party3conn));
+	private final ProtocolToPartyConnections connections3 = new ProtocolToPartyConnections(
+			Arrays.asList(party1conn, party2conn, party3conn));
+
+	private final Progress progresstime = mock(ProgressTime.class);
+	private final ProgressRounds progressrounds = mock(ProgressRounds.class);
+	private final ProgressRounds progressrounds1 = mock(ProgressRounds.class);
+	private final AMOPSettings settings = mock(AMOPSettings.class);
+	private final AMOPSettings settings2 = mock(AMOPSettings.class);
+	private AMOPState state1, state1a, state2, state3, state4, state5, state6,
+			state7, state8, state9;
+
+	private final Bid bid1 = mock(Bid.class);
+	private final Bid otherbid = mock(Bid.class);
+	private final Accept accept1 = new Accept(party1, bid1);
+	private final Accept accept2 = new Accept(party2, bid1);
+	private final Accept acceptother = new Accept(party2, otherbid);
+	private final Offer offer1 = new Offer(party1, bid1);
+	private final EndNegotiation endNegotiation1 = new EndNegotiation(party1);
+
+	private final Map<PartyId, PartyWithProfile> partyprofiles1 = mock(
+			HashMap.class);
+	private final Map<PartyId, PartyWithProfile> partyprofiles2 = mock(
+			HashMap.class);
+
+	private final Agreements agreements1 = new Agreements();
+	private final Agreements agreements2 = mock(Agreements.class);
+
+	private final Map<PartyId, ProtocolException> exceptions1 = mock(
+			HashMap.class);
+	private final Map<PartyId, ProtocolException> exceptions2 = mock(
+			HashMap.class);
+
+	private final List<PartyId> walkedaway0 = Arrays.asList();
+	private final List<PartyId> walkedaway1 = Arrays.asList(party1);
+	private final List<PartyId> walkedaway3 = Arrays.asList(party3);
+
+	@Before
+	public void before() {
+		when(party1conn.getParty()).thenReturn(party1);
+		when(party2conn.getParty()).thenReturn(party2);
+		when(party3conn.getParty()).thenReturn(party3);
+		when(party1conn.toString()).thenReturn("conn1");
+		when(party2conn.toString()).thenReturn("conn2");
+		when(party3conn.toString()).thenReturn("conn3");
+		when(action.toString()).thenReturn("act1");
+
+		when(progressrounds.getTerminationTime())
+				.thenReturn(new Date(System.currentTimeMillis() + 3600000l));
+		when(progressrounds1.getTerminationTime())
+				.thenReturn(new Date(System.currentTimeMillis() + 3600000l));
+		when(progressrounds.advance()).thenReturn(progressrounds1);
+
+		state1 = new AMOPState(Phase.INIT, actions, connections, progresstime,
+				settings, partyprofiles1, agreements1, exceptions1,
+				walkedaway0);
+		state1a = new AMOPState(Phase.INIT, actions, connections, progresstime,
+				settings, partyprofiles1, agreements1, exceptions1,
+				walkedaway0);
+		state2 = new AMOPState(Phase.INIT, actions2, connections, progresstime,
+				settings, partyprofiles1, agreements1, exceptions1,
+				walkedaway0);
+		state3 = new AMOPState(Phase.INIT, actions, connections2, progresstime,
+				settings, partyprofiles1, agreements1, exceptions1,
+				walkedaway0);
+		state4 = new AMOPState(Phase.INIT, actions, connections, progressrounds,
+				settings, partyprofiles1, agreements1, exceptions1,
+				walkedaway0);
+		state5 = new AMOPState(Phase.INIT, actions, connections, progresstime,
+				settings2, partyprofiles1, agreements1, exceptions1,
+				walkedaway0);
+		state6 = new AMOPState(Phase.INIT, actions, connections, progresstime,
+				settings, partyprofiles2, agreements1, exceptions1,
+				walkedaway0);
+		state7 = new AMOPState(Phase.INIT, actions, connections, progresstime,
+				settings, partyprofiles1, agreements2, exceptions1,
+				walkedaway0);
+		state8 = new AMOPState(Phase.INIT, actions, connections, progresstime,
+				settings, partyprofiles1, agreements1, exceptions2,
+				walkedaway0);
+		state9 = new AMOPState(Phase.INIT, actions, connections, progresstime,
+				settings, partyprofiles1, agreements1, exceptions1,
+				walkedaway3);
+	}
+
+	@Override
+	public List<List<AMOPState>> getGeneralTestData() {
+		return Arrays.asList(Arrays.asList(state1, state1a),
+				Arrays.asList(state2), Arrays.asList(state3),
+				Arrays.asList(state4), Arrays.asList(state5),
+				Arrays.asList(state6), Arrays.asList(state7),
+				Arrays.asList(state8), Arrays.asList(state9));
+	}
+
+	@Override
+	public List<String> getGeneralTestStrings() {
+		// being lazy, toString is terrible large and everything's mocked
+		return Arrays.asList("AMOPState.*", "AMOPState.*", "AMOPState.*",
+				"AMOPState.*", "AMOPState.*", "AMOPState.*", "AMOPState.*",
+				"AMOPState.*", "AMOPState.*");
+	}
+
+	@Test
+	public void constructWith0Connection() {
+		state1 = new AMOPState(Phase.INIT, actions,
+				new ProtocolToPartyConnections(Arrays.asList()), progresstime,
+				settings, partyprofiles1, agreements1, exceptions1,
+				walkedaway0);
+	}
+
+	@Test
+	public void constructWithNullConnection() {
+		// is allowed
+		new AMOPState(Phase.INIT, actions, null, progresstime, settings,
+				partyprofiles1, agreements1, exceptions1, walkedaway0);
+	}
+
+	@Test
+	public void isInitFinalTest() {
+		assertFalse(state1.isFinal(NOW));
+	}
+
+	@Test
+	public void isInitFinalTest2() {
+		assertFalse(state1.isFinal(NOW + 12000));
+	}
+
+	@Test
+	public void withExceptionTest() {
+		AMOPState newstate1 = state1.with(party1,
+				mock(ProtocolException.class));
+		// party errors are not terminating in AMOP
+		assertFalse(newstate1.isFinal(NOW));
+		AMOPState newstate2 = newstate1.with(party2,
+				mock(ProtocolException.class));
+		assertFalse(newstate2.isFinal(NOW));
+	}
+
+	@Test
+	public void isOfferAgreementTest1() {
+		List<Action> actions = Arrays.asList(offer1);
+		AMOPState state = new AMOPState(Phase.INIT, actions, connections3,
+				progresstime, settings, partyprofiles1, agreements1,
+				exceptions1, walkedaway0);
+		assertTrue(state.getAgreements().getMap().isEmpty());
+	}
+
+	@Test(expected = ProtocolException.class)
+	public void illegalActionInIllegalState() throws ProtocolException {
+		// party can not do accept. And certainly not in INIT phase.
+		state1.with(party1, offer1).with(party1, accept2);
+	}
+
+	@Test
+	public void isOfferAllowedInOFFER() throws ProtocolException {
+		AMOPState state = new AMOPState(Phase.OFFER, actions, connections,
+				progresstime, settings, partyprofiles1, agreements1,
+				exceptions1, walkedaway0);
+		state = state.with(party1, offer1);
+	}
+
+	@Test(expected = ProtocolException.class)
+	public void isOfferAllowedInINIT() throws ProtocolException {
+		AMOPState state = new AMOPState(Phase.INIT, actions, connections,
+				progresstime, settings, partyprofiles1, agreements1,
+				exceptions1, walkedaway0);
+		state = state.with(party1, offer1);
+	}
+
+	@Test(expected = ProtocolException.class)
+	public void isOfferAllowedInVOTE() throws ProtocolException {
+		AMOPState state = new AMOPState(Phase.VOTE, actions, connections,
+				progresstime, settings, partyprofiles1, agreements1,
+				exceptions1, walkedaway0);
+		state = state.with(party1, offer1);
+	}
+
+	@Test(expected = ProtocolException.class)
+	public void isOfferAcceptAgreementTest2() throws ProtocolException {
+		AMOPState state = new AMOPState(Phase.OFFER, actions, connections,
+				progresstime, settings, partyprofiles1, agreements1,
+				exceptions1, walkedaway0);
+		state = state.with(party1, offer1).with(party1, accept2);
+	}
+
+	@Test
+	public void testWithProgress() {
+		AMOPState state = new AMOPState(Phase.INIT, actions, connections, null,
+				settings, partyprofiles1, agreements1, exceptions1,
+				walkedaway0);
+		state = state.with(progresstime);
+		assertEquals(progresstime, state.getProgress());
+	}
+
+	@Test(expected = IllegalArgumentException.class)
+	public void testWithProgressAlreadySet() {
+		AMOPState state = new AMOPState(Phase.INIT, actions, connections,
+				progressrounds, settings, partyprofiles1, agreements1,
+				exceptions1, walkedaway0);
+		state = state.with(progresstime);
+	}
+
+	@Test
+	public void activePartiesWalkedAwayTest() {
+		AMOPState state = new AMOPState(Phase.INIT, actions, connections3,
+				progressrounds, settings, partyprofiles1, agreements1,
+				exceptions1, walkedaway3);
+		assertEquals(Arrays.asList(party1, party2), state.getActiveParties());
+	}
+
+	@Test
+	public void activePartiesAgreedTest() {
+		Agreements agreements = new Agreements().with(bid1,
+				new HashSet<>(Arrays.asList(party1, party2)));
+		AMOPState state = new AMOPState(Phase.INIT, actions, connections3,
+				progressrounds, settings, partyprofiles1, agreements,
+				exceptions1, walkedaway0);
+		assertEquals(Arrays.asList(party3), state.getActiveParties());
+	}
+
+	@Test
+	public void activePartiesErrorTest() {
+		Map<PartyId, ProtocolException> exceptions = Collections
+				.singletonMap(party2, new ProtocolException("test", party2));
+		AMOPState state = new AMOPState(Phase.INIT, actions, connections3,
+				progressrounds, settings, partyprofiles1, agreements1,
+				exceptions, walkedaway0);
+		assertEquals(Arrays.asList(party1, party3), state.getActiveParties());
+	}
+
+	/************** isFinal tests *****************/
+	@Test
+	public void deadlineProgressTimeDeadlineTest() {
+		Progress progress = mock(Progress.class);
+		when(progress.isPastDeadline(any())).thenReturn(true);
+		AMOPState state = new AMOPState(Phase.VOTE, actions, connections,
+				progress, settings, partyprofiles1, agreements1, exceptions1,
+				walkedaway0);
+		assertTrue(state.isFinal(10));
+	}
+
+	@Test
+	public void deadlineProgressTestOnly1Active() {
+		Progress progress = mock(Progress.class);
+		when(progress.isPastDeadline(any())).thenReturn(false);
+		List<PartyId> walkedaway13 = Arrays.asList(party1, party3);
+
+		AMOPState state = new AMOPState(Phase.VOTE, actions, connections,
+				progress, settings, partyprofiles1, agreements1, exceptions1,
+				walkedaway13);
+		assertTrue(state.isFinal(10));
+	}
+
+	/*************
+	 * action tests
+	 ***************/
+	@Test
+	public void OfferTest() throws ProtocolException {
+		AMOPState state = new AMOPState(Phase.OFFER, actions, connections,
+				progresstime, settings, partyprofiles1, agreements1,
+				exceptions1, walkedaway0);
+		state = state.with(party1, new Offer(party1, bid1));
+		assertEquals(1, state.getActions().size());
+	}
+
+	@Test(expected = ProtocolException.class)
+	public void OfferTwiceTest() throws ProtocolException {
+		AMOPState state = new AMOPState(Phase.OFFER, actions, connections,
+				progresstime, settings, partyprofiles1, agreements1,
+				exceptions1, walkedaway0);
+		state = state.with(party1, new Offer(party1, bid1));
+		// party1 may offer only once
+		state = state.with(party1, new Offer(party1, bid1));
+	}
+
+	@Test
+	public void endNegoOfferTest() throws ProtocolException {
+		AMOPState state = new AMOPState(Phase.OFFER, actions, connections,
+				progresstime, settings, partyprofiles1, agreements1,
+				exceptions1, walkedaway0);
+		state = state.with(party1, new EndNegotiation(party1));
+		assertEquals(1, state.getActions().size());
+		assertEquals(1, state.getWalkedAway().size());
+	}
+
+	@Test
+	public void endNegoVoteTest() throws ProtocolException {
+		AMOPState state = new AMOPState(Phase.VOTE, actions, connections,
+				progresstime, settings, partyprofiles1, agreements1,
+				exceptions1, walkedaway0);
+		state = state.with(party1, new EndNegotiation(party1));
+		assertEquals(1, state.getActions().size());
+		assertEquals(1, state.getWalkedAway().size());
+	}
+
+	@Test(expected = ProtocolException.class)
+	public void OfferButInactive() throws ProtocolException {
+		// party walked away or error'ed and then votes again
+		AMOPState state = new AMOPState(Phase.OFFER, actions, connections,
+				progresstime, settings, partyprofiles1, agreements1,
+				exceptions1, walkedaway1);
+		state = state.with(party1, new Offer(party1, bid1));
+	}
+
+	/************** NextPhase tests *****************/
+	@Test
+	public void isInitToOfferWorking() throws ProtocolException {
+		AMOPState state = state1.nextPhase();
+		assertEquals(Phase.OFFER, state.getPhase());
+	}
+
+	@Test
+	public void testCollectVotes() {
+		Votes vote1AB = new Votes(party1,
+				Arrays.asList(new Vote(party1, a, 2), new Vote(party1, b, 2)));
+		Votes vote2AB = new Votes(party2,
+				Arrays.asList(new Vote(party2, a, 2), new Vote(party2, b, 2)));
+		Votes vote3C = new Votes(party3, Arrays.asList(new Vote(party3, c, 2)));
+		Votes vote4AC = new Votes(party4,
+				Arrays.asList(new Vote(party4, a, 2), new Vote(party4, c, 2)));
+		// party 1,2,4 vote for A, party 1,2 vote for B, party 3,4 vote for C.
+		// the biggest vote is P,Q,S
+		Map<PartyId, Votes> votes = new HashMap<>();
+		votes.put(party1, vote1AB);
+		votes.put(party2, vote2AB);
+		votes.put(party3, vote3C);
+		votes.put(party4, vote4AC);
+
+		List<Action> actions1 = Arrays.asList(vote1AB, vote2AB, vote3C,
+				vote4AC);
+		AMOPState state = new AMOPState(Phase.VOTE, actions1, connections,
+				progresstime, settings, partyprofiles1, agreements1,
+				exceptions1, walkedaway1);
+		Agreements agrees = state.collectVotes(votes);
+		System.out.println(agrees);
+
+		// biggest agreement is party 1,2,4 for bid a.
+		assertEquals(new HashSet<>(Arrays.asList(party1, party2, party4)),
+				agrees.getMap().keySet());
+
+	}
+
+	@Test
+	public void testNextPhase() {
+		// copy of above. todo cleanup
+		Votes vote1AB = new Votes(party1,
+				Arrays.asList(new Vote(party1, a, 2), new Vote(party1, b, 2)));
+		Votes vote2AB = new Votes(party2,
+				Arrays.asList(new Vote(party2, a, 2), new Vote(party2, b, 2)));
+		Votes vote3C = new Votes(party3, Arrays.asList(new Vote(party3, c, 2)));
+		Votes vote4AC = new Votes(party4,
+				Arrays.asList(new Vote(party4, a, 2), new Vote(party4, c, 2)));
+		// party 1,2,4 vote for A, party 1,2 vote for B, party 3,4 vote for C.
+		// the biggest vote is P,Q,S
+		Map<PartyId, Votes> votes = new HashMap<>();
+		votes.put(party1, vote1AB);
+		votes.put(party2, vote2AB);
+		votes.put(party3, vote3C);
+		votes.put(party4, vote4AC);
+
+		List<Action> actions1 = Arrays.asList(vote1AB, vote2AB, vote3C,
+				vote4AC);
+		AMOPState state = new AMOPState(Phase.VOTE, actions1, connections,
+				progressrounds, settings, partyprofiles1, agreements1,
+				exceptions1, walkedaway1);
+		state = state.nextPhase();
+		assertEquals(Phase.OFFER, state.getPhase());
+		assertEquals(new HashSet<>(Arrays.asList(party1, party2, party4)),
+				state.getAgreements().getMap().keySet());
+		assertEquals(progressrounds.advance(), state.getProgress());
+
+	}
+}
Index: protocol/src/test/java/geniusweb/protocol/session/amop/AMOPTest.java
===================================================================
--- protocol/src/test/java/geniusweb/protocol/session/amop/AMOPTest.java	(revision 21)
+++ protocol/src/test/java/geniusweb/protocol/session/amop/AMOPTest.java	(revision 21)
@@ -0,0 +1,6 @@
+package geniusweb.protocol.session.amop;
+
+public class AMOPTest {
+
+	// TODO did not have time for this.
+}
Index: protocol/src/test/java/geniusweb/protocol/session/mopac/MOPACSettingsTest.java
===================================================================
--- protocol/src/test/java/geniusweb/protocol/session/mopac/MOPACSettingsTest.java	(revision 21)
+++ protocol/src/test/java/geniusweb/protocol/session/mopac/MOPACSettingsTest.java	(revision 21)
@@ -0,0 +1,165 @@
+package geniusweb.protocol.session.mopac;
+
+import static org.junit.Assert.assertEquals;
+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.List;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import geniusweb.deadline.Deadline;
+import geniusweb.deadline.DeadlineRounds;
+import geniusweb.deadline.DeadlineTime;
+import geniusweb.protocol.session.OnePartyTeam;
+import geniusweb.protocol.session.SessionSettings;
+import geniusweb.references.Parameters;
+import geniusweb.references.PartyRef;
+import geniusweb.references.PartyWithParameters;
+import geniusweb.references.ProfileRef;
+import geniusweb.voting.VotingEvaluator;
+import geniusweb.voting.votingevaluators.LargestAgreement;
+import tudelft.utilities.junit.GeneralTests;
+import tudelft.utilities.logging.ReportToLogger;
+
+public class MOPACSettingsTest extends GeneralTests<MOPACSettings> {
+
+	private final ObjectMapper jackson = new ObjectMapper();
+	private final Parameters noparams = new Parameters();
+	private OnePartyTeam partyprof1 = mockParty("party1", noparams);
+	private OnePartyTeam partyprof2 = mockParty("party2", noparams);
+	private OnePartyTeam partyprof3 = mockParty("party3", noparams);
+	private List<OnePartyTeam> participants2 = Arrays.asList(partyprof1,
+			partyprof2);
+	private List<OnePartyTeam> participants3 = Arrays.asList(partyprof1,
+			partyprof2, partyprof3);
+
+	private final VotingEvaluator ve = new LargestAgreement();
+
+	private DeadlineTime deadline = mock(DeadlineTime.class);
+	private Deadline deadline2 = mock(Deadline.class);
+	private MOPACSettings settings1 = new MOPACSettings(participants2, deadline,
+			ve);
+	private MOPACSettings settings1a = new MOPACSettings(participants2,
+			deadline, ve);
+	private MOPACSettings settings2 = new MOPACSettings(participants3, deadline,
+			ve);
+	private MOPACSettings settings3 = new MOPACSettings(participants2,
+			deadline2, ve);
+
+	private MOPACSettings sersettings;
+	private final String serialized = "{\"MOPACSettings\":{\"participants\":[{\"party\":{\"partyref\":\"http://party1\",\"parameters\":{}},\"profile\":\"http://profile1\"},{\"party\":{\"partyref\":\"http://party2\",\"parameters\":{}},\"profile\":\"http://profile2\"}],\"deadline\":{\"deadlinetime\":{\"durationms\":100}},\"votingevaluator\":{\"LargestAgreement\":{}}}}";
+	private List<OnePartyTeam> participants;
+
+	private OnePartyTeam mockParty(String partyname, Parameters params) {
+		OnePartyTeam team = mock(OnePartyTeam.class);
+		PartyWithParameters pwithp = mock(PartyWithParameters.class);
+		when(team.getParty()).thenReturn(pwithp);
+		when(team.toString()).thenReturn(partyname);
+		when(pwithp.toString()).thenReturn(partyname);
+		when(pwithp.getParameters()).thenReturn(params);
+		return team;
+	}
+
+	@Before
+	public void before() throws URISyntaxException {
+
+		when(deadline.getDuration()).thenReturn(1000l);
+		when(deadline.toString()).thenReturn("deadline");
+		when(deadline2.toString()).thenReturn("deadline2");
+
+		// SERIALIZABLE version with REAL objects. Still no workaround for
+		// this...
+		PartyWithParameters party1 = new PartyWithParameters(
+				new PartyRef("http://party1"), new Parameters());
+		ProfileRef profile1 = new ProfileRef("http://profile1");
+		PartyWithParameters party2 = new PartyWithParameters(
+				new PartyRef("http://party2"), new Parameters());
+		ProfileRef profile2 = new ProfileRef("http://profile2");
+		OnePartyTeam partywithprof1 = new OnePartyTeam(party1, profile1);
+		OnePartyTeam partywithprof2 = new OnePartyTeam(party2, profile2);
+		participants = Arrays.asList(partywithprof1, partywithprof2);
+
+		Deadline deadlinetime = new DeadlineTime(100);
+		sersettings = new MOPACSettings(participants, deadlinetime, ve);
+
+	}
+
+	@Override
+	public List<List<MOPACSettings>> getGeneralTestData() {
+		return Arrays.asList(Arrays.asList(settings1, settings1a),
+				Arrays.asList(settings2), Arrays.asList(settings3));
+	}
+
+	@Override
+	public List<String> getGeneralTestStrings() {
+		return Arrays.asList(
+				"MOPACSettings.*party1.*party2.*deadline.*LargestAgreement.*",
+				"MOPACSettings.*party1.*party2.*deadline.*LargestAgreement.*",
+				"MOPACSettings.*party1.*party2.*deadline2.*LargestAgreement.*");
+	}
+
+	@Test
+	public void getProtocolTest() {
+		assertEquals("MOPAC", settings1.getProtocol(new ReportToLogger("test"))
+				.getRef().getURI().toString());
+	}
+
+	@Test(expected = IllegalArgumentException.class)
+	public void constructorNoDeadlineTest() {
+		new MOPACSettings(participants2, null, ve);
+	}
+
+	@Test
+	public void testMaxRuntime() {
+		when(deadline.getDuration()).thenReturn(234l);
+		assertEquals((Double) .234d, settings1.getMaxRunTime());
+	}
+
+	@Test
+	public void testMaxRuntimeRounds() {
+		deadline = mock(DeadlineRounds.class);
+		when(deadline.getDuration()).thenReturn(12000l);
+
+		MOPACSettings settings = new MOPACSettings(participants2, deadline, ve);
+
+		assertEquals((Double) 12d, settings.getMaxRunTime());
+	}
+
+	@Test
+	public void testDeserialize() throws IOException {
+		SessionSettings obj = jackson.readValue(serialized,
+				SessionSettings.class);
+		System.out.println(obj);
+		assertEquals(sersettings, obj);
+	}
+
+	@Test
+	public void testSerialize()
+			throws JsonProcessingException, URISyntaxException {
+
+		String string = jackson.writeValueAsString(sersettings);
+		System.out.println(string);
+		assertEquals(serialized, string);
+	}
+
+	@Test
+	public void testWith() {
+		MOPACSettings saop = new MOPACSettings(participants2, deadline, ve);
+		SessionSettings saop2 = saop.with(partyprof3);
+		assertEquals(3, saop2.getTeams().size());
+	}
+
+	@Test
+	public void testGetAllParties() {
+		assertEquals(participants, sersettings.getAllParties());
+	}
+
+}
Index: protocol/src/test/java/geniusweb/protocol/session/mopac/MOPACTest.java
===================================================================
--- protocol/src/test/java/geniusweb/protocol/session/mopac/MOPACTest.java	(revision 21)
+++ protocol/src/test/java/geniusweb/protocol/session/mopac/MOPACTest.java	(revision 21)
@@ -0,0 +1,140 @@
+package geniusweb.protocol.session.mopac;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.databind.JsonMappingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import geniusweb.actions.Action;
+import geniusweb.actions.Offer;
+import geniusweb.actions.PartyId;
+import geniusweb.inform.Inform;
+import geniusweb.protocol.partyconnection.ProtocolToPartyConn;
+import geniusweb.protocol.partyconnection.ProtocolToPartyConnFactory;
+import tudelft.utilities.logging.Reporter;
+import tudelft.utilities.repository.NoResourcesNowException;
+
+public class MOPACTest {
+
+	private final ObjectMapper jackson = new ObjectMapper();
+
+	private static final PartyId PARTY1ID = new PartyId("party1");
+	private static final PartyId PARTY2ID = new PartyId("party2");
+	private static final PartyId PARTY3ID = new PartyId("party3");
+
+	// don't try to mock settings, all parts are needed and mocking
+	// makes the test unreadable.
+	private final String setstr = "{\"MOPACSettings\":{\"participants\":["
+			+ "{\"party\":{\"partyref\":\"http://party1\",\"parameters\":{}},\"profile\":\"http://profile1\"},"
+			+ "{\"party\":{\"partyref\":\"http://party2\",\"parameters\":{}},\"profile\":\"http://profile2\"},"
+			+ "{\"party\":{\"partyref\":\"http://party3\",\"parameters\":{}},\"profile\":\"http://profile3\"}],"
+			+ "\"deadline\":{\"deadlinetime\":{\"durationms\":100}},\"votingevaluator\":{\"LargestAgreement\":{}}}}";
+
+	private MOPACSettings settings;
+	private Reporter logger = mock(Reporter.class);
+	private MOPAC mopac;
+
+	private final ProtocolToPartyConnFactory factory = mock(
+			ProtocolToPartyConnFactory.class);
+	private final ProtocolToPartyConn conn1 = mock(ProtocolToPartyConn.class),
+			conn2 = mock(ProtocolToPartyConn.class),
+			conn3 = mock(ProtocolToPartyConn.class);
+
+	@Before
+	public void before() throws JsonParseException, JsonMappingException,
+			IOException, NoResourcesNowException {
+		settings = jackson.readValue(setstr, MOPACSettings.class);
+		mopac = settings.getProtocol(logger);
+
+		List connections = Arrays.asList(conn1, conn2, conn3);
+		when(factory.connect(any(List.class))).thenReturn(connections);
+
+		// hack the state.with(connection) stuff simplistically
+
+		when(conn1.getParty()).thenReturn(PARTY1ID);
+		when(conn2.getParty()).thenReturn(PARTY2ID);
+		when(conn3.getParty()).thenReturn(PARTY3ID);
+	}
+
+	@Test
+	public void testSmoke() {
+	}
+
+	@Test
+	public void testGetDescr() {
+		assertNotNull(mopac.getDescription());
+	}
+
+	@Test
+	public void testInitialState() {
+		MOPACState state = mopac.getState();
+		assertEquals(settings, state.getSettings());
+		assertTrue(state.getActions().isEmpty());
+	}
+
+	@Test
+	public void testProtocol() {
+		assertEquals("MOPAC", mopac.getRef().getURI().getPath());
+	}
+
+	@Ignore
+	@Test
+	public void testWorkingCheckDeadline()
+			throws IOException, NoResourcesNowException, InterruptedException {
+
+		mopac.start(factory);
+
+		System.out.println(mopac.getState());
+
+		// 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() {
+		mopac.start(factory);
+		verify(conn1, times(1)).addListener(any());
+		verify(conn2, times(1)).addListener(any());
+		verify(conn3, times(1)).addListener(any());
+	}
+
+	@Ignore
+	@Test
+	public void testActionIsBroadcast()
+			throws IOException, NoResourcesNowException, InterruptedException {
+
+		mopac.start(factory);
+		Action offer = mock(Offer.class);
+		mopac.actionRequest(conn1, offer, 1l);
+
+		// 1 time for YourTurn, one time for ActionDone.
+		// but filtering ActionDone here (instead of Action) does not work,
+		// maybe bug in Mockito?
+		verify(conn1, times(2)).send(any(Inform.class));
+	}
+
+	@Test
+	public void testAgreementTerminates() {
+
+	}
+}
Index: protocol/src/test/java/geniusweb/protocol/session/mopac/PartyStatesTest.java
===================================================================
--- protocol/src/test/java/geniusweb/protocol/session/mopac/PartyStatesTest.java	(revision 21)
+++ protocol/src/test/java/geniusweb/protocol/session/mopac/PartyStatesTest.java	(revision 21)
@@ -0,0 +1,57 @@
+package geniusweb.protocol.session.mopac;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+
+import org.junit.Test;
+
+import geniusweb.actions.PartyId;
+import geniusweb.inform.Agreements;
+import geniusweb.protocol.ProtocolException;
+
+public class PartyStatesTest {
+
+	private final PartyId party1 = new PartyId("party1");
+	private final PartyId party2 = new PartyId("party2");
+	private final PartyId party3 = new PartyId("party3");
+
+	private final Map<PartyId, Integer> powers = new HashMap<>();
+	private final PartyStates states;
+
+	public PartyStatesTest() {
+		powers.put(party1, 2);
+		powers.put(party2, 3);
+		powers.put(party3, 3);
+		states = new PartyStates(powers);
+	}
+
+	@Test
+	public void testBasics() {
+		assertEquals(powers.keySet(), states.getNegotiatingParties());
+		assertEquals(powers.keySet(), states.getNotYetActed());
+		assertEquals(0, states.getExceptions().size());
+	}
+
+	@Test
+	public void testException() {
+		PartyStates newstates = states
+				.with(new ProtocolException("bla", party1));
+		assertEquals(new Agreements(), newstates.getAgreements());
+		assertEquals(powers.keySet(), states.getNegotiatingParties());
+		assertEquals(new HashSet<>(Arrays.asList(party2, party3)),
+				newstates.getNotYetActed());
+	}
+
+	@Test
+	public void testFinish() {
+		PartyStates newstates = states.finish();
+		assertEquals(new Agreements(), newstates.getAgreements());
+		assertEquals(powers.keySet(), states.getNegotiatingParties());
+		assertEquals(Collections.emptySet(), newstates.getNotYetActed());
+	}
+}
Index: protocol/src/test/java/geniusweb/protocol/session/mopac/phase/OfferPhaseTest.java
===================================================================
--- protocol/src/test/java/geniusweb/protocol/session/mopac/phase/OfferPhaseTest.java	(revision 21)
+++ protocol/src/test/java/geniusweb/protocol/session/mopac/phase/OfferPhaseTest.java	(revision 21)
@@ -0,0 +1,67 @@
+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 java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.Test;
+
+import geniusweb.actions.EndNegotiation;
+import geniusweb.actions.PartyId;
+import geniusweb.actions.Votes;
+import geniusweb.protocol.ProtocolException;
+import geniusweb.protocol.session.mopac.PartyStates;
+import geniusweb.voting.VotingEvaluator;
+
+/**
+ * We also test defaultPhase here.
+ */
+public class OfferPhaseTest {
+
+	private final PartyId party1 = new PartyId("party1");
+	private final PartyId party2 = new PartyId("party2");
+	private final PartyId party3 = new PartyId("party3");
+
+	private final Map<PartyId, Integer> powers = new HashMap<>();
+	private final PartyStates states;
+	private final VotingEvaluator evaluator = mock(VotingEvaluator.class);
+	private final OfferPhase phase;
+
+	public OfferPhaseTest() {
+		powers.put(party1, 2);
+		powers.put(party2, 3);
+		powers.put(party3, 3);
+		states = new PartyStates(powers);
+		phase = new OfferPhase(null, states, 10l, evaluator);
+	}
+
+	@Test
+	public void isInitFinalTest() {
+		assertFalse(phase.isFinal(1l));
+		assertTrue(phase.isFinal(10l));
+	}
+
+	@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 testException() {
+		OfferPhase newphase = phase.with(new ProtocolException("bla", party1));
+		assertEquals(10l, newphase.getDeadline());
+		assertEquals(0l, phase.getPartyStates().getActions().size());
+	}
+
+}
Index: protocol/src/test/java/geniusweb/protocol/session/saop/SAOPSettingsTest.java
===================================================================
--- protocol/src/test/java/geniusweb/protocol/session/saop/SAOPSettingsTest.java	(revision 20)
+++ protocol/src/test/java/geniusweb/protocol/session/saop/SAOPSettingsTest.java	(revision 21)
@@ -19,4 +19,5 @@
 import geniusweb.deadline.DeadlineRounds;
 import geniusweb.deadline.DeadlineTime;
+import geniusweb.protocol.session.OnePartyTeam;
 import geniusweb.protocol.session.SessionSettings;
 import geniusweb.references.Parameters;
@@ -29,10 +30,10 @@
 public class SAOPSettingsTest extends GeneralTests<SAOPSettings> {
 
-	private SaopPartyWithProfile partyprof1 = mock(SaopPartyWithProfile.class);
-	private SaopPartyWithProfile partyprof2 = mock(SaopPartyWithProfile.class);
-	private SaopPartyWithProfile partyprof3 = mock(SaopPartyWithProfile.class);
-	private List<SaopPartyWithProfile> participants2 = Arrays.asList(partyprof1,
+	private OnePartyTeam partyprof1 = mock(OnePartyTeam.class);
+	private OnePartyTeam partyprof2 = mock(OnePartyTeam.class);
+	private OnePartyTeam partyprof3 = mock(OnePartyTeam.class);
+	private List<OnePartyTeam> participants2 = Arrays.asList(partyprof1,
 			partyprof2);
-	private List<SaopPartyWithProfile> participants3 = Arrays.asList(partyprof1,
+	private List<OnePartyTeam> participants3 = Arrays.asList(partyprof1,
 			partyprof2, partyprof3);
 
@@ -66,9 +67,7 @@
 				new PartyRef("http://party2"), new Parameters());
 		ProfileRef profile2 = new ProfileRef("http://profile2");
-		SaopPartyWithProfile partywithprof1 = new SaopPartyWithProfile(party1,
-				profile1);
-		SaopPartyWithProfile partywithprof2 = new SaopPartyWithProfile(party2,
-				profile2);
-		List<SaopPartyWithProfile> participants = Arrays.asList(partywithprof1,
+		OnePartyTeam partywithprof1 = new OnePartyTeam(party1, profile1);
+		OnePartyTeam partywithprof2 = new OnePartyTeam(party2, profile2);
+		List<OnePartyTeam> participants = Arrays.asList(partywithprof1,
 				partywithprof2);
 
Index: protocol/src/test/java/geniusweb/protocol/session/saop/SAOPStateTest.java
===================================================================
--- protocol/src/test/java/geniusweb/protocol/session/saop/SAOPStateTest.java	(revision 20)
+++ protocol/src/test/java/geniusweb/protocol/session/saop/SAOPStateTest.java	(revision 21)
@@ -176,5 +176,5 @@
 		SAOPState state = new SAOPState(actions, connections3, progressrounds,
 				settings, null, null);
-		assertNull(state.getAgreement());
+		assertTrue(state.getAgreements().getMap().isEmpty());
 	}
 
@@ -184,5 +184,5 @@
 		SAOPState state = new SAOPState(actions, connections3, progressrounds,
 				settings, null, null);
-		assertNull(state.getAgreement());
+		assertTrue(state.getAgreements().getMap().isEmpty());
 	}
 
@@ -192,5 +192,5 @@
 		SAOPState state = new SAOPState(actions, connections3, progressrounds,
 				settings, null, null);
-		assertNull(state.getAgreement());
+		assertTrue(state.getAgreements().getMap().isEmpty());
 	}
 
@@ -200,5 +200,5 @@
 		SAOPState state = new SAOPState(actions, connections3, progressrounds,
 				settings, null, null);
-		assertEquals(bid1, state.getAgreement());
+		assertEquals(bid1, state.getAgreements().getMap().get(party1));
 		assertTrue(state.isFinal(NOW));
 	}
@@ -209,5 +209,5 @@
 		SAOPState state = new SAOPState(actions, connections3, progressrounds,
 				settings, null, null);
-		assertEquals(null, state.getAgreement());
+		assertTrue(state.getAgreements().getMap().isEmpty());
 	}
 
@@ -217,5 +217,5 @@
 		SAOPState state = new SAOPState(actions, connections3, progressrounds,
 				settings, null, null);
-		assertEquals(null, state.getAgreement());
+		assertTrue(state.getAgreements().getMap().isEmpty());
 	}
 
@@ -246,5 +246,5 @@
 		SAOPState state = new SAOPState(actions, connections3, progressrounds,
 				settings, null, null);
-		assertEquals(null, state.getAgreement());
+		assertTrue(state.getAgreements().getMap().isEmpty());
 		assertEquals(null, state.getError());
 		assertTrue(state.isFinal(NOW));
@@ -255,5 +255,6 @@
 	public void isProtocolErrorFinal() {
 		SAOPState state = new SAOPState(actions, connections3, progressrounds,
-				settings, null, new ProtocolException("test error", "test"));
+				settings, null,
+				new ProtocolException("test error", new PartyId("test")));
 		assertTrue(state.isFinal(NOW));
 		assertNotNull(state.getError());
@@ -309,5 +310,5 @@
 		assertTrue(state.isFinal(NOW));
 		assertNull(state.getError());
-		assertEquals(bid1, state.getAgreement());
+		assertEquals(bid1, state.getAgreements().getMap().get(party1));
 
 	}
@@ -325,5 +326,5 @@
 		assertTrue(state.isFinal(NOW));
 		assertNull(state.getError());
-		assertEquals(bid2, state.getAgreement());
+		assertEquals(bid2, state.getAgreements().getMap().get(party1));
 
 	}
Index: protocol/src/test/java/geniusweb/protocol/session/saop/SAOPTest.java
===================================================================
--- protocol/src/test/java/geniusweb/protocol/session/saop/SAOPTest.java	(revision 20)
+++ protocol/src/test/java/geniusweb/protocol/session/saop/SAOPTest.java	(revision 21)
@@ -34,8 +34,8 @@
 import geniusweb.events.CurrentState;
 import geniusweb.events.ProtocolEvent;
-import geniusweb.party.inform.Finished;
-import geniusweb.party.inform.Inform;
-import geniusweb.party.inform.Settings;
-import geniusweb.party.inform.YourTurn;
+import geniusweb.inform.Finished;
+import geniusweb.inform.Inform;
+import geniusweb.inform.Settings;
+import geniusweb.inform.YourTurn;
 import geniusweb.progress.Progress;
 import geniusweb.protocol.ProtocolException;
@@ -43,4 +43,5 @@
 import geniusweb.protocol.partyconnection.ProtocolToPartyConnFactory;
 import geniusweb.protocol.partyconnection.ProtocolToPartyConnections;
+import geniusweb.protocol.session.OnePartyTeam;
 import geniusweb.protocol.session.TeamOfPartiesAndProfiles;
 import geniusweb.references.Parameters;
@@ -75,6 +76,6 @@
 	private final PartyRef party2ref = mock(PartyRef.class);
 	private final SAOPSettings settings = mock(SAOPSettings.class);
-	private final SaopPartyWithProfile team1 = mock(SaopPartyWithProfile.class);
-	private final SaopPartyWithProfile team2 = mock(SaopPartyWithProfile.class);
+	private final OnePartyTeam team1 = mock(OnePartyTeam.class);
+	private final OnePartyTeam team2 = mock(OnePartyTeam.class);
 	private SAOP saop;
 	private ProtocolToPartyConnFactory factory;
@@ -82,5 +83,5 @@
 	private ProtocolToPartyConn conn1 = mock(ProtocolToPartyConn.class),
 			conn2 = mock(ProtocolToPartyConn.class);
-	private Map<PartyId, SaopPartyWithProfile> partyprofiles;
+	private Map<PartyId, OnePartyTeam> partyprofiles;
 	private Progress progress = mock(Progress.class);
 	private ProfileRef profile1;
Index: protocol/src/test/java/geniusweb/protocol/session/saop/SaopPartyWithProfileTest.java
===================================================================
--- protocol/src/test/java/geniusweb/protocol/session/saop/SaopPartyWithProfileTest.java	(revision 20)
+++ protocol/src/test/java/geniusweb/protocol/session/saop/SaopPartyWithProfileTest.java	(revision 21)
@@ -17,4 +17,5 @@
 import com.fasterxml.jackson.databind.ObjectMapper;
 
+import geniusweb.protocol.session.OnePartyTeam;
 import geniusweb.protocol.session.TeamOfPartiesAndProfiles;
 import geniusweb.references.Parameters;
@@ -24,11 +25,10 @@
 import tudelft.utilities.junit.GeneralTests;
 
-public class SaopPartyWithProfileTest
-		extends GeneralTests<SaopPartyWithProfile> {
+public class SaopPartyWithProfileTest extends GeneralTests<OnePartyTeam> {
 
 	private PartyRef party1, party1a, party2, party3;
 	private ProfileRef profile1, profile2;
-	private SaopPartyWithProfile partyprof1, partyprof1a, partyprof2,
-			partyprof3, partyprof4;
+	private OnePartyTeam partyprof1, partyprof1a, partyprof2, partyprof3,
+			partyprof4;
 	private final String serialized = "{\"party\":{\"partyref\":\"ws:party1\",\"parameters\":{}},\"profile\":\"ws:profile1\"}";
 
@@ -54,14 +54,14 @@
 				settings1);
 
-		partyprof1 = new SaopPartyWithProfile(party1withparams1, profile1);
-		partyprof1a = new SaopPartyWithProfile(party1withparams1, profile1);
-		partyprof2 = new SaopPartyWithProfile(party2withparams1, profile1);
-		partyprof3 = new SaopPartyWithProfile(party1withparams1, profile2);
-		partyprof4 = new SaopPartyWithProfile(party1withparams2, profile1);
+		partyprof1 = new OnePartyTeam(party1withparams1, profile1);
+		partyprof1a = new OnePartyTeam(party1withparams1, profile1);
+		partyprof2 = new OnePartyTeam(party2withparams1, profile1);
+		partyprof3 = new OnePartyTeam(party1withparams1, profile2);
+		partyprof4 = new OnePartyTeam(party1withparams2, profile1);
 
 	}
 
 	@Override
-	public List<List<SaopPartyWithProfile>> getGeneralTestData() {
+	public List<List<OnePartyTeam>> getGeneralTestData() {
 		return Arrays.asList(Arrays.asList(partyprof1, partyprof1a),
 				Arrays.asList(partyprof2), Arrays.asList(partyprof3),
@@ -84,5 +84,5 @@
 	@Test(expected = IllegalArgumentException.class)
 	public void nullTest() throws URISyntaxException {
-		new SaopPartyWithProfile((PartyWithParameters) null, (ProfileRef) null);
+		new OnePartyTeam((PartyWithParameters) null, (ProfileRef) null);
 	}
 
@@ -103,5 +103,5 @@
 		// and therfore can not serialize as TeamOfPartiesAndProfiles
 		TeamOfPartiesAndProfiles p = jackson.readValue(serialized,
-				SaopPartyWithProfile.class);
+				OnePartyTeam.class);
 		System.out.println(p);
 		assertEquals(partyprof1, p);
Index: protocol/src/test/java/geniusweb/protocol/session/shaop/SHAOPStateTest.java
===================================================================
--- protocol/src/test/java/geniusweb/protocol/session/shaop/SHAOPStateTest.java	(revision 20)
+++ protocol/src/test/java/geniusweb/protocol/session/shaop/SHAOPStateTest.java	(revision 21)
@@ -4,5 +4,4 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.Mockito.mock;
@@ -194,5 +193,5 @@
 		SHAOPState state = new SHAOPState(actions, connections3, progressrounds,
 				settings, null, 0, null, null);
-		assertNull(state.getAgreement());
+		assertTrue(state.getAgreements().getMap().isEmpty());
 	}
 
@@ -201,6 +200,6 @@
 		List<Action> actions = Arrays.asList(offer1, accept2);
 		SHAOPState state = new SHAOPState(actions, connections4, progressrounds,
-				settings, null, 0, null, null);
-		assertNotNull(state.getAgreement());
+				settings, null, 0, partynrs, null);
+		assertFalse(state.getAgreements().getMap().isEmpty());
 		assertTrue(state.isFinal(NOW));
 	}
@@ -211,5 +210,5 @@
 		SHAOPState state = new SHAOPState(actions, connections3, progressrounds,
 				settings, null, 0, null, null);
-		assertNull(state.getAgreement());
+		assert (state.getAgreements().getMap().isEmpty());
 	}
 
@@ -219,5 +218,5 @@
 		SHAOPState state = new SHAOPState(actions, connections3, progressrounds,
 				settings, null, 0, null, null);
-		assertEquals(null, state.getAgreement());
+		assertTrue(state.getAgreements().getMap().isEmpty());
 	}
 
@@ -245,5 +244,5 @@
 		SHAOPState state = new SHAOPState(actions, connections3, progressrounds,
 				settings, null, 0, null, null);
-		assertEquals(null, state.getAgreement());
+		assertTrue(state.getAgreements().getMap().isEmpty());
 		assertEquals(null, state.getError());
 		assertTrue(state.isFinal(NOW));
@@ -254,6 +253,7 @@
 	public void isProtocolErrorFinal() {
 		SHAOPState state = new SHAOPState(actions, connections3, progressrounds,
-				settings, new ProtocolException("test error", "test"), 0, null,
-				null);
+				settings,
+				new ProtocolException("test error", new PartyId("test")), 0,
+				null, null);
 		assertTrue(state.isFinal(NOW));
 		assertNotNull(state.getError());
Index: protocol/src/test/java/geniusweb/protocol/tournament/allpermutations/AllPermutationsProtocolTest.java
===================================================================
--- protocol/src/test/java/geniusweb/protocol/tournament/allpermutations/AllPermutationsProtocolTest.java	(revision 20)
+++ protocol/src/test/java/geniusweb/protocol/tournament/allpermutations/AllPermutationsProtocolTest.java	(revision 21)
@@ -20,5 +20,5 @@
 
 import geniusweb.events.ProtocolEvent;
-import geniusweb.issuevalue.Bid;
+import geniusweb.inform.Agreements;
 import geniusweb.protocol.CurrentNegoState;
 import geniusweb.protocol.NegoState;
@@ -44,5 +44,5 @@
 	private final SessionSettings settings = mock(SessionSettings.class);
 	private final SessionState finalsessionstate = mock(SessionState.class);
-	private Bid agreement = mock(Bid.class);
+	private Agreements agreement = mock(Agreements.class);
 	private final long NOW = 1000;
 	private SessionResult finalstate = mock(SessionResult.class);
@@ -53,7 +53,7 @@
 		when(finalsessionstate.isFinal(anyLong())).thenReturn(true);
 		when(finalsessionstate.getSettings()).thenReturn(settings);
-		when(finalsessionstate.getAgreement()).thenReturn(agreement);
+		when(finalsessionstate.getAgreements()).thenReturn(agreement);
 		when(finalsessionstate.getResult()).thenReturn(finalstate);
-		when(finalstate.getAgreement()).thenReturn(agreement);
+		when(finalstate.getAgreements()).thenReturn(agreement);
 		when(state.with(any())).thenReturn(newstate);
 	}
@@ -112,5 +112,5 @@
 				.forClass(SessionResult.class);
 		verify(state, times(1)).with(argument.capture());
-		assertEquals(agreement, argument.getValue().getAgreement());
+		assertEquals(agreement, argument.getValue().getAgreements());
 		assertNull(argument.getValue().getError());
 	}
Index: protocol/src/test/java/geniusweb/protocol/tournament/allpermutations/AllPermutationsStateTest.java
===================================================================
--- protocol/src/test/java/geniusweb/protocol/tournament/allpermutations/AllPermutationsStateTest.java	(revision 20)
+++ protocol/src/test/java/geniusweb/protocol/tournament/allpermutations/AllPermutationsStateTest.java	(revision 21)
@@ -88,5 +88,4 @@
 		AllPermutationsState state1 = state.with(result);
 
-		assertEquals(null, state1.getError());
 		assertEquals(8, state1.getResults().size());
 		assertEquals(toursettings, state1.getSettings());
