Skip to content

Commit 83deb79

Browse files
committed
[WIP] combine multiple tests to one test
1 parent b04f94e commit 83deb79

File tree

8 files changed

+130
-106
lines changed

8 files changed

+130
-106
lines changed

app/src/main/java/com/lcl/lclmeasurementtool/MainActivityViewModel.kt

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import com.lcl.lclmeasurementtool.model.datamodel.UserData
2828
import com.lcl.lclmeasurementtool.model.repository.NetworkApiRepository
2929
import com.lcl.lclmeasurementtool.model.repository.UserDataRepository
3030
import dagger.hilt.android.lifecycle.HiltViewModel
31+
import dagger.hilt.android.qualifiers.ApplicationContext
3132
import kotlinx.coroutines.*
3233
import kotlinx.coroutines.flow.*
3334
import java.io.ByteArrayOutputStream
@@ -198,17 +199,18 @@ class MainActivityViewModel @Inject constructor(
198199

199200

200201
// Network Testing
202+
private val jobs = mutableListOf<Job>()
201203
private var _pingResult = MutableStateFlow(PingResultState())
202204
private var _downloadResult = MutableStateFlow(ConnectivityTestResult())
203205
private var _uploadResult = MutableStateFlow(ConnectivityTestResult())
206+
private val _isTestActive = MutableStateFlow(false)
204207

205208

206209
val pingResult: StateFlow<PingResultState> = _pingResult.asStateFlow()
207210
var downloadResult: StateFlow<ConnectivityTestResult> = _downloadResult.asStateFlow()
208211
var uploadResult: StateFlow<ConnectivityTestResult> = _uploadResult.asStateFlow()
209212

210213

211-
private val _isTestActive = MutableStateFlow(false)
212214
val isTestActive = _isTestActive.asStateFlow()
213215

214216
fun doPing() = viewModelScope.launch {
@@ -219,19 +221,17 @@ class MainActivityViewModel @Inject constructor(
219221
_isTestActive.value = true
220222
}
221223
.onCompletion {
222-
Log.d(TAG, "isActive = false")
223-
_isTestActive.value = false
224224
if (it != null) {
225225
// save to DB and send over the network
226226
Log.d(TAG, "Error is ${it.message}")
227+
} else {
228+
_isTestActive.value = false
227229
}
228230
}
229231
.collect {
230-
ensureActive()
231-
Log.d(TAG, "Test is still active")
232-
when(it.error.code) {
233-
PingErrorCase.OK -> _pingResult.value = PingResultState.Success(it)
234-
else -> _pingResult.value = PingResultState.Error(it.error)
232+
_pingResult.value = when(it.error.code) {
233+
PingErrorCase.OK -> PingResultState.Success(it)
234+
else -> PingResultState.Error(it.error)
235235
}
236236
}
237237
} catch (e: IllegalArgumentException) {
@@ -243,8 +243,6 @@ class MainActivityViewModel @Inject constructor(
243243
fun getUploadResult(context: Context) = viewModelScope.launch {
244244
IperfRunner().getTestResult(IperfRunner.iperfUploadConfig, context.cacheDir)
245245
.collect { result ->
246-
ensureActive()
247-
248246
_uploadResult.value = when(result.status) {
249247
IperfStatus.RUNNING -> ConnectivityTestResult.Result(result.bandWidth, Color.LightGray)
250248
IperfStatus.FINISHED -> ConnectivityTestResult.Result(result.bandWidth, Color.Black)
@@ -261,8 +259,6 @@ class MainActivityViewModel @Inject constructor(
261259
// TODO: write data to the database
262260
}
263261
.collect { result ->
264-
ensureActive()
265-
266262
_downloadResult.value = when(result.status) {
267263
IperfStatus.RUNNING -> ConnectivityTestResult.Result(result.bandWidth, Color.LightGray)
268264
IperfStatus.FINISHED -> ConnectivityTestResult.Result(result.bandWidth, Color.Black)
@@ -271,6 +267,13 @@ class MainActivityViewModel @Inject constructor(
271267
}
272268
}
273269

270+
fun doIperf(context: Context) = viewModelScope.launch {
271+
val uploadJob = getUploadResult(context = context)
272+
jobs.add(uploadJob)
273+
uploadJob.join()
274+
val downloadJob = getDownloadResult(context = context)
275+
jobs.add(downloadJob)
276+
}
274277
}
275278

276279
sealed interface MainActivityUiState {

app/src/main/java/com/lcl/lclmeasurementtool/constants/IperfConstants.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ class IperfConstants {
1111

1212
// the SSL key
1313
// TODO: hide it
14-
var IC_SSL_PK = """
14+
var IC_SSL_PK: String = """
1515
-----BEGIN PUBLIC KEY-----
1616
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwt8Pvsja7c6Co8nsyrCc
1717
qCYz3liIEUYS1QaoMgefQHRUoIVVi8Gh7/ZAzu6+Jfl/b0qhIb9vgbdKhSYM7lfB
@@ -29,7 +29,7 @@ class IperfConstants {
2929
const val IC_serverAddr = "othello-iperf.westus2.cloudapp.azure.com"
3030
const val IC_serverPort = 40404
3131

32-
fun base64Encode(input: String): String? {
32+
fun base64Encode(input: String): String {
3333
val buffer = input.toByteArray(StandardCharsets.US_ASCII)
3434
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
3535
// return the correct encoding for iperf

app/src/main/java/com/lcl/lclmeasurementtool/features/iperf/IperfClient.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ public void exec(IperfConfig testConfig, IperfCallback callback, File cacheDir)
4949
// TODO(matt9j) Propagate the error cause in the exception
5050
throw new RuntimeException("Iperf test failed to run");
5151
}
52+
Log.d(TAG, "Iperf Test with config" + testConfig.toString() + " is finished");
5253
}
5354

5455
/**

app/src/main/java/com/lcl/lclmeasurementtool/features/iperf/IperfConfig.kt

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
package com.lcl.lclmeasurementtool.features.iperf
22

33
data class IperfConfig(
4-
var serverAdder: String,
5-
var serverPort: Int,
4+
var mServerAddr: String,
5+
var mServerPort: Int,
66
var isDownMode: Boolean,
7-
var testInterval: Double,
7+
var interval: Double,
88
var bandwidth: Long = BANDWIDTH_1M,
9-
var unit: Char = 'm',
10-
var numParallels: Int = 1,
9+
var formatUnit: Char = 'm',
10+
var parallels: Int = 1,
1111
var userName: String,
1212
var password: String,
1313
var rsaKey: String

app/src/main/java/com/lcl/lclmeasurementtool/features/iperf/IperfRunner.kt

Lines changed: 27 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,7 @@ import android.util.Log
44
import com.lcl.lclmeasurementtool.constants.IperfConstants
55
import kotlinx.coroutines.Dispatchers
66
import kotlinx.coroutines.channels.awaitClose
7-
import kotlinx.coroutines.flow.callbackFlow
8-
import kotlinx.coroutines.flow.cancellable
9-
import kotlinx.coroutines.flow.conflate
10-
import kotlinx.coroutines.flow.flowOn
11-
import kotlinx.coroutines.isActive
7+
import kotlinx.coroutines.flow.*
128
import java.io.File
139
import java.util.concurrent.CountDownLatch
1410
import java.util.concurrent.TimeUnit
@@ -18,28 +14,37 @@ class IperfRunner {
1814
companion object {
1915
const val TAG = "IperfRunner"
2016
val iperfUploadConfig: IperfConfig = IperfConfig(
21-
serverAdder = IperfConstants.IC_serverAddr,
22-
serverPort = IperfConstants.IC_serverPort,
17+
mServerAddr = IperfConstants.IC_serverAddr,
18+
mServerPort = IperfConstants.IC_serverPort,
2319
isDownMode = false,
2420
userName = IperfConstants.IC_test_username,
2521
password = IperfConstants.IC_test_password,
26-
rsaKey = IperfConstants.IC_SSL_PK,
27-
testInterval = 1.0
22+
rsaKey = IperfConstants.base64Encode(IperfConstants.IC_SSL_PK),
23+
interval = 1.0
2824
)
2925

3026
val iperfDownloadConfig: IperfConfig = IperfConfig(
31-
serverAdder = IperfConstants.IC_serverAddr,
32-
serverPort = IperfConstants.IC_serverPort,
27+
mServerAddr = IperfConstants.IC_serverAddr,
28+
mServerPort = IperfConstants.IC_serverPort,
3329
isDownMode = true,
3430
userName = IperfConstants.IC_test_username,
3531
password = IperfConstants.IC_test_password,
36-
rsaKey = IperfConstants.IC_SSL_PK,
37-
testInterval = 1.0
32+
rsaKey = IperfConstants.base64Encode(IperfConstants.IC_SSL_PK),
33+
interval = 1.0
3834
)
3935
}
4036

4137
private val doneSignal = CountDownLatch(1)
4238

39+
fun fakeGetResult(config: IperfConfig, cacheDir: File) = flowOf(
40+
IperfResult(123.123f, 123.124f, "100", "45.3", true, null, IperfStatus.RUNNING),
41+
IperfResult(123.123f, 123.124f, "100", "45.5", true, null, IperfStatus.RUNNING),
42+
IperfResult(123.123f, 123.124f, "100", "42.3", true, null, IperfStatus.RUNNING),
43+
IperfResult(123.123f, 123.124f, "100", "45.7", true, null, IperfStatus.RUNNING),
44+
IperfResult(123.123f, 123.124f, "100", "41.3", true, null, IperfStatus.RUNNING),
45+
IperfResult(123.123f, 123.124f, "100", "40.3", true, null, IperfStatus.FINISHED),
46+
).flowOn(Dispatchers.IO).cancellable()
47+
4348
fun getTestResult(config: IperfConfig, cacheDir: File) = callbackFlow {
4449
val client = IperfClient()
4550
val callback = object : IperfCallback {
@@ -50,6 +55,8 @@ class IperfRunner {
5055
bandWidth: String,
5156
isDown: Boolean
5257
) {
58+
59+
Log.d(TAG, "isDown = $isDown, bandWidth = $bandWidth")
5360
channel.trySend(
5461
IperfResult(
5562
timeStart,
@@ -70,6 +77,7 @@ class IperfRunner {
7077
bandWidth: String,
7178
isDown: Boolean
7279
) {
80+
Log.d(TAG, "isDown = $isDown, bandWidth = $bandWidth")
7381
channel.trySend(
7482
IperfResult(
7583
timeStart,
@@ -107,18 +115,19 @@ class IperfRunner {
107115
} catch (e: RuntimeException) {
108116
client.cancelTest()
109117
} finally {
118+
close()
110119
doneSignal.countDown()
111120
}
112121

113122
awaitClose {
114-
onStopped {
115-
client.cancelTest()
116-
}
123+
onStopped(cancellation = null)
117124
}
118125
}.conflate().flowOn(Dispatchers.IO).cancellable()
119126

120-
private fun onStopped(cancellation: () -> Unit) {
121-
cancellation()
127+
private fun onStopped(cancellation: (() -> Unit)?) {
128+
if (cancellation != null) {
129+
cancellation()
130+
}
122131
try {
123132
Log.d(TAG,
124133
"Awaiting shutdown notification" + Thread.currentThread().name + ":" + Thread.currentThread().state

app/src/main/java/com/lcl/lclmeasurementtool/features/ping/Ping.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package com.lcl.lclmeasurementtool.features.ping
33
import kotlinx.coroutines.Dispatchers
44
import kotlinx.coroutines.flow.cancellable
55
import kotlinx.coroutines.flow.flow
6+
import kotlinx.coroutines.flow.flowOf
67
import kotlinx.coroutines.flow.flowOn
78

89
class Ping {
@@ -38,5 +39,9 @@ class Ping {
3839

3940
emit(PingUtil.doPing(address, times, timeout))
4041
}.flowOn(Dispatchers.IO).cancellable()
42+
43+
suspend fun fakeStart(address: String, times: Int = 5, timeout: Long) =
44+
flowOf(PingResult("0", "4.5", "5.1", "6.2", "0.34", PingError(PingErrorCase.OK, null)))
45+
.flowOn(Dispatchers.IO).cancellable()
4146
}
4247
}

app/src/main/java/com/lcl/lclmeasurementtool/ui/HomeScreen.kt

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -58,14 +58,16 @@ fun HomeScreen(modifier: Modifier = Modifier, isOffline: Boolean, mainActivityVi
5858
modifier = modifier,
5959
pingResult = pingResult.value,
6060
uploadResult = uploadResult.value,
61-
downloadResult = downloadResult.value
61+
downloadResult = downloadResult.value,
62+
jobs = jobs
6263
)
6364
}
6465

6566
FloatingActionButton(onClick = {
6667
if (!isTestActive.value) {
6768
jobs.clear()
68-
jobs.add(mainActivityViewModel.doPing())
69+
mainActivityViewModel.doIperf(context)
70+
// jobs.add(mainActivityViewModel.getDownloadResult(context))
6971
Log.d("HOMEScreen", "Test Starts")
7072

7173
} else {
@@ -133,6 +135,7 @@ private fun ConnectivityCard(
133135
pingResult: PingResultState,
134136
uploadResult: ConnectivityTestResult,
135137
downloadResult: ConnectivityTestResult,
138+
jobs: List<Job>
136139
) {
137140
Card(colors = CardDefaults.cardColors(MaterialTheme.colorScheme.surfaceVariant),
138141
modifier = Modifier
@@ -151,18 +154,21 @@ private fun ConnectivityCard(
151154
Row(horizontalArrangement = Arrangement.spacedBy(20.dp)) {
152155
when (uploadResult) {
153156
is ConnectivityTestResult.Result -> {
154-
DataEntry(icon = Rounded.CloudUpload, text = "${uploadResult.result} mbps")
157+
DataEntry(icon = Rounded.CloudUpload, text = uploadResult.result)
155158
}
156-
else -> DataEntry(icon = Rounded.CloudUpload, text = "0.0 mbps")
159+
is ConnectivityTestResult.Error -> {
160+
jobs.forEach { job -> job.cancel() }
161+
}
162+
else -> DataEntry(icon = Rounded.CloudUpload, text = "0.0 MBit")
157163
}
158164

159165

160166
when (downloadResult) {
161167
is ConnectivityTestResult.Result -> {
162-
DataEntry(icon = Rounded.CloudDownload, text = "${downloadResult.result} mbps")
168+
DataEntry(icon = Rounded.CloudDownload, text = downloadResult.result)
163169
}
164170
else -> {
165-
DataEntry(icon = Rounded.CloudUpload, text = "0.0 mbps")
171+
DataEntry(icon = Rounded.CloudDownload, text = "0.0 Mbit")
166172
}
167173
}
168174

0 commit comments

Comments
 (0)