6767package io.matthewnelson.topl_service.service
6868
6969import android.app.Application
70+ import android.content.ComponentName
7071import android.content.Intent
7172import androidx.test.core.app.ApplicationProvider
7273import io.matthewnelson.test_helpers.application_provided_classes.TestEventBroadcaster
@@ -92,11 +93,10 @@ import kotlinx.coroutines.test.resetMain
9293import kotlinx.coroutines.test.runBlockingTest
9394import kotlinx.coroutines.test.setMain
9495import org.junit.After
96+ import org.junit.Assert.*
9597import org.junit.Before
9698import org.junit.Rule
9799import org.junit.Test
98- import org.junit.Assert.assertEquals
99- import org.junit.Assert.assertTrue
100100import org.junit.rules.TemporaryFolder
101101import org.junit.runner.RunWith
102102import 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