diff --git a/CHANGELOG.md b/CHANGELOG.md index 962150580..0640478e2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,10 @@ - add flashes for auto-fixable Open Source Issues - show code vision for Open Source also, when Snyk Code is still analysing - clean-up old open source scan functionality +- don't print out exceptions during shutdown of the app/plugin +- if the language server listener is shut down, set initialized to false +- log error stream of language server to idea.log +- show error / warn messages if the project is null (e.g. for offline handling) ## [2.9.1] ### Fixed diff --git a/src/main/kotlin/io/snyk/plugin/SnykPostStartupActivity.kt b/src/main/kotlin/io/snyk/plugin/SnykPostStartupActivity.kt index 07538f7cf..1805c834a 100644 --- a/src/main/kotlin/io/snyk/plugin/SnykPostStartupActivity.kt +++ b/src/main/kotlin/io/snyk/plugin/SnykPostStartupActivity.kt @@ -86,7 +86,7 @@ class SnykPostStartupActivity : ProjectActivity { } if (!settings.token.isNullOrBlank() && settings.scanOnSave) { - getSnykTaskQueueService(project)?.scan(true) + getSnykTaskQueueService(project)?.scan() } ExtensionPointsUtil.controllerManager.extensionList.forEach { diff --git a/src/main/kotlin/io/snyk/plugin/SnykProjectManagerListener.kt b/src/main/kotlin/io/snyk/plugin/SnykProjectManagerListener.kt index a07a229e6..185bac6fa 100644 --- a/src/main/kotlin/io/snyk/plugin/SnykProjectManagerListener.kt +++ b/src/main/kotlin/io/snyk/plugin/SnykProjectManagerListener.kt @@ -28,8 +28,10 @@ class SnykProjectManagerListener : ProjectManagerListener { ls.updateWorkspaceFolders(emptySet(), ls.getWorkspaceFolders(project)) } }.get(TIMEOUT, TimeUnit.SECONDS) - } catch (ignored: RuntimeException) { - logger().info("Project closing clean up took too long", ignored) + } catch (ignored: Exception) { + val logger = logger() + logger.warn("Project closing clean up took longer than $TIMEOUT seconds") + logger.debug(ignored) } } } diff --git a/src/main/kotlin/io/snyk/plugin/extensions/SnykControllerImpl.kt b/src/main/kotlin/io/snyk/plugin/extensions/SnykControllerImpl.kt index e557d560e..402ae64b9 100644 --- a/src/main/kotlin/io/snyk/plugin/extensions/SnykControllerImpl.kt +++ b/src/main/kotlin/io/snyk/plugin/extensions/SnykControllerImpl.kt @@ -13,7 +13,7 @@ class SnykControllerImpl(val project: Project) : SnykController { * scan enqueues a scan of the project for vulnerabilities. */ override fun scan() { - getSnykTaskQueueService(project)?.scan(false) + getSnykTaskQueueService(project)?.scan() } /** diff --git a/src/main/kotlin/io/snyk/plugin/services/SnykTaskQueueService.kt b/src/main/kotlin/io/snyk/plugin/services/SnykTaskQueueService.kt index 7ed43d59e..b23b9c75f 100644 --- a/src/main/kotlin/io/snyk/plugin/services/SnykTaskQueueService.kt +++ b/src/main/kotlin/io/snyk/plugin/services/SnykTaskQueueService.kt @@ -89,7 +89,7 @@ class SnykTaskQueueService(val project: Project) { } } - fun scan(isStartup: Boolean) { + fun scan() { taskQueue.run(object : Task.Backgroundable(project, "Snyk: initializing...", true) { override fun run(indicator: ProgressIndicator) { if (!confirmScanningAndSetWorkspaceTrustedStateIfNeeded(project)) return @@ -101,9 +101,7 @@ class SnykTaskQueueService(val project: Project) { waitUntilCliDownloadedIfNeeded() indicator.checkCanceled() - if (!isStartup) { - LanguageServerWrapper.getInstance().sendScanCommand(project) - } + LanguageServerWrapper.getInstance().sendScanCommand(project) if (settings.iacScanEnabled) { if (!isSnykIaCLSEnabled()) { diff --git a/src/main/kotlin/io/snyk/plugin/services/download/CliDownloaderService.kt b/src/main/kotlin/io/snyk/plugin/services/download/CliDownloaderService.kt index a13944600..65c4a4b34 100644 --- a/src/main/kotlin/io/snyk/plugin/services/download/CliDownloaderService.kt +++ b/src/main/kotlin/io/snyk/plugin/services/download/CliDownloaderService.kt @@ -73,7 +73,7 @@ class SnykCliDownloaderService { try { if (languageServerWrapper.isInitialized) { try { - languageServerWrapper.shutdown().get(2, TimeUnit.SECONDS) + languageServerWrapper.shutdown() } catch (e: RuntimeException) { logger() .warn("Language server shutdown for download took too long, couldn't shutdown", e) diff --git a/src/main/kotlin/io/snyk/plugin/ui/SnykBalloonNotificationHelper.kt b/src/main/kotlin/io/snyk/plugin/ui/SnykBalloonNotificationHelper.kt index 108de1870..d5781f88e 100644 --- a/src/main/kotlin/io/snyk/plugin/ui/SnykBalloonNotificationHelper.kt +++ b/src/main/kotlin/io/snyk/plugin/ui/SnykBalloonNotificationHelper.kt @@ -30,10 +30,10 @@ object SnykBalloonNotificationHelper { showNotification(message, project, NotificationType.ERROR, *actions) } - fun showInfo(message: String, project: Project, vararg actions: AnAction) = + fun showInfo(message: String, project: Project?, vararg actions: AnAction) = showNotification(message, project, NotificationType.INFORMATION, *actions) - fun showWarn(message: String, project: Project, vararg actions: AnAction) = + fun showWarn(message: String, project: Project?, vararg actions: AnAction) = showNotification(message, project, NotificationType.WARNING, *actions) private fun showNotification( diff --git a/src/main/kotlin/io/snyk/plugin/ui/actions/SnykRunScanAction.kt b/src/main/kotlin/io/snyk/plugin/ui/actions/SnykRunScanAction.kt index 673e4ff6b..bb3adffb0 100644 --- a/src/main/kotlin/io/snyk/plugin/ui/actions/SnykRunScanAction.kt +++ b/src/main/kotlin/io/snyk/plugin/ui/actions/SnykRunScanAction.kt @@ -16,7 +16,7 @@ import io.snyk.plugin.pluginSettings class SnykRunScanAction : AnAction(AllIcons.Actions.Execute), DumbAware { override fun actionPerformed(actionEvent: AnActionEvent) { - getSnykTaskQueueService(actionEvent.project!!)?.scan(false) + getSnykTaskQueueService(actionEvent.project!!)?.scan() } override fun update(actionEvent: AnActionEvent) { diff --git a/src/main/kotlin/io/snyk/plugin/ui/settings/IssueViewOptionsPanel.kt b/src/main/kotlin/io/snyk/plugin/ui/settings/IssueViewOptionsPanel.kt index b40abd61b..94d464745 100644 --- a/src/main/kotlin/io/snyk/plugin/ui/settings/IssueViewOptionsPanel.kt +++ b/src/main/kotlin/io/snyk/plugin/ui/settings/IssueViewOptionsPanel.kt @@ -28,7 +28,7 @@ class IssueViewOptionsPanel( .actionListener{ _, it -> if (canBeChanged(it, it.isSelected)) { currentOpenIssuesEnabled = it.isSelected - getSnykTaskQueueService(project)?.scan(false) + getSnykTaskQueueService(project)?.scan() } } // bindSelected is needed to trigger apply() on the settings dialog that this panel is rendered in @@ -44,7 +44,7 @@ class IssueViewOptionsPanel( .actionListener{ _, it -> if (canBeChanged(it, it.isSelected)) { currentIgnoredIssuesEnabled = it.isSelected - getSnykTaskQueueService(project)?.scan(false) + getSnykTaskQueueService(project)?.scan() } } .bindSelected(settings::ignoredIssuesEnabled) diff --git a/src/main/kotlin/io/snyk/plugin/ui/toolwindow/SnykPluginDisposable.kt b/src/main/kotlin/io/snyk/plugin/ui/toolwindow/SnykPluginDisposable.kt index 90bc96daf..eba4422fc 100644 --- a/src/main/kotlin/io/snyk/plugin/ui/toolwindow/SnykPluginDisposable.kt +++ b/src/main/kotlin/io/snyk/plugin/ui/toolwindow/SnykPluginDisposable.kt @@ -44,7 +44,7 @@ class SnykPluginDisposable : Disposable, AppLifecycleListener { override fun appClosing() { try { - LanguageServerWrapper.getInstance().shutdown().get(2, TimeUnit.SECONDS) + LanguageServerWrapper.getInstance().shutdown() } catch (ignored: Exception) { // do nothing } @@ -52,7 +52,7 @@ class SnykPluginDisposable : Disposable, AppLifecycleListener { override fun appWillBeClosed(isRestart: Boolean) { try { - LanguageServerWrapper.getInstance().shutdown().get(2, TimeUnit.SECONDS) + LanguageServerWrapper.getInstance().shutdown() } catch (ignored: Exception) { // do nothing } diff --git a/src/main/kotlin/io/snyk/plugin/ui/toolwindow/SnykToolWindowPanel.kt b/src/main/kotlin/io/snyk/plugin/ui/toolwindow/SnykToolWindowPanel.kt index aec98ef48..0c7bd392d 100644 --- a/src/main/kotlin/io/snyk/plugin/ui/toolwindow/SnykToolWindowPanel.kt +++ b/src/main/kotlin/io/snyk/plugin/ui/toolwindow/SnykToolWindowPanel.kt @@ -449,7 +449,7 @@ class SnykToolWindowPanel( } private fun triggerScan() { - getSnykTaskQueueService(project)?.scan(false) + getSnykTaskQueueService(project)?.scan() } fun displayAuthPanel() { diff --git a/src/main/kotlin/snyk/common/lsp/LanguageServerWrapper.kt b/src/main/kotlin/snyk/common/lsp/LanguageServerWrapper.kt index c5487af1c..2f8112173 100644 --- a/src/main/kotlin/snyk/common/lsp/LanguageServerWrapper.kt +++ b/src/main/kotlin/snyk/common/lsp/LanguageServerWrapper.kt @@ -17,7 +17,6 @@ import io.snyk.plugin.getSnykTaskQueueService import io.snyk.plugin.getWaitForResultsTimeout import io.snyk.plugin.isSnykIaCLSEnabled import io.snyk.plugin.pluginSettings -import io.snyk.plugin.services.SnykApplicationSettingsStateService import io.snyk.plugin.toLanguageServerURL import io.snyk.plugin.ui.toolwindow.SnykPluginDisposable import kotlinx.coroutines.DelicateCoroutinesApi @@ -42,6 +41,7 @@ import org.eclipse.lsp4j.WorkspaceEditCapabilities import org.eclipse.lsp4j.WorkspaceFolder import org.eclipse.lsp4j.WorkspaceFoldersChangeEvent import org.eclipse.lsp4j.jsonrpc.Launcher +import org.eclipse.lsp4j.jsonrpc.RemoteEndpoint import org.eclipse.lsp4j.launch.LSPLauncher import org.eclipse.lsp4j.services.LanguageServer import org.jetbrains.concurrency.runAsync @@ -62,10 +62,10 @@ import snyk.trust.WorkspaceTrustService import snyk.trust.confirmScanningAndSetWorkspaceTrustedStateIfNeeded import java.util.concurrent.ExecutorService import java.util.concurrent.Executors -import java.util.concurrent.Future import java.util.concurrent.TimeUnit import java.util.concurrent.TimeoutException import java.util.concurrent.locks.ReentrantLock +import java.util.logging.Logger.getLogger import kotlin.io.path.exists private const val INITIALIZATION_TIMEOUT = 20L @@ -134,22 +134,32 @@ class LanguageServerWrapper( EnvironmentHelper.updateEnvironment(processBuilder.environment(), pluginSettings().token ?: "") process = processBuilder.start() - launcher = LSPLauncher.createClientLauncher(languageClient, process.inputStream, process.outputStream) - languageServer = launcher.remoteProxy - GlobalScope.launch { if (!disposed) { try { - process.errorStream.bufferedReader().forEachLine { println(it) } + process.errorStream.bufferedReader().forEachLine { logger.debug(it) } } catch (ignored: Exception) { // ignore } } } - launcher.startListening() - sendInitializeMessage() - isInitialized = true + launcher = LSPLauncher.createClientLauncher(languageClient, process.inputStream, process.outputStream) + languageServer = launcher.remoteProxy + + val listenerFuture = launcher.startListening() + + runAsync { + listenerFuture.get() + isInitialized = false + } + + if (!listenerFuture.isDone) { + sendInitializeMessage() + isInitialized = true + } else { + logger.warn("Language Server initialization did not succeed") + } } catch (e: Exception) { logger.warn(e) process.destroy() @@ -157,16 +167,29 @@ class LanguageServerWrapper( } } - fun shutdown(): Future<*> = - executorService.submit { - if (::process.isInitialized && process.isAlive) { - languageServer.shutdown().get(1, TimeUnit.SECONDS) - languageServer.exit() - if (process.isAlive) { - process.destroyForcibly() - } + fun shutdown() { + // LSP4j logs errors and rethrows - this is bad practice, and we don't need that log here, so we shut it up. + val lsp4jLogger = getLogger(RemoteEndpoint::class.java.name) + val previousLSP4jLogLevel = lsp4jLogger.level + lsp4jLogger.level = java.util.logging.Level.OFF + try { + val shouldShutdown = lsIsAlive() + executorService.submit { if (shouldShutdown) languageServer.shutdown().get(1, TimeUnit.SECONDS) } + } catch (ignored: Exception) { + // we don't care + } finally { + try { + if (lsIsAlive()) languageServer.exit() + } catch (ignore: Exception) { + // do nothing + } finally { + if (lsIsAlive()) process.destroyForcibly() } + lsp4jLogger.level = previousLSP4jLogLevel } + } + + private fun lsIsAlive() = ::process.isInitialized && process.isAlive private fun determineWorkspaceFolders(): List { val workspaceFolders = mutableSetOf() diff --git a/src/main/kotlin/snyk/common/lsp/SnykLanguageClient.kt b/src/main/kotlin/snyk/common/lsp/SnykLanguageClient.kt index e8af51dd1..b6c99ba97 100644 --- a/src/main/kotlin/snyk/common/lsp/SnykLanguageClient.kt +++ b/src/main/kotlin/snyk/common/lsp/SnykLanguageClient.kt @@ -460,12 +460,10 @@ class SnykLanguageClient : override fun showMessage(messageParams: MessageParams?) { if (disposed) return val project = ProjectUtil.getActiveProject() - if (project == null) { - logger.info(messageParams?.message) - return - } when (messageParams?.type) { - MessageType.Error -> SnykBalloonNotificationHelper.showError(messageParams.message, project) + MessageType.Error -> { + SnykBalloonNotificationHelper.showError(messageParams.message, project) + } MessageType.Warning -> SnykBalloonNotificationHelper.showWarn(messageParams.message, project) MessageType.Info -> { val notification = SnykBalloonNotificationHelper.showInfo(messageParams.message, project) diff --git a/src/main/kotlin/snyk/trust/TrustedProjects.kt b/src/main/kotlin/snyk/trust/TrustedProjects.kt index 508816c03..96cd62c79 100644 --- a/src/main/kotlin/snyk/trust/TrustedProjects.kt +++ b/src/main/kotlin/snyk/trust/TrustedProjects.kt @@ -3,7 +3,7 @@ package snyk.trust import com.intellij.openapi.application.ApplicationManager -import com.intellij.openapi.application.invokeAndWaitIfNeeded +import com.intellij.openapi.application.runInEdt import com.intellij.openapi.components.service import com.intellij.openapi.diagnostic.Logger import com.intellij.openapi.project.Project @@ -58,7 +58,7 @@ private fun confirmScanningUntrustedProject(project: Project): ScanUntrustedProj var choice = ScanUntrustedProjectChoice.CANCEL - invokeAndWaitIfNeeded { + runInEdt { val result = MessageDialogBuilder .yesNo(title, message) .icon(Messages.getWarningIcon()) diff --git a/src/test/kotlin/io/snyk/plugin/TestUtils.kt b/src/test/kotlin/io/snyk/plugin/TestUtils.kt index 5550032cb..53c1a5575 100644 --- a/src/test/kotlin/io/snyk/plugin/TestUtils.kt +++ b/src/test/kotlin/io/snyk/plugin/TestUtils.kt @@ -43,7 +43,11 @@ fun resetSettings(project: Project?) { SnykProjectSettingsStateService(), project ) - LanguageServerWrapper.getInstance().shutdown() + try { + LanguageServerWrapper.getInstance().shutdown() + } catch (ignore: Exception) { + // ignore + } } /** low level avoiding download the CLI file */ diff --git a/src/test/kotlin/io/snyk/plugin/services/SnykTaskQueueServiceTest.kt b/src/test/kotlin/io/snyk/plugin/services/SnykTaskQueueServiceTest.kt index 935321bfd..c4f8e706e 100644 --- a/src/test/kotlin/io/snyk/plugin/services/SnykTaskQueueServiceTest.kt +++ b/src/test/kotlin/io/snyk/plugin/services/SnykTaskQueueServiceTest.kt @@ -3,7 +3,6 @@ package io.snyk.plugin.services import com.intellij.openapi.components.service import com.intellij.testFramework.LightPlatformTestCase import com.intellij.testFramework.PlatformTestUtil -import com.intellij.testFramework.replaceService import io.mockk.every import io.mockk.mockk import io.mockk.mockkObject @@ -69,7 +68,7 @@ class SnykTaskQueueServiceTest : LightPlatformTestCase() { setupDummyCliFile() val snykTaskQueueService = project.service() - snykTaskQueueService.scan(false) + snykTaskQueueService.scan() PlatformTestUtil.dispatchAllInvocationEventsInIdeEventQueue() assertTrue(snykTaskQueueService.getTaskQueue().isEmpty) @@ -85,7 +84,7 @@ class SnykTaskQueueServiceTest : LightPlatformTestCase() { every { isCliInstalled() } returns true val snykTaskQueueService = project.service() - snykTaskQueueService.scan(false) + snykTaskQueueService.scan() PlatformTestUtil.dispatchAllInvocationEventsInIdeEventQueue() assertTrue(snykTaskQueueService.getTaskQueue().isEmpty) @@ -99,7 +98,7 @@ class SnykTaskQueueServiceTest : LightPlatformTestCase() { val snykTaskQueueService = project.service() every { isCliInstalled() } returns true - snykTaskQueueService.scan(false) + snykTaskQueueService.scan() PlatformTestUtil.dispatchAllInvocationEventsInIdeEventQueue() assertTrue(snykTaskQueueService.getTaskQueue().isEmpty) @@ -156,7 +155,7 @@ class SnykTaskQueueServiceTest : LightPlatformTestCase() { every { isCliInstalled() } returns true every { getIacService(project)?.scan() } returns fakeIacResult - snykTaskQueueService.scan(false) + snykTaskQueueService.scan() PlatformTestUtil.dispatchAllInvocationEventsInIdeEventQueue() assertEquals(fakeIacResult, getSnykCachedResults(project)?.currentIacResult) @@ -178,7 +177,7 @@ class SnykTaskQueueServiceTest : LightPlatformTestCase() { getSnykCachedResults(project)?.currentContainerResult = null - snykTaskQueueService.scan(false) + snykTaskQueueService.scan() PlatformTestUtil.dispatchAllInvocationEventsInIdeEventQueue() await().atMost(2, TimeUnit.SECONDS).until { diff --git a/src/test/kotlin/io/snyk/plugin/ui/BranchChooserComboBoxDialogTest.kt b/src/test/kotlin/io/snyk/plugin/ui/BranchChooserComboBoxDialogTest.kt index c55631bb7..9a7b000ff 100644 --- a/src/test/kotlin/io/snyk/plugin/ui/BranchChooserComboBoxDialogTest.kt +++ b/src/test/kotlin/io/snyk/plugin/ui/BranchChooserComboBoxDialogTest.kt @@ -11,6 +11,7 @@ import io.mockk.CapturingSlot import io.mockk.mockk import io.mockk.unmockkAll import io.mockk.verify +import io.snyk.plugin.getContentRootPaths import io.snyk.plugin.toVirtualFile import okio.Path.Companion.toPath import org.eclipse.lsp4j.DidChangeConfigurationParams @@ -21,11 +22,13 @@ import snyk.common.lsp.FolderConfigSettings import snyk.common.lsp.LanguageServerSettings import snyk.common.lsp.LanguageServerWrapper import snyk.trust.WorkspaceTrustService +import snyk.trust.WorkspaceTrustSettings +import kotlin.io.path.absolutePathString class BranchChooserComboBoxDialogTest : LightPlatform4TestCase() { private val lsMock: LanguageServer = mockk(relaxed = true) - lateinit var folderConfig: FolderConfig + private lateinit var folderConfig: FolderConfig lateinit var cut: BranchChooserComboBoxDialog override fun setUp(): Unit { @@ -33,6 +36,7 @@ class BranchChooserComboBoxDialogTest : LightPlatform4TestCase() { unmockkAll() folderConfig = FolderConfig(project.basePath.toString(), "testBranch") service().addFolderConfig(folderConfig) + project.getContentRootPaths().forEach { service().addTrustedPath(it.root.absolutePathString())} val languageServerWrapper = LanguageServerWrapper.getInstance() languageServerWrapper.isInitialized = true languageServerWrapper.languageServer = lsMock diff --git a/src/test/kotlin/io/snyk/plugin/ui/toolwindow/SnykToolWindowPanelIntegTest.kt b/src/test/kotlin/io/snyk/plugin/ui/toolwindow/SnykToolWindowPanelIntegTest.kt index 9ff2b1e19..421f22ea0 100644 --- a/src/test/kotlin/io/snyk/plugin/ui/toolwindow/SnykToolWindowPanelIntegTest.kt +++ b/src/test/kotlin/io/snyk/plugin/ui/toolwindow/SnykToolWindowPanelIntegTest.kt @@ -583,7 +583,7 @@ class SnykToolWindowPanelIntegTest : HeavyPlatformTestCase() { every { getIacService(project)?.scan() } returns iacResultWithError // actual test run - project.service().scan(false) + project.service().scan() PlatformTestUtil.waitWhileBusy(toolWindowPanel.getTree()) @@ -690,7 +690,7 @@ class SnykToolWindowPanelIntegTest : HeavyPlatformTestCase() { setUpContainerTest(containerResultWithError) // actual test run - project.service().scan(false) + project.service().scan() PlatformTestUtil.waitWhileBusy(toolWindowPanel.getTree()) @@ -717,7 +717,7 @@ class SnykToolWindowPanelIntegTest : HeavyPlatformTestCase() { setUpContainerTest(fakeContainerResult) // actual test run - project.service().scan(false) + project.service().scan() PlatformTestUtil.waitWhileBusy(toolWindowPanel.getTree()) // Assertions @@ -751,7 +751,7 @@ class SnykToolWindowPanelIntegTest : HeavyPlatformTestCase() { mockkObject(SnykBalloonNotificationHelper) // actual test run - project.service().scan(false) + project.service().scan() PlatformTestUtil.waitWhileBusy(toolWindowPanel.getTree()) // Assertions @@ -783,7 +783,7 @@ class SnykToolWindowPanelIntegTest : HeavyPlatformTestCase() { setUpContainerTest(fakeContainerResult) // actual test run - project.service().scan(false) + project.service().scan() PlatformTestUtil.waitWhileBusy(toolWindowPanel.getTree()) // Assertions @@ -876,7 +876,7 @@ class SnykToolWindowPanelIntegTest : HeavyPlatformTestCase() { setUpContainerTest(containerResult) // actual test run - project.service().scan(false) + project.service().scan() PlatformTestUtil.waitWhileBusy(toolWindowPanel.getTree()) return containerResult diff --git a/src/test/kotlin/io/snyk/plugin/ui/toolwindow/SnykToolWindowPanelTest.kt b/src/test/kotlin/io/snyk/plugin/ui/toolwindow/SnykToolWindowPanelTest.kt index b920408f0..d5530be34 100644 --- a/src/test/kotlin/io/snyk/plugin/ui/toolwindow/SnykToolWindowPanelTest.kt +++ b/src/test/kotlin/io/snyk/plugin/ui/toolwindow/SnykToolWindowPanelTest.kt @@ -21,7 +21,6 @@ import snyk.UIComponentFinder import snyk.common.lsp.LanguageServerWrapper import snyk.common.lsp.SnykLanguageClient import java.awt.Container -import java.io.File import java.util.concurrent.CompletableFuture class SnykToolWindowPanelTest : LightPlatform4TestCase() { @@ -102,7 +101,7 @@ class SnykToolWindowPanelTest : LightPlatform4TestCase() { fun `should not display onboarding panel and run scan directly`() { every { settings.token } returns "test-token" every { settings.pluginFirstRun } returns true - justRun { taskQueueService.scan(false) } + justRun { taskQueueService.scan() } cut = SnykToolWindowPanel(project) @@ -111,7 +110,7 @@ class SnykToolWindowPanelTest : LightPlatform4TestCase() { assertNotNull(descriptionPanel) assertEquals(findOnePixelSplitter(vulnerabilityTree), descriptionPanel!!.parent) - verify(exactly = 1) { taskQueueService.scan(false) } + verify(exactly = 1) { taskQueueService.scan() } } //TODO rewrite diff --git a/src/test/kotlin/io/snyk/plugin/ui/toolwindow/SnykToolWindowSnykScanListenerLSTest.kt b/src/test/kotlin/io/snyk/plugin/ui/toolwindow/SnykToolWindowSnykScanListenerLSTest.kt index 967ddd64b..31c6b625f 100644 --- a/src/test/kotlin/io/snyk/plugin/ui/toolwindow/SnykToolWindowSnykScanListenerLSTest.kt +++ b/src/test/kotlin/io/snyk/plugin/ui/toolwindow/SnykToolWindowSnykScanListenerLSTest.kt @@ -1,5 +1,6 @@ package io.snyk.plugin.ui.toolwindow +import com.intellij.ide.impl.TrustedPathsSettings import com.intellij.openapi.application.WriteAction import com.intellij.openapi.components.service import com.intellij.openapi.vfs.VirtualFile @@ -11,10 +12,12 @@ import io.snyk.plugin.Severity import io.snyk.plugin.getContentRootPaths import io.snyk.plugin.pluginSettings import io.snyk.plugin.resetSettings +import io.snyk.plugin.toVirtualFile import io.snyk.plugin.ui.toolwindow.nodes.root.RootOssTreeNode import io.snyk.plugin.ui.toolwindow.nodes.root.RootQualityIssuesTreeNode import io.snyk.plugin.ui.toolwindow.nodes.root.RootSecurityIssuesTreeNode import junit.framework.TestCase +import okio.Path.Companion.toPath import org.eclipse.lsp4j.Position import org.eclipse.lsp4j.Range import snyk.common.annotator.SnykCodeAnnotator @@ -23,9 +26,12 @@ import snyk.common.lsp.FolderConfig import snyk.common.lsp.FolderConfigSettings import snyk.common.lsp.IssueData import snyk.common.lsp.ScanIssue +import snyk.trust.WorkspaceTrustService +import snyk.trust.WorkspaceTrustSettings import java.nio.file.Paths import javax.swing.JTree import javax.swing.tree.DefaultMutableTreeNode +import kotlin.io.path.absolutePathString class SnykToolWindowSnykScanListenerLSTest : BasePlatformTestCase() { private lateinit var cut: SnykToolWindowSnykScanListenerLS @@ -53,10 +59,11 @@ class SnykToolWindowSnykScanListenerLSTest : BasePlatformTestCase() { file = myFixture.copyFileToProject(fileName) psiFile = WriteAction.computeAndWait { psiManager.findFile(file)!! } + val contentRootPaths = project.getContentRootPaths() service() .addFolderConfig( FolderConfig( - project.getContentRootPaths().first().toAbsolutePath().toString(), "main" + contentRootPaths.first().toAbsolutePath().toString(), "main" ) ) snykToolWindowPanel = SnykToolWindowPanel(project) @@ -64,6 +71,12 @@ class SnykToolWindowSnykScanListenerLSTest : BasePlatformTestCase() { rootSecurityIssuesTreeNode = RootSecurityIssuesTreeNode(project) rootQualityIssuesTreeNode = RootQualityIssuesTreeNode(project) pluginSettings().setDeltaEnabled() + contentRootPaths.forEach { service().addTrustedPath(it.root.absolutePathString())} + } + + override fun tearDown() { + super.tearDown() + unmockkAll() } private fun mockScanIssues( diff --git a/src/test/kotlin/io/snyk/plugin/ui/toolwindow/settings/ScanTypesPanelTest.kt b/src/test/kotlin/io/snyk/plugin/ui/toolwindow/settings/ScanTypesPanelTest.kt index d196cb343..18556e3cd 100644 --- a/src/test/kotlin/io/snyk/plugin/ui/toolwindow/settings/ScanTypesPanelTest.kt +++ b/src/test/kotlin/io/snyk/plugin/ui/toolwindow/settings/ScanTypesPanelTest.kt @@ -1,6 +1,7 @@ package io.snyk.plugin.ui.toolwindow.settings import com.intellij.openapi.Disposable +import com.intellij.openapi.components.service import com.intellij.openapi.util.Disposer import com.intellij.testFramework.LightPlatform4TestCase import com.intellij.ui.components.JBCheckBox @@ -10,6 +11,7 @@ import io.mockk.mockk import io.mockk.mockkStatic import io.mockk.unmockkAll import io.mockk.verify +import io.snyk.plugin.getContentRootPaths import io.snyk.plugin.getKubernetesImageCache import io.snyk.plugin.pluginSettings import io.snyk.plugin.resetSettings @@ -19,6 +21,8 @@ import snyk.common.ProductType import snyk.common.UIComponentFinder.getComponentByName import snyk.common.isSnykCodeAvailable import snyk.container.KubernetesImageCache +import snyk.trust.WorkspaceTrustSettings +import kotlin.io.path.absolutePathString class ScanTypesPanelTest : LightPlatform4TestCase() { private lateinit var disposable: Disposable @@ -26,6 +30,7 @@ class ScanTypesPanelTest : LightPlatform4TestCase() { override fun setUp() { super.setUp() unmockkAll() + project.getContentRootPaths().forEach { service().addTrustedPath(it.root.absolutePathString())} resetSettings(project) disposable = Disposer.newDisposable() } diff --git a/src/test/kotlin/snyk/container/ContainerBulkFileListenerTest.kt b/src/test/kotlin/snyk/container/ContainerBulkFileListenerTest.kt index 0e2ec34a1..cd5d769f5 100644 --- a/src/test/kotlin/snyk/container/ContainerBulkFileListenerTest.kt +++ b/src/test/kotlin/snyk/container/ContainerBulkFileListenerTest.kt @@ -4,6 +4,7 @@ import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.application.WriteAction import com.intellij.openapi.application.invokeAndWaitIfNeeded import com.intellij.openapi.application.invokeLater +import com.intellij.openapi.application.runInEdt import com.intellij.openapi.components.service import com.intellij.openapi.fileEditor.FileDocumentManager import com.intellij.openapi.vfs.VirtualFile @@ -75,8 +76,8 @@ class ContainerBulkFileListenerTest : BasePlatformTestCase() { val path = createNewFileInProjectRoot().toPath() Files.write(path, "\n".toByteArray(Charsets.UTF_8)) var virtualFile: VirtualFile? = null - invokeLater { - VirtualFileManager.getInstance().syncRefresh() + VirtualFileManager.getInstance().syncRefresh() + runInEdt { virtualFile = VirtualFileManager.getInstance().findFileByNioPath(path) } PlatformTestUtil.dispatchAllEventsInIdeEventQueue() diff --git a/src/test/kotlin/snyk/container/ContainerServiceIntegTest.kt b/src/test/kotlin/snyk/container/ContainerServiceIntegTest.kt index f0d70d0b3..2756f1941 100644 --- a/src/test/kotlin/snyk/container/ContainerServiceIntegTest.kt +++ b/src/test/kotlin/snyk/container/ContainerServiceIntegTest.kt @@ -1,12 +1,14 @@ package snyk.container import com.google.gson.Gson +import com.intellij.openapi.components.service import com.intellij.testFramework.LightPlatform4TestCase import io.mockk.every import io.mockk.mockk import io.mockk.spyk import io.mockk.unmockkAll import io.mockk.verify +import io.snyk.plugin.getContentRootPaths import io.snyk.plugin.removeDummyCliFile import io.snyk.plugin.setupDummyCliFile import io.snyk.plugin.ui.toolwindow.SnykToolWindowPanel @@ -16,9 +18,10 @@ import org.junit.Test import snyk.common.lsp.LanguageServerWrapper import snyk.common.lsp.commands.COMMAND_EXECUTE_CLI import snyk.container.TestYamls.podYaml +import snyk.trust.WorkspaceTrustSettings import java.util.concurrent.CompletableFuture +import kotlin.io.path.absolutePathString -@Suppress("FunctionName") class ContainerServiceIntegTest : LightPlatform4TestCase() { private lateinit var cut: ContainerService private val containerResultWithRemediationJson = javaClass.classLoader @@ -51,6 +54,7 @@ class ContainerServiceIntegTest : LightPlatform4TestCase() { super.setUp() unmockkAll() setupDummyCliFile() + project.getContentRootPaths().forEach { service().addTrustedPath(it.root.absolutePathString())} cut = ContainerService(project) val languageServerWrapper = LanguageServerWrapper.getInstance() languageServerWrapper.languageServer = lsMock