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

package software.aws.toolkits.jetbrains.services.lambda.sam.sync

import com.intellij.openapi.ui.DialogPanel
import com.intellij.openapi.ui.validation.DialogValidation
import com.intellij.openapi.vfs.VfsUtil
import com.intellij.testFramework.EdtRule
import com.intellij.testFramework.RuleChain
import com.intellij.testFramework.RunsInEdt
import com.intellij.testFramework.TemporaryDirectory
import com.intellij.testFramework.runInEdtAndWait
import com.intellij.util.io.writeChild
import org.assertj.core.api.Assertions.assertThat
import org.jetbrains.yaml.psi.YAMLSequence
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.StackSummary
import software.amazon.awssdk.services.ecr.EcrClient
import software.amazon.awssdk.services.s3.S3Client
import software.aws.toolkits.jetbrains.core.MockClientManagerRule
import software.aws.toolkits.jetbrains.services.cloudformation.Parameter
import software.aws.toolkits.jetbrains.services.ecr.resources.Repository
import software.aws.toolkits.jetbrains.services.lambda.sam.ValidateSamParameters
import software.aws.toolkits.jetbrains.utils.rules.JavaCodeInsightTestFixtureRule
import software.aws.toolkits.resources.message
import java.nio.file.Files

@RunsInEdt
class SyncSamApplicationValidatorTest {
    private val projectRule = JavaCodeInsightTestFixtureRule()

    @Rule
    @JvmField
    val ruleChain = RuleChain(projectRule, EdtRule())

    @Rule
    @JvmField
    val tempDir = TemporaryDirectory()

    @JvmField
    @Rule
    val mockClientManagerRule = MockClientManagerRule()

    private lateinit var sut: SyncServerlessApplicationDialog
    private lateinit var sutPanel: DialogPanel

    private val parameters = listOf<Parameter>(
        TestParameter(logicalName = "param1", type = "String", defaultValue = "value1"),
        TestParameter(logicalName = "param2", type = "String", defaultValue = "value2")
    )

    @Before
    fun wireMocksTogetherWithValidOptions() {
        mockClientManagerRule.apply {
            create<CloudFormationClient>()
            create<S3Client>()
            create<EcrClient>()
        }

        val dir = Files.createDirectory(tempDir.newPath()).toAbsolutePath()
        runInEdtAndWait {
            val template = VfsUtil.findFileByIoFile(dir.writeChild("path.yaml", byteArrayOf()).toFile(), true)

            if (template != null) {
                sut = SyncServerlessApplicationDialog(
                    projectRule.project,
                    template,
                    emptyList<StackSummary>(),
                    loadResourcesOnCreate = false
                )
            }

            sutPanel = sut.getParameterDialog()
        }

        val repo = Repository("repoName", "arn", "repositoryuri")
        sut.forceUi(
            sutPanel,
            isCreateStack = false,
            hasImageFunctions = false,
            stacks = listOf(StackSummary.builder().stackName("stack123").build()),
            buckets = listOf("bucket123"),
            ecrRepos = listOf(repo),
            stackName = "stack123",
            bucket = "bucket123",
            ecrRepo = repo.repositoryName,
            useContainer = true
        )
        sut.populateParameters(parameters, parameters)
    }

    @Test
    fun `Valid inputs returns null`() {
        assertThat(validateAll()).isEmpty()
    }

    @Test
    fun `valid inputs no repo returns null`() {
        sut.forceUi(sutPanel, forceEcrRepo = true, ecrRepo = null)
        assertThat(validateAll()).isEmpty()
    }

    @Test
    fun `valid inputs with new stack returns null`() {
        sut.forceUi(sutPanel, isCreateStack = true, stackName = "createStack")
        assertThat(validateAll()).isEmpty()

        sut.forceUi(sutPanel, stackName = "n")
        assertThat(validateAll()).isEmpty()

        sut.forceUi(sutPanel, stackName = "n1")
        assertThat(validateAll()).isEmpty()
    }

    @Test
    fun `valid inputs with image returns null`() {
        sut.forceUi(sutPanel, hasImageFunctions = true)
        assertThat(validateAll()).isEmpty()
    }

    @Test
    fun `stack must be selected`() {
        sut.forceUi(sutPanel, isCreateStack = false, forceStackName = true, stackName = null)
        assertThat(validateAll()).singleElement()
            .matches { it.validate()?.message?.contains(message("serverless.application.sync.validation.stack.missing")) == true }
    }

    @Test
    fun `new stack name must be specified`() {
        sut.forceUi(sutPanel, isCreateStack = true, forceStackName = true, stackName = null)
        assertThat(validateAll()).singleElement()
            .matches { it.validate()?.message?.contains(message("serverless.application.sync.validation.new.stack.name.missing")) == true }
    }

    @Test
    fun `invalid stack name too long`() {
        val maxLength = ValidateSamParameters.MAX_STACK_NAME_LENGTH
        sut.forceUi(sutPanel, isCreateStack = true, stackName = "x".repeat(maxLength + 1))

        assertThat(validateAll()).singleElement()
            .matches { it.validate()?.message?.contains(message("serverless.application.deploy.validation.new.stack.name.too.long", maxLength)) == true }
    }

    @Test
    fun `invalid stack name duplicate`() {
        sut.forceUi(
            sutPanel,
            isCreateStack = true,
            stackName = "bar",
            stacks = listOf(
                StackSummary.builder().stackName("foo").build(),
                StackSummary.builder().stackName("bar").build(),
                StackSummary.builder().stackName("baz").build()
            )
        )

        assertThat(validateAll()).singleElement()
            .matches { it.validate()?.message?.contains(message("serverless.application.deploy.validation.new.stack.name.duplicate")) == true }
    }

    @Test
    fun `invalid stack name invalid chars`() {
        val invalid = listOf(
            "stack_1",
            "stack#1",
            "1stack",
            " stack",
            "stack!@#$%^&*()_+-="
        )
        invalid.forEach { stackName ->
            sut.forceUi(sutPanel, isCreateStack = true, stackName = stackName)
            assertThat(validateAll())
                .singleElement()
                .matches({
                    it.validate()?.message?.contains(message("serverless.application.deploy.validation.new.stack.name.invalid")) == true
                }, "for input $stackName")
        }
    }

    @Test
    fun `template parameter all types valid has values`() {
        val parameters = listOf<Parameter>(
            TestParameter(logicalName = "param1", type = "String", defaultValue = "value1"),
            TestParameter(logicalName = "param2", type = "Number", defaultValue = "1"),
            TestParameter(logicalName = "param3", type = "Number", defaultValue = "1.2"),
            TestParameter(logicalName = "param4", type = "List<Number>", defaultValue = "10,20,1.2"),
            TestParameter(logicalName = "param5", type = "CommaDelimitedList", defaultValue = "param1,param2"),
            TestParameter(logicalName = "param6", type = "AWS::EC2::AvailabilityZone::Name", defaultValue = "us-fake-1"),
            TestParameter(logicalName = "param7", type = "List<AWS::EC2::AvailabilityZone::Name>", defaultValue = "us-fake-1a,us-fake-1b"),
            TestParameter(logicalName = "param8", type = "AWS::SSM::Parameter::Value<String>", defaultValue = "something"),

        )
        sut.populateParameters(parameters, parameters)

        assertThat(validateAll()).isEmpty()
    }

    @Test
    fun `template parameter all types valid no values`() {
        val parameters = listOf<Parameter>(
            TestParameter(logicalName = "param1", type = "String", defaultValue = ""),
            TestParameter(logicalName = "param4", type = "List<Number>", defaultValue = ""),
            TestParameter(logicalName = "param5", type = "CommaDelimitedList", defaultValue = ""),
            TestParameter(logicalName = "param6", type = "AWS::EC2::AvailabilityZone::Name", defaultValue = ""),
            TestParameter(logicalName = "param7", type = "List<AWS::EC2::AvailabilityZone::Name>", defaultValue = ""),
            TestParameter(logicalName = "param8", type = "AWS::SSM::Parameter::Value<String>", defaultValue = ""),
        )
        sut.populateParameters(parameters, parameters)

        assertThat(validateAll()).isEmpty()
    }

    @Test
    fun `template parameterstring regex`() {
        val parameters = listOf<Parameter>(
            TestParameter(
                logicalName = "goodRegex",
                type = "String",
                defaultValue = "example@example.com",
                additionalProperties = mapOf(
                    "AllowedPattern" to "^[_A-Za-z0-9-\\+]+(\\.[_A-Za-z0-9-]+)*@[A-Za-z0-9-]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$"
                )
            )
        )
        sut.populateParameters(parameters, parameters)

        assertThat(validateAll()).isEmpty()
    }

    @Test
    fun `template parameterstring too short`() {
        val parameters = listOf<Parameter>(
            TestParameter(
                logicalName = "tooShort",
                type = "String",
                defaultValue = "",
                additionalProperties = mapOf(
                    "MinLength" to "1",
                    "MaxLength" to "5"
                )
            )
        )
        sut.populateParameters(parameters, parameters)

        assertThat(validateAll()).singleElement()
            .matches { it.validate()?.message?.contains("tooShort does not meet MinLength") == true }
    }

    @Test
    fun `template parameter string too long`() {
        val parameters = listOf<Parameter>(
            TestParameter(
                logicalName = "tooLong",
                type = "String",
                defaultValue = "aaaaaaaaaa",
                additionalProperties = mapOf(
                    "MinLength" to "1",
                    "MaxLength" to "5"
                )
            )
        )
        sut.populateParameters(parameters, parameters)

        assertThat(validateAll()).singleElement()
            .matches { it.validate()?.message?.contains("tooLong exceeds MaxLength") == true }
    }

    @Test
    fun `template parameter string fails regex`() {
        val parameters = listOf<Parameter>(
            TestParameter(
                logicalName = "regexFail",
                type = "String",
                defaultValue = "aaaaaaaaaa",
                additionalProperties = mapOf(
                    "AllowedPattern" to "b*"

                )
            )
        )
        sut.populateParameters(parameters, parameters)

        assertThat(validateAll()).singleElement()
            .matches { it.validate()?.message?.contains("regexFail does not match AllowedPattern") == true }
    }

    @Test
    fun `template parameter string constraints invalid`() {
        val parameters = listOf<Parameter>(
            TestParameter(
                logicalName = "badRegex",
                type = "String",
                defaultValue = "",
                additionalProperties = mapOf(
                    "AllowedPattern" to ")]]]]]totallyValidRegex([[[["
                )
            ),
            TestParameter(
                logicalName = "badLengthConstraints",
                type = "String",
                defaultValue = "",
                additionalProperties = mapOf(
                    "MinLength" to "-42",
                    "MaxLength" to "3.14"
                )
            )
        )
        sut.populateParameters(parameters, parameters)

        assertThat(validateAll()).singleElement()
            .matches { it.validate()?.message?.contains("AllowedPattern for badRegex is not valid") == true }
    }

    @Test
    fun `template parameter number invalid`() {
        val parameters = listOf<Parameter>(
            TestParameter(logicalName = "notANumber", type = "Number", defaultValue = "f"),
            TestParameter(logicalName = "notANumber2", type = "Number", defaultValue = "")
        )
        sut.populateParameters(parameters, parameters)

        assertThat(validateAll()).singleElement()
            .matches { it.validate()?.message?.contains("not a number") == true }
    }

    @Test
    fun `template parameter number too small`() {
        val parameters = listOf<Parameter>(
            TestParameter(
                logicalName = "tooSmall",
                type = "Number",
                defaultValue = "0",
                additionalProperties = mapOf(
                    "MinValue" to "0.1",
                    "MaxValue" to "5"
                )
            )
        )
        sut.populateParameters(parameters, parameters)

        assertThat(validateAll()).singleElement()
            .matches { it.validate()?.message?.contains("tooSmall is smaller than MinValue") == true }
    }

    @Test
    fun `template parameter number too big`() {
        val parameters = listOf<Parameter>(
            TestParameter(
                logicalName = "tooBig",
                type = "Number",
                defaultValue = "${Float.MAX_VALUE}",
                additionalProperties = mapOf(
                    "MinValue" to "0.1",
                    "MaxValue" to "5"
                )
            )
        )
        sut.populateParameters(parameters, parameters)

        assertThat(validateAll()).singleElement()
            .matches { it.validate()?.message?.contains("tooBig is larger than MaxValue") == true }
    }

    @Test
    fun `template parameter number constraints invalid`() {
        val parameters = listOf<Parameter>(
            TestParameter(
                logicalName = "badValueConstraints",
                type = "Number",
                defaultValue = "0",
                additionalProperties = mapOf(
                    "MinValue" to "--3",
                    "MaxValue" to "++3"
                )
            )
        )
        sut.populateParameters(parameters, parameters)

        assertThat(validateAll()).isEmpty()
    }

    @Test
    fun `s3 bucket must be specified`() {
        sut.forceUi(sutPanel, forceBucket = true, bucket = null)

        assertThat(validateAll()).singleElement()
            .matches { it.validate()?.message?.contains(message("serverless.application.sync.validation.s3.bucket.empty")) == true }
    }

    private fun validateAll(): List<DialogValidation> =
        sutPanel.validationsOnApply.flatMap { it.value }.filter { it.validate() != null }

    private class TestParameter(
        override val logicalName: String,
        private val type: String,
        private val defaultValue: String?,
        private val additionalProperties: Map<String, String> = emptyMap()
    ) : Parameter {
        override fun getScalarProperty(key: String): String = getOptionalScalarProperty(key) ?: throw Exception("Cannot be null")

        override fun getOptionalScalarProperty(key: String): String? {
            if (key == "Type") {
                return type
            }
            return additionalProperties[key]
        }

        override fun setScalarProperty(key: String, value: String) {
            throw NotImplementedError()
        }

        override fun getSequenceProperty(key: String): YAMLSequence {
            throw NotImplementedError()
        }

        override fun getOptionalSequenceProperty(key: String): YAMLSequence? {
            throw NotImplementedError()
        }

        override fun defaultValue(): String? = defaultValue

        override fun description(): String? = null

        override fun constraintDescription(): String? = null
    }
}


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

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

import com.intellij.testFramework.ProjectRule
import org.assertj.core.api.Assertions.assertThat
import org.junit.Rule
import org.junit.Test
import org.mockito.kotlin.any
import org.mockito.kotlin.argumentCaptor
import org.mockito.kotlin.doReturn
import org.mockito.kotlin.stub
import org.mockito.kotlin.verify
import software.amazon.awssdk.http.SdkHttpResponse
import software.amazon.awssdk.services.lambda.LambdaClient
import software.amazon.awssdk.services.lambda.model.CreateFunctionRequest
import software.amazon.awssdk.services.lambda.model.CreateFunctionResponse
import software.amazon.awssdk.services.lambda.model.GetFunctionConfigurationRequest
import software.amazon.awssdk.services.lambda.model.GetFunctionConfigurationResponse
import software.amazon.awssdk.services.lambda.model.GetFunctionRequest
import software.amazon.awssdk.services.lambda.model.GetFunctionResponse
import software.amazon.awssdk.services.lambda.model.PackageType
import software.amazon.awssdk.services.lambda.model.Runtime
import software.amazon.awssdk.services.lambda.model.State
import software.aws.toolkits.core.utils.test.aString
import software.aws.toolkits.jetbrains.core.MockClientManagerRule
import software.aws.toolkits.jetbrains.services.iam.IamRole
import software.aws.toolkits.jetbrains.services.lambda.steps.CreateLambda.Companion.FUNCTION_ARN
import software.aws.toolkits.jetbrains.services.lambda.upload.FunctionDetails
import software.aws.toolkits.jetbrains.utils.execution.steps.ConsoleMessageEmitter
import software.aws.toolkits.jetbrains.utils.execution.steps.Context

class CreateLambdaTest {
    @Rule
    @JvmField
    val projectRule = ProjectRule()

    @Rule
    @JvmField
    val clientManagerRule = MockClientManagerRule()

    @Test
    fun `can update S3 code`() {
        validate(
            UploadedS3Code(
                bucket = aString(),
                key = aString(),
                version = null
            ),
            FunctionDetails(
                name = aString(),
                description = aString(),
                packageType = PackageType.ZIP,
                runtime = Runtime.knownValues().random(),
                handler = aString(),
                iamRole = IamRole(aString()),
                envVars = mapOf(aString() to aString()),
                timeout = 300,
                memorySize = 1024,
                xrayEnabled = true
            )
        )
    }

    @Test
    fun `can update S3 code with version`() {
        validate(
            UploadedS3Code(
                bucket = aString(),
                key = aString(),
                version = aString()
            ),
            FunctionDetails(
                name = aString(),
                description = aString(),
                packageType = PackageType.ZIP,
                runtime = Runtime.knownValues().random(),
                handler = aString(),
                iamRole = IamRole(aString()),
                envVars = mapOf(aString() to aString()),
                timeout = 300,
                memorySize = 1024,
                xrayEnabled = false
            )
        )
    }

    @Test
    fun `can update the code and handler`() {
        validate(
            UploadedS3Code(
                bucket = aString(),
                key = aString(),
                version = null
            ),
            FunctionDetails(
                name = aString(),
                description = aString(),
                packageType = PackageType.ZIP,
                runtime = Runtime.knownValues().random(),
                handler = aString(),
                iamRole = IamRole(aString()),
                envVars = mapOf(aString() to aString()),
                timeout = 300,
                memorySize = 1024,
                xrayEnabled = true
            )
        )
    }

    @Test
    fun `can update the code from ecr`() {
        validate(
            UploadedEcrCode(
                imageUri = aString()
            ),
            FunctionDetails(
                name = aString(),
                description = aString(),
                packageType = PackageType.IMAGE,
                runtime = null,
                handler = null,
                iamRole = IamRole(aString()),
                envVars = mapOf(aString() to aString()),
                timeout = 300,
                memorySize = 1024,
                xrayEnabled = true
            )
        )
    }

    private fun validate(codeLocation: UploadedCode, details: FunctionDetails) {
        val requestCaptor = argumentCaptor<CreateFunctionRequest>()
        val lambdaClient = clientManagerRule.create<LambdaClient>().stub {
            on { createFunction(requestCaptor.capture()) } doReturn CreateFunctionResponse.builder().functionArn("arn of ${details.name}").build()
            on { getFunction(any<GetFunctionRequest>()) } doReturn with(GetFunctionResponse.builder()) {
                configuration { it.functionArn("arn of ${details.name}") }
                sdkHttpResponse(SdkHttpResponse.builder().statusCode(200).build()) // waiters validate the status code
                build()
            }
            on { getFunctionConfiguration(any<GetFunctionConfigurationRequest>()) } doReturn with(GetFunctionConfigurationResponse.builder()) {
                functionArn("arn of ${details.name}")
                state(State.ACTIVE)
                sdkHttpResponse(SdkHttpResponse.builder().statusCode(200).build()) // waiters validate the status code
                build()
            }
        }

        val context = Context()
        context.putAttribute(PackageLambda.UPLOADED_CODE_LOCATION, codeLocation)

        CreateLambda(lambdaClient, details).run(context, ConsoleMessageEmitter("CreateLambda"))

        verify(lambdaClient).createFunction(any<CreateFunctionRequest>())
        with(requestCaptor) {
            assertThat(allValues).hasSize(1)

            assertThat(firstValue.functionName()).isEqualTo(details.name)
            assertThat(firstValue.description()).isEqualTo(details.description)
            assertThat(firstValue.environment().variables()).isEqualTo(details.envVars)
            assertThat(firstValue.handler()).isEqualTo(details.handler)
            assertThat(firstValue.runtime()).isEqualTo(details.runtime)
            assertThat(firstValue.role()).isEqualTo(details.iamRole.arn)
            assertThat(firstValue.memorySize()).isEqualTo(details.memorySize)
            assertThat(firstValue.timeout()).isEqualTo(details.timeout)
            assertThat(firstValue.tracingConfig().mode()).isEqualTo(details.tracingMode)

            when (codeLocation) {
                is UploadedS3Code -> {
                    assertThat(firstValue.code().s3Bucket()).isEqualTo(codeLocation.bucket)
                    assertThat(firstValue.code().s3Key()).isEqualTo(codeLocation.key)
                    assertThat(firstValue.code().s3ObjectVersion()).isEqualTo(codeLocation.version)
                }
                is UploadedEcrCode -> {
                    assertThat(firstValue.code().imageUri()).isEqualTo(codeLocation.imageUri)
                }
            }
        }

        assertThat(context.getAttribute(FUNCTION_ARN)).isEqualTo("arn of ${details.name}")
    }
}


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

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

import com.intellij.testFramework.ProjectRule
import org.assertj.core.api.Assertions.assertThat
import org.assertj.core.api.Assertions.assertThatThrownBy
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.rules.TemporaryFolder
import software.aws.toolkits.core.utils.test.aString
import software.aws.toolkits.core.utils.writeText
import software.aws.toolkits.jetbrains.core.executables.ExecutableManager
import software.aws.toolkits.jetbrains.core.executables.setExecutablePath
import software.aws.toolkits.jetbrains.services.lambda.sam.SamCommonTestUtils
import software.aws.toolkits.jetbrains.services.lambda.sam.SamExecutable
import software.aws.toolkits.jetbrains.services.lambda.steps.PackageLambda.Companion.UPLOADED_CODE_LOCATION
import software.aws.toolkits.jetbrains.utils.execution.steps.ConsoleMessageEmitter
import software.aws.toolkits.jetbrains.utils.execution.steps.Context
import software.aws.toolkits.jetbrains.utils.value
import java.nio.file.Path

class PackageLambdaTest {
    @Rule
    @JvmField
    val projectRule = ProjectRule()

    @Rule
    @JvmField
    val tempFolder = TemporaryFolder()

    @Before
    fun setUp() {
        ExecutableManager.getInstance().removeExecutable(SamExecutable())
    }

    @Test
    fun `error fails the step`() {
        setSamExecutable(SamCommonTestUtils.makeATestSam(message = "We broke it", exitCode = -1))

        val sut = PackageLambda(
            templatePath = tempFolder.newFile().toPath(),
            packagedTemplatePath = tempFolder.newFile().toPath(),
            logicalId = aString(),
            envVars = emptyMap(),
            s3Bucket = aString()
        )

        assertThatThrownBy {
            sut.run(Context(), ConsoleMessageEmitter("PackageLambdaTest"))
        }.hasMessageContaining("We broke it")
    }

    @Test
    fun `s3 bucket URI is parsed`() {
        testPackageStep(
            packagedTemplate = """
                Resources:
                  Function:
                    Type: AWS::Serverless::Function
                    Properties:
                      Handler: helloworld.App::handleRequest
                      CodeUri: s3://FooBucket/Foo/Key
                      Runtime: java8.al2
                      Timeout: 300
                      MemorySize: 128
            """.trimIndent(),
            s3Bucket = aString()
        ) {
            assertThat(it).isInstanceOfSatisfying(UploadedS3Code::class.java) { code ->
                assertThat(code.bucket).isEqualTo("FooBucket")
                assertThat(code.key).isEqualTo("Foo/Key")
                assertThat(code.version).isNull()
            }
        }
    }

    @Test
    fun `s3 block is parsed`() {
        testPackageStep(
            packagedTemplate = """
                Resources:
                  Function:
                    Type: AWS::Serverless::Function
                    Properties:
                      Handler: helloworld.App::handleRequest
                      CodeUri:
                        Bucket: FooBucket
                        Key: FooKey
                        Version: FooVersion
                      Runtime: java8.al2
                      Timeout: 300
                      MemorySize: 128
            """.trimIndent(),
            s3Bucket = aString()
        ) {
            assertThat(it).isInstanceOfSatisfying(UploadedS3Code::class.java) { code ->
                assertThat(code.bucket).isEqualTo("FooBucket")
                assertThat(code.key).isEqualTo("FooKey")
                assertThat(code.version).isEqualTo("FooVersion")
            }
        }
    }

    @Test
    fun `image uri block is parsed`() {
        testPackageStep(
            packagedTemplate = """
                Resources:
                  Function:
                    Type: AWS::Serverless::Function
                    Properties:
                      PackageType: Image
                      ImageUri: 111122223333.dkr.ecr.us-east-1.amazonaws.com/repo:tag
                      Timeout: 300
                      MemorySize: 128
            """.trimIndent(),
            ecrRepo = aString()
        ) {
            assertThat(it).isInstanceOfSatisfying(UploadedEcrCode::class.java) { code ->
                assertThat(code.imageUri).isEqualTo("111122223333.dkr.ecr.us-east-1.amazonaws.com/repo:tag")
            }
        }
    }

    private fun testPackageStep(packagedTemplate: String, s3Bucket: String? = null, ecrRepo: String? = null, assertBlock: (UploadedCode) -> Unit = {}) {
        setSamExecutable(SamCommonTestUtils.makeATestSam(SamCommonTestUtils.getMinVersionAsJson()))

        val templatePath = tempFolder.newFile().toPath()
        templatePath.writeText(packagedTemplate)

        val sut = PackageLambda(
            templatePath = tempFolder.newFile().toPath(),
            packagedTemplatePath = templatePath,
            logicalId = "Function",
            envVars = emptyMap(),
            s3Bucket = s3Bucket,
            ecrRepo = ecrRepo
        )

        val context = Context()
        sut.run(context, ConsoleMessageEmitter("PackageLambdaTest"))

        val uploadedCode = context.getRequiredAttribute(UPLOADED_CODE_LOCATION)
        assertBlock(uploadedCode)
    }

    private fun setSamExecutable(path: Path) {
        ExecutableManager.getInstance().setExecutablePath<SamExecutable>(path).value
    }
}


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

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

import com.intellij.testFramework.ProjectRule
import org.assertj.core.api.Assertions.assertThat
import org.junit.Rule
import org.junit.Test
import org.mockito.kotlin.any
import org.mockito.kotlin.argumentCaptor
import org.mockito.kotlin.doReturn
import org.mockito.kotlin.stub
import org.mockito.kotlin.times
import org.mockito.kotlin.verify
import software.amazon.awssdk.services.lambda.LambdaClient
import software.amazon.awssdk.services.lambda.model.GetFunctionConfigurationRequest
import software.amazon.awssdk.services.lambda.model.GetFunctionConfigurationResponse
import software.amazon.awssdk.services.lambda.model.LastUpdateStatus
import software.amazon.awssdk.services.lambda.model.State
import software.amazon.awssdk.services.lambda.model.UpdateFunctionCodeRequest
import software.amazon.awssdk.services.lambda.model.UpdateFunctionCodeResponse
import software.amazon.awssdk.services.lambda.model.UpdateFunctionConfigurationRequest
import software.amazon.awssdk.services.lambda.model.UpdateFunctionConfigurationResponse
import software.aws.toolkits.core.utils.test.aString
import software.aws.toolkits.jetbrains.core.MockClientManagerRule
import software.aws.toolkits.jetbrains.utils.execution.steps.ConsoleMessageEmitter
import software.aws.toolkits.jetbrains.utils.execution.steps.Context

class UpdateLambdaCodeTest {
    @Rule
    @JvmField
    val projectRule = ProjectRule()

    @Rule
    @JvmField
    val clientManagerRule = MockClientManagerRule()

    @Test
    fun `can update S3 code`() {
        validate(
            UploadedS3Code(
                bucket = aString(),
                key = aString(),
                version = null
            )
        )
    }

    @Test
    fun `can update S3 code with version`() {
        validate(
            UploadedS3Code(
                bucket = aString(),
                key = aString(),
                version = aString()
            )
        )
    }

    @Test
    fun `can update the code and handler`() {
        validate(
            UploadedS3Code(
                bucket = aString(),
                key = aString(),
                version = null
            ),
            handler = aString()
        )
    }

    @Test
    fun `can update image based code`() {
        validate(
            UploadedEcrCode(
                imageUri = aString()
            )
        )
    }

    private fun validate(codeLocation: UploadedCode, handler: String? = null) {
        val codeRequestCaptor = argumentCaptor<UpdateFunctionCodeRequest>()
        val configRequestCaptor = argumentCaptor<UpdateFunctionConfigurationRequest>()
        val lambdaClient = clientManagerRule.create<LambdaClient>().stub {
            on { updateFunctionCode(codeRequestCaptor.capture()) } doReturn UpdateFunctionCodeResponse.builder().build()
            on { updateFunctionConfiguration(configRequestCaptor.capture()) } doReturn UpdateFunctionConfigurationResponse.builder().build()
            on { getFunctionConfiguration(any<GetFunctionConfigurationRequest>()) } doReturn GetFunctionConfigurationResponse.builder()
                .state(State.ACTIVE)
                .lastUpdateStatus(LastUpdateStatus.SUCCESSFUL)
                .build()
        }
        val functionName = aString()

        val context = Context()
        context.putAttribute(PackageLambda.UPLOADED_CODE_LOCATION, codeLocation)

        UpdateLambdaCode(lambdaClient, functionName, handler).run(context, ConsoleMessageEmitter("UpdateLambdaCode"))

        verify(lambdaClient).updateFunctionCode(any<UpdateFunctionCodeRequest>())
        with(codeRequestCaptor) {
            assertThat(allValues).hasSize(1)

            assertThat(firstValue.functionName()).isEqualTo(functionName)

            when (codeLocation) {
                is UploadedS3Code -> {
                    assertThat(firstValue.s3Bucket()).isEqualTo(codeLocation.bucket)
                    assertThat(firstValue.s3Key()).isEqualTo(codeLocation.key)
                    assertThat(firstValue.s3ObjectVersion()).isEqualTo(codeLocation.version)
                }
                is UploadedEcrCode -> {
                    assertThat(firstValue.imageUri()).isEqualTo(codeLocation.imageUri)
                }
            }
        }

        if (handler == null) {
            verify(lambdaClient, times(0)).updateFunctionConfiguration(any<UpdateFunctionConfigurationRequest>())
        } else {
            verify(lambdaClient).updateFunctionConfiguration(any<UpdateFunctionConfigurationRequest>())
            with(configRequestCaptor) {
                assertThat(allValues).hasSize(1)

                assertThat(firstValue.functionName()).isEqualTo(functionName)
                assertThat(firstValue.handler()).isEqualTo(handler)
            }
        }
    }
}


// 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.ProjectRule
import com.intellij.testFramework.runInEdtAndGet
import com.intellij.testFramework.runInEdtAndWait
import org.assertj.core.api.Assertions.assertThat
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import software.amazon.awssdk.services.lambda.model.PackageType
import software.amazon.awssdk.services.s3.model.Bucket
import software.aws.toolkits.core.utils.test.aString
import software.aws.toolkits.jetbrains.core.MockClientManagerRule
import software.aws.toolkits.jetbrains.core.MockResourceCacheRule
import software.aws.toolkits.jetbrains.core.credentials.activeRegion
import software.aws.toolkits.jetbrains.services.ecr.resources.EcrResources
import software.aws.toolkits.jetbrains.services.ecr.resources.Repository
import software.aws.toolkits.jetbrains.services.s3.resources.S3Resources
import software.aws.toolkits.jetbrains.utils.waitToLoad

class CodeStoragePanelTest {
    @JvmField
    @Rule
    val projectRule = ProjectRule()

    @JvmField
    @Rule
    val mockClientManager = MockClientManagerRule()

    @JvmField
    @Rule
    val mockResourceCache = MockResourceCacheRule()

    private lateinit var bucketName: String
    private lateinit var repository: Repository

    @Before
    fun setUp() {
        bucketName = aString()
        repository = Repository(aString(), "arn", aString())

        val region = projectRule.project.activeRegion()

        mockResourceCache.addEntry(
            projectRule.project,
            S3Resources.LIST_REGIONALIZED_BUCKETS,
            listOf(S3Resources.RegionalizedBucket(Bucket.builder().name(bucketName).build(), region))
        )

        mockResourceCache.addEntry(
            projectRule.project,
            EcrResources.LIST_REPOS,
            listOf(repository)
        )
    }

    @Test
    fun `valid code storage for Zip returns null`() {
        val sut = createZipBasedCodeStorage()
        runInEdtAndWait {
            assertThat(sut.validatePanel()).isNull()
        }
    }

    @Test
    fun `code location for Zip returns bucket`() {
        val sut = createZipBasedCodeStorage()
        runInEdtAndWait {
            assertThat(sut.codeLocation()).isEqualTo(bucketName)
        }
    }

    @Test
    fun `bucket must be specified for Zip`() {
        val sut = createZipBasedCodeStorage()
        runInEdtAndWait {
            sut.sourceBucket.selectedItem = null
            assertThat(sut.validatePanel()?.message).contains("Bucket must be specified")
        }
    }

    @Test
    fun `valid code storage for Image returns null`() {
        val sut = createImageBasedCodeStorage()
        runInEdtAndWait {
            assertThat(sut.validatePanel()).isNull()
        }
    }

    @Test
    fun `code location for Image returns repo`() {
        val sut = createImageBasedCodeStorage()
        runInEdtAndWait {
            assertThat(sut.codeLocation()).isEqualTo(repository.repositoryUri)
        }
    }

    @Test
    fun `repo must be specified for Image`() {
        val sut = createImageBasedCodeStorage()
        runInEdtAndWait {
            sut.ecrRepo.selectedItem = null
            assertThat(sut.validatePanel()?.message).contains("Repository must be specified")
        }
    }

    private fun createZipBasedCodeStorage(): CodeStoragePanel {
        val panel = runInEdtAndGet {
            CodeStoragePanel(projectRule.project).apply {
                packagingType = PackageType.ZIP
                sourceBucket.selectedItem = bucketName
            }
        }

        panel.sourceBucket.waitToLoad()

        return panel
    }

    private fun createImageBasedCodeStorage(): CodeStoragePanel {
        val panel = runInEdtAndGet {
            CodeStoragePanel(projectRule.project).apply {
                packagingType = PackageType.IMAGE
                ecrRepo.selectedItem = repository
            }
        }

        panel.ecrRepo.waitToLoad()

        return panel
    }
}


// Copyright 2019 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.ProjectRule
import com.intellij.testFramework.runInEdtAndGet
import org.assertj.core.api.Assertions.assertThat
import org.junit.Rule
import org.junit.Test
import software.aws.toolkits.jetbrains.services.lambda.LambdaBuilder

class CreateFunctionDialogTest {
    @JvmField
    @Rule
    val projectRule = ProjectRule()

    @Test
    fun `dialog only shows runtimes we can build`() {
        val dialog = runInEdtAndGet {
            CreateFunctionDialog(project = projectRule.project, initialRuntime = null, handlerName = null)
        }
        assertThat(dialog.getViewForTestAssertions().configSettings.runtimeModel.items)
            .containsExactlyInAnyOrderElementsOf(LambdaBuilder.supportedRuntimeGroups().flatMap { it.supportedSdkRuntimes })
    }
}


// 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.openapi.application.runWriteAction
import com.intellij.openapi.projectRoots.ProjectJdkTable
import com.intellij.openapi.roots.ProjectRootManager
import com.intellij.testFramework.IdeaTestUtil
import com.intellij.testFramework.runInEdtAndWait
import org.assertj.core.api.Assertions.assertThat
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import software.amazon.awssdk.services.iam.model.Role
import software.amazon.awssdk.services.lambda.model.Runtime
import software.amazon.awssdk.services.s3.model.Bucket
import software.aws.toolkits.core.utils.test.aString
import software.aws.toolkits.jetbrains.core.MockResourceCacheRule
import software.aws.toolkits.jetbrains.core.credentials.activeRegion
import software.aws.toolkits.jetbrains.services.iam.IamResources
import software.aws.toolkits.jetbrains.services.s3.resources.S3Resources
import software.aws.toolkits.jetbrains.utils.rules.JavaCodeInsightTestFixtureRule
import software.aws.toolkits.jetbrains.utils.rules.openClass

class CreateFunctionPanelTest {
    @Rule
    @JvmField
    val projectRule = JavaCodeInsightTestFixtureRule()

    @Rule
    @JvmField
    val resourceCache = MockResourceCacheRule()

    private lateinit var sut: CreateFunctionPanel

    private val role = Role.builder()
        .arn(aString())
        .assumeRolePolicyDocument(LAMBDA_PRINCIPAL)
        .build()

    private val bucket = Bucket.builder().name(aString()).build()

    @Before
    fun wireMocksTogetherWithValidOptions() {
        val project = projectRule.project

        resourceCache.addEntry(
            project,
            IamResources.LIST_RAW_ROLES,
            listOf(role)
        )

        resourceCache.addEntry(
            project,
            S3Resources.LIST_REGIONALIZED_BUCKETS,
            listOf(S3Resources.RegionalizedBucket(bucket, project.activeRegion()))
        )

        val sdk = IdeaTestUtil.getMockJdk18()
        runInEdtAndWait {
            runWriteAction {
                ProjectJdkTable.getInstance().addJdk(sdk, projectRule.fixture.projectDisposable)
                ProjectRootManager.getInstance(project).projectSdk = sdk
            }
            sut = CreateFunctionPanel(project)

            sut.name.text = "name"
            sut.description.text = "description"
            sut.configSettings.handlerPanel.handler.text = "com.example.LambdaHandler::handleRequest"
            sut.configSettings.runtime.selectedItem = Runtime.JAVA8
            sut.configSettings.timeoutSlider.value = 30
            sut.configSettings.memorySlider.value = 512
        }

        projectRule.fixture.openClass(
            """
            package com.example;
            public class LambdaHandler {
                public static void handleRequest(InputStream input, OutputStream output) { }
            }
            """
        )
    }

    @Test
    fun `valid function return nulls`() {
        assertThat(sut.validatePanel()).isNull()
    }

    @Test
    fun `name must be specified`() {
        sut.name.text = ""
        assertThat(sut.validatePanel()?.message).contains("Function Name must be specified")
    }

    @Test
    fun `function name has a valid length`() {
        sut.name.text = "aStringThatIsGreaterThanSixtyFourCharactersInLengthAndIsThereforeInvalid"
        assertThat(sut.validatePanel()?.message).contains("must not exceed 64 characters")
    }

    @Test
    fun `function name must be alpha numeric`() {
        sut.name.text = "a string"
        assertThat(sut.validatePanel()?.message).contains("alphanumerics")
    }
}


// Copyright 2019 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.psi.PsiElement
import com.intellij.psi.SmartPointerManager
import com.intellij.psi.SmartPsiElementPointer
import com.intellij.testFramework.DisposableRule
import com.intellij.testFramework.ExtensionTestUtil
import com.intellij.testFramework.TestActionEvent
import com.intellij.testFramework.runInEdtAndWait
import org.assertj.core.api.Assertions.assertThat
import org.assertj.core.api.Assertions.assertThatThrownBy
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.mockito.kotlin.any
import org.mockito.kotlin.doAnswer
import org.mockito.kotlin.mock
import software.aws.toolkits.jetbrains.services.lambda.LambdaHandlerResolver
import software.aws.toolkits.jetbrains.utils.rules.JavaCodeInsightTestFixtureRule
import software.aws.toolkits.jetbrains.utils.rules.openFile

class CreateLambdaFunctionActionTest {
    @Rule
    @JvmField
    val projectRule = JavaCodeInsightTestFixtureRule()

    @Rule
    @JvmField
    val disposableRule = DisposableRule()

    lateinit var smartElement: SmartPsiElementPointer<PsiElement>

    @Before
    fun setup() {
        val fixture = projectRule.fixture

        val element = fixture.addClass(
            """
public class Processor {
    public void handler() {

    }
}
        """
        ).findMethodsByName("handler", false).first()

        runInEdtAndWait {
            smartElement = SmartPointerManager.createPointer(element)
        }

        fixture.openFile(
            "template.yaml",
            """
Resources:
  ServerlessFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: foo
      Handler: helloworld.App::handleRequest
      Runtime: foo
      Timeout: 800
"""
        )
    }

    @Test
    fun InvalidNullArgs() {
        val handlerName = "helloworld.App::handleRequest"

        runInEdtAndWait {
            assertThatThrownBy { CreateLambdaFunctionAction(handlerName, null, null) }.isInstanceOf(java.lang.IllegalArgumentException::class.java)
        }
    }

    @Test
    fun InvalidNullArgs_Element() {
        val handlerName = "helloworld.App::handleRequest"
        val handlerResolver = mock<LambdaHandlerResolver> {
            on { determineHandlers(any(), any()) }.doAnswer { setOf(handlerName) }
        }

        runInEdtAndWait {
            assertThatThrownBy { CreateLambdaFunctionAction(handlerName, null, handlerResolver) }.isInstanceOf(java.lang.IllegalArgumentException::class.java)
        }
    }

    @Test
    fun InvalidNullArgs_HandlerResolver() {
        val handlerName = "helloworld.App::handleRequest"

        runInEdtAndWait {
            assertThatThrownBy { CreateLambdaFunctionAction(handlerName, smartElement, null) }.isInstanceOf(java.lang.IllegalArgumentException::class.java)
        }
    }

    @Test
    fun SamFunction() {
        val handlerName = "helloworld.App::handleRequest"
        val handlerResolver = mock<LambdaHandlerResolver> {
            on { determineHandlers(any(), any()) }.doAnswer { setOf(handlerName) }
        }

        runInEdtAndWait {
            val action = CreateLambdaFunctionAction(handlerName, smartElement, handlerResolver)

            val actionEvent = TestActionEvent()
            action.update(actionEvent)

            assertThat(actionEvent.presentation.isVisible).isFalse()
        }
    }

    @Test
    fun NonSamFunction() {
        val handlerName = "helloworld.App2::handleRequest"
        val handlerResolver = mock<LambdaHandlerResolver> {
            on { determineHandlers(any(), any()) }.doAnswer { setOf(handlerName) }
        }

        runInEdtAndWait {
            val action = CreateLambdaFunctionAction(handlerName, smartElement, handlerResolver)

            val actionEvent = TestActionEvent()
            action.update(actionEvent)

            assertThat(actionEvent.presentation.isVisible).isTrue()
        }
    }

    @Test
    fun NonSamFunction_Substring() {
        val handlerName = "helloworld.App::handleReques"
        val handlerResolver = mock<LambdaHandlerResolver> {
            on { determineHandlers(any(), any()) }.doAnswer { setOf(handlerName) }
        }

        runInEdtAndWait {
            val action = CreateLambdaFunctionAction(handlerName, smartElement, handlerResolver)

            val actionEvent = TestActionEvent()
            action.update(actionEvent)

            assertThat(actionEvent.presentation.isVisible).isTrue()
        }
    }

    @Test
    fun `Supported runtime groups shows action`() {
        // With no masking it should be visible because we have runtime groups
        runInEdtAndWait {
            val action = CreateLambdaFunctionAction()
            val actionEvent = TestActionEvent()
            action.update(actionEvent)
            assertThat(actionEvent.presentation.isVisible).isTrue()
        }
    }

    @Test
    fun `No supported runtime groups hides action`() {
        ExtensionTestUtil.maskExtensions(
            LambdaHandlerResolver.extensionPointName,
            listOf(),
            disposableRule.disposable
        )
        runInEdtAndWait {
            val action = CreateLambdaFunctionAction()
            val actionEvent = TestActionEvent()
            action.update(actionEvent)
            assertThat(actionEvent.presentation.isVisible).isFalse()
        }
    }
}


// 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.openapi.application.runWriteAction
import com.intellij.openapi.projectRoots.ProjectJdkTable
import com.intellij.openapi.roots.ProjectRootManager
import com.intellij.testFramework.IdeaTestUtil
import com.intellij.testFramework.runInEdtAndGet
import com.intellij.testFramework.runInEdtAndWait
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.services.iam.model.Role
import software.amazon.awssdk.services.lambda.model.PackageType
import software.amazon.awssdk.services.lambda.model.Runtime
import software.aws.toolkits.core.utils.test.aString
import software.aws.toolkits.jetbrains.core.MockResourceCacheRule
import software.aws.toolkits.jetbrains.services.iam.IamResources
import software.aws.toolkits.jetbrains.services.iam.IamRole
import software.aws.toolkits.jetbrains.utils.rules.JavaCodeInsightTestFixtureRule
import software.aws.toolkits.jetbrains.utils.rules.openClass
import software.aws.toolkits.jetbrains.utils.waitToLoad

class LambdaConfigPanelTest {
    @Rule
    @JvmField
    val projectRule = JavaCodeInsightTestFixtureRule()

    @Rule
    @JvmField
    val resourceCache = MockResourceCacheRule()

    @Rule
    @JvmField
    val temporaryFolder = TemporaryFolder()

    private val role = Role.builder()
        .arn(aString())
        .assumeRolePolicyDocument(LAMBDA_PRINCIPAL)
        .build()

    @Before
    fun wireMocksTogetherWithValidOptions() {
        val project = projectRule.project

        resourceCache.addEntry(
            project,
            IamResources.LIST_RAW_ROLES,
            listOf(role)
        )

        val sdk = IdeaTestUtil.getMockJdk18()
        runInEdtAndWait {
            runWriteAction {
                ProjectJdkTable.getInstance().addJdk(sdk, projectRule.fixture.projectDisposable)
                ProjectRootManager.getInstance(project).projectSdk = sdk
            }
        }

        projectRule.fixture.openClass(
            """
            package com.example;
            public class LambdaHandler {
                public static void handleRequest(InputStream input, OutputStream output) { }
            }
            """
        )
    }

    @Test
    fun `valid zip config returns null when create`() {
        val sut = createConfigPanel(isUpdate = false)
        runInEdtAndWait {
            sut.packageZip.isSelected = true
            assertThat(sut.validatePanel()).isNull()
        }
    }

    @Test
    fun `valid zip config returns null when update`() {
        val sut = createConfigPanel(isUpdate = true)
        runInEdtAndWait {
            sut.packageZip.isSelected = true
            assertThat(sut.validatePanel()).isNull()
        }
    }

    @Test
    fun `valid image config returns null whe create`() {
        val sut = createConfigPanel(isUpdate = false)
        runInEdtAndWait {
            sut.packageImage.isSelected = true
            assertThat(sut.validatePanel()).isNull()
        }
    }

    @Test
    fun `valid image config returns null whe update`() {
        val sut = createConfigPanel(isUpdate = true)
        runInEdtAndWait {
            sut.packageImage.isSelected = true
            assertThat(sut.validatePanel()).isNull()
        }
    }

    @Test
    fun `handler cannot be blank`() {
        val sut = createConfigPanel(isUpdate = false)
        runInEdtAndWait {
            sut.handlerPanel.handler.text = ""
        }
        assertThat(sut.validatePanel()?.message).contains("Handler must be specified")
    }

    @Test
    fun `handler must exist to build when create`() {
        val sut = createConfigPanel(isUpdate = false)
        runInEdtAndWait {
            sut.handlerPanel.handler.text = "Foo"
        }
        assertThat(sut.validatePanel()?.message).contains("Must be able to locate the handler")
    }

    @Test
    fun `handler may not exist when update`() {
        val sut = createConfigPanel(isUpdate = true)
        runInEdtAndWait {
            sut.handlerPanel.handler.text = "Foo"
        }
        assertThat(sut.validatePanel()).isNull()
    }

    @Test
    fun `runtime must be selected`() {
        val sut = createConfigPanel(isUpdate = false)
        sut.runtime.selectedItem = null
        assertThat(sut.validatePanel()?.message).contains("Runtime must be specified")
    }

    @Test
    fun `iam role must be selected`() {
        val sut = createConfigPanel(isUpdate = false)
        sut.iamRole.selectedItem = null
        assertThat(sut.validatePanel()?.message).contains("IAM role must be specified")
    }

    @Test
    fun `timeout must be specified`() {
        val sut = createConfigPanel(isUpdate = false)
        sut.timeoutSlider.textField.text = ""
        assertThat(sut.validatePanel()?.message).contains("The specified value must be an integer and between")
    }

    @Test
    fun `timeout must be numeric`() {
        val sut = createConfigPanel(isUpdate = false)
        sut.timeoutSlider.textField.text = "foo"
        assertThat(sut.validatePanel()?.message).contains("The specified value must be an integer and between")
    }

    @Test
    fun `timeout must be positive`() {
        val sut = createConfigPanel(isUpdate = false)
        sut.timeoutSlider.textField.text = "-1"
        assertThat(sut.validatePanel()?.message).contains("The specified value must be an integer and between")
    }

    @Test
    fun `timeout must be within lower bound`() {
        val sut = createConfigPanel(isUpdate = false)
        sut.timeoutSlider.textField.text = "0"
        assertThat(sut.validatePanel()?.message).contains("The specified value must be an integer and between")
    }

    @Test
    fun `timeout must be within upper bound`() {
        val sut = createConfigPanel(isUpdate = false)
        sut.timeoutSlider.textField.text = Integer.MAX_VALUE.toString()
        assertThat(sut.validatePanel()?.message).contains("The specified value must be an integer and between")
    }

    @Test
    fun `memory must be specified`() {
        val sut = createConfigPanel(isUpdate = false)
        sut.memorySlider.textField.text = ""
        assertThat(sut.validatePanel()?.message).contains("The specified value must be an integer and between")
    }

    @Test
    fun `memory mus be numeric`() {
        val sut = createConfigPanel(isUpdate = false)
        sut.memorySlider.textField.text = "foo"
        assertThat(sut.validatePanel()?.message).contains("The specified value must be an integer and between")
    }

    @Test
    fun `memory must be positive`() {
        val sut = createConfigPanel(isUpdate = false)
        sut.memorySlider.textField.text = "-1"
        assertThat(sut.validatePanel()?.message).contains("The specified value must be an integer and between")
    }

    @Test
    fun `memory must be within lower bound`() {
        val sut = createConfigPanel(isUpdate = false)
        sut.memorySlider.textField.text = "0"
        assertThat(sut.validatePanel()?.message).contains("The specified value must be an integer and between")
    }

    @Test
    fun `memory must be within upper bound`() {
        val sut = createConfigPanel(isUpdate = false)
        sut.memorySlider.textField.text = Integer.MAX_VALUE.toString()
        assertThat(sut.validatePanel()?.message).contains("The specified value must be an integer and between")
    }

    @Test
    fun `dockerfile must be a found if in image mode and not an update`() {
        val sut = createConfigPanel(isUpdate = false)
        runInEdtAndWait {
            sut.packageImage.isSelected = true
            sut.dockerFile.text = ""
            assertThat(sut.validatePanel()?.message).contains("Dockerfile not found")
        }
    }

    @Test
    fun `dockerfile must exist if in image mode and not an update`() {
        val sut = createConfigPanel(isUpdate = false)
        runInEdtAndWait {
            sut.packageImage.isSelected = true
            sut.dockerFile.text = "iDontExist"
            assertThat(sut.validatePanel()?.message).contains("Dockerfile not found")
        }
    }

    @Test
    fun `dockerfile must be a file if in image mode and not an update`() {
        val sut = createConfigPanel(isUpdate = false)
        runInEdtAndWait {
            sut.packageImage.isSelected = true
            sut.dockerFile.text = temporaryFolder.newFolder().absolutePath
            assertThat(sut.validatePanel()?.message).contains("Dockerfile not found")
        }
    }

    @Test
    fun `dockerfile is not validated when an update`() {
        val sut = createConfigPanel(isUpdate = true)
        runInEdtAndWait {
            sut.packageImage.isSelected = true
            sut.dockerFile.text = "iDonExist"
            assertThat(sut.validatePanel()).isNull()
        }
    }

    @Test
    fun `correct elements are showing when image is selected when not in update mode`() {
        val sut = createConfigPanel(isUpdate = false)
        runInEdtAndWait {
            sut.packageImage.isSelected = true

            assertThat(sut.packageType()).isEqualTo(PackageType.IMAGE)
            assertThat(sut.packageZip.isSelected).isFalse()
            assertThat(sut.handlerLabel.isVisible).isFalse()
            assertThat(sut.handlerPanel.isVisible).isFalse()
            assertThat(sut.runtimeLabel.isVisible).isFalse()
            assertThat(sut.runtime.isVisible).isFalse()

            assertThat(sut.dockerFileLabel.isVisible).isTrue()
            assertThat(sut.dockerFile.isVisible).isTrue()
        }
    }

    @Test
    fun `correct elements are showing when image is selected when in update mode`() {
        val sut = createConfigPanel(isUpdate = true)
        runInEdtAndWait {
            sut.packageImage.isSelected = true

            assertThat(sut.packageType()).isEqualTo(PackageType.IMAGE)
            assertThat(sut.packageZip.isSelected).isFalse()
            assertThat(sut.handlerLabel.isVisible).isFalse()
            assertThat(sut.handlerPanel.isVisible).isFalse()
            assertThat(sut.runtimeLabel.isVisible).isFalse()
            assertThat(sut.runtime.isVisible).isFalse()

            assertThat(sut.dockerFileLabel.isVisible).isFalse()
            assertThat(sut.dockerFile.isVisible).isFalse()
        }
    }

    @Test
    fun `correct elements are showing when zip is selected`() {
        val sut = createConfigPanel(isUpdate = false)
        runInEdtAndWait {
            sut.packageZip.isSelected = true

            assertThat(sut.packageType()).isEqualTo(PackageType.ZIP)
            assertThat(sut.packageZip.isSelected).isTrue()
            assertThat(sut.handlerLabel.isVisible).isTrue()
            assertThat(sut.handlerPanel.isVisible).isTrue()
            assertThat(sut.runtimeLabel.isVisible).isTrue()
            assertThat(sut.runtime.isVisible).isTrue()

            assertThat(sut.dockerFileLabel.isVisible).isFalse()
            assertThat(sut.dockerFile.isVisible).isFalse()
        }
    }

    private fun createConfigPanel(isUpdate: Boolean): LambdaConfigPanel {
        val sut = runInEdtAndGet {
            LambdaConfigPanel(projectRule.project, isUpdate = isUpdate).also {
                it.dockerFile.text = temporaryFolder.newFile().absolutePath
                it.handlerPanel.handler.text = "com.example.LambdaHandler::handleRequest"
                it.runtime.selectedItem = Runtime.JAVA8
                it.timeoutSlider.value = 30
                it.memorySlider.value = 512
            }
        }

        sut.iamRole.waitToLoad()

        runInEdtAndWait {
            sut.iamRole.selectedItem = IamRole(role.arn())
        }

        return sut
    }
}


// Copyright 2019 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.ProjectRule
import com.intellij.testFramework.runInEdtAndGet
import org.assertj.core.api.Assertions.assertThat
import org.junit.Rule
import org.junit.Test
import software.amazon.awssdk.services.lambda.model.PackageType
import software.amazon.awssdk.services.lambda.model.Runtime
import software.amazon.awssdk.services.s3.model.Bucket
import software.aws.toolkits.core.utils.RuleUtils
import software.aws.toolkits.core.utils.test.aString
import software.aws.toolkits.core.utils.test.retryableAssert
import software.aws.toolkits.jetbrains.core.MockClientManagerRule
import software.aws.toolkits.jetbrains.core.MockResourceCacheRule
import software.aws.toolkits.jetbrains.core.credentials.activeRegion
import software.aws.toolkits.jetbrains.services.iam.IamRole
import software.aws.toolkits.jetbrains.services.lambda.LambdaFunction
import software.aws.toolkits.jetbrains.services.s3.resources.S3Resources
import software.aws.toolkits.jetbrains.settings.UpdateLambdaSettings
import software.aws.toolkits.jetbrains.utils.waitToLoad

class UpdateFunctionCodeDialogTest {
    @JvmField
    @Rule
    val projectRule = ProjectRule()

    @JvmField
    @Rule
    val mockClientManager = MockClientManagerRule()

    @JvmField
    @Rule
    val mockResourceCache = MockResourceCacheRule()

    @Test
    fun `Loads saved settings if function arn matches`() {
        mockBuckets()

        val arn = aString()
        val settings = UpdateLambdaSettings.getInstance(arn)

        settings.bucketName = "hello2"
        settings.useContainer = true

        val dialog = runInEdtAndGet {
            UpdateFunctionCodeDialog(project = projectRule.project, initialSettings = aLambdaFunction().copy(arn = arn))
        }
        dialog.getViewForTestAssertions().codeStorage.sourceBucket.waitToLoad()

        retryableAssert {
            assertThat(dialog.getViewForTestAssertions().buildSettings.buildInContainerCheckbox.isSelected).isEqualTo(true)
            assertThat(dialog.getViewForTestAssertions().codeStorage.sourceBucket.selectedItem?.toString()).isEqualTo("hello2")
        }
    }

    @Test
    fun `Does not load saved settings if function arn does not match`() {
        mockBuckets()

        val arn = RuleUtils.randomName()
        val settings = UpdateLambdaSettings.getInstance(arn)

        settings.bucketName = "hello2"
        settings.useContainer = true

        val dialog = runInEdtAndGet {
            UpdateFunctionCodeDialog(project = projectRule.project, initialSettings = aLambdaFunction().copy(arn = "not$arn"))
        }
        dialog.getViewForTestAssertions().codeStorage.sourceBucket.waitToLoad()

        retryableAssert {
            assertThat(dialog.getViewForTestAssertions().buildSettings.buildInContainerCheckbox.isSelected).isEqualTo(false)
            assertThat(dialog.getViewForTestAssertions().codeStorage.sourceBucket.selectedItem?.toString()).isNull()
        }
    }

    private fun mockBuckets() {
        val region = projectRule.project.activeRegion()

        mockResourceCache.addEntry(
            projectRule.project,
            S3Resources.LIST_REGIONALIZED_BUCKETS,
            listOf(
                S3Resources.RegionalizedBucket(Bucket.builder().name("hello").build(), region),
                S3Resources.RegionalizedBucket(Bucket.builder().name("hello2").build(), region)
            )
        )
    }

    private fun aLambdaFunction() = LambdaFunction(
        name = aString(),
        description = aString(),
        packageType = PackageType.ZIP,
        arn = aString(),
        lastModified = "",
        handler = aString(),
        runtime = Runtime.UNKNOWN_TO_SDK_VERSION,
        timeout = 1,
        memorySize = 1,
        xrayEnabled = false,
        role = IamRole(aString()),
        envVariables = emptyMap()
    )
}


// Copyright 2019 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.openapi.application.runWriteAction
import com.intellij.openapi.projectRoots.ProjectJdkTable
import com.intellij.openapi.roots.ProjectRootManager
import com.intellij.testFramework.IdeaTestUtil
import com.intellij.testFramework.runInEdtAndGet
import com.intellij.testFramework.runInEdtAndWait
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.services.lambda.model.PackageType
import software.amazon.awssdk.services.lambda.model.Runtime
import software.amazon.awssdk.services.s3.model.Bucket
import software.aws.toolkits.core.utils.test.aString
import software.aws.toolkits.jetbrains.core.MockResourceCacheRule
import software.aws.toolkits.jetbrains.core.credentials.activeRegion
import software.aws.toolkits.jetbrains.services.ecr.resources.EcrResources
import software.aws.toolkits.jetbrains.services.ecr.resources.Repository
import software.aws.toolkits.jetbrains.services.s3.resources.S3Resources
import software.aws.toolkits.jetbrains.utils.rules.JavaCodeInsightTestFixtureRule
import software.aws.toolkits.jetbrains.utils.waitToLoad

class UpdateFunctionCodePanelTest {
    @Rule
    @JvmField
    val projectRule = JavaCodeInsightTestFixtureRule()

    @Rule
    @JvmField
    val resourceCache = MockResourceCacheRule()

    @Rule
    @JvmField
    val temporaryFolder = TemporaryFolder()

    private lateinit var bucketName: String
    private lateinit var repository: Repository

    @Before
    fun wireMocksTogetherWithValidOptions() {
        val project = projectRule.project
        bucketName = aString()
        repository = Repository(aString(), "arn", aString())

        resourceCache.addEntry(
            project,
            S3Resources.LIST_REGIONALIZED_BUCKETS,
            listOf(S3Resources.RegionalizedBucket(Bucket.builder().name(bucketName).build(), project.activeRegion()))
        )

        resourceCache.addEntry(
            project,
            EcrResources.LIST_REPOS,
            listOf(repository)
        )
    }

    @Test
    fun `valid panel returns null for Zip`() {
        val sut = createZipBasedCodePanel()
        assertThat(sut.validatePanel()).isNull()
    }

    @Test
    fun `source bucket must be selected if Zip based`() {
        val sut = createZipBasedCodePanel()
        runInEdtAndWait {
            sut.codeStorage.sourceBucket.selectedItem = null
            assertThat(sut.validatePanel()?.message).contains("Bucket must be specified")
        }
    }

    @Test
    fun `handler cannot be blank if Zip based`() {
        val sut = createZipBasedCodePanel()
        runInEdtAndWait {
            sut.handlerPanel.handler.text = ""
            assertThat(sut.validatePanel()?.message).contains("Handler must be specified")
        }
    }

    @Test
    fun `handler must be in project`() {
        val sut = createZipBasedCodePanel()
        runInEdtAndWait {
            sut.handlerPanel.handler.text = "Foo"
            assertThat(sut.validatePanel()?.message).contains("Must be able to locate the handler")
        }
    }

    @Test
    fun `valid panel returns null for Image`() {
        val sut = createImageBasedCodePanel()
        assertThat(sut.validatePanel()).isNull()
    }

    @Test
    fun `repo must be selected if Image based`() {
        val sut = createImageBasedCodePanel()
        runInEdtAndWait {
            sut.codeStorage.ecrRepo.selectedItem = null
            assertThat(sut.validatePanel()?.message).contains("Repository must be specified")
        }
    }

    @Test
    fun `dockerfile cannot be blank if Image based`() {
        val sut = createImageBasedCodePanel()
        runInEdtAndWait {
            sut.dockerFile.text = ""
            assertThat(sut.validatePanel()?.message).contains("Dockerfile not found")
        }
    }

    @Test
    fun `dockerfile must exist if Image based`() {
        val sut = createImageBasedCodePanel()
        runInEdtAndWait {
            sut.dockerFile.text = "iDontExist"
            assertThat(sut.validatePanel()?.message).contains("Dockerfile not found")
        }
    }

    @Test
    fun `dockerfile must be a file if Image based`() {
        val sut = createImageBasedCodePanel()
        runInEdtAndWait {
            sut.dockerFile.text = temporaryFolder.newFolder().absolutePath
            assertThat(sut.validatePanel()?.message).contains("Dockerfile not found")
        }
    }

    private fun createZipBasedCodePanel(): UpdateFunctionCodePanel {
        val panel = runInEdtAndGet {
            val sdk = IdeaTestUtil.getMockJdk18()
            runInEdtAndWait {
                runWriteAction {
                    ProjectJdkTable.getInstance().addJdk(sdk, projectRule.fixture.projectDisposable)
                    ProjectRootManager.getInstance(projectRule.project).projectSdk = sdk
                }
            }

            projectRule.fixture.addClass(
                """
                package com.example;

                public class LambdaHandler {
                    public static void handleRequest(InputStream input, OutputStream output) { }
                }
                """
            )

            UpdateFunctionCodePanel(projectRule.project, PackageType.ZIP).apply {
                handlerPanel.setRuntime(Runtime.JAVA8)
                handlerPanel.handler.text = "com.example.LambdaHandler::handleRequest"
                codeStorage.sourceBucket.selectedItem = bucketName
            }
        }

        panel.codeStorage.sourceBucket.waitToLoad()

        return panel
    }

    private fun createImageBasedCodePanel(): UpdateFunctionCodePanel {
        val panel = runInEdtAndGet {
            UpdateFunctionCodePanel(projectRule.project, PackageType.IMAGE).apply {
                dockerFile.text = temporaryFolder.newFile().absolutePath
                codeStorage.ecrRepo.selectedItem = repository
            }
        }

        panel.codeStorage.ecrRepo.waitToLoad()

        return panel
    }
}


// Copyright 2019 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.ProjectRule
import com.intellij.testFramework.runInEdtAndWait
import org.assertj.core.api.Assertions.assertThat
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import software.amazon.awssdk.services.iam.model.Role
import software.amazon.awssdk.services.lambda.model.Runtime
import software.aws.toolkits.core.utils.test.aString
import software.aws.toolkits.jetbrains.core.MockResourceCacheRule
import software.aws.toolkits.jetbrains.services.iam.IamResources
import software.aws.toolkits.jetbrains.services.iam.IamRole
import software.aws.toolkits.jetbrains.utils.waitToLoad

class UpdateFunctionConfigPanelTest {
    @Rule
    @JvmField
    val projectRule = ProjectRule()

    @Rule
    @JvmField
    val resourceCache = MockResourceCacheRule()

    private lateinit var sut: UpdateFunctionConfigPanel
    private val role = Role.builder()
        .arn(aString())
        .assumeRolePolicyDocument(LAMBDA_PRINCIPAL)
        .build()

    @Before
    fun wireMocksTogetherWithValidOptions() {
        val project = projectRule.project

        resourceCache.addEntry(
            project,
            IamResources.LIST_RAW_ROLES,
            listOf(role)
        )

        runInEdtAndWait {
            sut = UpdateFunctionConfigPanel(project)
            sut.configSettings.handlerPanel.handler.text = "com.example.LambdaHandler::handleRequest"
            sut.configSettings.runtime.selectedItem = Runtime.JAVA8
        }

        sut.configSettings.iamRole.waitToLoad()

        runInEdtAndWait {
            sut.configSettings.iamRole.selectedItem = IamRole(role.arn())
        }
    }

    @Test
    fun `valid function returns null`() {
        runInEdtAndWait {
            assertThat(sut.validatePanel()).isNull()
        }
    }

    @Test
    fun `invalid function returns an error`() {
        runInEdtAndWait {
            sut.configSettings.handlerPanel.handler.text = ""
            assertThat(sut.validatePanel()).isNotNull
        }
    }
}


// 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.ProjectRule
import org.assertj.core.api.Assertions.assertThat
import org.junit.Rule
import org.junit.Test
import org.mockito.kotlin.any
import org.mockito.kotlin.argumentCaptor
import org.mockito.kotlin.doReturn
import org.mockito.kotlin.stub
import org.mockito.kotlin.verify
import software.amazon.awssdk.services.lambda.LambdaClient
import software.amazon.awssdk.services.lambda.model.PackageType
import software.amazon.awssdk.services.lambda.model.Runtime
import software.amazon.awssdk.services.lambda.model.UpdateFunctionConfigurationRequest
import software.amazon.awssdk.services.lambda.model.UpdateFunctionConfigurationResponse
import software.aws.toolkits.core.utils.test.aString
import software.aws.toolkits.jetbrains.core.MockClientManagerRule
import software.aws.toolkits.jetbrains.services.iam.IamRole

class UpdateLambdaConfigurationTest {
    @Rule
    @JvmField
    val projectRule = ProjectRule()

    @Rule
    @JvmField
    val clientManagerRule = MockClientManagerRule()

    @Test
    fun `can update the configuration`() {
        validate(
            FunctionDetails(
                name = aString(),
                description = aString(),
                packageType = PackageType.ZIP,
                handler = aString(),
                iamRole = IamRole(aString()),
                runtime = Runtime.knownValues().random(),
                envVars = mapOf(aString() to aString()),
                timeout = 300,
                memorySize = 1024,
                xrayEnabled = true
            )
        )
    }

    private fun validate(functionDetails: FunctionDetails) {
        val configRequestCaptor = argumentCaptor<UpdateFunctionConfigurationRequest>()
        val lambdaClient = clientManagerRule.create<LambdaClient>().stub {
            on { updateFunctionConfiguration(configRequestCaptor.capture()) } doReturn UpdateFunctionConfigurationResponse.builder().build()
        }

        lambdaClient.updateFunctionConfiguration(functionDetails)

        verify(lambdaClient).updateFunctionConfiguration(any<UpdateFunctionConfigurationRequest>())
        with(configRequestCaptor) {
            assertThat(allValues).hasSize(1)

            assertThat(firstValue.functionName()).isEqualTo(functionDetails.name)
            assertThat(firstValue.description()).isEqualTo(functionDetails.description)
            assertThat(firstValue.runtime()).isEqualTo(functionDetails.runtime)
            assertThat(firstValue.handler()).isEqualTo(functionDetails.handler)
            assertThat(firstValue.memorySize()).isEqualTo(functionDetails.memorySize)
            assertThat(firstValue.timeout()).isEqualTo(functionDetails.timeout)
            assertThat(firstValue.environment().variables()).isEqualTo(functionDetails.envVars)
            assertThat(firstValue.role()).isEqualTo(functionDetails.iamRole.arn)
            assertThat(firstValue.tracingConfig().mode()).isEqualTo(functionDetails.tracingMode)
        }
    }
}


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

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

import org.assertj.core.api.Assertions.assertThat
import org.junit.Test

// TODO: This is fragile. Very fragle. But it is necessary to get Schemas service launched, and we've evaluated all other tradeoffs
// This will be done on the server-side as soon as we can, but for now the client needs to do this
class SchemaCodeGenUtilsTest {

    @Test
    public fun awsEventPackageName() {
        assertThat(SchemaCodeGenUtils.buildSchemaPackageName("aws.ec2.EC2InstanceStateChangeNotificationEvent"))
            .isEqualTo("schema.aws.ec2.ec2instancestatechangenotificationevent")
        assertThat(SchemaCodeGenUtils.buildSchemaPackageName("aws.ec2@EC2InstanceStateChangeNotificationEvent"))
            .isEqualTo("schema.aws.ec2.ec2instancestatechangenotificationevent")
    }

    @Test
    public fun partnerEventPackageName() {
        assertThat(SchemaCodeGenUtils.buildSchemaPackageName("aws.partner-mongodb.com/1234567-tickets@TicketCreated"))
            .isEqualTo("schema.aws.partner.mongodb_com_1234567_tickets.ticketcreated")
        assertThat(SchemaCodeGenUtils.buildSchemaPackageName("aws.partner-zendesk.com/some#other#special#chars@MyEvent"))
            .isEqualTo("schema.aws.partner.zendesk_com_some_other_special_chars.myevent")
        assertThat(SchemaCodeGenUtils.buildSchemaPackageName("aws.partner-pagerduty.com@YouGotPaged"))
            .isEqualTo("schema.aws.partner.pagerduty_com.yougotpaged")
    }

    @Test
    public fun customerUploadedEventPackageName() {
        assertThat(SchemaCodeGenUtils.buildSchemaPackageName("MyEvent"))
            .isEqualTo("schema.myevent")
        assertThat(SchemaCodeGenUtils.buildSchemaPackageName("MyEvent.Special#Characters${'$'}etc"))
            .isEqualTo("schema.myevent_special_characters_etc")
        assertThat(SchemaCodeGenUtils.buildSchemaPackageName("MyEvent@Discriminator"))
            .isEqualTo("schema.myevent.discriminator")
        assertThat(SchemaCodeGenUtils.buildSchemaPackageName("MyEvent@Discriminator@Another"))
            .isEqualTo("schema.myevent.discriminator.another")
    }

    @Test
    public fun formatIdentifier() {
        assertThat(SchemaCodeGenUtils.IdentifierFormatter.toValidIdentifier("Review.created"))
            .isEqualTo("Review_created")
    }
}


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

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

import com.intellij.testFramework.ProjectRule
import com.intellij.testFramework.runInEdtAndGet
import com.intellij.testFramework.runInEdtAndWait
import org.assertj.core.api.Assertions.assertThat
import org.junit.Rule
import org.junit.Test
import software.amazon.awssdk.services.schemas.model.DescribeSchemaResponse
import software.aws.toolkits.jetbrains.core.MockResourceCacheRule
import software.aws.toolkits.jetbrains.core.credentials.MockAwsConnectionManager.ProjectAccountSettingsManagerRule
import software.aws.toolkits.jetbrains.services.lambda.wizard.SchemaResourceSelector.Companion.DEFAULT_EVENT_DETAIL_TYPE
import software.aws.toolkits.jetbrains.services.lambda.wizard.SchemaResourceSelector.Companion.DEFAULT_EVENT_SOURCE
import software.aws.toolkits.jetbrains.services.schemas.SchemaTemplateParameters
import software.aws.toolkits.jetbrains.services.schemas.resources.SchemasResources
import software.aws.toolkits.jetbrains.services.schemas.resources.SchemasResources.LIST_REGISTRIES_AND_SCHEMAS
import software.aws.toolkits.jetbrains.utils.waitToLoad

class SchemaSelectionPanelTest {

    @Rule
    @JvmField
    val projectRule = ProjectRule()

    @JvmField
    @Rule
    val resourceCache = MockResourceCacheRule()

    @JvmField
    @Rule
    val connectionManager = ProjectAccountSettingsManagerRule(projectRule)

    private fun initMockResourceCache() {
        resourceCache.addEntry(
            projectRule.project,
            SchemasResources.getSchema(REGISTRY_NAME, AWS_SCHEMA_NAME),
            DescribeSchemaResponse.builder()
                .schemaName(AWS_SCHEMA_NAME)
                .content(AWS_SCHEMA)
                .schemaVersion(SCHEMA_VERSION)
                .build()
        )
        resourceCache.addEntry(
            projectRule.project,
            SchemasResources.getSchema(REGISTRY_NAME, PARTNER_SCHEMA_NAME),
            DescribeSchemaResponse.builder()
                .schemaName(PARTNER_SCHEMA_NAME)
                .content(PARTNER_SCHEMA)
                .schemaVersion(SCHEMA_VERSION)
                .build()
        )
        resourceCache.addEntry(
            projectRule.project,
            SchemasResources.getSchema(REGISTRY_NAME, CUSTOMER_UPLOADED_SCHEMA_NAME),
            DescribeSchemaResponse.builder()
                .schemaName(CUSTOMER_UPLOADED_SCHEMA_NAME)
                .content(CUSTOMER_UPLOADED_SCHEMA)
                .schemaVersion(SCHEMA_VERSION)
                .build()
        )
        resourceCache.addEntry(
            projectRule.project,
            SchemasResources.getSchema(REGISTRY_NAME, CUSTOMER_UPLOADED_SCHEMA_MULTIPLE_TYPES_NAME),
            DescribeSchemaResponse.builder()
                .schemaName(CUSTOMER_UPLOADED_SCHEMA_MULTIPLE_TYPES_NAME)
                .content(CUSTOMER_UPLOADED_SCHEMA_MULTIPLE_TYPES)
                .schemaVersion(SCHEMA_VERSION)
                .build()
        )
        resourceCache.addEntry(
            projectRule.project,
            LIST_REGISTRIES_AND_SCHEMAS,
            listOf(REGISTRY_ITEM, AWS_SCHEMA_ITEM, PARTNER_SCHEMA_ITEM, CUSTOMER_UPLOADED_SCHEMA_ITEM, CUSTOMER_UPLOADED_SCHEMA_MULTIPLE_TYPES_ITEM)
        )
    }

    @Test
    fun schemaTemplateParametersNullWithoutSelection() {
        val schemaTemplateParameters = SchemaResourceSelector().buildSchemaTemplateParameters()

        assertThat(schemaTemplateParameters).isNull()
    }

    @Test
    fun schemaTemplateParametersFirstIfRegistrySelected() {
        val schemaSelectionSelector = createSelector()
        schemaSelectionSelector.schemasSelector.selectedItem = REGISTRY_ITEM

        val schemaTemplateParameters = schemaSelectionSelector.buildSchemaTemplateParameters()

        assertThat(schemaTemplateParameters?.schema?.name).isEqualTo(AWS_SCHEMA_NAME)
    }

    @Test
    fun schemaTemplateParametersBuiltAfterSelectionAwsSchema() {
        val schemaSelectionSelector = createSelector()
        schemaSelectionSelector.schemasSelector.selectedItem = AWS_SCHEMA_ITEM

        val schemaTemplateParameters = schemaSelectionSelector.buildSchemaTemplateParameters()

        assertAwsSchemaParameters(schemaTemplateParameters)
    }

    @Test
    fun schemaTemplateParametersBuiltAfterSelectionPartnerSchema() {
        val schemaSelectionSelector = createSelector()
        schemaSelectionSelector.schemasSelector.selectedItem = PARTNER_SCHEMA_ITEM

        val schemaTemplateParameters = schemaSelectionSelector.buildSchemaTemplateParameters()

        assertThat(schemaTemplateParameters).isNotNull
        assertThat(schemaTemplateParameters?.schema?.registryName).isEqualTo(REGISTRY_NAME)
        assertThat(schemaTemplateParameters?.schemaVersion).isEqualTo(SCHEMA_VERSION)

        assertThat(schemaTemplateParameters?.schema?.name).isEqualTo(PARTNER_SCHEMA_NAME)

        assertThat(schemaTemplateParameters?.templateExtraContext).isNotNull
        assertThat(schemaTemplateParameters?.templateExtraContext?.schemaRegistry).isEqualTo(REGISTRY_NAME)
        assertThat(schemaTemplateParameters?.templateExtraContext?.schemaRootEventName).isEqualTo("aws_partner_mongodb_com_Ticket_Created")
        assertThat(schemaTemplateParameters?.templateExtraContext?.schemaPackageHierarchy).isEqualTo(PARTNER_SCHEMA_EXPECTED_PACKAGE_NAME)
        assertThat(schemaTemplateParameters?.templateExtraContext?.source).isEqualTo("aws.partner-mongodb.com")
        assertThat(schemaTemplateParameters?.templateExtraContext?.detailType).isEqualTo("MongoDB Trigger for my_store.reviews")
        assertThat(schemaTemplateParameters?.templateExtraContext?.userAgent).isEqualTo(AWS_TOOLKIT_USER_AGENT)
    }

    @Test
    fun schemaTemplateParametersBuiltAfterSelectionCustomerUploadedSchema() {
        val schemaSelectionSelector = createSelector()
        schemaSelectionSelector.schemasSelector.selectedItem = CUSTOMER_UPLOADED_SCHEMA_ITEM

        val schemaTemplateParameters = schemaSelectionSelector.buildSchemaTemplateParameters()
        assertCustomerUploadedSchemaParameters(
            CUSTOMER_UPLOADED_SCHEMA_NAME,
            "Some_Awesome_Schema",
            CUSTOMER_UPLOADED_SCHEMA_EXPECTED_PACKAGE_NAME,
            schemaTemplateParameters
        )
    }

    @Test
    fun schemaTemplateParametersBuiltAfterSelectionCustomerUploadedSchemaMultipleTypes() {
        val schemaSelectionSelector = createSelector()
        runInEdtAndWait {
            schemaSelectionSelector.schemasSelector.selectedItem = CUSTOMER_UPLOADED_SCHEMA_MULTIPLE_TYPES_ITEM

            val schemaTemplateParameters = schemaSelectionSelector.buildSchemaTemplateParameters()
            assertCustomerUploadedSchemaParameters(
                CUSTOMER_UPLOADED_SCHEMA_MULTIPLE_TYPES_NAME,
                "Some_Awesome_Schema_Object_1",
                CUSTOMER_UPLOADED_SCHEMA_MULTIPLE_TYPES_EXPECTED_PACKAGE_NAME,
                schemaTemplateParameters
            )
        }
    }

    private fun assertAwsSchemaParameters(schemaTemplateParameters: SchemaTemplateParameters?) {
        assertThat(schemaTemplateParameters).isNotNull
        assertThat(schemaTemplateParameters?.schema?.registryName).isEqualTo(REGISTRY_NAME)
        assertThat(schemaTemplateParameters?.schemaVersion).isEqualTo(SCHEMA_VERSION)

        assertThat(schemaTemplateParameters?.schema?.name).isEqualTo(AWS_SCHEMA_NAME)

        assertThat(schemaTemplateParameters?.templateExtraContext).isNotNull
        assertThat(schemaTemplateParameters?.templateExtraContext?.schemaRegistry).isEqualTo(REGISTRY_NAME)
        assertThat(schemaTemplateParameters?.templateExtraContext?.schemaRootEventName).isEqualTo("EC2InstanceStateChangeNotification")
        assertThat(schemaTemplateParameters?.templateExtraContext?.schemaPackageHierarchy).isEqualTo(AWS_SCHEMA_EXPECTED_PACKAGE_NAME)
        assertThat(schemaTemplateParameters?.templateExtraContext?.source).isEqualTo("aws.ec2")
        assertThat(schemaTemplateParameters?.templateExtraContext?.detailType).isEqualTo("EC2 Instance State-change Notification")
        assertThat(schemaTemplateParameters?.templateExtraContext?.userAgent).isEqualTo(AWS_TOOLKIT_USER_AGENT)
    }

    private fun assertCustomerUploadedSchemaParameters(
        schemaName: String,
        schemaRootEventName: String,
        schemaPackageHierarchy: String,
        schemaTemplateParameters: SchemaTemplateParameters?
    ) {
        assertThat(schemaTemplateParameters).isNotNull
        assertThat(schemaTemplateParameters?.schema?.registryName).isEqualTo(REGISTRY_NAME)
        assertThat(schemaTemplateParameters?.schemaVersion).isEqualTo(SCHEMA_VERSION)

        assertThat(schemaTemplateParameters?.schema?.name).isEqualTo(schemaName)

        assertThat(schemaTemplateParameters?.templateExtraContext).isNotNull
        assertThat(schemaTemplateParameters?.templateExtraContext?.schemaRegistry).isEqualTo(REGISTRY_NAME)
        assertThat(schemaTemplateParameters?.templateExtraContext?.schemaRootEventName).isEqualTo(schemaRootEventName)
        assertThat(schemaTemplateParameters?.templateExtraContext?.schemaPackageHierarchy).isEqualTo(schemaPackageHierarchy)
        assertThat(schemaTemplateParameters?.templateExtraContext?.source).isEqualTo(DEFAULT_EVENT_SOURCE)
        assertThat(schemaTemplateParameters?.templateExtraContext?.detailType).isEqualTo(DEFAULT_EVENT_DETAIL_TYPE)
        assertThat(schemaTemplateParameters?.templateExtraContext?.userAgent).isEqualTo(AWS_TOOLKIT_USER_AGENT)
    }

    private fun createSelector(): SchemaResourceSelector {
        val selector = runInEdtAndGet {
            initMockResourceCache()

            val schemaSelectionSelector = SchemaResourceSelector()
            schemaSelectionSelector.awsConnection = connectionManager.settingsManager.connectionSettings()
            schemaSelectionSelector.reload()

            schemaSelectionSelector
        }

        selector.schemasSelector.waitToLoad()

        return selector
    }

    private companion object {
        private const val AWS_TOOLKIT_USER_AGENT = "AWSToolkit"

        private const val REGISTRY_NAME = "Registry"
        private val REGISTRY_ITEM = SchemaSelectionItem.RegistryItem(REGISTRY_NAME)

        private const val SCHEMA_VERSION = "1"

        private const val AWS_SCHEMA_NAME = "aws.ec2@EC2InstanceStateChangeNotification"
        private const val AWS_SCHEMA_EXPECTED_PACKAGE_NAME = "schema.aws.ec2.ec2instancestatechangenotification"
        private val AWS_SCHEMA_ITEM = SchemaSelectionItem.SchemaItem(AWS_SCHEMA_NAME, REGISTRY_NAME)
        private val AWS_SCHEMA = SchemaSelectionPanelTest::class.java.getResourceAsStream("/awsEventSchema.json.txt")!!.bufferedReader().readText()

        private const val PARTNER_SCHEMA_NAME = "aws.partner-mongodb.com/1234567-tickets@Ticket.Created"
        private const val PARTNER_SCHEMA_EXPECTED_PACKAGE_NAME = "schema.aws.partner.mongodb_com_1234567_tickets.ticket_created"
        private val PARTNER_SCHEMA_ITEM = SchemaSelectionItem.SchemaItem(PARTNER_SCHEMA_NAME, REGISTRY_NAME)
        private val PARTNER_SCHEMA = SchemaSelectionPanelTest::class.java.getResourceAsStream("/partnerEventSchema.json.txt")!!.bufferedReader().readText()

        private const val CUSTOMER_UPLOADED_SCHEMA_NAME = "someCustomer.SomeAwesomeSchema"
        private const val CUSTOMER_UPLOADED_SCHEMA_EXPECTED_PACKAGE_NAME = "schema.somecustomer_someawesomeschema"
        private val CUSTOMER_UPLOADED_SCHEMA_ITEM = SchemaSelectionItem.SchemaItem(CUSTOMER_UPLOADED_SCHEMA_NAME, REGISTRY_NAME)
        private val CUSTOMER_UPLOADED_SCHEMA =
            SchemaSelectionPanelTest::class.java.getResourceAsStream("/customerUploadedEventSchema.json.txt")!!.bufferedReader().readText()

        private const val CUSTOMER_UPLOADED_SCHEMA_MULTIPLE_TYPES_NAME = "someCustomer.multipleTypes@SomeOtherAwesomeSchema"
        private const val CUSTOMER_UPLOADED_SCHEMA_MULTIPLE_TYPES_EXPECTED_PACKAGE_NAME = "schema.somecustomer_multipletypes.someotherawesomeschema"
        private val CUSTOMER_UPLOADED_SCHEMA_MULTIPLE_TYPES_ITEM = SchemaSelectionItem.SchemaItem(CUSTOMER_UPLOADED_SCHEMA_MULTIPLE_TYPES_NAME, REGISTRY_NAME)
        private val CUSTOMER_UPLOADED_SCHEMA_MULTIPLE_TYPES =
            SchemaSelectionPanelTest::class.java.getResourceAsStream("/customerUploadedEventSchemaMultipleTypes.json.txt")!!.bufferedReader().readText()
    }
}


// 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.openapi.actionSystem.DataContext
import com.intellij.openapi.ide.CopyPasteManager
import com.intellij.testFramework.ProjectRule
import com.intellij.testFramework.TestActionEvent
import org.assertj.core.api.Assertions.assertThat
import org.junit.Rule
import org.junit.Test
import software.amazon.awssdk.services.s3.model.Bucket
import software.aws.toolkits.jetbrains.services.s3.bucketActions.CopyBucketNameAction
import java.awt.datatransfer.DataFlavor

class CopyBucketTest {

    @Rule
    @JvmField
    val projectRule = ProjectRule()

    @Test
    fun copyBucketName() {
        val bucket = S3BucketNode(projectRule.project, Bucket.builder().name("foo").build())
        val copyAction = CopyBucketNameAction()
        copyAction.actionPerformed(bucket, TestActionEvent(DataContext { projectRule.project }))
        val content = CopyPasteManager.getInstance().contents
        assertThat(content?.getTransferData(DataFlavor.stringFlavor)).isEqualTo("foo")
    }
}


// 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 com.intellij.testFramework.runInEdtAndWait
import org.assertj.core.api.Assertions.assertThat
import org.assertj.core.api.Assertions.assertThatThrownBy
import org.junit.Rule
import org.junit.Test
import org.mockito.kotlin.argumentCaptor
import org.mockito.kotlin.doReturn
import org.mockito.kotlin.doThrow
import org.mockito.kotlin.stub
import software.amazon.awssdk.services.s3.S3Client
import software.amazon.awssdk.services.s3.model.BucketAlreadyExistsException
import software.amazon.awssdk.services.s3.model.CreateBucketRequest
import software.amazon.awssdk.services.s3.model.CreateBucketResponse
import software.aws.toolkits.core.utils.delegateMock

class CreateBucketActionDialogTest {
    @Rule
    @JvmField
    val projectRule = ProjectRule()

    private val s3Mock = delegateMock<S3Client>()

    @Test
    fun validateBucketName_emptyBucketName() {
        runInEdtAndWait {
            val dialog = CreateS3BucketDialog(project = projectRule.project, s3Client = s3Mock)
            dialog.view.bucketName.text = "  "

            val validationInfo = dialog.validateBucketName()
            assertThat(validationInfo).isNotNull()
        }
    }

    @Test
    fun createBucketSuccessful() {
        val createBucketCaptor = argumentCaptor<CreateBucketRequest>()

        s3Mock.stub {
            on { createBucket(createBucketCaptor.capture()) } doReturn CreateBucketResponse.builder().build()
        }

        runInEdtAndWait {
            val dialog = CreateS3BucketDialog(
                project = projectRule.project,
                s3Client = s3Mock
            )
            dialog.view.bucketName.text = TEST_BUCKET_NAME

            dialog.createBucket()

            assertThat(dialog.bucketName()).isEqualTo(TEST_BUCKET_NAME)
        }

        assertThat(createBucketCaptor.firstValue.bucket()).isEqualTo(TEST_BUCKET_NAME)
    }

    @Test
    fun createBucketFailed() {
        val createBucketCaptor = argumentCaptor<CreateBucketRequest>()

        s3Mock.stub {
            on { createBucket(createBucketCaptor.capture()) } doThrow BucketAlreadyExistsException.builder().message(
                TEST_ERROR_MESSAGE
            ).build()
        }

        runInEdtAndWait {
            val dialog = CreateS3BucketDialog(project = projectRule.project, s3Client = s3Mock)
            dialog.view.bucketName.text = TEST_BUCKET_NAME

            assertThatThrownBy { dialog.createBucket() }.hasMessage(TEST_ERROR_MESSAGE)
        }

        assertThat(createBucketCaptor.firstValue.bucket()).isEqualTo(TEST_BUCKET_NAME)
    }

    companion object {
        const val TEST_BUCKET_NAME = "foo"
        const val TEST_ERROR_MESSAGE = "Bucket already exists!"
    }
}