Skip to content
This repository was archived by the owner on Dec 18, 2022. It is now read-only.

Commit bf137c5

Browse files
committed
update unit testing for setting the binder and stopping tor
1 parent 765a29e commit bf137c5

File tree

2 files changed

+95
-31
lines changed

2 files changed

+95
-31
lines changed

topl-service/src/test/java/io/matthewnelson/test_helpers/service/TestTorService.kt

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,6 @@ import io.matthewnelson.topl_service.service.components.onionproxy.ServiceTorIns
8383
import io.matthewnelson.topl_service.service.components.onionproxy.ServiceTorSettings
8484
import io.matthewnelson.topl_service.service.BaseService
8585
import io.matthewnelson.topl_service.service.components.actions.ServiceActionProcessor
86-
import io.matthewnelson.topl_service.service.components.binding.TorServiceConnection
8786
import io.matthewnelson.topl_service.service.components.receiver.TorServiceReceiver
8887
import kotlinx.coroutines.*
8988
import kotlinx.coroutines.test.TestCoroutineScope
@@ -104,17 +103,13 @@ internal class TestTorService(
104103
val testTorServiceBinder: TestTorServiceBinder by lazy {
105104
TestTorServiceBinder(this)
106105
}
107-
var serviceIsBound = false
108-
private set
109106

110107
override fun unbindTorService() {
111108
try {
112-
unbindService(context, TorServiceConnection.torServiceConnection)
113-
serviceIsBound = false
109+
unbindService(context)
114110
} catch (e: IllegalArgumentException) {}
115111
}
116112
override fun onBind(intent: Intent?): IBinder? {
117-
serviceIsBound = true
118113
return testTorServiceBinder
119114
}
120115

@@ -240,6 +235,11 @@ internal class TestTorService(
240235
override fun startTor() {
241236
simulateStart()
242237
}
238+
239+
val bandwidth1000 = "1000"
240+
val bandwidth0 = "0"
241+
242+
// Add 6_000ms delay at start of each test to account for startup time.
243243
@ExperimentalCoroutinesApi
244244
private fun simulateStart() = getScopeIO().launch {
245245
try {
@@ -251,19 +251,29 @@ internal class TestTorService(
251251
serviceEventBroadcaster.broadcastTorState(TorState.ON, TorNetworkState.DISABLED)
252252
delay(1000)
253253
serviceEventBroadcaster.broadcastTorState(TorState.ON, TorNetworkState.ENABLED)
254+
delay(1000)
255+
serviceEventBroadcaster.broadcastNotice("NOTICE|BaseEventListener|Bootstrapped 95% (")
256+
delay(1000)
257+
serviceEventBroadcaster.broadcastNotice("NOTICE|BaseEventListener|Bootstrapped 100% (")
258+
delay(1000)
259+
serviceEventBroadcaster.broadcastBandwidth(bandwidth1000, bandwidth1000)
260+
delay(1000)
261+
serviceEventBroadcaster.broadcastBandwidth(bandwidth0, bandwidth0)
254262
} catch (e: Exception) {
255263
broadcastLogger.exception(e)
256264
}
257265
}
258266
@WorkerThread
259267
override fun stopTor() {
260-
try {
261-
serviceEventBroadcaster.broadcastTorState(TorState.STOPPING, TorNetworkState.ENABLED)
262-
serviceEventBroadcaster.broadcastTorState(TorState.STOPPING, TorNetworkState.DISABLED)
263-
serviceEventBroadcaster.broadcastTorState(TorState.OFF, TorNetworkState.DISABLED)
264-
} catch (e: Exception) {
265-
broadcastLogger.exception(e)
266-
}
268+
simulateStopTor()
269+
}
270+
271+
private fun simulateStopTor() = getScopeIO().launch {
272+
serviceEventBroadcaster.broadcastTorState(TorState.STOPPING, TorNetworkState.ENABLED)
273+
delay(1000)
274+
serviceEventBroadcaster.broadcastTorState(TorState.STOPPING, TorNetworkState.DISABLED)
275+
delay(1000)
276+
serviceEventBroadcaster.broadcastTorState(TorState.OFF, TorNetworkState.DISABLED)
267277
}
268278
@WorkerThread
269279
@Throws(

topl-service/src/test/java/io/matthewnelson/topl_service/service/TorServiceUnitTest.kt

Lines changed: 72 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@
6767
package io.matthewnelson.topl_service.service
6868

6969
import android.app.Application
70+
import android.content.ComponentName
7071
import android.content.Intent
7172
import androidx.test.core.app.ApplicationProvider
7273
import io.matthewnelson.test_helpers.application_provided_classes.TestEventBroadcaster
@@ -92,11 +93,10 @@ import kotlinx.coroutines.test.resetMain
9293
import kotlinx.coroutines.test.runBlockingTest
9394
import kotlinx.coroutines.test.setMain
9495
import org.junit.After
96+
import org.junit.Assert.*
9597
import org.junit.Before
9698
import org.junit.Rule
9799
import org.junit.Test
98-
import org.junit.Assert.assertEquals
99-
import org.junit.Assert.assertTrue
100100
import org.junit.rules.TemporaryFolder
101101
import org.junit.runner.RunWith
102102
import org.robolectric.RobolectricTestRunner
@@ -154,7 +154,26 @@ internal class TorServiceUnitTest {
154154
.build()
155155

156156
Dispatchers.setMain(testDispatcher)
157+
158+
// Setup TestTorService
157159
testTorService = TestTorService(app, testDispatcher)
160+
161+
// Ensure everything's cleared
162+
shadowOf(app).clearStartedServices()
163+
assertNull(shadowOf(app).nextStartedService)
164+
165+
// Ensure binder is being set when startService is called
166+
shadowOf(app).setComponentNameAndServiceForBindService(
167+
ComponentName(app.applicationContext, TestTorService::class.java),
168+
testTorService.testTorServiceBinder
169+
)
170+
BaseService.startService(app, TestTorService::class.java)
171+
assertEquals(shadowOf(app).nextStartedService.action, ServiceActionName.START)
172+
assertNotNull(TorServiceConnection.serviceBinder)
173+
174+
// Simulate startup
175+
testTorService.onCreate()
176+
testTorService.onStartCommand(Intent(ServiceActionName.START), 0, 0)
158177
}
159178

160179
private fun getNewServiceNotificationBuilder(): ServiceNotification.Builder =
@@ -174,8 +193,7 @@ internal class TorServiceUnitTest {
174193
// Build it prior to initializing TorServiceController with the builder
175194
// so we get our test classes initialized which won't be overwritten.
176195
backgroundPolicyBuilder.build(
177-
TestTorService::class.java,
178-
TorServiceConnection.torServiceConnection
196+
TestTorService::class.java
179197
)
180198

181199
return TorServiceController.Builder(
@@ -201,8 +219,6 @@ internal class TorServiceUnitTest {
201219
@ExperimentalCoroutinesApi
202220
@Test
203221
fun `validate startup state`() = runBlockingTest(testDispatcher) {
204-
simulateStartService()
205-
206222
// Check EventBroadcasters are working and notification is being updated
207223
var statePair = testTorService.getSimulatedTorStates()
208224
assertEquals(TorState.STARTING, statePair.first)
@@ -226,26 +242,27 @@ internal class TorServiceUnitTest {
226242
// Waiting to Bootstrap
227243
assertEquals(true, serviceNotification.progressBarShown)
228244
assertEquals(serviceNotification.imageNetworkDisabled, serviceNotification.currentIcon)
245+
delay(1000)
229246

230247
// Bootstrapped
231-
serviceEventBroadcaster.broadcastNotice("NOTICE|BaseEventListener|Bootstrapped 95% (")
232248
assertEquals("Bootstrapped 95%", serviceNotification.currentContentText)
233-
serviceEventBroadcaster.broadcastNotice("NOTICE|BaseEventListener|Bootstrapped 100% (")
249+
delay(1000)
250+
234251
assertEquals("Bootstrapped 100%", serviceNotification.currentContentText)
235252
assertEquals(false, serviceNotification.progressBarShown)
236253
assertEquals(serviceNotification.imageNetworkEnabled, serviceNotification.currentIcon)
254+
delay(1000)
237255

238256
// Data transfer
239-
val bytesRead = "1000"
240-
val bytesWritten = "1050"
241-
serviceEventBroadcaster.broadcastBandwidth(bytesRead, bytesWritten)
257+
val bandwidth = testTorService.bandwidth1000
242258
val contentTextString =
243-
ServiceUtilities.getFormattedBandwidthString(bytesRead.toLong(), bytesWritten.toLong())
259+
ServiceUtilities.getFormattedBandwidthString(bandwidth.toLong(), bandwidth.toLong())
244260
assertEquals(contentTextString, serviceNotification.currentContentText)
245261
assertEquals(serviceNotification.imageDataTransfer, serviceNotification.currentIcon)
246-
serviceEventBroadcaster.broadcastBandwidth("0", "0")
247-
assertEquals(serviceNotification.imageNetworkEnabled, serviceNotification.currentIcon)
262+
delay(1000)
248263

264+
assertEquals(serviceNotification.imageNetworkEnabled, serviceNotification.currentIcon)
265+
delay(1000)
249266

250267
// Ensure Receivers were registered
251268
shadowOf(app).registeredReceivers.elementAtOrNull(0)?.let {
@@ -264,9 +281,46 @@ internal class TorServiceUnitTest {
264281
testTorService.refreshBroadcastLoggerWasCalled = false
265282
}
266283

267-
private fun simulateStartService() {
268-
testTorService.onCreate()
269-
testTorService.onStartCommand(Intent(ServiceActionName.START), 0, 0)
270-
testTorService.onBind(null)
284+
@ExperimentalCoroutinesApi
285+
@Test
286+
fun `calling stopTor cleans up`() = runBlockingTest(testDispatcher){
287+
delay(6000) // testTorService.simulateStart() takes 6000ms
288+
289+
TorServiceController.stopTor()
290+
291+
// Broadcaster and notification are working properly
292+
var statePair = testTorService.getSimulatedTorStates()
293+
assertEquals(TorState.STOPPING, statePair.first)
294+
assertEquals(TorNetworkState.ENABLED, statePair.second)
295+
assertEquals(TorState.STOPPING, serviceNotification.currentContentTitle)
296+
assertEquals("Stopping Service...", serviceNotification.currentContentText)
297+
delay(1000)
298+
299+
statePair = testTorService.getSimulatedTorStates()
300+
assertEquals(TorState.STOPPING, statePair.first)
301+
assertEquals(TorNetworkState.DISABLED, statePair.second)
302+
assertEquals(TorState.STOPPING, serviceNotification.currentContentTitle)
303+
delay(1000)
304+
305+
statePair = testTorService.getSimulatedTorStates()
306+
assertEquals(TorState.OFF, statePair.first)
307+
assertEquals(TorNetworkState.DISABLED, statePair.second)
308+
assertEquals(TorState.OFF, serviceNotification.currentContentTitle)
309+
delay(1000)
310+
311+
// Ensure Receivers were unregistered
312+
shadowOf(app).registeredReceivers.elementAtOrNull(0)?.let {
313+
// Registered with the system
314+
assertNull(it.broadcastReceiver)
315+
// Boolean value is correct
316+
assertEquals(false, TorServiceReceiver.isRegistered)
317+
}
318+
319+
// Test TorServicePrefsListener is unregistered
320+
val currentHasDebugLogsValue = testTorService.serviceTorSettings.hasDebugLogs
321+
val prefs = TorServicePrefs(app.applicationContext)
322+
assertFalse(testTorService.refreshBroadcastLoggerWasCalled)
323+
prefs.putBoolean(PrefKeyBoolean.HAS_DEBUG_LOGS, !currentHasDebugLogsValue)
324+
assertFalse(testTorService.refreshBroadcastLoggerWasCalled)
271325
}
272326
}

0 commit comments

Comments
 (0)