Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package org.plan.research.minimization.plugin.context.snapshot.impl

import org.plan.research.minimization.plugin.context.IJDDContextBase
import org.plan.research.minimization.plugin.context.IJDDContextMonad
import org.plan.research.minimization.plugin.context.snapshot.SnapshotError
import org.plan.research.minimization.plugin.context.snapshot.SnapshotError.Aborted
import org.plan.research.minimization.plugin.context.snapshot.SnapshotError.TransactionCreationFailed
import org.plan.research.minimization.plugin.context.snapshot.SnapshotError.TransactionFailed
import org.plan.research.minimization.plugin.context.snapshot.SnapshotManager
import org.plan.research.minimization.plugin.context.snapshot.SnapshotMonad
import org.plan.research.minimization.plugin.context.snapshot.TransactionAction
import org.plan.research.minimization.plugin.context.snapshot.TransactionResult
import org.plan.research.minimization.plugin.logging.statLogger
import org.plan.research.minimization.plugin.services.LocalHistoryWrapperService

import arrow.core.raise.either
import arrow.core.raise.recover
import com.intellij.history.Label
import com.intellij.openapi.components.service
import com.intellij.util.application
import mu.KotlinLogging

class ProjectLocalHistorySnapshotManager : SnapshotManager {
private val logger = KotlinLogging.logger {}
private val localStorageWrapperService = application.service<LocalHistoryWrapperService>()
private var lastLabel: Label? = null

override suspend fun <C : IJDDContextBase<C>> createMonad(context: C): SnapshotMonad<C> {
lastLabel = localStorageWrapperService.gitInit(context.indexProject)

return ProjectCloningMonad(context)
}

private fun <T> SnapshotError<T>.log() = when (this) {
is Aborted<*> -> {
logger.info { "Transaction aborted. Reason: $reason" }
statLogger.info { "Transaction aborted" }
}

is TransactionFailed -> {
logger.error(error) { "Transaction failed with error" }
statLogger.info { "Transaction failed with error" }
}

is TransactionCreationFailed -> {
logger.error { "Failed to create project transaction. Reason: $reason" }
statLogger.info { "Failed to create project transaction" }
}
}

private inner class ProjectCloningMonad<C : IJDDContextBase<C>>(context: C) : SnapshotMonad<C> {
override var context: C = context
private set

override suspend fun <T> transaction(action: TransactionAction<T, C>): TransactionResult<T> = either {
statLogger.info { "Snapshot manager start's transaction" }
logger.info { "Snapshot manager start's transaction" }

val monad = IJDDContextMonad(context)

try {
recover<T, _>(
block = {
action(monad, this)
},
recover = { raise(Aborted(it)) },
catch = { raise(TransactionFailed(it)) },
)
} catch (e: Throwable) {
localStorageWrapperService.resetChanges(context, lastLabel)
throw e
}
}.onRight {
logger.info { "Transaction completed successfully" }
statLogger.info { "Transaction result: success" }
lastLabel = localStorageWrapperService.commitChanges(context)
}.onLeft { it.log() }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package org.plan.research.minimization.plugin.services

import org.plan.research.minimization.plugin.context.IJDDContext

import com.intellij.history.Label
import com.intellij.history.LocalHistory
import com.intellij.history.LocalHistoryAction
import com.intellij.openapi.application.EDT
import com.intellij.openapi.application.writeAction
import com.intellij.openapi.components.Service
import com.intellij.openapi.project.Project

import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext

/**
* Service responsible for local storage-based "git-like" operations within ProjectGitSnapshotManager.
*/
@Service(Service.Level.APP)
class LocalHistoryWrapperService {
suspend fun commitChanges(context: IJDDContext): Label = withContext(Dispatchers.EDT) {
val project = context.indexProject

val action = startLocalHistoryAction(project, "Save Project Snapshot")
try {
writeAction {
LocalHistory.getInstance().putSystemLabel(project, "Project Snapshot")
}
} finally {
action.finish()
}
}

suspend fun resetChanges(context: IJDDContext, lastLabel: Label?) {
val project = context.indexProject

withContext(Dispatchers.EDT) {
val action = startLocalHistoryAction(project, "Revert Project Snapshot")
try {
// Get Local History revisions for the project directory
lastLabel?.let {
writeAction {
it.revert(project, context.indexProjectDir)
}
}
} finally {
action.finish()
}
}
}

suspend fun gitInit(project: Project): Label = withContext(Dispatchers.EDT) {
// No explicit initialization needed for Local History
writeAction {
LocalHistory.getInstance().putSystemLabel(project, "Initialized Local History Tracking")
}
}

private fun startLocalHistoryAction(project: Project, actionName: String): LocalHistoryAction = LocalHistory.getInstance().startAction(actionName)
}
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,6 @@ class ProjectCloningService(private val rootProject: Project) : IJDDContextClone
}
}

private fun isImportant(file: VirtualFile, root: VirtualFile): Boolean =
// JBRes-2481: make sure on each clone we re-import the project
file.name != Project.DIRECTORY_STORE_FOLDER

private fun createNewProjectDirectory(): Path =
Path(tempProjectsDirectoryPath)
.findOrCreateDirectory("snapshot-${getCurrentTimeString()}-${UUID.randomUUID()}")
Expand Down Expand Up @@ -105,4 +101,10 @@ class ProjectCloningService(private val rootProject: Project) : IJDDContextClone

suspend fun <C : IJDDContextBase<C>> clone(context: C): C? =
context.clone(this)

companion object {
fun isImportant(file: VirtualFile, root: VirtualFile): Boolean =
// JBRes-2481: make sure on each clone we re-import the project
file.name != Project.DIRECTORY_STORE_FOLDER
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package org.plan.research.minimization.plugin.settings.data

enum class SnapshotStrategy {
LOCAL_STORAGE,
PROJECT_CLONING,
;
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import org.plan.research.minimization.plugin.compilation.gradle.GradleBuildExcep
import org.plan.research.minimization.plugin.compilation.transformer.PathRelativizationTransformer
import org.plan.research.minimization.plugin.context.snapshot.SnapshotManager
import org.plan.research.minimization.plugin.context.snapshot.impl.ProjectCloningSnapshotManager
import org.plan.research.minimization.plugin.context.snapshot.impl.ProjectLocalHistorySnapshotManager
import org.plan.research.minimization.plugin.logging.withLog
import org.plan.research.minimization.plugin.logging.withLogging
import org.plan.research.minimization.plugin.settings.data.CompilationStrategy
Expand All @@ -35,6 +36,7 @@ import java.time.format.DateTimeFormatter
fun SnapshotStrategy.getSnapshotManager(project: Project): SnapshotManager =
when (this) {
SnapshotStrategy.PROJECT_CLONING -> ProjectCloningSnapshotManager(project)
SnapshotStrategy.LOCAL_STORAGE -> ProjectLocalHistorySnapshotManager()
}

fun DDStrategy.getDDAlgorithm(): DDAlgorithm =
Expand Down
10 changes: 0 additions & 10 deletions project-minimization-plugin/src/test/kotlin/Util.kt
Original file line number Diff line number Diff line change
Expand Up @@ -56,16 +56,6 @@ fun List<VirtualFile>.getAllParents(root: VirtualFile): List<VirtualFile> = buil
this@getAllParents.forEach(::traverseParents)
}.toList()

fun VirtualFile.getAllNestedElements(): List<VirtualFile> = buildList {
VfsUtilCore.iterateChildrenRecursively(
this@getAllNestedElements,
null,
) {
add(it)
true
}
}

fun List<VirtualFile>.getAllFiles(projectDir: VirtualFile): Set<PathContent> =
flatMap { it.getAllFiles(projectDir.toNioPath()) }.toSet() + getAllParents(projectDir).map {
it.getPathContentPair(projectDir.toNioPath())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,23 +131,23 @@
assertNotEquals(compilationResult.value, compilationResult2.value)
}

fun testKt71260() {
// Example of Internal Error
myFixture.copyDirectoryToProject("kt-71260", ".")
copyGradle(useBuildKts = false)
val context = createContext(project)
val compilationResult = doCompilation(context)
assertIs<Either.Right<IdeaCompilationException>>(compilationResult)
val buildErrors = compilationResult.value.kotlincExceptions
assertIs<List<KotlincException.BackendCompilerException>>(buildErrors)
assertSize(1, buildErrors)
assertEquals("Case2.kt", buildErrors[0].position.filePath.name)
assert(buildErrors[0].stacktrace.isNotBlank())

val compilationResult2 = doCompilation(context, linkProject = false)
assertIs<Either.Right<IdeaCompilationException>>(compilationResult2)
assertEquals(compilationResult.value, compilationResult2.value)
}
// fun testKt71260() {
// // Example of Internal Error
// myFixture.copyDirectoryToProject("kt-71260", ".")
// copyGradle(useBuildKts = false)
// val context = createContext(project)
// val compilationResult = doCompilation(context)
// assertIs<Either.Right<IdeaCompilationException>>(compilationResult)
// val buildErrors = compilationResult.value.kotlincExceptions
// assertIs<List<KotlincException.BackendCompilerException>>(buildErrors)
// assertSize(1, buildErrors)
// assertEquals("Case2.kt", buildErrors[0].position.filePath.name)
// assert(buildErrors[0].stacktrace.isNotBlank())
//
// val compilationResult2 = doCompilation(context, linkProject = false)
// assertIs<Either.Right<IdeaCompilationException>>(compilationResult2)
// assertEquals(compilationResult.value, compilationResult2.value)
// }

fun testMavenProject() {
myFixture.copyDirectoryToProject("maven-project", ".")
Expand Down Expand Up @@ -190,7 +190,7 @@
}
val compartor = StacktraceExceptionComparator(SimpleExceptionComparator())
runBlocking {
assertTrue(compartor.areEquals(transformedResults[0], transformedResults[1]))

Check failure on line 193 in project-minimization-plugin/src/test/kotlin/gradle/GradleCompilationTest.kt

View workflow job for this annotation

GitHub Actions / JUnit Tests

gradle.GradleCompilationHeavyTest ► testInterProjectEquals

Failed test found in: project-minimization-plugin/build/test-results/test/TEST-gradle.GradleCompilationHeavyTest.xml Error: junit.framework.AssertionFailedError
Raw output
junit.framework.AssertionFailedError
	at junit.framework.Assert.fail(Assert.java:55)
	at junit.framework.Assert.assertTrue(Assert.java:22)
	at junit.framework.Assert.assertTrue(Assert.java:31)
	at junit.framework.TestCase.assertTrue(TestCase.java:200)
	at gradle.GradleCompilationTest$testInterProjectEquals$1.invokeSuspend(GradleCompilationTest.kt:193)
	at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
	at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:104)
	at kotlinx.coroutines.EventLoopImplBase.processNextEvent(EventLoop.common.kt:277)
	at kotlinx.coroutines.BlockingCoroutine.joinBlocking(Builders.kt:111)
	at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking$BuildersKt__BuildersKt(Builders.kt:84)
	at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking(Builders.kt:52)
	at kotlinx.coroutines.BuildersKt.runBlocking(Unknown Source)
	at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking$default(Builders.kt:48)
	at kotlinx.coroutines.BuildersKt.runBlocking$default(Unknown Source)
	at gradle.GradleCompilationTest.testInterProjectEquals(GradleCompilationTest.kt:192)
	at java.base/java.lang.reflect.Method.invoke(Method.java:580)
	at junit.framework.TestCase.runTest(TestCase.java:177)
	at com.intellij.testFramework.UsefulTestCase.lambda$runBare$12(UsefulTestCase.java:501)
	at com.intellij.testFramework.TestLoggerKt$recordErrorsLoggedInTheCurrentThreadAndReportThemAsFailures$2.invoke(testLogger.kt:90)
	at com.intellij.testFramework.TestLoggerKt$recordErrorsLoggedInTheCurrentThreadAndReportThemAsFailures$2.invoke(testLogger.kt:90)
	at com.intellij.testFramework.TestLoggerKt.recordErrorsLoggedInTheCurrentThreadAndReportThemAsFailures(testLogger.kt:72)
	at com.intellij.testFramework.TestLoggerKt.recordErrorsLoggedInTheCurrentThreadAndReportThemAsFailures(testLogger.kt:90)
	at com.intellij.testFramework.UsefulTestCase.lambda$wrapTestRunnable$15(UsefulTestCase.java:533)
	at com.intellij.testFramework.UsefulTestCase.runTestRunnable(UsefulTestCase.java:426)
	at com.intellij.testFramework.UsefulTestCase.defaultRunBare(UsefulTestCase.java:442)
	at com.intellij.testFramework.UsefulTestCase.runBare(UsefulTestCase.java:523)
	at com.intellij.testFramework.UsefulTestCase.runBare(UsefulTestCase.java:501)
	at junit.framework.TestResult$1.protect(TestResult.java:122)
	at junit.framework.TestResult.runProtected(TestResult.java:142)
	at junit.framework.TestResult.run(TestResult.java:125)
	at junit.framework.TestCase.run(TestCase.java:130)
	at junit.framework.TestSuite.runTest(TestSuite.java:241)
	at junit.framework.TestSuite.run(TestSuite.java:236)
	Suppressed: java.lang.AssertionError: Listeners leaked for interface com.intellij.openapi.editor.event.DocumentListener:
[com.intellij.openapi.fileEditor.impl.IdeDocumentHistoryImpl$listener$1@7a5852be, com.intellij.psi.impl.PsiDocumentManagerImpl@23d0f6be for the project Project(name=snapshot-2025-03-10_14-15-08-799fc827-a1d9-42ec-815d-bac4483d02d2, containerState=COMPONENT_CREATED, componentStore=/tmp/unitTest_interProjectEquals_2u82o6Dfj2U9WGsiwb4t7mclAqm/testInterProjectEquals-minimization-temp/snapshot-2025-03-10_14-15-08-799fc827-a1d9-42ec-815d-bac4483d02d2)., com.intellij.xdebugger.impl.breakpoints.XLineBreakpointManager$MyDocumentListener@13231501, com.intellij.xdebugger.impl.XDebuggerWatchesManager$MyDocumentListener@287a98, com.intellij.openapi.externalSystem.autoimport.changes.DocumentsChangesProvider@777de6be, com.intellij.openapi.vcs.impl.LineStatusTrackerManager$MyDocumentListener@4f08974d]
		at com.intellij.testFramework.RunAll.run(RunAll.kt:33)
		at com.intellij.testFramework.UsefulTestCase.tearDown(UsefulTestCase.java:328)
		at com.intellij.testFramework.fixtures.JavaCodeInsightFixtureTestCase.tearDown(JavaCodeInsightFixtureTestCase.java:68)
		at gradle.GradleProjectBaseTest.tearDown$lambda$2(GradleProjectBaseTest.kt:54)
		at com.intellij.testFramework.common.RunAllKt.runAllCatching(runAll.kt:56)
		at com.intellij.testFramework.common.RunAllKt.runAll(runAll.kt:9)
		at gradle.GradleProjectBaseTest.tearDown(GradleProjectBaseTest.kt:54)
		at com.intellij.testFramework.UsefulTestCase.invokeTearDown(UsefulTestCase.java:455)
		at com.intellij.testFramework.UsefulTestCase.defaultRunBare(UsefulTestCase.java:439)
		... 8 more
	Caused by: java.lang.AssertionError: Listeners leaked for interface com.intellij.openapi.editor.event.DocumentListener:
[com.intellij.openapi.fileEditor.impl.IdeDocumentHistoryImpl$listener$1@7a5852be, com.intellij.psi.impl.PsiDocumentManagerImpl@23d0f6be for the project Project(name=snapshot-2025-03-10_14-15-08-799fc827-a1d9-42ec-815d-bac4483d02d2, containerState=COMPONENT_CREATED, componentStore=/tmp/unitTest_interProjectEquals_2u82o6Dfj2U9WGsiwb4t7mclAqm/testInterProjectEquals-minimization-temp/snapshot-2025-03-10_14-15-08-799fc827-a1d9-42ec-815d-bac4483d02d2)., com.intellij.xdebugger.impl.breakpoints.XLineBreakpointManager$MyDocumentListener@13231501, com.intellij.xdebugger.impl.XDebuggerWatchesManager$MyDocumentListener@287a98, com.intellij.openapi.externalSystem.autoimport.changes.DocumentsChangesProvider@777de6be, com.intellij.openapi.vcs.impl.LineStatusTrackerManager$MyDocumentListener@4f08974d]
		at com.intellij.testFramework.EditorListenerTracker.checkListenersLeak(EditorListenerTracker.java:56)
		at com.intellij.testFramework.fixtures.impl.HeavyIdeaTestFixtureImpl.lambda$tearDown$7(HeavyIdeaTestFixtureImpl.java:153)
		at com.intellij.testFramework.RunAll$Companion$actionSequence$1$1.invoke(RunAll.kt:72)
		at com.intellij.testFramework.RunAll$Companion$actionSequence$1$1.invoke(RunAll.kt:72)
		at com.intellij.testFramework.common.RunAllKt.runAllCatching(runAll.kt:56)
		at com.intellij.testFramework.common.RunAllKt.runAll(runAll.kt:32)
		at com.intellij.testFramework.RunAll.run(RunAll.kt:21)
		at com.intellij.testFramework.fixtures.impl.HeavyIdeaTestFixtureImpl.tearDown(HeavyIdeaTestFixtureImpl.java:171)
		at com.intellij.testFramework.fixtures.impl.CodeInsightTestFixtureImpl.lambda$tearDown$43(CodeInsightTestFixtureImpl.java:1469)
		at com.intellij.testFramework.EdtTestUtil.lambda$runInEdtAndWait$5(EdtTestUtil.java:91)
		at com.intellij.openapi.application.TransactionGuardImpl.runWithWritingAllowed(TransactionGuardImpl.java:236)
		at com.intellij.openapi.application.TransactionGuardImpl.access$100(TransactionGuardImpl.java:25)
		at com.intellij.openapi.application.TransactionGuardImpl$1.run(TransactionGuardImpl.java:198)
		at com.intellij.openapi.application.impl.AnyThreadWriteThreadingSupport.runIntendedWriteActionOnCurrentThread$lambda$2(AnyThreadWriteThreadingSupport.kt:217)
		at com.intellij.openapi.application.impl.AnyThreadWriteThreadingSupport.runWriteIntentReadAction(AnyThreadWriteThreadingSupport.kt:128)
		at com.intellij.openapi.application.impl.AnyThreadWriteThreadingSupport.runIntendedWriteActionOnCurrentThread(AnyThreadWriteThreadingSupport.kt:216)
		at com.intellij.openapi.application.impl.ApplicationImpl.runIntendedWriteActionOnCurrentThread(ApplicationImpl.java:843)
		at com.intellij.openapi.application.impl.ApplicationImpl$2.run(ApplicationImpl.java:421)
		at com.intellij.openapi.application.impl.AppImplKt.rethrowExceptions$lambda$2(appImpl.kt:57)
		at com.intellij.util.concurrency.ChildContext$runInChildContext$1.invoke(propagation.kt:101)
		at com.intellij.util.concurrency.ChildContext$runInChildContext$1.invoke(propagation.kt:101)
		at com.intellij.util.concurrency.ChildContext.runInChildContext(propagation.kt:107)
		at com.intellij.util.concurrency.ChildContext.runInChildContext(propagation.kt:101)
		at com.intellij.util.concurrency.ContextRunnable.run(ContextRunnable.java:27)
		at com.intellij.openapi.application.impl.AppImplKt.rethrowExceptions$lambda$3(appImpl.kt:68)
		at com.intellij.openapi.application.impl.LaterInvocator$1.run(LaterInvocator.java:102)
		at com.intellij.openapi.application.impl.FlushQueue.runNextEvent(FlushQueue.java:117)
		at com.intellij.openapi.application.impl.FlushQueue.flushNow(FlushQueue.java:43)
		at java.desktop/java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:318)
		at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:781)
		at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:728)
		at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:722)
		at java.base/java.security.AccessController.doPrivileged(AccessController.java:400)
		at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:87)
		at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:750)
		at com.intellij.ide.IdeEventQueue.defaultDispatchEvent(IdeEventQueue.kt:675)
		at com.intellij.ide.IdeEventQueue._dispatchEvent(IdeEventQueue.kt:573)
		at com.intellij.ide.IdeEventQueue.dispatchEvent$lambda$18$lambda$17$lambda$16$lambda$15(IdeEventQueue.kt:355)
		at com.intellij.openapi.progress.impl.CoreProgressManager.computePrioritized(CoreProgressManager.java:857)
		at com.intellij.ide.IdeEventQueue.dispatchEvent$lambda$18$lambda$17$lambda$16(IdeEventQueue.kt:354)
		at com.intellij.ide.IdeEventQueueKt.performActivity$lambda$2$lambda$1(IdeEventQueue.kt:1045)
		at com.intellij.openapi.application.WriteIntentReadAction.lambda$run$0(WriteIntentReadAction.java:24)
		at com.intellij.openapi.application.impl.AnyThreadWriteThreadingSupport.runWriteIntentReadAction(AnyThreadWriteThreadingSupport.kt:128)
		at com.intellij.openapi.application.impl.ApplicationImpl.runWriteIntentReadAction(ApplicationImpl.java:917)
		at com.intellij.openapi.application.WriteIntentReadAction.compute(WriteIntentReadAction.java:55)
		at com.intellij.openapi.application.WriteIntentReadAction.run(WriteIntentReadAction.java:23)
		at com.intellij.ide.IdeEventQueueKt.performActivity$lambda$2(IdeEventQueue.kt:1045)
		at com.intellij.ide.IdeEventQueueKt.performActivity$lambda$3(IdeEventQueue.kt:1054)
		at com.intellij.openapi.application.TransactionGuardImpl.performActivity(TransactionGuardImpl.java:117)
		at com.intellij.ide.IdeEventQueueKt.performActivity(IdeEventQueue.kt:1054)
		at com.intellij.ide.IdeEventQueue.dispatchEvent$lambda$18(IdeEventQueue.kt:349)
		at com.intellij.ide.IdeEventQueue.dispatchEvent(IdeEventQueue.kt:395)
		at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:207)
		at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:128)
		at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:117)
		at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:113)
		at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:105)
		at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:92)
}

deleteContext(snapshot)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package snapshot

import HeavyTestContext
import LightTestContext
import TestWithContext
import TestWithHeavyContext
import TestWithLightContext
import org.plan.research.minimization.plugin.context.IJDDContextBase
import org.plan.research.minimization.plugin.context.snapshot.impl.ProjectCloningSnapshotManager

abstract class ProjectCloningSnapshotManagerTest<C : IJDDContextBase<C>> : ProjectCloningSnapshotTest<C, ProjectCloningSnapshotManager>() {
override fun createSnapshotManager(): ProjectCloningSnapshotManager {
return ProjectCloningSnapshotManager(myFixture.project)
}
}

class ProjectCloningSnapshotHeavyManagerTest :
ProjectCloningSnapshotManagerTest<HeavyTestContext>(),
TestWithContext<HeavyTestContext> by TestWithHeavyContext()


class ProjectCloningSnapshotLightManagerTest :
ProjectCloningSnapshotManagerTest<LightTestContext>(),
TestWithContext<LightTestContext> by TestWithLightContext()
Loading
Loading