diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/TrackedEvent.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/TrackedEvent.java index a44c2bfb1e4..aa7481d19fa 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/TrackedEvent.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/TrackedEvent.java @@ -23,9 +23,13 @@ public interface TrackedEvent { Iterable getTrackedRaces(BoatClass boatClass); /** - * Creates a {@link TrackedRace} based on the parameter specified and {@link #addTrackedRace(TrackedRace) adds} it to - * this tracked event. Afterwards, calling {@link #getTrackedRace(RaceDefinition) getTrackedRace(raceDefinition)} will - * return the result of this method call. + * Creates a {@link TrackedRace} based on the parameter specified and {@link #addTrackedRace(TrackedRace) adds} it + * to this tracked event. Afterwards, calling {@link #getTrackedRace(RaceDefinition) getTrackedRace(raceDefinition)} + * will return the result of this method call. + * + * @param raceDefinitionSetToUpdate + * if not null, after creating the {@link TrackedRace}, the raceDefinition is + * {@link DynamicRaceDefinitionSet#addRaceDefinition(RaceDefinition) added} to that object. */ TrackedRace createTrackedRace(RaceDefinition raceDefinition, WindStore windStore, long millisecondsOverWhichToAverageWind, long millisecondsOverWhichToAverageSpeed, diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedEventImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedEventImpl.java index 1817c4faaee..6a1e0f60267 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedEventImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedEventImpl.java @@ -141,7 +141,9 @@ public class TrackedEventImpl implements TrackedEvent { logger.log(Level.INFO, "Creating DynamicTrackedRaceImpl for RaceDefinition "+raceDefinition.getName()); DynamicTrackedRaceImpl result = new DynamicTrackedRaceImpl(this, raceDefinition, windStore, millisecondsOverWhichToAverageWind, millisecondsOverWhichToAverageSpeed); - raceDefinitionSetToUpdate.addRaceDefinition(raceDefinition); + if (raceDefinitionSetToUpdate != null) { + raceDefinitionSetToUpdate.addRaceDefinition(raceDefinition); + } return result; } diff --git a/java/com.sap.sailing.server.test/META-INF/MANIFEST.MF b/java/com.sap.sailing.server.test/META-INF/MANIFEST.MF index e0088719c55..9e96f75cc68 100755 --- a/java/com.sap.sailing.server.test/META-INF/MANIFEST.MF +++ b/java/com.sap.sailing.server.test/META-INF/MANIFEST.MF @@ -6,6 +6,10 @@ Bundle-Version: 1.0.0.qualifier Bundle-Vendor: SAP Bundle-RequiredExecutionEnvironment: JavaSE-1.6 Require-Bundle: com.sap.sailing.server, + com.sap.sailing.server.api, com.sap.sailing.domain, com.sap.sailing.domain.tractracadapter, + com.sap.sailing.domain.swisstimingadapter, + org.json.simple;bundle-version="1.1.0", org.junit4 +Import-Package: com.tractrac.clientmodule diff --git a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/RaceTrackerMock.java b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/RaceTrackerMock.java new file mode 100644 index 00000000000..109bf291965 --- /dev/null +++ b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/RaceTrackerMock.java @@ -0,0 +1,83 @@ +package com.sap.sailing.server.test; + +import java.io.IOException; +import java.net.MalformedURLException; +import java.util.Set; + +import com.sap.sailing.domain.base.Event; +import com.sap.sailing.domain.base.RaceDefinition; +import com.sap.sailing.domain.tracking.DynamicTrackedEvent; +import com.sap.sailing.domain.tracking.RaceTracker; +import com.sap.sailing.domain.tracking.RacesHandle; +import com.sap.sailing.domain.tracking.WindStore; + +public class RaceTrackerMock implements RaceTracker{ + + private Long id; + private Event event; + private Set raceDefinitions; + private boolean isTracking; + + public RaceTrackerMock() { + // TODO check if necesary + } + + + + public RaceTrackerMock(Long id, Event event, Set raceDefinitions, boolean isTracking) { + super(); + this.id = id; + this.event = event; + this.raceDefinitions = raceDefinitions; + this.isTracking = isTracking; + } + + public void setIsTracking(boolean isTracking){ + this.isTracking = isTracking; + } + + public boolean getIsTracking(){ + return isTracking; + } + + public RaceTrackerMock(Long id) { + this.id = id; + } + + @Override + public void stop() throws MalformedURLException, IOException, InterruptedException { + isTracking = false; + } + + @Override + public Event getEvent() { + return event; + } + + @Override + public Set getRaces() { + return raceDefinitions; + } + + @Override + public RacesHandle getRaceHandle() { + throw new RuntimeException("No race Handle in RaceTrackerMock"); + } + + @Override + public DynamicTrackedEvent getTrackedEvent() { + // TODO Auto-generated method stub + return null; + } + + @Override + public WindStore getWindStore() { + throw new RuntimeException("No wind store in racetracker mock"); + } + + @Override + public Object getID() { + return id; + } + +} diff --git a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/RaceTrackerStartStopTest.java b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/RaceTrackerStartStopTest.java new file mode 100644 index 00000000000..67b2a6ffb6c --- /dev/null +++ b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/RaceTrackerStartStopTest.java @@ -0,0 +1,199 @@ +package com.sap.sailing.server.test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; + +import java.io.IOException; +import java.net.MalformedURLException; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; + +import org.junit.Before; +import org.junit.Test; + +import com.sap.sailing.domain.base.BoatClass; +import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.Event; +import com.sap.sailing.domain.base.RaceDefinition; +import com.sap.sailing.domain.base.Waypoint; +import com.sap.sailing.domain.base.impl.BoatClassImpl; +import com.sap.sailing.domain.base.impl.CourseImpl; +import com.sap.sailing.domain.base.impl.EventImpl; +import com.sap.sailing.domain.base.impl.RaceDefinitionImpl; +import com.sap.sailing.domain.tracking.RaceTracker; +import com.sap.sailing.domain.tracking.TrackedEvent; +import com.sap.sailing.domain.tracking.TrackedRace; +import com.sap.sailing.domain.tracking.impl.EmptyWindStore; +import com.sap.sailing.server.RacingEventService; + +public class RaceTrackerStartStopTest { + + private static final String RACENAME3 = "racedef3"; + private static final String RACENAME2 = "racedef2"; + private static final String RACENAME1 = "racedef1"; + private final static String EVENTNAME = "TESTEVENT"; + private final static String BOATCLASSNAME = "HAPPYBOATCLASS"; + + private RacingEventServiceImplMock racingEventService; + private Event event; + private BoatClass boatClass; + private Set raceTrackerSet = new HashSet(); + + private RaceDefinition raceDef1; + private RaceDefinition raceDef2; + private RaceDefinition raceDef3; + + private RaceTrackerMock raceTracker1; + private RaceTrackerMock raceTracker2; + private RaceTrackerMock raceTracker3; + + @Before + public void setUp() { + racingEventService = new RacingEventServiceImplMock(); + boatClass = new BoatClassImpl(BOATCLASSNAME); + event = new EventImpl(EVENTNAME, boatClass); + racingEventService.getEventsByName().put(EVENTNAME, event); + TrackedEvent trackedEvent1 = racingEventService.getOrCreateTrackedEvent(event); + racingEventService.getEventsByNameMap().put(EVENTNAME, event); + raceTrackerSet = new HashSet(); + raceDef1 = new RaceDefinitionImpl(RACENAME1, new CourseImpl("Course1", new ArrayList()), boatClass, new ArrayList()); + raceDef2 = new RaceDefinitionImpl(RACENAME2, new CourseImpl("Course2", new ArrayList()), boatClass, new ArrayList()); + raceDef3 = new RaceDefinitionImpl(RACENAME3, new CourseImpl("Course3", new ArrayList()), boatClass, new ArrayList()); + event.addRace(raceDef1); + trackedEvent1.createTrackedRace(raceDef1, /* windStore */ EmptyWindStore.INSTANCE, /* millisecondsOverWhichToAverageWind */ 0l, + /* millisecondsOverWhichToAverageSpeed */ 0l, /* raceDefinitionSetToUpdate */ null); + event.addRace(raceDef2); + trackedEvent1.createTrackedRace(raceDef2, /* windStore */ EmptyWindStore.INSTANCE, /* millisecondsOverWhichToAverageWind */ 0l, + /* millisecondsOverWhichToAverageSpeed */ 0l, /* raceDefinitionSetToUpdate */ null); + event.addRace(raceDef3); + trackedEvent1.createTrackedRace(raceDef3, /* windStore */ EmptyWindStore.INSTANCE, /* millisecondsOverWhichToAverageWind */ 0l, + /* millisecondsOverWhichToAverageSpeed */ 0l, /* raceDefinitionSetToUpdate */ null); + Set raceDefinitionSetRace1 = new HashSet(); + raceDefinitionSetRace1.add(raceDef1); + Set raceDefinitionSetRace2 = new HashSet(); + raceDefinitionSetRace2.add(raceDef1); + raceDefinitionSetRace2.add(raceDef2); + Set raceDefinitionSetRace3 = new HashSet(); + raceDefinitionSetRace3.add(raceDef1); + raceDefinitionSetRace3.add(raceDef2); + raceDefinitionSetRace3.add(raceDef3); + Long trackerID1 = new Long(1); + Long trackerID2 = new Long(2); + Long trackerID3 = new Long(3); + raceTracker1 = new RaceTrackerMock(new Long(1), event, raceDefinitionSetRace1, true); + raceTracker2 = new RaceTrackerMock(new Long(2), event, raceDefinitionSetRace2, true); + raceTracker3 = new RaceTrackerMock(new Long(3), event, raceDefinitionSetRace3, true); + raceTrackerSet.add(raceTracker1); + raceTrackerSet.add(raceTracker2); + raceTrackerSet.add(raceTracker3); + racingEventService.getRaceTrackersByEventMap().put(event, raceTrackerSet); + racingEventService.getRaceTrackersByIDMap().put(trackerID1, raceTracker1); + racingEventService.getRaceTrackersByIDMap().put(trackerID2, raceTracker2); + racingEventService.getRaceTrackersByIDMap().put(trackerID3, raceTracker3); + } + + /** + * This test method tests, if the {@link RacingEventService#stopTracking(Event, RaceDefinition) stopTracking} method works correctly. + */ + @Test + public void testStopTrackingRace() throws MalformedURLException, IOException, InterruptedException { + Event event = racingEventService.getEventByName(EVENTNAME); + TrackedEvent trackedEvent = racingEventService.getTrackedEvent(event); + assertNotNull(event.getRaceByName(RACENAME2)); + assertNotNull(trackedEvent.getExistingTrackedRace(event.getRaceByName(RACENAME2))); + racingEventService.stopTracking(event, raceDef2); + // the raceDef2 should still be part of the event, and the corresponding tracked race should still be part + // of the tracked event + assertNotNull(event.getRaceByName(RACENAME2)); + boolean foundTrackedRaceForRaceDef2 = false; + for (TrackedRace trackedRace : trackedEvent.getTrackedRaces()) { + if (trackedRace.getRace().getName().equals(RACENAME2)) { + foundTrackedRaceForRaceDef2 = true; + } + } + assertTrue(foundTrackedRaceForRaceDef2); + // The raceTracker2 and raceTracker3 should currently not be in track mode. + assertTrue(raceTracker1.getIsTracking()); + assertFalse(raceTracker2.getIsTracking()); + assertFalse(raceTracker3.getIsTracking()); + // The RaceTrackersByID map should not contain the trackers raceTracker2 and raceTracker3 anymore + assertTrue(racingEventService.getRaceTrackersByIDMap().containsValue(raceTracker1)); + assertFalse(racingEventService.getRaceTrackersByIDMap().containsValue(raceTracker2)); + assertFalse(racingEventService.getRaceTrackersByIDMap().containsValue(raceTracker3)); + // The RaceTrakcersByEvent map should contain a tracker with a set of RaceDefinitions, containing the + // raceDefinition1 + assertEquals(1, racingEventService.getRaceTrackersByEventMap().size()); + Iterator raceTrackerIter = racingEventService.getRaceTrackersByEventMap().get(event).iterator(); + while (raceTrackerIter.hasNext()) { + RaceTracker currentTracker = raceTrackerIter.next(); + assertSame(raceTracker1, currentTracker); + } + } + /** + * This test methods checks if the {@link RacingEventService#removeRace(Event, RaceDefinition) removeRace} method works correctly + */ + @Test + public void testRemoveRace() throws MalformedURLException, IOException, InterruptedException { + Event event = racingEventService.getEventByName(EVENTNAME); + TrackedEvent trackedEvent = racingEventService.getTrackedEvent(event); + assertNotNull(event.getRaceByName(RACENAME2)); + assertNotNull(trackedEvent.getExistingTrackedRace(event.getRaceByName(RACENAME2))); + racingEventService.removeRace(event, raceDef2); + // the raceDef2 should be removed from the event, and the corresponding tracked race should be removed + // from the tracked event + assertNull(event.getRaceByName(RACENAME2)); + boolean foundTrackedRaceForRaceDef2 = false; + for (TrackedRace trackedRace : trackedEvent.getTrackedRaces()) { + if (trackedRace.getRace().getName().equals(RACENAME2)) { + foundTrackedRaceForRaceDef2 = true; + } + } + assertFalse(foundTrackedRaceForRaceDef2); + // The trackers map should still contain the raceTrackers + assertTrue(racingEventService.getRaceTrackersByEventMap().get(event).contains(raceTracker1)); + assertTrue(racingEventService.getRaceTrackersByEventMap().get(event).contains(raceTracker2)); + assertTrue(racingEventService.getRaceTrackersByEventMap().get(event).contains(raceTracker3)); + // The raceTrackerMap should still contain the raceTrackers. These raceTracker should not contain the raceDefinition raceDef2 anymore + assertTrue(racingEventService.getRaceTrackersByIDMap().containsValue(raceTracker1)); + assertTrue(racingEventService.getRaceTrackersByIDMap().containsValue(raceTracker2)); + assertTrue(racingEventService.getRaceTrackersByIDMap().containsValue(raceTracker3)); + // The raceTracker should still exist; it shall still contain raceDef1 and raceDef2 because a tracker keeps tracking what it tracks... + assertTrue(raceTracker1.getRaces().contains(raceDef1)); + assertEquals(1, raceTracker1.getRaces().size()); + assertTrue(raceTracker2.getRaces().contains(raceDef1)); + assertTrue(raceTracker2.getRaces().contains(raceDef2)); + assertEquals(2, raceTracker2.getRaces().size()); + assertTrue(raceTracker3.getRaces().contains(raceDef1)); + assertTrue(raceTracker3.getRaces().contains(raceDef2)); + assertTrue(raceTracker3.getRaces().contains(raceDef3)); + assertEquals(3, raceTracker3.getRaces().size()); + } + + /** + * This test methods checks if the {@link RacingEventService#removeRace(Event, RaceDefinition) removeRace} method works correctly if the + * race to be stopped is the last race of a tracker + */ + @Test + public void testRemoveLastRaceOfTracker() throws MalformedURLException, IOException, InterruptedException { + racingEventService.removeRace(event, raceDef1); + racingEventService.removeRace(event, raceDef2); + // The event map should still contain the raceTrackers except of raceTracker1 and raceTracker2 + assertFalse(racingEventService.getRaceTrackersByEventMap().get(event).contains(raceTracker1)); + assertFalse(racingEventService.getRaceTrackersByEventMap().get(event).contains(raceTracker2)); + assertTrue(racingEventService.getRaceTrackersByEventMap().get(event).contains(raceTracker3)); + // The RaceTrackerByID map should still contain raceTracker3, but not raceTracker1 and raceTracker2 anymore + assertFalse(racingEventService.getRaceTrackersByIDMap().containsValue(raceTracker1)); + assertFalse(racingEventService.getRaceTrackersByIDMap().containsValue(raceTracker2)); + assertTrue(racingEventService.getRaceTrackersByIDMap().containsValue(raceTracker3)); + // The raceTracker 3 should exist, and it should contain all race definitions still + assertTrue(raceTracker3.getRaces().contains(raceDef3)); + assertEquals(3, raceTracker3.getRaces().size()); + } + +} diff --git a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/RacingEventServiceImplMock.java b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/RacingEventServiceImplMock.java new file mode 100644 index 00000000000..36bd1ebebcf --- /dev/null +++ b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/RacingEventServiceImplMock.java @@ -0,0 +1,31 @@ +package com.sap.sailing.server.test; + +import java.util.Map; +import java.util.Set; + +import com.sap.sailing.domain.base.Event; +import com.sap.sailing.domain.tracking.RaceTracker; +import com.sap.sailing.server.impl.RacingEventServiceImpl; + +public class RacingEventServiceImplMock extends RacingEventServiceImpl { + + public RacingEventServiceImplMock() { + super(); + } + + public Map getEventsByNameMap() { + return eventsByName; + } + + public Map> getRaceTrackersByEventMap() { + return raceTrackersByEvent; + } + + public Map getRaceTrackersByIDMap() { + return raceTrackersByID; + } + + public Map getEventsByName() { + return eventsByName; + } +} diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/RacingEventServiceImpl.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/RacingEventServiceImpl.java index cb4b88c1ecc..d414a1e60d9 100755 --- a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/RacingEventServiceImpl.java +++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/RacingEventServiceImpl.java @@ -81,9 +81,9 @@ public class RacingEventServiceImpl implements RacingEventService, EventFetcher, private final WindTrackerFactory windTrackerFactory; - private final Map eventsByName; + protected final Map eventsByName; - private final Map> raceTrackersByEvent; + protected final Map> raceTrackersByEvent; /** * Remembers the wind tracker and the port on which the UDP receiver with which the wind tracker is @@ -94,7 +94,7 @@ public class RacingEventServiceImpl implements RacingEventService, EventFetcher, /** * Remembers the trackers by paramURL/liveURI/storedURI to avoid duplication */ - private final Map raceTrackersByID; + protected final Map raceTrackersByID; /** * Leaderboards managed by this racing event service