failing test case for bug 3648; introduced Speed.travel(Duration)

Change-Id: Ib164a12b0330f8c99251031553866435e82632fe
This commit is contained in:
Axel Uhl committed 2016-05-11 15:15:05 +02:00
1 parent fd348db671
commit fbd79b6dde
6 files changed
+83 -3

No files matched your search

@@ -16,7 +16,12 @@ public abstract class AbstractSpeedImpl implements Speed {
@Override
public Distance travel(TimePoint t1, TimePoint t2) {
return new NauticalMileDistance((t2.asMillis() - t1.asMillis()) / 1000. / 3600. * getKnots());
return travel(t1.until(t2));
}
@Override
public Distance travel(Duration duration) {
return new NauticalMileDistance(duration.asHours() * getKnots());
}
@Override
@@ -60,6 +60,11 @@ public interface Speed extends Comparable<Speed>, Serializable {
public double getStatuteMilesPerHour() {
return 0;
}
@Override
public Distance travel(Duration duration) {
return Distance.NULL;
}
};
@Statistic(messageKey="", resultDecimals=2)
@@ -85,4 +90,6 @@ public interface Speed extends Comparable<Speed>, Serializable {
* line" on a sphere) with this speed.
*/
Duration getDuration(Distance distance);
Distance travel(Duration duration);
}
@@ -0,0 +1,60 @@
package com.sap.sailing.domain.test;
import static org.junit.Assert.assertEquals;
import java.util.Collections;
import org.junit.Before;
import org.junit.Test;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.common.Distance;
import com.sap.sailing.domain.common.Position;
import com.sap.sailing.domain.common.TrackedRaceStatusEnum;
import com.sap.sailing.domain.common.impl.DegreeBearingImpl;
import com.sap.sailing.domain.common.impl.DegreePosition;
import com.sap.sailing.domain.common.impl.KnotSpeedWithBearingImpl;
import com.sap.sailing.domain.common.tracking.impl.GPSFixMovingImpl;
import com.sap.sailing.domain.tracking.DynamicTrackedRace;
import com.sap.sailing.domain.tracking.impl.MarkPassingImpl;
import com.sap.sailing.domain.tracking.impl.TrackedRaceStatusImpl;
import com.sap.sse.common.Duration;
import com.sap.sse.common.TimePoint;
import com.sap.sse.common.impl.MillisecondsTimePoint;
/**
* See bug 3648: When a race is loading, cache invalidation is suspended which also affects the distance cache.
* However, for the distance cache, during resuming caching operations there was a cache invalidation missing.
* This tests, failing before the fix for bug 3648, ensures that this type of invalidation actually happens.
*
* @author Axel Uhl (d043530)
*
*/
public class DistanceCacheInvalidationAfterLoadingFinishedTest extends TrackBasedTest {
private Competitor competitor;
private DynamicTrackedRace trackedRace;
@Before
public void setUp() {
competitor = createCompetitor("Test Competitor");
trackedRace = createTestTrackedRace("Test Regatta", "Test Race", "505", Collections.singleton(competitor), MillisecondsTimePoint.now());
}
@Test
public void testDistanceCalculationWhileLoading() {
final TimePoint now = MillisecondsTimePoint.now();
trackedRace.updateMarkPassings(competitor, Collections.singleton(new MarkPassingImpl(now, trackedRace.getRace().getCourse().getFirstWaypoint(), competitor)));
// no distance traveled yet because there is no fix yet; this may be cached for now
assertEquals(Distance.NULL, trackedRace.getDistanceTraveled(competitor, now));
trackedRace.setStatus(new TrackedRaceStatusImpl(TrackedRaceStatusEnum.LOADING, /* progress */ 0.1));
assertEquals(Distance.NULL, trackedRace.getDistanceTraveled(competitor, now.plus(Duration.ONE_SECOND.times(2))));
final Position startPos = new DegreePosition(0, 0);
final DegreeBearingImpl bearing = new DegreeBearingImpl(10);
final KnotSpeedWithBearingImpl speed = new KnotSpeedWithBearingImpl(10, bearing);
trackedRace.recordFix(competitor, new GPSFixMovingImpl(startPos, now, speed));
final Distance distance = speed.travel(Duration.ONE_SECOND);
trackedRace.recordFix(competitor, new GPSFixMovingImpl(startPos.translateGreatCircle(bearing, distance), now.plus(Duration.ONE_SECOND), speed));
trackedRace.setStatus(new TrackedRaceStatusImpl(TrackedRaceStatusEnum.TRACKING, /* progress */ 1.0));
assertEquals(distance.getMeters(), trackedRace.getDistanceTraveled(competitor, now.plus(Duration.ONE_SECOND.times(2))).getMeters(), 0.000001); // ask 1s after the second fix
}
}
@@ -549,22 +549,26 @@ public class GPSFixTrackImpl<ItemType, FixType extends GPSFix> extends TrackImpl
if (!from.before(to)) {
result = Distance.NULL;
} else {
boolean perfectCacheHit = false;
lockForRead();
try {
Util.Pair<TimePoint, Util.Pair<TimePoint, Distance>> bestCacheEntry = getDistanceCache()
.getEarliestFromAndDistanceAtOrAfterFrom(from, to);
if (bestCacheEntry != null) {
perfectCacheHit = true; // potentially a cache hit; but if it doesn't span the full interval, it's not perfect; see below
// compute the missing stretches between best cache entry's "from" and our "from" and the cache
// entry's "to" and our "to"
Distance distanceFromFromToBeginningOfCacheEntry = Distance.NULL;
Distance distanceFromEndOfCacheEntryToTo = Distance.NULL;
if (!bestCacheEntry.getB().getA().equals(from)) {
assert bestCacheEntry.getB().getA().after(from);
perfectCacheHit = false;
distanceFromFromToBeginningOfCacheEntry = getDistanceTraveledRecursively(from, bestCacheEntry
.getB().getA(), recursionDepth + 1);
}
if (!bestCacheEntry.getA().equals(to)) {
assert bestCacheEntry.getA().before(to);
perfectCacheHit = false;
distanceFromEndOfCacheEntryToTo = getDistanceTraveledRecursively(bestCacheEntry.getA(), to,
recursionDepth + 1);
}
@@ -599,7 +603,7 @@ public class GPSFixTrackImpl<ItemType, FixType extends GPSFix> extends TrackImpl
} finally {
unlockAfterRead();
}
if (recursionDepth == 0) {
if (!perfectCacheHit && recursionDepth == 0) {
getDistanceCache().cache(from, to, result);
}
}
@@ -398,6 +398,10 @@ public class WindTrackImpl extends TrackImpl<Wind> implements WindTrack {
public double getStatuteMilesPerHour() {
return 0;
}
@Override
public Distance travel(Duration duration) {
return null;
}
}
@Override
@@ -60,7 +60,7 @@ public class MillisecondsDurationImpl implements Duration {
@Override
public double asHours() {
return asMillis() / Duration.ONE_HOUR.asMillis();
return ((double) asMillis()) / (double) Duration.ONE_HOUR.asMillis();
}
@Override