| /* |
| * Copyright 2017 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package androidx.work.impl.background.systemjob; |
| |
| import static androidx.work.NetworkType.CONNECTED; |
| import static androidx.work.NetworkType.METERED; |
| import static androidx.work.NetworkType.NOT_REQUIRED; |
| import static androidx.work.NetworkType.NOT_ROAMING; |
| import static androidx.work.NetworkType.UNMETERED; |
| |
| import static org.hamcrest.CoreMatchers.is; |
| import static org.hamcrest.MatcherAssert.assertThat; |
| import static org.hamcrest.Matchers.arrayContaining; |
| import static org.hamcrest.Matchers.greaterThanOrEqualTo; |
| |
| import android.app.job.JobInfo; |
| import android.net.Uri; |
| import android.os.Build; |
| |
| import androidx.test.core.app.ApplicationProvider; |
| import androidx.test.ext.junit.runners.AndroidJUnit4; |
| import androidx.test.filters.SdkSuppress; |
| import androidx.test.filters.SmallTest; |
| import androidx.work.BackoffPolicy; |
| import androidx.work.Constraints; |
| import androidx.work.NetworkType; |
| import androidx.work.OneTimeWorkRequest; |
| import androidx.work.PeriodicWorkRequest; |
| import androidx.work.WorkManagerTest; |
| import androidx.work.impl.WorkManagerImpl; |
| import androidx.work.impl.model.WorkSpec; |
| import androidx.work.worker.TestWorker; |
| |
| import org.junit.Before; |
| import org.junit.Test; |
| import org.junit.runner.RunWith; |
| |
| import java.util.concurrent.TimeUnit; |
| |
| @RunWith(AndroidJUnit4.class) |
| @SdkSuppress(minSdkVersion = WorkManagerImpl.MIN_JOB_SCHEDULER_API_LEVEL) |
| public class SystemJobInfoConverterTest extends WorkManagerTest { |
| |
| private static final long TEST_INTERVAL_DURATION = |
| PeriodicWorkRequest.MIN_PERIODIC_INTERVAL_MILLIS + 1232L; |
| private static final long TEST_FLEX_DURATION = |
| PeriodicWorkRequest.MIN_PERIODIC_FLEX_MILLIS + 112L; |
| private static final int JOB_ID = 101; |
| |
| private SystemJobInfoConverter mConverter; |
| |
| @Before |
| public void setUp() { |
| mConverter = new SystemJobInfoConverter( |
| ApplicationProvider.getApplicationContext()); |
| } |
| |
| @Test |
| @SmallTest |
| public void testConvert_ids() { |
| final String expectedWorkSpecId = "026e3422-9cd1-11e7-abc4-cec278b6b50a"; |
| WorkSpec workSpec = new WorkSpec(expectedWorkSpecId, TestWorker.class.getName()); |
| JobInfo jobInfo = mConverter.convert(workSpec, JOB_ID); |
| String actualWorkSpecId = jobInfo.getExtras().getString( |
| SystemJobInfoConverter.EXTRA_WORK_SPEC_ID); |
| assertThat(actualWorkSpecId, is(expectedWorkSpecId)); |
| assertThat(jobInfo.getId(), is(JOB_ID)); |
| } |
| |
| @Test |
| @SmallTest |
| public void testConvert_setPersistedByDefault() { |
| JobInfo jobInfo = mConverter.convert( |
| new WorkSpec("id", TestWorker.class.getName()), JOB_ID); |
| assertThat(jobInfo.isPersisted(), is(false)); |
| } |
| |
| /** |
| * Due to b/6771687, calling {@link JobInfo.Builder#build} with no constraints throws an |
| * {@link IllegalArgumentException}. This is testing that {@link SystemJobInfoConverter#convert} |
| * sets some dummy constraint to toggle some internal boolean flags in {@link JobInfo.Builder} |
| * to allow {@link OneTimeWorkRequest} with no constraints to be converted without affecting its |
| * runtime, e.g. calling builder.setMinLatencyMillis(0L). |
| */ |
| @Test |
| @SmallTest |
| public void testConvert_noConstraints_doesNotThrowException() { |
| mConverter.convert(new WorkSpec("id", TestWorker.class.getName()), JOB_ID); |
| } |
| |
| @Test |
| @SmallTest |
| public void testConvert_retryPolicy() { |
| long expectedBackoffDelayDuration = 50000; |
| WorkSpec workSpec = new WorkSpec("id", TestWorker.class.getName()); |
| workSpec.setBackoffDelayDuration(expectedBackoffDelayDuration); |
| workSpec.backoffPolicy = BackoffPolicy.LINEAR; |
| JobInfo jobInfo = mConverter.convert(workSpec, JOB_ID); |
| assertThat(jobInfo.getInitialBackoffMillis(), is(expectedBackoffDelayDuration)); |
| assertThat(jobInfo.getBackoffPolicy(), is(JobInfo.BACKOFF_POLICY_LINEAR)); |
| } |
| |
| @Test |
| @SmallTest |
| public void testConvert_initialDelay() { |
| final long expectedInitialDelay = 12123L; |
| WorkSpec workSpec = new WorkSpec("id", TestWorker.class.getName()); |
| workSpec.initialDelay = expectedInitialDelay; |
| JobInfo jobInfo = mConverter.convert(workSpec, JOB_ID); |
| assertCloseValues(jobInfo.getMinLatencyMillis(), expectedInitialDelay); |
| } |
| |
| @Test |
| @SmallTest |
| public void testConvert_periodicWithNoFlex() { |
| WorkSpec workSpec = new WorkSpec("id", TestWorker.class.getName()); |
| workSpec.setPeriodic(TEST_INTERVAL_DURATION); |
| JobInfo jobInfo = mConverter.convert(workSpec, JOB_ID); |
| assertThat(jobInfo.getMinLatencyMillis(), is(0L)); |
| } |
| |
| @Test |
| @SmallTest |
| public void testConvert_periodicWithFlex() { |
| WorkSpec workSpec = new WorkSpec("id", TestWorker.class.getName()); |
| workSpec.setPeriodic(TEST_INTERVAL_DURATION, TEST_FLEX_DURATION); |
| JobInfo jobInfo = mConverter.convert(workSpec, JOB_ID); |
| assertCloseValues(jobInfo.getMinLatencyMillis(), |
| TEST_INTERVAL_DURATION - TEST_FLEX_DURATION); |
| } |
| |
| @Test |
| @SmallTest |
| public void testConvert_requireCharging() { |
| final boolean expectedRequireCharging = true; |
| WorkSpec workSpec = getTestWorkSpecWithConstraints(new Constraints.Builder() |
| .setRequiresCharging(expectedRequireCharging).build()); |
| JobInfo jobInfo = mConverter.convert(workSpec, JOB_ID); |
| assertThat(jobInfo.isRequireCharging(), is(expectedRequireCharging)); |
| } |
| |
| @Test |
| @SmallTest |
| @SdkSuppress(minSdkVersion = 24) |
| public void testConvert_requireContentUriTrigger() { |
| final Uri expectedUri = Uri.parse("TEST_URI"); |
| final JobInfo.TriggerContentUri expectedTriggerContentUri = |
| new JobInfo.TriggerContentUri( |
| expectedUri, JobInfo.TriggerContentUri.FLAG_NOTIFY_FOR_DESCENDANTS); |
| WorkSpec workSpec = getTestWorkSpecWithConstraints(new Constraints.Builder() |
| .addContentUriTrigger(expectedUri, true) |
| .setTriggerContentUpdateDelay(5, TimeUnit.SECONDS) |
| .setTriggerContentMaxDelay(10, TimeUnit.SECONDS) |
| .build()); |
| JobInfo jobInfo = mConverter.convert(workSpec, JOB_ID); |
| |
| JobInfo.TriggerContentUri[] triggerContentUris = jobInfo.getTriggerContentUris(); |
| assertThat(triggerContentUris, is(arrayContaining(expectedTriggerContentUri))); |
| assertThat(jobInfo.getTriggerContentUpdateDelay(), is(TimeUnit.SECONDS.toMillis(5))); |
| assertThat(jobInfo.getTriggerContentMaxDelay(), is(TimeUnit.SECONDS.toMillis(10))); |
| } |
| |
| @Test |
| @SmallTest |
| public void testConvert_requireDeviceIdle() { |
| final boolean expectedRequireDeviceIdle = true; |
| WorkSpec workSpec = getTestWorkSpecWithConstraints(new Constraints.Builder() |
| .setRequiresDeviceIdle(expectedRequireDeviceIdle).build()); |
| JobInfo jobInfo = mConverter.convert(workSpec, JOB_ID); |
| assertThat(jobInfo.isRequireDeviceIdle(), is(expectedRequireDeviceIdle)); |
| } |
| |
| @Test |
| @SmallTest |
| @SdkSuppress(minSdkVersion = 26) |
| public void testConvert_requireBatteryNotLow() { |
| final boolean expectedRequireBatteryNotLow = true; |
| WorkSpec workSpec = getTestWorkSpecWithConstraints(new Constraints.Builder() |
| .setRequiresBatteryNotLow(expectedRequireBatteryNotLow).build()); |
| JobInfo jobInfo = mConverter.convert(workSpec, JOB_ID); |
| assertThat(jobInfo.isRequireBatteryNotLow(), is(expectedRequireBatteryNotLow)); |
| } |
| |
| @Test |
| @SmallTest |
| @SdkSuppress(minSdkVersion = 26) |
| public void testConvert_requireStorageNotLow() { |
| final boolean expectedRequireStorageNotLow = true; |
| WorkSpec workSpec = getTestWorkSpecWithConstraints(new Constraints.Builder() |
| .setRequiresStorageNotLow(expectedRequireStorageNotLow).build()); |
| JobInfo jobInfo = mConverter.convert(workSpec, JOB_ID); |
| assertThat(jobInfo.isRequireStorageNotLow(), is(expectedRequireStorageNotLow)); |
| } |
| |
| @Test |
| @SmallTest |
| public void testConvert_networkTypeNotRoamingRequiresApi24() { |
| convertWithRequiredNetworkType(NOT_ROAMING, JobInfo.NETWORK_TYPE_NOT_ROAMING, 24); |
| } |
| |
| @Test |
| @SmallTest |
| public void testConvert_networkTypeMeteredRequiresApi26() { |
| convertWithRequiredNetworkType(METERED, JobInfo.NETWORK_TYPE_METERED, 26); |
| } |
| |
| @Test |
| @SmallTest |
| @SdkSuppress(minSdkVersion = 29) |
| public void testConvert_setImportantWhileForeground() { |
| WorkSpec workSpec = getTestWorkSpecWithConstraints(new Constraints.Builder().build()); |
| JobInfo jobInfo = mConverter.convert(workSpec, JOB_ID); |
| assertThat(jobInfo.isImportantWhileForeground(), is(true)); |
| } |
| |
| @Test |
| @SmallTest |
| @SdkSuppress(minSdkVersion = 29) |
| public void testConvert_setImportantWhileForeground_withTimingConstraints() { |
| WorkSpec workSpec = new WorkSpec("id", TestWorker.class.getName()); |
| workSpec.setPeriodic(TEST_INTERVAL_DURATION, TEST_FLEX_DURATION); |
| JobInfo jobInfo = mConverter.convert(workSpec, JOB_ID); |
| assertThat(jobInfo.isImportantWhileForeground(), is(false)); |
| } |
| |
| private void convertWithRequiredNetworkType(NetworkType networkType, |
| int jobInfoNetworkType, |
| int minSdkVersion) { |
| WorkSpec workSpec = getTestWorkSpecWithConstraints(new Constraints.Builder() |
| .setRequiredNetworkType(networkType).build()); |
| JobInfo jobInfo = mConverter.convert(workSpec, JOB_ID); |
| if (Build.VERSION.SDK_INT >= minSdkVersion) { |
| assertThat(jobInfo.getNetworkType(), is(jobInfoNetworkType)); |
| } else { |
| assertThat(jobInfo.getNetworkType(), is(JobInfo.NETWORK_TYPE_ANY)); |
| } |
| } |
| |
| @Test |
| @SmallTest |
| public void testConvertNetworkType_none() { |
| assertThat(SystemJobInfoConverter.convertNetworkType(NOT_REQUIRED), |
| is(JobInfo.NETWORK_TYPE_NONE)); |
| } |
| |
| @Test |
| @SmallTest |
| public void testConvertNetworkType_any() { |
| assertThat(SystemJobInfoConverter.convertNetworkType(CONNECTED), |
| is(JobInfo.NETWORK_TYPE_ANY)); |
| } |
| |
| @Test |
| @SmallTest |
| public void testConvertNetworkType_unmetered() { |
| assertThat(SystemJobInfoConverter.convertNetworkType(UNMETERED), |
| is(JobInfo.NETWORK_TYPE_UNMETERED)); |
| } |
| |
| @Test |
| @SmallTest |
| @SdkSuppress(minSdkVersion = 23, maxSdkVersion = 23) |
| public void testConvertNetworkType_notRoaming_returnAnyBeforeApi24() { |
| assertThat(SystemJobInfoConverter.convertNetworkType(NOT_ROAMING), |
| is(JobInfo.NETWORK_TYPE_ANY)); |
| } |
| |
| @Test |
| @SmallTest |
| @SdkSuppress(minSdkVersion = 24) |
| public void testConvertNetworkType_notRoaming_returnsNotRoamingAtOrAfterApi24() { |
| assertThat(SystemJobInfoConverter.convertNetworkType(NOT_ROAMING), |
| is(JobInfo.NETWORK_TYPE_NOT_ROAMING)); |
| } |
| |
| @Test |
| @SmallTest |
| @SdkSuppress(minSdkVersion = WorkManagerImpl.MIN_JOB_SCHEDULER_API_LEVEL, maxSdkVersion = 25) |
| public void testConvertNetworkType_metered_returnsAnyBeforeApi26() { |
| assertThat(SystemJobInfoConverter.convertNetworkType(METERED), |
| is(JobInfo.NETWORK_TYPE_ANY)); |
| } |
| |
| @Test |
| @SmallTest |
| @SdkSuppress(minSdkVersion = 26) |
| public void testConvertNetworkType_metered_returnsMeteredAtOrAfterApi26() { |
| assertThat(SystemJobInfoConverter.convertNetworkType(METERED), |
| is(JobInfo.NETWORK_TYPE_METERED)); |
| } |
| |
| private WorkSpec getTestWorkSpecWithConstraints(Constraints constraints) { |
| return getWorkSpec(new OneTimeWorkRequest.Builder(TestWorker.class) |
| .setConstraints(constraints) |
| .build()); |
| } |
| |
| private void assertCloseValues(long value, long target) { |
| double min = Math.min(value, target); |
| double max = Math.max(value, target); |
| double ratio = min / max; |
| assertThat(ratio, greaterThanOrEqualTo(0.999d)); |
| } |
| } |