Skip to content
This repository has been archived by the owner on Jun 22, 2022. It is now read-only.

Commit

Permalink
Merge pull request #221 from Ph0tonic/feature/droneMeasures
Browse files Browse the repository at this point in the history
Implement Drone measures callback
  • Loading branch information
AlexisTabin authored Jun 5, 2020
2 parents 65b936a + b3fff7f commit 93dd3f6
Show file tree
Hide file tree
Showing 21 changed files with 152 additions and 105 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import androidx.test.uiautomator.UiDevice
import androidx.test.uiautomator.UiObject
import androidx.test.uiautomator.UiSelector
import ch.epfl.sdp.database.data_manager.MainDataManager
import ch.epfl.sdp.ui.drone.DroneInstanceMock
import ch.epfl.sdp.drone.DroneInstanceMock
import ch.epfl.sdp.ui.MainActivity
import ch.epfl.sdp.utils.CentralLocationManager
import org.hamcrest.CoreMatchers.equalTo
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import ch.epfl.sdp.database.data.HeatmapData
import ch.epfl.sdp.database.data.HeatmapPointData
import ch.epfl.sdp.database.providers.HeatmapRepositoryProvider
import ch.epfl.sdp.database.repository.IHeatmapRepository
import ch.epfl.sdp.utils.Auth
import com.mapbox.mapboxsdk.geometry.LatLng
import org.hamcrest.CoreMatchers.equalTo
import org.hamcrest.MatcherAssert.assertThat
Expand All @@ -23,7 +24,6 @@ class HeatmapDataManagerTest {
private val DUMMY_LOCATION = LatLng(0.123, 23.1234)
}


@get:Rule
val instantTaskExecutorRule = InstantTaskExecutorRule()

Expand All @@ -34,11 +34,13 @@ class HeatmapDataManagerTest {
), DUMMY_HEATMAP_ID)
val expectedGroupId = DUMMY_GROUP_ID

Auth.accountId.value = DUMMY_HEATMAP_ID

val repo = Mockito.mock(IHeatmapRepository::class.java)
Mockito.`when`(repo.getGroupHeatmaps(expectedGroupId)).thenReturn(MutableLiveData(mutableMapOf()))

HeatmapRepositoryProvider.provide = { repo }
HeatmapDataManager().addMeasureToHeatmap(DUMMY_GROUP_ID, DUMMY_HEATMAP_ID, DUMMY_LOCATION, DUMMY_INTENSITY)
HeatmapDataManager().addMeasureToHeatmap(DUMMY_GROUP_ID, DUMMY_LOCATION, DUMMY_INTENSITY)

Mockito.verify(repo, Mockito.times(1)).getGroupHeatmaps(expectedGroupId)
Mockito.verify(repo, Mockito.times(1)).updateHeatmap(expectedGroupId, expectedHeatMapData)
Expand All @@ -52,11 +54,13 @@ class HeatmapDataManagerTest {
val expectedGroupId = DUMMY_GROUP_ID
val previousHeatMapData = HeatmapData(mutableListOf(), DUMMY_HEATMAP_ID)

Auth.accountId.value = DUMMY_HEATMAP_ID

val repo = Mockito.mock(IHeatmapRepository::class.java)
Mockito.`when`(repo.getGroupHeatmaps(expectedGroupId)).thenReturn(MutableLiveData(mutableMapOf(Pair(DUMMY_HEATMAP_ID, MutableLiveData(previousHeatMapData)))))

HeatmapRepositoryProvider.provide = { repo }
HeatmapDataManager().addMeasureToHeatmap(DUMMY_GROUP_ID, DUMMY_HEATMAP_ID, DUMMY_LOCATION, DUMMY_INTENSITY)
HeatmapDataManager().addMeasureToHeatmap(DUMMY_GROUP_ID, DUMMY_LOCATION, DUMMY_INTENSITY)

Mockito.verify(repo, Mockito.times(1)).getGroupHeatmaps(expectedGroupId)
Mockito.verify(repo, Mockito.times(1)).updateHeatmap(expectedGroupId, expectedHeatMapData)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,28 +1,16 @@
package ch.epfl.sdp.ui.drone

import android.content.Intent
import androidx.test.espresso.Espresso
import androidx.test.espresso.assertion.ViewAssertions
import androidx.test.espresso.intent.rule.IntentsTestRule
import androidx.test.espresso.matcher.RootMatchers
import androidx.test.espresso.matcher.ViewMatchers
package ch.epfl.sdp.drone

import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.internal.runner.junit4.statement.UiThreadStatement.runOnUiThread
import ch.epfl.sdp.MainApplication
import ch.epfl.sdp.R
import ch.epfl.sdp.drone.Drone
import ch.epfl.sdp.drone.DroneUtils
import ch.epfl.sdp.ui.MainActivity
import ch.epfl.sdp.utils.CentralLocationManager
import com.mapbox.mapboxsdk.geometry.LatLng
import io.mavsdk.telemetry.Telemetry
import io.reactivex.Completable
import org.hamcrest.CoreMatchers
import io.reactivex.Flowable
import org.hamcrest.MatcherAssert.assertThat
import org.hamcrest.Matchers.`is`
import org.hamcrest.Matchers.nullValue
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentMatchers
Expand All @@ -34,6 +22,7 @@ class DroneErrorTest {

companion object {
private const val DEFAULT_ALTITUDE = 10f
private const val DUMMY_GROUP_ID = "dummy_group_id"
val someLocationsList = listOf(
LatLng(47.398979, 8.543434),
LatLng(47.398279, 8.543934),
Expand All @@ -42,12 +31,6 @@ class DroneErrorTest {
)
}

@get:Rule
val mActivityRule = IntentsTestRule(
MainActivity::class.java,
true,
false)

@Before
fun before() {
DroneInstanceMock.setupDefaultMocks()
Expand All @@ -64,12 +47,14 @@ class DroneErrorTest {
.thenReturn(Completable.error(Throwable("Error StartMission")))
`when`(DroneInstanceMock.droneMission.clearMission())
.thenReturn(Completable.error(Throwable("Error Clear Mission")))
`when`(DroneInstanceMock.droneMission.missionProgress)
.thenReturn(Flowable.empty())
}

@Test
fun failToStartMissionResetMission() {
runOnUiThread {
Drone.startMission(DroneUtils.makeDroneMission(someLocationsList, DEFAULT_ALTITUDE))
Drone.startMission(DroneUtils.makeDroneMission(someLocationsList, DEFAULT_ALTITUDE), DUMMY_GROUP_ID)
}

assertThat(Drone.isMissionPausedLiveData.value, `is`(true))
Expand All @@ -91,7 +76,7 @@ class DroneErrorTest {
}

@Test
fun failToRestartMissionResetsMissionStatus() {
fun failToResumeMissionResetsMissionStatus() {
runOnUiThread {
Drone.isFlyingLiveData.value = true
Drone.isMissionPausedLiveData.value = true
Expand All @@ -113,12 +98,7 @@ class DroneErrorTest {
}

@Test
fun failToReturnToUserShowsToast() {
runOnUiThread{
CentralLocationManager.currentUserPosition.value = LatLng(0.0, 0.0)
}
mActivityRule.launchActivity(Intent())

fun failToReturnToUserResetMission() {
Mockito.reset(DroneInstanceMock.droneAction)

//Action mocks
Expand All @@ -135,11 +115,10 @@ class DroneErrorTest {
`when`(DroneInstanceMock.droneAction.land())
.thenReturn(Completable.complete())

Drone.returnToUserLocationAndLand()

// Test that the toast is displayed
Espresso.onView(ViewMatchers.withText(MainApplication.applicationContext().getString(R.string.drone_user_error)))
.inRoot(RootMatchers.withDecorView(CoreMatchers.not(mActivityRule.activity.window.decorView)))
.check(ViewAssertions.matches(ViewMatchers.isDisplayed()))
runOnUiThread {
CentralLocationManager.currentUserPosition.value = LatLng(0.0, 0.0)
Drone.returnToUserLocationAndLand()
}
assertThat(Drone.missionLiveData.value, `is`(nullValue()))
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package ch.epfl.sdp.ui.drone
package ch.epfl.sdp.drone

import ch.epfl.sdp.drone.DroneInstanceProvider
import io.mavsdk.System
import io.mavsdk.action.Action
import io.mavsdk.core.Core
Expand All @@ -13,11 +12,11 @@ import org.mockito.Mockito
import org.mockito.Mockito.`when`

object DroneInstanceMock {
val droneSystem = Mockito.mock(System::class.java)
val droneTelemetry = Mockito.mock(Telemetry::class.java)
val droneCore = Mockito.mock(Core::class.java)
val droneMission = Mockito.mock(Mission::class.java)
val droneAction = Mockito.mock(Action::class.java)
val droneSystem: System = Mockito.mock(System::class.java)
val droneTelemetry: Telemetry = Mockito.mock(Telemetry::class.java)
val droneCore: Core = Mockito.mock(Core::class.java)
val droneMission: Mission = Mockito.mock(Mission::class.java)
val droneAction: Action = Mockito.mock(Action::class.java)

init {
DroneInstanceProvider.provide = {
Expand All @@ -42,15 +41,19 @@ object DroneInstanceMock {
.thenReturn(Flowable.fromArray(
Telemetry.FlightMode.LAND,
Telemetry.FlightMode.MISSION,
Telemetry.FlightMode.HOLD
Telemetry.FlightMode.HOLD,
Telemetry.FlightMode.MISSION
))
`when`(droneTelemetry.armed)
.thenReturn(Flowable.fromArray(
true
))
`when`(droneTelemetry.position)
.thenReturn(Flowable.fromArray(
Telemetry.Position(0.0, 0.0, 0.0f, 0.0f)
Telemetry.Position(0.0, 0.0, 0.0f, 0.0f),
Telemetry.Position(0.1, 0.0, 0.0f, 0.0f),
Telemetry.Position(0.2, 0.0, 0.0f, 0.0f),
Telemetry.Position(0.3, 0.0, 0.0f, 0.0f)
))
`when`(droneTelemetry.battery)
.thenReturn(Flowable.fromArray(
Expand Down Expand Up @@ -89,6 +92,14 @@ object DroneInstanceMock {
.thenReturn(Completable.complete())
`when`(droneMission.clearMission())
.thenReturn(Completable.complete())
`when`(droneMission.missionProgress)
.thenReturn(Flowable.fromArray(
Mission.MissionProgress(0, 4),
Mission.MissionProgress(1, 4),
Mission.MissionProgress(2, 4),
Mission.MissionProgress(3, 4),
Mission.MissionProgress(4, 4)
))

//Action mocks
`when`(droneAction.arm())
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
package ch.epfl.sdp.ui.drone
package ch.epfl.sdp.drone

import androidx.arch.core.executor.testing.InstantTaskExecutorRule
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.rule.ActivityTestRule
import ch.epfl.sdp.database.data_manager.MainDataManager
import ch.epfl.sdp.drone.Drone
import ch.epfl.sdp.drone.DroneUtils
import ch.epfl.sdp.ui.maps.MapActivity
import ch.epfl.sdp.utils.CentralLocationManager
import com.mapbox.mapboxsdk.geometry.LatLng
import io.mavsdk.telemetry.Telemetry
Expand All @@ -16,15 +12,24 @@ import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mockito


@RunWith(AndroidJUnit4::class)
class DroneTest {

private fun <T> any(): T {
Mockito.any<T>()
return uninitialized()
}

private fun <T> uninitialized(): T = null as T

companion object {
const val SIGNAL_STRENGTH = 1.0
private const val EPSILON = 1e-5
private const val DEFAULT_ALTITUDE = 10f
private const val DUMMY_GROUP_ID = "dummy_group_id"
val someLocationsList = listOf(
LatLng(47.398979, 8.543434),
LatLng(47.398279, 8.543934),
Expand All @@ -36,13 +41,6 @@ class DroneTest {
@get:Rule
val instantTaskExecutorRule = InstantTaskExecutorRule()

@get:Rule
var mActivityRule = ActivityTestRule(
MapActivity::class.java,
true,
false) // Activity is not launched immediately


@Before
fun before() {
DroneInstanceMock.setupDefaultMocks()
Expand All @@ -57,13 +55,13 @@ class DroneTest {
}

@Test
fun missionTestDoesNotCrash() {
fun startMissionUpdatesLiveData() {
Drone.missionLiveData.value = null
assertThat(Drone.missionLiveData.value, `is`(nullValue()))

Drone.startMission(DroneUtils.makeDroneMission(someLocationsList, DEFAULT_ALTITUDE))
Drone.startMission(DroneUtils.makeDroneMission(someLocationsList, DEFAULT_ALTITUDE), DUMMY_GROUP_ID)

// This assert prevent the app to crash in cash the mission has not been updated
// This assert prevent the app to crash in case the mission has not been updated
assertThat(Drone.missionLiveData.value, `is`(notNullValue()))
assertThat(Drone.missionLiveData.value?.isEmpty(), `is`(false))
}
Expand All @@ -75,7 +73,7 @@ class DroneTest {
Drone.positionLiveData.value = expectedLatLng
Drone.homeLocationLiveData.value =
Telemetry.Position(expectedLatLng.latitude, expectedLatLng.longitude, 400f, 50f)
Drone.startMission(DroneUtils.makeDroneMission(someLocationsList, DEFAULT_ALTITUDE))
Drone.startMission(DroneUtils.makeDroneMission(someLocationsList, DEFAULT_ALTITUDE), DUMMY_GROUP_ID)

Drone.returnToHomeLocationAndLand()

Expand All @@ -98,7 +96,7 @@ class DroneTest {
val expectedLatLng = LatLng(47.297428, 8.445369) //Position near the takeoff
CentralLocationManager.currentUserPosition.value = expectedLatLng

Drone.startMission(DroneUtils.makeDroneMission(someLocationsList, DEFAULT_ALTITUDE))
Drone.startMission(DroneUtils.makeDroneMission(someLocationsList, DEFAULT_ALTITUDE), DUMMY_GROUP_ID)

assertThat(CentralLocationManager.currentUserPosition.value, `is`(notNullValue()))
Drone.returnToUserLocationAndLand()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package ch.epfl.sdp.drone

import ch.epfl.sdp.ui.drone.DroneInstanceMock
import com.mapbox.mapboxsdk.geometry.LatLng
import io.mavsdk.mission.Mission
import org.junit.Assert
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import ch.epfl.sdp.database.repository.HeatmapRepository
import ch.epfl.sdp.database.repository.MarkerRepository
import ch.epfl.sdp.database.repository.SearchGroupRepository
import ch.epfl.sdp.database.repository.UserRepository
import ch.epfl.sdp.ui.drone.DroneInstanceMock
import ch.epfl.sdp.drone.DroneInstanceMock
import ch.epfl.sdp.ui.settings.SettingsActivity
import ch.epfl.sdp.utils.Auth
import org.hamcrest.CoreMatchers.*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import ch.epfl.sdp.database.repository.MarkerRepository
import ch.epfl.sdp.database.repository.SearchGroupRepository
import ch.epfl.sdp.database.repository.UserRepository
import ch.epfl.sdp.drone.Drone
import ch.epfl.sdp.drone.DroneInstanceMock
import ch.epfl.sdp.ui.maps.MapActivity
import ch.epfl.sdp.utils.Auth
import ch.epfl.sdp.utils.CentralLocationManager
Expand All @@ -47,7 +48,6 @@ class DroneStatusFragmentTest {
private const val DEFAULT_ALTITUDE_DISPLAY = " 0.0 m"
private const val FAKE_ACCOUNT_ID = "fake_account_id"
private const val DUMMY_GROUP_ID = "DummyGroupId"
private const val MAP_LOADING_TIMEOUT = 1000L
}

private lateinit var preferencesEditor: SharedPreferences.Editor
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import ch.epfl.sdp.database.repository.MarkerRepository
import ch.epfl.sdp.database.repository.SearchGroupRepository
import ch.epfl.sdp.database.repository.UserRepository
import ch.epfl.sdp.drone.Drone
import ch.epfl.sdp.drone.DroneInstanceMock
import ch.epfl.sdp.ui.maps.MapActivity
import ch.epfl.sdp.utils.Auth
import ch.epfl.sdp.utils.CentralLocationManager
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import androidx.test.rule.GrantPermissionRule.grant
import androidx.test.uiautomator.UiDevice
import ch.epfl.sdp.MainApplication
import ch.epfl.sdp.R
import ch.epfl.sdp.ui.drone.DroneInstanceMock
import ch.epfl.sdp.drone.DroneInstanceMock
import ch.epfl.sdp.ui.MainActivity
import ch.epfl.sdp.utils.Auth
import com.google.android.gms.auth.api.signin.GoogleSignIn
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ import ch.epfl.sdp.drone.Drone
import ch.epfl.sdp.mission.SimpleQuadStrategy
import ch.epfl.sdp.mission.SpiralStrategy
import ch.epfl.sdp.searcharea.QuadrilateralArea
import ch.epfl.sdp.ui.drone.DroneInstanceMock
import ch.epfl.sdp.drone.DroneInstanceMock
import ch.epfl.sdp.ui.maps.offline.OfflineManagerActivity
import ch.epfl.sdp.utils.Auth
import ch.epfl.sdp.utils.CentralLocationManager
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import androidx.test.uiautomator.UiDevice
import androidx.test.uiautomator.Until
import ch.epfl.sdp.MainApplication.Companion.applicationContext
import ch.epfl.sdp.R
import ch.epfl.sdp.ui.drone.DroneInstanceMock
import ch.epfl.sdp.drone.DroneInstanceMock
import ch.epfl.sdp.map.MapUtils.getCameraWithParameters
import ch.epfl.sdp.map.offline.OfflineRegionUtils.getRegionName
import com.mapbox.mapboxsdk.geometry.LatLng
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import ch.epfl.sdp.database.data.Role
import ch.epfl.sdp.database.data_manager.MainDataManager
import ch.epfl.sdp.database.repository.HeatmapRepository
import ch.epfl.sdp.database.repository.MarkerRepository
import ch.epfl.sdp.ui.drone.DroneInstanceMock
import ch.epfl.sdp.drone.DroneInstanceMock
import ch.epfl.sdp.ui.maps.MapActivity
import org.hamcrest.CoreMatchers.equalTo
import org.hamcrest.MatcherAssert.assertThat
Expand Down
Loading

0 comments on commit 93dd3f6

Please sign in to comment.