jetbrains-ultimate/it/software/aws/toolkits/jetbrains/services/lambda/go/GoLocalRunConfigurationIntegrationTest.kt (243 lines of code) (raw):
// Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package software.aws.toolkits.jetbrains.services.lambda.go
import com.goide.sdk.GoSdk
import com.goide.sdk.GoSdkService
import com.goide.sdk.GoSdkUtil
import com.goide.vgo.VgoTestUtil
import com.intellij.execution.executors.DefaultDebugExecutor
import com.intellij.openapi.module.WebModuleTypeBase
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.openapi.vfs.newvfs.impl.VfsRootAccess
import com.intellij.testFramework.DisposableRule
import com.intellij.testFramework.PsiTestUtil
import com.intellij.testFramework.fixtures.CodeInsightTestFixture
import com.intellij.testFramework.runInEdtAndWait
import org.assertj.core.api.Assertions.assertThat
import org.junit.Assume.assumeFalse
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.aws.toolkits.core.lambda.LambdaRuntime
import software.aws.toolkits.core.utils.RuleUtils
import software.aws.toolkits.jetbrains.core.credentials.MockCredentialManagerRule
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.utils.UltimateTestUtils
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.HeavyGoCodeInsightTestFixtureRule
import software.aws.toolkits.jetbrains.utils.rules.addGoModFile
import software.aws.toolkits.jetbrains.utils.rules.compatibleGoForIde
import software.aws.toolkits.jetbrains.utils.rules.ensureCorrectGoVersion
import software.aws.toolkits.jetbrains.utils.rules.runGoModTidy
import software.aws.toolkits.jetbrains.utils.samImageRunDebugTest
import software.aws.toolkits.jetbrains.utils.setSamExecutableFromEnvironment
@RunWith(Parameterized::class)
class GoLocalRunConfigurationIntegrationTest(private val runtime: LambdaRuntime) {
companion object {
@JvmStatic
@Parameterized.Parameters(name = "{0}")
fun parameters(): Collection<Array<LambdaRuntime>> = listOf(
arrayOf(LambdaRuntime.GO1_X)
)
}
@Rule
@JvmField
val projectRule = HeavyGoCodeInsightTestFixtureRule()
@Rule
@JvmField
val credentialManager = MockCredentialManagerRule()
@Rule
@JvmField
val disposableRule = DisposableRule()
private val input = RuleUtils.randomName()
private val mockId = "MockCredsId"
private val mockCreds = AwsBasicCredentials.create("Access", "ItsASecret")
private lateinit var goModFile: VirtualFile
private val fileContents = """
package main
import (
"github.com/aws/aws-lambda-go/lambda"
"strings"
)
func handler(request string) (string, error) {
return strings.ToUpper(request), nil
}
func main() {
lambda.Start(handler)
}
""".trimIndent()
private val envVarsFileContents = """
package main
import (
"github.com/aws/aws-lambda-go/lambda"
"os"
"strings"
)
func handler() (interface{}, error) {
entries := map[string]string{}
for _, item := range os.Environ() {
entry := strings.Split(item, "=")
entries[entry[0]] = entry[1]
}
return entries, nil
}
func main() {
lambda.Start(handler)
}
""".trimIndent()
@Before
fun setUp() {
setSamExecutableFromEnvironment()
UltimateTestUtils.ensureBuiltInServerStarted()
val fixture = projectRule.fixture
fixture.ensureCorrectGoVersion(disposableRule.disposable)
PsiTestUtil.addModule(projectRule.project, WebModuleTypeBase.getInstance(), "main", fixture.tempDirFixture.findOrCreateDir("."))
goModFile = projectRule.fixture.addGoModFile("hello-world").virtualFile
// This block does 2 things:
// 1. sets up vgo support which is required for sam cli
// 2. Makes VgoDlvPositionConverter#toRemotePath work so we can set breakpoints
runInEdtAndWait {
VgoTestUtil.setupVgoIntegration(fixture)
}
credentialManager.addCredentials(mockId, mockCreds)
}
@Test
fun sessionCredentialsArePassed() {
projectRule.fixture.addLambdaFile(envVarsFileContents)
runGoModTidy(goModFile)
val mockSessionId = "mockSessionId"
val mockSessionCreds = AwsSessionCredentials.create("access", "secret", "session")
MockCredentialsManager.getInstance().addCredentials(mockSessionId, mockSessionCreds)
val runConfiguration = createHandlerBasedRunConfiguration(
project = projectRule.project,
runtime = runtime.toSdkRuntime(),
handler = "handler",
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 samIsExecuted() {
projectRule.fixture.addLambdaFile(envVarsFileContents)
runGoModTidy(goModFile)
val envVars = mutableMapOf("Foo" to "Bar", "Bat" to "Baz")
val runConfiguration = createHandlerBasedRunConfiguration(
project = projectRule.project,
runtime = runtime.toSdkRuntime(),
handler = "handler",
input = "\"${input}\"",
credentialsProviderId = mockId,
environmentVariables = envVars
)
assertThat(runConfiguration).isNotNull
val executeLambda = executeRunConfigurationAndWait(runConfiguration)
assertThat(executeLambda.exitCode).isEqualTo(0)
assertThat(jsonToMap(executeLambda.stdout))
.describedAs("Region is passed")
.containsEntry("AWS_REGION", getDefaultRegion().id)
assertThat(jsonToMap(executeLambda.stdout))
.describedAs("Envvars are passed")
.containsEntry("Foo", "Bar")
.containsEntry("Bat", "Baz")
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 samIsExecutedWithFileInput() {
projectRule.fixture.addLambdaFile(envVarsFileContents)
runGoModTidy(goModFile)
val runConfiguration = createHandlerBasedRunConfiguration(
project = projectRule.project,
runtime = runtime.toSdkRuntime(),
handler = "handler",
input = projectRule.fixture.tempDirFixture.createFile("tmp", "\"${input}\"").canonicalPath!!,
inputIsFile = true,
credentialsProviderId = mockId,
)
assertThat(runConfiguration).isNotNull
val executeLambda = executeRunConfigurationAndWait(runConfiguration)
assertThat(executeLambda.exitCode).isEqualTo(0)
}
@Test
fun samIsExecutedWithDebugger() {
projectRule.fixture.addLambdaFile(fileContents)
runGoModTidy(goModFile)
val runConfiguration = createHandlerBasedRunConfiguration(
project = projectRule.project,
runtime = runtime.toSdkRuntime(),
handler = "handler",
input = "\"${input}\"",
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(input.toUpperCase())
assertThat(debuggerIsHit.get()).isTrue
}
@Test
fun `works when handler is 'main'`() {
assumeFalse(true) // TODO: fix when new build images are ready
// fails if [Lambda.findPsiElementsForHandler] finds the handler in the Go standard library
val sdkDir = GoSdkUtil.suggestSdkDirectory()!!.children.sortedByDescending { it.name }.first().canonicalPath!!
VfsRootAccess.allowRootAccess(projectRule.project, sdkDir)
runInEdtAndWait {
GoSdkService.getInstance(projectRule.project).setSdk(GoSdk.fromHomePath(sdkDir))
}
projectRule.fixture.addLambdaFile(fileContents)
runGoModTidy(goModFile)
val runConfiguration = createHandlerBasedRunConfiguration(
project = projectRule.project,
runtime = runtime.toSdkRuntime(),
handler = "main",
input = "\"${input}\"",
credentialsProviderId = mockId
)
assertThat(runConfiguration).isNotNull
val executeLambda = executeRunConfigurationAndWait(runConfiguration, DefaultDebugExecutor.EXECUTOR_ID)
assertThat(executeLambda.exitCode).isEqualTo(0)
}
@Test
fun samIsExecutedImage(): Unit = samImageRunDebugTest(
projectRule = projectRule,
relativePath = "samProjects/image/$runtime",
templatePatches = mapOf("[GoVersion]" to (compatibleGoForIde() ?: "1")),
sourceFileName = "main.go",
runtime = runtime,
mockCredentialsId = mockId,
input = input,
expectedOutput = input.toUpperCase()
)
@Test
fun samIsExecutedWithDebuggerImage() {
samImageRunDebugTest(
projectRule = projectRule,
relativePath = "samProjects/image/$runtime",
templatePatches = mapOf("[GoVersion]" to (compatibleGoForIde() ?: "1")),
sourceFileName = "main.go",
runtime = runtime,
mockCredentialsId = mockId,
input = input,
addBreakpoint = { projectRule.addBreakpoint() }
)
}
private fun CodeInsightTestFixture.addLambdaFile(contents: String) {
val psiFile = addFileToProject("hello-world/main.go", contents)
runInEdtAndWait {
openFileInEditor(psiFile.virtualFile)
}
}
}