From 0a818bc880d7e809c442388a7db1d61f7731eeff Mon Sep 17 00:00:00 2001 From: Dzmitry Fomchyn <5161509+DzmitryFomchyn@users.noreply.github.com> Date: Wed, 25 May 2022 12:53:28 +0300 Subject: [PATCH] Common SDK logs (#41) * Common SDK log * Remove deprecated function --- LICENSE.md | 36 --------- MapboxSearch/gradle/versions.gradle | 3 +- .../java/com/mapbox/common/CommonSdkLog.kt | 78 +++++++++++++++++++ .../com/mapbox/search/common/Assertions.kt | 40 ++-------- .../com/mapbox/search/common/logger/Log.kt | 43 ++++------ .../search/common/logger/LogFunctionsTest.kt | 52 ++++--------- MapboxSearch/sdk/build.gradle | 3 - .../java/com/mapbox/search/MapboxSearchSdk.kt | 7 +- .../search/analytics/AnalyticsServiceImpl.kt | 9 +-- .../search/analytics/CrashEventsFactory.kt | 4 +- .../engine/OneStepRequestCallbackWrapper.kt | 5 +- .../engine/TwoStepsRequestCallbackWrapper.kt | 5 +- .../search/location/LocationEngineAdapter.kt | 6 +- .../mapbox/search/record/LocalDataProvider.kt | 4 +- .../com/mapbox/search/CategorySearchTest.kt | 12 +-- .../mapbox/search/HighlightsCalculatorTest.kt | 18 +++++ .../mapbox/search/OfflineSearchEngineTest.kt | 8 +- .../search/ReverseGeocodingSearchTest.kt | 8 +- .../com/mapbox/search/SearchEngineTest.kt | 8 +- .../events/AnalyticsServiceImplTest.kt | 18 +++++ .../location/LocationEngineAdapterTest.kt | 18 +++++ .../search/metadata/WeekTimestampTest.kt | 4 - .../search/result/OriginalSearchResultTest.kt | 9 ++- .../search/result/SearchResultFactoryTest.kt | 9 ++- .../mapbox/search/result/SearchResultTest.kt | 5 +- .../search/ui/view/SearchResultsView.kt | 2 +- .../view/favorite/rename/EditFavoriteView.kt | 2 +- .../view/place/SearchPlaceBottomSheetView.kt | 2 +- .../address/AddressSearchViewController.kt | 2 +- 29 files changed, 223 insertions(+), 197 deletions(-) create mode 100644 MapboxSearch/sdk-common/src/main/java/com/mapbox/common/CommonSdkLog.kt diff --git a/LICENSE.md b/LICENSE.md index 334b74c25..3a20868d5 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -268,24 +268,6 @@ License: [Mapbox Terms of Service](https://www.mapbox.com/legal/tos) =========================================================================== -Mapbox Search Android uses portions of the okhttp. -URL: [https://square.github.io/okhttp/](https://square.github.io/okhttp/) -License: [The Apache Software License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt) - -=========================================================================== - -Mapbox Search Android uses portions of the okhttp-logging-interceptor. -URL: [https://square.github.io/okhttp/](https://square.github.io/okhttp/) -License: [The Apache Software License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt) - -=========================================================================== - -Mapbox Search Android uses portions of the Okio. -URL: [https://github.com/square/okio/](https://github.com/square/okio/) -License: [The Apache Software License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt) - -=========================================================================== - Mapbox Search Android uses portions of the Parcelize Runtime. URL: [https://kotlinlang.org/](https://kotlinlang.org/) License: [The Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt) @@ -648,24 +630,6 @@ License: [The Apache Software License, Version 2.0](http://www.apache.org/licens =========================================================================== -Mapbox Search Android uses portions of the okhttp. -URL: [https://square.github.io/okhttp/](https://square.github.io/okhttp/) -License: [The Apache Software License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt) - -=========================================================================== - -Mapbox Search Android uses portions of the okhttp-logging-interceptor. -URL: [https://square.github.io/okhttp/](https://square.github.io/okhttp/) -License: [The Apache Software License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt) - -=========================================================================== - -Mapbox Search Android uses portions of the Okio. -URL: [https://github.com/square/okio/](https://github.com/square/okio/) -License: [The Apache Software License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt) - -=========================================================================== - Mapbox Search Android uses portions of the Parcelize Runtime. URL: [https://kotlinlang.org/](https://kotlinlang.org/) License: [The Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt) diff --git a/MapboxSearch/gradle/versions.gradle b/MapboxSearch/gradle/versions.gradle index 719584d01..885025376 100644 --- a/MapboxSearch/gradle/versions.gradle +++ b/MapboxSearch/gradle/versions.gradle @@ -19,7 +19,6 @@ ext { ktlint_version = '0.39.0' okhttp_version = '4.9.0' - okhttp_interceptor_version = '4.9.0' okhttp_mock_version = '1.5.0' conductor_version = "3.1.2" @@ -43,7 +42,7 @@ ext { mapbox_maps_version = "10.5.0" common_sdk_version = '21.3.0' - mapbox_base_version = '0.6.0' + mapbox_base_version = '0.8.0' mapbox_android_core_version = '5.0.1' search_native_version = '0.54.1' diff --git a/MapboxSearch/sdk-common/src/main/java/com/mapbox/common/CommonSdkLog.kt b/MapboxSearch/sdk-common/src/main/java/com/mapbox/common/CommonSdkLog.kt new file mode 100644 index 000000000..25ed11500 --- /dev/null +++ b/MapboxSearch/sdk-common/src/main/java/com/mapbox/common/CommonSdkLog.kt @@ -0,0 +1,78 @@ +package com.mapbox.common + +import androidx.annotation.VisibleForTesting + +/** + * This class in a "com.mapbox.common" package + * because we need to access package-private com.mapbox.common.Log class from the Common SDK. + */ +internal object CommonSdkLog { + + private const val SDK_IDENTIFIER = "search-sdk-android" + + private var logger: LogImpl? = CommonSdkLogImpl() + + /** + * Resets implementation that uses Common SDK class which can't be loaded in unit tests. + */ + @VisibleForTesting + fun resetLogImpl() { + logger = null + } + + @VisibleForTesting + fun reinitializeLogImpl() { + logger = CommonSdkLogImpl() + } + + fun logd(tag: String?, message: String) { + logger?.logd(tag, message) + } + + fun logi(tag: String?, message: String) { + logger?.logi(tag, message) + } + + fun logw(tag: String?, message: String) { + logger?.logw(tag, message) + } + + fun loge(tag: String?, message: String) { + logger?.loge(tag, message) + } + + private fun formatCategory(tag: String?): String { + return when (tag) { + null -> SDK_IDENTIFIER + else -> "$SDK_IDENTIFIER\\$tag" + } + } + + private interface LogImpl { + fun logd(tag: String?, message: String) + + fun logi(tag: String?, message: String) + + fun logw(tag: String?, message: String) + + fun loge(tag: String?, message: String) + } + + private class CommonSdkLogImpl : LogImpl { + override fun logd(tag: String?, message: String) { + Log.debug(message, formatCategory(tag)) + } + + override fun logi(tag: String?, message: String) { + Log.info(message, formatCategory(tag)) + } + + override fun logw(tag: String?, message: String) { + Log.warning(message, formatCategory(tag)) + } + + override fun loge(tag: String?, message: String) { + Log.error(message, formatCategory(tag)) + } + } +} diff --git a/MapboxSearch/sdk-common/src/main/java/com/mapbox/search/common/Assertions.kt b/MapboxSearch/sdk-common/src/main/java/com/mapbox/search/common/Assertions.kt index f0fbda345..b146e6e88 100644 --- a/MapboxSearch/sdk-common/src/main/java/com/mapbox/search/common/Assertions.kt +++ b/MapboxSearch/sdk-common/src/main/java/com/mapbox/search/common/Assertions.kt @@ -10,8 +10,7 @@ inline fun assertDebug(value: Boolean, message: () -> Any) { if (!value) { logw(message().toString()) - @Suppress("DEPRECATION") - reportError(IllegalStateException(message().toString())) + CommonErrorsReporter.reporter?.invoke(IllegalStateException(message().toString())) } } @@ -20,8 +19,7 @@ inline fun failDebug(cause: Throwable? = null, message: () -> Any) { if (BuildConfig.DEBUG) { throw exception } else { - @Suppress("DEPRECATION") - reportError(exception) + CommonErrorsReporter.reporter?.invoke(exception) } logw(message().toString()) } @@ -31,38 +29,12 @@ inline fun throwDebug(e: Throwable? = null, message: () -> Any = { "Error!" }) { if (BuildConfig.DEBUG) { throw exception } - if (e != null) { - logw(e, message().toString()) - } else { - logw(message().toString()) - } -} - -fun reportRelease(e: Throwable, message: String) { - reportRelease(e) { - message - } + loge(message().toString()) } -inline fun reportRelease(e: Throwable, message: () -> Any = { "Error!" }) { - loge(e, message().toString()) +fun reportRelease(e: Throwable, message: String = "Error occurred") { + loge("$message. Error: ${e.message}") if (!BuildConfig.DEBUG) { - @Suppress("DEPRECATION") - reportError(e) - } -} - -@Deprecated( - """ - Do not use this method inside SDK code. - Better use a more suitable "reportRelease(e)" method. - """, - replaceWith = ReplaceWith("reportRelease(e)")) -fun reportError(e: Throwable) { - val reporter = CommonErrorsReporter.reporter - if (reporter != null) { - reporter(e) - } else { - logw("Errors reported is not initialized") + CommonErrorsReporter.reporter?.invoke(e) } } diff --git a/MapboxSearch/sdk-common/src/main/java/com/mapbox/search/common/logger/Log.kt b/MapboxSearch/sdk-common/src/main/java/com/mapbox/search/common/logger/Log.kt index a36dd9cee..9d09ba97a 100644 --- a/MapboxSearch/sdk-common/src/main/java/com/mapbox/search/common/logger/Log.kt +++ b/MapboxSearch/sdk-common/src/main/java/com/mapbox/search/common/logger/Log.kt @@ -1,41 +1,30 @@ package com.mapbox.search.common.logger -import com.mapbox.base.common.logger.Logger -import com.mapbox.base.common.logger.model.Message -import com.mapbox.base.common.logger.model.Tag +import androidx.annotation.VisibleForTesting +import com.mapbox.common.CommonSdkLog -const val DEFAULT_SEARCH_SDK_LOG_TAG = "SearchSDK" - -var searchSdkLogger: Logger? = null - -fun logd(throwable: Throwable, message: String, tag: String = DEFAULT_SEARCH_SDK_LOG_TAG) { - searchSdkLogger?.d(tag = Tag(tag), msg = Message(message), tr = throwable) -} - -fun logd(message: String, tag: String = DEFAULT_SEARCH_SDK_LOG_TAG) { - searchSdkLogger?.d(tag = Tag(tag), msg = Message(message)) -} - -fun logi(throwable: Throwable, message: String, tag: String = DEFAULT_SEARCH_SDK_LOG_TAG) { - searchSdkLogger?.i(tag = Tag(tag), msg = Message(message), tr = throwable) +@VisibleForTesting +fun resetLogImpl() { + CommonSdkLog.resetLogImpl() } -fun logi(message: String, tag: String = DEFAULT_SEARCH_SDK_LOG_TAG) { - searchSdkLogger?.i(tag = Tag(tag), msg = Message(message)) +@VisibleForTesting +fun reinitializeLogImpl() { + CommonSdkLog.resetLogImpl() } -fun logw(throwable: Throwable, message: String, tag: String = DEFAULT_SEARCH_SDK_LOG_TAG) { - searchSdkLogger?.w(tag = Tag(tag), msg = Message(message), tr = throwable) +fun logd(message: String, tag: String? = null) { + CommonSdkLog.logd(tag, message) } -fun logw(message: String, tag: String = DEFAULT_SEARCH_SDK_LOG_TAG) { - searchSdkLogger?.w(tag = Tag(tag), msg = Message(message)) +fun logi(message: String, tag: String? = null) { + CommonSdkLog.logi(tag, message) } -fun loge(throwable: Throwable, message: String, tag: String = DEFAULT_SEARCH_SDK_LOG_TAG) { - searchSdkLogger?.e(tag = Tag(tag), msg = Message(message), tr = throwable) +fun logw(message: String, tag: String? = null) { + CommonSdkLog.logw(tag, message) } -fun loge(message: String, tag: String = DEFAULT_SEARCH_SDK_LOG_TAG) { - searchSdkLogger?.e(tag = Tag(tag), msg = Message(message)) +fun loge(message: String, tag: String? = null) { + CommonSdkLog.loge(tag, message) } diff --git a/MapboxSearch/sdk-common/src/test/java/com/mapbox/search/common/logger/LogFunctionsTest.kt b/MapboxSearch/sdk-common/src/test/java/com/mapbox/search/common/logger/LogFunctionsTest.kt index ccdb3a185..a0b3b309b 100644 --- a/MapboxSearch/sdk-common/src/test/java/com/mapbox/search/common/logger/LogFunctionsTest.kt +++ b/MapboxSearch/sdk-common/src/test/java/com/mapbox/search/common/logger/LogFunctionsTest.kt @@ -1,9 +1,10 @@ package com.mapbox.search.common.logger -import com.mapbox.base.common.logger.model.Message -import com.mapbox.base.common.logger.model.Tag +import com.mapbox.common.CommonSdkLog import com.mapbox.test.dsl.TestCase -import io.mockk.mockk +import io.mockk.every +import io.mockk.mockkObject +import io.mockk.unmockkObject import org.junit.jupiter.api.AfterEach import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.TestFactory @@ -12,12 +13,16 @@ internal class LogFunctionsTest { @BeforeEach fun setUp() { - searchSdkLogger = mockk(relaxed = true) + mockkObject(CommonSdkLog) + every { CommonSdkLog.logd(any(), any()) } returns Unit + every { CommonSdkLog.logi(any(), any()) } returns Unit + every { CommonSdkLog.logw(any(), any()) } returns Unit + every { CommonSdkLog.loge(any(), any()) } returns Unit } @AfterEach fun tearDown() { - searchSdkLogger = null + unmockkObject(CommonSdkLog) } @TestFactory @@ -26,56 +31,28 @@ internal class LogFunctionsTest { When("Call debug log") { logd(message = MESSAGE, tag = TAG) VerifyOnce("Call passed to logger instance") { - searchSdkLogger?.d(tag = Tag(TAG), msg = Message(MESSAGE)) - } - } - - When("Call debug log with exception") { - logd(throwable = ERROR_CAUSE, message = MESSAGE, tag = TAG) - VerifyOnce("Call passed to logger instance") { - searchSdkLogger?.d(tag = Tag(TAG), msg = Message(MESSAGE), tr = ERROR_CAUSE) + CommonSdkLog.logd(TAG, MESSAGE) } } When("Call info log") { logi(message = MESSAGE, tag = TAG) VerifyOnce("Call passed to logger instance") { - searchSdkLogger?.i(tag = Tag(TAG), msg = Message(MESSAGE)) - } - } - - When("Call info log with exception") { - logi(throwable = ERROR_CAUSE, message = MESSAGE, tag = TAG) - VerifyOnce("Call passed to logger instance") { - searchSdkLogger?.i(tag = Tag(TAG), msg = Message(MESSAGE), tr = ERROR_CAUSE) + CommonSdkLog.logi(TAG, MESSAGE) } } When("Call warning log") { logw(message = MESSAGE, tag = TAG) VerifyOnce("Call passed to logger instance") { - searchSdkLogger?.w(tag = Tag(TAG), msg = Message(MESSAGE)) - } - } - - When("Call warning log with exception") { - logw(throwable = ERROR_CAUSE, message = MESSAGE, tag = TAG) - VerifyOnce("Call passed to logger instance") { - searchSdkLogger?.w(tag = Tag(TAG), msg = Message(MESSAGE), tr = ERROR_CAUSE) + CommonSdkLog.logw(TAG, MESSAGE) } } When("Call error log") { loge(message = MESSAGE, tag = TAG) VerifyOnce("Call passed to logger instance") { - searchSdkLogger?.e(tag = Tag(TAG), msg = Message(MESSAGE)) - } - } - - When("Call error log with exception") { - loge(throwable = ERROR_CAUSE, message = MESSAGE, tag = TAG) - VerifyOnce("Call passed to logger instance") { - searchSdkLogger?.e(tag = Tag(TAG), msg = Message(MESSAGE), tr = ERROR_CAUSE) + CommonSdkLog.loge(TAG, MESSAGE) } } } @@ -84,6 +61,5 @@ internal class LogFunctionsTest { private companion object { const val MESSAGE = "message" const val TAG = "tag" - val ERROR_CAUSE = Exception() } } diff --git a/MapboxSearch/sdk/build.gradle b/MapboxSearch/sdk/build.gradle index 7a030f59a..dfed5e397 100644 --- a/MapboxSearch/sdk/build.gradle +++ b/MapboxSearch/sdk/build.gradle @@ -96,9 +96,6 @@ dependencies { implementation "androidx.collection:collection-ktx:$androidx_collection_version" implementation "androidx.core:core-ktx:$androidx_core_version" - implementation "com.squareup.okhttp3:okhttp:$okhttp_version" - implementation "com.squareup.okhttp3:logging-interceptor:$okhttp_interceptor_version" - api "com.mapbox.common:common:$common_sdk_version" api "com.mapbox.mapboxsdk:mapbox-android-core:$mapbox_android_core_version" diff --git a/MapboxSearch/sdk/src/main/java/com/mapbox/search/MapboxSearchSdk.kt b/MapboxSearch/sdk/src/main/java/com/mapbox/search/MapboxSearchSdk.kt index d3ed4cb81..45b511af0 100755 --- a/MapboxSearch/sdk/src/main/java/com/mapbox/search/MapboxSearchSdk.kt +++ b/MapboxSearch/sdk/src/main/java/com/mapbox/search/MapboxSearchSdk.kt @@ -22,7 +22,6 @@ import com.mapbox.search.common.BuildConfig import com.mapbox.search.common.CommonErrorsReporter import com.mapbox.search.common.concurrent.CommonMainThreadChecker import com.mapbox.search.common.logger.logd -import com.mapbox.search.common.logger.searchSdkLogger import com.mapbox.search.core.CoreEngineOptions import com.mapbox.search.core.CoreLocationProvider import com.mapbox.search.core.CoreSearchEngine @@ -184,10 +183,6 @@ public object MapboxSearchSdk { SearchSdkMainThreadWorker.isMainThread } - searchSdkLogger = MapboxModuleProvider.createModule( - MapboxModuleType.CommonLogger, ::mapboxModuleParamsProvider - ) - MapboxModuleProvider.createModule( MapboxModuleType.CommonLibraryLoader, ::mapboxModuleParamsProvider ).run { @@ -306,7 +301,7 @@ public object MapboxSearchSdk { } override fun onError(e: Exception) { - logd(e, "Unable to register ${provider.dataProviderName} data provider for $apiType") + logd("Unable to register ${provider.dataProviderName} data provider for $apiType: ${e.message}") } } diff --git a/MapboxSearch/sdk/src/main/java/com/mapbox/search/analytics/AnalyticsServiceImpl.kt b/MapboxSearch/sdk/src/main/java/com/mapbox/search/analytics/AnalyticsServiceImpl.kt index c7d19bbec..777a87875 100644 --- a/MapboxSearch/sdk/src/main/java/com/mapbox/search/analytics/AnalyticsServiceImpl.kt +++ b/MapboxSearch/sdk/src/main/java/com/mapbox/search/analytics/AnalyticsServiceImpl.kt @@ -109,7 +109,7 @@ internal class AnalyticsServiceImpl( } override fun onError(e: Exception) { - loge(e, "Unable to send event: $event") + loge("Unable to send event $event: ${e.message}") } } ) @@ -133,7 +133,7 @@ internal class AnalyticsServiceImpl( } override fun onError(e: Exception) { - loge(e, "Unable to send event: $event") + loge("Unable to send event $event: ${e.message}") } } ) @@ -165,7 +165,7 @@ internal class AnalyticsServiceImpl( } override fun onError(e: Exception) { - loge(e, "Unable to send event: $event") + loge("Unable to send event $event: ${e.message}") } } ) @@ -181,8 +181,7 @@ internal class AnalyticsServiceImpl( eventsService.sendEventJson(jsonEvent) logd("Feedback event: $feedbackEvent") } catch (e: Exception) { - loge(e, "Unable to send event: $feedbackEvent") - throwDebug(e) + throwDebug(e) { "Unable to send event: $feedbackEvent: ${e.message}" } } } diff --git a/MapboxSearch/sdk/src/main/java/com/mapbox/search/analytics/CrashEventsFactory.kt b/MapboxSearch/sdk/src/main/java/com/mapbox/search/analytics/CrashEventsFactory.kt index 76040b369..af5be8d24 100644 --- a/MapboxSearch/sdk/src/main/java/com/mapbox/search/analytics/CrashEventsFactory.kt +++ b/MapboxSearch/sdk/src/main/java/com/mapbox/search/analytics/CrashEventsFactory.kt @@ -49,7 +49,7 @@ internal class CrashEventsFactory( put(key, value) } } catch (e: JSONException) { - loge(e, "Failed json encode value: $value") + loge("Failed json encode value: $value: ${e.message}") } } @@ -64,7 +64,7 @@ internal class CrashEventsFactory( } jsonArray } catch (e: JSONException) { - loge(e, "Failed to create JSON array for custom data") + loge("Failed to create JSON array for custom data: ${e.message}") null } } diff --git a/MapboxSearch/sdk/src/main/java/com/mapbox/search/engine/OneStepRequestCallbackWrapper.kt b/MapboxSearch/sdk/src/main/java/com/mapbox/search/engine/OneStepRequestCallbackWrapper.kt index e5b86611f..649941159 100644 --- a/MapboxSearch/sdk/src/main/java/com/mapbox/search/engine/OneStepRequestCallbackWrapper.kt +++ b/MapboxSearch/sdk/src/main/java/com/mapbox/search/engine/OneStepRequestCallbackWrapper.kt @@ -96,8 +96,9 @@ internal class OneStepRequestCallbackWrapper( if (this != null && isSuccess) { searchResults.add(getOrThrow()) } else { - throwDebug(this?.exceptionOrNull()) { - "Can't parse data from backend: ${responseResult[resultIndex]}" + val e = this?.exceptionOrNull() + throwDebug(e) { + "Can't parse data from backend: ${responseResult[resultIndex]}: ${e?.message}" } } } diff --git a/MapboxSearch/sdk/src/main/java/com/mapbox/search/engine/TwoStepsRequestCallbackWrapper.kt b/MapboxSearch/sdk/src/main/java/com/mapbox/search/engine/TwoStepsRequestCallbackWrapper.kt index 43e1b04b6..b55715c9b 100644 --- a/MapboxSearch/sdk/src/main/java/com/mapbox/search/engine/TwoStepsRequestCallbackWrapper.kt +++ b/MapboxSearch/sdk/src/main/java/com/mapbox/search/engine/TwoStepsRequestCallbackWrapper.kt @@ -166,8 +166,9 @@ internal class TwoStepsRequestCallbackWrapper( val original = searchResult.mapToPlatform() val task = searchResultFactory.createSearchSuggestionAsync(original, requestOptions, apiType, workerExecutor, isOfflineSearch) { if (it.isFailure) { - throwDebug(it.exceptionOrNull()) { - "Can't create suggestions ${response.results}" + val e = it.exceptionOrNull() + throwDebug(e) { + "Can't create suggestions ${response.results}: ${e?.message}" } } diff --git a/MapboxSearch/sdk/src/main/java/com/mapbox/search/location/LocationEngineAdapter.kt b/MapboxSearch/sdk/src/main/java/com/mapbox/search/location/LocationEngineAdapter.kt index 1f4c1011d..91afdf61e 100644 --- a/MapboxSearch/sdk/src/main/java/com/mapbox/search/location/LocationEngineAdapter.kt +++ b/MapboxSearch/sdk/src/main/java/com/mapbox/search/location/LocationEngineAdapter.kt @@ -37,7 +37,7 @@ internal class LocationEngineAdapter( } override fun onFailure(e: Exception) { - loge(e, "Can't access location") + loge("Can't access location: ${e.message}") } } @@ -56,7 +56,7 @@ internal class LocationEngineAdapter( } override fun onFailure(e: Exception) { - loge(e, "Can't access last location") + loge("Can't access last location: ${e.message}") startLocationListener() } }) @@ -71,7 +71,7 @@ internal class LocationEngineAdapter( locationEngine.requestLocationUpdates(request, locationEngineCallback, Looper.getMainLooper()) } catch (e: Exception) { - loge(e, "Error during location request") + loge("Error during location request: ${e.message}") } } diff --git a/MapboxSearch/sdk/src/main/java/com/mapbox/search/record/LocalDataProvider.kt b/MapboxSearch/sdk/src/main/java/com/mapbox/search/record/LocalDataProvider.kt index 6816e4f15..223b4c620 100644 --- a/MapboxSearch/sdk/src/main/java/com/mapbox/search/record/LocalDataProvider.kt +++ b/MapboxSearch/sdk/src/main/java/com/mapbox/search/record/LocalDataProvider.kt @@ -9,8 +9,6 @@ import com.mapbox.search.CompletionCallback import com.mapbox.search.plusAssign import com.mapbox.search.runIfNotCancelled import com.mapbox.search.utils.concurrent.SearchSdkMainThreadWorker -import okhttp3.internal.notifyAll -import okhttp3.internal.wait import java.util.Collections import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.CopyOnWriteArrayList @@ -138,7 +136,7 @@ internal abstract class LocalDataProviderImpl( @Volatile protected var dataState: DataState? = null - private val initializingLock: Any = Any() + private val initializingLock = Object() init { require(maxRecordsAmount > 0) { diff --git a/MapboxSearch/sdk/src/test/java/com/mapbox/search/CategorySearchTest.kt b/MapboxSearch/sdk/src/test/java/com/mapbox/search/CategorySearchTest.kt index 751cb755c..861bebeab 100644 --- a/MapboxSearch/sdk/src/test/java/com/mapbox/search/CategorySearchTest.kt +++ b/MapboxSearch/sdk/src/test/java/com/mapbox/search/CategorySearchTest.kt @@ -2,7 +2,8 @@ package com.mapbox.search import com.mapbox.geojson.Point import com.mapbox.search.TestConstants.ASSERTIONS_KT_CLASS_NAME -import com.mapbox.search.common.reportError +import com.mapbox.search.common.logger.reinitializeLogImpl +import com.mapbox.search.common.logger.resetLogImpl import com.mapbox.search.core.CoreSearchCallback import com.mapbox.search.core.CoreSearchEngineInterface import com.mapbox.search.core.CoreSearchOptions @@ -344,9 +345,9 @@ internal class CategorySearchTest { TEST_RESPONSE_UUID ) - val TEST_ERROR_CORE_RESPONSE_HTTP_CODE = 401 + const val TEST_ERROR_CORE_RESPONSE_HTTP_CODE = 401 - val TEST_ERROR_CORE_RESPONSE_MESSAGE = "Auth failed" + const val TEST_ERROR_CORE_RESPONSE_MESSAGE = "Auth failed" val TEST_ERROR_CORE_RESPONSE = createTestCoreSearchResponseError( TEST_ERROR_CORE_RESPONSE_HTTP_CODE, @@ -356,18 +357,19 @@ internal class CategorySearchTest { TEST_RESPONSE_UUID ) - @Suppress("DEPRECATION", "JVM_STATIC_IN_PRIVATE_COMPANION") + @Suppress("JVM_STATIC_IN_PRIVATE_COMPANION") @BeforeAll @JvmStatic fun setUpAll() { + resetLogImpl() mockkStatic(ASSERTIONS_KT_CLASS_NAME) - every { reportError(any()) } returns Unit } @Suppress("JVM_STATIC_IN_PRIVATE_COMPANION") @AfterAll @JvmStatic fun tearDownAll() { + reinitializeLogImpl() unmockkStatic(ASSERTIONS_KT_CLASS_NAME) } } diff --git a/MapboxSearch/sdk/src/test/java/com/mapbox/search/HighlightsCalculatorTest.kt b/MapboxSearch/sdk/src/test/java/com/mapbox/search/HighlightsCalculatorTest.kt index bdd44e3fd..f53951b43 100644 --- a/MapboxSearch/sdk/src/test/java/com/mapbox/search/HighlightsCalculatorTest.kt +++ b/MapboxSearch/sdk/src/test/java/com/mapbox/search/HighlightsCalculatorTest.kt @@ -1,8 +1,12 @@ package com.mapbox.search +import com.mapbox.search.common.logger.reinitializeLogImpl +import com.mapbox.search.common.logger.resetLogImpl import com.mapbox.test.dsl.TestCase import io.mockk.every import io.mockk.mockk +import org.junit.jupiter.api.AfterAll +import org.junit.jupiter.api.BeforeAll import org.junit.jupiter.api.TestFactory internal class HighlightsCalculatorTest { @@ -81,5 +85,19 @@ internal class HighlightsCalculatorTest { emptyList() ) ) + + @Suppress("JVM_STATIC_IN_PRIVATE_COMPANION") + @BeforeAll + @JvmStatic + fun setUpAll() { + resetLogImpl() + } + + @Suppress("JVM_STATIC_IN_PRIVATE_COMPANION") + @AfterAll + @JvmStatic + fun tearDownAll() { + reinitializeLogImpl() + } } } diff --git a/MapboxSearch/sdk/src/test/java/com/mapbox/search/OfflineSearchEngineTest.kt b/MapboxSearch/sdk/src/test/java/com/mapbox/search/OfflineSearchEngineTest.kt index 46d03d84a..4a3516f79 100644 --- a/MapboxSearch/sdk/src/test/java/com/mapbox/search/OfflineSearchEngineTest.kt +++ b/MapboxSearch/sdk/src/test/java/com/mapbox/search/OfflineSearchEngineTest.kt @@ -2,7 +2,8 @@ package com.mapbox.search import com.mapbox.geojson.Point import com.mapbox.search.TestConstants.ASSERTIONS_KT_CLASS_NAME -import com.mapbox.search.common.reportError +import com.mapbox.search.common.logger.reinitializeLogImpl +import com.mapbox.search.common.logger.resetLogImpl import com.mapbox.search.core.CoreSearchCallback import com.mapbox.search.core.CoreSearchEngineInterface import com.mapbox.search.internal.bindgen.ResultType @@ -693,18 +694,19 @@ internal class OfflineSearchEngineTest { requestOptions = TEST_REQUEST_OPTIONS, ) - @Suppress("DEPRECATION", "JVM_STATIC_IN_PRIVATE_COMPANION") + @Suppress("JVM_STATIC_IN_PRIVATE_COMPANION") @BeforeAll @JvmStatic fun setUpAll() { + resetLogImpl() mockkStatic(ASSERTIONS_KT_CLASS_NAME) - every { reportError(any()) } returns Unit } @Suppress("JVM_STATIC_IN_PRIVATE_COMPANION") @AfterAll @JvmStatic fun tearDownAll() { + reinitializeLogImpl() unmockkStatic(ASSERTIONS_KT_CLASS_NAME) } } diff --git a/MapboxSearch/sdk/src/test/java/com/mapbox/search/ReverseGeocodingSearchTest.kt b/MapboxSearch/sdk/src/test/java/com/mapbox/search/ReverseGeocodingSearchTest.kt index 6e73e2fa9..ede7e8590 100644 --- a/MapboxSearch/sdk/src/test/java/com/mapbox/search/ReverseGeocodingSearchTest.kt +++ b/MapboxSearch/sdk/src/test/java/com/mapbox/search/ReverseGeocodingSearchTest.kt @@ -2,7 +2,8 @@ package com.mapbox.search import com.mapbox.geojson.Point import com.mapbox.search.TestConstants.ASSERTIONS_KT_CLASS_NAME -import com.mapbox.search.common.reportError +import com.mapbox.search.common.logger.reinitializeLogImpl +import com.mapbox.search.common.logger.resetLogImpl import com.mapbox.search.core.CoreReverseGeoOptions import com.mapbox.search.core.CoreSearchCallback import com.mapbox.search.core.CoreSearchEngineInterface @@ -334,18 +335,19 @@ internal class ReverseGeocodingSearchTest { TEST_RESPONSE_UUID ) - @Suppress("DEPRECATION", "JVM_STATIC_IN_PRIVATE_COMPANION") + @Suppress("JVM_STATIC_IN_PRIVATE_COMPANION") @BeforeAll @JvmStatic fun setUpAll() { + resetLogImpl() mockkStatic(ASSERTIONS_KT_CLASS_NAME) - every { reportError(any()) } returns Unit } @Suppress("JVM_STATIC_IN_PRIVATE_COMPANION") @AfterAll @JvmStatic fun tearDownAll() { + reinitializeLogImpl() unmockkStatic(ASSERTIONS_KT_CLASS_NAME) } } diff --git a/MapboxSearch/sdk/src/test/java/com/mapbox/search/SearchEngineTest.kt b/MapboxSearch/sdk/src/test/java/com/mapbox/search/SearchEngineTest.kt index 03d786981..741ac9ab8 100644 --- a/MapboxSearch/sdk/src/test/java/com/mapbox/search/SearchEngineTest.kt +++ b/MapboxSearch/sdk/src/test/java/com/mapbox/search/SearchEngineTest.kt @@ -2,7 +2,8 @@ package com.mapbox.search import com.mapbox.geojson.Point import com.mapbox.search.TestConstants.ASSERTIONS_KT_CLASS_NAME -import com.mapbox.search.common.reportError +import com.mapbox.search.common.logger.reinitializeLogImpl +import com.mapbox.search.common.logger.resetLogImpl import com.mapbox.search.core.CoreRequestOptions import com.mapbox.search.core.CoreSearchCallback import com.mapbox.search.core.CoreSearchEngineInterface @@ -693,18 +694,19 @@ internal class SearchEngineTest { requestOptions = TEST_USER_RECORD_SEARCH_SUGGESTION.requestOptions ) - @Suppress("DEPRECATION", "JVM_STATIC_IN_PRIVATE_COMPANION") + @Suppress("JVM_STATIC_IN_PRIVATE_COMPANION") @BeforeAll @JvmStatic fun setUpAll() { + resetLogImpl() mockkStatic(ASSERTIONS_KT_CLASS_NAME) - every { reportError(any()) } returns Unit } @Suppress("JVM_STATIC_IN_PRIVATE_COMPANION") @AfterAll @JvmStatic fun tearDownAll() { + reinitializeLogImpl() unmockkStatic(ASSERTIONS_KT_CLASS_NAME) } } diff --git a/MapboxSearch/sdk/src/test/java/com/mapbox/search/analytics/events/AnalyticsServiceImplTest.kt b/MapboxSearch/sdk/src/test/java/com/mapbox/search/analytics/events/AnalyticsServiceImplTest.kt index c4f831a38..012563510 100644 --- a/MapboxSearch/sdk/src/test/java/com/mapbox/search/analytics/events/AnalyticsServiceImplTest.kt +++ b/MapboxSearch/sdk/src/test/java/com/mapbox/search/analytics/events/AnalyticsServiceImplTest.kt @@ -16,6 +16,8 @@ import com.mapbox.search.analytics.MissingResultFeedbackEvent import com.mapbox.search.analytics.SearchEventsService import com.mapbox.search.analytics.SearchFeedbackEventsFactory import com.mapbox.search.common.FixedPointLocationEngine +import com.mapbox.search.common.logger.reinitializeLogImpl +import com.mapbox.search.common.logger.resetLogImpl import com.mapbox.search.result.mapToPlatform import com.mapbox.search.tests_support.BlockingCompletionCallback import com.mapbox.search.tests_support.TestExecutor @@ -33,8 +35,10 @@ import io.mockk.mockkStatic import io.mockk.slot import io.mockk.spyk import io.mockk.unmockkStatic +import org.junit.jupiter.api.AfterAll import org.junit.jupiter.api.AfterEach import org.junit.jupiter.api.Assertions +import org.junit.jupiter.api.BeforeAll import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.TestFactory import java.lang.IllegalStateException @@ -465,5 +469,19 @@ internal class AnalyticsServiceImplTest { TEST_RESPONSE_INFO, "Fix, please!" ) + + @Suppress("JVM_STATIC_IN_PRIVATE_COMPANION") + @BeforeAll + @JvmStatic + fun setUpAll() { + resetLogImpl() + } + + @Suppress("JVM_STATIC_IN_PRIVATE_COMPANION") + @AfterAll + @JvmStatic + fun tearDownAll() { + reinitializeLogImpl() + } } } diff --git a/MapboxSearch/sdk/src/test/java/com/mapbox/search/location/LocationEngineAdapterTest.kt b/MapboxSearch/sdk/src/test/java/com/mapbox/search/location/LocationEngineAdapterTest.kt index 82ddb60f0..491a11cec 100644 --- a/MapboxSearch/sdk/src/test/java/com/mapbox/search/location/LocationEngineAdapterTest.kt +++ b/MapboxSearch/sdk/src/test/java/com/mapbox/search/location/LocationEngineAdapterTest.kt @@ -7,6 +7,8 @@ import com.mapbox.android.core.location.LocationEngineCallback import com.mapbox.android.core.location.LocationEngineResult import com.mapbox.android.core.permissions.PermissionsManager import com.mapbox.geojson.Point +import com.mapbox.search.common.logger.reinitializeLogImpl +import com.mapbox.search.common.logger.resetLogImpl import com.mapbox.search.utils.TimeProvider import com.mapbox.test.dsl.TestCase import io.mockk.every @@ -14,7 +16,9 @@ import io.mockk.mockk import io.mockk.mockkStatic import io.mockk.slot import io.mockk.unmockkStatic +import org.junit.jupiter.api.AfterAll import org.junit.jupiter.api.AfterEach +import org.junit.jupiter.api.BeforeAll import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.TestFactory @@ -151,5 +155,19 @@ internal class LocationEngineAdapterTest { every { longitude } returns point.longitude() every { latitude } returns point.latitude() } + + @Suppress("JVM_STATIC_IN_PRIVATE_COMPANION") + @BeforeAll + @JvmStatic + fun setUpAll() { + resetLogImpl() + } + + @Suppress("JVM_STATIC_IN_PRIVATE_COMPANION") + @AfterAll + @JvmStatic + fun tearDownAll() { + reinitializeLogImpl() + } } } diff --git a/MapboxSearch/sdk/src/test/java/com/mapbox/search/metadata/WeekTimestampTest.kt b/MapboxSearch/sdk/src/test/java/com/mapbox/search/metadata/WeekTimestampTest.kt index 9af316e95..c620c3216 100644 --- a/MapboxSearch/sdk/src/test/java/com/mapbox/search/metadata/WeekTimestampTest.kt +++ b/MapboxSearch/sdk/src/test/java/com/mapbox/search/metadata/WeekTimestampTest.kt @@ -2,10 +2,8 @@ package com.mapbox.search.metadata import com.mapbox.search.BuildConfig import com.mapbox.search.TestConstants.ASSERTIONS_KT_CLASS_NAME -import com.mapbox.search.common.reportError import com.mapbox.search.tests_support.catchThrowable import com.mapbox.test.dsl.TestCase -import io.mockk.every import io.mockk.mockkStatic import io.mockk.unmockkStatic import org.junit.jupiter.api.AfterAll @@ -52,8 +50,6 @@ internal class WeekTimestampTest { @JvmStatic fun setUpAll() { mockkStatic(ASSERTIONS_KT_CLASS_NAME) - @Suppress("DEPRECATION") - every { reportError(any()) } returns Unit } @AfterAll diff --git a/MapboxSearch/sdk/src/test/java/com/mapbox/search/result/OriginalSearchResultTest.kt b/MapboxSearch/sdk/src/test/java/com/mapbox/search/result/OriginalSearchResultTest.kt index 14e1783df..5f1f30016 100644 --- a/MapboxSearch/sdk/src/test/java/com/mapbox/search/result/OriginalSearchResultTest.kt +++ b/MapboxSearch/sdk/src/test/java/com/mapbox/search/result/OriginalSearchResultTest.kt @@ -5,7 +5,8 @@ import com.mapbox.search.BuildConfig import com.mapbox.search.Language import com.mapbox.search.SearchResultMetadata import com.mapbox.search.TestConstants.ASSERTIONS_KT_CLASS_NAME -import com.mapbox.search.common.reportError +import com.mapbox.search.common.logger.reinitializeLogImpl +import com.mapbox.search.common.logger.resetLogImpl import com.mapbox.search.core.CoreResultMetadata import com.mapbox.search.core.CoreRoutablePoint import com.mapbox.search.core.CoreSearchResult @@ -14,7 +15,6 @@ import com.mapbox.search.internal.bindgen.ResultType import com.mapbox.search.tests_support.catchThrowable import com.mapbox.search.tests_support.createCoreSearchAddress import com.mapbox.test.dsl.TestCase -import io.mockk.every import io.mockk.mockkStatic import io.mockk.unmockkStatic import org.junit.jupiter.api.AfterAll @@ -209,18 +209,19 @@ internal class OriginalSearchResultTest { ) } - @Suppress("DEPRECATION", "JVM_STATIC_IN_PRIVATE_COMPANION") + @Suppress("JVM_STATIC_IN_PRIVATE_COMPANION") @BeforeAll @JvmStatic fun setUpAll() { + resetLogImpl() mockkStatic(ASSERTIONS_KT_CLASS_NAME) - every { reportError(any()) } returns Unit } @Suppress("JVM_STATIC_IN_PRIVATE_COMPANION") @AfterAll @JvmStatic fun tearDownAll() { + reinitializeLogImpl() unmockkStatic(ASSERTIONS_KT_CLASS_NAME) } } diff --git a/MapboxSearch/sdk/src/test/java/com/mapbox/search/result/SearchResultFactoryTest.kt b/MapboxSearch/sdk/src/test/java/com/mapbox/search/result/SearchResultFactoryTest.kt index 638ac5679..1f403fd9e 100644 --- a/MapboxSearch/sdk/src/test/java/com/mapbox/search/result/SearchResultFactoryTest.kt +++ b/MapboxSearch/sdk/src/test/java/com/mapbox/search/result/SearchResultFactoryTest.kt @@ -2,12 +2,12 @@ package com.mapbox.search.result import com.mapbox.geojson.Point import com.mapbox.search.TestConstants.ASSERTIONS_KT_CLASS_NAME -import com.mapbox.search.common.reportError +import com.mapbox.search.common.logger.reinitializeLogImpl +import com.mapbox.search.common.logger.resetLogImpl import com.mapbox.search.common.reportRelease import com.mapbox.search.tests_support.createTestOriginalSearchResult import com.mapbox.search.tests_support.createTestRequestOptions import com.mapbox.test.dsl.TestCase -import io.mockk.every import io.mockk.mockkStatic import io.mockk.unmockkStatic import org.junit.jupiter.api.AfterAll @@ -92,18 +92,19 @@ internal class SearchResultFactoryTest { types = listOf(OriginalResultType.POI) ) - @Suppress("DEPRECATION", "JVM_STATIC_IN_PRIVATE_COMPANION") + @Suppress("JVM_STATIC_IN_PRIVATE_COMPANION") @BeforeAll @JvmStatic fun setUpAll() { + resetLogImpl() mockkStatic(ASSERTIONS_KT_CLASS_NAME) - every { reportError(any()) } returns Unit } @Suppress("JVM_STATIC_IN_PRIVATE_COMPANION") @AfterAll @JvmStatic fun tearDownAll() { + reinitializeLogImpl() unmockkStatic(ASSERTIONS_KT_CLASS_NAME) } } diff --git a/MapboxSearch/sdk/src/test/java/com/mapbox/search/result/SearchResultTest.kt b/MapboxSearch/sdk/src/test/java/com/mapbox/search/result/SearchResultTest.kt index 12d01fd72..098704680 100644 --- a/MapboxSearch/sdk/src/test/java/com/mapbox/search/result/SearchResultTest.kt +++ b/MapboxSearch/sdk/src/test/java/com/mapbox/search/result/SearchResultTest.kt @@ -3,7 +3,6 @@ package com.mapbox.search.result import com.mapbox.geojson.Point import com.mapbox.search.BuildConfig import com.mapbox.search.TestConstants.ASSERTIONS_KT_CLASS_NAME -import com.mapbox.search.common.reportError import com.mapbox.search.common.tests.CustomTypeObjectCreatorImpl import com.mapbox.search.common.tests.ReflectionObjectsFactory import com.mapbox.search.common.tests.ToStringVerifier @@ -14,7 +13,6 @@ import com.mapbox.search.tests_support.withPrefabTestBoundingBox import com.mapbox.search.tests_support.withPrefabTestOriginalSearchResult import com.mapbox.search.tests_support.withPrefabTestPoint import com.mapbox.test.dsl.TestCase -import io.mockk.every import io.mockk.mockkStatic import io.mockk.unmockkStatic import nl.jqno.equalsverifier.EqualsVerifier @@ -160,12 +158,11 @@ internal class SearchResultTest { action = SearchResultSuggestAction(endpoint = "test-endpoint-1", path = "test-path-1", query = "test-query-1", body = null, multiRetrievable = true) ) - @Suppress("DEPRECATION", "JVM_STATIC_IN_PRIVATE_COMPANION") + @Suppress("JVM_STATIC_IN_PRIVATE_COMPANION") @BeforeAll @JvmStatic fun setUpAll() { mockkStatic(ASSERTIONS_KT_CLASS_NAME) - every { reportError(any()) } returns Unit } @Suppress("JVM_STATIC_IN_PRIVATE_COMPANION") diff --git a/MapboxSearch/ui/src/main/java/com/mapbox/search/ui/view/SearchResultsView.kt b/MapboxSearch/ui/src/main/java/com/mapbox/search/ui/view/SearchResultsView.kt index a7effa5b6..07d5a85dc 100644 --- a/MapboxSearch/ui/src/main/java/com/mapbox/search/ui/view/SearchResultsView.kt +++ b/MapboxSearch/ui/src/main/java/com/mapbox/search/ui/view/SearchResultsView.kt @@ -404,7 +404,7 @@ public class SearchResultsView @JvmOverloads constructor( isLoadingCompleted = true showError(UiError.UnknownError) throwDebug(e) { - "Unable to load history records" + "Unable to load history records: ${e.message}" } } } diff --git a/MapboxSearch/ui/src/main/java/com/mapbox/search/ui/view/favorite/rename/EditFavoriteView.kt b/MapboxSearch/ui/src/main/java/com/mapbox/search/ui/view/favorite/rename/EditFavoriteView.kt index 580550867..80bf2d9c2 100644 --- a/MapboxSearch/ui/src/main/java/com/mapbox/search/ui/view/favorite/rename/EditFavoriteView.kt +++ b/MapboxSearch/ui/src/main/java/com/mapbox/search/ui/view/favorite/rename/EditFavoriteView.kt @@ -144,7 +144,7 @@ internal class EditFavoriteView : LinearLayout { Toast.makeText(context, R.string.mapbox_search_sdk_favorite_update_error, Toast.LENGTH_SHORT).show() throwDebug(e) { - "Unable to update favorite record" + "Unable to update favorite record: ${e.message}" } } } diff --git a/MapboxSearch/ui/src/main/java/com/mapbox/search/ui/view/place/SearchPlaceBottomSheetView.kt b/MapboxSearch/ui/src/main/java/com/mapbox/search/ui/view/place/SearchPlaceBottomSheetView.kt index bc03b6c42..609d3c952 100644 --- a/MapboxSearch/ui/src/main/java/com/mapbox/search/ui/view/place/SearchPlaceBottomSheetView.kt +++ b/MapboxSearch/ui/src/main/java/com/mapbox/search/ui/view/place/SearchPlaceBottomSheetView.kt @@ -296,7 +296,7 @@ public class SearchPlaceBottomSheetView @JvmOverloads constructor( override fun onError(e: Exception) { // Shouldn't happen with favorites throwDebug(e) { - "Unable to add favorite" + "Unable to add favorite: ${e.message}" } } }) diff --git a/MapboxSearch/ui/src/main/java/com/mapbox/search/ui/view/search/address/AddressSearchViewController.kt b/MapboxSearch/ui/src/main/java/com/mapbox/search/ui/view/search/address/AddressSearchViewController.kt index 2b4a4fc1a..bb77964a8 100644 --- a/MapboxSearch/ui/src/main/java/com/mapbox/search/ui/view/search/address/AddressSearchViewController.kt +++ b/MapboxSearch/ui/src/main/java/com/mapbox/search/ui/view/search/address/AddressSearchViewController.kt @@ -119,7 +119,7 @@ internal class AddressSearchViewController : BaseSearchController { } throwDebug(e) { - "Unable to update favorite record" + "Unable to update favorite record: ${e.message}" } router.popToRoot() }