mirror of
https://github.com/meshtastic/Meshtastic-Android.git
synced 2026-04-20 22:23:37 +00:00
refactor: coroutine dispatchers and modernize testing infrastructure (#4901)
Some checks are pending
Dependency Submission / dependency-submission (push) Waiting to run
Main CI (Verify & Build) / validate-and-build (push) Waiting to run
Main Push Changelog / Generate main push changelog (push) Waiting to run
Some checks are pending
Dependency Submission / dependency-submission (push) Waiting to run
Main CI (Verify & Build) / validate-and-build (push) Waiting to run
Main Push Changelog / Generate main push changelog (push) Waiting to run
Signed-off-by: James Rich <2199651+jamesarich@users.noreply.github.com>
This commit is contained in:
parent
664ebf218e
commit
96060a0a4d
36 changed files with 621 additions and 182 deletions
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Copyright (c) 2026 Meshtastic LLC
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.meshtastic.core.testing
|
||||
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import org.meshtastic.core.repository.MeshLogPrefs
|
||||
|
||||
class FakeMeshLogPrefs : MeshLogPrefs {
|
||||
private val _retentionDays = MutableStateFlow(MeshLogPrefs.DEFAULT_RETENTION_DAYS)
|
||||
override val retentionDays = _retentionDays
|
||||
|
||||
override fun setRetentionDays(days: Int) {
|
||||
_retentionDays.value = days
|
||||
}
|
||||
|
||||
private val _loggingEnabled = MutableStateFlow(true)
|
||||
override val loggingEnabled = _loggingEnabled
|
||||
|
||||
override fun setLoggingEnabled(enabled: Boolean) {
|
||||
_loggingEnabled.value = enabled
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* Copyright (c) 2026 Meshtastic LLC
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.meshtastic.core.testing
|
||||
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.map
|
||||
import org.meshtastic.core.model.MeshLog
|
||||
import org.meshtastic.core.repository.MeshLogRepository
|
||||
import org.meshtastic.proto.MeshPacket
|
||||
import org.meshtastic.proto.MyNodeInfo
|
||||
import org.meshtastic.proto.PortNum
|
||||
import org.meshtastic.proto.Telemetry
|
||||
|
||||
@Suppress("TooManyFunctions")
|
||||
class FakeMeshLogRepository : MeshLogRepository {
|
||||
private val logsFlow = MutableStateFlow<List<MeshLog>>(emptyList())
|
||||
val currentLogs: List<MeshLog>
|
||||
get() = logsFlow.value
|
||||
|
||||
var deleteLogsOlderThanCalledDays: Int? = null
|
||||
|
||||
override fun getAllLogs(maxItem: Int): Flow<List<MeshLog>> = logsFlow.map { it.take(maxItem) }
|
||||
|
||||
override fun getAllLogsInReceiveOrder(maxItem: Int): Flow<List<MeshLog>> = logsFlow.map { it.take(maxItem) }
|
||||
|
||||
override fun getAllLogsUnbounded(): Flow<List<MeshLog>> = logsFlow
|
||||
|
||||
override fun getLogsFrom(nodeNum: Int, portNum: Int): Flow<List<MeshLog>> = logsFlow.map {
|
||||
it.filter { log -> log.fromNum == nodeNum && log.portNum == portNum }
|
||||
}
|
||||
|
||||
override fun getMeshPacketsFrom(nodeNum: Int, portNum: Int): Flow<List<MeshPacket>> = MutableStateFlow(emptyList())
|
||||
|
||||
override fun getTelemetryFrom(nodeNum: Int): Flow<List<Telemetry>> = MutableStateFlow(emptyList())
|
||||
|
||||
override fun getRequestLogs(targetNodeNum: Int, portNum: PortNum): Flow<List<MeshLog>> =
|
||||
MutableStateFlow(emptyList())
|
||||
|
||||
override fun getMyNodeInfo(): Flow<MyNodeInfo?> = MutableStateFlow(null)
|
||||
|
||||
override suspend fun insert(log: MeshLog) {
|
||||
logsFlow.value = logsFlow.value + log
|
||||
}
|
||||
|
||||
override suspend fun deleteAll() {
|
||||
logsFlow.value = emptyList()
|
||||
}
|
||||
|
||||
override suspend fun deleteLog(uuid: String) {
|
||||
logsFlow.value = logsFlow.value.filter { it.uuid != uuid }
|
||||
}
|
||||
|
||||
override suspend fun deleteLogs(nodeNum: Int, portNum: Int) {
|
||||
logsFlow.value = logsFlow.value.filterNot { it.fromNum == nodeNum && it.portNum == portNum }
|
||||
}
|
||||
|
||||
override suspend fun deleteLogsOlderThan(retentionDays: Int) {
|
||||
deleteLogsOlderThanCalledDays = retentionDays
|
||||
}
|
||||
|
||||
fun setLogs(logs: List<MeshLog>) {
|
||||
logsFlow.value = logs
|
||||
}
|
||||
}
|
||||
|
|
@ -52,6 +52,7 @@ class FakeRadioController : RadioController {
|
|||
val favoritedNodes = mutableListOf<Int>()
|
||||
val sentSharedContacts = mutableListOf<Int>()
|
||||
var throwOnSend: Boolean = false
|
||||
var lastSetDeviceAddress: String? = null
|
||||
|
||||
override suspend fun sendMessage(packet: DataPacket) {
|
||||
if (throwOnSend) error("Fake send failure")
|
||||
|
|
@ -136,7 +137,9 @@ class FakeRadioController : RadioController {
|
|||
|
||||
override fun stopProvideLocation() {}
|
||||
|
||||
override fun setDeviceAddress(address: String) {}
|
||||
override fun setDeviceAddress(address: String) {
|
||||
lastSetDeviceAddress = address
|
||||
}
|
||||
|
||||
// --- Helper methods for testing ---
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
* Copyright (c) 2026 Meshtastic LLC
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.meshtastic.core.testing
|
||||
|
||||
import co.touchlab.kermit.Severity
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.SharedFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import org.meshtastic.core.model.ConnectionState
|
||||
import org.meshtastic.core.model.service.ServiceAction
|
||||
import org.meshtastic.core.model.service.TracerouteResponse
|
||||
import org.meshtastic.core.repository.ServiceRepository
|
||||
import org.meshtastic.proto.ClientNotification
|
||||
import org.meshtastic.proto.MeshPacket
|
||||
|
||||
@Suppress("TooManyFunctions")
|
||||
class FakeServiceRepository : ServiceRepository {
|
||||
private val _connectionState = MutableStateFlow<ConnectionState>(ConnectionState.Disconnected)
|
||||
override val connectionState: StateFlow<ConnectionState> = _connectionState
|
||||
|
||||
override fun setConnectionState(connectionState: ConnectionState) {
|
||||
_connectionState.value = connectionState
|
||||
}
|
||||
|
||||
private val _clientNotification = MutableStateFlow<ClientNotification?>(null)
|
||||
override val clientNotification: StateFlow<ClientNotification?> = _clientNotification
|
||||
|
||||
override fun setClientNotification(notification: ClientNotification?) {
|
||||
_clientNotification.value = notification
|
||||
}
|
||||
|
||||
override fun clearClientNotification() {
|
||||
_clientNotification.value = null
|
||||
}
|
||||
|
||||
private val _errorMessage = MutableStateFlow<String?>(null)
|
||||
override val errorMessage: StateFlow<String?> = _errorMessage
|
||||
|
||||
override fun setErrorMessage(text: String, severity: Severity) {
|
||||
_errorMessage.value = text
|
||||
}
|
||||
|
||||
override fun clearErrorMessage() {
|
||||
_errorMessage.value = null
|
||||
}
|
||||
|
||||
private val _connectionProgress = MutableStateFlow<String?>(null)
|
||||
override val connectionProgress: StateFlow<String?> = _connectionProgress
|
||||
|
||||
override fun setConnectionProgress(text: String) {
|
||||
_connectionProgress.value = text
|
||||
}
|
||||
|
||||
private val _meshPacketFlow = MutableSharedFlow<MeshPacket>()
|
||||
override val meshPacketFlow: SharedFlow<MeshPacket> = _meshPacketFlow
|
||||
|
||||
override suspend fun emitMeshPacket(packet: MeshPacket) {
|
||||
_meshPacketFlow.emit(packet)
|
||||
}
|
||||
|
||||
private val _tracerouteResponse = MutableStateFlow<TracerouteResponse?>(null)
|
||||
override val tracerouteResponse: StateFlow<TracerouteResponse?> = _tracerouteResponse
|
||||
|
||||
override fun setTracerouteResponse(value: TracerouteResponse?) {
|
||||
_tracerouteResponse.value = value
|
||||
}
|
||||
|
||||
override fun clearTracerouteResponse() {
|
||||
_tracerouteResponse.value = null
|
||||
}
|
||||
|
||||
private val _neighborInfoResponse = MutableStateFlow<String?>(null)
|
||||
override val neighborInfoResponse: StateFlow<String?> = _neighborInfoResponse
|
||||
|
||||
override fun setNeighborInfoResponse(value: String?) {
|
||||
_neighborInfoResponse.value = value
|
||||
}
|
||||
|
||||
override fun clearNeighborInfoResponse() {
|
||||
_neighborInfoResponse.value = null
|
||||
}
|
||||
|
||||
private val _serviceAction = MutableSharedFlow<ServiceAction>(replay = 1)
|
||||
override val serviceAction: Flow<ServiceAction> = _serviceAction
|
||||
|
||||
override suspend fun onServiceAction(action: ServiceAction) {
|
||||
_serviceAction.emit(action)
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue