SystemJobInfoConverterTest.java revision c4de263bc3abaf06ee41a2835c471752a1825e0c
1/*
2 * Copyright 2017 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 org.hamcrest.CoreMatchers.is;
20import static org.hamcrest.MatcherAssert.assertThat;
21import static org.hamcrest.Matchers.arrayContaining;
22import static org.mockito.Mockito.mock;
23import static org.mockito.Mockito.when;
24
25import static androidx.work.NetworkType.CONNECTED;
26import static androidx.work.NetworkType.METERED;
27import static androidx.work.NetworkType.NOT_REQUIRED;
28import static androidx.work.NetworkType.NOT_ROAMING;
29import static androidx.work.NetworkType.UNMETERED;
30
31import android.app.job.JobInfo;
32import android.net.Uri;
33import android.os.Build;
34import android.support.test.InstrumentationRegistry;
35import android.support.test.filters.SdkSuppress;
36import android.support.test.filters.SmallTest;
37import android.support.test.runner.AndroidJUnit4;
38
39import org.junit.Before;
40import org.junit.Test;
41import org.junit.runner.RunWith;
42
43import androidx.work.BackoffPolicy;
44import androidx.work.Constraints;
45import androidx.work.NetworkType;
46import androidx.work.PeriodicWork;
47import androidx.work.Work;
48import androidx.work.WorkManagerTest;
49import androidx.work.impl.WorkManagerImpl;
50import androidx.work.impl.model.WorkSpec;
51import androidx.work.impl.utils.IdGenerator;
52import androidx.work.worker.TestWorker;
53
54@RunWith(AndroidJUnit4.class)
55@SdkSuppress(minSdkVersion = WorkManagerImpl.MIN_JOB_SCHEDULER_API_LEVEL)
56public class SystemJobInfoConverterTest extends WorkManagerTest {
57
58    private static final long TEST_INTERVAL_DURATION =
59            PeriodicWork.MIN_PERIODIC_INTERVAL_MILLIS + 1232L;
60    private static final long TEST_FLEX_DURATION = PeriodicWork.MIN_PERIODIC_FLEX_MILLIS + 112L;
61
62    private IdGenerator mMockIdGenerator;
63    private SystemJobInfoConverter mConverter;
64
65    @Before
66    public void setUp() {
67        mMockIdGenerator = mock(IdGenerator.class);
68        mConverter = new SystemJobInfoConverter(
69                InstrumentationRegistry.getTargetContext(),
70                mMockIdGenerator);
71    }
72
73    @Test
74    @SmallTest
75    public void testConvert_ids() {
76        final String expectedWorkSpecId = "026e3422-9cd1-11e7-abc4-cec278b6b50a";
77        final int expectedJobId = 101;
78        when(mMockIdGenerator.nextJobSchedulerId()).thenReturn(expectedJobId);
79        WorkSpec workSpec = new WorkSpec(expectedWorkSpecId);
80        JobInfo jobInfo = mConverter.convert(workSpec);
81        String actualWorkSpecId = jobInfo.getExtras().getString(
82                SystemJobInfoConverter.EXTRA_WORK_SPEC_ID);
83        assertThat(actualWorkSpecId, is(expectedWorkSpecId));
84        assertThat(jobInfo.getId(), is(expectedJobId));
85    }
86
87    @Test
88    @SmallTest
89    public void testConvert_setPersistedByDefault() {
90        JobInfo jobInfo = mConverter.convert(new WorkSpec("id"));
91        assertThat(jobInfo.isPersisted(), is(true));
92    }
93
94    /**
95     * Due to b/6771687, calling {@link JobInfo.Builder#build} with no constraints throws an
96     * {@link IllegalArgumentException}. This is testing that {@link SystemJobInfoConverter#convert}
97     * sets some dummy constraint to toggle some internal boolean flags in {@link JobInfo.Builder}
98     * to allow {@link Work} with no constraints to be converted without affecting its runtime,
99     * e.g. calling builder.setMinLatencyMillis(0L).
100     */
101    @Test
102    @SmallTest
103    public void testConvert_noConstraints_doesNotThrowException() {
104        mConverter.convert(new WorkSpec("id"));
105    }
106
107    @Test
108    @SmallTest
109    public void testConvert_retryPolicy() {
110        long expectedBackoffDelayDuration = 50000;
111        WorkSpec workSpec = new WorkSpec("id");
112        workSpec.setBackoffDelayDuration(expectedBackoffDelayDuration);
113        workSpec.setBackoffPolicy(BackoffPolicy.LINEAR);
114        JobInfo jobInfo = mConverter.convert(workSpec);
115        assertThat(jobInfo.getInitialBackoffMillis(), is(expectedBackoffDelayDuration));
116        assertThat(jobInfo.getBackoffPolicy(), is(JobInfo.BACKOFF_POLICY_LINEAR));
117    }
118
119    @Test
120    @SmallTest
121    public void testConvert_initialDelay() {
122        final long expectedInitialDelay = 12123L;
123        WorkSpec workSpec = new WorkSpec("id");
124        workSpec.setInitialDelay(expectedInitialDelay);
125        JobInfo jobInfo = mConverter.convert(workSpec);
126        assertThat(jobInfo.getMinLatencyMillis(), is(expectedInitialDelay));
127    }
128
129    @Test
130    @SmallTest
131    public void testConvert_periodicWithNoFlex() {
132        WorkSpec workSpec = new WorkSpec("id");
133        workSpec.setPeriodic(TEST_INTERVAL_DURATION);
134        JobInfo jobInfo = mConverter.convert(workSpec);
135        assertThat(jobInfo.getIntervalMillis(), is(TEST_INTERVAL_DURATION));
136    }
137
138    @Test
139    @SmallTest
140    @SdkSuppress(minSdkVersion = 24)
141    public void testConvert_periodicWithFlex() {
142        WorkSpec workSpec = new WorkSpec("id");
143        workSpec.setPeriodic(TEST_INTERVAL_DURATION, TEST_FLEX_DURATION);
144        JobInfo jobInfo = mConverter.convert(workSpec);
145        assertThat(jobInfo.getIntervalMillis(), is(TEST_INTERVAL_DURATION));
146        assertThat(jobInfo.getFlexMillis(), is(TEST_FLEX_DURATION));
147    }
148
149    @Test
150    @SmallTest
151    public void testConvert_requireCharging() {
152        final boolean expectedRequireCharging = true;
153        WorkSpec workSpec = getTestWorkSpecWithConstraints(new Constraints.Builder()
154                .setRequiresCharging(expectedRequireCharging).build());
155        JobInfo jobInfo = mConverter.convert(workSpec);
156        assertThat(jobInfo.isRequireCharging(), is(expectedRequireCharging));
157    }
158
159    @Test
160    @SmallTest
161    @SdkSuppress(minSdkVersion = 24)
162    public void testConvert_requireContentUriTrigger() {
163        final Uri expectedUri = Uri.parse("TEST_URI");
164        final JobInfo.TriggerContentUri expectedTriggerContentUri =
165                new JobInfo.TriggerContentUri(
166                        expectedUri, JobInfo.TriggerContentUri.FLAG_NOTIFY_FOR_DESCENDANTS);
167        WorkSpec workSpec = getTestWorkSpecWithConstraints(new Constraints.Builder()
168                .addContentUriTrigger(expectedUri, true).build());
169        JobInfo jobInfo = mConverter.convert(workSpec);
170
171        JobInfo.TriggerContentUri[] triggerContentUris = jobInfo.getTriggerContentUris();
172        assertThat(triggerContentUris, is(arrayContaining(expectedTriggerContentUri)));
173    }
174
175    @Test
176    @SmallTest
177    public void testConvert_requireDeviceIdle() {
178        final boolean expectedRequireDeviceIdle = true;
179        WorkSpec workSpec = getTestWorkSpecWithConstraints(new Constraints.Builder()
180                .setRequiresDeviceIdle(expectedRequireDeviceIdle).build());
181        JobInfo jobInfo = mConverter.convert(workSpec);
182        assertThat(jobInfo.isRequireDeviceIdle(), is(expectedRequireDeviceIdle));
183    }
184
185    @Test
186    @SmallTest
187    @SdkSuppress(minSdkVersion = 26)
188    public void testConvert_requireBatteryNotLow() {
189        final boolean expectedRequireBatteryNotLow = true;
190        WorkSpec workSpec = getTestWorkSpecWithConstraints(new Constraints.Builder()
191                .setRequiresBatteryNotLow(expectedRequireBatteryNotLow).build());
192        JobInfo jobInfo = mConverter.convert(workSpec);
193        assertThat(jobInfo.isRequireBatteryNotLow(), is(expectedRequireBatteryNotLow));
194    }
195
196    @Test
197    @SmallTest
198    @SdkSuppress(minSdkVersion = 26)
199    public void testConvert_requireStorageNotLow() {
200        final boolean expectedRequireStorageNotLow = true;
201        WorkSpec workSpec = getTestWorkSpecWithConstraints(new Constraints.Builder()
202                .setRequiresStorageNotLow(expectedRequireStorageNotLow).build());
203        JobInfo jobInfo = mConverter.convert(workSpec);
204        assertThat(jobInfo.isRequireStorageNotLow(), is(expectedRequireStorageNotLow));
205    }
206
207    @Test
208    @SmallTest
209    public void testConvert_networkTypeNotRoamingRequiresApi24() {
210        convertWithRequiredNetworkType(NOT_ROAMING, JobInfo.NETWORK_TYPE_NOT_ROAMING, 24);
211    }
212
213    @Test
214    @SmallTest
215    public void testConvert_networkTypeMeteredRequiresApi26() {
216        convertWithRequiredNetworkType(METERED, JobInfo.NETWORK_TYPE_METERED, 26);
217    }
218
219    private void convertWithRequiredNetworkType(NetworkType networkType,
220                                                int jobInfoNetworkType,
221                                                int minSdkVersion) {
222        WorkSpec workSpec = getTestWorkSpecWithConstraints(new Constraints.Builder()
223                .setRequiredNetworkType(networkType).build());
224        JobInfo jobInfo = mConverter.convert(workSpec);
225        if (Build.VERSION.SDK_INT >= minSdkVersion) {
226            assertThat(jobInfo.getNetworkType(), is(jobInfoNetworkType));
227        } else {
228            assertThat(jobInfo.getNetworkType(), is(JobInfo.NETWORK_TYPE_ANY));
229        }
230    }
231
232    @Test
233    @SmallTest
234    public void testConvertNetworkType_none() {
235        assertThat(SystemJobInfoConverter.convertNetworkType(NOT_REQUIRED),
236                is(JobInfo.NETWORK_TYPE_NONE));
237    }
238
239    @Test
240    @SmallTest
241    public void testConvertNetworkType_any() {
242        assertThat(SystemJobInfoConverter.convertNetworkType(CONNECTED),
243                is(JobInfo.NETWORK_TYPE_ANY));
244    }
245
246    @Test
247    @SmallTest
248    public void testConvertNetworkType_unmetered() {
249        assertThat(SystemJobInfoConverter.convertNetworkType(UNMETERED),
250                is(JobInfo.NETWORK_TYPE_UNMETERED));
251    }
252
253    @Test
254    @SmallTest
255    @SdkSuppress(minSdkVersion = 23, maxSdkVersion = 23)
256    public void testConvertNetworkType_notRoaming_returnAnyBeforeApi24() {
257        assertThat(SystemJobInfoConverter.convertNetworkType(NOT_ROAMING),
258                is(JobInfo.NETWORK_TYPE_ANY));
259    }
260
261    @Test
262    @SmallTest
263    @SdkSuppress(minSdkVersion = 24)
264    public void testConvertNetworkType_notRoaming_returnsNotRoamingAtOrAfterApi24() {
265        assertThat(SystemJobInfoConverter.convertNetworkType(NOT_ROAMING),
266                is(JobInfo.NETWORK_TYPE_NOT_ROAMING));
267    }
268
269    @Test
270    @SmallTest
271    @SdkSuppress(minSdkVersion = WorkManagerImpl.MIN_JOB_SCHEDULER_API_LEVEL, maxSdkVersion = 25)
272    public void testConvertNetworkType_metered_returnsAnyBeforeApi26() {
273        assertThat(SystemJobInfoConverter.convertNetworkType(METERED),
274                is(JobInfo.NETWORK_TYPE_ANY));
275    }
276
277    @Test
278    @SmallTest
279    @SdkSuppress(minSdkVersion = 26)
280    public void testConvertNetworkType_metered_returnsMeteredAtOrAfterApi26() {
281        assertThat(SystemJobInfoConverter.convertNetworkType(METERED),
282                is(JobInfo.NETWORK_TYPE_METERED));
283    }
284
285    private WorkSpec getTestWorkSpecWithConstraints(Constraints constraints) {
286        return getWorkSpec(new Work.Builder(TestWorker.class).withConstraints(constraints).build());
287    }
288}
289