Merge branch 'master' into test

This commit is contained in:
Axel Uhl committed 2011-06-14 19:27:11 +02:00
commit abe8a71d15
17 files changed
+386 -38

No files matched your search

@@ -16,5 +16,5 @@
<stringAttribute key="org.eclipse.jdt.junit.TEST_KIND" value="org.eclipse.jdt.junit.loader.junit4"/>
<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value=""/>
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="com.sap.sailing.domain.test"/>
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Dhttp.proxyHost=proxy -Dhttp.proxyPort=8080 -XX:+UseParallelGC"/>
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Dhttp.proxyHost=proxy -Dhttp.proxyPort=8080 -XX:+UseParallelGC -Dtractrac.tunnel=true"/>
</launchConfiguration>
@@ -46,13 +46,15 @@ public abstract class AbstractTracTracLiveTest implements Listener {
// for stored race, non-real-time simulation:
paramUrl = new URL("http://germanmaster.traclive.dk/events/event_20110505_SailingTea/clientparams.php?event=event_20110505_SailingTea&race=bd8c778e-7c65-11e0-8236-406186cbf87c");
// tunneled:
//liveUri = new URI("tcp://localhost:4412");
//storedUri = new URI("tcp://localhost:4413");
//no tunnel:
liveUri = new URI("tcp://germanmaster.traclive.dk:4400");
storedUri = new URI("tcp://germanmaster.traclive.dk:4401");
if (Boolean.valueOf(System.getProperty("tractrac.tunnel", "false"))) {
// tunnel
liveUri = new URI("tcp://localhost:4412");
storedUri = new URI("tcp://localhost:4413");
} else {
//no tunnel:
liveUri = new URI("tcp://germanmaster.traclive.dk:4400");
storedUri = new URI("tcp://germanmaster.traclive.dk:4401");
}
receivers = new HashSet<Receiver>();
}
@@ -22,8 +22,14 @@ public interface Track<FixType extends Timed> {
FixType getFirstFixAfter(TimePoint timePoint);
/**
* The first fix in this track or <code>null</code> if the track is empty
*/
FixType getFirstFix();
/**
* The last fix in this track or <code>null</code> if the track is empty
*/
FixType getLastFix();
/**
@@ -80,7 +80,7 @@ public interface TrackedRace {
* @return a sequential number counting the updates that occurred to this tracked race. Callers may use this to ask
* for updates newer than such a sequence number.
*/
int getUpdateCount();
long getUpdateCount();
int getRankDifference(Competitor competitor, Leg leg, TimePoint timePoint);
@@ -74,13 +74,21 @@ public abstract class TrackImpl<FixType extends Timed> implements Track<FixType>
@SuppressWarnings("unchecked")
@Override
public FixType getFirstFix() {
return (FixType) fixes.first();
if (fixes.isEmpty()) {
return null;
} else {
return (FixType) fixes.first();
}
}
@SuppressWarnings("unchecked")
@Override
public FixType getLastFix() {
return (FixType) fixes.last();
if (fixes.isEmpty()) {
return null;
} else {
return (FixType) fixes.last();
}
}
@Override
@@ -47,7 +47,7 @@ public abstract class TrackedRaceImpl implements TrackedRace, CourseListener {
private TimePoint finish;
private TimePoint timePointOfNewestEvent;
private TimePoint timePointOfLastEvent;
private int updateCount;
private long updateCount;
private final Map<TimePoint, TreeSet<Competitor>> competitorRankings;
@@ -216,7 +216,7 @@ public abstract class TrackedRaceImpl implements TrackedRace, CourseListener {
}
@Override
public int getUpdateCount() {
public long getUpdateCount() {
return updateCount;
}
@@ -242,18 +242,18 @@ public abstract class TrackedRaceImpl implements TrackedRace, CourseListener {
@Override
public int getRank(Competitor competitor, TimePoint timePoint) throws NoWindException {
try {
synchronized (competitorRankings) {
TreeSet<Competitor> rankedCompetitors = competitorRankings.get(timePoint);
if (rankedCompetitors == null) {
RaceRankComparator comparator = new RaceRankComparator(this, timePoint);
rankedCompetitors = new TreeSet<Competitor>(comparator);
for (Competitor c : getRace().getCompetitors()) {
rankedCompetitors.add(c);
synchronized (competitorRankings) {
TreeSet<Competitor> rankedCompetitors = competitorRankings.get(timePoint);
if (rankedCompetitors == null) {
RaceRankComparator comparator = new RaceRankComparator(this, timePoint);
rankedCompetitors = new TreeSet<Competitor>(comparator);
for (Competitor c : getRace().getCompetitors()) {
rankedCompetitors.add(c);
}
competitorRankings.put(timePoint, rankedCompetitors);
}
competitorRankings.put(timePoint, rankedCompetitors);
return rankedCompetitors.headSet(competitor, /* inclusive */true).size();
}
return rankedCompetitors.headSet(competitor, /* inclusive */ true).size();
}
} catch (NoWindError e) {
throw e.getCause();
}
@@ -37,7 +37,7 @@ public class WindTrackImpl extends TrackImpl<Wind> implements WindTrack {
}
@Override
public synchronized void add(Wind wind) {
public void add(Wind wind) {
getInternalFixes().add(wind);
notifyListenersAboutReceive(wind);
}
@@ -99,7 +99,7 @@ public class MockedTrackedRace implements DynamicTrackedRace {
}
@Override
public int getUpdateCount() {
public long getUpdateCount() {
// TODO Auto-generated method stub
return 0;
}
@@ -1,6 +1,7 @@
package com.sap.sailing.expeditionconnector.test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
@@ -164,6 +165,37 @@ public class UDPExpeditionReceiverTest {
assertTrue(cal.get(Calendar.SECOND) == 46 || cal.get(Calendar.SECOND) == 45);
}
/**
* If no timestamp is received in a message, by default the time the message was received is used to fill it in.
*/
@Test
public void testTimeStampCompletionFromCurrentTime() throws IOException, InterruptedException {
receiver.addListener(listener, /* validMessagesOnly */ true);
sendAndWaitABit(new String[] { "#0,9,318.0*0E" });
assertEquals(1, messages.size());
assertFalse(messages.get(0).hasValue(ExpeditionMessage.ID_GPS_TIME));
assertEquals(messages.get(0).getCreatedAt(), messages.get(0).getTimePoint());
}
/**
* If no timestamp is received in a message, by default the time the message was received is used to fill it in.
*/
@Test
public void testTimeStampCompletionFromLastTimePointReceived() throws IOException, InterruptedException {
receiver.addListener(listener, /* validMessagesOnly */ true);
sendAndWaitABit(validLines);
assertEquals(validLines.length, messages.size());
assertTrue(messages.get(0).hasValue(ExpeditionMessage.ID_GPS_TIME));
assertTrue(messages.get(10).hasValue(ExpeditionMessage.ID_GPS_TIME));
TimePoint m0Time = messages.get(0).getTimePoint();
TimePoint m10Time = messages.get(10).getTimePoint();
for (int i=1; i<=9; i++) {
TimePoint m_iTime = messages.get(i).getTimePoint();
assertTrue(m_iTime.compareTo(m0Time) >= 0);
assertTrue(m_iTime.compareTo(m10Time) <= 0);
}
}
@Test
public void sendAndValidateSomeInvalidDatagrams() throws IOException, InterruptedException {
receiver.addListener(listener, /* validMessagesOnly */ true);
@@ -102,4 +102,6 @@ public interface ExpeditionMessage {
Bearing getCourseOverGround();
TimePoint getTimePoint();
TimePoint getCreatedAt();
}
@@ -10,6 +10,8 @@ import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.sap.sailing.domain.base.TimePoint;
import com.sap.sailing.domain.base.impl.MillisecondsTimePoint;
import com.sap.sailing.expeditionconnector.impl.ExpeditionMessageImpl;
/**
@@ -35,6 +37,12 @@ public class UDPExpeditionReceiver implements Runnable {
* Maximum IP packet length
*/
private static final int MAX_PACKET_SIZE = 65536;
/**
* Remembers, per boat ID, the milliseconds difference between the time the message was received
* and the GPS time stamp provided by the message.
*/
private final Map<Integer, Long> timeStampOfLastMessageReceived;
/**
* Launches a listener and dumps messages received to the console
@@ -61,6 +69,7 @@ public class UDPExpeditionReceiver implements Runnable {
udpSocket = new DatagramSocket(listeningOnPort);
listeners = new HashMap<ExpeditionListener, Boolean>();
this.listeningOnPort = listeningOnPort;
this.timeStampOfLastMessageReceived = new HashMap<Integer, Long>();
}
public void stop() throws SocketException, IOException {
@@ -110,6 +119,16 @@ public class UDPExpeditionReceiver implements Runnable {
String variableValuePairs = m.group(2).trim().substring(",".length()); // skip the leading ","
Map<Integer, Double> values = new HashMap<Integer, Double>();
String[] variablesAndValuesInterleaved = variableValuePairs.split(",");
long now = System.currentTimeMillis();
Long diff = timeStampOfLastMessageReceived.get(boatID);
TimePoint defaultForMessageTimePoint;
if (diff != null) {
// compute a reasonable default for a time stamp in case message doesn't provide one
// by subtracting the last diff from now
defaultForMessageTimePoint = new MillisecondsTimePoint(now - diff);
} else {
defaultForMessageTimePoint = MillisecondsTimePoint.now();
}
for (int i = 0; i < variablesAndValuesInterleaved.length; i++) {
int variableID = Integer.valueOf(variablesAndValuesInterleaved[i++]);
double variableValue = Double.valueOf(variablesAndValuesInterleaved[i]);
@@ -117,7 +136,12 @@ public class UDPExpeditionReceiver implements Runnable {
}
int checksum = Integer.valueOf(m.group(m.groupCount()), 16);
valid = valid && checksumOk(checksum, packetAsString);
return new ExpeditionMessageImpl(boatID, values, valid);
ExpeditionMessageImpl result = new ExpeditionMessageImpl(boatID, values, valid, defaultForMessageTimePoint);
if (result.hasValue(ExpeditionMessage.ID_GPS_TIME)) {
// an original GPS time stamp; then remember the difference between now and the time stamp
timeStampOfLastMessageReceived.put(boatID, now-result.getTimePoint().asMillis());
}
return result;
} else {
System.err.println("Unparsable expedition message: " + packetAsString);
return null; // couldn't even parse
@@ -28,6 +28,18 @@ public class ExpeditionMessageImpl implements ExpeditionMessage {
private final long createdAtMillis;
private final TimePoint timePoint;
private static final TimeZone UTC = TimeZone.getTimeZone("UTC") == null ? TimeZone.getTimeZone("GMT") : TimeZone.getTimeZone("UTC");
private static final GregorianCalendar cal = new GregorianCalendar(UTC);
static {
cal.set(1899, 11, 30, 0, 0, 0);
}
/**
* Creates a message instance based on <code>values</code>. If there is no timestamp delivered by
* <code>values</code>, the {@link System#currentTimeMillis() current time} is used as the message's
* {@link #getTimePoint() time point}.
*/
public ExpeditionMessageImpl(int boatID, Map<Integer, Double> values, boolean valid) {
this.boatID = boatID;
// ensure that nobody can manipulate the map used by this message object from outside
@@ -35,12 +47,6 @@ public class ExpeditionMessageImpl implements ExpeditionMessage {
this.valid = valid;
this.createdAtMillis = System.currentTimeMillis();
if (hasValue(ID_GPS_TIME)) {
TimeZone UTC = TimeZone.getTimeZone("UTC");
if (UTC == null) {
UTC = TimeZone.getTimeZone("GMT");
}
GregorianCalendar cal = new GregorianCalendar(UTC);
cal.set(1899, 11, 30, 0, 0, 0);
timePoint = new MillisecondsTimePoint((long)
(getValue(ID_GPS_TIME)*24*3600*1000) + // this is the milliseconds since 31.12.1899 0:00:00 UTC
cal.getTimeInMillis());
@@ -49,6 +55,29 @@ public class ExpeditionMessageImpl implements ExpeditionMessage {
}
}
/**
* @param defaultTimePoint
* a non-<code>null</code> default time point to use in case the message received does not carry a time
* stamp
*/
public ExpeditionMessageImpl(int boatID, Map<Integer, Double> values, boolean valid, TimePoint defaultTimePoint) {
if (defaultTimePoint == null) {
throw new IllegalArgumentException("defaultTimePoint for ExpeditionMessageImpl constructor must not be null");
}
this.boatID = boatID;
// ensure that nobody can manipulate the map used by this message object from outside
this.values = new HashMap<Integer, Double>(values);
this.valid = valid;
this.createdAtMillis = System.currentTimeMillis();
if (hasValue(ID_GPS_TIME)) {
timePoint = new MillisecondsTimePoint((long)
(getValue(ID_GPS_TIME)*24*3600*1000) + // this is the milliseconds since 31.12.1899 0:00:00 UTC
cal.getTimeInMillis());
} else {
timePoint = defaultTimePoint;
}
}
@Override
public boolean isValid() {
return valid;
@@ -91,6 +120,11 @@ public class ExpeditionMessageImpl implements ExpeditionMessage {
return timePoint;
}
@Override
public TimePoint getCreatedAt() {
return new MillisecondsTimePoint(createdAtMillis);
}
@Override
public GPSFixMoving getGPSFixMoving() {
if (hasValue(ID_GPS_LAT) && hasValue(ID_GPS_LNG)) {
@@ -11,7 +11,6 @@
<booleanAttribute key="default" value="true"/>
<booleanAttribute key="default_auto_start" value="true"/>
<intAttribute key="default_start_level" value="4"/>
<stringAttribute key="deselected_workspace_plugins" value="ucar.grib.osgi"/>
<booleanAttribute key="includeOptional" value="true"/>
<listAttribute key="org.eclipse.debug.ui.favoriteGroups">
<listEntry value="org.eclipse.debug.ui.launchGroup.debug"/>
@@ -23,9 +22,9 @@
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Xdebug -Xrunjdwp:transport=dt_socket,address=8000,server=y -Declipse.ignoreApp=true -Dosgi.noShutdown=true -Dorg.osgi.service.http.port=8888"/>
<stringAttribute key="pde.version" value="3.3"/>
<booleanAttribute key="show_selected_only" value="false"/>
<stringAttribute key="target_bundles" value="org.eclipse.equinox.http.servlet@default:default,org.eclipse.osgi@-1:true,org.apache.ant@default:default,org.hamcrest.core@default:default,org.eclipse.net4j.jms.api@default:default,javax.activation@default:default,org.junit*4.8.1.v4_8_1_v20100427-1100@default:default,org.eclipse.equinox.http.jetty@default:default,javax.transaction@default:false,org.eclipse.equinox.weaving.hook@default:false,org.eclipse.core.runtime.compatibility.registry@default:false,org.eclipse.core.jobs@default:default,org.apache.jasper@default:default,org.mortbay.jetty.util@default:default,org.junit4@default:default,ch.qos.logback.classic@default:default,org.eclipse.osgi.services@default:default,ch.qos.logback.core@default:default,org.eclipse.equinox.util@default:default,org.apache.commons.el@default:default,org.mortbay.jetty.server@default:default,org.eclipse.osgi.util@default:default,javax.servlet.jsp@default:default,org.eclipse.equinox.common@2:true,org.slf4j.api@default:default,ch.qos.logback.slf4j@default:false,org.junit*3.8.2.v3_8_2_v20100427-1100@default:default,javax.servlet@default:default,org.eclipse.equinox.registry@default:default,org.apache.commons.logging@default:default,org.eclipse.equinox.http.registry@default:default"/>
<stringAttribute key="target_bundles" value="javax.servlet.jsp@default:default,javax.servlet@default:default,org.apache.ant@default:default,org.apache.commons.el@default:default,org.apache.commons.logging@default:default,org.apache.jasper@default:default,org.eclipse.core.jobs@default:default,org.eclipse.core.runtime.compatibility.registry@default:false,org.eclipse.equinox.common@2:true,org.eclipse.equinox.http.jetty@default:default,org.eclipse.equinox.http.registry@default:default,org.eclipse.equinox.http.servlet@default:default,org.eclipse.equinox.registry@default:default,org.eclipse.equinox.util@default:default,org.eclipse.osgi.services@default:default,org.eclipse.osgi.util@default:default,org.eclipse.osgi@-1:true,org.hamcrest.core@default:default,org.junit*3.8.2.v3_8_2_v20100427-1100@default:default,org.junit4@default:default,org.mortbay.jetty.server@default:default,org.mortbay.jetty.util@default:default"/>
<booleanAttribute key="tracing" value="false"/>
<booleanAttribute key="useCustomFeatures" value="false"/>
<booleanAttribute key="useDefaultConfigArea" value="true"/>
<stringAttribute key="workspace_bundles" value="com.sap.sailing.declination@default:default,com.sap.sailing.declination.test@default:default,com.sap.sailing.expeditionconnector.test@default:default,com.sap.sailing.domain.tractracadapter@default:default,com.tractrac.resultapi@default:default,com.sap.sailing.server@default:default,com.tractrac.clientmodule@default:default,com.sap.sailing.domain.test@default:default,com.sap.sailing.domain@default:default,com.sap.sailing.expeditionconnector@default:default,org.json.simple@default:default"/>
<stringAttribute key="workspace_bundles" value="com.googlecode.java-diff-utils.test@default:default,com.googlecode.java-diff-utils@default:default,com.mongodb.driver@default:default,com.sap.sailing.declination.test@default:default,com.sap.sailing.declination@default:default,com.sap.sailing.domain.test@default:default,com.sap.sailing.domain.tractracadapter@default:default,com.sap.sailing.domain@default:default,com.sap.sailing.expeditionconnector.test@default:default,com.sap.sailing.expeditionconnector@default:default,com.sap.sailing.mongodb.test@default:default,com.sap.sailing.mongodb@default:default,com.sap.sailing.server.test@default:default,com.sap.sailing.server@default:default,com.tractrac.clientmodule@default:default,com.tractrac.resultapi@default:default,org.json.simple@default:default"/>
</launchConfiguration>
@@ -20,9 +20,9 @@
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Declipse.ignoreApp=true -Dosgi.noShutdown=true -Dhttp.proxyHost=proxy.wdf.sap.corp -Dhttp.proxyPort=8080&#13;&#10;-Dorg.osgi.service.http.port=8888"/>
<stringAttribute key="pde.version" value="3.3"/>
<booleanAttribute key="show_selected_only" value="false"/>
<stringAttribute key="target_bundles" value="org.mortbay.jetty.server@default:default,ch.qos.logback.core@default:default,org.eclipse.core.runtime.compatibility.registry@default:false,org.eclipse.equinox.http.servlet@default:default,org.apache.jasper@default:default,ch.qos.logback.classic@default:default,org.apache.ant@default:default,org.eclipse.net4j.jms.api@default:default,org.eclipse.equinox.common@2:true,javax.servlet@default:default,org.eclipse.osgi.services@default:default,org.eclipse.equinox.http.jetty@default:default,org.eclipse.osgi@-1:true,org.eclipse.equinox.http.registry@default:default,org.eclipse.core.jobs@default:default,org.eclipse.equinox.registry@default:default,org.eclipse.update.configurator@3:true,javax.servlet.jsp@default:default,javax.transaction@default:false,org.apache.commons.logging@default:default,org.eclipse.equinox.weaving.hook@default:false,org.slf4j.api@default:default,javax.activation@default:default,org.apache.commons.el@default:default,ch.qos.logback.slf4j@default:false,org.mortbay.jetty.util@default:default"/>
<stringAttribute key="target_bundles" value="javax.servlet.jsp@default:default,javax.servlet@default:default,org.apache.ant@default:default,org.apache.commons.el@default:default,org.apache.commons.logging@default:default,org.apache.jasper@default:default,org.eclipse.core.jobs@default:default,org.eclipse.core.runtime.compatibility.registry@default:false,org.eclipse.equinox.common@2:true,org.eclipse.equinox.http.jetty@default:default,org.eclipse.equinox.http.registry@default:default,org.eclipse.equinox.http.servlet@default:default,org.eclipse.equinox.registry@default:default,org.eclipse.osgi.services@default:default,org.eclipse.osgi@-1:true,org.eclipse.update.configurator@3:true,org.mortbay.jetty.server@default:default,org.mortbay.jetty.util@default:default"/>
<booleanAttribute key="tracing" value="false"/>
<booleanAttribute key="useCustomFeatures" value="false"/>
<booleanAttribute key="useDefaultConfigArea" value="false"/>
<stringAttribute key="workspace_bundles" value="com.sap.sailing.declination@default:default,com.mongodb.driver@default:default,com.sap.sailing.server@default:default,com.sap.sailing.domain@default:default,com.tractrac.clientmodule@default:default,com.sap.sailing.expeditionconnector@default:default,org.json.simple@default:default,com.sap.sailing.mongodb.test@default:default,com.sap.sailing.expeditionconnector.test@default:default,com.tractrac.resultapi@default:default,com.sap.sailing.domain.test@default:default,com.sap.sailing.domain.tractracadapter@default:default,com.sap.sailing.mongodb@default:default"/>
<stringAttribute key="workspace_bundles" value="com.googlecode.java-diff-utils.test@default:default,com.googlecode.java-diff-utils@default:default,com.mongodb.driver@default:default,com.sap.sailing.declination.test@default:default,com.sap.sailing.declination@default:default,com.sap.sailing.domain.test@default:default,com.sap.sailing.domain.tractracadapter@default:default,com.sap.sailing.domain@default:default,com.sap.sailing.expeditionconnector.test@default:default,com.sap.sailing.expeditionconnector@default:default,com.sap.sailing.mongodb.test@default:default,com.sap.sailing.mongodb@default:default,com.sap.sailing.server.test@default:default,com.sap.sailing.server@default:default,com.tractrac.clientmodule@default:default,com.tractrac.resultapi@default:default,org.json.simple@default:default"/>
</launchConfiguration>
@@ -186,9 +186,9 @@ public class ModeratorApp extends Servlet {
trackedRace.getTimePointOfLastEvent()==null?MillisecondsTimePoint.now():trackedRace.getTimePointOfLastEvent());
String sinceUpdateString = req.getParameter(PARAM_NAME_SINCE_UPDATE);
if (sinceUpdateString != null) {
System.out.println("Blocking...");
int sinceUpdate = Integer.valueOf(sinceUpdateString);
// block until there is new data:
System.out.println("Blocking at "+trackedRace.getUpdateCount()+" waiting for "+sinceUpdate);
trackedRace.waitForNextUpdate(sinceUpdate);
}
JSONObject jsonRace = new JSONObject();