Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix race on set route #4755

Merged
merged 2 commits into from
Aug 26, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import com.mapbox.navigator.NavigationStatus
import com.mapbox.navigator.NavigationStatusOrigin
import com.mapbox.navigator.NavigatorObserver
import com.mapbox.navigator.RouteState
import kotlinx.coroutines.Job
import kotlinx.coroutines.cancelChildren
import kotlinx.coroutines.launch
import java.util.concurrent.CopyOnWriteArraySet
Expand All @@ -64,16 +65,17 @@ internal class MapboxTripSession(
private val eHorizonSubscriptionManager: EHorizonSubscriptionManager,
) : TripSession {

private var updateRouteJob: Job? = null

override var route: DirectionsRoute? = null
set(value) {
val isSameUuid = value?.isSameUuid(field) ?: false
val isSameRoute = value?.isSameRoute(field) ?: false
field = value
if (value == null) {
roadObjects = emptyList()
routeProgress = null
}
val updateRouteJob = threadController.getMainScopeAndRootJob().scope.launch {
updateRouteJob = threadController.getMainScopeAndRootJob().scope.launch {
when {
isSameUuid && isSameRoute && value != null -> {
navigator.updateAnnotations(value)
Expand All @@ -86,10 +88,11 @@ internal class MapboxTripSession(
}
}
mainJobController.scope.launch {
updateRouteJob.join()
updateRouteJob?.join()
field = value
isOffRoute = false
invalidateLatestBannerInstructionEvent()
}
isOffRoute = false
invalidateLatestBannerInstructionEvent()
}

private val mainJobController: JobControl = threadController.getMainScopeAndRootJob()
Expand Down Expand Up @@ -604,6 +607,10 @@ internal class MapboxTripSession(
progress: RouteProgress?,
shouldTriggerBannerInstructionsObserver: Boolean
) {
if (updateRouteJob?.isActive == true) {
return
}

routeProgress = progress
if (tripService.hasServiceStarted()) {
tripService.updateNotification(buildTripNotificationState(progress))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,12 @@ import com.mapbox.navigator.NavigationStatusOrigin
import com.mapbox.navigator.NavigatorObserver
import com.mapbox.navigator.RouteInfo
import com.mapbox.navigator.RouteState
import io.mockk.Runs
import io.mockk.clearMocks
import io.mockk.coEvery
import io.mockk.coVerify
import io.mockk.every
import io.mockk.just
import io.mockk.mockk
import io.mockk.mockkObject
import io.mockk.mockkStatic
Expand All @@ -62,6 +64,8 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.InternalCoroutinesApi
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.cancelAndJoin
import kotlinx.coroutines.delay
import kotlinx.coroutines.test.runBlockingTest
import org.junit.After
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
Expand Down Expand Up @@ -1079,6 +1083,55 @@ class MapboxTripSessionTest {
verify(exactly = 0) { navigator.setFallbackVersionsObserver(any()) }
}

@Test
fun routeIsSetAfterNativeJobComplete() = runBlockingTest {
coEvery { navigator.setRoute(any()) } coAnswers {
delay(100)
null
}

tripSession.route = route

assertEquals(tripSession.route, null)

coroutineRule.testDispatcher.advanceTimeBy(200)

assertEquals(tripSession.route, route)
}

@Test
fun routeProgressProvidedWhenRouteIsSet() = runBlockingTest {
coEvery { navigator.setRoute(any()) } coAnswers {
delay(100)
null
}

val observerOne: RouteProgressObserver = mockk(relaxUnitFun = true)
val observerTwo: RouteProgressObserver = mockk(relaxUnitFun = true)
every { observerOne.onRouteProgressChanged(any()) } just Runs
every { observerTwo.onRouteProgressChanged(any()) } just Runs
every { route.legs() } returns null

tripSession = buildTripSession()
tripSession.registerRouteProgressObserver(observerOne)
tripSession.registerRouteProgressObserver(observerTwo)
tripSession.start(true)
tripSession.route = route

repeat(5) {
navigatorObserverImplSlot.captured.onStatus(navigationStatusOrigin, navigationStatus)
}

coroutineRule.testDispatcher.advanceTimeBy(200)

repeat(2) {
navigatorObserverImplSlot.captured.onStatus(navigationStatusOrigin, navigationStatus)
}

verify(exactly = 2) { observerOne.onRouteProgressChanged(any()) }
verify(exactly = 2) { observerTwo.onRouteProgressChanged(any()) }
}

@After
fun cleanUp() {
unmockkObject(MapboxNativeNavigatorImpl)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@ object MapboxNativeNavigatorImpl : MapboxNativeNavigator {
// TODO migrate to RouterInterface
private var nativeRouter: Router? = null
private var historyRecorderHandle: HistoryRecorderHandle? = null
private var route: DirectionsRoute? = null
override var graphAccessor: GraphAccessor? = null
override var roadObjectMatcher: RoadObjectMatcher? = null
override var roadObjectsStore: RoadObjectsStore? = null
Expand Down Expand Up @@ -103,7 +102,6 @@ object MapboxNativeNavigatorImpl : MapboxNativeNavigator {
roadObjectsStore = nativeComponents.navigator.roadObjectStore()
experimental = nativeComponents.navigator.experimental
cache = nativeComponents.cache
route = null
this.logger = logger
return this
}
Expand Down Expand Up @@ -175,7 +173,6 @@ object MapboxNativeNavigatorImpl : MapboxNativeNavigator {
legIndex: Int
): RouteInfo? =
withContext(NavigatorDispatcher) {
MapboxNativeNavigatorImpl.route = route
val result = navigator!!.setRoute(
route?.toJson() ?: "{}",
PRIMARY_ROUTE_INDEX,
Expand All @@ -194,7 +191,6 @@ object MapboxNativeNavigatorImpl : MapboxNativeNavigator {
*/
override suspend fun updateAnnotations(route: DirectionsRoute): Unit =
withContext(NavigatorDispatcher) {
MapboxNativeNavigatorImpl.route = route
route.legs()?.forEachIndexed { index, routeLeg ->
routeLeg.annotation()?.toJson()?.let { annotations ->
navigator!!.updateAnnotations(annotations, PRIMARY_ROUTE_INDEX, index)
Expand Down