mirror of
https://github.com/afollestad/nock-nock.git
synced 2025-09-04 08:36:13 +00:00
Update ValidationExecutorTest
This commit is contained in:
parent
8535a6fe8b
commit
6bb131fb23
6 changed files with 378 additions and 109 deletions
|
@ -19,12 +19,13 @@ import android.app.PendingIntent
|
|||
import android.content.Intent
|
||||
import android.content.IntentFilter
|
||||
import com.afollestad.nocknock.data.AppDatabase
|
||||
import com.afollestad.nocknock.data.model.RetryPolicy
|
||||
import com.afollestad.nocknock.data.HeaderDao
|
||||
import com.afollestad.nocknock.data.RetryPolicyDao
|
||||
import com.afollestad.nocknock.data.SiteDao
|
||||
import com.afollestad.nocknock.data.SiteSettingsDao
|
||||
import com.afollestad.nocknock.data.ValidationResultsDao
|
||||
import com.afollestad.nocknock.data.model.Header
|
||||
import com.afollestad.nocknock.data.model.RetryPolicy
|
||||
import com.afollestad.nocknock.data.model.Site
|
||||
import com.afollestad.nocknock.data.model.SiteSettings
|
||||
import com.afollestad.nocknock.data.model.Status
|
||||
|
@ -56,7 +57,8 @@ fun fakeSettingsModel(
|
|||
validationMode = validationMode,
|
||||
validationArgs = null,
|
||||
disabled = false,
|
||||
networkTimeout = 10000
|
||||
networkTimeout = 10000,
|
||||
certificate = null
|
||||
)
|
||||
|
||||
fun fakeResultModel(
|
||||
|
@ -165,12 +167,29 @@ fun mockDatabase(): AppDatabase {
|
|||
on { update(isA()) } doReturn 1
|
||||
on { delete(isA()) } doReturn 1
|
||||
}
|
||||
val headerDao = mock<HeaderDao> {
|
||||
on { all() } doReturn com.afollestad.nocknock.engine.MOCK_MODEL_1.headers + com.afollestad.nocknock.engine.MOCK_MODEL_2.headers + com.afollestad.nocknock.engine.MOCK_MODEL_3.headers
|
||||
on { forSite(isA()) } doAnswer { inv ->
|
||||
val id = inv.getArgument<Long>(0)
|
||||
return@doAnswer when (id) {
|
||||
1L -> com.afollestad.nocknock.engine.MOCK_MODEL_1.headers
|
||||
2L -> com.afollestad.nocknock.engine.MOCK_MODEL_2.headers
|
||||
3L -> com.afollestad.nocknock.engine.MOCK_MODEL_3.headers
|
||||
else -> listOf()
|
||||
}
|
||||
}
|
||||
on { insert(isA<Header>()) } doReturn 1L
|
||||
on { insert(isA<List<Header>>()) } doReturn listOf(1L, 2L)
|
||||
on { update(isA()) } doReturn 1
|
||||
on { delete(isA()) } doReturn 1
|
||||
}
|
||||
|
||||
return mock {
|
||||
on { siteDao() } doReturn siteDao
|
||||
on { siteSettingsDao() } doReturn settingsDao
|
||||
on { validationResultsDao() } doReturn resultsDao
|
||||
on { retryPolicyDao() } doReturn retryDao
|
||||
on { headerDao() } doReturn headerDao
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ import android.app.Application
|
|||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import androidx.annotation.CheckResult
|
||||
import com.afollestad.nocknock.utilities.ext.toUri
|
||||
import okhttp3.OkHttpClient
|
||||
import java.io.BufferedInputStream
|
||||
import java.io.FileInputStream
|
||||
|
@ -33,8 +34,8 @@ import timber.log.Timber.d as log
|
|||
interface SslManager {
|
||||
|
||||
@CheckResult fun clientForCertificate(
|
||||
certUri: Uri,
|
||||
host: String,
|
||||
certUri: String,
|
||||
siteUri: String,
|
||||
client: OkHttpClient
|
||||
): OkHttpClient
|
||||
}
|
||||
|
@ -45,21 +46,25 @@ class RealSslManager(
|
|||
) : SslManager {
|
||||
|
||||
override fun clientForCertificate(
|
||||
certUri: Uri,
|
||||
host: String,
|
||||
certUri: String,
|
||||
siteUri: String,
|
||||
client: OkHttpClient
|
||||
): OkHttpClient {
|
||||
log("Loading certificate $certUri for host $host")
|
||||
val parsedCertUri = certUri.toUri()
|
||||
val parsedSiteUri = siteUri.toUri()
|
||||
val siteHost = parsedSiteUri.host ?: ""
|
||||
|
||||
log("Loading certificate $certUri for host $siteHost")
|
||||
val keyStore = KeyStore.getInstance(KeyStore.getDefaultType())
|
||||
keyStore.load(null, null)
|
||||
|
||||
val certInputStream = app.openUri(certUri)
|
||||
val certInputStream = app.openUri(parsedCertUri)
|
||||
val bis = BufferedInputStream(certInputStream)
|
||||
val certificateFactory = CertificateFactory.getInstance("X.509")
|
||||
|
||||
while (bis.available() > 0) {
|
||||
val cert = certificateFactory.generateCertificate(bis)
|
||||
keyStore.setCertificateEntry(host, cert)
|
||||
keyStore.setCertificateEntry(siteHost, cert)
|
||||
}
|
||||
|
||||
val trustManagerFactory =
|
||||
|
@ -76,7 +81,7 @@ class RealSslManager(
|
|||
.sslSocketFactory(sslContext.socketFactory, trustManager)
|
||||
.hostnameVerifier { hostname, _ ->
|
||||
log("Verifying hostname $hostname")
|
||||
hostname == host
|
||||
hostname == siteHost
|
||||
}
|
||||
.build()
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ package com.afollestad.nocknock.engine.validation
|
|||
|
||||
import android.app.job.JobScheduler
|
||||
import android.app.job.JobScheduler.RESULT_SUCCESS
|
||||
import android.net.Uri
|
||||
import com.afollestad.nocknock.data.AppDatabase
|
||||
import com.afollestad.nocknock.data.allSites
|
||||
import com.afollestad.nocknock.data.model.Site
|
||||
|
@ -25,7 +26,6 @@ import com.afollestad.nocknock.data.model.Status.OK
|
|||
import com.afollestad.nocknock.engine.R
|
||||
import com.afollestad.nocknock.engine.ssl.SslManager
|
||||
import com.afollestad.nocknock.engine.validation.ValidationJob.Companion.KEY_SITE_ID
|
||||
import com.afollestad.nocknock.utilities.ext.toUri
|
||||
import com.afollestad.nocknock.utilities.providers.BundleProvider
|
||||
import com.afollestad.nocknock.utilities.providers.JobInfoProvider
|
||||
import com.afollestad.nocknock.utilities.providers.StringProvider
|
||||
|
@ -45,6 +45,8 @@ data class CheckResult(
|
|||
|
||||
typealias ClientTimeoutChanger = (client: OkHttpClient, timeout: Int) -> OkHttpClient
|
||||
|
||||
typealias UriConverter = (String) -> Uri
|
||||
|
||||
/** @author Aidan Follestad (@afollestad) */
|
||||
interface ValidationExecutor {
|
||||
|
||||
|
@ -168,8 +170,8 @@ class RealValidationExecutor(
|
|||
val clientWithTimeout = clientTimeoutChanger(okHttpClient, siteSettings.networkTimeout)
|
||||
val client = if (!siteSettings.certificate.isNullOrEmpty()) {
|
||||
sslManager.clientForCertificate(
|
||||
certUri = siteSettings.certificate!!.toUri(),
|
||||
host = site.url.toUri().host ?: "",
|
||||
certUri = siteSettings.certificate!!,
|
||||
siteUri = site.url,
|
||||
client = clientWithTimeout
|
||||
)
|
||||
} else {
|
||||
|
@ -212,9 +214,7 @@ class RealValidationExecutor(
|
|||
jobScheduler.allPendingJobs
|
||||
.firstOrNull { job -> job.id == site.id.toInt() }
|
||||
|
||||
@Suppress("unused")
|
||||
@TestOnly
|
||||
fun setClientTimeoutChanger(changer: ClientTimeoutChanger) {
|
||||
@TestOnly fun setClientTimeoutChanger(changer: ClientTimeoutChanger) {
|
||||
this.clientTimeoutChanger = changer
|
||||
}
|
||||
}
|
||||
|
|
189
engine/src/test/java/com/afollestad/nocknock/engine/TestData.kt
Normal file
189
engine/src/test/java/com/afollestad/nocknock/engine/TestData.kt
Normal file
|
@ -0,0 +1,189 @@
|
|||
/**
|
||||
* Designed and developed by Aidan Follestad (@afollestad)
|
||||
*
|
||||
* 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 com.afollestad.nocknock.engine
|
||||
|
||||
import android.content.Intent
|
||||
import com.afollestad.nocknock.data.AppDatabase
|
||||
import com.afollestad.nocknock.data.HeaderDao
|
||||
import com.afollestad.nocknock.data.RetryPolicyDao
|
||||
import com.afollestad.nocknock.data.SiteDao
|
||||
import com.afollestad.nocknock.data.SiteSettingsDao
|
||||
import com.afollestad.nocknock.data.ValidationResultsDao
|
||||
import com.afollestad.nocknock.data.model.Header
|
||||
import com.afollestad.nocknock.data.model.RetryPolicy
|
||||
import com.afollestad.nocknock.data.model.Site
|
||||
import com.afollestad.nocknock.data.model.SiteSettings
|
||||
import com.afollestad.nocknock.data.model.Status
|
||||
import com.afollestad.nocknock.data.model.Status.OK
|
||||
import com.afollestad.nocknock.data.model.ValidationMode
|
||||
import com.afollestad.nocknock.data.model.ValidationMode.STATUS_CODE
|
||||
import com.afollestad.nocknock.data.model.ValidationResult
|
||||
import com.nhaarman.mockitokotlin2.doAnswer
|
||||
import com.nhaarman.mockitokotlin2.doReturn
|
||||
import com.nhaarman.mockitokotlin2.isA
|
||||
import com.nhaarman.mockitokotlin2.mock
|
||||
import java.lang.System.currentTimeMillis
|
||||
|
||||
fun fakeIntent(action: String): Intent {
|
||||
return mock {
|
||||
on { getAction() } doReturn action
|
||||
}
|
||||
}
|
||||
|
||||
fun fakeSettingsModel(
|
||||
id: Long,
|
||||
validationMode: ValidationMode = STATUS_CODE
|
||||
) = SiteSettings(
|
||||
siteId = id,
|
||||
validationIntervalMs = 600000,
|
||||
validationMode = validationMode,
|
||||
validationArgs = null,
|
||||
disabled = false,
|
||||
networkTimeout = 10000,
|
||||
certificate = null
|
||||
)
|
||||
|
||||
fun fakeResultModel(
|
||||
id: Long,
|
||||
status: Status = OK,
|
||||
reason: String? = null
|
||||
) = ValidationResult(
|
||||
siteId = id,
|
||||
status = status,
|
||||
reason = reason,
|
||||
timestampMs = currentTimeMillis()
|
||||
)
|
||||
|
||||
fun fakeRetryPolicy(
|
||||
id: Long,
|
||||
count: Int = 3,
|
||||
minutes: Int = 6
|
||||
) = RetryPolicy(
|
||||
siteId = id,
|
||||
count = count,
|
||||
minutes = minutes
|
||||
)
|
||||
|
||||
fun fakeHeaders(siteId: Long): List<Header> {
|
||||
return listOf(
|
||||
Header(id = siteId + 1, siteId = siteId, key = "Content-Type", value = "text/html"),
|
||||
Header(id = siteId + 2, siteId = siteId, key = "User-Agent", value = "NockNock")
|
||||
)
|
||||
}
|
||||
|
||||
fun fakeModel(id: Long) = Site(
|
||||
id = id,
|
||||
name = "Test",
|
||||
url = "https://test.com",
|
||||
tags = "",
|
||||
settings = fakeSettingsModel(id),
|
||||
lastResult = fakeResultModel(id),
|
||||
retryPolicy = fakeRetryPolicy(id),
|
||||
headers = fakeHeaders(id)
|
||||
)
|
||||
|
||||
val MOCK_MODEL_1 = fakeModel(1)
|
||||
val MOCK_MODEL_2 = fakeModel(2)
|
||||
val MOCK_MODEL_3 = fakeModel(3)
|
||||
val ALL_MOCK_MODELS = listOf(MOCK_MODEL_1, MOCK_MODEL_2, MOCK_MODEL_3)
|
||||
|
||||
fun mockDatabase(): AppDatabase {
|
||||
val siteDao = mock<SiteDao> {
|
||||
on { insert(isA()) } doReturn 1
|
||||
on { one(isA()) } doAnswer { inv ->
|
||||
val id = inv.getArgument<Long>(0)
|
||||
return@doAnswer when (id) {
|
||||
1L -> listOf(MOCK_MODEL_1)
|
||||
2L -> listOf(MOCK_MODEL_2)
|
||||
3L -> listOf(MOCK_MODEL_3)
|
||||
else -> listOf()
|
||||
}
|
||||
}
|
||||
on { all() } doReturn ALL_MOCK_MODELS
|
||||
on { update(isA()) } doAnswer { inv ->
|
||||
return@doAnswer inv.arguments.size
|
||||
}
|
||||
on { delete(isA()) } doAnswer { inv ->
|
||||
return@doAnswer inv.arguments.size
|
||||
}
|
||||
}
|
||||
val settingsDao = mock<SiteSettingsDao> {
|
||||
on { insert(isA()) } doReturn 1L
|
||||
on { forSite(isA()) } doAnswer { inv ->
|
||||
val id = inv.getArgument<Long>(0)
|
||||
return@doAnswer when (id) {
|
||||
1L -> listOf(MOCK_MODEL_1.settings!!)
|
||||
2L -> listOf(MOCK_MODEL_2.settings!!)
|
||||
3L -> listOf(MOCK_MODEL_3.settings!!)
|
||||
else -> listOf()
|
||||
}
|
||||
}
|
||||
on { update(isA()) } doReturn 1
|
||||
on { delete(isA()) } doReturn 1
|
||||
}
|
||||
val resultsDao = mock<ValidationResultsDao> {
|
||||
on { insert(isA()) } doReturn 1L
|
||||
on { forSite(isA()) } doAnswer { inv ->
|
||||
val id = inv.getArgument<Long>(0)
|
||||
return@doAnswer when (id) {
|
||||
1L -> listOf(MOCK_MODEL_1.lastResult!!)
|
||||
2L -> listOf(MOCK_MODEL_2.lastResult!!)
|
||||
3L -> listOf(MOCK_MODEL_3.lastResult!!)
|
||||
else -> listOf()
|
||||
}
|
||||
}
|
||||
on { update(isA()) } doReturn 1
|
||||
on { delete(isA()) } doReturn 1
|
||||
}
|
||||
val retryDao = mock<RetryPolicyDao> {
|
||||
on { insert(isA()) } doReturn 1L
|
||||
on { forSite(isA()) } doAnswer { inv ->
|
||||
val id = inv.getArgument<Long>(0)
|
||||
return@doAnswer when (id) {
|
||||
1L -> listOf(MOCK_MODEL_1.retryPolicy!!)
|
||||
2L -> listOf(MOCK_MODEL_2.retryPolicy!!)
|
||||
3L -> listOf(MOCK_MODEL_3.retryPolicy!!)
|
||||
else -> listOf()
|
||||
}
|
||||
}
|
||||
on { update(isA()) } doReturn 1
|
||||
on { delete(isA()) } doReturn 1
|
||||
}
|
||||
val headerDao = mock<HeaderDao> {
|
||||
on { all() } doReturn MOCK_MODEL_1.headers + MOCK_MODEL_2.headers + MOCK_MODEL_3.headers
|
||||
on { forSite(isA()) } doAnswer { inv ->
|
||||
val id = inv.getArgument<Long>(0)
|
||||
return@doAnswer when (id) {
|
||||
1L -> MOCK_MODEL_1.headers
|
||||
2L -> MOCK_MODEL_2.headers
|
||||
3L -> MOCK_MODEL_3.headers
|
||||
else -> listOf()
|
||||
}
|
||||
}
|
||||
on { insert(isA<Header>()) } doReturn 1L
|
||||
on { insert(isA<List<Header>>()) } doReturn listOf(1L, 2L)
|
||||
on { update(isA()) } doReturn 1
|
||||
on { delete(isA()) } doReturn 1
|
||||
}
|
||||
|
||||
return mock {
|
||||
on { siteDao() } doReturn siteDao
|
||||
on { siteSettingsDao() } doReturn settingsDao
|
||||
on { validationResultsDao() } doReturn resultsDao
|
||||
on { retryPolicyDao() } doReturn retryDao
|
||||
on { headerDao() } doReturn headerDao
|
||||
}
|
||||
}
|
|
@ -18,6 +18,8 @@ package com.afollestad.nocknock.engine
|
|||
import android.app.job.JobInfo
|
||||
import android.content.ComponentName
|
||||
import android.os.PersistableBundle
|
||||
import com.afollestad.nocknock.data.AppDatabase
|
||||
import com.afollestad.nocknock.data.model.Site
|
||||
import com.afollestad.nocknock.utilities.providers.BundleProvider
|
||||
import com.afollestad.nocknock.utilities.providers.IBundle
|
||||
import com.afollestad.nocknock.utilities.providers.IBundler
|
||||
|
@ -34,11 +36,11 @@ fun testBundleProvider(): BundleProvider {
|
|||
val realBundle = mock<PersistableBundle>()
|
||||
val creator = it.getArgument<IBundler>(0)
|
||||
creator(object : IBundle {
|
||||
override fun putInt(
|
||||
override fun putLong(
|
||||
key: String,
|
||||
value: Int
|
||||
value: Long
|
||||
) {
|
||||
whenever(realBundle.getInt(key)).doReturn(value)
|
||||
whenever(realBundle.getLong(key)).doReturn(value)
|
||||
}
|
||||
})
|
||||
return@doAnswer realBundle
|
||||
|
@ -66,3 +68,21 @@ fun testJobInfoProvider(): JobInfoProvider {
|
|||
}
|
||||
return provider
|
||||
}
|
||||
|
||||
fun AppDatabase.setAllSites(vararg sites: Site) {
|
||||
whenever(siteDao().all()).doReturn(listOf(*sites))
|
||||
for (site in sites) {
|
||||
whenever(siteSettingsDao().forSite(site.id))
|
||||
.doReturn(listOf(site.settings!!))
|
||||
if (site.lastResult != null) {
|
||||
whenever(validationResultsDao().forSite(site.id))
|
||||
.doReturn(listOf(site.lastResult!!))
|
||||
}
|
||||
if (site.retryPolicy != null) {
|
||||
whenever(retryPolicyDao().forSite(site.id))
|
||||
.doReturn(listOf(site.retryPolicy!!))
|
||||
}
|
||||
whenever(headerDao().forSite(site.id))
|
||||
.doReturn(site.headers)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,13 +17,12 @@ package com.afollestad.nocknock.engine
|
|||
|
||||
import android.app.job.JobInfo
|
||||
import android.app.job.JobScheduler
|
||||
import com.afollestad.nocknock.data.legacy.ServerModel
|
||||
import com.afollestad.nocknock.data.model.Header
|
||||
import com.afollestad.nocknock.data.model.Status.ERROR
|
||||
import com.afollestad.nocknock.data.model.Status.OK
|
||||
import com.afollestad.nocknock.data.model.ValidationMode.STATUS_CODE
|
||||
import com.afollestad.nocknock.data.legacy.ServerModelStore
|
||||
import com.afollestad.nocknock.engine.ssl.SslManager
|
||||
import com.afollestad.nocknock.engine.validation.RealValidationExecutor
|
||||
import com.afollestad.nocknock.engine.validation.ValidationJob.Companion.KEY_SITE_ID
|
||||
import com.afollestad.nocknock.engine.validation.RealValidationManager
|
||||
import com.afollestad.nocknock.utilities.providers.StringProvider
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import com.nhaarman.mockitokotlin2.any
|
||||
|
@ -56,15 +55,21 @@ class ValidationExecutorTest {
|
|||
}
|
||||
private val bundleProvider = testBundleProvider()
|
||||
private val jobInfoProvider = testJobInfoProvider()
|
||||
private val store = mock<ServerModelStore>()
|
||||
private val database = mockDatabase()
|
||||
private val sslManager = mock<SslManager> {
|
||||
on { clientForCertificate(any(), any(), any()) } doAnswer { inv ->
|
||||
inv.getArgument<OkHttpClient>(2)
|
||||
}
|
||||
}
|
||||
|
||||
private val manager = RealValidationManager(
|
||||
private val manager = RealValidationExecutor(
|
||||
jobScheduler,
|
||||
okHttpClient,
|
||||
stringProvider,
|
||||
bundleProvider,
|
||||
jobInfoProvider,
|
||||
store
|
||||
database,
|
||||
sslManager
|
||||
).apply {
|
||||
setClientTimeoutChanger { _, timeout ->
|
||||
whenever(okHttpClient.callTimeoutMillis()).doReturn(timeout)
|
||||
|
@ -72,202 +77,241 @@ class ValidationExecutorTest {
|
|||
}
|
||||
}
|
||||
|
||||
@Test fun ensureScheduledChecks_noEnabledSites() = runBlocking {
|
||||
val model1 = fakeModel().copy(disabled = true)
|
||||
whenever(store.get()).doReturn(listOf(model1))
|
||||
@Test fun ensureScheduledValidations_noEnabledSites() = runBlocking {
|
||||
val model1 = fakeModel(id = 1)
|
||||
model1.settings = model1.settings!!.copy(disabled = true)
|
||||
database.setAllSites(model1)
|
||||
|
||||
manager.ensureScheduledChecks()
|
||||
manager.ensureScheduledValidations()
|
||||
|
||||
verifyNoMoreInteractions(jobScheduler)
|
||||
}
|
||||
|
||||
@Test fun ensureScheduledChecks_sitesAlreadyHaveJobs() = runBlocking<Unit> {
|
||||
val model1 = fakeModel()
|
||||
val job1 = fakeJob(model1.id)
|
||||
whenever(store.get()).doReturn(listOf(model1))
|
||||
@Test fun ensureScheduledValidations_sitesAlreadyHaveJobs() = runBlocking<Unit> {
|
||||
val model1 = fakeModel(id = 1)
|
||||
val job1 = fakeJob(1)
|
||||
database.setAllSites(model1)
|
||||
whenever(jobScheduler.allPendingJobs).doReturn(listOf(job1))
|
||||
|
||||
manager.ensureScheduledChecks()
|
||||
manager.ensureScheduledValidations()
|
||||
|
||||
verify(jobScheduler, never()).schedule(any())
|
||||
}
|
||||
|
||||
@Test fun ensureScheduledChecks() = runBlocking {
|
||||
val model1 = fakeModel()
|
||||
whenever(store.get()).doReturn(listOf(model1))
|
||||
@Test fun ensureScheduledValidations() = runBlocking {
|
||||
val model1 = fakeModel(id = 1)
|
||||
database.setAllSites(model1)
|
||||
|
||||
whenever(jobScheduler.allPendingJobs).doReturn(listOf<JobInfo>())
|
||||
|
||||
manager.ensureScheduledChecks()
|
||||
manager.ensureScheduledValidations()
|
||||
|
||||
val jobCaptor = argumentCaptor<JobInfo>()
|
||||
verify(jobScheduler).schedule(jobCaptor.capture())
|
||||
val jobInfo = jobCaptor.allValues.single()
|
||||
assertThat(jobInfo.id).isEqualTo(model1.id)
|
||||
assertThat(jobInfo.extras.getInt(KEY_SITE_ID)).isEqualTo(model1.id)
|
||||
assertThat(jobInfo.extras.getLong(KEY_SITE_ID)).isEqualTo(model1.id)
|
||||
}
|
||||
|
||||
@Test fun scheduleCheck_rightNow() {
|
||||
val model1 = fakeModel()
|
||||
@Test fun scheduleValidation_rightNow() {
|
||||
val model1 = fakeModel(id = 1)
|
||||
whenever(jobScheduler.allPendingJobs).doReturn(listOf<JobInfo>())
|
||||
|
||||
manager.scheduleCheck(
|
||||
manager.scheduleValidation(
|
||||
site = model1,
|
||||
rightNow = true
|
||||
)
|
||||
|
||||
val jobCaptor = argumentCaptor<JobInfo>()
|
||||
verify(jobScheduler).schedule(jobCaptor.capture())
|
||||
verify(jobScheduler).cancel(model1.id)
|
||||
verify(jobScheduler).cancel(1)
|
||||
|
||||
val jobInfo = jobCaptor.allValues.single()
|
||||
assertThat(jobInfo.id).isEqualTo(model1.id)
|
||||
assertThat(jobInfo.extras.getInt(KEY_SITE_ID)).isEqualTo(model1.id)
|
||||
assertThat(jobInfo.extras.getLong(KEY_SITE_ID)).isEqualTo(model1.id)
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException::class)
|
||||
fun scheduleCheck_notFromFinishingJob_haveExistingJob() {
|
||||
val model1 = fakeModel()
|
||||
val job1 = fakeJob(model1.id)
|
||||
fun scheduleValidation_notFromFinishingJob_haveExistingJob() {
|
||||
val model1 = fakeModel(id = 1)
|
||||
val job1 = fakeJob(1)
|
||||
whenever(jobScheduler.allPendingJobs).doReturn(listOf(job1))
|
||||
|
||||
manager.scheduleCheck(
|
||||
manager.scheduleValidation(
|
||||
site = model1,
|
||||
fromFinishingJob = false
|
||||
)
|
||||
}
|
||||
|
||||
@Test fun scheduleCheck_fromFinishingJob_haveExistingJob() {
|
||||
val model1 = fakeModel()
|
||||
val job1 = fakeJob(model1.id)
|
||||
@Test fun scheduleValidation_fromFinishingJob_haveExistingJob() {
|
||||
val model1 = fakeModel(id = 1)
|
||||
val job1 = fakeJob(1)
|
||||
whenever(jobScheduler.allPendingJobs).doReturn(listOf(job1))
|
||||
|
||||
manager.scheduleCheck(
|
||||
manager.scheduleValidation(
|
||||
site = model1,
|
||||
fromFinishingJob = true
|
||||
)
|
||||
|
||||
val jobCaptor = argumentCaptor<JobInfo>()
|
||||
verify(jobScheduler).schedule(jobCaptor.capture())
|
||||
verify(jobScheduler, never()).cancel(model1.id)
|
||||
verify(jobScheduler, never()).cancel(any())
|
||||
|
||||
val jobInfo = jobCaptor.allValues.single()
|
||||
assertThat(jobInfo.id).isEqualTo(model1.id)
|
||||
assertThat(jobInfo.extras.getInt(KEY_SITE_ID)).isEqualTo(model1.id)
|
||||
assertThat(jobInfo.extras.getLong(KEY_SITE_ID)).isEqualTo(model1.id)
|
||||
}
|
||||
|
||||
@Test fun scheduleCheck() {
|
||||
val model1 = fakeModel()
|
||||
@Test fun scheduleValidation() {
|
||||
val model1 = fakeModel(id = 1)
|
||||
whenever(jobScheduler.allPendingJobs).doReturn(listOf<JobInfo>())
|
||||
|
||||
manager.scheduleCheck(
|
||||
manager.scheduleValidation(
|
||||
site = model1,
|
||||
fromFinishingJob = true
|
||||
)
|
||||
|
||||
val jobCaptor = argumentCaptor<JobInfo>()
|
||||
verify(jobScheduler).schedule(jobCaptor.capture())
|
||||
verify(jobScheduler, never()).cancel(model1.id)
|
||||
verify(jobScheduler, never()).cancel(any())
|
||||
|
||||
val jobInfo = jobCaptor.allValues.single()
|
||||
assertThat(jobInfo.id).isEqualTo(model1.id)
|
||||
assertThat(jobInfo.extras.getInt(KEY_SITE_ID)).isEqualTo(model1.id)
|
||||
assertThat(jobInfo.extras.getLong(KEY_SITE_ID)).isEqualTo(model1.id)
|
||||
}
|
||||
|
||||
@Test fun cancelCheck() {
|
||||
val model1 = fakeModel()
|
||||
manager.cancelCheck(model1)
|
||||
verify(jobScheduler).cancel(model1.id)
|
||||
@Test fun cancelScheduledValidation() {
|
||||
val model1 = fakeModel(id = 1)
|
||||
manager.cancelScheduledValidation(model1)
|
||||
verify(jobScheduler).cancel(1)
|
||||
}
|
||||
|
||||
@Test fun performCheck_httpNotSuccess() = runBlocking {
|
||||
@Test fun performValidation_httpNotSuccess() = runBlocking {
|
||||
val response = fakeResponse(500, "Internal Server Error", "Hello World")
|
||||
val call = mock<Call> {
|
||||
on { execute() } doReturn response
|
||||
}
|
||||
whenever(okHttpClient.newCall(any())).doReturn(call)
|
||||
|
||||
val model1 = fakeModel()
|
||||
val result = manager.performCheck(model1)
|
||||
val model1 = fakeModel(id = 1)
|
||||
val result = manager.performValidation(model1)
|
||||
|
||||
assertThat(result.model).isEqualTo(
|
||||
model1.copy(
|
||||
status = ERROR,
|
||||
reason = "Response 500 - Hello World"
|
||||
lastResult = model1.lastResult?.copy(
|
||||
status = ERROR,
|
||||
reason = "Response 500 - Hello World"
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@Test fun performCheck_socketTimeout() = runBlocking {
|
||||
@Test fun performValidation_socketTimeout() = runBlocking {
|
||||
val error = SocketTimeoutException("Oh no!")
|
||||
val call = mock<Call> {
|
||||
on { execute() } doAnswer { throw error }
|
||||
}
|
||||
whenever(okHttpClient.newCall(any())).doReturn(call)
|
||||
|
||||
val model1 = fakeModel()
|
||||
val result = manager.performCheck(model1)
|
||||
val model1 = fakeModel(id = 1)
|
||||
val result = manager.performValidation(model1)
|
||||
|
||||
assertThat(result.model).isEqualTo(
|
||||
model1.copy(
|
||||
status = ERROR,
|
||||
reason = timeoutError
|
||||
lastResult = model1.lastResult?.copy(
|
||||
status = ERROR,
|
||||
reason = timeoutError
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@Test fun performCheck_exception() = runBlocking {
|
||||
@Test fun performValidation_exception() = runBlocking {
|
||||
val error = Exception("Oh no!")
|
||||
val call = mock<Call> {
|
||||
on { execute() } doAnswer { throw error }
|
||||
}
|
||||
whenever(okHttpClient.newCall(any())).doReturn(call)
|
||||
|
||||
val model1 = fakeModel()
|
||||
val result = manager.performCheck(model1)
|
||||
val model1 = fakeModel(id = 1)
|
||||
val result = manager.performValidation(model1)
|
||||
|
||||
assertThat(result.model).isEqualTo(
|
||||
model1.copy(
|
||||
status = ERROR,
|
||||
reason = "Oh no!"
|
||||
lastResult = model1.lastResult?.copy(
|
||||
status = ERROR,
|
||||
reason = "Oh no!"
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@Test fun performCheck_success() = runBlocking {
|
||||
@Test fun performValidation_success_withHeaders() = runBlocking {
|
||||
val requestCaptor = argumentCaptor<Request>()
|
||||
val response = fakeResponse(200, "OK", "Hello World")
|
||||
|
||||
val call = mock<Call> {
|
||||
on { execute() } doReturn response
|
||||
}
|
||||
whenever(okHttpClient.newCall(requestCaptor.capture()))
|
||||
.doReturn(call)
|
||||
|
||||
val model1 = fakeModel(id = 1).copy(
|
||||
headers = listOf(
|
||||
Header(
|
||||
key = "X-Test-Header",
|
||||
value = "Hello, World!"
|
||||
)
|
||||
)
|
||||
)
|
||||
val result = manager.performValidation(model1)
|
||||
val httpRequest = requestCaptor.firstValue
|
||||
|
||||
assertThat(result.model).isEqualTo(
|
||||
model1.copy(
|
||||
lastResult = model1.lastResult?.copy(
|
||||
status = OK,
|
||||
reason = null
|
||||
)
|
||||
)
|
||||
)
|
||||
assertThat(okHttpClient.callTimeoutMillis())
|
||||
.isEqualTo(model1.settings!!.networkTimeout)
|
||||
assertThat(httpRequest.header("X-Test-Header"))
|
||||
.isEqualTo("Hello, World!")
|
||||
}
|
||||
|
||||
@Test fun performValidation_success_withCustomSslCert() = runBlocking<Unit> {
|
||||
val response = fakeResponse(200, "OK", "Hello World")
|
||||
val call = mock<Call> {
|
||||
on { execute() } doReturn response
|
||||
}
|
||||
whenever(okHttpClient.newCall(any())).doReturn(call)
|
||||
|
||||
val model1 = fakeModel()
|
||||
val result = manager.performCheck(model1)
|
||||
val model1 = fakeModel(id = 1).copy(
|
||||
url = "http://wwww.mysite.com/test.html",
|
||||
headers = emptyList()
|
||||
)
|
||||
model1.settings = model1.settings!!.copy(
|
||||
certificate = "file:///sdcard/cert.pem"
|
||||
)
|
||||
val result = manager.performValidation(model1)
|
||||
|
||||
assertThat(result.model).isEqualTo(
|
||||
model1.copy(
|
||||
status = OK,
|
||||
reason = null
|
||||
lastResult = model1.lastResult?.copy(
|
||||
status = OK,
|
||||
reason = null
|
||||
)
|
||||
)
|
||||
)
|
||||
assertThat(okHttpClient.callTimeoutMillis())
|
||||
.isEqualTo(model1.networkTimeout)
|
||||
}
|
||||
.isEqualTo(model1.settings!!.networkTimeout)
|
||||
|
||||
@Test fun performCheck_401_butStillSuccess() = runBlocking {
|
||||
val response = fakeResponse(401, "Unauthorized", "Hello World")
|
||||
val call = mock<Call> {
|
||||
on { execute() } doReturn response
|
||||
}
|
||||
whenever(okHttpClient.newCall(any())).doReturn(call)
|
||||
|
||||
val model1 = fakeModel()
|
||||
val result = manager.performCheck(model1)
|
||||
|
||||
assertThat(result.model).isEqualTo(
|
||||
model1.copy(
|
||||
status = OK,
|
||||
reason = null
|
||||
)
|
||||
verify(sslManager).clientForCertificate(
|
||||
"file:///sdcard/cert.pem",
|
||||
"http://wwww.mysite.com/test.html",
|
||||
okHttpClient
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -293,14 +337,6 @@ class ValidationExecutorTest {
|
|||
.build()
|
||||
}
|
||||
|
||||
private fun fakeModel() = ServerModel(
|
||||
id = 1,
|
||||
name = "Wakanda Forever",
|
||||
url = "https://www.wakanda.gov",
|
||||
validationMode = STATUS_CODE,
|
||||
networkTimeout = 60000
|
||||
)
|
||||
|
||||
private fun fakeJob(id: Int): JobInfo {
|
||||
return mock {
|
||||
on { this.id } doReturn id
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue