[TestFramework] new: added source roots assertions

GitOrigin-RevId: 503322a89965375e496ed2ade7c8641f7cc4499b
This commit is contained in:
Sergei Vorobyov
2024-07-12 18:48:48 +02:00
committed by intellij-monorepo-bot
parent dfb09586ae
commit 323f3a0015
5 changed files with 442 additions and 6 deletions

View File

@@ -0,0 +1,67 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.platform.externalSystem.testFramework.utils.module
import com.intellij.java.workspace.entities.javaResourceRoots
import com.intellij.java.workspace.entities.javaSourceRoots
import com.intellij.openapi.externalSystem.model.project.ExternalSystemSourceType
import com.intellij.platform.workspace.jps.entities.SourceRootEntity
import com.intellij.workspaceModel.ide.legacyBridge.impl.java.JAVA_RESOURCE_ROOT_ENTITY_TYPE_ID
import com.intellij.workspaceModel.ide.legacyBridge.impl.java.JAVA_SOURCE_ROOT_ENTITY_TYPE_ID
import com.intellij.workspaceModel.ide.legacyBridge.impl.java.JAVA_TEST_RESOURCE_ROOT_ENTITY_TYPE_ID
import com.intellij.workspaceModel.ide.legacyBridge.impl.java.JAVA_TEST_ROOT_ENTITY_TYPE_ID
import java.util.function.BiConsumer
import java.util.function.Consumer
class ExternalSystemSourceRootAssertion<T> private constructor(
private val assertSourceRoot: (ExternalSystemSourceType, List<T>) -> Unit,
) {
private val checkedRoots = HashSet<ExternalSystemSourceType>()
fun sourceRoots(type: ExternalSystemSourceType, vararg expectedRoots: T): ExternalSystemSourceRootAssertion<T> {
require(checkedRoots.add(type)) {
"The source root of type $type is already checked"
}
assertSourceRoot(type, expectedRoots.toList())
return this
}
companion object {
@JvmStatic
fun <T> assertSourceRoots(
applyAssertion: Consumer<ExternalSystemSourceRootAssertion<T>>,
assertSourceRoots: BiConsumer<ExternalSystemSourceType, List<T>>,
) {
val assertion = ExternalSystemSourceRootAssertion(assertSourceRoots::accept)
applyAssertion.accept(assertion)
for (type in ExternalSystemSourceType.entries) {
if (type !in assertion.checkedRoots) {
assertSourceRoots.accept(type, emptyList())
}
}
}
@JvmStatic
val SourceRootEntity.exType: ExternalSystemSourceType
get() = when (rootTypeId) {
JAVA_SOURCE_ROOT_ENTITY_TYPE_ID -> when (javaSourceRoots.any { it.generated }) {
true -> ExternalSystemSourceType.SOURCE_GENERATED
else -> ExternalSystemSourceType.SOURCE
}
JAVA_TEST_ROOT_ENTITY_TYPE_ID -> when (javaSourceRoots.any { it.generated }) {
true -> ExternalSystemSourceType.TEST_GENERATED
else -> ExternalSystemSourceType.TEST
}
JAVA_RESOURCE_ROOT_ENTITY_TYPE_ID -> when (javaResourceRoots.any { it.generated }) {
true -> ExternalSystemSourceType.RESOURCE_GENERATED
else -> ExternalSystemSourceType.RESOURCE
}
JAVA_TEST_RESOURCE_ROOT_ENTITY_TYPE_ID -> when (javaResourceRoots.any { it.generated }) {
true -> ExternalSystemSourceType.TEST_RESOURCE_GENERATED
else -> ExternalSystemSourceType.TEST_RESOURCE
}
else -> throw NoWhenBranchMatchedException("Unexpected source type: $this")
}
}
}

View File

@@ -0,0 +1,135 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
@file:JvmName("ExternalSystemSourceRootAssertions")
package com.intellij.platform.externalSystem.testFramework.utils.module
import com.intellij.java.workspace.entities.javaResourceRoots
import com.intellij.java.workspace.entities.javaSourceRoots
import com.intellij.openapi.externalSystem.model.project.ExternalSystemSourceType
import com.intellij.openapi.module.Module
import com.intellij.openapi.project.Project
import com.intellij.platform.workspace.jps.entities.ModuleEntity
import com.intellij.platform.workspace.jps.entities.SourceRootEntity
import com.intellij.platform.workspace.storage.EntityStorage
import com.intellij.platform.workspace.storage.url.VirtualFileUrl
import com.intellij.platform.workspace.storage.url.VirtualFileUrlManager
import com.intellij.testFramework.utils.module.assertSourceRoots
import com.intellij.workspaceModel.ide.legacyBridge.impl.java.JAVA_RESOURCE_ROOT_ENTITY_TYPE_ID
import com.intellij.workspaceModel.ide.legacyBridge.impl.java.JAVA_SOURCE_ROOT_ENTITY_TYPE_ID
import com.intellij.workspaceModel.ide.legacyBridge.impl.java.JAVA_TEST_RESOURCE_ROOT_ENTITY_TYPE_ID
import com.intellij.workspaceModel.ide.legacyBridge.impl.java.JAVA_TEST_ROOT_ENTITY_TYPE_ID
import java.nio.file.Path
fun assertNoSourceRoots(
module: Module,
) {
assertSourceRoots(module) {}
}
fun assertSourceRoots(
module: Module,
configure: ExternalSystemSourceRootAssertion<Path>.() -> Unit,
) {
ExternalSystemSourceRootAssertion.assertSourceRoots(configure) { type, expectedRoots ->
assertSourceRoots(module, { it.exType == type }, expectedRoots) {
"${module.name} source root of type $type"
}
}
}
fun assertNoSourceRoots(
project: Project,
moduleName: String,
) {
assertSourceRoots(project, moduleName) {}
}
fun assertSourceRoots(
project: Project,
moduleName: String,
configure: ExternalSystemSourceRootAssertion<Path>.() -> Unit,
) {
ExternalSystemSourceRootAssertion.assertSourceRoots(configure) { type, expectedRoots ->
assertSourceRoots(project, moduleName, { it.exType == type }, expectedRoots) {
"$moduleName source root of type $type"
}
}
}
fun assertNoSourceRoots(
virtualFileUrlManager: VirtualFileUrlManager,
storage: EntityStorage,
moduleName: String,
) {
assertSourceRoots(virtualFileUrlManager, storage, moduleName) {}
}
fun assertSourceRoots(
virtualFileUrlManager: VirtualFileUrlManager,
storage: EntityStorage,
moduleName: String,
configure: ExternalSystemSourceRootAssertion<Path>.() -> Unit,
) {
ExternalSystemSourceRootAssertion.assertSourceRoots(configure) { type, expectedRoots ->
assertSourceRoots(virtualFileUrlManager, storage, moduleName, { it.exType == type }, expectedRoots) {
"$moduleName source root of type $type"
}
}
}
fun assertNoSourceRoots(
virtualFileUrlManager: VirtualFileUrlManager,
moduleEntity: ModuleEntity,
) {
assertSourceRoots(virtualFileUrlManager, moduleEntity) {}
}
fun assertSourceRoots(
virtualFileUrlManager: VirtualFileUrlManager,
moduleEntity: ModuleEntity,
configure: ExternalSystemSourceRootAssertion<Path>.() -> Unit,
) {
ExternalSystemSourceRootAssertion.assertSourceRoots(configure) { type, expectedRoots ->
assertSourceRoots(virtualFileUrlManager, moduleEntity, { it.exType == type }, expectedRoots) {
"${moduleEntity.name} source root of type $type"
}
}
}
fun assertNoSourceRoots(
moduleEntity: ModuleEntity,
) {
assertSourceRoots(moduleEntity) {}
}
fun assertSourceRoots(
moduleEntity: ModuleEntity,
configure: ExternalSystemSourceRootAssertion<VirtualFileUrl>.() -> Unit,
) {
ExternalSystemSourceRootAssertion.assertSourceRoots(configure) { type, expectedRoots ->
assertSourceRoots(moduleEntity, { it.exType == type }, expectedRoots) {
"${moduleEntity.name} source root of type $type"
}
}
}
val SourceRootEntity.exType: ExternalSystemSourceType
get() = when (rootTypeId) {
JAVA_SOURCE_ROOT_ENTITY_TYPE_ID -> when (javaSourceRoots.any { it.generated }) {
true -> ExternalSystemSourceType.SOURCE_GENERATED
else -> ExternalSystemSourceType.SOURCE
}
JAVA_TEST_ROOT_ENTITY_TYPE_ID -> when (javaSourceRoots.any { it.generated }) {
true -> ExternalSystemSourceType.TEST_GENERATED
else -> ExternalSystemSourceType.TEST
}
JAVA_RESOURCE_ROOT_ENTITY_TYPE_ID -> when (javaResourceRoots.any { it.generated }) {
true -> ExternalSystemSourceType.RESOURCE_GENERATED
else -> ExternalSystemSourceType.RESOURCE
}
JAVA_TEST_RESOURCE_ROOT_ENTITY_TYPE_ID -> when (javaResourceRoots.any { it.generated }) {
true -> ExternalSystemSourceType.TEST_RESOURCE_GENERATED
else -> ExternalSystemSourceType.TEST_RESOURCE
}
else -> throw NoWhenBranchMatchedException("Unexpected source type: $this")
}

View File

@@ -0,0 +1,133 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
@file:JvmName("SourceRootAssertions")
package com.intellij.testFramework.utils.module
import com.intellij.openapi.module.Module
import com.intellij.openapi.project.Project
import com.intellij.platform.backend.workspace.workspaceModel
import com.intellij.platform.workspace.jps.entities.ModuleEntity
import com.intellij.platform.workspace.jps.entities.ModuleId
import com.intellij.platform.workspace.jps.entities.SourceRootEntity
import com.intellij.platform.workspace.storage.EntityStorage
import com.intellij.platform.workspace.storage.impl.url.toVirtualFileUrl
import com.intellij.platform.workspace.storage.url.VirtualFileUrl
import com.intellij.platform.workspace.storage.url.VirtualFileUrlManager
import org.junit.jupiter.api.Assertions
import java.nio.file.Path
import java.util.ArrayList
fun assertSourceRoots(
module: Module,
filter: (SourceRootEntity) -> Boolean,
vararg expectedRoots: Path,
messageSupplier: (() -> String)? = null,
) {
assertSourceRoots(module, filter, expectedRoots.asList(), messageSupplier)
}
fun assertSourceRoots(
module: Module,
filter: (SourceRootEntity) -> Boolean,
expectedRoots: List<Path>,
messageSupplier: (() -> String)? = null,
) {
assertSourceRoots(module.project, module.name, filter, expectedRoots, messageSupplier)
}
fun assertSourceRoots(
project: Project,
moduleName: String,
filter: (SourceRootEntity) -> Boolean,
vararg expectedRoots: Path,
messageSupplier: (() -> String)? = null,
) {
assertSourceRoots(project, moduleName, filter, expectedRoots.asList(), messageSupplier)
}
fun assertSourceRoots(
project: Project,
moduleName: String,
filter: (SourceRootEntity) -> Boolean,
expectedRoots: List<Path>,
messageSupplier: (() -> String)? = null,
) {
val workspaceModel = project.workspaceModel
val storage = workspaceModel.currentSnapshot
val virtualFileUrlManager = workspaceModel.getVirtualFileUrlManager()
assertSourceRoots(virtualFileUrlManager, storage, moduleName, filter, expectedRoots, messageSupplier)
}
fun assertSourceRoots(
virtualFileUrlManager: VirtualFileUrlManager,
storage: EntityStorage,
moduleName: String,
filter: (SourceRootEntity) -> Boolean,
vararg expectedRoots: Path,
messageSupplier: (() -> String)? = null,
) {
assertSourceRoots(virtualFileUrlManager, storage, moduleName, filter, expectedRoots.asList(), messageSupplier)
}
fun assertSourceRoots(
virtualFileUrlManager: VirtualFileUrlManager,
storage: EntityStorage,
moduleName: String,
filter: (SourceRootEntity) -> Boolean,
expectedRoots: List<Path>,
messageSupplier: (() -> String)? = null,
) {
val moduleId = ModuleId(moduleName)
val moduleEntity = storage.resolve(moduleId)
Assertions.assertNotNull(moduleEntity) {
"The module '$moduleName' doesn't exist"
}
assertSourceRoots(virtualFileUrlManager, moduleEntity!!, filter, expectedRoots, messageSupplier)
}
fun assertSourceRoots(
virtualFileUrlManager: VirtualFileUrlManager,
moduleEntity: ModuleEntity,
filter: (SourceRootEntity) -> Boolean,
vararg expectedRoots: Path,
messageSupplier: (() -> String)? = null,
) {
assertSourceRoots(virtualFileUrlManager, moduleEntity, filter, expectedRoots.asList(), messageSupplier)
}
fun assertSourceRoots(
virtualFileUrlManager: VirtualFileUrlManager,
moduleEntity: ModuleEntity,
filter: (SourceRootEntity) -> Boolean,
expectedRoots: List<Path>,
messageSupplier: (() -> String)? = null,
) {
val expectedRootUrls = expectedRoots.map { it.normalize().toVirtualFileUrl(virtualFileUrlManager) }
assertSourceRoots(moduleEntity, filter, expectedRootUrls, messageSupplier)
}
fun assertSourceRoots(
moduleEntity: ModuleEntity,
filter: (SourceRootEntity) -> Boolean,
vararg expectedRoots: VirtualFileUrl,
messageSupplier: (() -> String)? = null,
) {
assertSourceRoots(moduleEntity, filter, expectedRoots.asList(), messageSupplier)
}
fun assertSourceRoots(
moduleEntity: ModuleEntity,
filter: (SourceRootEntity) -> Boolean,
expectedRoots: List<VirtualFileUrl>,
messageSupplier: (() -> String)? = null,
) {
val actualRoots = ArrayList<VirtualFileUrl>()
for (contentRoot in moduleEntity.contentRoots) {
for (sourceRoot in contentRoot.sourceRoots) {
if (filter(sourceRoot)) {
actualRoots.add(sourceRoot.url)
}
}
}
assertEqualsUnordered(actualRoots, expectedRoots, messageSupplier)
}

View File

@@ -7,6 +7,8 @@ import com.intellij.openapi.project.ex.ProjectManagerEx
import com.intellij.platform.backend.workspace.workspaceModel
import com.intellij.platform.workspace.jps.entities.ContentRootEntity
import com.intellij.platform.workspace.jps.entities.ModuleEntity
import com.intellij.platform.workspace.jps.entities.SourceRootEntity
import com.intellij.platform.workspace.jps.entities.SourceRootTypeId
import com.intellij.platform.workspace.storage.MutableEntityStorage
import com.intellij.platform.workspace.storage.impl.url.toVirtualFileUrl
import com.intellij.platform.workspace.storage.url.VirtualFileUrlManager
@@ -36,8 +38,8 @@ abstract class ModuleAssertionTestCase {
project.withProjectAsync {
val virtualFileUrlManager = project.workspaceModel.getVirtualFileUrlManager()
project.workspaceModel.update("test project initialisation") { storage ->
val projectConfigurator = ProjectConfigurator(storage, virtualFileUrlManager, projectRoot)
projectConfigurator.configure()
ProjectConfigurator(storage, virtualFileUrlManager, projectRoot)
.configure()
}
}
return project
@@ -49,12 +51,57 @@ abstract class ModuleAssertionTestCase {
private val projectRoot: Path
) {
fun addModuleEntity(moduleName: String, relativePath: String) {
fun addModuleEntity(moduleName: String, relativePath: String, configure: ContentRootConfigurator.() -> Unit = {}) {
addModuleEntity(moduleName) {
addContentRoot(relativePath, configure)
}
}
fun addModuleEntity(moduleName: String, configure: ModuleConfigurator.() -> Unit = {}) {
val moduleEntity = ModuleEntity(moduleName, emptyList(), NonPersistentEntitySource)
storage addEntity moduleEntity
ModuleConfigurator(storage, virtualFileUrlManager, projectRoot, moduleEntity)
.configure()
}
}
class ModuleConfigurator(
private val storage: MutableEntityStorage,
private val virtualFileUrlManager: VirtualFileUrlManager,
private val projectRoot: Path,
private val moduleEntity: ModuleEntity.Builder,
) {
fun addContentRoot(relativePath: String, configure: ContentRootConfigurator.() -> Unit = {}) {
val contentRootPath = projectRoot.resolve(relativePath).normalize()
val contentRoot = contentRootPath.toVirtualFileUrl(virtualFileUrlManager)
storage addEntity (ContentRootEntity(contentRoot, emptyList(), NonPersistentEntitySource) {
module = ModuleEntity(moduleName, emptyList(), NonPersistentEntitySource)
})
val contentRootEntity = ContentRootEntity(contentRoot, emptyList(), NonPersistentEntitySource) {
module = moduleEntity
}
storage addEntity contentRootEntity
ContentRootConfigurator(storage, virtualFileUrlManager, projectRoot, contentRootEntity)
.configure()
}
}
class ContentRootConfigurator(
private val storage: MutableEntityStorage,
private val virtualFileUrlManager: VirtualFileUrlManager,
private val projectRoot: Path,
private val contentRootEntity: ContentRootEntity.Builder,
) {
fun addSourceRoot(typeId: SourceRootTypeId, relativePath: String) {
val sourceRootPath = projectRoot.resolve(relativePath).normalize()
val sourceRoot = sourceRootPath.toVirtualFileUrl(virtualFileUrlManager)
val sourceRootEntity = SourceRootEntity(sourceRoot, typeId, NonPersistentEntitySource) {
contentRoot = contentRootEntity
}
storage addEntity sourceRootEntity
}
}
}

View File

@@ -0,0 +1,54 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.testFramework.utils.module
import com.intellij.platform.workspace.jps.entities.SourceRootTypeId
import com.intellij.testFramework.useProjectAsync
import com.intellij.testFramework.utils.io.createDirectory
import kotlinx.coroutines.runBlocking
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test
class SourceRootAssertionTest : ModuleAssertionTestCase() {
@Test
fun `test SourceRootAssertions#assertModules`() {
runBlocking {
val type1 = SourceRootTypeId("type1")
val type2 = SourceRootTypeId("type2")
val projectRoot = testDirectory.createDirectory("project")
generateProject(projectRoot) {
addModuleEntity("project", ".") {
addSourceRoot(type1, "source1-1")
addSourceRoot(type1, "source1-2")
addSourceRoot(type2, "source2-1")
addSourceRoot(type2, "source2-2")
}
addModuleEntity("project.module1", "module1") {
addSourceRoot(type1, "module1/source1")
}
addModuleEntity("project.module2", "module2") {
addSourceRoot(type2, "module2/source2")
}
}.useProjectAsync { project ->
assertSourceRoots(project, "project", { it.rootTypeId == type1 }, projectRoot.resolve("source1-1"), projectRoot.resolve("source1-2"))
assertSourceRoots(project, "project", { it.rootTypeId == type2 }, projectRoot.resolve("source2-1"), projectRoot.resolve("source2-2"))
assertSourceRoots(project, "project.module1", { it.rootTypeId == type1 }, projectRoot.resolve("module1/source1"))
assertSourceRoots(project, "project.module1", { it.rootTypeId == type2 })
assertSourceRoots(project, "project.module2", { it.rootTypeId == type1 })
assertSourceRoots(project, "project.module2", { it.rootTypeId == type2 }, projectRoot.resolve("module2/source2"))
Assertions.assertThrows(AssertionError::class.java) {
assertSourceRoots(project, "module1", { it.rootTypeId == type1 }, projectRoot.resolve("module1/source1"))
}
Assertions.assertThrows(AssertionError::class.java) {
assertSourceRoots(project, "project", { it.rootTypeId == type1 }, projectRoot.resolve("other-root"))
}
Assertions.assertThrows(AssertionError::class.java) {
assertSourceRoots(project, "other-module", { it.rootTypeId == type1 }, projectRoot.resolve("other-module"))
}
}
}
}
}