-
Notifications
You must be signed in to change notification settings - Fork 319
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fast integration test for artificial driver (#6799)
- Loading branch information
1 parent
2275707
commit 6fc4e70
Showing
5 changed files
with
23,578 additions
and
20 deletions.
There are no files selected for viewing
146 changes: 146 additions & 0 deletions
146
...core/src/androidTest/java/com/mapbox/navigation/core/trip/service/ArtificialDriverTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
package com.mapbox.navigation.core.trip.service | ||
|
||
import androidx.test.ext.junit.runners.AndroidJUnit4 | ||
import androidx.test.platform.app.InstrumentationRegistry | ||
import com.mapbox.navigation.base.options.NavigationOptions | ||
import com.mapbox.navigation.base.route.NavigationRoute | ||
import com.mapbox.navigation.base.route.RouterOrigin | ||
import com.mapbox.navigation.core.MapboxNavigation | ||
import com.mapbox.navigation.core.MapboxNavigationProvider | ||
import com.mapbox.navigation.core.navigator.toFixLocation | ||
import com.mapbox.navigation.core.replay.history.ReplayEventUpdateLocation | ||
import com.mapbox.navigation.core.replay.history.mapToLocation | ||
import com.mapbox.navigation.core.replay.route.ReplayRouteMapper | ||
import com.mapbox.navigation.core.test.R | ||
import com.mapbox.navigation.navigator.internal.MapboxNativeNavigator | ||
import com.mapbox.navigation.navigator.internal.MapboxNativeNavigatorImpl | ||
import com.mapbox.navigator.NavigationStatus | ||
import com.mapbox.navigator.NavigationStatusOrigin | ||
import com.mapbox.navigator.NavigatorObserver | ||
import com.mapbox.navigator.RouteState | ||
import com.mapbox.navigator.SetRoutesReason | ||
import kotlinx.coroutines.Dispatchers | ||
import kotlinx.coroutines.ExperimentalCoroutinesApi | ||
import kotlinx.coroutines.async | ||
import kotlinx.coroutines.channels.awaitClose | ||
import kotlinx.coroutines.flow.Flow | ||
import kotlinx.coroutines.flow.callbackFlow | ||
import kotlinx.coroutines.flow.map | ||
import kotlinx.coroutines.flow.takeWhile | ||
import kotlinx.coroutines.flow.toList | ||
import kotlinx.coroutines.runBlocking | ||
import org.junit.Assert.assertTrue | ||
import org.junit.Ignore | ||
import org.junit.Test | ||
import org.junit.runner.RunWith | ||
import kotlin.coroutines.resume | ||
import kotlin.coroutines.suspendCoroutine | ||
|
||
@RunWith(AndroidJUnit4::class) | ||
class ArtificialDriverTest { | ||
|
||
@Test | ||
@Ignore("test sometimes fails because of https://mapbox.atlassian.net/browse/NN-418") | ||
fun nativeNavigatorFollowsArtificialDriverWithoutReroutes() = | ||
runBlocking<Unit>(Dispatchers.Main) { | ||
withNavigators { mapboxNavigation, nativeNavigator -> | ||
mapboxNavigation.historyRecorder.startRecording() | ||
val testRoute = getTestRoute() | ||
val events = createArtificialLocationUpdates(testRoute) | ||
val setRoutesResult = | ||
nativeNavigator.setRoutes(testRoute, reason = SetRoutesReason.NEW_ROUTE) | ||
assertTrue("result is $setRoutesResult", setRoutesResult.isValue) | ||
val statusesTracking = async<List<NavigationStatus>> { | ||
nativeNavigator.collectStatuses(untilRouteState = RouteState.COMPLETE) | ||
} | ||
|
||
for (location in events.map { it.location.mapToLocation() }) { | ||
assertTrue(nativeNavigator.updateLocation(location.toFixLocation())) | ||
} | ||
|
||
val states = statusesTracking.await() | ||
val historyFile = suspendCoroutine<String> { continuation -> | ||
mapboxNavigation.historyRecorder.stopRecording { | ||
continuation.resume(it ?: "null") | ||
} | ||
} | ||
val offRouteState = states.filter { it.routeState == RouteState.OFF_ROUTE } | ||
assertTrue( | ||
"${offRouteState.size} off-route states have been detected(" + | ||
"more info in $historyFile): $offRouteState", | ||
offRouteState.isEmpty() | ||
) | ||
} | ||
} | ||
} | ||
|
||
private fun createArtificialLocationUpdates( | ||
testRoute: NavigationRoute | ||
): List<ReplayEventUpdateLocation> { | ||
val replayRouteMapper = ReplayRouteMapper() | ||
return replayRouteMapper | ||
.mapDirectionsRouteGeometry(testRoute.directionsRoute) | ||
.filterIsInstance<ReplayEventUpdateLocation>() | ||
} | ||
|
||
private suspend fun MapboxNativeNavigator.collectStatuses( | ||
untilRouteState: RouteState | ||
): MutableList<NavigationStatus> { | ||
val statues = mutableListOf<NavigationStatus>() | ||
statusUpdates() | ||
.map { it.status } | ||
.takeWhile { it.routeState != untilRouteState } | ||
.toList(statues) | ||
return statues | ||
} | ||
|
||
data class OnStatusUpdateParameters( | ||
val origin: NavigationStatusOrigin, | ||
val status: NavigationStatus | ||
) | ||
|
||
@OptIn(ExperimentalCoroutinesApi::class) | ||
fun MapboxNativeNavigator.statusUpdates(): Flow<OnStatusUpdateParameters> { | ||
return callbackFlow { | ||
val observer = NavigatorObserver { origin, status -> | ||
this.trySend(OnStatusUpdateParameters(origin, status)) | ||
} | ||
addNavigatorObserver(observer) | ||
awaitClose { | ||
removeNavigatorObserver(observer) | ||
} | ||
} | ||
} | ||
|
||
private suspend fun withNavigators( | ||
block: suspend (MapboxNavigation, MapboxNativeNavigator) -> Unit | ||
) { | ||
val context = InstrumentationRegistry.getInstrumentation().targetContext | ||
val mapboxNavigation = MapboxNavigationProvider.create( | ||
NavigationOptions.Builder(context) | ||
.accessToken(context.getString(R.string.mapbox_access_token)) | ||
.build() | ||
) | ||
try { | ||
block(mapboxNavigation, MapboxNativeNavigatorImpl) | ||
} finally { | ||
mapboxNavigation.onDestroy() | ||
} | ||
} | ||
|
||
private fun getTestRoute(): NavigationRoute { | ||
val context = InstrumentationRegistry.getInstrumentation().targetContext | ||
return NavigationRoute.create( | ||
directionsResponseJson = context.resources.openRawResource(R.raw.test_long_route) | ||
.readBytes().decodeToString(), | ||
routeRequestUrl = "https://api.mapbox.com/directions/v5/mapbox/driving/" + | ||
"11.566744%2C48.143769%3B8.675521%2C50.119087" + | ||
"?alternatives=false" + | ||
"&geometries=polyline6" + | ||
"&language=en" + | ||
"&overview=full" + | ||
"&steps=true" + | ||
"&access_token=YOUR_MAPBOX_ACCESS_TOKEN", | ||
routerOrigin = RouterOrigin.Custom() | ||
).first() | ||
} |
Oops, something went wrong.