From a4d9c31141a64c0d2403e24e2e38857b67fe9edf Mon Sep 17 00:00:00 2001 From: "service.tip.git" Date: Thu, 16 Jan 2020 20:09:44 +0000 Subject: [PATCH 1/4] [INTERNAL] Translation delivery: commit by LX Lab Change-Id: I6a8784409999de6f0c1bc9a3a4491b0787e62084 --- .../com/sap/sailing/gwt/ui/client/StringMessages_fr.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_fr.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_fr.properties index 1f01651abc7..b2290fe2365 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_fr.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_fr.properties @@ -2011,7 +2011,7 @@ enterTagsForTheVideo=Entrez des balises pour la vidéo. enterIdOfWindFinderReviewedSpotCollection=Entrez l''ID d''un ensemble d''endroits WindFinder révisé, par exemple, "Schilksee". windFinderSpotCollectionsList=Ensemble d''endroits WindFinder enterTagsForTheImage=Entrez des balises pour l''image. -unableToResolveWindFinderSpotId=Impossible de traiter l''endroit WindFinder ayant l''ID {0} : {1} +unableToResolveWindFinderSpotId=Impossible de traiter l''endroit WindFinder avec l''ID {0} : {1} windFinderWeatherData=Données météo positionEditOnNonTrackingRace=Cette course n''est pas suivie actuellement. Les mises à jour d''erreurs ne sont plus reçues par la course suivie. Pour voir les modifications, vous devez recharger la course. errorCreatingLeaderboardGroup=Erreur lors de la tentative de création du nouveau groupe de palmarès {0} From 371a0dd973a4f5e916a5e6f7dd6c86650702477f Mon Sep 17 00:00:00 2001 From: Steffen Schaefer Date: Fri, 17 Jan 2020 15:06:17 +0100 Subject: [PATCH 2/4] Bug 5085 Fixed concurrency issue in course update --- .../src/com/sap/sailing/domain/base/impl/CourseImpl.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) mode change 100755 => 100644 java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/CourseImpl.java diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/CourseImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/CourseImpl.java old mode 100755 new mode 100644 index c6d97e16dec..d16b54929d3 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/CourseImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/CourseImpl.java @@ -368,9 +368,6 @@ public class CourseImpl extends RenamableImpl implements Course { newWaypointList.add(waypoint); } patch = DiffUtils.diff(courseWaypoints, newWaypointList); - - this.getAssociatedRoles().clear(); - this.getAssociatedRoles().putAll(associatedRoles); } finally { unlockAfterRead(); } @@ -378,6 +375,8 @@ public class CourseImpl extends RenamableImpl implements Course { lockForWrite(); try { logger.info("applying course update " + patch + " to course " + this); + this.getAssociatedRoles().clear(); + this.getAssociatedRoles().putAll(associatedRoles); CourseAsWaypointList courseAsWaypointList = new CourseAsWaypointList(this); patch.applyToInPlace(courseAsWaypointList); } finally { From 2737661d79a9652288fcf443d446e7556a2c8c3b Mon Sep 17 00:00:00 2001 From: Steffen Schaefer Date: Fri, 17 Jan 2020 15:08:51 +0100 Subject: [PATCH 3/4] Bug 5085: Include originatingCouseTemplateIdOrNull in Course update to ensure consistency with a CourseBase that is the source of the update operation --- .../domain/racelogtracking/impl/RaceLogRaceTracker.java | 3 ++- .../domain/swisstimingadapter/impl/DomainFactoryImpl.java | 3 ++- .../impl/SwissTimingReplayToDomainAdapter.java | 3 ++- .../src/com/sap/sailing/domain/test/CourseTest.java | 6 ++++-- .../src/com/sap/sailing/domain/test/CourseUpdateTest.java | 3 ++- .../domain/tractracadapter/impl/DomainFactoryImpl.java | 3 ++- .../src/com/sap/sailing/domain/base/Course.java | 4 ++-- .../src/com/sap/sailing/domain/base/impl/CourseImpl.java | 6 ++++-- .../com/sap/sailing/gwt/ui/server/SailingServiceImpl.java | 6 ++++-- .../sap/sailing/server/gateway/jaxrs/api/MarkResource.java | 3 ++- 10 files changed, 26 insertions(+), 14 deletions(-) diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/RaceLogRaceTracker.java b/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/RaceLogRaceTracker.java index d1dca35e653..0601fc5ccaf 100755 --- a/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/RaceLogRaceTracker.java +++ b/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/RaceLogRaceTracker.java @@ -262,7 +262,8 @@ public class RaceLogRaceTracker extends AbstractRaceTrackerBaseImpl { } try { final Course course = trackedRace.getRace().getCourse(); - course.update(update, event.getCourseDesign().getAssociatedRoles(), params.getDomainFactory()); + course.update(update, event.getCourseDesign().getAssociatedRoles(), + event.getCourseDesign().getOriginatingCourseTemplateIdOrNull(), params.getDomainFactory()); if (base.getName() != null) { course.setName(base.getName()); } diff --git a/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/DomainFactoryImpl.java b/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/DomainFactoryImpl.java index 8f8a87d5cc4..12706237559 100755 --- a/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/DomainFactoryImpl.java +++ b/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/DomainFactoryImpl.java @@ -391,7 +391,8 @@ public class DomainFactoryImpl implements DomainFactory { mark.getDeviceIds(), getMarkType(mark.getMarkType()), mark.getDescription()); newDomainControlPoints.add(new com.sap.sse.common.Util.Pair<>(domainControlPoint, PassingInstruction.None)); } - courseToUpdate.update(newDomainControlPoints, courseToUpdate.getAssociatedRoles(), baseDomainFactory); + courseToUpdate.update(newDomainControlPoints, courseToUpdate.getAssociatedRoles(), + courseToUpdate.getOriginatingCourseTemplateIdOrNull(), baseDomainFactory); } @Override diff --git a/java/com.sap.sailing.domain.swisstimingreplayadapter/src/com/sap/sailing/domain/swisstimingreplayadapter/impl/SwissTimingReplayToDomainAdapter.java b/java/com.sap.sailing.domain.swisstimingreplayadapter/src/com/sap/sailing/domain/swisstimingreplayadapter/impl/SwissTimingReplayToDomainAdapter.java index bb27692ffa2..b2aa6c6264e 100755 --- a/java/com.sap.sailing.domain.swisstimingreplayadapter/src/com/sap/sailing/domain/swisstimingreplayadapter/impl/SwissTimingReplayToDomainAdapter.java +++ b/java/com.sap.sailing.domain.swisstimingreplayadapter/src/com/sap/sailing/domain/swisstimingreplayadapter/impl/SwissTimingReplayToDomainAdapter.java @@ -393,7 +393,8 @@ public class SwissTimingReplayToDomainAdapter extends SwissTimingReplayAdapter i for (ControlPoint cp : currentCourseDefinition) { courseToUpdate.add(new Pair(cp, PassingInstruction.None)); } - course.update(courseToUpdate, course.getAssociatedRoles(), domainFactory.getBaseDomainFactory()); + course.update(courseToUpdate, course.getAssociatedRoles(), + course.getOriginatingCourseTemplateIdOrNull(), domainFactory.getBaseDomainFactory()); } catch (PatchFailedException e) { throw new RuntimeException(e); } diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CourseTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CourseTest.java index afe4cc97144..e150d79ed46 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CourseTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CourseTest.java @@ -193,7 +193,8 @@ public class CourseTest { courseToUpdate.add(new com.sap.sse.common.Util.Pair(wp2.getMarks().iterator().next(), wp2.getPassingInstructions())); courseToUpdate.add(new com.sap.sse.common.Util.Pair(wp3.getMarks().iterator().next(), wp3.getPassingInstructions())); courseToUpdate.add(new com.sap.sse.common.Util.Pair(wp1.getMarks().iterator().next(), wp1.getPassingInstructions())); - course.update(courseToUpdate, new HashMap<>(), DomainFactory.INSTANCE); + course.update(courseToUpdate, new HashMap<>(), course.getOriginatingCourseTemplateIdOrNull(), + DomainFactory.INSTANCE); assertWaypointIndexes(course); } @@ -231,7 +232,8 @@ public class CourseTest { courseToUpdate.add(new Pair<>(red.getControlPoint(), red.getPassingInstructions())); courseToUpdate.add(new Pair<>(yellow.getControlPoint(), yellow.getPassingInstructions())); courseToUpdate.add(new Pair<>(finishPoleCylinder.getControlPoint(), finishPoleCylinder.getPassingInstructions())); - course.update(courseToUpdate, new HashMap<>(), DomainFactory.INSTANCE); + course.update(courseToUpdate, new HashMap<>(), course.getOriginatingCourseTemplateIdOrNull(), + DomainFactory.INSTANCE); assertWaypointIndexes(course); List newControlPoints = new ArrayList<>(); for (Waypoint newWp : course.getWaypoints()) { diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CourseUpdateTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CourseUpdateTest.java index 84379e303fb..ea998a07607 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CourseUpdateTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CourseUpdateTest.java @@ -198,7 +198,8 @@ public class CourseUpdateTest extends AbstractTracTracLiveTest { changedControlPoints.add(new Pair<>(wp2.getControlPoint(), wp2.getPassingInstructions())); changedControlPoints.add(new Pair<>(wp3.getControlPoint(), wp3.getPassingInstructions())); changedControlPoints.add(new Pair<>(wp4.getControlPoint(), wp4.getPassingInstructions())); - course.update(changedControlPoints, new HashMap<>(), com.sap.sailing.domain.base.DomainFactory.INSTANCE); + course.update(changedControlPoints, new HashMap<>(), course.getOriginatingCourseTemplateIdOrNull(), + com.sap.sailing.domain.base.DomainFactory.INSTANCE); assertNotSame(wp1, Util.get(course.getWaypoints(), 0)); assertSame(wp2, Util.get(course.getWaypoints(), 1)); diff --git a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/DomainFactoryImpl.java b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/DomainFactoryImpl.java index 69b40ad4151..03b7b1e486a 100755 --- a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/DomainFactoryImpl.java +++ b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/DomainFactoryImpl.java @@ -200,7 +200,8 @@ public class DomainFactoryImpl implements DomainFactory { com.sap.sailing.domain.base.ControlPoint newDomainControlPoint = getOrCreateControlPoint(tractracControlPoint.getA()); newDomainControlPoints.add(new com.sap.sse.common.Util.Pair(newDomainControlPoint, tractracControlPoint.getB())); } - courseToUpdate.update(newDomainControlPoints, courseToUpdate.getAssociatedRoles(), baseDomainFactory); + courseToUpdate.update(newDomainControlPoints, courseToUpdate.getAssociatedRoles(), + courseToUpdate.getOriginatingCourseTemplateIdOrNull(), baseDomainFactory); } @Override diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/Course.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/Course.java index 64d1b07db7d..33668d13c27 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/Course.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/Course.java @@ -43,8 +43,8 @@ public interface Course extends CourseBase, Renamable { * to the registered {@link CourseListener}s as if {@link #addWaypoint(int, Waypoint)} and {@link #removeWaypoint(int)} * had been used. */ - void update(Iterable> newControlPoints, - Map associatedRoles, DomainFactory baseDomainFactory) throws PatchFailedException; + void update(Iterable> newControlPoints, Map associatedRoles, + UUID originatingCouseTemplateIdOrNull, DomainFactory baseDomainFactory) throws PatchFailedException; int getNumberOfWaypoints(); diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/CourseImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/CourseImpl.java index d16b54929d3..38bdef5cb6d 100644 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/CourseImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/CourseImpl.java @@ -44,7 +44,7 @@ public class CourseImpl extends RenamableImpl implements Course { private final List waypoints; private final Map waypointIndexes; private final List legs; - private final UUID originatingCourseTemplateId; + private UUID originatingCourseTemplateId; private final Map associatedRoles; private transient Set listeners; private transient NamedReentrantReadWriteLock lock; @@ -335,7 +335,8 @@ public class CourseImpl extends RenamableImpl implements Course { @Override public void update(Iterable> newControlPoints, - Map associatedRoles, DomainFactory baseDomainFactory) throws PatchFailedException { + Map associatedRoles, UUID originatingCouseTemplateIdOrNull, DomainFactory baseDomainFactory) + throws PatchFailedException { Patch patch = null; synchronized (updateMonitor) { lockForRead(); @@ -377,6 +378,7 @@ public class CourseImpl extends RenamableImpl implements Course { logger.info("applying course update " + patch + " to course " + this); this.getAssociatedRoles().clear(); this.getAssociatedRoles().putAll(associatedRoles); + this.originatingCourseTemplateId = originatingCouseTemplateIdOrNull; CourseAsWaypointList courseAsWaypointList = new CourseAsWaypointList(this); patch.applyToInPlace(courseAsWaypointList); } finally { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java index 1594f460fb6..4f47bedb48c 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java @@ -2635,7 +2635,8 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet controlPoints.add(new Pair<>(getOrCreateControlPoint(waypointDTO.getA()), waypointDTO.getB())); } try { - course.update(controlPoints, course.getAssociatedRoles(), baseDomainFactory); + course.update(controlPoints, course.getAssociatedRoles(), course.getOriginatingCourseTemplateIdOrNull(), + baseDomainFactory); } catch (Exception e) { throw new RuntimeException(e); } @@ -6988,7 +6989,8 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet Course course = new CourseImpl(courseName, lastPublishedCourse.getWaypoints()); try { - course.update(controlPoints, lastPublishedCourse.getAssociatedRoles(), baseDomainFactory); + course.update(controlPoints, lastPublishedCourse.getAssociatedRoles(), + lastPublishedCourse.getOriginatingCourseTemplateIdOrNull(), baseDomainFactory); } catch (Exception e) { throw new RuntimeException(e); } diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/MarkResource.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/MarkResource.java index 3e6f6caee73..9f7bdc5460a 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/MarkResource.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/MarkResource.java @@ -272,7 +272,8 @@ public class MarkResource extends AbstractSailingServerResource { } Course course = new CourseImpl(courseName, lastPublishedCourse.getWaypoints(), originatingCourseTemplateId); try { - course.update(controlPoints, lastPublishedCourse.getAssociatedRoles(), getService().getBaseDomainFactory()); + course.update(controlPoints, lastPublishedCourse.getAssociatedRoles(), + lastPublishedCourse.getOriginatingCourseTemplateIdOrNull(), getService().getBaseDomainFactory()); } catch (Exception e) { throw new RuntimeException(e); } From 32330adf5f2d18af7e30ef076ede44111ba01dbc Mon Sep 17 00:00:00 2001 From: Steffen Schaefer Date: Fri, 17 Jan 2020 16:10:29 +0100 Subject: [PATCH 4/4] Fixed non deterministic behavior in CourseUpdateTest --- .../sailing/domain/test/CourseUpdateTest.java | 71 +++++++++++-------- 1 file changed, 40 insertions(+), 31 deletions(-) diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CourseUpdateTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CourseUpdateTest.java index 1cfc431b7d2..09dc1668356 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CourseUpdateTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CourseUpdateTest.java @@ -15,6 +15,10 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.UUID; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; import org.junit.After; import org.junit.Before; @@ -70,7 +74,7 @@ public class CourseUpdateTest extends AbstractTracTracLiveTest { private Course course; private Regatta domainRegatta; private DynamicTrackedRegatta trackedRegatta; - private final IControlRoute[] routeData = new IControlRoute[1]; + private CompletableFuture routeDataFuture; private DomainFactory domainFactory; public CourseUpdateTest() throws URISyntaxException, MalformedURLException { @@ -80,6 +84,7 @@ public class CourseUpdateTest extends AbstractTracTracLiveTest { @Before public void setUp() throws Exception { super.setUp(); + routeDataFuture = new CompletableFuture<>(); domainFactory = new DomainFactoryImpl(new com.sap.sailing.domain.base.impl.DomainFactoryImpl(com.sap.sailing.domain.base.DomainFactory.TEST_RACE_LOG_RESOLVER)); domainRegatta = domainFactory.getOrCreateDefaultRegatta(EmptyRaceLogStore.INSTANCE, EmptyRegattaLogStore.INSTANCE, getTracTracRace(), /* trackedRegattaRegistry */ null); @@ -99,9 +104,8 @@ public class CourseUpdateTest extends AbstractTracTracLiveTest { @Override protected void handleEvent(Triple event) { super.handleEvent(event); - synchronized (routeData) { - routeData[0] = event.getA(); - routeData.notifyAll(); + if (!event.getA().getControls().isEmpty()) { + routeDataFuture.complete(event.getA()); } } }); @@ -132,20 +136,25 @@ public class CourseUpdateTest extends AbstractTracTracLiveTest { private void testLegStructure(int minimalNumberOfLegsExpected) throws InterruptedException { waitForRouteData(); - assertTrue(course.getLegs().size() >= minimalNumberOfLegsExpected); - TrackedRace trackedRace = trackedRegatta.getTrackedRace(race); - assertEquals(course.getLegs().size(), Util.size(trackedRace.getTrackedLegs())); - Iterator legIter = course.getLegs().iterator(); - for (TrackedLeg trackedLeg : trackedRace.getTrackedLegs()) { - assertTrue(legIter.hasNext()); - Leg leg = legIter.next(); - assertSame(leg, trackedLeg.getLeg()); - for (Competitor competitor : race.getCompetitors()) { - TrackedLegOfCompetitor tloc = trackedLeg.getTrackedLeg(competitor); - assertNotNull(tloc); - assertSame(competitor, tloc.getCompetitor()); - assertSame(leg, tloc.getLeg()); + course.lockForRead(); + try { + assertTrue(course.getLegs().size() >= minimalNumberOfLegsExpected); + TrackedRace trackedRace = trackedRegatta.getTrackedRace(race); + assertEquals(course.getLegs().size(), Util.size(trackedRace.getTrackedLegs())); + Iterator legIter = course.getLegs().iterator(); + for (TrackedLeg trackedLeg : trackedRace.getTrackedLegs()) { + assertTrue(legIter.hasNext()); + Leg leg = legIter.next(); + assertSame(leg, trackedLeg.getLeg()); + for (Competitor competitor : race.getCompetitors()) { + TrackedLegOfCompetitor tloc = trackedLeg.getTrackedLeg(competitor); + assertNotNull(tloc); + assertSame(competitor, tloc.getCompetitor()); + assertSame(leg, tloc.getLeg()); + } } + } finally { + course.unlockAfterRead(); } } @@ -208,8 +217,8 @@ public class CourseUpdateTest extends AbstractTracTracLiveTest { @Test public void testLastWaypointRemoved() throws PatchFailedException, InterruptedException { final boolean[] result = new boolean[1]; - waitForRouteData(); - final List controlPoints = new ArrayList<>(routeData[0].getControls()); + final IControlRoute routeData = waitForRouteData(); + final List controlPoints = new ArrayList<>(routeData.getControls()); final IControl removedControlPoint = controlPoints.remove(controlPoints.size()-1); course.addCourseListener(new CourseListener() { @Override @@ -232,8 +241,8 @@ public class CourseUpdateTest extends AbstractTracTracLiveTest { @Test public void testLastButOneWaypointRemoved() throws PatchFailedException, InterruptedException { final boolean[] result = new boolean[1]; - waitForRouteData(); - final List controlPoints = new ArrayList<>(routeData[0].getControls()); + final IControlRoute routeData = waitForRouteData(); + final List controlPoints = new ArrayList<>(routeData.getControls()); final IControl removedControlPoint = controlPoints.remove(1); course.addCourseListener(new CourseListener() { @Override @@ -253,11 +262,11 @@ public class CourseUpdateTest extends AbstractTracTracLiveTest { testLegStructure(1); } - private void waitForRouteData() throws InterruptedException { - synchronized (routeData) { - while (routeData[0] == null) { - routeData.wait(); - } + private IControlRoute waitForRouteData() { + try { + return routeDataFuture.get(1, TimeUnit.MINUTES); + } catch (ExecutionException | TimeoutException | InterruptedException e) { + throw new RuntimeException(e); } } @@ -265,8 +274,8 @@ public class CourseUpdateTest extends AbstractTracTracLiveTest { public void testWaypointAddedAtEnd() throws PatchFailedException, InterruptedException { final boolean[] result = new boolean[1]; final IControl cp1 = createMockedControlPoint("CP1", 1, UUID.randomUUID()); - waitForRouteData(); - final List controlPoints = new ArrayList<>(routeData[0].getControls()); + final IControlRoute routeData = waitForRouteData(); + final List controlPoints = new ArrayList<>(routeData.getControls()); controlPoints.add(cp1); course.addCourseListener(new CourseListener() { @Override @@ -303,8 +312,8 @@ public class CourseUpdateTest extends AbstractTracTracLiveTest { public void testTrackedRacesTrackedLegsUpdatedProperly() throws InterruptedException, PatchFailedException { final boolean[] result = new boolean[1]; final IControl cp1 = createMockedControlPoint("CP1", 1, UUID.randomUUID()); - waitForRouteData(); - final List controlPoints = new ArrayList<>(routeData[0].getControls()); + final IControlRoute routeData = waitForRouteData(); + final List controlPoints = new ArrayList<>(routeData.getControls()); controlPoints.add(cp1); course.addCourseListener(new CourseListener() { @Override @@ -327,6 +336,6 @@ public class CourseUpdateTest extends AbstractTracTracLiveTest { @After public void tearDown() throws MalformedURLException, IOException, InterruptedException { super.tearDown(); - routeData[0] = null; + routeDataFuture = null; } }