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 17 package androidx.work.impl.background.firebase; 18 19 import static androidx.work.NetworkType.CONNECTED; 20 import static androidx.work.NetworkType.METERED; 21 import static androidx.work.NetworkType.NOT_ROAMING; 22 import static androidx.work.NetworkType.UNMETERED; 23 24 import static org.hamcrest.MatcherAssert.assertThat; 25 import static org.hamcrest.Matchers.contains; 26 import static org.hamcrest.Matchers.instanceOf; 27 import static org.hamcrest.core.Is.is; 28 29 import android.content.Context; 30 import android.net.Uri; 31 import android.support.test.InstrumentationRegistry; 32 import android.support.test.filters.SdkSuppress; 33 import android.support.test.filters.SmallTest; 34 import android.support.test.runner.AndroidJUnit4; 35 36 import androidx.work.BackoffPolicy; 37 import androidx.work.Constraints; 38 import androidx.work.OneTimeWorkRequest; 39 import androidx.work.PeriodicWorkRequest; 40 import androidx.work.impl.model.WorkSpec; 41 import androidx.work.impl.utils.PackageManagerHelper; 42 import androidx.work.worker.FirebaseTestWorker; 43 44 import com.firebase.jobdispatcher.Constraint; 45 import com.firebase.jobdispatcher.FirebaseJobDispatcher; 46 import com.firebase.jobdispatcher.GooglePlayDriver; 47 import com.firebase.jobdispatcher.Job; 48 import com.firebase.jobdispatcher.JobTrigger; 49 import com.firebase.jobdispatcher.Lifetime; 50 import com.firebase.jobdispatcher.ObservedUri; 51 import com.firebase.jobdispatcher.RetryStrategy; 52 import com.firebase.jobdispatcher.Trigger; 53 54 import org.hamcrest.MatcherAssert; 55 import org.junit.Before; 56 import org.junit.Test; 57 import org.junit.runner.RunWith; 58 59 import java.util.List; 60 import java.util.concurrent.TimeUnit; 61 62 @RunWith(AndroidJUnit4.class) 63 public class FirebaseJobConverterTest { 64 private FirebaseJobConverter mConverter; 65 66 @Before 67 public void setUp() { 68 Context context = InstrumentationRegistry.getTargetContext().getApplicationContext(); 69 PackageManagerHelper.setComponentEnabled(context, FirebaseJobService.class, true); 70 FirebaseJobDispatcher dispatcher = new FirebaseJobDispatcher(new GooglePlayDriver(context)); 71 mConverter = new FirebaseJobConverter(dispatcher); 72 } 73 74 @Test 75 @SmallTest 76 public void testConvert_basicWorkSpec() { 77 final String expectedWorkSpecId = "026e3422-9cd1-11e7-abc4-cec278b6b50a"; 78 WorkSpec workSpec = new WorkSpec(expectedWorkSpecId, FirebaseTestWorker.class.getName()); 79 Job job = mConverter.convert(workSpec); 80 assertThat(job.getTag(), is(expectedWorkSpecId)); 81 assertThat(job.getLifetime(), is(Lifetime.FOREVER)); 82 assertThat(job.getService(), is(FirebaseJobService.class.getName())); 83 84 JobTrigger.ImmediateTrigger trigger = (JobTrigger.ImmediateTrigger) job.getTrigger(); 85 assertThat(trigger, is(Trigger.NOW)); 86 } 87 88 @Test 89 @SmallTest 90 public void testConvert_backoffPolicy() { 91 long givenBackoffDelayDuration = 50000L; 92 WorkSpec workSpec = new WorkSpec("id", FirebaseTestWorker.class.getName()); 93 workSpec.setBackoffDelayDuration(givenBackoffDelayDuration); 94 workSpec.backoffPolicy = BackoffPolicy.LINEAR; 95 Job job = mConverter.convert(workSpec); 96 97 int expectedBackoffDelayDuration = (int) TimeUnit.SECONDS 98 .convert(givenBackoffDelayDuration, TimeUnit.MILLISECONDS); 99 assertThat(job.getRetryStrategy().getInitialBackoff(), is(expectedBackoffDelayDuration)); 100 assertThat(job.getRetryStrategy().getPolicy(), is(RetryStrategy.RETRY_POLICY_LINEAR)); 101 } 102 103 @Test 104 @SmallTest 105 public void testConvert_initialDelay() { 106 long givenInitialDelayDuration = 50000L; 107 WorkSpec workSpec = new WorkSpec("id", FirebaseTestWorker.class.getName()); 108 workSpec.initialDelay = givenInitialDelayDuration; 109 Job job = mConverter.convert(workSpec); 110 111 // Initial delay is handled via an AlarmManager broadcast 112 assertThat(job.getTrigger(), is(instanceOf(JobTrigger.ImmediateTrigger.class))); 113 } 114 115 @Test 116 @SmallTest 117 @SdkSuppress(minSdkVersion = 24) 118 public void testConvert_requireContentUriTrigger() { 119 final Uri expectedUri = Uri.parse("TEST_URI"); 120 final ObservedUri expectedObservedUri = 121 new ObservedUri(expectedUri, ObservedUri.Flags.FLAG_NOTIFY_FOR_DESCENDANTS); 122 WorkSpec workSpec = new OneTimeWorkRequest.Builder(FirebaseTestWorker.class) 123 .setConstraints(new Constraints.Builder() 124 .addContentUriTrigger(expectedUri, true) 125 .build()) 126 .build() 127 .getWorkSpec(); 128 Job job = mConverter.convert(workSpec); 129 130 JobTrigger.ContentUriTrigger trigger = (JobTrigger.ContentUriTrigger) job.getTrigger(); 131 List<ObservedUri> observedUriList = trigger.getUris(); 132 MatcherAssert.assertThat(observedUriList, contains(expectedObservedUri)); 133 } 134 135 @Test 136 @SmallTest 137 public void testConvert_requiresCharging() { 138 WorkSpec workSpec = new OneTimeWorkRequest.Builder(FirebaseTestWorker.class) 139 .setConstraints(new Constraints.Builder() 140 .setRequiresCharging(true) 141 .build()) 142 .build() 143 .getWorkSpec(); 144 Job job = mConverter.convert(workSpec); 145 assertHasIntInArray(job.getConstraints(), Constraint.DEVICE_CHARGING); 146 } 147 148 @Test 149 @SmallTest 150 public void testConvert_periodic() { 151 long testInterval = PeriodicWorkRequest.MIN_PERIODIC_INTERVAL_MILLIS; 152 long testFlex = PeriodicWorkRequest.MIN_PERIODIC_INTERVAL_MILLIS; 153 154 int expectedWindowEndSeconds = 155 FirebaseJobConverter.convertMillisecondsToSeconds(testInterval); 156 int flexSeconds = FirebaseJobConverter.convertMillisecondsToSeconds(testFlex); 157 int expectedWindowStartSeconds = expectedWindowEndSeconds - flexSeconds; 158 159 WorkSpec workSpec = new WorkSpec("id", FirebaseTestWorker.class.getName()); 160 workSpec.setPeriodic(testInterval); 161 Job job = mConverter.convert(workSpec); 162 163 JobTrigger.ExecutionWindowTrigger trigger = 164 (JobTrigger.ExecutionWindowTrigger) job.getTrigger(); 165 assertThat(trigger.getWindowEnd(), is(expectedWindowEndSeconds)); 166 assertThat(trigger.getWindowStart(), is(expectedWindowStartSeconds)); 167 } 168 169 @Test 170 @SmallTest 171 @SdkSuppress(minSdkVersion = 23) 172 public void testConvert_requiresDeviceIdle() { 173 WorkSpec workSpec = new OneTimeWorkRequest.Builder(FirebaseTestWorker.class) 174 .setConstraints(new Constraints.Builder() 175 .setRequiresDeviceIdle(true) 176 .build()) 177 .build() 178 .getWorkSpec(); 179 Job job = mConverter.convert(workSpec); 180 assertHasIntInArray(job.getConstraints(), Constraint.DEVICE_IDLE); 181 } 182 183 @Test 184 @SmallTest 185 public void testConvert_requiresNetworkAny() { 186 WorkSpec workSpec = new OneTimeWorkRequest.Builder(FirebaseTestWorker.class) 187 .setConstraints(new Constraints.Builder() 188 .setRequiredNetworkType(CONNECTED) 189 .build()) 190 .build() 191 .getWorkSpec(); 192 Job job = mConverter.convert(workSpec); 193 assertHasIntInArray(job.getConstraints(), Constraint.ON_ANY_NETWORK); 194 } 195 196 @Test 197 @SmallTest 198 public void testConvert_requiresNetworkMetered_unsupported() { 199 WorkSpec workSpec = new OneTimeWorkRequest.Builder(FirebaseTestWorker.class) 200 .setConstraints(new Constraints.Builder() 201 .setRequiredNetworkType(METERED) 202 .build()) 203 .build() 204 .getWorkSpec(); 205 Job job = mConverter.convert(workSpec); 206 assertHasIntInArray(job.getConstraints(), Constraint.ON_ANY_NETWORK); 207 } 208 209 @Test 210 @SmallTest 211 public void testConvert_requiresNetworkNotRoaming_unsupported() { 212 WorkSpec workSpec = new OneTimeWorkRequest.Builder(FirebaseTestWorker.class) 213 .setConstraints(new Constraints.Builder() 214 .setRequiredNetworkType(NOT_ROAMING) 215 .build()) 216 .build() 217 .getWorkSpec(); 218 Job job = mConverter.convert(workSpec); 219 assertHasIntInArray(job.getConstraints(), Constraint.ON_ANY_NETWORK); 220 } 221 222 @Test 223 @SmallTest 224 public void testConvert_requiresNetworkUnmetered() { 225 WorkSpec workSpec = new OneTimeWorkRequest.Builder(FirebaseTestWorker.class) 226 .setConstraints(new Constraints.Builder() 227 .setRequiredNetworkType(UNMETERED) 228 .build()) 229 .build() 230 .getWorkSpec(); 231 Job job = mConverter.convert(workSpec); 232 assertHasIntInArray(job.getConstraints(), Constraint.ON_UNMETERED_NETWORK); 233 } 234 235 private void assertHasIntInArray(int[] array, int expectedItem) { 236 boolean found = false; 237 for (int item : array) { 238 if (item == expectedItem) { 239 found = true; 240 break; 241 } 242 } 243 assertThat(found, is(true)); 244 } 245 } 246