mirror of
https://gitee.com/zhangsken/AndroidIDE.git
synced 2026-10-16 07:49:44 +08:00
tests: use FileProvider API to access file paths
This commit is contained in:
@@ -0,0 +1,3 @@
|
|||||||
|
DO NOT DELETE!
|
||||||
|
|
||||||
|
This file is used in tests to check for the project's root directory.
|
||||||
Binary file not shown.
@@ -33,10 +33,11 @@ dependencies {
|
|||||||
implementation(projects.common)
|
implementation(projects.common)
|
||||||
implementation(projects.eventbusAndroid)
|
implementation(projects.eventbusAndroid)
|
||||||
implementation(projects.subprojects.toolingApiTesting)
|
implementation(projects.subprojects.toolingApiTesting)
|
||||||
|
implementation(projects.shared)
|
||||||
|
|
||||||
implementation(libs.common.editor)
|
implementation(libs.common.editor)
|
||||||
implementation(libs.tests.junit)
|
implementation(libs.tests.junit)
|
||||||
implementation(libs.tests.google.truth)
|
implementation(libs.tests.google.truth)
|
||||||
implementation(libs.tests.robolectric)
|
implementation(libs.tests.robolectric)
|
||||||
implementation(libs.tests.mockk)
|
implementation(libs.tests.mockk)
|
||||||
implementation(projects.actions)
|
|
||||||
}
|
}
|
||||||
@@ -39,19 +39,20 @@ import com.itsaky.androidide.tooling.api.messages.InitializeProjectMessage
|
|||||||
import com.itsaky.androidide.tooling.testing.ToolingApiTestLauncher
|
import com.itsaky.androidide.tooling.testing.ToolingApiTestLauncher
|
||||||
import com.itsaky.androidide.tooling.testing.ToolingApiTestLauncher.MultiVersionTestClient
|
import com.itsaky.androidide.tooling.testing.ToolingApiTestLauncher.MultiVersionTestClient
|
||||||
import com.itsaky.androidide.utils.Environment
|
import com.itsaky.androidide.utils.Environment
|
||||||
|
import com.itsaky.androidide.utils.FileProvider
|
||||||
import com.itsaky.androidide.utils.ILogger
|
import com.itsaky.androidide.utils.ILogger
|
||||||
import io.github.rosemoe.sora.text.Content
|
import io.github.rosemoe.sora.text.Content
|
||||||
import io.mockk.every
|
import io.mockk.every
|
||||||
import io.mockk.mockkStatic
|
import io.mockk.mockkStatic
|
||||||
import java.io.File
|
|
||||||
import java.nio.file.Path
|
|
||||||
import kotlin.io.path.pathString
|
|
||||||
import org.greenrobot.eventbus.EventBus
|
import org.greenrobot.eventbus.EventBus
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
import org.robolectric.RobolectricTestRunner
|
import org.robolectric.RobolectricTestRunner
|
||||||
import org.robolectric.RuntimeEnvironment
|
import org.robolectric.RuntimeEnvironment
|
||||||
import org.robolectric.annotation.Config
|
import org.robolectric.annotation.Config
|
||||||
|
import java.io.File
|
||||||
|
import java.nio.file.Path
|
||||||
|
import kotlin.io.path.pathString
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Runs tests for a language server.
|
* Runs tests for a language server.
|
||||||
@@ -87,7 +88,6 @@ abstract class LSPTest {
|
|||||||
val (server, project) =
|
val (server, project) =
|
||||||
ToolingApiTestLauncher()
|
ToolingApiTestLauncher()
|
||||||
.launchServer(
|
.launchServer(
|
||||||
implDir = FileProvider.implModule().pathString,
|
|
||||||
client = MultiVersionTestClient()
|
client = MultiVersionTestClient()
|
||||||
)
|
)
|
||||||
this.toolingProject = project
|
this.toolingProject = project
|
||||||
@@ -96,7 +96,7 @@ abstract class LSPTest {
|
|||||||
Lookup.DEFAULT.update(BuildService.KEY_PROJECT_PROXY, project)
|
Lookup.DEFAULT.update(BuildService.KEY_PROJECT_PROXY, project)
|
||||||
|
|
||||||
server
|
server
|
||||||
.initialize(InitializeProjectMessage(FileProvider.projectRoot().toFile().absolutePath))
|
.initialize(InitializeProjectMessage(FileProvider.testProjectRoot().toFile().absolutePath))
|
||||||
.get()
|
.get()
|
||||||
|
|
||||||
Environment.ANDROID_JAR = FileProvider.resources().resolve("android.jar").toFile()
|
Environment.ANDROID_JAR = FileProvider.resources().resolve("android.jar").toFile()
|
||||||
@@ -130,7 +130,17 @@ abstract class LSPTest {
|
|||||||
|
|
||||||
// As the content has been changed, we have to
|
// As the content has been changed, we have to
|
||||||
// Update the content in language server
|
// Update the content in language server
|
||||||
dispatchEvent(DocumentChangeEvent(file!!, contents.toString(), contents.toString(), 1, DELETE, 0, Range.NONE))
|
dispatchEvent(
|
||||||
|
DocumentChangeEvent(
|
||||||
|
file!!,
|
||||||
|
contents.toString(),
|
||||||
|
contents.toString(),
|
||||||
|
1,
|
||||||
|
DELETE,
|
||||||
|
0,
|
||||||
|
Range.NONE
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmOverloads
|
@JvmOverloads
|
||||||
|
|||||||
@@ -25,4 +25,7 @@ dependencies {
|
|||||||
implementation(libs.androidx.annotation)
|
implementation(libs.androidx.annotation)
|
||||||
implementation(libs.google.guava)
|
implementation(libs.google.guava)
|
||||||
implementation(projects.logger)
|
implementation(projects.logger)
|
||||||
|
|
||||||
|
testImplementation(libs.tests.google.truth)
|
||||||
|
testImplementation(libs.tests.junit)
|
||||||
}
|
}
|
||||||
+31
-5
@@ -14,15 +14,21 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
|
* along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package com.itsaky.androidide.lsp.api
|
package com.itsaky.androidide.utils
|
||||||
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
import java.nio.file.Paths
|
import java.nio.file.Paths
|
||||||
|
import kotlin.io.path.ExperimentalPathApi
|
||||||
|
import kotlin.io.path.absolute
|
||||||
|
import kotlin.io.path.name
|
||||||
import kotlin.io.path.readText
|
import kotlin.io.path.readText
|
||||||
|
import kotlin.io.path.walk
|
||||||
|
|
||||||
|
const val PROJECT_ROOT_FILE = ".androidide_root"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides paths to source files in 'resources' directory.
|
* Provides paths to various directories and files.
|
||||||
*
|
*
|
||||||
* @author Akash Yadav
|
* @author Akash Yadav
|
||||||
*/
|
*/
|
||||||
@@ -30,6 +36,10 @@ class FileProvider {
|
|||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
|
private val projectRoot by lazy {
|
||||||
|
currentDir().findProjectRoot()?.absolute()?.normalize()
|
||||||
|
}
|
||||||
|
|
||||||
@JvmField
|
@JvmField
|
||||||
val extension = run {
|
val extension = run {
|
||||||
val file = File(".").canonicalFile
|
val file = File(".").canonicalFile
|
||||||
@@ -41,8 +51,15 @@ class FileProvider {
|
|||||||
|
|
||||||
@JvmStatic fun currentDir(): Path = Paths.get(System.getProperty("user.dir")!!)
|
@JvmStatic fun currentDir(): Path = Paths.get(System.getProperty("user.dir")!!)
|
||||||
|
|
||||||
@JvmStatic fun implModule(): Path = currentDir().resolve("../../subprojects/tooling-api-impl")
|
@JvmStatic fun implModule(): Path = projectRoot().resolve("subprojects/tooling-api-impl")
|
||||||
@JvmStatic fun projectRoot(): Path = currentDir().resolve("../../tests/test-project")
|
|
||||||
|
@JvmStatic
|
||||||
|
fun projectRoot(): Path =
|
||||||
|
checkNotNull(projectRoot) {
|
||||||
|
"Unable to file project root. Check if '${PROJECT_ROOT_FILE}' file exists in the project root directory."
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic fun testProjectRoot(): Path = projectRoot().resolve("tests/test-project")
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the path to the 'resources' directory.
|
* Get the path to the 'resources' directory.
|
||||||
@@ -51,7 +68,7 @@ class FileProvider {
|
|||||||
*/
|
*/
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun resources(): Path {
|
fun resources(): Path {
|
||||||
return projectRoot().resolve("app/src/main/resources")
|
return testProjectRoot().resolve("app/src/main/resources")
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -68,3 +85,12 @@ class FileProvider {
|
|||||||
@JvmStatic fun contents(file: Path): StringBuilder = StringBuilder(file.readText())
|
@JvmStatic fun contents(file: Path): StringBuilder = StringBuilder(file.readText())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalPathApi::class)
|
||||||
|
private fun Path.findProjectRoot(): Path? {
|
||||||
|
if (walk().find { it.name == PROJECT_ROOT_FILE } != null) {
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
return parent?.findProjectRoot()
|
||||||
|
}
|
||||||
+10
-16
@@ -15,41 +15,35 @@
|
|||||||
* along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
|
* along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.itsaky.androidide.lsp.api
|
package com.itsaky.androidide.utils
|
||||||
|
|
||||||
import com.google.common.truth.Truth
|
import com.google.common.truth.Truth.assertThat
|
||||||
|
import org.junit.Test
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.nio.file.Files
|
import java.nio.file.Files
|
||||||
import org.junit.Test
|
|
||||||
import org.junit.runner.RunWith
|
|
||||||
import org.robolectric.RobolectricTestRunner
|
|
||||||
import org.robolectric.annotation.Config
|
|
||||||
|
|
||||||
/** @author Akash Yadav */
|
|
||||||
@RunWith(RobolectricTestRunner::class)
|
|
||||||
@Config(manifest = Config.NONE)
|
|
||||||
class FileProviderTest {
|
class FileProviderTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testPath() {
|
fun testPath() {
|
||||||
val path = FileProvider.sourceFile("SourceFileTest")
|
val path = FileProvider.sourceFile("SourceFileTest")
|
||||||
Truth.assertThat(Files.exists(path)).isTrue()
|
assertThat(Files.exists(path)).isTrue()
|
||||||
Truth.assertThat(path.fileName.toString()).isEqualTo("SourceFileTest_template.java")
|
assertThat(path.fileName.toString()).isEqualTo("SourceFileTest_template.java")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testNested() {
|
fun testNested() {
|
||||||
val path = FileProvider.sourceFile("package/SourceFileTest")
|
val path = FileProvider.sourceFile("package/SourceFileTest")
|
||||||
Truth.assertThat(Files.exists(path)).isTrue()
|
assertThat(Files.exists(path)).isTrue()
|
||||||
Truth.assertThat(path.fileName.toString()).isEqualTo("SourceFileTest_template.java")
|
assertThat(path.fileName.toString()).isEqualTo("SourceFileTest_template.java")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testExtension() {
|
fun testExtension() {
|
||||||
val folder = File(".").canonicalFile
|
val folder = File(".").canonicalFile
|
||||||
|
|
||||||
Truth.assertThat(FileProvider.extension).isNotEmpty()
|
assertThat(FileProvider.extension).isNotEmpty()
|
||||||
Truth.assertThat(FileProvider.extension)
|
assertThat(FileProvider.extension)
|
||||||
.isEqualTo(
|
.isEqualTo(
|
||||||
when (folder.name) {
|
when (folder.name) {
|
||||||
"xml" -> "xml"
|
"xml" -> "xml"
|
||||||
@@ -57,4 +51,4 @@ class FileProviderTest {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -44,4 +44,5 @@ dependencies {
|
|||||||
testImplementation(libs.tests.junit)
|
testImplementation(libs.tests.junit)
|
||||||
testImplementation(libs.tests.robolectric)
|
testImplementation(libs.tests.robolectric)
|
||||||
testImplementation(libs.tests.google.truth)
|
testImplementation(libs.tests.google.truth)
|
||||||
|
testImplementation(projects.shared)
|
||||||
}
|
}
|
||||||
+2
-1
@@ -26,6 +26,7 @@ import com.android.aaptcompiler.compileResource
|
|||||||
import com.android.aaptcompiler.extractPathData
|
import com.android.aaptcompiler.extractPathData
|
||||||
import com.android.utils.StdLogger
|
import com.android.utils.StdLogger
|
||||||
import com.android.utils.StdLogger.Level.VERBOSE
|
import com.android.utils.StdLogger.Level.VERBOSE
|
||||||
|
import com.itsaky.androidide.utils.FileProvider
|
||||||
import java.nio.file.Paths
|
import java.nio.file.Paths
|
||||||
import kotlin.io.path.absolute
|
import kotlin.io.path.absolute
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
@@ -39,7 +40,7 @@ class CompilerTest {
|
|||||||
@Test
|
@Test
|
||||||
fun `test simple compilatation`() {
|
fun `test simple compilatation`() {
|
||||||
val input =
|
val input =
|
||||||
Paths.get("../../app/src/main/res/layout/activity_editor.xml").absolute().normalize().toFile()
|
FileProvider.projectRoot().resolve("app/src/main/res/layout/activity_editor.xml").toFile()
|
||||||
val output = Paths.get("./build").absolute().normalize().toFile()
|
val output = Paths.get("./build").absolute().normalize().toFile()
|
||||||
println(input)
|
println(input)
|
||||||
println(output)
|
println(output)
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ dependencies {
|
|||||||
implementation(libs.google.guava)
|
implementation(libs.google.guava)
|
||||||
|
|
||||||
testImplementation(projects.subprojects.toolingApiTesting)
|
testImplementation(projects.subprojects.toolingApiTesting)
|
||||||
|
testImplementation(projects.shared)
|
||||||
testImplementation(libs.tests.junit)
|
testImplementation(libs.tests.junit)
|
||||||
testImplementation(libs.tests.google.truth)
|
testImplementation(libs.tests.google.truth)
|
||||||
testImplementation(libs.tests.robolectric)
|
testImplementation(libs.tests.robolectric)
|
||||||
|
|||||||
+9
-8
@@ -26,15 +26,16 @@ import com.itsaky.androidide.projects.ProjectManager
|
|||||||
import com.itsaky.androidide.projects.builder.BuildService
|
import com.itsaky.androidide.projects.builder.BuildService
|
||||||
import com.itsaky.androidide.tooling.api.messages.InitializeProjectMessage
|
import com.itsaky.androidide.tooling.api.messages.InitializeProjectMessage
|
||||||
import com.itsaky.androidide.tooling.testing.ToolingApiTestLauncher
|
import com.itsaky.androidide.tooling.testing.ToolingApiTestLauncher
|
||||||
|
import com.itsaky.androidide.utils.FileProvider
|
||||||
import com.itsaky.androidide.utils.SourceClassTrie.SourceNode
|
import com.itsaky.androidide.utils.SourceClassTrie.SourceNode
|
||||||
|
import java.io.File
|
||||||
|
import java.nio.file.Files
|
||||||
|
import kotlin.io.path.pathString
|
||||||
|
import kotlin.io.path.writeText
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
import org.robolectric.RobolectricTestRunner
|
import org.robolectric.RobolectricTestRunner
|
||||||
import org.robolectric.annotation.Config
|
import org.robolectric.annotation.Config
|
||||||
import java.io.File
|
|
||||||
import java.nio.file.Files
|
|
||||||
import java.nio.file.Paths
|
|
||||||
import kotlin.io.path.writeText
|
|
||||||
|
|
||||||
/** @author Akash Yadav */
|
/** @author Akash Yadav */
|
||||||
@RunWith(RobolectricTestRunner::class)
|
@RunWith(RobolectricTestRunner::class)
|
||||||
@@ -44,7 +45,7 @@ class ModuleProjectTest {
|
|||||||
@Test
|
@Test
|
||||||
fun test() {
|
fun test() {
|
||||||
val (server, project) = ToolingApiTestLauncher().launchServer()
|
val (server, project) = ToolingApiTestLauncher().launchServer()
|
||||||
server.initialize(InitializeProjectMessage(File("../../tests/test-project").absolutePath)).get()
|
server.initialize(InitializeProjectMessage(FileProvider.testProjectRoot().pathString)).get()
|
||||||
|
|
||||||
Lookup.DEFAULT.register(BuildService.KEY_PROJECT_PROXY, project)
|
Lookup.DEFAULT.register(BuildService.KEY_PROJECT_PROXY, project)
|
||||||
|
|
||||||
@@ -56,8 +57,7 @@ class ModuleProjectTest {
|
|||||||
|
|
||||||
val rootDir = root.projectDir
|
val rootDir = root.projectDir
|
||||||
assertThat(rootDir).isNotNull()
|
assertThat(rootDir).isNotNull()
|
||||||
assertThat(Files.isSameFile(rootDir.toPath(), File("../../tests/test-project").toPath()))
|
assertThat(Files.isSameFile(rootDir.toPath(), FileProvider.testProjectRoot())).isTrue()
|
||||||
.isTrue()
|
|
||||||
|
|
||||||
val app = root.findByPath(":app")
|
val app = root.findByPath(":app")
|
||||||
assertThat(app).isNotNull()
|
assertThat(app).isNotNull()
|
||||||
@@ -183,7 +183,8 @@ class ModuleProjectTest {
|
|||||||
private fun verifyProjectManagerAPIs() {
|
private fun verifyProjectManagerAPIs() {
|
||||||
|
|
||||||
val testCls =
|
val testCls =
|
||||||
Paths.get("../../tests/test-project/app/src/main/java/com/itsaky/test/app/Test.java")
|
FileProvider.testProjectRoot()
|
||||||
|
.resolve("app/src/main/java/com/itsaky/test/app/Test.java")
|
||||||
.toAbsolutePath()
|
.toAbsolutePath()
|
||||||
.normalize()
|
.normalize()
|
||||||
val testCls_renamed = testCls.parent!!.resolve("TestRenamed.java")
|
val testCls_renamed = testCls.parent!!.resolve("TestRenamed.java")
|
||||||
|
|||||||
+7
-4
@@ -18,7 +18,7 @@
|
|||||||
package com.itsaky.androidide.projects.classpath
|
package com.itsaky.androidide.projects.classpath
|
||||||
|
|
||||||
import com.google.common.truth.Truth.assertThat
|
import com.google.common.truth.Truth.assertThat
|
||||||
import java.io.File
|
import com.itsaky.androidide.utils.FileProvider
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
import org.robolectric.RobolectricTestRunner
|
import org.robolectric.RobolectricTestRunner
|
||||||
@@ -32,9 +32,12 @@ class ZipFileClasspathReaderTest {
|
|||||||
@Test
|
@Test
|
||||||
fun testListClasses() {
|
fun testListClasses() {
|
||||||
val classes =
|
val classes =
|
||||||
ZipFileClasspathReader().listClasses(
|
ZipFileClasspathReader()
|
||||||
listOf(File("../../tests/test-project/app/src/main/resources/android.jar"))
|
.listClasses(
|
||||||
)
|
listOf(
|
||||||
|
FileProvider.testProjectRoot().resolve("app/src/main/resources/android.jar").toFile()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
val context = classes.firstOrNull { it.name == "android.content.Context" }
|
val context = classes.firstOrNull { it.name == "android.content.Context" }
|
||||||
assertThat(context).isNotNull()
|
assertThat(context).isNotNull()
|
||||||
|
|||||||
@@ -63,6 +63,7 @@ dependencies {
|
|||||||
implementation(libs.tooling.gradleApi)
|
implementation(libs.tooling.gradleApi)
|
||||||
|
|
||||||
testImplementation(projects.subprojects.toolingApiTesting)
|
testImplementation(projects.subprojects.toolingApiTesting)
|
||||||
|
testImplementation(projects.shared)
|
||||||
testImplementation(libs.tests.junit)
|
testImplementation(libs.tests.junit)
|
||||||
testImplementation(libs.tests.google.truth)
|
testImplementation(libs.tests.google.truth)
|
||||||
|
|
||||||
|
|||||||
+14
-15
@@ -30,11 +30,12 @@ import com.itsaky.androidide.tooling.api.model.JavaModuleExternalDependency
|
|||||||
import com.itsaky.androidide.tooling.api.model.JavaModuleProjectDependency
|
import com.itsaky.androidide.tooling.api.model.JavaModuleProjectDependency
|
||||||
import com.itsaky.androidide.tooling.testing.ToolingApiTestLauncher
|
import com.itsaky.androidide.tooling.testing.ToolingApiTestLauncher
|
||||||
import com.itsaky.androidide.tooling.testing.ToolingApiTestLauncher.MultiVersionTestClient
|
import com.itsaky.androidide.tooling.testing.ToolingApiTestLauncher.MultiVersionTestClient
|
||||||
|
import com.itsaky.androidide.utils.FileProvider
|
||||||
|
import kotlin.io.path.deleteExisting
|
||||||
|
import kotlin.io.path.pathString
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
import org.junit.runners.JUnit4
|
import org.junit.runners.JUnit4
|
||||||
import java.io.File
|
|
||||||
import kotlin.jvm.Throws
|
|
||||||
|
|
||||||
/** @author Akash Yadav */
|
/** @author Akash Yadav */
|
||||||
@RunWith(JUnit4::class)
|
@RunWith(JUnit4::class)
|
||||||
@@ -42,8 +43,8 @@ class MultiModuleAndroidProjectTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `test simple multi module project initialization`() {
|
fun `test simple multi module project initialization`() {
|
||||||
val (server, project) = ToolingApiTestLauncher().launchServer(client = MultiVersionTestClient("7.2.0"))
|
val (server, project) = ToolingApiTestLauncher().launchServer()
|
||||||
server.initialize(InitializeProjectMessage(File("../../tests/test-project").absolutePath)).get()
|
server.initialize(InitializeProjectMessage(FileProvider.testProjectRoot().pathString)).get()
|
||||||
doAssertions(project, server)
|
doAssertions(project, server)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -148,37 +149,35 @@ class MultiModuleAndroidProjectTest {
|
|||||||
val versions = listOf("7.2.0", "7.2.1", "7.2.2", "7.3.0", "7.4.0", "8.0.0-rc01")
|
val versions = listOf("7.2.0", "7.2.1", "7.2.2", "7.3.0", "7.4.0", "8.0.0-rc01")
|
||||||
val client = MultiVersionTestClient()
|
val client = MultiVersionTestClient()
|
||||||
for (version in versions) {
|
for (version in versions) {
|
||||||
client.version = version
|
client.agpVersion = version
|
||||||
val (server, project) = ToolingApiTestLauncher().launchServer(client = client)
|
val (server, project) = ToolingApiTestLauncher().launchServer(client = client)
|
||||||
server
|
server.initialize(InitializeProjectMessage(FileProvider.testProjectRoot().pathString)).get()
|
||||||
.initialize(InitializeProjectMessage(File("../../tests/test-project").absolutePath))
|
|
||||||
.get()
|
|
||||||
doAssertions(project = project, server = server)
|
doAssertions(project = project, server = server)
|
||||||
MultiVersionTestClient.buildFile.delete()
|
FileProvider.testProjectRoot().resolve(MultiVersionTestClient.buildFile).deleteExisting()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun ciOnlyTest(test: () -> Unit) {
|
private fun ciOnlyTest(test: () -> Unit) {
|
||||||
try {
|
try {
|
||||||
assertIsCI()
|
assertIsCI()
|
||||||
test()
|
test()
|
||||||
} catch (err: CIOnlyException) {
|
} catch (err: CIOnlyException) {
|
||||||
if(shouldTestMultipleVersions()) {
|
if (shouldTestMultipleVersions()) {
|
||||||
throw err
|
throw err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun assertIsCI() {
|
private fun assertIsCI() {
|
||||||
if (!shouldTestMultipleVersions()) {
|
if (!shouldTestMultipleVersions()) {
|
||||||
throw CIOnlyException()
|
throw CIOnlyException()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun shouldTestMultipleVersions() : Boolean {
|
private fun shouldTestMultipleVersions(): Boolean {
|
||||||
return System.getenv("TEST_TOOLING_API_IMPL").let { it == "true" }
|
return System.getenv("TEST_TOOLING_API_IMPL").let { it == "true" }
|
||||||
}
|
}
|
||||||
|
|
||||||
private class CIOnlyException : IllegalStateException()
|
private class CIOnlyException : IllegalStateException()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,7 +25,8 @@ dependencies {
|
|||||||
implementation(libs.common.jkotlin)
|
implementation(libs.common.jkotlin)
|
||||||
implementation(projects.logger)
|
implementation(projects.logger)
|
||||||
implementation(projects.subprojects.toolingApi)
|
implementation(projects.subprojects.toolingApi)
|
||||||
|
implementation(projects.shared)
|
||||||
|
|
||||||
// build tooling API before tests
|
// build tooling API before tests
|
||||||
compileOnly(projects.subprojects.toolingApiImpl)
|
compileOnly(projects.subprojects.toolingApiImpl)
|
||||||
}
|
}
|
||||||
+88
-24
@@ -25,13 +25,19 @@ import com.itsaky.androidide.tooling.api.messages.result.BuildResult
|
|||||||
import com.itsaky.androidide.tooling.api.messages.result.GradleWrapperCheckResult
|
import com.itsaky.androidide.tooling.api.messages.result.GradleWrapperCheckResult
|
||||||
import com.itsaky.androidide.tooling.api.util.ToolingApiLauncher
|
import com.itsaky.androidide.tooling.api.util.ToolingApiLauncher
|
||||||
import com.itsaky.androidide.tooling.events.ProgressEvent
|
import com.itsaky.androidide.tooling.events.ProgressEvent
|
||||||
|
import com.itsaky.androidide.utils.FileProvider
|
||||||
import com.itsaky.androidide.utils.ILogger
|
import com.itsaky.androidide.utils.ILogger
|
||||||
import java.io.BufferedReader
|
import java.io.BufferedReader
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
import java.io.InputStreamReader
|
import java.io.InputStreamReader
|
||||||
|
import java.nio.file.Path
|
||||||
import java.util.Collections
|
import java.util.Collections
|
||||||
import java.util.concurrent.CompletableFuture
|
import java.util.concurrent.CompletableFuture
|
||||||
|
import kotlin.io.path.bufferedReader
|
||||||
|
import kotlin.io.path.bufferedWriter
|
||||||
|
import kotlin.io.path.deleteIfExists
|
||||||
|
import kotlin.io.path.pathString
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Launches the Tooling API server in a separate JVM process.
|
* Launches the Tooling API server in a separate JVM process.
|
||||||
@@ -46,7 +52,7 @@ class ToolingApiTestLauncher {
|
|||||||
|
|
||||||
private val opens =
|
private val opens =
|
||||||
mutableMapOf("java.base" to "java.lang", "java.base" to "java.util", "java.base" to "java.io")
|
mutableMapOf("java.base" to "java.lang", "java.base" to "java.util", "java.base" to "java.io")
|
||||||
|
|
||||||
private val exports =
|
private val exports =
|
||||||
mutableMapOf(
|
mutableMapOf(
|
||||||
"jdk.compiler" to "com.sun.tools.javac.api",
|
"jdk.compiler" to "com.sun.tools.javac.api",
|
||||||
@@ -57,10 +63,14 @@ class ToolingApiTestLauncher {
|
|||||||
)
|
)
|
||||||
|
|
||||||
fun launchServer(
|
fun launchServer(
|
||||||
client: IToolingApiClient = TestClient(),
|
client: IToolingApiClient = MultiVersionTestClient(),
|
||||||
implDir: String = "../tooling-api-impl"
|
|
||||||
): Pair<IToolingApiServer, IProject> {
|
): Pair<IToolingApiServer, IProject> {
|
||||||
val builder = ProcessBuilder(createProcessCmd("$implDir/build/libs/tooling-api-all.jar"))
|
val builder =
|
||||||
|
ProcessBuilder(
|
||||||
|
createProcessCmd(
|
||||||
|
FileProvider.implModule().resolve("build/libs/tooling-api-all.jar").pathString
|
||||||
|
)
|
||||||
|
)
|
||||||
val androidHome = findAndroidHome()
|
val androidHome = findAndroidHome()
|
||||||
println("ANDROID_HOME=$androidHome")
|
println("ANDROID_HOME=$androidHome")
|
||||||
builder.environment()["ANDROID_SDK_ROOT"] = androidHome
|
builder.environment()["ANDROID_SDK_ROOT"] = androidHome
|
||||||
@@ -86,9 +96,9 @@ class ToolingApiTestLauncher {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Collections.addAll(cmd, "-jar", jar)
|
Collections.addAll(cmd, "-jar", jar)
|
||||||
|
|
||||||
println("[ToolingApiTestLauncher] Java cmd: " + cmd.joinToString(separator = " "))
|
println("[ToolingApiTestLauncher] Java cmd: " + cmd.joinToString(separator = " "))
|
||||||
|
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,8 +122,26 @@ class ToolingApiTestLauncher {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
open class TestClient : IToolingApiClient {
|
class MultiVersionTestClient(
|
||||||
private val log = ILogger.newInstance(javaClass.simpleName)
|
private val projectDir: Path = FileProvider.testProjectRoot(),
|
||||||
|
var agpVersion: String = DEFAULT_AGP_VERSION,
|
||||||
|
var gradleVersion: String = DEFAULT_GRADLE_VERSION
|
||||||
|
) : IToolingApiClient {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val buildFile = "build.gradle"
|
||||||
|
const val buildFileIn = "$buildFile.in"
|
||||||
|
|
||||||
|
const val gradlewProps = "gradle/wrapper/gradle-wrapper.properties"
|
||||||
|
const val gradlewPropsIn = "$gradlewProps.in"
|
||||||
|
|
||||||
|
const val DEFAULT_AGP_VERSION = "7.2.0"
|
||||||
|
const val DEFAULT_GRADLE_VERSION = "7.5.1"
|
||||||
|
|
||||||
|
const val GENERATED_FILE_WARNING = "DO NOT EDIT - Automatically generated file"
|
||||||
|
|
||||||
|
private val log = ILogger.newInstance("MultiVersionTestClient")
|
||||||
|
}
|
||||||
override fun logMessage(line: LogLine) {
|
override fun logMessage(line: LogLine) {
|
||||||
log.log(line.priority, line.formattedTagAndMessage())
|
log.log(line.priority, line.formattedTagAndMessage())
|
||||||
}
|
}
|
||||||
@@ -122,7 +150,27 @@ class ToolingApiTestLauncher {
|
|||||||
log.debug(line.trim())
|
log.debug(line.trim())
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun prepareBuild() {}
|
override fun prepareBuild() {
|
||||||
|
log.debug("-----------------------------------")
|
||||||
|
log.debug("---------- PREPARE BUILD ----------")
|
||||||
|
log.debug("-----------------------------------")
|
||||||
|
|
||||||
|
projectDir
|
||||||
|
.resolve(buildFileIn)
|
||||||
|
.replaceContents(
|
||||||
|
dest = projectDir.resolve(buildFile),
|
||||||
|
candidate = "@@TOOLING_API_TEST_AGP_VERSION@@" to this.agpVersion
|
||||||
|
)
|
||||||
|
|
||||||
|
projectDir
|
||||||
|
.resolve(gradlewPropsIn)
|
||||||
|
.replaceContents(
|
||||||
|
comment = "#",
|
||||||
|
dest = projectDir.resolve(gradlewProps),
|
||||||
|
candidate = "@@GRADLE_VERSION@@" to this.gradleVersion
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
override fun onBuildSuccessful(result: BuildResult) {}
|
override fun onBuildSuccessful(result: BuildResult) {}
|
||||||
override fun onBuildFailed(result: BuildResult) {}
|
override fun onBuildFailed(result: BuildResult) {}
|
||||||
|
|
||||||
@@ -134,24 +182,40 @@ class ToolingApiTestLauncher {
|
|||||||
|
|
||||||
override fun checkGradleWrapperAvailability(): CompletableFuture<GradleWrapperCheckResult> =
|
override fun checkGradleWrapperAvailability(): CompletableFuture<GradleWrapperCheckResult> =
|
||||||
CompletableFuture.completedFuture(GradleWrapperCheckResult(true))
|
CompletableFuture.completedFuture(GradleWrapperCheckResult(true))
|
||||||
}
|
|
||||||
|
|
||||||
class MultiVersionTestClient(var version: String = "7.2.0") : TestClient() {
|
private fun Path.replaceContents(
|
||||||
|
dest: Path,
|
||||||
|
comment: String = "//",
|
||||||
|
candidate: Pair<String, String>
|
||||||
|
) = replaceContents(dest, comment, *arrayOf(candidate))
|
||||||
|
|
||||||
companion object {
|
private fun Path.replaceContents(
|
||||||
val buildTemplateFile = File("../../tests/test-project/build.gradle.in")
|
dest: Path,
|
||||||
val buildFile = File(buildTemplateFile.parentFile, "build.gradle")
|
comment: String = "//",
|
||||||
}
|
vararg candidates: Pair<String, String>
|
||||||
|
) {
|
||||||
|
val contents =
|
||||||
|
StringBuilder()
|
||||||
|
.append(comment)
|
||||||
|
.append(" ")
|
||||||
|
.append(GENERATED_FILE_WARNING)
|
||||||
|
.append(System.getProperty("line.separator").repeat(2))
|
||||||
|
|
||||||
override fun prepareBuild() {
|
bufferedReader().use { reader ->
|
||||||
super.prepareBuild()
|
reader.readText().also { text ->
|
||||||
var contents = buildTemplateFile.bufferedReader().readText()
|
var t = text
|
||||||
contents = contents.replace("@@TOOLING_API_TEST_AGP_VERSION@@", this.version)
|
for ((old, new) in candidates) {
|
||||||
contents = "/* DO NOT EDIT - Automatically generated file */\n${contents.trim()}"
|
t = t.replace(old, new)
|
||||||
val writer = buildFile.bufferedWriter()
|
}
|
||||||
writer.use {
|
contents.append(t)
|
||||||
it.write(contents)
|
}
|
||||||
it.flush()
|
}
|
||||||
|
|
||||||
|
dest.deleteIfExists()
|
||||||
|
|
||||||
|
dest.bufferedWriter().use { writer ->
|
||||||
|
writer.write(contents.toString())
|
||||||
|
writer.flush()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
build/
|
/build.gradle
|
||||||
|
build/
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
/* DO NOT EDIT - Automatically generated file */
|
// DO NOT EDIT - Automatically generated file
|
||||||
|
|
||||||
buildscript {
|
buildscript {
|
||||||
ext {
|
ext {
|
||||||
build_gradle_version = "7.2.0"
|
build_gradle_version = "7.2.0"
|
||||||
@@ -34,4 +35,4 @@ allprojects {
|
|||||||
|
|
||||||
task clean (type: Delete) {
|
task clean (type: Delete) {
|
||||||
delete rootProject.buildDir
|
delete rootProject.buildDir
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
gradle-wrapper.properties
|
||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.2-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-@@GRADLE_VERSION@@-bin.zip
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
@@ -42,6 +42,7 @@ dependencies {
|
|||||||
|
|
||||||
testImplementation(projects.subprojects.projects)
|
testImplementation(projects.subprojects.projects)
|
||||||
testImplementation(projects.subprojects.toolingApiTesting)
|
testImplementation(projects.subprojects.toolingApiTesting)
|
||||||
|
testImplementation(projects.shared)
|
||||||
testImplementation(libs.tests.junit)
|
testImplementation(libs.tests.junit)
|
||||||
testImplementation(libs.tests.google.truth)
|
testImplementation(libs.tests.google.truth)
|
||||||
testImplementation(libs.tests.robolectric)
|
testImplementation(libs.tests.robolectric)
|
||||||
|
|||||||
@@ -26,9 +26,11 @@ import com.itsaky.androidide.projects.api.AndroidModule
|
|||||||
import com.itsaky.androidide.projects.builder.BuildService
|
import com.itsaky.androidide.projects.builder.BuildService
|
||||||
import com.itsaky.androidide.tooling.api.messages.InitializeProjectMessage
|
import com.itsaky.androidide.tooling.api.messages.InitializeProjectMessage
|
||||||
import com.itsaky.androidide.tooling.testing.ToolingApiTestLauncher
|
import com.itsaky.androidide.tooling.testing.ToolingApiTestLauncher
|
||||||
|
import com.itsaky.androidide.utils.FileProvider
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import org.junit.Ignore
|
import org.junit.Ignore
|
||||||
import org.robolectric.Robolectric
|
import org.robolectric.Robolectric
|
||||||
|
import kotlin.io.path.pathString
|
||||||
|
|
||||||
@Ignore("Test utility provider")
|
@Ignore("Test utility provider")
|
||||||
object XmlInflaterTest {
|
object XmlInflaterTest {
|
||||||
@@ -42,8 +44,8 @@ object XmlInflaterTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val (server, project) =
|
val (server, project) =
|
||||||
ToolingApiTestLauncher().launchServer(implDir = "../subprojects/tooling-api-impl")
|
ToolingApiTestLauncher().launchServer()
|
||||||
server.initialize(InitializeProjectMessage(File("../tests/test-project").absolutePath)).get()
|
server.initialize(InitializeProjectMessage(FileProvider.testProjectRoot().pathString)).get()
|
||||||
|
|
||||||
Lookup.DEFAULT.register(BuildService.KEY_PROJECT_PROXY, project)
|
Lookup.DEFAULT.register(BuildService.KEY_PROJECT_PROXY, project)
|
||||||
ProjectManager.setupProject()
|
ProjectManager.setupProject()
|
||||||
|
|||||||
Reference in New Issue
Block a user