From 87e468e9942f1a65b4e42a841dc2c18cdc508199 Mon Sep 17 00:00:00 2001 From: "Ilya.Kazakevich" Date: Mon, 1 Jul 2024 18:00:58 +0200 Subject: [PATCH] Rewrite "resource"-based JUnit5 tests into "fixture" based. See `com.intellij.testFramework.junit5.showcase.resources` and use it as examples to create JUnit5-based tests GitOrigin-RevId: 92c2831205d7bad28b1500f9fa510b93fed52e19 --- .../JUnit5ClassLevelFieldResource.kt | 32 ----- .../disposable/JUnit5ClassLevelResource.kt | 63 ---------- .../JUnit5ClassLevelResourceAnnotation.kt | 27 ----- .../disposable/JUnit5MethodLevelResource.kt | 59 ---------- .../resources/full/JUnit5Automatic.kt | 51 -------- .../showcase/resources/full/JUnit5Manually.kt | 111 ------------------ .../resources/full/JUnit5SemiAutomatic.kt | 39 ------ .../module/JUnit5ClassLevelModule.kt | 64 ++-------- .../module/JUnit5MethodLevelModule.kt | 21 ++-- ...nceField.kt => JUnit5ClassLeveLProject.kt} | 13 +- .../project/JUnit5ClassLevelProject.kt | 91 -------------- .../JUnit5ClassLevelProjectAnnotation.kt | 22 ---- .../project/JUnit5ProjectClassField.kt | 26 ---- .../project/JUnit5TestLevelProject.kt | 73 ++++++++++++ 14 files changed, 96 insertions(+), 596 deletions(-) delete mode 100644 platform/testFramework/junit5/test/showcase/resources/disposable/JUnit5ClassLevelFieldResource.kt delete mode 100644 platform/testFramework/junit5/test/showcase/resources/disposable/JUnit5ClassLevelResource.kt delete mode 100644 platform/testFramework/junit5/test/showcase/resources/disposable/JUnit5ClassLevelResourceAnnotation.kt delete mode 100644 platform/testFramework/junit5/test/showcase/resources/disposable/JUnit5MethodLevelResource.kt delete mode 100644 platform/testFramework/junit5/test/showcase/resources/full/JUnit5Automatic.kt delete mode 100644 platform/testFramework/junit5/test/showcase/resources/full/JUnit5Manually.kt delete mode 100644 platform/testFramework/junit5/test/showcase/resources/full/JUnit5SemiAutomatic.kt rename platform/testFramework/junit5/test/showcase/resources/project/{JUnit5ProjectInstanceField.kt => JUnit5ClassLeveLProject.kt} (64%) delete mode 100644 platform/testFramework/junit5/test/showcase/resources/project/JUnit5ClassLevelProject.kt delete mode 100644 platform/testFramework/junit5/test/showcase/resources/project/JUnit5ClassLevelProjectAnnotation.kt delete mode 100644 platform/testFramework/junit5/test/showcase/resources/project/JUnit5ProjectClassField.kt create mode 100644 platform/testFramework/junit5/test/showcase/resources/project/JUnit5TestLevelProject.kt diff --git a/platform/testFramework/junit5/test/showcase/resources/disposable/JUnit5ClassLevelFieldResource.kt b/platform/testFramework/junit5/test/showcase/resources/disposable/JUnit5ClassLevelFieldResource.kt deleted file mode 100644 index a6e058025257..000000000000 --- a/platform/testFramework/junit5/test/showcase/resources/disposable/JUnit5ClassLevelFieldResource.kt +++ /dev/null @@ -1,32 +0,0 @@ -// 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.junit5.showcase.resources.disposable - -import com.intellij.openapi.Disposable -import com.intellij.openapi.util.Disposer -import com.intellij.testFramework.junit5.TestApplication -import com.intellij.testFramework.junit5.resources.DisposableResource -import com.intellij.testFramework.junit5.showcase.resources.disposable.JUnit5ClassLevelFieldResource.Companion.disposable1 -import org.junit.jupiter.api.Assertions.assertEquals -import org.junit.jupiter.api.Assertions.assertNotNull -import org.junit.jupiter.api.Test - -/** - * Class-level [Disposable] injected both into [disposable1] and arguments - */ -@TestApplication -@DisposableResource -class JUnit5ClassLevelFieldResource { - companion object { - @JvmStatic - private lateinit var disposable1: Disposable - } - - @Test - fun test(disposable2: Disposable) { - assertNotNull(disposable1) - assertNotNull(disposable2) - assertEquals(disposable1, disposable1) - Disposer.register(disposable1, Disposer.newCheckedDisposable()) - Disposer.register(disposable2, Disposer.newCheckedDisposable()) - } -} \ No newline at end of file diff --git a/platform/testFramework/junit5/test/showcase/resources/disposable/JUnit5ClassLevelResource.kt b/platform/testFramework/junit5/test/showcase/resources/disposable/JUnit5ClassLevelResource.kt deleted file mode 100644 index 17c42f3a0b4a..000000000000 --- a/platform/testFramework/junit5/test/showcase/resources/disposable/JUnit5ClassLevelResource.kt +++ /dev/null @@ -1,63 +0,0 @@ -// 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.junit5.showcase.resources.disposable - -import com.intellij.openapi.Disposable -import com.intellij.openapi.util.Disposer -import com.intellij.testFramework.junit5.resources.ResourceExtensionApi -import com.intellij.testFramework.junit5.resources.asExtension -import com.intellij.testFramework.junit5.resources.create -import com.intellij.testFramework.junit5.resources.providers.DisposableProvider -import com.intellij.testFramework.junit5.showcase.resources.ResourceCounter -import com.intellij.testFramework.junit5.showcase.resources.disposable.JUnit5ClassLevelResource.Companion.checkLeaks -import kotlinx.coroutines.runBlocking -import org.junit.jupiter.api.Assertions.assertEquals -import org.junit.jupiter.api.Assertions.assertNotEquals -import org.junit.jupiter.api.Order -import org.junit.jupiter.api.Test -import org.junit.jupiter.api.extension.AfterAllCallback -import org.junit.jupiter.api.extension.RegisterExtension - -/** - * Class level [Disposable] created programmatically. - * [checkLeaks] will be created before and destroyed ([AfterAllCallback]) after - */ -class JUnit5ClassLevelResource { - - companion object { - @JvmStatic - @RegisterExtension - @Order(0) - val checkLeaks = AfterAllCallback { - resourceCounter.ensureEmpty() - } - - @JvmStatic - @RegisterExtension - @Order(1) - val ext = DisposableProvider().asExtension() - - private val resourceCounter = ResourceCounter() - } - - - @Test - fun test(disposable1: Disposable, disposable2: Disposable) { - assertEquals(disposable1, disposable2, "Class level must use same resource") - resourceCounter.acquire(disposable1) - resourceCounter.ensureNotEmpty() - } - - @Test - fun testManualDestroy(): Unit = runBlocking { - val disposable = ext.create(disposeOnExit = false) - Disposer.dispose(disposable) - } - - @Test - fun testManualResource(): Unit = runBlocking { - resourceCounter.acquire(ext.create()) - - // Manually created resources are different - assertNotEquals(ext.create(), ext.create()) - } -} \ No newline at end of file diff --git a/platform/testFramework/junit5/test/showcase/resources/disposable/JUnit5ClassLevelResourceAnnotation.kt b/platform/testFramework/junit5/test/showcase/resources/disposable/JUnit5ClassLevelResourceAnnotation.kt deleted file mode 100644 index ff3d1a482299..000000000000 --- a/platform/testFramework/junit5/test/showcase/resources/disposable/JUnit5ClassLevelResourceAnnotation.kt +++ /dev/null @@ -1,27 +0,0 @@ -// 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.junit5.showcase.resources.disposable - -import com.intellij.openapi.Disposable -import com.intellij.openapi.diagnostic.thisLogger -import com.intellij.openapi.util.Disposer -import com.intellij.testFramework.junit5.TestApplication -import com.intellij.testFramework.junit5.resources.DisposableResource -import org.junit.jupiter.api.Assertions.assertEquals -import org.junit.jupiter.api.Test - -/** - * Class level disposable in automatic manner - */ -@TestApplication -@DisposableResource -class JUnit5ClassLevelResourceAnnotation { - - @Test - fun test(disposable1: Disposable, disposable2: Disposable) { - assertEquals(disposable1, disposable2, "Class level must use same resource") - Disposer.register(disposable1, Disposable { - thisLogger().info("It must be disposed. Otherwise, leak would be reported") - }) - } - -} \ No newline at end of file diff --git a/platform/testFramework/junit5/test/showcase/resources/disposable/JUnit5MethodLevelResource.kt b/platform/testFramework/junit5/test/showcase/resources/disposable/JUnit5MethodLevelResource.kt deleted file mode 100644 index 8068ace1403a..000000000000 --- a/platform/testFramework/junit5/test/showcase/resources/disposable/JUnit5MethodLevelResource.kt +++ /dev/null @@ -1,59 +0,0 @@ -// 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.junit5.showcase.resources.disposable - -import com.intellij.openapi.Disposable -import com.intellij.testFramework.junit5.TestApplication -import com.intellij.testFramework.junit5.resources.ResourceExtensionApi -import com.intellij.testFramework.junit5.resources.asExtension -import com.intellij.testFramework.junit5.resources.create -import com.intellij.testFramework.junit5.resources.providers.DisposableProvider -import com.intellij.testFramework.junit5.showcase.resources.ResourceCounter -import kotlinx.coroutines.runBlocking -import org.junit.jupiter.api.Assertions.assertEquals -import org.junit.jupiter.api.Order -import org.junit.jupiter.api.Test -import org.junit.jupiter.api.extension.AfterEachCallback -import org.junit.jupiter.api.extension.RegisterExtension - -/** - * [Disposable] created on method level and disposed after each test. - * [checkLeaks] proofs it - */ -@TestApplication -class JUnit5MethodLevelResource { - @JvmField - @RegisterExtension - @Order(0) - val checkLeaks = AfterEachCallback { - resourceCounter.ensureEmpty() - } - - @JvmField - @RegisterExtension - @Order(1) - val ext = DisposableProvider().asExtension() - - - private val resourceCounter = ResourceCounter() - - private lateinit var disposableField: Disposable - - - @Test - fun test(disposable1: Disposable, disposable2: Disposable) { - assertEquals(disposable1, disposable2, "Instance level must use same resource") - assertEquals(disposable1, disposableField, "Instance level must use same resource") - resourceCounter.acquire(disposable1) - runBlocking { - resourceCounter.acquire(ext.create()) - } - resourceCounter.ensureNotEmpty() - } - - @Test - fun test2(disposable: Disposable) { - resourceCounter.ensureEmpty() // Method-level resource should already be destroyed - resourceCounter.acquire(disposable) - resourceCounter.acquire(disposableField) - } -} \ No newline at end of file diff --git a/platform/testFramework/junit5/test/showcase/resources/full/JUnit5Automatic.kt b/platform/testFramework/junit5/test/showcase/resources/full/JUnit5Automatic.kt deleted file mode 100644 index 8735390c9eb5..000000000000 --- a/platform/testFramework/junit5/test/showcase/resources/full/JUnit5Automatic.kt +++ /dev/null @@ -1,51 +0,0 @@ -// 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.junit5.showcase.resources.full - -import com.intellij.openapi.application.writeAction -import com.intellij.openapi.components.Service -import com.intellij.openapi.components.service -import com.intellij.openapi.fileEditor.FileEditorManager -import com.intellij.openapi.module.Module -import com.intellij.openapi.project.Project -import com.intellij.openapi.vfs.LocalFileSystem -import com.intellij.openapi.vfs.findOrCreateFile -import com.intellij.openapi.vfs.writeText -import com.intellij.psi.PsiManager -import com.intellij.testFramework.junit5.resources.FullApplication -import kotlinx.coroutines.runBlocking -import org.junit.jupiter.api.Assertions -import org.junit.jupiter.api.Assertions.assertEquals -import org.junit.jupiter.api.Assertions.assertFalse -import org.junit.jupiter.api.Test -import org.junit.jupiter.api.io.TempDir -import java.nio.file.Path - -@Service(Service.Level.PROJECT) -private class MyService(val project: Project) - -/** - * Test that gets all resources in a fully automated manner, thanks to [FullApplication] - */ -@FullApplication -class JUnit5Automatic { - - @Test - /** - * [tempDir] is a JUnit5 temporary directory here - */ - fun funProjectModuleEditor(module: Module, project: Project, @TempDir tempDir: Path): Unit = runBlocking { - assertEquals(module.project, project.service().project) - writeAction { - val file = LocalFileSystem.getInstance().findFileByNioFile(tempDir)!! - .findOrCreateFile("file.txt") - .apply { writeText("hello") } - FileEditorManager.getInstance(project).openFile(file).first() - Assertions.assertNotNull(PsiManager.getInstance(project).findFile(file)?.fileDocument) - } - } - - @Test - fun funModule(module: Module) { - assertFalse(module.isDisposed) - } -} \ No newline at end of file diff --git a/platform/testFramework/junit5/test/showcase/resources/full/JUnit5Manually.kt b/platform/testFramework/junit5/test/showcase/resources/full/JUnit5Manually.kt deleted file mode 100644 index fce2a01d83e5..000000000000 --- a/platform/testFramework/junit5/test/showcase/resources/full/JUnit5Manually.kt +++ /dev/null @@ -1,111 +0,0 @@ -// 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.junit5.showcase.resources.full - -import com.intellij.openapi.module.Module -import com.intellij.openapi.project.Project -import com.intellij.openapi.project.guessProjectDir -import com.intellij.testFramework.junit5.TestApplication -import com.intellij.testFramework.junit5.resources.asExtension -import com.intellij.testFramework.junit5.resources.create -import com.intellij.testFramework.junit5.resources.providers.PathInfo -import com.intellij.testFramework.junit5.resources.providers.ProjectProvider -import com.intellij.testFramework.junit5.resources.providers.module.ModuleName -import com.intellij.testFramework.junit5.resources.providers.module.ModuleParams -import com.intellij.testFramework.junit5.resources.providers.module.ModulePersistenceType.Persistent -import com.intellij.testFramework.junit5.resources.providers.module.ModuleProvider -import com.intellij.testFramework.junit5.resources.providers.module.ProjectSource.ExplicitProject -import com.intellij.testFramework.junit5.resources.providers.module.ProjectSource.ProjectFromExtension -import kotlinx.coroutines.runBlocking -import org.junit.jupiter.api.AfterEach -import org.junit.jupiter.api.Assertions.* -import org.junit.jupiter.api.Order -import org.junit.jupiter.api.Test -import org.junit.jupiter.api.extension.AfterEachCallback -import org.junit.jupiter.api.extension.RegisterExtension -import org.junit.jupiter.api.io.TempDir -import java.nio.file.Files -import java.nio.file.Path -import kotlin.io.path.name -import kotlin.io.path.pathString - -/** - * Everything created manually here for fine-tuning freaks. - * [allModulesClearListener] checks that modules do not leak - */ -@TestApplication -class JUnit5Manually { - - @JvmField - @Order(0) - @RegisterExtension - val allModulesClearListener = AfterEachCallback { - assertTrue(modules.all { it.isDisposed }) - assertTrue(modules.all { it.project.isDisposed }) - } - private val projectName = "myProject${hashCode()}" - private val explicitProjectPath = Files.createTempDirectory(projectName) - private val explicitModulePath = Files.createTempDirectory(projectName) - - @JvmField - @RegisterExtension - @Order(1) - val projectExt = ProjectProvider { PathInfo(explicitProjectPath) }.asExtension() - - - @JvmField - @RegisterExtension - @Order(2) - val moduleExt = ModuleProvider { - ModuleParams( - name = ModuleName("${Math.random()}MyModule${Math.random()}"), - modulePersistenceType = Persistent { _, name -> - PathInfo(explicitModulePath.resolve(name.name), deletePathOnExit = true, closeFsOnExit = false) - }, - projectSource = ProjectFromExtension - ) - }.asExtension() - - private val modules = mutableListOf() - - @AfterEach - fun deletePath() { - Files.deleteIfExists(explicitProjectPath) - Files.deleteIfExists(explicitModulePath) - } - - @Test - fun ensureModuleObeyParams(module: Module) { - assertTrue(module.moduleNioFile.pathString.startsWith(explicitModulePath.pathString)) { - "Module $module sits in a wrong dir" - } - } - - @Test - fun ensureAutoProjectObeysParams(project: Project) { - val projectDir = project.guessProjectDir()!!.toNioPath().name - assertTrue(projectDir.startsWith(projectName)) { - "$projectDir is not correct" - } - } - - - @Test - fun createManually(@TempDir projectPath: Path): Unit = runBlocking { - val project1 = projectExt.create(PathInfo((projectPath))) - val project2 = projectExt.create(PathInfo(projectPath)) - assertNotEquals(project1, project2) - - val module = moduleExt.create(ModuleParams( - name = ModuleName("MyModule"), - modulePersistenceType = Persistent(), - projectSource = ExplicitProject(project1) - )) - assertEquals(module.project, project1) - - val module2 = moduleExt.create() - assertNotEquals(module, module2) - modules.add(module) - modules.add(module2) - } - -} \ No newline at end of file diff --git a/platform/testFramework/junit5/test/showcase/resources/full/JUnit5SemiAutomatic.kt b/platform/testFramework/junit5/test/showcase/resources/full/JUnit5SemiAutomatic.kt deleted file mode 100644 index 1179f9cf40bd..000000000000 --- a/platform/testFramework/junit5/test/showcase/resources/full/JUnit5SemiAutomatic.kt +++ /dev/null @@ -1,39 +0,0 @@ -// 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.junit5.showcase.resources.full - -import com.intellij.openapi.module.Module -import com.intellij.openapi.project.Project -import com.intellij.testFramework.junit5.TestApplication -import com.intellij.testFramework.junit5.resources.ProjectResource -import com.intellij.testFramework.junit5.resources.ResourceExtensionApi -import com.intellij.testFramework.junit5.resources.providers.module.ModuleName -import com.intellij.testFramework.junit5.resources.providers.module.ModuleParams -import com.intellij.testFramework.junit5.resources.providers.module.ModuleProvider -import org.junit.jupiter.api.Assertions.assertEquals -import org.junit.jupiter.api.Assertions.assertTrue -import org.junit.jupiter.api.Test -import org.junit.jupiter.api.extension.RegisterExtension - -/** - * Class-level [Module] with custom name - */ -@TestApplication -@ProjectResource -class JUnit5SemiAutomatic { - - companion object { - private val ID = hashCode().toString() - - @JvmStatic - @RegisterExtension - val moduleEx = ResourceExtensionApi.forProvider(ModuleProvider { - ModuleParams(name = ModuleName("$ID-MyTest")) - }) - } - - @Test - fun funProjectModule(module: Module, project: Project) { - assertEquals(module.project, project) - assertTrue(module.name.startsWith(ID)) - } -} \ No newline at end of file diff --git a/platform/testFramework/junit5/test/showcase/resources/module/JUnit5ClassLevelModule.kt b/platform/testFramework/junit5/test/showcase/resources/module/JUnit5ClassLevelModule.kt index e90a6dd57f19..ecd7f23b3266 100644 --- a/platform/testFramework/junit5/test/showcase/resources/module/JUnit5ClassLevelModule.kt +++ b/platform/testFramework/junit5/test/showcase/resources/module/JUnit5ClassLevelModule.kt @@ -1,78 +1,28 @@ // 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.junit5.showcase.resources.module -import com.intellij.openapi.application.writeAction -import com.intellij.openapi.module.Module -import com.intellij.openapi.module.ModuleManager import com.intellij.testFramework.junit5.TestApplication -import com.intellij.testFramework.junit5.resources.ProjectResource -import com.intellij.testFramework.junit5.resources.ResourceExtensionApi -import com.intellij.testFramework.junit5.resources.create -import com.intellij.testFramework.junit5.resources.providers.PathInfo -import com.intellij.testFramework.junit5.resources.providers.module.ModuleName -import com.intellij.testFramework.junit5.resources.providers.module.ModuleParams -import com.intellij.testFramework.junit5.resources.providers.module.ModulePersistenceType.Persistent -import com.intellij.testFramework.junit5.resources.providers.module.ModuleProvider -import com.intellij.testFramework.junit5.showcase.resources.ResourceCounter -import com.intellij.testFramework.junit5.showcase.resources.module.JUnit5ClassLevelModule.Companion.counter -import kotlinx.coroutines.runBlocking +import com.intellij.testFramework.junit5.fixture.moduleFixture +import com.intellij.testFramework.junit5.fixture.projectFixture import org.junit.jupiter.api.Assertions -import org.junit.jupiter.api.Order import org.junit.jupiter.api.Test -import org.junit.jupiter.api.extension.AfterAllCallback -import org.junit.jupiter.api.extension.RegisterExtension -import org.junit.jupiter.api.io.TempDir -import java.nio.file.Path -/** - * [Module] created on class-level. Since module needs project, set [ProjectResource]. - * [counter] ensures modules are disposed - */ @TestApplication -@ProjectResource class JUnit5ClassLevelModule { companion object { - @Order(0) - @JvmStatic - @RegisterExtension - val leak = AfterAllCallback { - counter.ensureEmpty() - } + private val projectFixture = projectFixture() + private val moduleFixture = projectFixture.moduleFixture() - @JvmStatic - @RegisterExtension - @Order(1) - val ext = ResourceExtensionApi.forProvider(ModuleProvider()) - - private val counter = ResourceCounter() } @Test - fun test(module1: Module, module2: Module) { + fun test() { + val module1 = moduleFixture.get() + val module2 = moduleFixture.get() Assertions.assertEquals(module1, module2, "Class level modules must be same") Assertions.assertFalse(module1.isDisposed) } - - @Test - fun testManualDestroy(@TempDir tempDir: Path): Unit = runBlocking { - val module = ext.create(ModuleParams(modulePersistenceType = Persistent { _, _ -> PathInfo(tempDir.resolve("module.iml")) }), disposeOnExit = false) - Assertions.assertEquals(tempDir, module.moduleNioFile.parent) - counter.acquire(module) - writeAction { - ModuleManager.getInstance(module.project).disposeModule(module) - } - } - - @Test - fun testManualResource(): Unit = runBlocking { - // Manually created projects are always different - val m1 = ext.create() - val m2 = ext.create() - val m3 = ext.create(ModuleParams(ModuleName("abc123"))) - Assertions.assertNotEquals(m1, m2) - Assertions.assertNotEquals(m1, m3) - } } \ No newline at end of file diff --git a/platform/testFramework/junit5/test/showcase/resources/module/JUnit5MethodLevelModule.kt b/platform/testFramework/junit5/test/showcase/resources/module/JUnit5MethodLevelModule.kt index b5047c88ab32..5b626c9a3d79 100644 --- a/platform/testFramework/junit5/test/showcase/resources/module/JUnit5MethodLevelModule.kt +++ b/platform/testFramework/junit5/test/showcase/resources/module/JUnit5MethodLevelModule.kt @@ -3,38 +3,33 @@ package com.intellij.testFramework.junit5.showcase.resources.module import com.intellij.openapi.module.Module import com.intellij.testFramework.junit5.TestApplication -import com.intellij.testFramework.junit5.resources.NoInject -import com.intellij.testFramework.junit5.resources.ProjectResource -import com.intellij.testFramework.junit5.resources.asExtension -import com.intellij.testFramework.junit5.resources.providers.module.ModuleProvider +import com.intellij.testFramework.junit5.fixture.moduleFixture +import com.intellij.testFramework.junit5.fixture.projectFixture import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Test -import org.junit.jupiter.api.extension.RegisterExtension /** * Method-level [Module]s are destroyed after each test */ @TestApplication -@ProjectResource class JUnit5MethodLevelModule { - @JvmField - @RegisterExtension - val ext = ModuleProvider().asExtension() + private val moduleFixture = projectFixture().moduleFixture() - @NoInject private var moduleFromPreviousTest: Module? = null @Test - fun test(module1: Module, module2: Module) { + fun test() { + val module1 = moduleFixture.get() + val module2 = moduleFixture.get() Assertions.assertEquals(module1, module2, "Method level modules must be same") Assertions.assertFalse(module1.isDisposed) ensureNotModuleFromPrevTest(module1) } @Test - fun testDifferentModule(module: Module) { - ensureNotModuleFromPrevTest(module) + fun testDifferentModule() { + ensureNotModuleFromPrevTest(moduleFixture.get()) } private fun ensureNotModuleFromPrevTest(module: Module) { diff --git a/platform/testFramework/junit5/test/showcase/resources/project/JUnit5ProjectInstanceField.kt b/platform/testFramework/junit5/test/showcase/resources/project/JUnit5ClassLeveLProject.kt similarity index 64% rename from platform/testFramework/junit5/test/showcase/resources/project/JUnit5ProjectInstanceField.kt rename to platform/testFramework/junit5/test/showcase/resources/project/JUnit5ClassLeveLProject.kt index 49a2b83efcc9..60cc3e88d6e5 100644 --- a/platform/testFramework/junit5/test/showcase/resources/project/JUnit5ProjectInstanceField.kt +++ b/platform/testFramework/junit5/test/showcase/resources/project/JUnit5ClassLeveLProject.kt @@ -1,21 +1,24 @@ // 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.junit5.showcase.resources.project -import com.intellij.openapi.project.Project import com.intellij.openapi.util.Disposer -import com.intellij.testFramework.junit5.resources.FullApplication +import com.intellij.testFramework.junit5.TestApplication +import com.intellij.testFramework.junit5.fixture.projectFixture import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Test /** * Inject project in an instance field: one project for the whole class */ -@FullApplication -class JUnit5ProjectInstanceField { - lateinit var project: Project +@TestApplication +class JUnit5ClassLeveLProject { + companion object { + private val projectFixture = projectFixture() + } @Test fun ensureProject() { + val project = projectFixture.get() Assertions.assertFalse(project.isDisposed) Disposer.register(project) { diff --git a/platform/testFramework/junit5/test/showcase/resources/project/JUnit5ClassLevelProject.kt b/platform/testFramework/junit5/test/showcase/resources/project/JUnit5ClassLevelProject.kt deleted file mode 100644 index b2b943699f3b..000000000000 --- a/platform/testFramework/junit5/test/showcase/resources/project/JUnit5ClassLevelProject.kt +++ /dev/null @@ -1,91 +0,0 @@ -// 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.junit5.showcase.resources.project - -import com.intellij.openapi.components.Service -import com.intellij.openapi.components.service -import com.intellij.openapi.project.Project -import com.intellij.openapi.project.ex.ProjectManagerEx -import com.intellij.openapi.util.io.toNioPathOrNull -import com.intellij.testFramework.junit5.TestApplication -import com.intellij.testFramework.junit5.resources.asExtension -import com.intellij.testFramework.junit5.resources.create -import com.intellij.testFramework.junit5.resources.providers.PathInfo -import com.intellij.testFramework.junit5.resources.providers.ProjectProvider -import com.intellij.testFramework.junit5.showcase.resources.ResourceCounter -import com.intellij.testFramework.junit5.showcase.resources.project.JUnit5ClassLevelProject.Companion.counter -import kotlinx.coroutines.* -import org.junit.jupiter.api.Assertions -import org.junit.jupiter.api.Assertions.assertEquals -import org.junit.jupiter.api.Assertions.assertFalse -import org.junit.jupiter.api.Order -import org.junit.jupiter.api.Test -import org.junit.jupiter.api.extension.AfterAllCallback -import org.junit.jupiter.api.extension.RegisterExtension -import org.junit.jupiter.api.io.TempDir -import java.nio.file.Path - - -@Service(Service.Level.PROJECT) -private class MyProjectService(private val scope: CoroutineScope) { - init { - scope.launch { - while (true) { - delay(100) // Should be stopped after the test. Leakage will be reported - } - } - } - - fun regCodeOnDispose(code: () -> Unit) { - scope.coroutineContext.job.invokeOnCompletion { - code() - } - } -} - -/** - * Class-level project created once per test class. - * [counter] ensures it doesn't leak - */ -@TestApplication -class JUnit5ClassLevelProject { - - companion object { - @Order(0) - @JvmStatic - @RegisterExtension - val leak = AfterAllCallback { - counter.ensureEmpty() - } - - @Order(1) - @JvmStatic - @RegisterExtension - val ext = ProjectProvider().asExtension() - private val counter = ResourceCounter() - } - - @Test - fun test(project1: Project, project2: Project) { - assertEquals(project1, project2, "Class level must use same resource") - assertFalse(project1.isDisposed) - counter.acquire() - project1.service().regCodeOnDispose { - counter.release() - } - } - - @Test - fun testManualDestroy(@TempDir tempDir: Path): Unit = runBlocking { - val project = ext.create(PathInfo(tempDir, deletePathOnExit = false), disposeOnExit = true) - assertEquals(tempDir, project.basePath!!.toNioPathOrNull()!!) - Assertions.assertTrue(ProjectManagerEx.getInstanceEx().forceCloseProjectAsync(project, save = false)) - } - - @Test - fun testManualResource(): Unit = runBlocking { - // Manually created projects are always different - val p1 = ext.create() - val p2 = ext.create() - Assertions.assertNotEquals(p1, p2) - } -} \ No newline at end of file diff --git a/platform/testFramework/junit5/test/showcase/resources/project/JUnit5ClassLevelProjectAnnotation.kt b/platform/testFramework/junit5/test/showcase/resources/project/JUnit5ClassLevelProjectAnnotation.kt deleted file mode 100644 index 59d4bc5a5026..000000000000 --- a/platform/testFramework/junit5/test/showcase/resources/project/JUnit5ClassLevelProjectAnnotation.kt +++ /dev/null @@ -1,22 +0,0 @@ -// 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.junit5.showcase.resources.project - -import com.intellij.openapi.project.Project -import com.intellij.testFramework.junit5.TestApplication -import com.intellij.testFramework.junit5.resources.ProjectResource -import org.junit.jupiter.api.Assertions.assertFalse -import org.junit.jupiter.api.Test - - -/** - * Getting a project created automatically on class-level - */ -@TestApplication -@ProjectResource -class JUnit5ClassLevelProjectAnnotation { - - @Test - fun test(project: Project) { - assertFalse(project.isDisposed) - } -} \ No newline at end of file diff --git a/platform/testFramework/junit5/test/showcase/resources/project/JUnit5ProjectClassField.kt b/platform/testFramework/junit5/test/showcase/resources/project/JUnit5ProjectClassField.kt deleted file mode 100644 index 3e67bcf61be7..000000000000 --- a/platform/testFramework/junit5/test/showcase/resources/project/JUnit5ProjectClassField.kt +++ /dev/null @@ -1,26 +0,0 @@ -// 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.junit5.showcase.resources.project - -import com.intellij.openapi.project.Project -import com.intellij.openapi.util.Disposer -import com.intellij.testFramework.junit5.resources.FullApplication -import org.junit.jupiter.api.Assertions -import org.junit.jupiter.api.Test - -/** - * Inject project in a static field: one project for the whole class - */ -@FullApplication -class JUnit5ProjectClassField { - companion object { - lateinit var project: Project - } - - @Test - fun ensureProject() { - Assertions.assertFalse(project.isDisposed) - Disposer.register(project) { - - } - } -} \ No newline at end of file diff --git a/platform/testFramework/junit5/test/showcase/resources/project/JUnit5TestLevelProject.kt b/platform/testFramework/junit5/test/showcase/resources/project/JUnit5TestLevelProject.kt new file mode 100644 index 000000000000..55323c3110bd --- /dev/null +++ b/platform/testFramework/junit5/test/showcase/resources/project/JUnit5TestLevelProject.kt @@ -0,0 +1,73 @@ +// 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.junit5.showcase.resources.project + +import com.intellij.openapi.components.Service +import com.intellij.openapi.components.service +import com.intellij.openapi.util.Disposer +import com.intellij.testFramework.junit5.TestApplication +import com.intellij.testFramework.junit5.fixture.projectFixture +import com.intellij.testFramework.junit5.showcase.resources.ResourceCounter +import com.intellij.testFramework.junit5.showcase.resources.project.JUnit5TestLevelProject.Companion.counter +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.delay +import kotlinx.coroutines.job +import kotlinx.coroutines.launch +import org.junit.jupiter.api.AfterAll +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Assertions.assertFalse +import org.junit.jupiter.api.Test + + +@Service(Service.Level.PROJECT) +private class MyProjectService(private val scope: CoroutineScope) { + init { + scope.launch { + while (true) { + delay(100) // Should be stopped after the test. Leakage will be reported + } + } + } + + fun regCodeOnDispose(code: () -> Unit) { + scope.coroutineContext.job.invokeOnCompletion { + code() + } + } +} + +/** + * Class-level project created once per test class. + * [counter] ensures it doesn't leak + */ +@TestApplication +class JUnit5TestLevelProject { + + companion object { + @AfterAll + @JvmStatic + fun ensureEmpty() { + counter.ensureEmpty() + } + + @JvmStatic + private val counter = ResourceCounter() + + } + + private val projectFixture = projectFixture() + + @Test + fun test() { + val project1 = projectFixture.get() + val project2 = projectFixture.get() + assertEquals(project1, project2, "Class level must use same resource") + assertFalse(project1.isDisposed) + Disposer.register(project1) { + + } + counter.acquire() + project1.service().regCodeOnDispose { + counter.release() + } + } +} \ No newline at end of file