From 05e231579b4d01e73e77229ac9d2d543dcb17039 Mon Sep 17 00:00:00 2001 From: MohitMaliFtechiz Date: Mon, 31 Mar 2025 15:27:31 +0530 Subject: [PATCH] Fixed: Compilation issues in unit test cases. The issue was in Gradle itself, which was preventing us from merging or excluding duplicate META-INF files. * Upgraded Gradle to `8.11.0-alpha03` for better support for Android 16. * Upgraded the Gradle wrapper to `8.13`, the latest version. * Fixed: Some deprecated methods in the custom app's Gradle. The new methods for registering tasks are better than the previous ones, which is why Gradle deprecated the older methods. * Refactored the `createDynamically` task for custom apps according to new gradle. * Fixed: Some lint and detekt issues. --- app/build.gradle.kts | 13 ++++++--- build.gradle.kts | 4 ++- buildSrc/build.gradle.kts | 2 +- buildSrc/src/main/kotlin/Versions.kt | 2 +- buildSrc/src/main/kotlin/custom/CustomApps.kt | 2 +- .../kiwixmobile/core/dao/NewBookDaoTest.kt | 4 ++- .../core/dao/NewBookmarksDaoTest.kt | 7 +++-- .../core/entity/MetaLinkNetworkEntityTest.kt | 27 +++++++------------ .../core/search/viewmodel/SearchStateTest.kt | 8 +++--- .../search/viewmodel/SearchViewModelTest.kt | 2 -- .../viewmodel/SuggestionIteratorWrapper.kt | 4 ++- custom/build.gradle.kts | 18 ++++++------- gradle/wrapper/gradle-wrapper.properties | 2 +- lintConfig.xml | 1 + 14 files changed, 50 insertions(+), 46 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index d868903fd..2226a86b1 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -1,3 +1,4 @@ +import com.android.build.gradle.internal.tasks.factory.dependsOn import com.slack.keeper.optInToKeeper import org.w3c.dom.Element import plugin.KiwixConfigurationPlugin @@ -130,7 +131,7 @@ dependencies { androidTestImplementation(Libs.leakcanary_android_instrumentation) testImplementation(Libs.kotlinx_coroutines_test) } -task("generateVersionCodeAndName") { +tasks.register("generateVersionCodeAndName") { val file = File("VERSION_INFO") if (!file.exists()) file.createNewFile() file.printWriter().use { @@ -138,7 +139,7 @@ task("generateVersionCodeAndName") { } } -task("renameTarakFile") { +tasks.register("renameTarakFile") { val taraskFile = File("$rootDir/core/src/main/res/values-b+be+tarask/strings.xml") val mainStringsFile = File("$rootDir/core/src/main/res/values/strings.xml") @@ -214,6 +215,10 @@ fun elementToString(element: Element): String { return result.writer.toString() } -tasks.build { - dependsOn("renameTarakFile") +gradle.projectsEvaluated { + tasks.forEach { task -> + if (task.name != "renameTarakFile") { + task.dependsOn("renameTarakFile") + } + } } diff --git a/build.gradle.kts b/build.gradle.kts index 95259c517..326f75613 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,3 +1,5 @@ +import org.gradle.kotlin.dsl.register + buildscript { repositories { google() @@ -28,6 +30,6 @@ allprojects { } } -tasks.create("clean") { +tasks.register("clean") { delete(rootProject.layout.buildDirectory) } diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index 718c011bf..7765fae0c 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -11,7 +11,7 @@ repositories { } dependencies { - implementation("com.android.tools.build:gradle:8.10.0-alpha08") + implementation("com.android.tools.build:gradle:8.11.0-alpha03") implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:2.0.0") implementation("com.google.devtools.ksp:com.google.devtools.ksp.gradle.plugin:2.0.0-1.0.24") implementation("org.jacoco:org.jacoco.core:0.8.12") diff --git a/buildSrc/src/main/kotlin/Versions.kt b/buildSrc/src/main/kotlin/Versions.kt index 48d372ea9..57a9d6e18 100644 --- a/buildSrc/src/main/kotlin/Versions.kt +++ b/buildSrc/src/main/kotlin/Versions.kt @@ -48,7 +48,7 @@ object Versions { const val android_arch_lifecycle_extensions: String = "1.1.1" - const val com_android_tools_build_gradle: String = "8.10.0-alpha08" + const val com_android_tools_build_gradle: String = "8.11.0-alpha03" const val de_fayard_buildsrcversions_gradle_plugin: String = "0.7.0" diff --git a/buildSrc/src/main/kotlin/custom/CustomApps.kt b/buildSrc/src/main/kotlin/custom/CustomApps.kt index 7f4faa4d1..b1dade9ed 100644 --- a/buildSrc/src/main/kotlin/custom/CustomApps.kt +++ b/buildSrc/src/main/kotlin/custom/CustomApps.kt @@ -24,7 +24,7 @@ import org.json.simple.JSONObject import org.json.simple.parser.JSONParser import java.io.File -typealias ProductFlavors = NamedDomainObjectContainer +typealias ProductFlavors = NamedDomainObjectContainer object CustomApps { diff --git a/core/src/test/java/org/kiwix/kiwixmobile/core/dao/NewBookDaoTest.kt b/core/src/test/java/org/kiwix/kiwixmobile/core/dao/NewBookDaoTest.kt index 1010622c1..338de94cb 100644 --- a/core/src/test/java/org/kiwix/kiwixmobile/core/dao/NewBookDaoTest.kt +++ b/core/src/test/java/org/kiwix/kiwixmobile/core/dao/NewBookDaoTest.kt @@ -91,7 +91,9 @@ internal class NewBookDaoTest { } } - private fun expectEmissionOfExistingAndNotExistingBook(isInTrashFolder: Boolean = false): Pair { + private fun expectEmissionOfExistingAndNotExistingBook( + isInTrashFolder: Boolean = false + ): Pair { val query: Query = mockk() every { box.query().build() } returns query val zimReaderSourceThatExists = mockk() diff --git a/core/src/test/java/org/kiwix/kiwixmobile/core/dao/NewBookmarksDaoTest.kt b/core/src/test/java/org/kiwix/kiwixmobile/core/dao/NewBookmarksDaoTest.kt index 4b6955b0c..a01d40020 100644 --- a/core/src/test/java/org/kiwix/kiwixmobile/core/dao/NewBookmarksDaoTest.kt +++ b/core/src/test/java/org/kiwix/kiwixmobile/core/dao/NewBookmarksDaoTest.kt @@ -18,17 +18,17 @@ package org.kiwix.kiwixmobile.core.dao -import org.junit.jupiter.api.Test import io.mockk.every import io.mockk.mockk import io.mockk.verify import io.objectbox.Box import io.objectbox.query.Query import io.objectbox.query.QueryBuilder -import org.kiwix.kiwixmobile.core.dao.entities.BookmarkEntity_ +import org.junit.jupiter.api.Test import org.kiwix.kiwixmobile.core.dao.entities.BookmarkEntity -import org.kiwix.kiwixmobile.core.page.bookmark +import org.kiwix.kiwixmobile.core.dao.entities.BookmarkEntity_ import org.kiwix.kiwixmobile.core.page.adapter.Page +import org.kiwix.kiwixmobile.core.page.bookmark import org.kiwix.kiwixmobile.core.page.bookmark.adapter.BookmarkItem import org.kiwix.kiwixmobile.core.reader.ZimFileReader @@ -69,7 +69,6 @@ internal class NewBookmarksDaoTest { every { bookmarkItem.zimName } returns "" every { bookmarkItem.databaseId } returns 0L newBookmarksDao.getCurrentZimBookmarksUrl(zimFileReader) - val bookmarkEntity: BookmarkEntity = mockk() every { query.property(BookmarkEntity_.bookmarkUrl).findStrings().toList().distinct() } returns listOf("") diff --git a/core/src/test/java/org/kiwix/kiwixmobile/core/entity/MetaLinkNetworkEntityTest.kt b/core/src/test/java/org/kiwix/kiwixmobile/core/entity/MetaLinkNetworkEntityTest.kt index 2bf805b39..81dee0a95 100644 --- a/core/src/test/java/org/kiwix/kiwixmobile/core/entity/MetaLinkNetworkEntityTest.kt +++ b/core/src/test/java/org/kiwix/kiwixmobile/core/entity/MetaLinkNetworkEntityTest.kt @@ -27,13 +27,12 @@ class MetaLinkNetworkEntityTest { @Throws(Exception::class) fun testDeserialize() { val serializer = Persister() - val result = - serializer.read( - MetaLinkNetworkEntity::class.java, - MetaLinkNetworkEntityTest::class.java.classLoader!!.getResourceAsStream( - "wikipedia_af_all_nopic_2016-05.zim.meta4" - ) + val result = serializer.read( + MetaLinkNetworkEntity::class.java, + MetaLinkNetworkEntityTest::class.java.classLoader!!.getResourceAsStream( + "wikipedia_af_all_nopic_2016-05.zim.meta4" ) + ) result?.urls?.let { MetaLinkNetworkEntityUrlAssert(it).hasItems( listOf( @@ -68,9 +67,7 @@ class MetaLinkNetworkEntityTest { } // Basic file attributes assertThat(result.file?.name).isEqualTo("wikipedia_af_all_nopic_2016-05.zim") - assertThat(result.file?.size).isEqualTo(63973123L) - // File hashes assertThat(result.file?.getHash("md5")).isEqualTo("6f06866b61c4a921b57f28cfd4307220") assertThat( @@ -103,21 +100,17 @@ class MetaLinkNetworkEntityTest { */ class MetaLinkNetworkEntityUrlAssert( actual: List - ) : - AbstractAssert>( - actual, - MetaLinkNetworkEntityUrlAssert::class.java - ) { + ) : AbstractAssert>( + actual, + MetaLinkNetworkEntityUrlAssert::class.java + ) { private fun intersectionWith( first: List, second: List, function: (S, T) -> Boolean ): Boolean { val filtered = first.filter { a -> second.any { b -> function(a, b) } } - if (filtered.isNotEmpty()) { - return true - } - return false + return filtered.isNotEmpty() } fun hasItems(items: List): Boolean { diff --git a/core/src/test/java/org/kiwix/kiwixmobile/core/search/viewmodel/SearchStateTest.kt b/core/src/test/java/org/kiwix/kiwixmobile/core/search/viewmodel/SearchStateTest.kt index 116177b7c..9aca9dabe 100644 --- a/core/src/test/java/org/kiwix/kiwixmobile/core/search/viewmodel/SearchStateTest.kt +++ b/core/src/test/java/org/kiwix/kiwixmobile/core/search/viewmodel/SearchStateTest.kt @@ -43,8 +43,9 @@ internal class SearchStateTest { val estimatedMatches = 100 every { suggestionSearchWrapper.estimatedMatches } returns estimatedMatches.toLong() // Settings list to hasNext() to ensure it returns true only for the first call. - // Otherwise, if we do not set this, the method will always return true when checking if the iterator has a next value, - // causing our test case to get stuck in an infinite loop due to this explicit setting. + // Otherwise, if we do not set this, the method will always return true when + // checking if the iterator has a next value, causing our test case to get stuck + // in an infinite loop due to this explicit setting. every { searchIteratorWrapper.hasNext() } returnsMany listOf(true, false) every { searchIteratorWrapper.next() } returns entryWrapper every { entryWrapper.title } returns searchTerm @@ -119,7 +120,8 @@ internal class SearchStateTest { every { entryWrapper.path } returns "path" every { suggestionSearchWrapper.getResults(any(), any()) } returns searchIteratorWrapper - val searchResultsWithTerm = SearchResultsWithTerm(searchTerm, suggestionSearchWrapper, mockk()) + val searchResultsWithTerm = + SearchResultsWithTerm(searchTerm, suggestionSearchWrapper, mockk()) val searchState = SearchState(searchTerm, searchResultsWithTerm, emptyList(), FromWebView) var list: List? = emptyList() var list1: List? = emptyList() diff --git a/core/src/test/java/org/kiwix/kiwixmobile/core/search/viewmodel/SearchViewModelTest.kt b/core/src/test/java/org/kiwix/kiwixmobile/core/search/viewmodel/SearchViewModelTest.kt index 3b4103db6..1aadfb56b 100644 --- a/core/src/test/java/org/kiwix/kiwixmobile/core/search/viewmodel/SearchViewModelTest.kt +++ b/core/src/test/java/org/kiwix/kiwixmobile/core/search/viewmodel/SearchViewModelTest.kt @@ -50,7 +50,6 @@ import org.kiwix.kiwixmobile.core.dao.RecentSearchRoomDao import org.kiwix.kiwixmobile.core.reader.ZimFileReader import org.kiwix.kiwixmobile.core.reader.ZimReaderContainer import org.kiwix.kiwixmobile.core.search.adapter.SearchListItem.RecentSearchListItem -import org.kiwix.kiwixmobile.core.search.adapter.SearchListItem.ZimSearchResultListItem import org.kiwix.kiwixmobile.core.search.viewmodel.Action.ActivityResultReceived import org.kiwix.kiwixmobile.core.search.viewmodel.Action.ClickedSearchInText import org.kiwix.kiwixmobile.core.search.viewmodel.Action.ConfirmedDelete @@ -123,7 +122,6 @@ internal class SearchViewModelTest { @Test fun `SearchState combines sources from inputs`() = runTest { - val item = ZimSearchResultListItem("", "") val searchTerm = "searchTerm" val searchOrigin = FromWebView val suggestionSearch: SuggestionSearch = mockk() diff --git a/core/src/test/java/org/kiwix/kiwixmobile/core/search/viewmodel/SuggestionIteratorWrapper.kt b/core/src/test/java/org/kiwix/kiwixmobile/core/search/viewmodel/SuggestionIteratorWrapper.kt index 85340cd69..e2299e646 100644 --- a/core/src/test/java/org/kiwix/kiwixmobile/core/search/viewmodel/SuggestionIteratorWrapper.kt +++ b/core/src/test/java/org/kiwix/kiwixmobile/core/search/viewmodel/SuggestionIteratorWrapper.kt @@ -21,7 +21,9 @@ package org.kiwix.kiwixmobile.core.search.viewmodel import org.kiwix.libzim.SuggestionIterator class SuggestionIteratorWrapper : SuggestionIterator() { - override fun remove() {} + override fun remove() { + // Do nothing just to ignore the EmptyFunctionBlock detekt error. + } override fun hasNext(): Boolean = super.hasNext() override fun next(): SuggestionItemWrapper = super.next() as SuggestionItemWrapper diff --git a/custom/build.gradle.kts b/custom/build.gradle.kts index 61ab62934..3284ccdaf 100644 --- a/custom/build.gradle.kts +++ b/custom/build.gradle.kts @@ -60,8 +60,8 @@ android { } } -fun ProductFlavor.createDownloadTask(file: File): Task { - return tasks.create( +fun ProductFlavor.createDownloadTask(file: File): TaskProvider { + return tasks.register( "download${ name.replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else "$it" @@ -157,8 +157,8 @@ fun writeZimFileDataInChunk( outputStream?.close() } -fun ProductFlavor.createDownloadTaskForPlayAssetDelivery(file: File): Task { - return tasks.create( +fun ProductFlavor.createDownloadTaskForPlayAssetDelivery(file: File): TaskProvider { + return tasks.register( "download${ name.replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else "$it" @@ -206,10 +206,10 @@ val String.removeAuthenticationFromUrl: String fun ProductFlavor.createPublishApkWithExpansionTask( file: File, applicationVariants: DomainObjectSet -): Task { +): TaskProvider { val capitalizedName = name.replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else "$it" } - return tasks.create("publish${capitalizedName}ReleaseApkWithExpansionFile") { + return tasks.register("publish${capitalizedName}ReleaseApkWithExpansionFile") { group = "publishing" description = "Uploads $capitalizedName to the Play Console with an Expansion file" doLast { @@ -237,10 +237,10 @@ fun DomainObjectSet.releaseVariantsFor(productFlavor: Produc .filter { !it.outputFileName.contains("universal") } .sortedBy { it.versionCodeOverride } -fun ProductFlavor.createPublishBundleWithAssetPlayDelivery(): Task { +fun ProductFlavor.createPublishBundleWithAssetPlayDelivery(): TaskProvider { val capitalizedName = name.replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else "$it" } - return tasks.create("publish${capitalizedName}ReleaseBundleWithPlayAssetDelivery") { + return tasks.register("publish${capitalizedName}ReleaseBundleWithPlayAssetDelivery") { group = "publishing" description = "Uploads $capitalizedName to the Play Console with an Play Asset delivery mode" doLast { @@ -250,7 +250,7 @@ fun ProductFlavor.createPublishBundleWithAssetPlayDelivery(): Task { .transactionWithCommit(packageName) { val generatedBundleFile = File( - "$buildDir/outputs/bundle/${capitalizedName.lowercase(Locale.getDefault())}" + + "${layout.buildDirectory}/outputs/bundle/${capitalizedName.lowercase(Locale.getDefault())}" + "Release/custom-${capitalizedName.lowercase(Locale.getDefault())}-release.aab" ) if (generatedBundleFile.exists()) { diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 0856dc972..5fdc5bb53 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ #Mon Dec 19 16:13:45 IST 2022 distributionBase=GRADLE_USER_HOME -distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip distributionPath=wrapper/dists zipStorePath=wrapper/dists zipStoreBase=GRADLE_USER_HOME diff --git a/lintConfig.xml b/lintConfig.xml index 44af8acfc..218443479 100644 --- a/lintConfig.xml +++ b/lintConfig.xml @@ -52,4 +52,5 @@ +