SystemJobServiceTest.java revision 681a8d809fe41189c9d590d33b986b98170e4963
1/*
2 * Copyright 2018 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.background.systemjob;
18
19import static android.support.test.espresso.matcher.ViewMatchers.assertThat;
20
21import static org.hamcrest.CoreMatchers.is;
22import static org.mockito.Mockito.mock;
23import static org.mockito.Mockito.when;
24
25import android.app.job.JobParameters;
26import android.arch.core.executor.ArchTaskExecutor;
27import android.arch.core.executor.TaskExecutor;
28import android.net.Uri;
29import android.os.PersistableBundle;
30import android.support.annotation.NonNull;
31import android.support.test.InstrumentationRegistry;
32import android.support.test.filters.SdkSuppress;
33import android.support.test.filters.SmallTest;
34import android.support.test.runner.AndroidJUnit4;
35
36import androidx.work.BaseWork;
37import androidx.work.State;
38import androidx.work.Work;
39import androidx.work.WorkManagerTest;
40import androidx.work.Worker;
41import androidx.work.impl.WorkDatabase;
42import androidx.work.impl.WorkManagerImpl;
43import androidx.work.impl.model.WorkSpecDao;
44import androidx.work.impl.utils.taskexecutor.InstantTaskExecutorRule;
45import androidx.work.worker.InfiniteTestWorker;
46
47import org.junit.After;
48import org.junit.Before;
49import org.junit.Rule;
50import org.junit.Test;
51import org.junit.runner.RunWith;
52
53@RunWith(AndroidJUnit4.class)
54@SdkSuppress(minSdkVersion = WorkManagerImpl.MIN_JOB_SCHEDULER_API_LEVEL)
55public class SystemJobServiceTest extends WorkManagerTest {
56
57    @Rule
58    public InstantTaskExecutorRule mRule = new InstantTaskExecutorRule();
59
60    private WorkDatabase mDatabase;
61    private SystemJobService mSystemJobService;
62
63    @Before
64    public void setUp() {
65        ArchTaskExecutor.getInstance().setDelegate(new TaskExecutor() {
66            @Override
67            public void executeOnDiskIO(@NonNull Runnable runnable) {
68                runnable.run();
69            }
70
71            @Override
72            public void postToMainThread(@NonNull Runnable runnable) {
73                runnable.run();
74            }
75
76            @Override
77            public boolean isMainThread() {
78                return true;
79            }
80        });
81
82        mDatabase = WorkManagerImpl.getInstance(InstrumentationRegistry.getTargetContext())
83                .getWorkDatabase();
84        mSystemJobService = new SystemJobService(); // Bleh.
85        mSystemJobService.onCreate();
86    }
87
88    @After
89    public void tearDown() {
90        mSystemJobService.onDestroy();
91        ArchTaskExecutor.getInstance().setDelegate(null);
92    }
93
94    @Test
95    @SmallTest
96    public void testOnStopJob_ResetsWorkStatus() throws InterruptedException {
97        Work work = new Work.Builder(InfiniteTestWorker.class).build();
98        insertWork(work);
99
100        JobParameters mockParams = createMockJobParameters(work.getId());
101        mSystemJobService.onStartJob(mockParams);
102
103        // TODO(sumir): Remove later.  Put here because WorkerWrapper sets state to RUNNING.
104        Thread.sleep(1000L);
105
106        WorkSpecDao workSpecDao = mDatabase.workSpecDao();
107        assertThat(workSpecDao.getState(work.getId()), is(State.RUNNING));
108
109        mSystemJobService.onStopJob(mockParams);
110        assertThat(workSpecDao.getState(work.getId()), is(State.ENQUEUED));
111    }
112
113    @Test
114    @SmallTest
115    public void testOnStopJob_ReschedulesWhenNotCancelled() {
116        Work work = new Work.Builder(InfiniteTestWorker.class).build();
117        insertWork(work);
118
119        JobParameters mockParams = createMockJobParameters(work.getId());
120        assertThat(mSystemJobService.onStartJob(mockParams), is(true));
121        assertThat(mSystemJobService.onStopJob(mockParams), is(true));
122    }
123
124    @Test
125    @SmallTest
126    public void testOnStopJob_DoesNotRescheduleWhenCancelled() {
127        Work work = new Work.Builder(InfiniteTestWorker.class).build();
128        insertWork(work);
129
130        JobParameters mockParams = createMockJobParameters(work.getId());
131        assertThat(mSystemJobService.onStartJob(mockParams), is(true));
132        WorkManagerImpl.getInstance(InstrumentationRegistry.getTargetContext())
133                .cancelWorkById(work.getId());
134        assertThat(mSystemJobService.onStopJob(mockParams), is(false));
135    }
136
137    @Test
138    @SmallTest
139    public void testStartJob_ReturnsFalseWithDuplicateJob() {
140        Work work = new Work.Builder(InfiniteTestWorker.class).build();
141        insertWork(work);
142
143        JobParameters mockParams = createMockJobParameters(work.getId());
144        assertThat(mSystemJobService.onStartJob(mockParams), is(true));
145        assertThat(mSystemJobService.onStartJob(mockParams), is(false));
146    }
147
148    @Test
149    @SmallTest
150    @SdkSuppress(minSdkVersion = 24)
151    public void testStartJob_PassesContentUriTriggers() throws InterruptedException {
152        Work work = new Work.Builder(ContentUriTriggerLoggingWorker.class).build();
153        insertWork(work);
154
155        final String[] testContentAuthorities = new String[] {
156                work.getId(),
157                "yet another " + work.getId()
158        };
159
160        final Uri[] testContentUris = new Uri[] {
161                Uri.parse("http://www.android.com"),
162                Uri.parse("http://www.google.com")
163        };
164
165        JobParameters mockParams = createMockJobParameters(work.getId());
166        when(mockParams.getTriggeredContentAuthorities()).thenReturn(testContentAuthorities);
167        when(mockParams.getTriggeredContentUris()).thenReturn(testContentUris);
168
169        assertThat(ContentUriTriggerLoggingWorker.sTimesUpdated, is(0));
170        assertThat(mSystemJobService.onStartJob(mockParams), is(true));
171
172        Thread.sleep(1000L);
173
174        assertThat(ContentUriTriggerLoggingWorker.sTimesUpdated, is(1));
175        assertThat(ContentUriTriggerLoggingWorker.sTriggeredContentAuthorities,
176                is(testContentAuthorities));
177        assertThat(ContentUriTriggerLoggingWorker.sTriggeredContentUris, is(testContentUris));
178    }
179
180    private JobParameters createMockJobParameters(String id) {
181        JobParameters jobParameters = mock(JobParameters.class);
182
183        PersistableBundle persistableBundle = new PersistableBundle();
184        persistableBundle.putString(SystemJobInfoConverter.EXTRA_WORK_SPEC_ID, id);
185        when(jobParameters.getExtras()).thenReturn(persistableBundle);
186
187        return jobParameters;
188    }
189
190    private void insertWork(BaseWork work) {
191        mDatabase.workSpecDao().insertWorkSpec(getWorkSpec(work));
192    }
193
194    public static class ContentUriTriggerLoggingWorker extends Worker {
195
196        static int sTimesUpdated = 0;
197        static String[] sTriggeredContentAuthorities;
198        static Uri[] sTriggeredContentUris;
199
200        @Override
201        public WorkerResult doWork() {
202            synchronized (ContentUriTriggerLoggingWorker.class) {
203                ++sTimesUpdated;
204                sTriggeredContentAuthorities = getTriggeredContentAuthorities();
205                sTriggeredContentUris = getTriggeredContentUris();
206            }
207            return WorkerResult.SUCCESS;
208        }
209    }
210}
211