Skip to content

Commit

Permalink
Merge branch 'main' into issue/2066-performance-tests-load-data
Browse files Browse the repository at this point in the history
  • Loading branch information
pld authored Jul 19, 2023
2 parents 177ae85 + 41af798 commit b3fda7d
Show file tree
Hide file tree
Showing 24 changed files with 328 additions and 59 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package org.smartregister.fhircore.engine.configuration

import android.content.Context
import android.database.SQLException
import com.google.android.fhir.FhirEngine
import com.google.android.fhir.db.ResourceNotFoundException
import com.google.android.fhir.get
Expand Down Expand Up @@ -238,7 +239,9 @@ constructor(
if (iconConfigs.isNotEmpty()) {
val ids = iconConfigs.joinToString(DEFAULT_STRING_SEPARATOR) { it.focus.extractId() }
fhirResourceDataSource
.getResource("${ResourceType.Binary.name}?$ID=$ids")
.getResource(
"${ResourceType.Binary.name}?$ID=$ids&_count=$DEFAULT_COUNT",
)
.entry
.forEach { addOrUpdate(it.resource) }
}
Expand Down Expand Up @@ -368,16 +371,19 @@ constructor(
}
.forEach { resourceGroup ->
if (resourceGroup.key == ResourceType.List.name) {
if (isNonProxy()) { // Backward compatibility for NON-PROXY version
if (isNonProxy()) {
val chunkedResourceIdList =
resourceGroup.value.chunked(MANIFEST_PROCESSOR_BATCH_SIZE)
chunkedResourceIdList.forEach {
val resourceIds =
it.joinToString(DEFAULT_STRING_SEPARATOR) { sectionComponent ->
sectionComponent.focus.extractId()
}

fhirResourceDataSource
.getResource("${resourceGroup.key}?$ID=$resourceIds")
.getResource(
"${resourceGroup.key}?$ID=$resourceIds&_count=$DEFAULT_COUNT",
)
.entry
.forEach { bundleEntryComponent ->
when (bundleEntryComponent.resource) {
Expand All @@ -391,8 +397,8 @@ constructor(
)
val resourceId =
listEntryComponent.item.reference.extractLogicalIdUuid()

val listResourceUrlPath = "$resourceKey?$ID=$resourceId"
val listResourceUrlPath =
"$resourceKey?$ID=$resourceId&_count=$DEFAULT_COUNT"
fhirResourceDataSource.getResource(listResourceUrlPath).entry.forEach {
listEntryResourceBundle ->
addOrUpdate(listEntryResourceBundle.resource)
Expand Down Expand Up @@ -420,7 +426,7 @@ constructor(
sectionComponent.focus.extractId()
}
processCompositionManifestResources(
searchPath = "${resourceGroup.key}?$ID=$resourceIds",
searchPath = "${resourceGroup.key}?$ID=$resourceIds&_count=$DEFAULT_COUNT",
)
}
}
Expand Down Expand Up @@ -458,7 +464,9 @@ constructor(
}
else -> {
addOrUpdate(bundleEntryComponent.resource)
Timber.d("Fetched and processed resources $searchPath")
Timber.d(
"Fetched and processed resources ${bundleEntryComponent.resource.resourceType}/${bundleEntryComponent.resource.id}",
)
}
}
}
Expand All @@ -483,7 +491,11 @@ constructor(
fhirEngine.update(updateFrom(resource))
}
} catch (resourceNotFoundException: ResourceNotFoundException) {
create(resource)
try {
create(resource)
} catch (sqlException: SQLException) {
Timber.e(sqlException)
}
}
}
}
Expand All @@ -501,7 +513,7 @@ constructor(
}
}

@VisibleForTesting fun isNonProxy() = isNonProxy_
@VisibleForTesting fun isNonProxy(): Boolean = isNonProxy_

@VisibleForTesting
fun setNonProxy(nonProxy: Boolean) {
Expand All @@ -522,5 +534,6 @@ constructor(
const val MANIFEST_PROCESSOR_BATCH_SIZE = 30
const val ORGANIZATION = "organization"
const val TYPE_REFERENCE_DELIMITER = "/"
const val DEFAULT_COUNT = 200
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ import android.os.Handler
import android.os.Looper
import android.os.Message
import androidx.core.os.bundleOf
import com.google.android.fhir.sync.Authenticator as FhirAuthenticator
import com.google.android.fhir.sync.HttpAuthenticationMethod
import com.google.android.fhir.sync.HttpAuthenticator as FhirAuthenticator
import dagger.hilt.android.qualifiers.ApplicationContext
import io.jsonwebtoken.JwtException
import io.jsonwebtoken.Jwts
Expand Down Expand Up @@ -65,7 +66,7 @@ constructor(
private val authConfiguration by lazy { configService.provideAuthConfiguration() }
private var isLoginPageRendered = false

override fun getAccessToken(): String {
fun getAccessToken(): String {
val account = findAccount()
return if (account != null) {
val accessToken = accountManager.peekAuthToken(account, AUTH_TOKEN_TYPE) ?: ""
Expand Down Expand Up @@ -280,4 +281,7 @@ constructor(
const val AUTH_TOKEN_TYPE = "provider"
const val CANCEL_BACKGROUND_SYNC = "cancelBackgroundSync"
}

override fun getAuthenticationMethod(): HttpAuthenticationMethod =
HttpAuthenticationMethod.Bearer(getAccessToken())
}
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ class ResourceDataRulesExecutor @Inject constructor(val rulesFactory: RulesFacto
val listItemRelatedResources = mutableMapOf<String, List<Resource>>()
listResource.relatedResources.forEach { relatedListResource ->
val retrieveRelatedResources: List<Resource>? =
relatedListResource.fhirPathExpression?.let {
relatedListResource.fhirPathExpression.let {
rulesFactory.rulesEngineService.retrieveRelatedResources(
resource = resource,
relatedResourceKey = relatedListResource.relatedResourceId
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ constructor(
fun retrieveRelatedResources(
resource: Resource,
relatedResourceKey: String,
referenceFhirPathExpression: String,
referenceFhirPathExpression: String?,
relatedResourcesMap: Map<String, List<Resource>>? = null,
): List<Resource> {
val value: List<Resource> =
Expand All @@ -163,10 +163,15 @@ constructor(
emptyList()
}

return value.filter {
resource.logicalId ==
fhirPathDataExtractor.extractValue(it, referenceFhirPathExpression).extractLogicalIdUuid()
}
return if (referenceFhirPathExpression.isNullOrEmpty()) {
value
} else
value.filter {
resource.logicalId ==
fhirPathDataExtractor
.extractValue(it, referenceFhirPathExpression)
.extractLogicalIdUuid()
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import org.junit.Test
import org.smartregister.fhircore.engine.configuration.view.ButtonProperties
import org.smartregister.fhircore.engine.configuration.view.ButtonType
import org.smartregister.fhircore.engine.configuration.view.ViewAlignment
import org.smartregister.fhircore.engine.domain.model.ServiceStatus
import org.smartregister.fhircore.engine.domain.model.ViewType
import org.smartregister.fhircore.engine.robolectric.RobolectricTest
import org.smartregister.fhircore.engine.ui.theme.DangerColor
Expand Down Expand Up @@ -58,7 +59,20 @@ class ButtonPropertiesTest : RobolectricTest() {
map["enabled"] = "true"
map["text"] = "ANC Visit"
val interpolatedButton = buttonProperties.interpolate(map)
Assert.assertEquals("DUE", interpolatedButton.status)
Assert.assertEquals(ServiceStatus.DUE.name, interpolatedButton.status)
Assert.assertEquals("#FFA500", interpolatedButton.backgroundColor)
Assert.assertEquals("true", interpolatedButton.enabled)
Assert.assertEquals("ANC Visit", interpolatedButton.text)
}

@Test
fun testInterpolateInButtonPropertiesUpcoming() {
val map = mutableMapOf<String, String>()
map["backgroundColor"] = "#FFA500"
map["enabled"] = "true"
map["text"] = "ANC Visit"
val interpolatedButton = buttonProperties.interpolate(map)
Assert.assertEquals(ServiceStatus.UPCOMING.name, interpolatedButton.status)
Assert.assertEquals("#FFA500", interpolatedButton.backgroundColor)
Assert.assertEquals("true", interpolatedButton.enabled)
Assert.assertEquals("ANC Visit", interpolatedButton.text)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,27 @@ class ConfigurationRegistryTest : RobolectricTest() {
Assert.assertEquals(id, registerConfig.id)
}

@Test
@kotlinx.coroutines.ExperimentalCoroutinesApi
fun testRetrieveConfigurationPassParamsMap() {
val appId = "idOfApp"
val id = "register"
val paramAppId = "idOfAppParam"
val paramId = "registerParam"
val configId = "idOfConfig"
configRegistry.configsJsonMap[configId] =
"{\"appId\": \"@{$appId}\", \"id\": \"@{$id}\", \"fhirResource\": {\"baseResource\": { \"resource\": \"Patient\"}}}"
val registerConfig =
configRegistry.retrieveConfiguration<RegisterConfiguration>(
ConfigType.Register,
configId,
mapOf(appId to paramAppId, id to paramId),
)
Assert.assertTrue(configRegistry.configCacheMap.containsKey(configId))
Assert.assertEquals(paramAppId, registerConfig.appId)
Assert.assertEquals(paramId, registerConfig.id)
}

@Test
@kotlinx.coroutines.ExperimentalCoroutinesApi
fun testRetrieveConfigurationParseResource() {
Expand Down Expand Up @@ -305,8 +326,10 @@ class ConfigurationRegistryTest : RobolectricTest() {
bundle
coEvery { fhirEngine.update(any()) } returns Unit
coEvery { fhirEngine.get(ResourceType.List, testListId) } returns listResource
coEvery { fhirResourceDataSource.getResource("$resourceKey?_id=$resourceId") } returns bundle
coEvery { fhirResourceService.getResource("List?_id=$testListId") } returns bundle
coEvery {
fhirResourceDataSource.getResource("$resourceKey?_id=$resourceId&_count=200")
} returns bundle
coEvery { fhirResourceService.getResource("List?_id=$testListId&_count=200") } returns bundle

runTest {
configRegistry.fhirEngine.create(composition)
Expand All @@ -315,7 +338,7 @@ class ConfigurationRegistryTest : RobolectricTest() {
}

coVerify { fhirEngine.get(ResourceType.List, testListId) }
coVerify { fhirResourceDataSource.getResource("$resourceKey?_id=$resourceId") }
coVerify { fhirResourceDataSource.getResource("$resourceKey?_id=$resourceId&_count=200") }
coEvery { fhirResourceDataSource.getResource("$focusReference?_id=$focusReference") }
}

Expand Down Expand Up @@ -607,10 +630,10 @@ class ConfigurationRegistryTest : RobolectricTest() {

Assert.assertEquals(2, requestPathArgumentSlot.size)
Assert.assertEquals(
"StructureMap?_id=id-1,id-2,id-3,id-4,id-5,id-6,id-7,id-8,id-9,id-10,id-11,id-12,id-13,id-14,id-15,id-16,id-17,id-18,id-19,id-20,id-21,id-22,id-23,id-24,id-25,id-26,id-27,id-28,id-29,id-30",
"StructureMap?_id=id-1,id-2,id-3,id-4,id-5,id-6,id-7,id-8,id-9,id-10,id-11,id-12,id-13,id-14,id-15,id-16,id-17,id-18,id-19,id-20,id-21,id-22,id-23,id-24,id-25,id-26,id-27,id-28,id-29,id-30&_count=200",
requestPathArgumentSlot.first(),
)
Assert.assertEquals("StructureMap?_id=id-31", requestPathArgumentSlot.last())
Assert.assertEquals("StructureMap?_id=id-31&_count=200", requestPathArgumentSlot.last())
}

@Test
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* Copyright 2021-2023 Ona Systems, Inc
*
* 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 org.smartregister.fhircore.engine.configuration.view

import org.junit.Assert
import org.junit.Test

class DividerPropertiesTest {
private val imageProperties =
DividerProperties(
backgroundColor = "@{backgroundColor}",
visible = "@{visible}",
)

@Test
fun testInterpolateInImageProperties() {
val computedValuesMap = mutableMapOf<String, String>()
computedValuesMap["backgroundColor"] = "#000000"
computedValuesMap["visible"] = "false"

val interpolatedDividerProperties =
imageProperties.interpolate(computedValuesMap) as DividerProperties

Assert.assertEquals("#000000", interpolatedDividerProperties.backgroundColor)
Assert.assertEquals("false", interpolatedDividerProperties.visible)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,18 @@ class RulesFactoryTest : RobolectricTest() {
Assert.assertEquals("careplan-1", result[0].logicalId)
}

@Test
fun retrieveRelatedResourcesWithoutReferenceReturnsResources() {
populateFactsWithResources()
val result =
rulesEngineService.retrieveRelatedResources(
resource = Faker.buildPatient(),
relatedResourceKey = ResourceType.CarePlan.name,
referenceFhirPathExpression = "",
)
Assert.assertEquals(1, result.size)
}

@Test
fun retrieveParentResourcesReturnsCorrectResource() {
populateFactsWithResources()
Expand Down
2 changes: 1 addition & 1 deletion android/gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ desugar-jdk-libs = "1.1.5"
easy-rules-jexl = "4.1.0"
espresso-core = "3.5.0"
fhir-common-utils = "0.0.2-SNAPSHOT"
fhir-engine = "0.1.0-beta03-preview9.2-SNAPSHOT"
fhir-engine = "0.1.0-beta03-preview9.5-SNAPSHOT"
foundation = "1.3.1"
fragment-ktx = "1.5.5"
fragment-testing = "1.5.2"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ class UserSettingScreenTest {
lastSyncTime = "05:30 PM, Mar 3",
unsyncedResourcesFlow = unsyncedResourcesFlow,
dismissInsightsView = {},
showProgressIndicatorFlow = MutableStateFlow(false),
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import org.hl7.fhir.r4.model.Composition
import org.hl7.fhir.r4.model.ResourceType
import org.smartregister.fhircore.engine.BuildConfig
import org.smartregister.fhircore.engine.R
import org.smartregister.fhircore.engine.configuration.ConfigType
import org.smartregister.fhircore.engine.configuration.ConfigurationRegistry
import org.smartregister.fhircore.engine.configuration.ConfigurationRegistry.Companion.DEBUG_SUFFIX
import org.smartregister.fhircore.engine.configuration.app.ConfigService
Expand Down Expand Up @@ -101,7 +102,8 @@ constructor(
viewModelScope.launch {
try {
Timber.i("Fetching configs for app $appId")
val urlPath = "${ResourceType.Composition.name}?${Composition.SP_IDENTIFIER}=$appId"
val urlPath =
"${ResourceType.Composition.name}?${Composition.SP_IDENTIFIER}=$appId&_count=${ConfigurationRegistry.DEFAULT_COUNT}"
val compositionResource =
withContext(dispatcherProvider.io()) { fetchComposition(urlPath, context) }
?: return@launch
Expand All @@ -120,7 +122,8 @@ constructor(
entry.value.chunked(ConfigurationRegistry.MANIFEST_PROCESSOR_BATCH_SIZE)
chunkedResourceIdList.forEach { parentIt ->
val ids = parentIt.joinToString(",") { it.focus.extractId() }
val resourceUrlPath = "${entry.key}?${Composition.SP_RES_ID}=$ids"
val resourceUrlPath =
"${entry.key}?${Composition.SP_RES_ID}=$ids&_count=${ConfigurationRegistry.DEFAULT_COUNT}"
Timber.d("Fetching config: $resourceUrlPath")
fhirResourceDataSource.getResource(resourceUrlPath).entry.forEach {
bundleEntryComponent ->
Expand All @@ -129,15 +132,20 @@ constructor(
if (bundleEntryComponent.resource is Binary) {
val binary = bundleEntryComponent.resource as Binary
binary.data.decodeToString().decodeBase64()?.string(StandardCharsets.UTF_8)?.let {
val config =
it.tryDecodeJson<RegisterConfiguration>()
?: it.tryDecodeJson<ProfileConfiguration>()

when (config) {
is RegisterConfiguration ->
config.fhirResource.dependentResourceTypes(patientRelatedResourceTypes)
is ProfileConfiguration ->
config.fhirResource.dependentResourceTypes(patientRelatedResourceTypes)
val registerConfig = it.tryDecodeJson<RegisterConfiguration>()
if (registerConfig != null) {
if (registerConfig.configType == ConfigType.Profile.name) {
val profileConfig = it.tryDecodeJson<ProfileConfiguration>()
profileConfig
?.fhirResource
?.dependentResourceTypes(
patientRelatedResourceTypes,
)
} else {
registerConfig.fhirResource.dependentResourceTypes(
patientRelatedResourceTypes,
)
}
}
}
}
Expand Down
Loading

0 comments on commit b3fda7d

Please sign in to comment.