first testing of regattalog replication

This commit is contained in:
Fredrik Teschke committed 2014-12-05 20:18:37 +01:00
1 parent d6fbb077c9
commit 0a8af6fbb7
3 files changed
+229 -101

No files matched your search

@@ -0,0 +1,120 @@
package com.sap.sailing.server.replication.test;
import static org.junit.Assert.assertEquals;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.UUID;
import com.sap.sailing.domain.abstractlog.AbstractLog;
import com.sap.sailing.domain.abstractlog.AbstractLogEvent;
import com.sap.sailing.domain.abstractlog.race.RaceLog;
import com.sap.sailing.domain.abstractlog.race.RaceLogEvent;
import com.sap.sailing.domain.abstractlog.race.RaceLogRaceStatusEvent;
import com.sap.sailing.domain.base.Regatta;
import com.sap.sailing.domain.base.Series;
import com.sap.sailing.domain.common.Color;
import com.sap.sailing.domain.common.RegattaName;
import com.sap.sailing.domain.common.dto.FleetDTO;
import com.sap.sailing.domain.common.dto.RegattaCreationParametersDTO;
import com.sap.sailing.domain.common.dto.SeriesCreationParametersDTO;
import com.sap.sailing.domain.leaderboard.FlexibleLeaderboard;
import com.sap.sailing.domain.leaderboard.impl.LowPoint;
import com.sap.sailing.domain.persistence.MongoObjectFactory;
import com.sap.sailing.domain.persistence.PersistenceFactory;
import com.sap.sailing.domain.racelog.RaceLogIdentifier;
import com.sap.sailing.server.impl.RacingEventServiceImpl;
import com.sap.sailing.server.operationaltransformation.AddSpecificRegatta;
import com.sap.sailing.server.operationaltransformation.CreateFlexibleLeaderboard;
import com.sap.sse.common.Util;
public abstract class AbstractLogReplicationTest<LogT extends AbstractLog<EventT, VisitorT>, EventT extends AbstractLogEvent<VisitorT>, VisitorT>
extends AbstractServerReplicationTest {
protected static final String BOAT_CLASS_NAME_49er = "49er";
/**
* Uses a new master that loads the existing regatta and race log to append an event to the race log. This will store it to the DB so that if the original
* master re-loads the race log it should see the new race log event.
*/
protected void addEventToDB(RaceLogIdentifier raceLogIdentifier, RaceLogRaceStatusEvent createRaceStatusEvent, String regattaName, String raceColumnName, String fleetName) {
final MongoObjectFactory defaultMongoObjectFactory = PersistenceFactory.INSTANCE.getDefaultMongoObjectFactory();
defaultMongoObjectFactory.getDatabase().getLastError(); // wait for regatta write operation to complete
final RacingEventServiceImpl temporaryMaster = createNewMaster();
Regatta regatta = temporaryMaster.getRegatta(new RegattaName(regattaName+" ("+BOAT_CLASS_NAME_49er+")"));
Series series = regatta.getSeries().iterator().next();
RaceLog masterLog = series.getRaceColumnByName(raceColumnName).getRaceLog(series.getFleetByName(fleetName));
masterLog.add(createRaceStatusEvent);
defaultMongoObjectFactory.getDatabase().getLastError(); // wait for write operation to complete
}
/**
* Validation is done based only on the identifier and type of the {@link RaceLogEvent}s.
*/
protected void addAndValidateEventIds(LogT masterLog, LogT replicaLog, @SuppressWarnings("unchecked") EventT... addedEvents) throws InterruptedException {
// 1. Check state of replica after initial load...
assertEqualsOnId(masterLog, replicaLog);
// 2. ... add all incoming events...
for (EventT event : addedEvents) {
masterLog.add(event);
}
// 3. ... and give replication some time to deliver messages.
Thread.sleep(3000);
assertEqualsOnId(masterLog, replicaLog);
}
/**
* Equality of the events is done based only on the identifier and type.
*/
protected void assertEqualsOnId(LogT masterLog, LogT replicaLog) {
replicaLog.lockForRead();
try {
masterLog.lockForRead();
try {
assertEqualsOnId(masterLog.getRawFixes(), replicaLog.getRawFixes());
} finally {
masterLog.unlockAfterRead();
}
} finally {
replicaLog.unlockAfterRead();
}
}
/**
* Equality of the events is done based only on the {@link RaceLogEvent}'s identifier and type.
*/
private void assertEqualsOnId(Iterable<EventT> expectedEvents, Iterable<EventT> actualEvents) {
List<EventT> expectedCollection = new ArrayList<>();
Util.addAll(expectedEvents, expectedCollection);
List<EventT> actualCollection = new ArrayList<>();
Util.addAll(actualEvents, actualCollection);
assertEquals(Util.size(expectedEvents), Util.size(actualEvents));
for (int i = 0; i < expectedCollection.size(); i++) {
assertEquals(expectedCollection.get(i).getClass(), actualCollection.get(i).getClass());
assertEquals(expectedCollection.get(i).getId(), actualCollection.get(i).getId());
}
}
protected Regatta setupRegatta(final String regattaName, String seriesName, String fleetName, String boatClassName) {
LinkedHashMap<String, SeriesCreationParametersDTO> seriesCreationParameters = new LinkedHashMap<>();
SeriesCreationParametersDTO creationParametersForDefaultSeries = new SeriesCreationParametersDTO(
Arrays.asList(new FleetDTO[] { new FleetDTO(fleetName, 0, Color.BLACK), }), /* medal */false, /* startsWithZero */
false, /* firstColumnIsNonDiscardableCarryForward */false, /* discardingThresholds */new int[0], /* hasSplitFleetContiguousScoring */
false);
seriesCreationParameters.put(seriesName, creationParametersForDefaultSeries);
// 1. Install some race column on master...
RegattaCreationParametersDTO regattaCreationParams = new RegattaCreationParametersDTO(seriesCreationParameters);
AddSpecificRegatta addRegattaOperation = new AddSpecificRegatta(regattaName, boatClassName,
/*startDate*/ null, /*endDate*/ null, /* regatta ID */ UUID.randomUUID(), regattaCreationParams, /* persistent */ true,
new LowPoint(), /* default course area ID */ UUID.randomUUID(), /* useStartTimeInference */ true);
return master.apply(addRegattaOperation);
}
protected FlexibleLeaderboard setupFlexibleLeaderboard(final String leaderboardName) {
CreateFlexibleLeaderboard createTestLeaderboard = new CreateFlexibleLeaderboard(leaderboardName, leaderboardName, new int[] { 19, 44 }, new LowPoint(), null);
FlexibleLeaderboard masterLeaderboard = master.apply(createTestLeaderboard);
return masterLeaderboard;
}
}
@@ -4,10 +4,6 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.UUID;
import junit.framework.Assert;
@@ -22,6 +18,7 @@ import com.sap.sailing.domain.abstractlog.race.RaceLog;
import com.sap.sailing.domain.abstractlog.race.RaceLogCourseDesignChangedEvent;
import com.sap.sailing.domain.abstractlog.race.RaceLogEvent;
import com.sap.sailing.domain.abstractlog.race.RaceLogEventFactory;
import com.sap.sailing.domain.abstractlog.race.RaceLogEventVisitor;
import com.sap.sailing.domain.abstractlog.race.RaceLogRaceStatusEvent;
import com.sap.sailing.domain.base.ControlPointWithTwoMarks;
import com.sap.sailing.domain.base.CourseBase;
@@ -35,27 +32,15 @@ import com.sap.sailing.domain.base.impl.CourseDataImpl;
import com.sap.sailing.domain.base.impl.MarkImpl;
import com.sap.sailing.domain.base.impl.RegattaImpl;
import com.sap.sailing.domain.base.impl.WaypointImpl;
import com.sap.sailing.domain.common.Color;
import com.sap.sailing.domain.common.MarkType;
import com.sap.sailing.domain.common.PassingInstruction;
import com.sap.sailing.domain.common.RegattaName;
import com.sap.sailing.domain.common.dto.FleetDTO;
import com.sap.sailing.domain.common.dto.RegattaCreationParametersDTO;
import com.sap.sailing.domain.common.dto.SeriesCreationParametersDTO;
import com.sap.sailing.domain.common.racelog.RaceLogRaceStatus;
import com.sap.sailing.domain.leaderboard.FlexibleLeaderboard;
import com.sap.sailing.domain.leaderboard.Leaderboard;
import com.sap.sailing.domain.leaderboard.RegattaLeaderboard;
import com.sap.sailing.domain.leaderboard.impl.LowPoint;
import com.sap.sailing.domain.persistence.MongoObjectFactory;
import com.sap.sailing.domain.persistence.PersistenceFactory;
import com.sap.sailing.domain.racelog.RaceLogIdentifier;
import com.sap.sailing.server.RacingEventService;
import com.sap.sailing.server.impl.RacingEventServiceImpl;
import com.sap.sailing.server.operationaltransformation.AddColumnToLeaderboard;
import com.sap.sailing.server.operationaltransformation.AddColumnToSeries;
import com.sap.sailing.server.operationaltransformation.AddSpecificRegatta;
import com.sap.sailing.server.operationaltransformation.CreateFlexibleLeaderboard;
import com.sap.sailing.server.operationaltransformation.CreateRegattaLeaderboard;
import com.sap.sailing.server.operationaltransformation.RenameLeaderboard;
import com.sap.sse.common.Util;
@@ -63,8 +48,7 @@ import com.sap.sse.common.Util.Pair;
import com.sap.sse.common.impl.MillisecondsTimePoint;
import com.sap.sse.replication.ReplicationMasterDescriptor;
public class RaceLogReplicationTest extends AbstractServerReplicationTest {
private static final String BOAT_CLASS_NAME_49er = "49er";
public class RaceLogReplicationTest extends AbstractLogReplicationTest<RaceLog, RaceLogEvent, RaceLogEventVisitor> {
private Pair<com.sap.sse.replication.testsupport.AbstractServerReplicationTest.ReplicationServiceTestImpl<RacingEventService>, ReplicationMasterDescriptor> replicationDescriptorPair;
@@ -259,68 +243,6 @@ public class RaceLogReplicationTest extends AbstractServerReplicationTest {
assertNotNull(lastEventReadFromMasterLog);
assertEqualsOnId(reloadedMasterLog, getReplicaLog(seriesName, fleetName, raceColumnName, masterRegatta));
}
/**
* Uses a new master that loads the existing regatta and race log to append an event to the race log. This will store it to the DB so that if the original
* master re-loads the race log it should see the new race log event.
*/
private void addEventToDB(RaceLogIdentifier raceLogIdentifier, RaceLogRaceStatusEvent createRaceStatusEvent, String regattaName, String raceColumnName, String fleetName) {
final MongoObjectFactory defaultMongoObjectFactory = PersistenceFactory.INSTANCE.getDefaultMongoObjectFactory();
defaultMongoObjectFactory.getDatabase().getLastError(); // wait for regatta write operation to complete
final RacingEventServiceImpl temporaryMaster = createNewMaster();
Regatta regatta = temporaryMaster.getRegatta(new RegattaName(regattaName+" ("+BOAT_CLASS_NAME_49er+")"));
Series series = regatta.getSeries().iterator().next();
RaceLog masterLog = series.getRaceColumnByName(raceColumnName).getRaceLog(series.getFleetByName(fleetName));
masterLog.add(createRaceStatusEvent);
defaultMongoObjectFactory.getDatabase().getLastError(); // wait for write operation to complete
}
/**
* Validation is done based only on the identifier and type of the {@link RaceLogEvent}s.
*/
private void addAndValidateEventIds(RaceLog masterLog, RaceLog replicaLog, RaceLogEvent... addedEvents) throws InterruptedException {
// 1. Check state of replica after initial load...
assertEqualsOnId(masterLog, replicaLog);
// 2. ... add all incoming events...
for (RaceLogEvent event : addedEvents) {
masterLog.add(event);
}
// 3. ... and give replication some time to deliver messages.
Thread.sleep(3000);
assertEqualsOnId(masterLog, replicaLog);
}
/**
* Equality of the events is done based only on the identifier and type.
*/
private void assertEqualsOnId(RaceLog masterLog, RaceLog replicaLog) {
replicaLog.lockForRead();
try {
masterLog.lockForRead();
try {
assertEqualsOnId(masterLog.getRawFixes(), replicaLog.getRawFixes());
} finally {
masterLog.unlockAfterRead();
}
} finally {
replicaLog.unlockAfterRead();
}
}
/**
* Equality of the events is done based only on the {@link RaceLogEvent}'s identifier and type.
*/
private void assertEqualsOnId(Iterable<RaceLogEvent> expectedEvents, Iterable<RaceLogEvent> actualEvents) {
List<RaceLogEvent> expectedCollection = new ArrayList<>();
Util.addAll(expectedEvents, expectedCollection);
List<RaceLogEvent> actualCollection = new ArrayList<>();
Util.addAll(actualEvents, actualCollection);
assertEquals(Util.size(expectedEvents), Util.size(actualEvents));
for (int i = 0; i < expectedCollection.size(); i++) {
assertEquals(expectedCollection.get(i).getClass(), actualCollection.get(i).getClass());
assertEquals(expectedCollection.get(i).getId(), actualCollection.get(i).getId());
}
}
private RaceLog getReplicaLog(final String fleetName, final String raceColumnName, Leaderboard leaderboard) {
Leaderboard replicaLeaderboard = replica.getLeaderboardByName(leaderboard.getName());
@@ -337,21 +259,6 @@ public class RaceLogReplicationTest extends AbstractServerReplicationTest {
return replicaColumn.getRaceLog(replicaFleet);
}
private Regatta setupRegatta(final String regattaName, String seriesName, String fleetName, String boatClassName) {
LinkedHashMap<String, SeriesCreationParametersDTO> seriesCreationParameters = new LinkedHashMap<>();
SeriesCreationParametersDTO creationParametersForDefaultSeries = new SeriesCreationParametersDTO(
Arrays.asList(new FleetDTO[] { new FleetDTO(fleetName, 0, Color.BLACK), }), /* medal */false, /* startsWithZero */
false, /* firstColumnIsNonDiscardableCarryForward */false, /* discardingThresholds */new int[0], /* hasSplitFleetContiguousScoring */
false);
seriesCreationParameters.put(seriesName, creationParametersForDefaultSeries);
// 1. Install some race column on master...
RegattaCreationParametersDTO regattaCreationParams = new RegattaCreationParametersDTO(seriesCreationParameters);
AddSpecificRegatta addRegattaOperation = new AddSpecificRegatta(regattaName, boatClassName,
/*startDate*/ null, /*endDate*/ null, /* regatta ID */ UUID.randomUUID(), regattaCreationParams, /* persistent */ true,
new LowPoint(), /* default course area ID */ UUID.randomUUID(), /* useStartTimeInference */ true);
return master.apply(addRegattaOperation);
}
private RaceLog setupRaceColumn(final Regatta regatta, final String seriesName,
final String raceColumnName, final String fleetName) {
AddColumnToSeries addColumnOperation = new AddColumnToSeries(regatta.getRegattaIdentifier(), seriesName, raceColumnName);
@@ -360,12 +267,6 @@ public class RaceLogReplicationTest extends AbstractServerReplicationTest {
return raceColumn.getRaceLog(masterFleet);
}
private FlexibleLeaderboard setupFlexibleLeaderboard(final String leaderboardName) {
CreateFlexibleLeaderboard createTestLeaderboard = new CreateFlexibleLeaderboard(leaderboardName, leaderboardName, new int[] { 19, 44 }, new LowPoint(), null);
FlexibleLeaderboard masterLeaderboard = master.apply(createTestLeaderboard);
return masterLeaderboard;
}
private RaceLog setupRaceColumn(final String leaderboardName, final String fleetName, final String raceColumnName) {
AddColumnToLeaderboard addColumnOperation = new AddColumnToLeaderboard(raceColumnName, leaderboardName, false);
RaceColumn masterRaceColumn = master.apply(addColumnOperation);
@@ -0,0 +1,107 @@
package com.sap.sailing.server.replication.test;
import java.io.IOException;
import org.junit.Before;
import org.junit.Test;
import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor;
import com.sap.sailing.domain.abstractlog.impl.LogEventAuthorImpl;
import com.sap.sailing.domain.abstractlog.regatta.RegattaLog;
import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEvent;
import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEventVisitor;
import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRegisterCompetitorEventImpl;
import com.sap.sailing.domain.base.Regatta;
import com.sap.sailing.domain.base.impl.RegattaImpl;
import com.sap.sailing.domain.leaderboard.FlexibleLeaderboard;
import com.sap.sailing.domain.leaderboard.Leaderboard;
import com.sap.sailing.server.RacingEventService;
import com.sap.sse.common.TimePoint;
import com.sap.sse.common.Util.Pair;
import com.sap.sse.common.impl.MillisecondsTimePoint;
import com.sap.sse.replication.ReplicationMasterDescriptor;
public class RegattaLogReplicationTest extends
AbstractLogReplicationTest<RegattaLog, RegattaLogEvent, RegattaLogEventVisitor> {
private Pair<com.sap.sse.replication.testsupport.AbstractServerReplicationTest.ReplicationServiceTestImpl<RacingEventService>, ReplicationMasterDescriptor> replicationDescriptorPair;
private RegattaLogEvent regattaLogEvent;
// private RegattaLogEvent anotherRegattaLogEvent;
private AbstractLogEventAuthor author = new LogEventAuthorImpl("Test Author", 1);
private TimePoint t(long millis) {
return new MillisecondsTimePoint(millis);
}
@Before
@Override
public void setUp() throws Exception {
regattaLogEvent = new RegattaLogRegisterCompetitorEventImpl(t(0), author, t(0), 0, null);
// anotherRegattaLogEvent = new RegattaLogRegisterCompetitorEventImpl(t(1), author, t(1), 1, null);
try {
replicationDescriptorPair = basicSetUp(/* dropDB */ true, null, null);
} catch (Exception e) {
e.printStackTrace();
tearDown();
}
}
@Test
public void testRegattaLogEmptyOnInitialLoad() throws ClassNotFoundException, IOException, InterruptedException {
final String regattaName = "Test";
final String seriesName = "Default";
final String fleetName = "Default";
Regatta regatta = setupRegatta(RegattaImpl.getDefaultName(regattaName, BOAT_CLASS_NAME_49er), seriesName, fleetName, BOAT_CLASS_NAME_49er);
RegattaLog masterLog = regatta.getRegattaLog();
replicationDescriptorPair.getA().startToReplicateFrom(replicationDescriptorPair.getB());
RegattaLog replicaLog = getReplicaLog(regatta);
addAndValidateEventIds(masterLog, replicaLog);
}
@Test
public void testRegattaLogStateOnInitialLoad() throws InterruptedException, ClassNotFoundException, IOException {
final String regattaName = "Test";
final String seriesName = "Default";
final String fleetName = "Default";
Regatta regatta = setupRegatta(RegattaImpl.getDefaultName(regattaName, BOAT_CLASS_NAME_49er), seriesName, fleetName, BOAT_CLASS_NAME_49er);
RegattaLog masterLog = regatta.getRegattaLog();
masterLog.add(regattaLogEvent);
replicationDescriptorPair.getA().startToReplicateFrom(replicationDescriptorPair.getB());
RegattaLog replicaLog = getReplicaLog(regatta);
addAndValidateEventIds(masterLog, replicaLog);
}
@Test
public void testRaceEventReplicationOnEmptyRegatta() throws ClassNotFoundException, IOException, InterruptedException {
final String regattaName = "Test";
final String seriesName = "Default";
final String fleetName = "Default";
Regatta masterRegatta = setupRegatta(RegattaImpl.getDefaultName(regattaName, BOAT_CLASS_NAME_49er), seriesName, fleetName, BOAT_CLASS_NAME_49er);
RegattaLog masterLog = masterRegatta.getRegattaLog();
masterLog.add(regattaLogEvent);
replicationDescriptorPair.getA().startToReplicateFrom(replicationDescriptorPair.getB());
RegattaLog replicaLog = getReplicaLog(masterRegatta);
addAndValidateEventIds(masterLog, replicaLog, regattaLogEvent);
}
@Test
public void testRaceEventReplicationOnEmptyFlexibleLeaderboard() throws ClassNotFoundException, IOException, InterruptedException {
final String leaderboardName = "Test";
FlexibleLeaderboard masterLeaderboard = setupFlexibleLeaderboard(leaderboardName);
RegattaLog masterLog = masterLeaderboard.getRegattaLog();
masterLog.add(regattaLogEvent);
replicationDescriptorPair.getA().startToReplicateFrom(replicationDescriptorPair.getB());
RegattaLog replicaLog = getReplicaLog(masterLeaderboard);
addAndValidateEventIds(masterLog, replicaLog, regattaLogEvent);
}
private RegattaLog getReplicaLog(Leaderboard leaderboard) {
return ((FlexibleLeaderboard) replica.getLeaderboardByName(leaderboard.getName())).getRegattaLog();
}
private RegattaLog getReplicaLog(Regatta masterRegatta) {
return replica.getRegatta(masterRegatta.getRegattaIdentifier()).getRegattaLog();
}
}