// Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

package software.aws.toolkits.gradle.detekt.rules

import io.github.detekt.test.utils.createEnvironment
import io.gitlab.arturbosch.detekt.test.compileAndLintWithContext
import org.assertj.core.api.Assertions.assertThat
import org.junit.Test
import java.io.File

class LazyLogRuleTest {
    private val rule = LazyLogRule()
    private val environment = createEnvironment(
        additionalRootPaths = LazyLogRule.loggers.map {
            File(Class.forName(it).protectionDomain.codeSource.location.path)
        }
    ).env

    @Test
    fun lambdaIsUsedToLog() {
        assertThat(
            rule.compileAndLintWithContext(
                environment,
                """
import org.slf4j.LoggerFactory

val LOG = LoggerFactory.getLogger("")
fun foo() {
    LOG.debug { "Hi" }
}
                """.trimIndent()
            )
        ).isEmpty()
    }

    @Test
    fun methodCallIsUsedToLog() {
        assertThat(
            rule.compileAndLintWithContext(
                environment,
                """
import org.slf4j.LoggerFactory

val LOG = LoggerFactory.getLogger("")
fun foo() {
    LOG.debug("Hi")
}
                """.trimIndent()
            )
        ).singleElement()
            .matches {
                it.id == "LazyLog" && it.message == "Use the lambda version of LOG.debug instead"
            }
    }

    @Test
    fun lambdaIsUsedToLogButWithException() {
        assertThat(
            rule.compileAndLintWithContext(
                environment,
                """
import org.slf4j.LoggerFactory

val LOG = LoggerFactory.getLogger("")
fun foo() {
    val e = RuntimeException()
    LOG.debug(e) {"Hi" }
}
                """.trimIndent()
            )
        ).isEmpty()
    }

    @Test
    fun methodCallIsUsedToLogInUiTests() {
        assertThat(
            rule.compileAndLintWithContext(
                environment,
                """
package software.aws.toolkits.jetbrains.uitests.really.cool.test

import org.slf4j.LoggerFactory

val LOG = LoggerFactory.getLogger("")
fun foo() {
    LOG.debug("Hi")
}
                """.trimIndent()
            )
        ).isEmpty()
    }
}


// Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

package software.aws.toolkits.jetbrains.core

import com.intellij.openapi.application.ReadAction
import com.intellij.openapi.application.WriteAction
import com.intellij.openapi.util.Disposer
import com.intellij.testFramework.ApplicationRule
import com.intellij.testFramework.DisposableRule
import com.intellij.testFramework.runInEdtAndWait
import com.intellij.util.net.HttpConfigurable
import org.eclipse.jetty.proxy.ConnectHandler
import org.eclipse.jetty.proxy.ProxyServlet
import org.eclipse.jetty.server.Server
import org.eclipse.jetty.server.ServerConnector
import org.eclipse.jetty.servlet.ServletContextHandler
import org.eclipse.jetty.servlet.ServletHolder
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.mockito.kotlin.any
import org.mockito.kotlin.spy
import org.mockito.kotlin.times
import org.mockito.kotlin.verify
import software.amazon.awssdk.regions.Region
import software.amazon.awssdk.services.s3.S3Client

class AwsSdkClientProxyTest {
    @Rule
    @JvmField
    val application = ApplicationRule()

    @Rule
    @JvmField
    val disposableRule = DisposableRule()

    private val proxyServletSpy = spy(ConnectHandler())

    private lateinit var awsSdkClient: AwsSdkClient

    private val proxyServer = Server().also {
        it.addConnector(ServerConnector(it))
        it.handler = proxyServletSpy

        val context = ServletContextHandler(proxyServletSpy, "/", ServletContextHandler.SESSIONS)

        context.addServlet(ServletHolder(ProxyServlet()), "/*")
        it.start()
    }

    @Before
    fun setUp() {
        awsSdkClient = AwsSdkClient()
        Disposer.register(disposableRule.disposable, awsSdkClient)

        val httpConfigurable = HttpConfigurable.getInstance()
        httpConfigurable.USE_HTTP_PROXY = true
        httpConfigurable.PROXY_HOST = "localhost"
        httpConfigurable.PROXY_PORT = proxyServer.uri.port
    }

    @After
    fun tearDown() {
        HttpConfigurable.getInstance().USE_HTTP_PROXY = false

        proxyServer.stop()
        proxyServer.join()
    }

    @Test
    fun proxyIsBypassed() {
        HttpConfigurable.getInstance().USE_HTTP_PROXY = false

        makeAwsCall()

        verify(proxyServletSpy, times(0)).handle(any(), any(), any(), any())
    }

    @Test
    fun proxyCallIsMade() {
        makeAwsCall()

        verify(proxyServletSpy).handle(any(), any(), any(), any())
    }

    @Test(expected = AssertionError::class)
    fun callCantBeMadeOnEdt() {
        runInEdtAndWait {
            makeAwsCall()
        }
    }

    @Test(expected = AssertionError::class)
    fun callCantBeMadeInReadAction() {
        ReadAction.run<Nothing> {
            makeAwsCall()
        }
    }

    @Test(expected = AssertionError::class)
    fun callCantBeMadeInWriteAction() {
        runInEdtAndWait {
            WriteAction.run<Nothing> {
                makeAwsCall()
            }
        }
    }

    private fun makeAwsCall() {
        S3Client.builder()
            .region(Region.US_WEST_2)
            .httpClient(AwsSdkClient.getInstance().sharedSdkClient())
            .build().use {
                it.listBuckets()
            }
    }
}


// Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

package software.aws.toolkits.jetbrains.core.credentials.sso.bearer

import com.intellij.openapi.util.Disposer
import com.intellij.testFramework.ApplicationExtension
import org.assertj.core.api.Assertions.assertThat
import org.assertj.core.api.Assumptions.assumeThat
import org.junit.jupiter.api.MethodOrderer
import org.junit.jupiter.api.Order
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.TestMethodOrder
import org.junit.jupiter.api.condition.DisabledIfEnvironmentVariable
import org.junit.jupiter.api.extension.ExtendWith
import org.junit.jupiter.api.io.TempDir
import software.aws.toolkits.jetbrains.core.credentials.sono.SONO_REGION
import software.aws.toolkits.jetbrains.core.credentials.sono.SONO_URL
import software.aws.toolkits.jetbrains.core.credentials.sso.AccessTokenCacheKey
import software.aws.toolkits.jetbrains.core.credentials.sso.DiskCache
import software.aws.toolkits.jetbrains.utils.extensions.SsoLogin
import software.aws.toolkits.jetbrains.utils.extensions.SsoLoginExtension
import java.nio.file.Path
import java.time.Instant

@TestMethodOrder(MethodOrderer.OrderAnnotation::class)
@ExtendWith(ApplicationExtension::class, SsoLoginExtension::class)
@SsoLogin("codecatalyst-test-account")
@DisabledIfEnvironmentVariable(named = "IS_PROD", matches = "false")
class InteractiveBearerTokenProviderIntegrationTest {
    companion object {
        @JvmStatic
        @TempDir
        private lateinit var diskCachePath: Path

        private val testScopes = listOf("sso:account:access")
        private val diskCache by lazy { DiskCache(cacheDir = diskCachePath) }
        private val cacheKey = AccessTokenCacheKey(SONO_REGION, SONO_URL, testScopes)
    }

    @Test
    @Order(1)
    fun `test Builder ID login`() {
        val initialToken = diskCache.loadAccessToken(cacheKey)
        assertThat(initialToken).isNull()

        val sut = InteractiveBearerTokenProvider(
            startUrl = SONO_URL,
            region = SONO_REGION,
            scopes = testScopes,
            cache = diskCache
        )

        sut.reauthenticate()
        assertThat(sut.resolveToken()).isNotNull()

        Disposer.dispose(sut)
    }

    @Test
    @Order(2)
    fun `test token refresh`() {
        val initialToken = diskCache.loadAccessToken(cacheKey)
        assumeThat(initialToken).isNotNull

        diskCache.saveAccessToken(cacheKey, initialToken!!.copy(accessToken = "invalid", expiresAt = Instant.EPOCH))
        val sut = InteractiveBearerTokenProvider(
            startUrl = SONO_URL,
            region = SONO_REGION,
            scopes = testScopes,
            cache = diskCache
        )

        assertThat(sut.resolveToken()).satisfies {
            assertThat(it).isNotNull()
            assertThat(it).isNotEqualTo(initialToken)
        }

        Disposer.dispose(sut)
    }
}


// Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

package software.aws.toolkits.jetbrains.core.execution

import com.intellij.compiler.CompilerTestUtil
import com.intellij.execution.RunManager
import com.intellij.execution.application.ApplicationConfiguration
import com.intellij.execution.application.ApplicationConfigurationType
import com.intellij.openapi.application.runReadAction
import com.intellij.openapi.command.WriteCommandAction
import com.intellij.openapi.module.Module
import com.intellij.openapi.module.ModuleManager
import com.intellij.openapi.projectRoots.JavaSdk
import com.intellij.openapi.projectRoots.ProjectJdkTable
import com.intellij.openapi.projectRoots.impl.SdkConfigurationUtil
import com.intellij.openapi.roots.CompilerProjectExtension
import com.intellij.openapi.roots.ModuleRootModificationUtil
import com.intellij.openapi.vfs.LocalFileSystem
import com.intellij.openapi.vfs.newvfs.impl.VfsRootAccess
import com.intellij.testFramework.IdeaTestUtil
import com.intellij.testFramework.PlatformTestUtil
import com.intellij.testFramework.runInEdtAndWait
import org.assertj.core.api.Assertions.assertThat
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import software.aws.toolkits.jetbrains.core.compileProjectAndWait
import software.aws.toolkits.jetbrains.core.credentials.MockCredentialManagerRule
import software.aws.toolkits.jetbrains.core.region.MockRegionProviderRule
import software.aws.toolkits.jetbrains.utils.executeRunConfigurationAndWait
import software.aws.toolkits.jetbrains.utils.rules.ExperimentRule
import software.aws.toolkits.jetbrains.utils.rules.HeavyJavaCodeInsightTestFixtureRule
import software.aws.toolkits.jetbrains.utils.rules.addClass
import software.aws.toolkits.jetbrains.utils.rules.addModule

class JavaAwsConnectionExtensionIntegrationTest {

    @Before
    fun setUp() {
        CompilerTestUtil.enableExternalCompiler()
    }

    @After
    fun tearDown() {
        CompilerTestUtil.disableExternalCompiler(projectRule.project)
    }

    @Rule
    @JvmField
    val projectRule = HeavyJavaCodeInsightTestFixtureRule()

    @Rule
    @JvmField
    val regionProviderRule = MockRegionProviderRule()

    @Rule
    @JvmField
    val credentialManagerRule = MockCredentialManagerRule()

    @Rule
    @JvmField
    val experiment = ExperimentRule(JavaAwsConnectionExperiment)

    @Test
    fun connectionDetailsAreInjected() {
        val fixture = projectRule.fixture

        val module = fixture.addModule("main")

        val psiClass = fixture.addClass(
            module,
            """
            package com.example;

            public class AnyOldClass {
                public static void main(String[] args) {
                    System.out.println(System.getenv("AWS_REGION"));
                }
            }
            """
        )

        val mockRegion = regionProviderRule.createAwsRegion()
        val mockCredential = credentialManagerRule.createCredentialProvider()
        val runManager = RunManager.getInstance(projectRule.project)
        val configuration = runManager.createConfiguration("test", ApplicationConfigurationType::class.java)
        val runConfiguration = configuration.configuration as ApplicationConfiguration
        runConfiguration.putCopyableUserData(
            AWS_CONNECTION_RUN_CONFIGURATION_KEY,
            AwsCredentialInjectionOptions {
                region = mockRegion.id
                credential = mockCredential.id
            }
        )

        runReadAction {
            runConfiguration.setMainClass(psiClass)
        }

        compileModule(module)

        assertThat(executeRunConfigurationAndWait(runConfiguration).stdout).isEqualToIgnoringWhitespace(mockRegion.id)
    }

    private fun compileModule(module: Module) {
        setUpCompiler()
        compileProjectAndWait(module.project)
    }

    private fun setUpCompiler() {
        val project = projectRule.project
        val modules = ModuleManager.getInstance(project).modules

        WriteCommandAction.writeCommandAction(project).run<Nothing> {
            val compilerExtension = CompilerProjectExtension.getInstance(project)!!
            compilerExtension.compilerOutputUrl = projectRule.fixture.tempDirFixture.findOrCreateDir("out").url
            val jdkHome = IdeaTestUtil.requireRealJdkHome()
            VfsRootAccess.allowRootAccess(projectRule.fixture.testRootDisposable, jdkHome)
            val jdkHomeDir = LocalFileSystem.getInstance().refreshAndFindFileByPath(jdkHome)!!
            val jdkName = "Real JDK"
            val jdk = SdkConfigurationUtil.setupSdk(emptyArray(), jdkHomeDir, JavaSdk.getInstance(), false, null, jdkName)!!

            ProjectJdkTable.getInstance().addJdk(jdk, projectRule.fixture.testRootDisposable)

            for (module in modules) {
                ModuleRootModificationUtil.setModuleSdk(module, jdk)
            }
        }

        runInEdtAndWait {
            PlatformTestUtil.saveProject(project)
            CompilerTestUtil.saveApplicationSettings()
        }
    }
}


// Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

package software.aws.toolkits.jetbrains.core.execution

import com.intellij.execution.ExecutorRegistry
import com.intellij.execution.RunManager
import com.intellij.execution.executors.DefaultRunExecutor
import com.intellij.openapi.application.runWriteActionAndWait
import com.intellij.openapi.projectRoots.ProjectJdkTable
import com.intellij.openapi.util.Disposer
import com.intellij.openapi.util.use
import com.intellij.openapi.vfs.newvfs.impl.VfsRootAccess
import com.intellij.testFramework.DisposableRule
import com.intellij.util.SystemProperties
import com.jetbrains.python.run.PythonConfigurationType
import com.jetbrains.python.run.PythonRunConfiguration
import com.jetbrains.python.sdk.PyDetectedSdk
import com.jetbrains.python.sdk.detectSystemWideSdks
import org.assertj.core.api.Assertions.assertThat
import org.junit.Rule
import org.junit.Test
import software.aws.toolkits.jetbrains.core.credentials.MockCredentialManagerRule
import software.aws.toolkits.jetbrains.core.region.MockRegionProviderRule
import software.aws.toolkits.jetbrains.utils.executeRunConfigurationAndWait
import software.aws.toolkits.jetbrains.utils.rules.ExperimentRule
import software.aws.toolkits.jetbrains.utils.rules.PythonCodeInsightTestFixtureRule
import java.nio.file.FileSystems
import java.nio.file.Files
import java.nio.file.Paths
import kotlin.test.assertNotNull

class PythonAwsConnectionExtensionIntegrationTest {

    @Rule
    @JvmField
    val projectRule = PythonCodeInsightTestFixtureRule()

    @Rule
    @JvmField
    val regionProviderRule = MockRegionProviderRule()

    @Rule
    @JvmField
    val credentialManagerRule = MockCredentialManagerRule()

    @Rule
    @JvmField
    val experiment = ExperimentRule(PythonAwsConnectionExperiment)

    @Rule
    @JvmField
    val disposableRule = DisposableRule()

    @Test
    fun happyPathPythonConnectionInjection() {
        val file = projectRule.fixture.addFileToProject(
            "hello.py",
            """
            import os
            print(os.environ["AWS_REGION"])
            """.trimIndent()
        )

        val runManager = RunManager.getInstance(projectRule.project)
        val configuration = runManager.createConfiguration("test", PythonConfigurationType::class.java)
        val runConfiguration = configuration.configuration as PythonRunConfiguration

        lateinit var pythonExecutable: String
        Disposer.newDisposable().use { disposable ->
            // Allow us to search system for all pythons
            FileSystems.getDefault().rootDirectories.forEach { root ->
                Files.list(root).forEach {
                    VfsRootAccess.allowRootAccess(disposable, it.toString())
                }
            }

            pythonExecutable = detectSystemWideSdks(null, emptyList()).firstOrNull()?.homePath
                // hack for CI because we use pyenv and 221 changed detection logic
                ?: Paths.get(SystemProperties.getUserHome())
                    .resolve(".pyenv")
                    .resolve("versions")
                    .toFile().listFiles()!!.first()
                    .resolve("bin")
                    .resolve("python")
                    .path
        }

        assertThat(pythonExecutable).isNotEmpty
        runWriteActionAndWait {
            ProjectJdkTable.getInstance().addJdk(PyDetectedSdk(pythonExecutable), disposableRule.disposable)
        }
        runConfiguration.scriptName = file.virtualFile.path
        runConfiguration.sdkHome = pythonExecutable
        val mockRegion = regionProviderRule.createAwsRegion()
        val mockCredential = credentialManagerRule.createCredentialProvider()

        runConfiguration.putCopyableUserData<AwsCredentialInjectionOptions>(
            AWS_CONNECTION_RUN_CONFIGURATION_KEY,
            AwsCredentialInjectionOptions {
                region = mockRegion.id
                credential = mockCredential.id
            }
        )

        VfsRootAccess.allowRootAccess(projectRule.fixture.testRootDisposable, pythonExecutable)

        val executor = ExecutorRegistry.getInstance().getExecutorById(DefaultRunExecutor.EXECUTOR_ID)
        assertNotNull(executor)

        assertThat(executeRunConfigurationAndWait(runConfiguration).stdout).isEqualToIgnoringWhitespace(mockRegion.id)
    }
}


// Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

package software.aws.toolkits.jetbrains.services.codewhisperer

import com.intellij.testFramework.runInEdtAndWait
import org.assertj.core.api.Assertions.assertThat
import org.junit.Test
import software.aws.toolkits.jetbrains.services.codewhisperer.CodeWhispererTestUtil.cppFileName
import software.aws.toolkits.jetbrains.services.codewhisperer.CodeWhispererTestUtil.cppTestLeftContext
import software.aws.toolkits.jetbrains.services.codewhisperer.codescan.sessionconfig.CodeScanSessionConfig
import software.aws.toolkits.jetbrains.utils.rules.RunWithRealCredentials.RequiresRealCredentials
import software.aws.toolkits.resources.message

@RequiresRealCredentials
class CodeWhispererCodeScanIntegrationTest : CodeWhispererIntegrationTestBase() {
    private val filePromptWithSecurityIssues = """
        from flask import app

        @app.route('/')
        def execute_input_noncompliant():
            from flask import request
            module_version = request.args.get("module_version")
            # Noncompliant: executes unsanitized inputs.
            exec("import urllib%s as urllib" % module_version)

        @app.route('/')
        def execute_input_compliant():
            from flask import request
            module_version = request.args.get("module_version")
            # Compliant: executes sanitized inputs.
            exec("import urllib%d as urllib" % int(module_version))
    """.trimIndent()

    @Test
    fun testCodeScanValidWithIssues() {
        projectRule.fixture.addFileToProject("test2.py", filePromptWithSecurityIssues)
        val response = runCodeScan()
        assertThat(response.issues.size).isEqualTo(3)
        assertThat(response.responseContext.codeScanTotalIssues).isEqualTo(3)
        assertThat(response.responseContext.codeScanJobId).isNotNull
    }

    @Test
    fun testCodeScanValidWithNoIssues() {
        val response = runCodeScan()
        assertThat(response.issues.size).isEqualTo(0)
        assertThat(response.responseContext.codeScanTotalIssues).isEqualTo(0)
        assertThat(response.responseContext.codeScanJobId).isNotNull
    }

    @Test
    fun testCodeScanFileTooLarge() {
        val largePrompt = "a".repeat(1024 * 300)
        val file = projectRule.fixture.addFileToProject("test2.py", largePrompt)
        runInEdtAndWait {
            projectRule.fixture.openFileInEditor(file.virtualFile)
        }
        testCodeScanWithErrorMessage(
            message(
                "codewhisperer.codescan.file_too_large",
                CodeScanSessionConfig.create(file.virtualFile, projectRule.project).getPresentablePayloadLimit()
            )
        )
    }

    @Test
    fun testCodeScanUnsupportedLanguage() {
        val file = projectRule.fixture.addFileToProject(cppFileName, cppTestLeftContext)
        runInEdtAndWait {
            projectRule.fixture.openFileInEditor(file.virtualFile)
        }
        testCodeScanWithErrorMessage(
            message("codewhisperer.codescan.file_ext_not_supported", file.virtualFile.extension ?: "")
        )
    }
}


// Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

package software.aws.toolkits.jetbrains.services.codewhisperer

import com.intellij.testFramework.runInEdtAndWait
import org.junit.Test
import software.aws.toolkits.jetbrains.services.codewhisperer.CodeWhispererTestUtil.javaTestContext
import software.aws.toolkits.jetbrains.utils.rules.HeavyJavaCodeInsightTestFixtureRule
import software.aws.toolkits.jetbrains.utils.rules.RunWithRealCredentials.RequiresRealCredentials
import software.aws.toolkits.jetbrains.utils.rules.addClass
import software.aws.toolkits.jetbrains.utils.rules.addModule
import software.aws.toolkits.resources.message

@RequiresRealCredentials
class CodeWhispererCodeScanJavaIntegrationTest : CodeWhispererIntegrationTestBase(HeavyJavaCodeInsightTestFixtureRule()) {
    @Test
    fun testCodeScanJavaProjectNoBuild() {
        projectRule as HeavyJavaCodeInsightTestFixtureRule
        val module = projectRule.fixture.addModule("main")

        val psiClass = projectRule.fixture.addClass(module, javaTestContext)
        runInEdtAndWait {
            projectRule.fixture.openFileInEditor(psiClass.containingFile.virtualFile)
        }
        testCodeScanWithErrorMessage(message("codewhisperer.codescan.build_artifacts_not_found"))
    }
}


// Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

package software.aws.toolkits.jetbrains.services.codewhisperer

import org.assertj.core.api.Assertions.assertThat
import org.junit.Test
import org.junit.jupiter.api.assertDoesNotThrow
import org.mockito.kotlin.any
import org.mockito.kotlin.never
import org.mockito.kotlin.verify
import software.aws.toolkits.jetbrains.services.codewhisperer.CodeWhispererTestUtil.cppFileName
import software.aws.toolkits.jetbrains.services.codewhisperer.service.CodeWhispererService
import software.aws.toolkits.jetbrains.utils.rules.RunWithRealCredentials.RequiresRealCredentials
import software.aws.toolkits.resources.message

@RequiresRealCredentials
class CodeWhispererCompletionIntegrationTest : CodeWhispererIntegrationTestBase() {
    @Test
    fun testInvokeCompletionManualTrigger() {
        assertDoesNotThrow {
            withCodeWhispererServiceInvokedAndWait { response ->
                val requestId = response.responseMetadata().requestId()
                assertThat(requestId).isNotNull
                val sessionId = response.sdkHttpResponse().headers().getOrDefault(
                    CodeWhispererService.KET_SESSION_ID,
                    listOf(requestId)
                )[0]
                assertThat(sessionId).isNotNull
            }
        }
    }

    @Test
    fun testInvokeCompletionAutoTrigger() {
        assertDoesNotThrow {
            stateManager.setAutoEnabled(true)
            withCodeWhispererServiceInvokedAndWait(false) { response ->
                val requestId = response.responseMetadata().requestId()
                assertThat(requestId).isNotNull
                val sessionId = response.sdkHttpResponse().headers().getOrDefault(
                    CodeWhispererService.KET_SESSION_ID,
                    listOf(requestId)
                )[0]
                assertThat(sessionId).isNotNull
            }
        }
    }

    @Test
    fun testInvokeCompletionUnsupportedLanguage() {
        val file = setFileContext(cppFileName, CodeWhispererTestUtil.cppTestLeftContext, "")
        assertDoesNotThrow {
            invokeCodeWhispererService()
            verify(popupManager, never()).showPopup(any(), any(), any(), any(), any())
            verify(clientAdaptor, never()).generateCompletionsPaginator(any())
            testMessageShown(message("codewhisperer.language.error", file.fileType.name))
        }
    }
}


// Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

package software.aws.toolkits.jetbrains.services.codewhisperer

import com.intellij.analysis.problemsView.toolWindow.ProblemsView
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.wm.RegisterToolWindowTask
import com.intellij.openapi.wm.ToolWindowManager
import com.intellij.psi.PsiFile
import com.intellij.testFramework.DisposableRule
import com.intellij.testFramework.RuleChain
import com.intellij.testFramework.replaceService
import com.intellij.testFramework.runInEdtAndWait
import kotlinx.coroutines.runBlocking
import org.assertj.core.api.Assertions.assertThat
import org.junit.After
import org.junit.Assume.assumeTrue
import org.junit.Before
import org.junit.Rule
import org.mockito.kotlin.any
import org.mockito.kotlin.anyOrNull
import org.mockito.kotlin.argumentCaptor
import org.mockito.kotlin.atLeastOnce
import org.mockito.kotlin.doNothing
import org.mockito.kotlin.spy
import org.mockito.kotlin.timeout
import org.mockito.kotlin.times
import org.mockito.kotlin.verify
import org.mockito.kotlin.whenever
import software.amazon.awssdk.services.codewhispererruntime.model.GenerateCompletionsResponse
import software.aws.toolkits.core.TokenConnectionSettings
import software.aws.toolkits.core.credentials.ToolkitBearerTokenProvider
import software.aws.toolkits.jetbrains.core.MockClientManager
import software.aws.toolkits.jetbrains.core.credentials.ToolkitAuthManager
import software.aws.toolkits.jetbrains.core.credentials.loginSso
import software.aws.toolkits.jetbrains.core.credentials.sono.CODEWHISPERER_SCOPES
import software.aws.toolkits.jetbrains.core.credentials.sono.SONO_REGION
import software.aws.toolkits.jetbrains.core.credentials.sono.SONO_URL
import software.aws.toolkits.jetbrains.core.credentials.sso.bearer.BearerTokenProvider
import software.aws.toolkits.jetbrains.services.codewhisperer.CodeWhispererTestUtil.codeWhispererRecommendationActionId
import software.aws.toolkits.jetbrains.services.codewhisperer.CodeWhispererTestUtil.pythonFileName
import software.aws.toolkits.jetbrains.services.codewhisperer.CodeWhispererTestUtil.pythonTestLeftContext
import software.aws.toolkits.jetbrains.services.codewhisperer.codescan.CodeScanResponse
import software.aws.toolkits.jetbrains.services.codewhisperer.codescan.CodeWhispererCodeScanException
import software.aws.toolkits.jetbrains.services.codewhisperer.codescan.CodeWhispererCodeScanIssue
import software.aws.toolkits.jetbrains.services.codewhisperer.codescan.CodeWhispererCodeScanManager
import software.aws.toolkits.jetbrains.services.codewhisperer.credentials.CodeWhispererClientAdaptor
import software.aws.toolkits.jetbrains.services.codewhisperer.explorer.CodeWhispererExploreActionState
import software.aws.toolkits.jetbrains.services.codewhisperer.explorer.CodeWhispererExploreStateType
import software.aws.toolkits.jetbrains.services.codewhisperer.explorer.CodeWhispererExplorerActionManager
import software.aws.toolkits.jetbrains.services.codewhisperer.model.CodeScanTelemetryEvent
import software.aws.toolkits.jetbrains.services.codewhisperer.model.InvocationContext
import software.aws.toolkits.jetbrains.services.codewhisperer.popup.CodeWhispererPopupManager
import software.aws.toolkits.jetbrains.services.codewhisperer.service.CodeWhispererInvocationStatus
import software.aws.toolkits.jetbrains.services.codewhisperer.service.CodeWhispererService
import software.aws.toolkits.jetbrains.services.codewhisperer.settings.CodeWhispererConfiguration
import software.aws.toolkits.jetbrains.services.codewhisperer.settings.CodeWhispererConfigurationType
import software.aws.toolkits.jetbrains.services.codewhisperer.settings.CodeWhispererSettings
import software.aws.toolkits.jetbrains.services.codewhisperer.telemetry.CodeWhispererTelemetryService
import software.aws.toolkits.jetbrains.utils.rules.CodeInsightTestFixtureRule
import software.aws.toolkits.jetbrains.utils.rules.PythonCodeInsightTestFixtureRule
import software.aws.toolkits.jetbrains.utils.rules.RunWithRealCredentials

open class CodeWhispererIntegrationTestBase(val projectRule: CodeInsightTestFixtureRule = PythonCodeInsightTestFixtureRule()) {

    private val realCredentials = RunWithRealCredentials(projectRule)
    internal val disposableRule = DisposableRule()

    @Rule
    @JvmField
    val ruleChain = RuleChain(projectRule, disposableRule, realCredentials)

    protected lateinit var popupManager: CodeWhispererPopupManager
    protected lateinit var clientAdaptor: CodeWhispererClientAdaptor
    protected lateinit var stateManager: CodeWhispererExplorerActionManager
    protected lateinit var codewhispererService: CodeWhispererService
    protected lateinit var settingsManager: CodeWhispererSettings
    private lateinit var originalExplorerActionState: CodeWhispererExploreActionState
    private lateinit var originalSettings: CodeWhispererConfiguration
    internal lateinit var scanManager: CodeWhispererCodeScanManager
    protected lateinit var telemetryServiceSpy: CodeWhispererTelemetryService

    @Suppress("UnreachableCode")
    @Before
    open fun setUp() {
        assumeTrue("CI doesn't have Builder ID credentials", System.getenv("CI").isNullOrBlank())
        MockClientManager.useRealImplementations(disposableRule.disposable)

        loginSso(projectRule.project, SONO_URL, SONO_REGION, CODEWHISPERER_SCOPES)
        val connectionId = ToolkitBearerTokenProvider.ssoIdentifier(SONO_URL)
        val connection = ToolkitAuthManager.getInstance().getConnection(connectionId) ?: return
        val tokenProvider = (connection.getConnectionSettings() as TokenConnectionSettings).tokenProvider.delegate as BearerTokenProvider
        tokenProvider.resolveToken()

        ToolWindowManager.getInstance(projectRule.project).registerToolWindow(
            RegisterToolWindowTask(id = ProblemsView.ID, canWorkInDumbMode = true)
        )

        scanManager = spy(CodeWhispererCodeScanManager.getInstance(projectRule.project))
        doNothing().whenever(scanManager).addCodeScanUI(any())
        projectRule.project.replaceService(CodeWhispererCodeScanManager::class.java, scanManager, disposableRule.disposable)

        telemetryServiceSpy = spy(CodeWhispererTelemetryService.getInstance())
        ApplicationManager.getApplication().replaceService(CodeWhispererTelemetryService::class.java, telemetryServiceSpy, disposableRule.disposable)

        stateManager = CodeWhispererExplorerActionManager.getInstance()
        stateManager.setAutoEnabled(false)

        popupManager = spy(CodeWhispererPopupManager.getInstance())
        popupManager.reset()
        doNothing().whenever(popupManager).showPopup(any(), any(), any(), any(), any())
        ApplicationManager.getApplication().replaceService(CodeWhispererPopupManager::class.java, popupManager, disposableRule.disposable)

        codewhispererService = spy(CodeWhispererService.getInstance())
        ApplicationManager.getApplication().replaceService(CodeWhispererService::class.java, codewhispererService, disposableRule.disposable)

        settingsManager = CodeWhispererSettings.getInstance()

        clientAdaptor = spy(CodeWhispererClientAdaptor.getInstance(projectRule.project))
        projectRule.project.replaceService(CodeWhispererClientAdaptor::class.java, clientAdaptor, disposableRule.disposable)

        originalExplorerActionState = stateManager.state
        originalSettings = settingsManager.state
        stateManager.loadState(
            CodeWhispererExploreActionState().apply {
                CodeWhispererExploreStateType.values().forEach {
                    value[it] = true
                }
            }
        )
        settingsManager.loadState(
            CodeWhispererConfiguration().apply {
                value[CodeWhispererConfigurationType.IsIncludeCodeWithReference] = true
            }
        )

        setFileContext(pythonFileName, pythonTestLeftContext, "")
    }

    @After
    open fun tearDown() {
        runInEdtAndWait {
            if (::stateManager.isInitialized) {
                stateManager.loadState(originalExplorerActionState)
            }

            if (::settingsManager.isInitialized) {
                settingsManager.loadState(originalSettings)
            }

            if (::popupManager.isInitialized) {
                popupManager.reset()
            }
        }
    }

    fun withCodeWhispererServiceInvokedAndWait(manual: Boolean = true, runnable: (GenerateCompletionsResponse) -> Unit) {
        val responseCaptor = argumentCaptor<GenerateCompletionsResponse>()
        val statesCaptor = argumentCaptor<InvocationContext>()
        invokeCodeWhispererService(manual)
        verify(codewhispererService, timeout(5000).atLeastOnce()).validateResponse(responseCaptor.capture())
        val response = responseCaptor.lastValue
        verify(popupManager, timeout(5000).atLeastOnce()).showPopup(statesCaptor.capture(), any(), any(), any(), any())
        val states = statesCaptor.lastValue

        runInEdtAndWait {
            try {
                runnable(response)
            } finally {
                CodeWhispererPopupManager.getInstance().closePopup(states.popup)
            }
        }
    }

    fun invokeCodeWhispererService(manual: Boolean = true) {
        if (manual) {
            runInEdtAndWait {
                projectRule.fixture.performEditorAction(codeWhispererRecommendationActionId)
            }
        } else {
            runInEdtAndWait {
                projectRule.fixture.type('(')
            }
        }
        while (CodeWhispererInvocationStatus.getInstance().hasExistingInvocation()) {
            Thread.sleep(10)
        }
    }

    fun setFileContext(filename: String, leftContext: String, rightContext: String): PsiFile {
        val file = projectRule.fixture.configureByText(filename, leftContext + rightContext)
        runInEdtAndWait {
            projectRule.fixture.editor.caretModel.primaryCaret.moveToOffset(leftContext.length)
        }
        return file
    }

    fun runCodeScan(success: Boolean = true): CodeScanResponse {
        runInEdtAndWait {
            projectRule.fixture.performEditorAction(CodeWhispererTestUtil.codeWhispererCodeScanActionId)
        }
        val issuesCaptor = argumentCaptor<List<CodeWhispererCodeScanIssue>>()
        val codeScanEventCaptor = argumentCaptor<CodeScanTelemetryEvent>()
        return runBlocking {
            var issues = emptyList<CodeWhispererCodeScanIssue>()
            if (success) {
                verify(scanManager, timeout(60000).atLeastOnce()).renderResponseOnUIThread(issuesCaptor.capture(), any(), any())
                issues = issuesCaptor.lastValue
            }
            verify(telemetryServiceSpy, timeout(60000).atLeastOnce()).sendSecurityScanEvent(codeScanEventCaptor.capture(), anyOrNull())
            val codeScanResponseContext = codeScanEventCaptor.lastValue.codeScanResponseContext
            CodeScanResponse.Success(issues, codeScanResponseContext)
        }
    }

    fun testCodeScanWithErrorMessage(message: String) {
        val response = runCodeScan(success = false)
        assertThat(response.issues.size).isEqualTo(0)
        assertThat(response.responseContext.codeScanTotalIssues).isEqualTo(0)
        assertThat(response.responseContext.codeScanJobId).isNull()
        val exceptionCaptor = argumentCaptor<Exception>()
        verify(scanManager, atLeastOnce()).handleException(any(), exceptionCaptor.capture())
        val e = exceptionCaptor.lastValue
        assertThat(e is CodeWhispererCodeScanException).isTrue
        assertThat(e.message).isEqualTo(message)
    }

    fun testMessageShown(message: String, info: Boolean = true) {
        val messageCaptor = argumentCaptor<String>()
        if (info) {
            verify(codewhispererService, timeout(5000).times(1))
                .showCodeWhispererInfoHint(any(), messageCaptor.capture())
        } else {
            verify(codewhispererService, timeout(5000).times(1))
                .showCodeWhispererErrorHint(any(), messageCaptor.capture())
        }
        assertThat(messageCaptor.lastValue).isEqualTo(message)
    }
}


// Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

package software.aws.toolkits.jetbrains.services.codewhisperer

import org.assertj.core.api.Assertions.assertThat
import org.junit.Before
import org.junit.Test
import org.junit.jupiter.api.assertDoesNotThrow
import org.mockito.kotlin.any
import org.mockito.kotlin.never
import org.mockito.kotlin.verify
import software.aws.toolkits.jetbrains.services.codewhisperer.CodeWhispererTestUtil.jsFileName
import software.aws.toolkits.jetbrains.services.codewhisperer.service.CodeWhispererService
import software.aws.toolkits.jetbrains.utils.rules.RunWithRealCredentials.RequiresRealCredentials
import software.aws.toolkits.resources.message

@RequiresRealCredentials
class CodeWhispererReferenceTrackerIntegrationTest : CodeWhispererIntegrationTestBase() {
    private val leftContextWithReference = """
InAuto.GetContent(
    InAuto.servers.auto, "vendors.json", function (data) {
        let block = '';
        for(let i = 0; i < data.length; i++) {
            block += '' + cars[i].title + '';
        }
        ${'$'}('#cars').html(block);
    }
);
    """.trimIndent()

    @Before
    override fun setUp() {
        super.setUp()
        setFileContext(jsFileName, leftContextWithReference, rightContextWithReference)
    }

    @Test
    fun testInvokeCompletionWithReference() {
        assertDoesNotThrow {
            settingsManager.toggleIncludeCodeWithReference(true)
            withCodeWhispererServiceInvokedAndWait { response ->
                val requestId = response.responseMetadata().requestId()
                assertThat(requestId).isNotNull
                val sessionId = response.sdkHttpResponse().headers().getOrDefault(
                    CodeWhispererService.KET_SESSION_ID,
                    listOf(requestId)
                )[0]
                assertThat(sessionId).isNotNull
                assertThat(response.hasCompletions()).isTrue
                assertThat(response.completions()).isNotEmpty
                assertThat(response.completions()[0].hasReferences()).isTrue
            }
        }
    }

    @Test
    fun testInvokeCompletionWithReferenceWithReferenceSettingDisabled() {
        assertDoesNotThrow {
            settingsManager.toggleIncludeCodeWithReference(false)
            invokeCodeWhispererService()
            verify(popupManager, never()).showPopup(any(), any(), any(), any(), any())
            testMessageShown(message("codewhisperer.popup.no_recommendations"))
        }
    }
}


// Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

package software.aws.toolkits.jetbrains.services.ecr

object EcrIntegrationTestUtils {
    fun getImagePrefix(imageId: String): String = imageId
}


// Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

package software.aws.toolkits.jetbrains.services.ecr

import com.intellij.testFramework.ProjectRule
import kotlinx.coroutines.future.await
import kotlinx.coroutines.runBlocking
import org.assertj.core.api.Assertions.assertThat
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.rules.TemporaryFolder
import software.amazon.awssdk.regions.Region
import software.amazon.awssdk.services.ecr.EcrClient
import software.aws.toolkits.core.rules.EcrTemporaryRepositoryRule
import software.aws.toolkits.jetbrains.core.docker.ToolkitDockerAdapter
import software.aws.toolkits.jetbrains.core.docker.getDockerServerRuntimeFacade
import software.aws.toolkits.jetbrains.services.ecr.resources.Repository
import java.util.UUID

class EcrPullIntegrationTest {
    private val ecrClient = EcrClient.builder()
        .region(Region.US_WEST_2)
        .build()

    @Rule
    @JvmField
    val projectRule = ProjectRule()

    @Rule
    @JvmField
    val folder = TemporaryFolder()

    @Rule
    @JvmField
    val ecrRule = EcrTemporaryRepositoryRule(ecrClient)

    private lateinit var remoteRepo: Repository

    @Before
    fun setUp() {
        remoteRepo = ecrRule.createRepository().toToolkitEcrRepository()!!
    }

    @Test
    fun testPullImage() {
        val remoteTag = UUID.randomUUID().toString()

        val dockerfile = folder.newFile()
        dockerfile.writeText(
            """
                # arbitrary base image with a shell
                FROM public.ecr.aws/docker/library/alpine:latest
                RUN touch $(date +%s)
            """.trimIndent()
        )

        val project = projectRule.project
        runBlocking {
            val serverRuntime = getDockerServerRuntimeFacade(project)
            val ecrLogin = ecrClient.authorizationToken.authorizationData().first().getDockerLogin()
            val dockerAdapter = ToolkitDockerAdapter(project, serverRuntime)
            val imageId = dockerAdapter.buildLocalImage(dockerfile)!!

            // gross transform because we only have the short SHA right now
            val localImage = serverRuntime.agent.getImages(null).first { it.imageId.startsWith(EcrIntegrationTestUtils.getImagePrefix(imageId)) }
            val localImageId = localImage.imageId
            val config = EcrUtils.buildDockerRepositoryModel(ecrLogin, remoteRepo, remoteTag)
            val pushRequest = ImageEcrPushRequest(
                serverRuntime,
                localImageId,
                remoteRepo,
                remoteTag
            )
            // push up and image and then delete the local tag
            EcrUtils.pushImage(projectRule.project, ecrLogin, pushRequest).await()
            localImage.deleteImage().await()
            assertThat(serverRuntime.agent.getImages(null).firstOrNull { it.imageId == localImageId }).isNull()

            // pull it from the remote
            dockerAdapter.pullImage(config).await()
            assertThat(serverRuntime.agent.getImages(null).firstOrNull { it.imageId == localImageId }).isNotNull()
        }
    }

    // FIX_WHEN_MIN_IS_231: deleteImage() is blocking prior to 231
    private fun Unit.await() {}
}


// Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

package software.aws.toolkits.jetbrains.services.ecr

import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import com.intellij.testFramework.ProjectRule
import kotlinx.coroutines.future.await
import kotlinx.coroutines.runBlocking
import org.assertj.core.api.Assertions.assertThat
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.rules.TemporaryFolder
import software.amazon.awssdk.regions.Region
import software.amazon.awssdk.services.ecr.EcrClient
import software.amazon.awssdk.services.ecr.model.Image
import software.amazon.awssdk.services.ecr.model.ImageIdentifier
import software.aws.toolkits.core.rules.EcrTemporaryRepositoryRule
import software.aws.toolkits.jetbrains.core.docker.ToolkitDockerAdapter
import software.aws.toolkits.jetbrains.core.docker.getDockerServerRuntimeFacade
import software.aws.toolkits.jetbrains.services.ecr.resources.Repository
import java.util.UUID

class EcrPushIntegrationTest {
    private val ecrClient = EcrClient.builder()
        .region(Region.US_WEST_2)
        .build()

    @Rule
    @JvmField
    val projectRule = ProjectRule()

    @Rule
    @JvmField
    val folder = TemporaryFolder()

    @Rule
    @JvmField
    val ecrRule = EcrTemporaryRepositoryRule(ecrClient)

    private lateinit var remoteRepo: Repository

    @Before
    fun setUp() {
        remoteRepo = ecrRule.createRepository().toToolkitEcrRepository()!!
    }

    @Test
    fun testPush() {
        val remoteTag = UUID.randomUUID().toString()

        val dockerfile = folder.newFile()
        dockerfile.writeText(
            """
                # arbitrary base image with a shell
                FROM public.ecr.aws/docker/library/alpine:latest
                RUN touch $(date +%s)
            """.trimIndent()
        )

        val project = projectRule.project
        runBlocking {
            val serverRuntime = getDockerServerRuntimeFacade(project)
            val ecrLogin = ecrClient.authorizationToken.authorizationData().first().getDockerLogin()
            val dockerAdapter = ToolkitDockerAdapter(project, serverRuntime)
            val imageId = dockerAdapter.buildLocalImage(dockerfile)!!

            // gross transform because we only have the short SHA right now
            val localImage = serverRuntime.agent.getImages(null).first { it.imageId.startsWith(EcrIntegrationTestUtils.getImagePrefix(imageId)) }
            val localImageId = localImage.imageId
            val pushRequest = ImageEcrPushRequest(
                serverRuntime,
                localImageId,
                remoteRepo,
                remoteTag
            )
            EcrUtils.pushImage(projectRule.project, ecrLogin, pushRequest).await()

            assertThat(
                ecrClient.batchGetImage {
                    it.repositoryName(remoteRepo.repositoryName)
                    it.imageIds(ImageIdentifier.builder().imageTag(remoteTag).build())
                }.images()
            )
                .hasSize(1)
                .allSatisfy { image ->
                    assertDigestFromDockerManifest(image, localImageId)
                }
        }
    }

    @Test
    fun testPushFromDockerfile() {
        val remoteTag = UUID.randomUUID().toString()

        val dockerfile = folder.newFile()
        dockerfile.writeText(
            """
                # arbitrary base image with a shell
                FROM public.ecr.aws/docker/library/alpine:latest
                RUN touch $(date +%s)
            """.trimIndent()
        )

        val ecrLogin = ecrClient.authorizationToken.authorizationData().first().getDockerLogin()
        val config = EcrUtils.dockerRunConfigurationFromPath(projectRule.project, remoteTag, dockerfile.absolutePath)
        val pushRequest = DockerfileEcrPushRequest(
            config.configuration as DockerRunConfiguration,
            remoteRepo,
            remoteTag
        )
        runBlocking {
            EcrUtils.pushImage(projectRule.project, ecrLogin, pushRequest).await()

            // find our local image id
            val serverRuntime = getDockerServerRuntimeFacade(projectRule.project)
            val localImageId = serverRuntime.agent.getImages(null).first { it.imageRepoTags.contains("${remoteRepo.repositoryUri}:$remoteTag") }.imageId

            assertThat(
                ecrClient.batchGetImage {
                    it.repositoryName(remoteRepo.repositoryName)
                    it.imageIds(ImageIdentifier.builder().imageTag(remoteTag).build())
                }.images()
            )
                .hasSize(1)
                .allSatisfy { image ->
                    assertDigestFromDockerManifest(image, localImageId)
                }
        }
    }

    private fun assertDigestFromDockerManifest(image: Image, imageId: String) {
        // inspect the manifest because the registry digest is not the same as the image id
        // https://github.com/docker/hub-feedback/issues/1925
        val node = objectMapper.readTree(image.imageManifest())
        assertThat(node.get("config").get("digest").asText()).isEqualTo(imageId)
    }

    companion object {
        val objectMapper = jacksonObjectMapper()
    }
}


// Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

package software.aws.toolkits.jetbrains.services.federation

import com.intellij.testFramework.TestApplicationManager
import com.intellij.util.io.HttpRequests
import org.assertj.core.api.Assertions.assertThat
import org.junit.Assume.assumeFalse
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.Parameterized
import software.amazon.awssdk.auth.credentials.ProfileCredentialsProvider
import software.aws.toolkits.core.ConnectionSettings
import software.aws.toolkits.core.region.AwsRegion
import software.aws.toolkits.jetbrains.core.credentials.MockCredentialManagerRule
import software.aws.toolkits.jetbrains.core.region.AwsRegionProvider

@RunWith(Parameterized::class)
class AwsConsoleUrlFactoryIntegrationTest(@Suppress("UNUSED_PARAMETER") regionId: String, private val region: AwsRegion) {
    companion object {
        @JvmStatic
        @Parameterized.Parameters(name = "{0}")
        fun data(): Collection<Array<Any>> {
            // hack because parameters are evalutaed before rules https://github.com/junit-team/junit4/issues/671
            TestApplicationManager.getInstance()

            return AwsRegionProvider().allRegions().values.sortedWith(compareBy<AwsRegion> { it.partitionId }.thenBy { it.id })
                .map { arrayOf(it.id, it) }
        }
    }

    @Rule
    @JvmField
    val credRule = MockCredentialManagerRule()

    /**
     * There is currently no good way to test this in our integration CI fleet, so this test suite only runs locally
     */
    @Test
    fun `can sign-in`() {
        val profileName = when (region.partitionId) {
            // define these environment variables to test signin for the given partition
            "aws" -> System.getenv("AWS_CLASSIC_TEST_PROFILE")
            "aws-us-gov" -> System.getenv("AWS_GOV_TEST_PROFILE")
            "aws-cn" -> System.getenv("AWS_CN_TEST_PROFILE")
            else -> throw RuntimeException("Region partition is unknown for $region")
        }
        assumeFalse("Skipping console sign-in test for $region since a credentials profile was not available", profileName.isNullOrBlank())

        val credProvider = credRule.createCredentialProvider(profileName, ProfileCredentialsProvider.create(profileName).resolveCredentials())
        val credSettings = ConnectionSettings(credProvider, region)
        val signinUrl = AwsConsoleUrlFactory.getSigninUrl(credSettings, destination = "")
        val responseCode = HttpRequests.request(signinUrl)
            // don't throw because it'll print the signin token as part of the exception
            .throwStatusCodeException(false)
            .tryConnect()

        assertThat(responseCode).isGreaterThanOrEqualTo(200).isLessThan(400)
    }
}


// Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

package software.aws.toolkits.jetbrains.services.lambda.deploy

import com.intellij.openapi.vfs.VirtualFile
import com.intellij.testFramework.RuleChain
import com.intellij.testFramework.runInEdtAndGet
import com.intellij.util.ExceptionUtil
import org.assertj.core.api.Assertions.assertThat
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import software.amazon.awssdk.services.cloudformation.CloudFormationClient
import software.amazon.awssdk.services.cloudformation.model.Parameter
import software.amazon.awssdk.services.cloudformation.model.Tag
import software.aws.toolkits.core.rules.EcrTemporaryRepositoryRule
import software.aws.toolkits.core.rules.S3TemporaryBucketRule
import software.aws.toolkits.jetbrains.core.awsClient
import software.aws.toolkits.jetbrains.services.lambda.steps.DeployLambda
import software.aws.toolkits.jetbrains.services.lambda.steps.createDeployWorkflow
import software.aws.toolkits.jetbrains.utils.assumeImageSupport
import software.aws.toolkits.jetbrains.utils.execution.steps.ConsoleViewWorkflowEmitter
import software.aws.toolkits.jetbrains.utils.execution.steps.StepExecutor
import software.aws.toolkits.jetbrains.utils.readProject
import software.aws.toolkits.jetbrains.utils.rules.HeavyJavaCodeInsightTestFixtureRule
import software.aws.toolkits.jetbrains.utils.rules.RunWithRealCredentials
import software.aws.toolkits.jetbrains.utils.rules.RunWithRealCredentials.RequiresRealCredentials
import software.aws.toolkits.jetbrains.utils.rules.addModule
import software.aws.toolkits.jetbrains.utils.setSamExecutableFromEnvironment
import java.io.File
import java.nio.file.Paths
import java.util.UUID
import java.util.concurrent.TimeUnit

@RequiresRealCredentials
class SamDeployTest {
    private val largeTemplateLocation = Paths.get(System.getProperty("testDataPath"), "testFiles", "LargeTemplate.yml").toString()
    private val projectRule = HeavyJavaCodeInsightTestFixtureRule()
    private val bucketRule = S3TemporaryBucketRule { projectRule.project.awsClient() }
    private val repositoryRule = EcrTemporaryRepositoryRule { projectRule.project.awsClient() }
    private val realCredentials = RunWithRealCredentials(projectRule)

    @Rule
    @JvmField
    val ruleChain = RuleChain(
        projectRule,
        realCredentials,
        repositoryRule,
        bucketRule
    )

    @Before
    fun setUp() {
        setSamExecutableFromEnvironment()

        // we need at least one module for deploy image (for read project)
        projectRule.fixture.addModule("main")
    }

    @Test
    fun deployAppUsingSam() {
        val stackName = "SamDeployTest-${UUID.randomUUID()}"
        val templateFile = setUpProject()
        runAssertsAndClean(stackName) {
            val changeSetArn = createChangeSet(templateFile, stackName, hasImage = false)

            assertThat(changeSetArn).isNotNull
            val describeChangeSetResponse = projectRule.project.awsClient<CloudFormationClient>().describeChangeSet {
                it.stackName(stackName)
                it.changeSetName(changeSetArn)
            }

            assertThat(describeChangeSetResponse).isNotNull
            assertThat(describeChangeSetResponse.parameters()).contains(
                Parameter.builder()
                    .parameterKey("TestParameter")
                    .parameterValue("HelloWorld")
                    .build()
            )
        }
    }

    @Test
    // Tests using a stack > the CFN limit of 51200 bytes
    fun deployLargeAppUsingSam() {
        val stackName = "SamDeployTest-${UUID.randomUUID()}"
        val templateFile = setUpProject(largeTemplateLocation)
        runAssertsAndClean(stackName) {
            val changeSetArn = createChangeSet(templateFile, stackName, hasImage = false, parameters = mapOf("InstanceType" to "t2.small"))

            assertThat(changeSetArn).isNotNull
            val describeChangeSetResponse = projectRule.project.awsClient<CloudFormationClient>().describeChangeSet {
                it.stackName(stackName)
                it.changeSetName(changeSetArn)
            }

            assertThat(describeChangeSetResponse).isNotNull
            assertThat(describeChangeSetResponse.parameters()).contains(
                Parameter.builder()
                    .parameterKey("InstanceType")
                    .parameterValue("t2.small")
                    .build()
            )
        }
    }

    @Test
    fun deployAppUsingSamWithParameters() {
        val stackName = "SamDeployTest-${UUID.randomUUID()}"
        val templateFile = setUpProject()
        runAssertsAndClean(stackName) {
            val changeSetArn = createChangeSet(templateFile, stackName, hasImage = false, parameters = mapOf("TestParameter" to "FooBar"))

            assertThat(changeSetArn).isNotNull
            val describeChangeSetResponse = projectRule.project.awsClient<CloudFormationClient>().describeChangeSet {
                it.stackName(stackName)
                it.changeSetName(changeSetArn)
            }

            assertThat(describeChangeSetResponse).isNotNull
            assertThat(describeChangeSetResponse.parameters()).contains(
                Parameter.builder()
                    .parameterKey("TestParameter")
                    .parameterValue("FooBar")
                    .build()
            )
        }
    }

    @Test
    fun deployImageBasedSamApp() {
        assumeImageSupport()
        val stackName = "SamDeployTest-${UUID.randomUUID()}"
        val (_, templateFile) = readProject(
            projectRule = projectRule,
            relativePath = "samProjects/image/java11/maven",
            sourceFileName = "App.java"
        )
        runAssertsAndClean(stackName) {
            val changeSetArn = createChangeSet(templateFile, stackName, hasImage = true)

            assertThat(changeSetArn).isNotNull
            val describeChangeSetResponse = projectRule.project.awsClient<CloudFormationClient>().describeChangeSet {
                it.stackName(stackName)
                it.changeSetName(changeSetArn)
            }

            assertThat(describeChangeSetResponse).isNotNull
            assertThat(describeChangeSetResponse.parameters()).isEmpty()
        }
    }

    @Test
    fun deployAppUsingSamWithTags() {
        val stackName = "SamDeployTest-${UUID.randomUUID()}"
        val templateFile = setUpProject()
        runAssertsAndClean(stackName) {
            val changeSetArn = createChangeSet(
                templateFile,
                stackName,
                hasImage = false,
                tags = mapOf(
                    "TestTag" to "FooBar",
                    "some:gross" to "tag name and value",
                    // SAM test cases https://github.com/aws/aws-sam-cli/pull/1798/files
                    "a+-=._:/@" to "b+-=._:/@",
                    "--c=" to "=d/"
                )
            )

            assertThat(changeSetArn).isNotNull

            val describeChangeSetResponse = projectRule.project.awsClient<CloudFormationClient>().describeChangeSet {
                it.stackName(stackName)
                it.changeSetName(changeSetArn)
            }

            assertThat(describeChangeSetResponse).isNotNull
            assertThat(describeChangeSetResponse.tags()).containsExactlyInAnyOrder(
                Tag.builder()
                    .key("TestTag")
                    .value("FooBar")
                    .build(),
                Tag.builder()
                    .key("some:gross")
                    .value("tag name and value")
                    .build(),
                Tag.builder()
                    .key("a+-=._:/@")
                    .value("b+-=._:/@")
                    .build(),
                Tag.builder()
                    .key("--c=")
                    .value("=d/")
                    .build()
            )
        }
    }

    private fun setUpProject(templateFilePath: String? = null): VirtualFile {
        projectRule.fixture.addFileToProject(
            "hello_world/app.py",
            """
                def lambda_handler(event, context):
                    return "Hello world"
            """.trimIndent()
        )

        projectRule.fixture.addFileToProject(
            "requirements.txt",
            ""
        )

        return if (templateFilePath == null) {
            projectRule.fixture.addFileToProject(
                "template.yaml",
                """
                AWSTemplateFormatVersion: '2010-09-09'
                Transform: AWS::Serverless-2016-10-31
                Parameters:
                  TestParameter:
                    Type: String
                    Default: HelloWorld
                    AllowedValues:
                      - HelloWorld
                      - FooBar
                Resources:
                  SomeFunction:
                    Type: AWS::Serverless::Function
                    Properties:
                      Handler: hello_world/app.lambda_handler
                      CodeUri: .
                      Runtime: python3.8
                      Timeout: 900
                """.trimIndent()
            ).virtualFile
        } else {
            projectRule.fixture.addFileToProject("template.yaml", File(templateFilePath).readText()).virtualFile
        }
    }

    private fun createChangeSet(
        templateFile: VirtualFile,
        stackName: String,
        hasImage: Boolean,
        parameters: Map<String, String> = emptyMap(),
        tags: Map<String, String> = emptyMap()
    ): String? {
        val bucket = bucketRule.createBucket(stackName)
        val ecrRepo = if (hasImage) repositoryRule.createRepository(stackName).repositoryUri() else null

        var changeSetArn: String? = null
        val deployDialog = runInEdtAndGet {
            val workflow = StepExecutor(
                projectRule.project,
                createDeployWorkflow(
                    projectRule.project,
                    templateFile,
                    DeployServerlessApplicationSettings(
                        stackName = stackName,
                        bucket = bucket,
                        ecrRepo = ecrRepo,
                        autoExecute = true,
                        parameters = parameters,
                        tags = tags,
                        useContainer = false,
                        capabilities = CreateCapabilities.values().toList()
                    )
                ),
                ConsoleViewWorkflowEmitter.createEmitter(stackName)
            )

            workflow.onSuccess = {
                changeSetArn = it.getRequiredAttribute(DeployLambda.CHANGE_SET_ARN)
            }

            workflow.startExecution()
        }

        deployDialog.waitFor(TimeUnit.MINUTES.toMillis(5))

        return changeSetArn
    }

    private fun runAssertsAndClean(stackName: String, asserts: () -> Unit) {
        try {
            asserts.invoke()
        } finally {
            try {
                projectRule.project.awsClient<CloudFormationClient>().deleteStack {
                    it.stackName(stackName)
                }
            } catch (e: Exception) {
                println("Failed to delete stack $stackName: ${ExceptionUtil.getMessage(e)}")
            }
        }
    }
}


// Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

package software.aws.toolkits.jetbrains.services.lambda.java

import com.intellij.compiler.CompilerTestUtil
import com.intellij.execution.executors.DefaultDebugExecutor
import com.intellij.testFramework.runInEdtAndWait
import org.assertj.core.api.Assertions.assertThat
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.Parameterized
import software.amazon.awssdk.auth.credentials.AwsBasicCredentials
import software.aws.toolkits.core.lambda.LambdaRuntime
import software.aws.toolkits.core.utils.RuleUtils
import software.aws.toolkits.jetbrains.core.credentials.MockCredentialsManager
import software.aws.toolkits.jetbrains.services.lambda.execution.local.createHandlerBasedRunConfiguration
import software.aws.toolkits.jetbrains.services.lambda.execution.local.createTemplateRunConfiguration
import software.aws.toolkits.jetbrains.utils.addBreakpoint
import software.aws.toolkits.jetbrains.utils.checkBreakPointHit
import software.aws.toolkits.jetbrains.utils.executeRunConfigurationAndWait
import software.aws.toolkits.jetbrains.utils.rules.HeavyJavaCodeInsightTestFixtureRule
import software.aws.toolkits.jetbrains.utils.rules.addClass
import software.aws.toolkits.jetbrains.utils.rules.addFileToModule
import software.aws.toolkits.jetbrains.utils.rules.addModule
import software.aws.toolkits.jetbrains.utils.samImageRunDebugTest
import software.aws.toolkits.jetbrains.utils.setSamExecutableFromEnvironment
import software.aws.toolkits.jetbrains.utils.setUpGradleProject
import software.aws.toolkits.jetbrains.utils.setUpJdk

@RunWith(Parameterized::class)
class JavaLocalLambdaRunConfigurationIntegrationTest(private val runtime: LambdaRuntime) {
    companion object {
        @JvmStatic
        @Parameterized.Parameters(name = "{0}")
        fun data() = listOf(
            arrayOf(LambdaRuntime.JAVA8),
            arrayOf(LambdaRuntime.JAVA8_AL2),
            arrayOf(LambdaRuntime.JAVA11),
            arrayOf(LambdaRuntime.JAVA17)
        )
    }

    @Rule
    @JvmField
    val projectRule = HeavyJavaCodeInsightTestFixtureRule()

    private val mockId = "MockCredsId"
    private val mockCreds = AwsBasicCredentials.create("Access", "ItsASecret")
    private val input = RuleUtils.randomName()

    @Before
    fun setUp() {
        setSamExecutableFromEnvironment()

        val fixture = projectRule.fixture
        val module = fixture.addModule("main")
        val psiClass = fixture.addClass(
            module,
            """
            package com.example;

            public class LambdaHandler {
                public String handleRequest(String request) {
                    return request.toUpperCase();
                }
            }
            """
        )

        val compatibility = when (runtime) {
            LambdaRuntime.JAVA8, LambdaRuntime.JAVA8_AL2 -> "1.8"
            LambdaRuntime.JAVA11 -> "11"
            LambdaRuntime.JAVA17 -> "17"
            else -> throw NotImplementedError()
        }

        projectRule.setUpJdk()

        projectRule.setUpGradleProject(compatibility)

        runInEdtAndWait {
            fixture.openFileInEditor(psiClass.containingFile.virtualFile)
        }

        MockCredentialsManager.getInstance().addCredentials(mockId, mockCreds)
    }

    @After
    fun tearDown() {
        CompilerTestUtil.disableExternalCompiler(projectRule.project)
        MockCredentialsManager.getInstance().reset()
    }

    @Test
    fun samIsExecuted() {
        val runConfiguration = createHandlerBasedRunConfiguration(
            project = projectRule.project,
            runtime = runtime.toSdkRuntime(),
            input = "\"Hello World\"",
            credentialsProviderId = mockId
        )
        assertThat(runConfiguration).isNotNull

        val executeLambda = executeRunConfigurationAndWait(runConfiguration)

        assertThat(executeLambda.exitCode).isEqualTo(0)
        assertThat(executeLambda.stdout).contains("HELLO WORLD")
    }

    @Test
    fun samIsExecutedWithFileInput() {
        val runConfiguration = createHandlerBasedRunConfiguration(
            project = projectRule.project,
            runtime = runtime.toSdkRuntime(),
            input = projectRule.fixture.tempDirFixture.createFile("tmp", "\"Hello World\"").canonicalPath!!,
            inputIsFile = true,
            credentialsProviderId = mockId
        )
        assertThat(runConfiguration).isNotNull

        val executeLambda = executeRunConfigurationAndWait(runConfiguration)

        assertThat(executeLambda.exitCode).isEqualTo(0)
        assertThat(executeLambda.stdout).contains("HELLO WORLD")
    }

    @Test
    fun samIsExecutedWhenRunWithATemplateServerless() {
        val templateFile = projectRule.fixture.addFileToModule(
            projectRule.module,
            "template.yaml",
            """
            Resources:
              SomeFunction:
                Type: AWS::Serverless::Function
                Properties:
                  Handler: com.example.LambdaHandler::handleRequest
                  CodeUri: .
                  Runtime: $runtime
                  Timeout: 900
            """.trimIndent()
        )

        val runConfiguration = createTemplateRunConfiguration(
            project = projectRule.project,
            templateFile = templateFile.containingFile.virtualFile.path,
            logicalId = "SomeFunction",
            input = "\"Hello World\"",
            credentialsProviderId = mockId
        )

        assertThat(runConfiguration).isNotNull

        val executeLambda = executeRunConfigurationAndWait(runConfiguration)

        assertThat(executeLambda.exitCode).isEqualTo(0)
        assertThat(executeLambda.stdout).contains("HELLO WORLD")
    }

    @Test
    fun samIsExecutedWhenRunWithATemplateLambda() {
        val templateFile = projectRule.fixture.addFileToModule(
            projectRule.module,
            "template.yaml",
            """
            Resources:
              SomeFunction:
                Type: AWS::Lambda::Function
                Properties:
                  Handler: com.example.LambdaHandler::handleRequest
                  Code: .
                  Runtime: $runtime
                  Timeout: 900
            """.trimIndent()
        )

        val runConfiguration = createTemplateRunConfiguration(
            project = projectRule.project,
            templateFile = templateFile.containingFile.virtualFile.path,
            logicalId = "SomeFunction",
            input = "\"Hello World\"",
            credentialsProviderId = mockId
        )

        assertThat(runConfiguration).isNotNull

        val executeLambda = executeRunConfigurationAndWait(runConfiguration)

        assertThat(executeLambda.exitCode).isEqualTo(0)
        assertThat(executeLambda.stdout).contains("HELLO WORLD")
    }

    @Test
    fun samIsExecutedWithDebugger() {
        projectRule.addBreakpoint()

        val runConfiguration = createHandlerBasedRunConfiguration(
            project = projectRule.project,
            runtime = runtime.toSdkRuntime(),
            input = "\"Hello World\"",
            credentialsProviderId = mockId
        )
        assertThat(runConfiguration).isNotNull

        val debuggerIsHit = checkBreakPointHit(projectRule.project)

        val executeLambda = executeRunConfigurationAndWait(runConfiguration, DefaultDebugExecutor.EXECUTOR_ID)

        assertThat(executeLambda.exitCode).isEqualTo(0)
        assertThat(executeLambda.stdout).contains("HELLO WORLD")

        assertThat(debuggerIsHit.get()).isTrue()
    }

    @Test
    fun samIsExecutedWhenRunWithATemplateImage(): Unit = samImageRunDebugTest(
        projectRule = projectRule,
        relativePath = "samProjects/image/$runtime/maven",
        sourceFileName = "App.java",
        runtime = runtime,
        mockCredentialsId = mockId,
        input = input,
        expectedOutput = input.uppercase()
    )

    @Test
    fun samIsExecutedWithDebuggerImage(): Unit = samImageRunDebugTest(
        projectRule = projectRule,
        relativePath = "samProjects/image/$runtime/maven",
        sourceFileName = "App.java",
        runtime = runtime,
        mockCredentialsId = mockId,
        input = input,
        expectedOutput = input.uppercase(),
        addBreakpoint = { projectRule.addBreakpoint() }
    )
}


// Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

package software.aws.toolkits.jetbrains.services.lambda.python

import com.intellij.execution.executors.DefaultDebugExecutor
import com.intellij.openapi.command.WriteCommandAction
import com.intellij.openapi.fileEditor.FileDocumentManager
import com.intellij.psi.PsiDocumentManager
import com.intellij.psi.PsiFile
import com.intellij.testFramework.PsiTestUtil
import com.intellij.testFramework.runInEdtAndWait
import org.assertj.core.api.Assertions.assertThat
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.Parameterized
import software.amazon.awssdk.auth.credentials.AwsBasicCredentials
import software.amazon.awssdk.auth.credentials.AwsSessionCredentials
import software.amazon.awssdk.services.lambda.model.Runtime
import software.aws.toolkits.core.lambda.LambdaRuntime
import software.aws.toolkits.core.utils.RuleUtils
import software.aws.toolkits.core.utils.test.aString
import software.aws.toolkits.jetbrains.core.credentials.MockCredentialsManager
import software.aws.toolkits.jetbrains.core.region.getDefaultRegion
import software.aws.toolkits.jetbrains.services.lambda.execution.local.createHandlerBasedRunConfiguration
import software.aws.toolkits.jetbrains.services.lambda.execution.local.createTemplateRunConfiguration
import software.aws.toolkits.jetbrains.services.lambda.sam.SamOptions
import software.aws.toolkits.jetbrains.utils.checkBreakPointHit
import software.aws.toolkits.jetbrains.utils.executeRunConfigurationAndWait
import software.aws.toolkits.jetbrains.utils.jsonToMap
import software.aws.toolkits.jetbrains.utils.rules.PythonCodeInsightTestFixtureRule
import software.aws.toolkits.jetbrains.utils.rules.addBreakpoint
import software.aws.toolkits.jetbrains.utils.samImageRunDebugTest
import software.aws.toolkits.jetbrains.utils.setSamExecutableFromEnvironment
import software.aws.toolkits.jetbrains.utils.stopOnPause

@RunWith(Parameterized::class)
class PythonLocalLambdaRunConfigurationIntegrationTest(private val runtime: Runtime) {
    companion object {
        @JvmStatic
        @Parameterized.Parameters(name = "{0}")
        fun data(): Collection<Array<Runtime>> = listOf(
            arrayOf(Runtime.PYTHON3_7),
            arrayOf(Runtime.PYTHON3_8),
            arrayOf(Runtime.PYTHON3_9),
            arrayOf(Runtime.PYTHON3_10)
        )
    }

    @Rule
    @JvmField
    val projectRule = PythonCodeInsightTestFixtureRule()

    private val mockId = "MockCredsId"
    private val mockCreds = AwsBasicCredentials.create("Access", "ItsASecret")
    private val input = RuleUtils.randomName()
    private lateinit var lambdaClass: PsiFile

    @Before
    fun setUp() {
        setSamExecutableFromEnvironment()

        val fixture = projectRule.fixture
        fixture.addFileToProject(
            "src/hello_world/__init__.py",
            ""
        )

        lambdaClass = fixture.addFileToProject(
            "src/hello_world/app.py",
            """
            import os
            import time

            def lambda_handler(event, context):
                print(os.environ)
                return "Hello world"

            def env_print(event, context):
                return dict(**os.environ)

            def run_forever(event, context):
                print(os.environ)
                while true:
                   time.sleep(1)
            """.trimIndent()
        )

        runInEdtAndWait {
            fixture.openFileInEditor(lambdaClass.virtualFile)
        }

        MockCredentialsManager.getInstance().addCredentials(mockId, mockCreds)
    }

    @After
    fun tearDown() {
        MockCredentialsManager.getInstance().reset()
    }

    @Test
    fun samIsExecutedWithContainer() {
        projectRule.fixture.addFileToProject("requirements.txt", "")

        val samOptions = SamOptions().apply {
            this.buildInContainer = true
        }

        val runConfiguration = createHandlerBasedRunConfiguration(
            project = projectRule.project,
            runtime = runtime,
            handler = "src/hello_world.app.lambda_handler",
            input = "\"Hello World\"",
            credentialsProviderId = mockId,
            samOptions = samOptions
        )
        assertThat(runConfiguration).isNotNull

        val executeLambda = executeRunConfigurationAndWait(runConfiguration)

        assertThat(executeLambda.exitCode).isEqualTo(0)
        assertThat(executeLambda.stdout).contains("Hello world")
    }

    @Test
    fun samIsExecuted() {
        projectRule.fixture.addFileToProject("requirements.txt", "")

        val envVars = mutableMapOf("Foo" to "Bar", "Bat" to "Baz")

        val runConfiguration = createHandlerBasedRunConfiguration(
            project = projectRule.project,
            runtime = runtime,
            handler = "src/hello_world.app.env_print",
            input = "\"Hello World\"",
            credentialsProviderId = mockId,
            environmentVariables = envVars
        )
        assertThat(runConfiguration).isNotNull

        val executeLambda = executeRunConfigurationAndWait(runConfiguration)

        assertThat(executeLambda.exitCode).isEqualTo(0)
        assertThat(jsonToMap(executeLambda.stdout))
            .describedAs("Environment variables are passed")
            .containsEntry("Foo", "Bar")
            .containsEntry("Bat", "Baz")
        assertThat(jsonToMap(executeLambda.stdout))
            .describedAs("Region is set")
            .containsEntry("AWS_REGION", getDefaultRegion().id)
        assertThat(jsonToMap(executeLambda.stdout))
            .describedAs("Credentials are passed")
            .containsEntry("AWS_ACCESS_KEY_ID", mockCreds.accessKeyId())
            .containsEntry("AWS_SECRET_ACCESS_KEY", mockCreds.secretAccessKey())
            // An empty AWS_SESSION_TOKEN is inserted by Samcli/the Lambda runtime as of 1.13.1
            .containsEntry("AWS_SESSION_TOKEN", "")
    }

    @Test
    fun fileContentsAreSavedBeforeRunning() {
        projectRule.fixture.addFileToProject("requirements.txt", "")

        val randomString = aString()
        runInEdtAndWait {
            WriteCommandAction.runWriteCommandAction(projectRule.project) {
                val document = FileDocumentManager.getInstance().getDocument(lambdaClass.virtualFile)!!
                document.replaceString(
                    0,
                    document.textLength,
                    """
                    def print_string(event, context):
                        return "$randomString"
                    """.trimIndent()
                )
                PsiDocumentManager.getInstance(projectRule.project).commitDocument(document)
            }
        }

        val runConfiguration = createHandlerBasedRunConfiguration(
            project = projectRule.project,
            runtime = runtime,
            handler = "src/hello_world.app.print_string",
            input = "\"Hello World\"",
            credentialsProviderId = mockId,
        )
        assertThat(runConfiguration).isNotNull

        val executeLambda = executeRunConfigurationAndWait(runConfiguration)

        assertThat(executeLambda.exitCode).isEqualTo(0)
        assertThat(executeLambda.stdout)
            .describedAs("Random string is printed")
            .contains(randomString)
    }

    @Test
    fun samIsExecutedWithFileInput() {
        projectRule.fixture.addFileToProject("requirements.txt", "")

        val envVars = mutableMapOf("Foo" to "Bar", "Bat" to "Baz")

        val runConfiguration = createHandlerBasedRunConfiguration(
            project = projectRule.project,
            runtime = runtime,
            handler = "src/hello_world.app.env_print",
            input = projectRule.fixture.tempDirFixture.createFile("tmp", "Hello World").canonicalPath!!,
            inputIsFile = true,
            credentialsProviderId = mockId,
            environmentVariables = envVars
        )
        assertThat(runConfiguration).isNotNull

        val executeLambda = executeRunConfigurationAndWait(runConfiguration)

        assertThat(executeLambda.exitCode).isEqualTo(0)
    }

    @Test
    fun sessionCredentialsArePassed() {
        projectRule.fixture.addFileToProject("requirements.txt", "")

        val mockSessionId = "mockSessionId"
        val mockSessionCreds = AwsSessionCredentials.create("access", "secret", "session")

        MockCredentialsManager.getInstance().addCredentials(mockSessionId, mockSessionCreds)

        val runConfiguration = createHandlerBasedRunConfiguration(
            project = projectRule.project,
            runtime = runtime,
            handler = "src/hello_world.app.env_print",
            input = "\"Hello World\"",
            credentialsProviderId = mockSessionId
        )
        assertThat(runConfiguration).isNotNull

        val executeLambda = executeRunConfigurationAndWait(runConfiguration)

        assertThat(executeLambda.exitCode).isEqualTo(0)
        assertThat(jsonToMap(executeLambda.stdout))
            .containsEntry("AWS_ACCESS_KEY_ID", mockSessionCreds.accessKeyId())
            .containsEntry("AWS_SECRET_ACCESS_KEY", mockSessionCreds.secretAccessKey())
            .containsEntry("AWS_SESSION_TOKEN", mockSessionCreds.sessionToken())
    }

    @Test
    fun samIsExecutedWithDebugger() {
        projectRule.fixture.addFileToProject("requirements.txt", "")

        val runConfiguration = createHandlerBasedRunConfiguration(
            project = projectRule.project,
            runtime = runtime,
            handler = "src/hello_world.app.lambda_handler",
            input = "\"Hello World\"",
            credentialsProviderId = mockId
        )
        assertThat(runConfiguration).isNotNull

        projectRule.addBreakpoint()
        val debuggerIsHit = checkBreakPointHit(projectRule.project)

        val executeLambda = executeRunConfigurationAndWait(runConfiguration, DefaultDebugExecutor.EXECUTOR_ID)

        assertThat(executeLambda.exitCode).isEqualTo(0)
        assertThat(executeLambda.stdout).contains("Hello world")

        assertThat(debuggerIsHit.get()).isTrue()
    }

    @Test
    fun samIsExecutedWithDebuggerSourceRoot() {
        projectRule.fixture.addFileToProject("src/requirements.txt", "")

        val srcRoot = projectRule.fixture.file.virtualFile.parent.parent
        PsiTestUtil.addSourceRoot(projectRule.module, srcRoot)

        val runConfiguration = createHandlerBasedRunConfiguration(
            project = projectRule.project,
            runtime = runtime,
            handler = "hello_world.app.lambda_handler",
            input = "\"Hello World\"",
            credentialsProviderId = mockId
        )
        assertThat(runConfiguration).isNotNull

        projectRule.addBreakpoint()
        val debuggerIsHit = checkBreakPointHit(projectRule.project)

        val executeLambda = executeRunConfigurationAndWait(runConfiguration, DefaultDebugExecutor.EXECUTOR_ID)

        assertThat(executeLambda.exitCode).isEqualTo(0)
        assertThat(executeLambda.stdout).contains("Hello world")

        assertThat(debuggerIsHit.get()).isTrue()
    }

    @Test
    fun samIsExecutedWithTemplate() {
        projectRule.fixture.addFileToProject("src/requirements.txt", "")

        val srcRoot = projectRule.fixture.file.virtualFile.parent.parent
        PsiTestUtil.addSourceRoot(projectRule.module, srcRoot)

        val templateFile = projectRule.fixture.addFileToProject(
            "template.yaml",
            """
            Resources:
              SomeFunction:
                Type: AWS::Serverless::Function
                Properties:
                  Handler: hello_world.app.lambda_handler
                  CodeUri: src
                  Runtime: $runtime
                  Timeout: 900
            """.trimIndent()
        )

        val runConfiguration = createTemplateRunConfiguration(
            project = projectRule.project,
            templateFile = templateFile.virtualFile.path,
            logicalId = "SomeFunction",
            input = "\"Hello World\"",
            credentialsProviderId = mockId
        )
        assertThat(runConfiguration).isNotNull

        projectRule.addBreakpoint()
        val debuggerIsHit = checkBreakPointHit(projectRule.project)

        val executeLambda = executeRunConfigurationAndWait(runConfiguration, DefaultDebugExecutor.EXECUTOR_ID)

        assertThat(executeLambda.exitCode).isEqualTo(0)
        assertThat(executeLambda.stdout).contains("Hello world")

        assertThat(debuggerIsHit.get()).isTrue()
    }

    @Test
    fun samIsExecutedImage(): Unit = samImageRunDebugTest(
        projectRule = projectRule,
        relativePath = "samProjects/image/$runtime",
        sourceFileName = "app.py",
        runtime = LambdaRuntime.fromValue(runtime)!!,
        mockCredentialsId = mockId,
        input = input,
        expectedOutput = input.uppercase()
    )

    @Test
    fun samIsExecutedWithDebuggerImage(): Unit = samImageRunDebugTest(
        projectRule = projectRule,
        relativePath = "samProjects/image/$runtime",
        sourceFileName = "app.py",
        runtime = LambdaRuntime.fromValue(runtime)!!,
        mockCredentialsId = mockId,
        input = input,
        expectedOutput = input.uppercase(),
        addBreakpoint = { projectRule.addBreakpoint() }
    )

    @Test
    fun samIsExecutedWithTemplateWithLocalCodeUri() {
        val templateFile = projectRule.fixture.addFileToProject(
            "src/hello_world/template.yaml",
            """
            Resources:
              SomeFunction:
                Type: AWS::Serverless::Function
                Properties:
                  Handler: app.lambda_handler
                  CodeUri: .
                  Runtime: $runtime
                  Timeout: 900
            """.trimIndent()
        )

        projectRule.fixture.addFileToProject("src/hello_world/requirements.txt", "")
        PsiTestUtil.addSourceRoot(projectRule.module, templateFile.virtualFile.parent)

        val runConfiguration = createTemplateRunConfiguration(
            project = projectRule.project,
            templateFile = templateFile.virtualFile.path,
            logicalId = "SomeFunction",
            input = "\"Hello World\"",
            credentialsProviderId = mockId
        )
        assertThat(runConfiguration).isNotNull

        projectRule.addBreakpoint()
        val debuggerIsHit = checkBreakPointHit(projectRule.project)

        val executeLambda = executeRunConfigurationAndWait(runConfiguration, DefaultDebugExecutor.EXECUTOR_ID)

        assertThat(executeLambda.exitCode).isEqualTo(0)
        assertThat(executeLambda.stdout).contains("Hello world")

        assertThat(debuggerIsHit.get()).isTrue()
    }

    @Test
    fun stopDebuggerStopsSamCli() {
        projectRule.fixture.addFileToProject("requirements.txt", "")

        val runConfiguration = createHandlerBasedRunConfiguration(
            project = projectRule.project,
            runtime = runtime,
            handler = "src/hello_world.app.run_forever",
            input = "\"Hello World\"",
            credentialsProviderId = mockId,
        )
        assertThat(runConfiguration).isNotNull

        projectRule.addBreakpoint()
        stopOnPause(projectRule.project)

        val executeLambda = executeRunConfigurationAndWait(runConfiguration, DefaultDebugExecutor.EXECUTOR_ID)

        assertThat(executeLambda.exitCode).isEqualTo(0)
    }
}


// Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

package software.aws.toolkits.jetbrains.services.lambda.upload

import com.intellij.testFramework.DisposableRule
import com.intellij.testFramework.RuleChain
import com.intellij.testFramework.RunAll
import com.intellij.testFramework.runInEdtAndGet
import org.assertj.core.api.Assertions.assertThat
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import software.amazon.awssdk.regions.Region
import software.amazon.awssdk.services.ecr.EcrClient
import software.amazon.awssdk.services.iam.IamClient
import software.amazon.awssdk.services.iam.model.Role
import software.amazon.awssdk.services.lambda.LambdaClient
import software.amazon.awssdk.services.lambda.model.ResourceNotFoundException
import software.amazon.awssdk.services.lambda.model.Runtime
import software.amazon.awssdk.services.s3.model.Bucket
import software.aws.toolkits.core.rules.S3TemporaryBucketRule
import software.aws.toolkits.core.utils.RuleUtils
import software.aws.toolkits.core.utils.createIntegrationTestCredentialProvider
import software.aws.toolkits.jetbrains.core.MockClientManager
import software.aws.toolkits.jetbrains.core.MockResourceCacheRule
import software.aws.toolkits.jetbrains.core.awsClient
import software.aws.toolkits.jetbrains.core.credentials.MockAwsConnectionManager.ProjectAccountSettingsManagerRule
import software.aws.toolkits.jetbrains.core.credentials.MockCredentialManagerRule
import software.aws.toolkits.jetbrains.core.credentials.activeRegion
import software.aws.toolkits.jetbrains.core.region.AwsRegionProvider
import software.aws.toolkits.jetbrains.services.ecr.resources.EcrResources
import software.aws.toolkits.jetbrains.services.ecr.resources.Repository
import software.aws.toolkits.jetbrains.services.iam.Iam.createRoleWithPolicy
import software.aws.toolkits.jetbrains.services.iam.IamResources
import software.aws.toolkits.jetbrains.services.s3.resources.S3Resources
import software.aws.toolkits.jetbrains.utils.assumeImageSupport
import software.aws.toolkits.jetbrains.utils.execution.steps.StepExecutor
import software.aws.toolkits.jetbrains.utils.readProject
import software.aws.toolkits.jetbrains.utils.rules.HeavyJavaCodeInsightTestFixtureRule
import software.aws.toolkits.jetbrains.utils.rules.addModule
import software.aws.toolkits.jetbrains.utils.setSamExecutableFromEnvironment
import software.aws.toolkits.jetbrains.utils.setUpGradleProject
import software.aws.toolkits.jetbrains.utils.waitToLoad
import java.time.Duration

class CreateFunctionIntegrationTest {
    private val projectRule = HeavyJavaCodeInsightTestFixtureRule()
    private val resourceCache = MockResourceCacheRule()
    private val disposableRule = DisposableRule()
    private val credentialManager = MockCredentialManagerRule()
    private val settingsManager = ProjectAccountSettingsManagerRule(projectRule)
    private val temporaryBucket = S3TemporaryBucketRule { projectRule.project.awsClient() }

    @Rule
    @JvmField
    // we need to control the life cycle of what gets started and shut down in a very specific way.
    // i.e. disposable needs to be near front of chain so it is first and last so that the ability to make real AWS calls lives for the life of full test
    val ruleChain = RuleChain(
        projectRule,
        disposableRule,
        credentialManager,
        settingsManager,
        temporaryBucket
    )

    private lateinit var lambdaClient: LambdaClient
    private lateinit var iamClient: IamClient
    private lateinit var ecrClient: EcrClient

    private lateinit var lambdaName: String
    private lateinit var iamRole: Role

    @Before
    fun setUp() {
        setSamExecutableFromEnvironment()
        projectRule.fixture.addModule("main")

        // Make sure this is called before we use real credentials since if we assume a role, we will trigger SDK client creation and that will show up as a
        // leaked thread in the idle connection reaper
        // TODO: To defend against this we should make a AwsSdkClient that throws telling people to use this method
        MockClientManager.useRealImplementations(disposableRule.disposable)

        val region = AwsRegionProvider.getInstance()[Region.US_WEST_2.id()]!!
        val credentials = credentialManager.addCredentials("ReadCreds", createIntegrationTestCredentialProvider(), region.id)

        settingsManager.settingsManager.changeRegion(region)
        settingsManager.settingsManager.changeCredentialProviderAndWait(credentials)

        lambdaClient = projectRule.project.awsClient()
        iamClient = projectRule.project.awsClient()
        ecrClient = projectRule.project.awsClient()

        lambdaName = RuleUtils.randomName()
        iamRole = iamClient.createRoleWithPolicy(RuleUtils.randomName(), DEFAULT_LAMBDA_ASSUME_ROLE_POLICY)

        // Sleep for a while to allow the new IAM role to propagate to other regions
        Thread.sleep(Duration.ofSeconds(30).toMillis())

        resourceCache.addEntry(
            projectRule.project,
            IamResources.LIST_RAW_ROLES,
            listOf(iamRole)
        )
    }

    @After
    fun tearDown() {
        // static method import incompatible when jb converted framework to KT: FIX_WHEN_MIN_IS_212
        RunAll(
            {
                try {
                    lambdaClient.deleteFunction { it.functionName(lambdaName) }
                } catch (e: Exception) {
                    if (e !is ResourceNotFoundException) {
                        throw e
                    }
                }
            },
            {
                iamClient.deleteRole { it.roleName(iamRole.roleName()) }
            }
        ).run()
    }

    @Test
    fun `zip based lambda can be created`() {
        val s3Bucket = temporaryBucket.createBucket()
        resourceCache.addEntry(
            projectRule.project,
            "s3.list_buckets",
            listOf(S3Resources.RegionalizedBucket(Bucket.builder().name(s3Bucket).build(), projectRule.project.activeRegion()))
        )

        projectRule.setUpGradleProject()

        executeCreateFunction {
            val dialog = runInEdtAndGet {
                CreateFunctionDialog(projectRule.project, Runtime.JAVA8, "com.example.SomeClass").apply {
                    val view = getViewForTestAssertions()
                    view.name.text = lambdaName
                    view.configSettings.iamRole.selectedItem { iamRole.arn() == it.arn }
                    view.codeStorage.sourceBucket.selectedItem = s3Bucket
                }
            }

            val view = dialog.getViewForTestAssertions()
            view.codeStorage.sourceBucket.waitToLoad()
            view.configSettings.iamRole.waitToLoad()

            runInEdtAndGet {
                assertThat(view.validatePanel()?.message).isNull() // Validate we set everything up
                dialog.createWorkflow()
            }
        }
    }

    @Test
    fun `image based lambda can be created`() {
        assumeImageSupport()
        val (dockerfile, _) = readProject("samProjects/image/java8/maven", "Dockerfile", projectRule)
        val ecrRepo = ecrClient.createRepository {
            it.repositoryName(RuleUtils.randomName().lowercase())
        }.repository()

        val repository = Repository(ecrRepo.repositoryName(), ecrRepo.repositoryArn(), ecrRepo.repositoryUri())

        try {
            resourceCache.addEntry(
                projectRule.project,
                EcrResources.LIST_REPOS,
                listOf(repository)
            )

            executeCreateFunction {
                val dialog = runInEdtAndGet {
                    CreateFunctionDialog(projectRule.project, null, null).apply {
                        val view = getViewForTestAssertions()
                        view.name.text = lambdaName
                        view.configSettings.packageImage.isSelected = true
                        view.configSettings.dockerFile.textField.text = dockerfile.path
                        view.configSettings.iamRole.selectedItem { iamRole.arn() == it.arn }
                        view.codeStorage.ecrRepo.selectedItem = repository
                    }
                }

                val view = dialog.getViewForTestAssertions()
                view.codeStorage.ecrRepo.waitToLoad()
                view.configSettings.iamRole.waitToLoad()

                runInEdtAndGet {
                    assertThat(view.validatePanel()?.message).isNull() // Validate we set everything up
                    dialog.createWorkflow()
                }
            }
        } finally {
            ecrClient.deleteRepository {
                it.repositoryName(repository.repositoryName)
                it.force(true)
            }
        }
    }

    private fun executeCreateFunction(workflowBuilder: () -> StepExecutor) {
        val workflow = workflowBuilder()

        var passed = false
        workflow.onSuccess = {
            passed = true
        }

        workflow.startExecution().waitFor(Duration.ofMinutes(15).toMillis())

        assertThat(passed).isTrue()
        assertThat(lambdaClient.getFunction { it.functionName(lambdaName) }).isNotNull
    }
}


// Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

package software.aws.toolkits.jetbrains.services.s3

import com.intellij.testFramework.ProjectRule
import org.assertj.core.api.Assertions.assertThat
import org.junit.Rule
import org.junit.Test
import org.junit.rules.TemporaryFolder
import software.amazon.awssdk.http.apache.ApacheHttpClient
import software.amazon.awssdk.regions.Region
import software.amazon.awssdk.services.s3.S3Client
import software.aws.toolkits.core.rules.S3TemporaryBucketRule
import software.aws.toolkits.jetbrains.utils.value

class TransferUtilsIntegrationTest {
    private val s3Client = S3Client.builder()
        .httpClient(ApacheHttpClient.builder().build())
        .region(Region.US_WEST_2)
        .serviceConfiguration { it.pathStyleAccessEnabled(true) }
        .build()

    @JvmField
    @Rule
    val folder = TemporaryFolder()

    @JvmField
    @Rule
    val projectRule = ProjectRule()

    @JvmField
    @Rule
    val bucketRule = S3TemporaryBucketRule(s3Client)

    @Test
    fun canDoUploadAndDownload() {
        val bucket = bucketRule.createBucket()
        val bigString = "hello world".repeat(1000)

        val sourceFile = folder.newFile()
        sourceFile.writeText(bigString)

        s3Client.upload(projectRule.project, sourceFile.toPath(), bucket, "file", message = "uploading").value

        val destinationFile = folder.newFile()
        s3Client.download(projectRule.project, bucket, "file", null, destinationFile.toPath(), message = "downloading").value

        assertThat(destinationFile).hasSameTextualContentAs(sourceFile)
    }
}