// Copyright 2016-2018, Pulumi Corporation.  All rights reserved.

package ints

import (
	"testing"

	"github.com/pulumi/pulumi/pkg/resource"
	"github.com/pulumi/pulumi/pkg/resource/deploy/providers"
	"github.com/pulumi/pulumi/pkg/testing/integration"
	"github.com/stretchr/testify/assert"
)

// Test that the engine tolerates two deletions of the same URN in the same plan.
func TestDoublePendingDelete(t *testing.T) {
	integration.ProgramTest(t, &integration.ProgramTestOptions{
		Dir:          "step1",
		Dependencies: []string{"@pulumi/pulumi"},
		Quick:        true,
		EditDirs: []integration.EditDir{
			{
				Dir:           "step2",
				Additive:      true,
				ExpectFailure: true,
				ExtraRuntimeValidation: func(t *testing.T, stackInfo integration.RuntimeValidationStackInfo) {
					assert.NotNil(t, stackInfo.Deployment)

					// Four resources in this deployment: the root resource, A, B, and A (pending delete)
					assert.Equal(t, 5, len(stackInfo.Deployment.Resources))
					stackRes := stackInfo.Deployment.Resources[0]
					assert.Equal(t, resource.RootStackType, stackRes.URN.Type())
					providerRes := stackInfo.Deployment.Resources[1]
					assert.True(t, providers.IsProviderType(providerRes.URN.Type()))

					a := stackInfo.Deployment.Resources[2]
					assert.Equal(t, "a", string(a.URN.Name()))
					assert.False(t, a.Delete)

					aCondemned := stackInfo.Deployment.Resources[3]
					assert.Equal(t, "a", string(aCondemned.URN.Name()))
					assert.True(t, aCondemned.Delete)

					b := stackInfo.Deployment.Resources[4]
					assert.Equal(t, "b", string(b.URN.Name()))
					assert.False(t, b.Delete)

				},
			},
			{
				Dir:           "step3",
				Additive:      true,
				ExpectFailure: true,
				ExtraRuntimeValidation: func(t *testing.T, stackInfo integration.RuntimeValidationStackInfo) {
					// There is still only one pending delete resource in this snapshot.
					assert.NotNil(t, stackInfo.Deployment)

					assert.Equal(t, 5, len(stackInfo.Deployment.Resources))
					stackRes := stackInfo.Deployment.Resources[0]
					assert.Equal(t, resource.RootStackType, stackRes.URN.Type())
					providerRes := stackInfo.Deployment.Resources[1]
					assert.True(t, providers.IsProviderType(providerRes.URN.Type()))

					a := stackInfo.Deployment.Resources[2]
					assert.Equal(t, "a", string(a.URN.Name()))
					assert.False(t, a.Delete)

					aCondemned := stackInfo.Deployment.Resources[3]
					assert.Equal(t, "a", string(aCondemned.URN.Name()))
					assert.True(t, aCondemned.Delete)

					b := stackInfo.Deployment.Resources[4]
					assert.Equal(t, "b", string(b.URN.Name()))
					assert.False(t, b.Delete)
				},
			},
			{
				Dir:      "step4",
				Additive: true,
				ExtraRuntimeValidation: func(t *testing.T, stackInfo integration.RuntimeValidationStackInfo) {
					// We should have cleared out all of the pending deletes now.
					assert.NotNil(t, stackInfo.Deployment)

					assert.Equal(t, 4, len(stackInfo.Deployment.Resources))
					stackRes := stackInfo.Deployment.Resources[0]
					assert.Equal(t, resource.RootStackType, stackRes.URN.Type())
					providerRes := stackInfo.Deployment.Resources[1]
					assert.True(t, providers.IsProviderType(providerRes.URN.Type()))

					a := stackInfo.Deployment.Resources[2]
					assert.Equal(t, "a", string(a.URN.Name()))
					assert.False(t, a.Delete)

					b := stackInfo.Deployment.Resources[3]
					assert.Equal(t, "b", string(b.URN.Name()))
					assert.False(t, b.Delete)
				},
			},
		},
	})
}
