blob: 89a0e4d0dea38882a32e2f4ba850890f7ddea8d9 [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 deltaStart = task.windowStart - offset
val deltaEnd = 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)
// Account for time unit quantization errors
assertThat(deltaStart, lessThanOrEqualTo(1L))
assertThat(deltaEnd, 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 deltaStart = task.windowStart - offset
val deltaEnd = 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)
// Account for time unit quantization errors
assertThat(deltaStart, lessThanOrEqualTo(1L))
assertThat(deltaEnd, 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 deltaStart = task.windowStart - offset
val deltaEnd = 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)
// Account for time unit quantization errors
assertThat(deltaStart, lessThanOrEqualTo(1L))
assertThat(deltaEnd, 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 deltaStart = task.windowStart - offset
val deltaEnd = 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)
// Account for time unit quantization errors
assertThat(deltaStart, lessThanOrEqualTo(1L))
assertThat(deltaEnd, 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 deltaStart = task.windowStart - offset
val deltaEnd = 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)
// Account for time unit quantization errors
assertThat(deltaStart, lessThanOrEqualTo(1L))
assertThat(deltaEnd, 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 deltaStart = task.windowStart - offset
val deltaEnd = 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)
// Account for time unit quantization errors
assertThat(deltaStart, lessThanOrEqualTo(1L))
assertThat(deltaEnd, 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)
}
}