blob: fdcc604bdea7391c15253bde55bd90b1106eec0c [file] [log] [blame]
Rahul Ravikumar06eec682019-09-18 14:29:19 -07001/*
2 * Copyright 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package androidx.work.impl.foreground
18
19import android.app.Notification
20import android.content.Context
21import android.util.Log
22import androidx.test.core.app.ApplicationProvider
23import androidx.test.ext.junit.runners.AndroidJUnit4
24import androidx.test.filters.MediumTest
25import androidx.work.Configuration
26import androidx.work.Constraints
Rahul Ravikumar3ceb16d2019-10-03 17:20:59 -070027import androidx.work.ForegroundInfo
Rahul Ravikumar06eec682019-09-18 14:29:19 -070028import androidx.work.NetworkType
Rahul Ravikumar06eec682019-09-18 14:29:19 -070029import androidx.work.OneTimeWorkRequest
Rahul Ravikumar0edc3822019-09-26 16:07:46 -070030import androidx.work.impl.Processor
31import androidx.work.impl.Scheduler
Rahul Ravikumar06eec682019-09-18 14:29:19 -070032import androidx.work.impl.WorkDatabase
33import androidx.work.impl.WorkManagerImpl
34import androidx.work.impl.constraints.WorkConstraintsCallback
35import androidx.work.impl.constraints.WorkConstraintsTracker
Rahul Ravikumarbee795cf2019-10-22 13:40:27 -070036import androidx.work.impl.foreground.SystemForegroundDispatcher.createCancelWorkIntent
Rahul Ravikumar06eec682019-09-18 14:29:19 -070037import androidx.work.impl.foreground.SystemForegroundDispatcher.createNotifyIntent
38import androidx.work.impl.foreground.SystemForegroundDispatcher.createStartForegroundIntent
39import androidx.work.impl.foreground.SystemForegroundDispatcher.createStopForegroundIntent
40import androidx.work.impl.utils.SynchronousExecutor
41import androidx.work.impl.utils.taskexecutor.InstantWorkTaskExecutor
42import androidx.work.impl.utils.taskexecutor.TaskExecutor
43import androidx.work.worker.TestWorker
Rahul Ravikumarbee795cf2019-10-22 13:40:27 -070044import org.hamcrest.CoreMatchers.`is`
45import org.hamcrest.MatcherAssert.assertThat
Rahul Ravikumar06eec682019-09-18 14:29:19 -070046import org.junit.Before
47import org.junit.Test
48import org.junit.runner.RunWith
49import org.mockito.ArgumentMatchers.any
50import org.mockito.ArgumentMatchers.eq
51import org.mockito.Mockito.mock
52import org.mockito.Mockito.spy
53import org.mockito.Mockito.times
54import org.mockito.Mockito.verify
55import org.mockito.Mockito.verifyZeroInteractions
Rahul Ravikumarbf0431692019-10-03 11:26:50 -070056import java.util.UUID
Rahul Ravikumar06eec682019-09-18 14:29:19 -070057
58@RunWith(AndroidJUnit4::class)
59@MediumTest
60class SystemForegroundDispatcherTest {
61
62 private lateinit var context: Context
63 private lateinit var config: Configuration
64 private lateinit var taskExecutor: TaskExecutor
65 private lateinit var workManager: WorkManagerImpl
66 private lateinit var workDatabase: WorkDatabase
Rahul Ravikumar0edc3822019-09-26 16:07:46 -070067 private lateinit var processor: Processor
Rahul Ravikumar06eec682019-09-18 14:29:19 -070068 private lateinit var tracker: WorkConstraintsTracker
69 private lateinit var constraintsCallback: WorkConstraintsCallback
70 private lateinit var dispatcher: SystemForegroundDispatcher
71 private lateinit var dispatcherCallback: SystemForegroundDispatcher.Callback
72
73 @Before
74 fun setUp() {
75 context = ApplicationProvider.getApplicationContext()
76 config = Configuration.Builder()
77 .setExecutor(SynchronousExecutor())
78 .setMinimumLoggingLevel(Log.DEBUG)
79 .build()
80 taskExecutor = InstantWorkTaskExecutor()
Rahul Ravikumar0edc3822019-09-26 16:07:46 -070081 val scheduler = mock(Scheduler::class.java)
82 workDatabase = WorkDatabase.create(context, taskExecutor.backgroundExecutor, true)
83 processor = Processor(context, config, taskExecutor, workDatabase, listOf(scheduler))
84 workManager = spy(
85 WorkManagerImpl(
86 context,
87 config,
88 taskExecutor,
89 workDatabase,
90 listOf(scheduler),
91 processor
92 )
93 )
Rahul Ravikumar06eec682019-09-18 14:29:19 -070094 workDatabase = workManager.workDatabase
Rahul Ravikumar06eec682019-09-18 14:29:19 -070095 // Initialize WorkConstraintsTracker
96 constraintsCallback = mock(WorkConstraintsCallback::class.java)
97 tracker = spy(WorkConstraintsTracker(context, taskExecutor, constraintsCallback))
98 // Initialize dispatcher
99 dispatcherCallback = mock(SystemForegroundDispatcher.Callback::class.java)
Rahul Ravikumar09082032019-10-18 13:26:48 -0700100 dispatcher = spy(SystemForegroundDispatcher(context, workManager, tracker))
Rahul Ravikumar06eec682019-09-18 14:29:19 -0700101 dispatcher.setCallback(dispatcherCallback)
102 }
103
104 @Test
105 fun testStartForeground_noInteractions_workSpecHasNoConstraints() {
106 val request = OneTimeWorkRequest.Builder(TestWorker::class.java).build()
107 workDatabase.workSpecDao().insertWorkSpec(request.workSpec)
108 val intent = createStartForegroundIntent(context, request.stringId)
109 dispatcher.onStartCommand(intent)
110 verifyZeroInteractions(tracker)
111 }
112
113 @Test
114 fun testStartForeground_trackConstraints_workSpecHasConstraints() {
115 val request = OneTimeWorkRequest.Builder(TestWorker::class.java)
116 .setConstraints(
117 Constraints.Builder().setRequiredNetworkType(NetworkType.CONNECTED).build()
118 ).build()
119 workDatabase.workSpecDao().insertWorkSpec(request.workSpec)
120
121 val intent = createStartForegroundIntent(context, request.stringId)
122 dispatcher.onStartCommand(intent)
123 verify(tracker, times(1)).replace(setOf(request.workSpec))
124 }
125
126 @Test
127 fun testStopForeground() {
128 val intent = createStopForegroundIntent(context)
129 dispatcher.onStartCommand(intent)
130 verify(dispatcherCallback, times(1)).stop()
131 }
132
133 @Test
134 fun testHandleNotify() {
Rahul Ravikumar3ceb16d2019-10-03 17:20:59 -0700135 val workSpecId = "workSpecId"
Rahul Ravikumarb29c1de2019-12-04 12:20:34 -0800136 val notificationId = 1
Rahul Ravikumar06eec682019-09-18 14:29:19 -0700137 val notification = mock(Notification::class.java)
Rahul Ravikumarb29c1de2019-12-04 12:20:34 -0800138 val metadata = ForegroundInfo(notificationId, notification)
Rahul Ravikumar3ceb16d2019-10-03 17:20:59 -0700139 val intent = createNotifyIntent(context, workSpecId, metadata)
Rahul Ravikumar06eec682019-09-18 14:29:19 -0700140 dispatcher.onStartCommand(intent)
141 verify(dispatcherCallback, times(1))
Rahul Ravikumarb29c1de2019-12-04 12:20:34 -0800142 .notify(eq(notificationId), eq(0), eq(workSpecId), any<Notification>())
Rahul Ravikumar06eec682019-09-18 14:29:19 -0700143 }
144
145 @Test
146 fun testStartForeground_trackConstraints_constraintsUnMet() {
147 val request = OneTimeWorkRequest.Builder(TestWorker::class.java)
148 .setConstraints(
149 Constraints.Builder().setRequiredNetworkType(NetworkType.CONNECTED).build()
150 ).build()
151 workDatabase.workSpecDao().insertWorkSpec(request.workSpec)
152
153 val intent = createStartForegroundIntent(context, request.stringId)
154 dispatcher.onStartCommand(intent)
155 verify(tracker, times(1)).replace(setOf(request.workSpec))
156 dispatcher.onAllConstraintsNotMet(listOf(request.workSpec.id))
157 verify(workManager, times(1)).stopForegroundWork(eq(request.workSpec.id))
158 }
Rahul Ravikumarbf0431692019-10-03 11:26:50 -0700159
160 @Test
161 fun testCancelForegroundWork() {
162 val request = OneTimeWorkRequest.Builder(TestWorker::class.java)
163 .setConstraints(
164 Constraints.Builder().setRequiredNetworkType(NetworkType.CONNECTED).build()
165 ).build()
166 workDatabase.workSpecDao().insertWorkSpec(request.workSpec)
167
168 val intent = createStartForegroundIntent(context, request.stringId)
169 dispatcher.onStartCommand(intent)
170 verify(tracker, times(1)).replace(setOf(request.workSpec))
171 val stopIntent = createCancelWorkIntent(context, request.stringId)
172 dispatcher.onStartCommand(stopIntent)
173 verify(workManager, times(1)).cancelWorkById(eq(UUID.fromString(request.workSpec.id)))
Rahul Ravikumarbee795cf2019-10-22 13:40:27 -0700174 assertThat(processor.hasWork(), `is`(false))
Rahul Ravikumarbf0431692019-10-03 11:26:50 -0700175 }
Rahul Ravikumar06eec682019-09-18 14:29:19 -0700176}