blob: 547c3ac8d5f204a2f7cf9177f61aaa59a4c23771 [file] [log] [blame]
/*
* Copyright 2019 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.gcm
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SdkSuppress
import androidx.test.filters.SmallTest
import androidx.work.Constraints
import androidx.work.NetworkType
import androidx.work.OneTimeWorkRequestBuilder
import androidx.work.PeriodicWorkRequestBuilder
import androidx.work.impl.WorkManagerImpl
import androidx.work.impl.background.gcm.GcmTaskConverter.EXECUTION_WINDOW_SIZE_IN_SECONDS
import com.google.android.gms.gcm.Task
import org.hamcrest.Matchers.greaterThan
import org.hamcrest.Matchers.lessThanOrEqualTo
import org.junit.Assert.assertEquals
import org.junit.Assert.assertThat
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mockito.`when`
import org.mockito.Mockito.spy
import java.util.concurrent.TimeUnit
@RunWith(AndroidJUnit4::class)
@SmallTest
class GcmTaskConverterTest {
lateinit var mTaskConverter: GcmTaskConverter
@Before
fun setUp() {
mTaskConverter = spy(GcmTaskConverter())
}
@Test
fun testOneTimeRequest_noInitialDelay() {
val now = System.currentTimeMillis()
`when`(mTaskConverter.now()).thenReturn(now)
val request = OneTimeWorkRequestBuilder<TestWorker>().build()
val task = mTaskConverter.convert(request.workSpec)
val expected = request.workSpec.calculateNextRunTime()
val offset = offset(expected, now)
val delta = task.windowEnd - (offset + EXECUTION_WINDOW_SIZE_IN_SECONDS)
assertEquals(task.serviceName, WorkManagerGcmService::class.java.name)
assertEquals(task.isPersisted, false)
assertEquals(task.isUpdateCurrent, true)
assertEquals(task.requiredNetwork, Task.NETWORK_STATE_ANY)
assertEquals(task.requiresCharging, false)
assertEquals(task.windowStart, offset)
// Account for time unit quantization errors
assertThat(delta, lessThanOrEqualTo(1L))
}
@Test
fun testOneTimeRequest_noInitialDelay_withConstraintNetworkConnected() {
val now = System.currentTimeMillis()
`when`(mTaskConverter.now()).thenReturn(now)
val constraints = Constraints.Builder()
.setRequiredNetworkType(NetworkType.METERED)
.setRequiresCharging(true)
.build()
val request = OneTimeWorkRequestBuilder<TestWorker>()
.setConstraints(constraints)
.build()
val task = mTaskConverter.convert(request.workSpec)
val expected = request.workSpec.calculateNextRunTime()
val offset = offset(expected, now)
val delta = task.windowEnd - (offset + EXECUTION_WINDOW_SIZE_IN_SECONDS)
assertEquals(task.serviceName, WorkManagerGcmService::class.java.name)
assertEquals(task.isPersisted, false)
assertEquals(task.isUpdateCurrent, true)
assertEquals(task.requiredNetwork, Task.NETWORK_STATE_CONNECTED)
assertEquals(task.requiresCharging, true)
assertEquals(task.windowStart, offset)
// Account for time unit quantization errors
assertThat(delta, lessThanOrEqualTo(1L))
}
@Test
fun testOneTimeRequest_noInitialDelay_withConstraintNetworkUnMetered() {
val now = System.currentTimeMillis()
`when`(mTaskConverter.now()).thenReturn(now)
val constraints = Constraints.Builder()
.setRequiredNetworkType(NetworkType.UNMETERED)
.build()
val request = OneTimeWorkRequestBuilder<TestWorker>()
.setConstraints(constraints)
.build()
val task = mTaskConverter.convert(request.workSpec)
val expected = request.workSpec.calculateNextRunTime()
val offset = offset(expected, now)
val delta = task.windowEnd - (offset + EXECUTION_WINDOW_SIZE_IN_SECONDS)
assertEquals(task.serviceName, WorkManagerGcmService::class.java.name)
assertEquals(task.isPersisted, false)
assertEquals(task.isUpdateCurrent, true)
assertEquals(task.requiredNetwork, Task.NETWORK_STATE_UNMETERED)
assertEquals(task.requiresCharging, false)
assertEquals(task.windowStart, offset)
// Account for time unit quantization errors
assertThat(delta, lessThanOrEqualTo(1L))
}
@Test
fun testOneTimeRequest_hasInitialDelay() {
val initialDelay = 10L
val now = System.currentTimeMillis()
`when`(mTaskConverter.now()).thenReturn(now)
val request = OneTimeWorkRequestBuilder<TestWorker>()
.setInitialDelay(initialDelay, TimeUnit.SECONDS)
.build()
val task = mTaskConverter.convert(request.workSpec)
val expected = request.workSpec.calculateNextRunTime()
val offset = offset(expected, now)
val delta = task.windowEnd - (offset + EXECUTION_WINDOW_SIZE_IN_SECONDS)
assertEquals(task.serviceName, WorkManagerGcmService::class.java.name)
assertEquals(task.isPersisted, false)
assertEquals(task.isUpdateCurrent, true)
assertEquals(task.requiredNetwork, Task.NETWORK_STATE_ANY)
assertEquals(task.requiresCharging, false)
assertEquals(task.windowStart, offset)
// Account for time unit quantization errors
assertThat(delta, lessThanOrEqualTo(1L))
}
@Test
fun testOneTimeWorkRequest_backedOff() {
val now = System.currentTimeMillis()
`when`(mTaskConverter.now()).thenReturn(now)
val request = OneTimeWorkRequestBuilder<TestWorker>()
.setInitialRunAttemptCount(1)
.build()
val workSpec = request.workSpec
val task = mTaskConverter.convert(request.workSpec)
val expected = workSpec.calculateNextRunTime()
val offset = offset(expected, now)
val delta = task.windowEnd - (offset + EXECUTION_WINDOW_SIZE_IN_SECONDS)
assertEquals(task.serviceName, WorkManagerGcmService::class.java.name)
assertEquals(task.isPersisted, false)
assertEquals(task.isUpdateCurrent, true)
assertEquals(task.requiredNetwork, Task.NETWORK_STATE_ANY)
assertEquals(task.requiresCharging, false)
assertEquals(task.windowStart, offset)
// Account for time unit quantization errors
assertThat(delta, lessThanOrEqualTo(1L))
}
@Test
@SdkSuppress(maxSdkVersion = WorkManagerImpl.MAX_PRE_JOB_SCHEDULER_API_LEVEL)
fun testPeriodicWorkRequest_firstRun() {
val now = System.currentTimeMillis()
`when`(mTaskConverter.now()).thenReturn(now)
val request = PeriodicWorkRequestBuilder<TestWorker>(15L, TimeUnit.MINUTES)
.build()
val task = mTaskConverter.convert(request.workSpec)
val expected = request.workSpec.calculateNextRunTime()
val offset = offset(expected, now)
val delta = task.windowEnd - (offset + EXECUTION_WINDOW_SIZE_IN_SECONDS)
assertEquals(task.serviceName, WorkManagerGcmService::class.java.name)
assertEquals(task.isPersisted, false)
assertEquals(task.isUpdateCurrent, true)
assertEquals(task.requiredNetwork, Task.NETWORK_STATE_ANY)
assertEquals(task.requiresCharging, false)
assertEquals(task.windowStart, offset)
// Account for time unit quantization errors
assertThat(delta, lessThanOrEqualTo(1L))
}
@Test
@SdkSuppress(maxSdkVersion = WorkManagerImpl.MAX_PRE_JOB_SCHEDULER_API_LEVEL)
fun testPeriodicWorkRequest_withFlex_firstRun() {
val request = PeriodicWorkRequestBuilder<TestWorker>(
15L, TimeUnit.MINUTES, 5, TimeUnit.MINUTES
).build()
val task = mTaskConverter.convert(request.workSpec)
assertEquals(task.serviceName, WorkManagerGcmService::class.java.name)
assertEquals(task.isPersisted, false)
assertEquals(task.isUpdateCurrent, true)
assertEquals(task.requiredNetwork, Task.NETWORK_STATE_ANY)
assertEquals(task.requiresCharging, false)
assertThat(task.windowStart, greaterThan(0L)) // should be in the future
}
@Test
@SdkSuppress(maxSdkVersion = WorkManagerImpl.MAX_PRE_JOB_SCHEDULER_API_LEVEL)
fun testPeriodicWorkRequest_withFlex_nextRun() {
val now = System.currentTimeMillis()
`when`(mTaskConverter.now()).thenReturn(now)
val request = PeriodicWorkRequestBuilder<TestWorker>(
15L, TimeUnit.MINUTES, 5, TimeUnit.MINUTES
).build()
request.workSpec.periodStartTime = now
val expected = TimeUnit.MINUTES.toSeconds(15L)
val task = mTaskConverter.convert(request.workSpec)
assertEquals(task.serviceName, WorkManagerGcmService::class.java.name)
assertEquals(task.isPersisted, false)
assertEquals(task.isUpdateCurrent, true)
assertEquals(task.requiredNetwork, Task.NETWORK_STATE_ANY)
assertEquals(task.requiresCharging, false)
assertEquals(task.windowStart, expected)
assertEquals(task.windowEnd, expected + EXECUTION_WINDOW_SIZE_IN_SECONDS)
}
private fun offset(expected: Long, now: Long): Long {
val delta = Math.max(expected - now, 0)
return TimeUnit.SECONDS.convert(delta, TimeUnit.MILLISECONDS)
}
}