// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package command

import (
	"encoding/json"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
	"testing"

	"github.com/google/go-cmp/cmp"
	"github.com/hashicorp/terraform/internal/addrs"
	"github.com/hashicorp/terraform/internal/configs/configschema"
	"github.com/hashicorp/terraform/internal/plans"
	"github.com/hashicorp/terraform/internal/providers"
	"github.com/hashicorp/terraform/internal/states"
	"github.com/hashicorp/terraform/internal/states/statemgr"
	"github.com/hashicorp/terraform/internal/terraform"
	"github.com/hashicorp/terraform/version"
	"github.com/mitchellh/cli"
	"github.com/zclconf/go-cty/cty"
)

func TestShow_badArgs(t *testing.T) {
	view, done := testView(t)
	c := &ShowCommand{
		Meta: Meta{
			testingOverrides: metaOverridesForProvider(testProvider()),
			View:             view,
		},
	}

	args := []string{
		"bad",
		"bad",
		"-no-color",
	}

	code := c.Run(args)
	output := done(t)

	if code != 1 {
		t.Fatalf("unexpected exit status %d; want 1\ngot: %s", code, output.Stdout())
	}
}

func TestShow_noArgsNoState(t *testing.T) {
	view, done := testView(t)
	c := &ShowCommand{
		Meta: Meta{
			testingOverrides: metaOverridesForProvider(testProvider()),
			View:             view,
		},
	}

	code := c.Run([]string{})
	output := done(t)

	if code != 0 {
		t.Fatalf("unexpected exit status %d; want 0\ngot: %s", code, output.Stderr())
	}

	got := output.Stdout()
	want := `No state.`
	if !strings.Contains(got, want) {
		t.Fatalf("unexpected output\ngot: %s\nwant: %s", got, want)
	}
}

func TestShow_noArgsWithState(t *testing.T) {
	// Get a temp cwd
	testCwd(t)
	// Create the default state
	testStateFileDefault(t, testState())

	view, done := testView(t)
	c := &ShowCommand{
		Meta: Meta{
			testingOverrides: metaOverridesForProvider(showFixtureProvider()),
			View:             view,
		},
	}

	code := c.Run([]string{})
	output := done(t)

	if code != 0 {
		t.Fatalf("unexpected exit status %d; want 0\ngot: %s", code, output.Stderr())
	}

	got := output.Stdout()
	want := `# test_instance.foo:`
	if !strings.Contains(got, want) {
		t.Fatalf("unexpected output\ngot: %s\nwant: %s", got, want)
	}
}

func TestShow_argsWithState(t *testing.T) {
	// Create the default state
	statePath := testStateFile(t, testState())
	stateDir := filepath.Dir(statePath)
	defer os.RemoveAll(stateDir)
	defer testChdir(t, stateDir)()

	view, done := testView(t)
	c := &ShowCommand{
		Meta: Meta{
			testingOverrides: metaOverridesForProvider(showFixtureProvider()),
			View:             view,
		},
	}

	path := filepath.Base(statePath)
	args := []string{
		path,
		"-no-color",
	}
	code := c.Run(args)
	output := done(t)

	if code != 0 {
		t.Fatalf("unexpected exit status %d; want 0\ngot: %s", code, output.Stderr())
	}
}

// https://github.com/hashicorp/terraform/issues/21462
func TestShow_argsWithStateAliasedProvider(t *testing.T) {
	// Create the default state with aliased resource
	testState := states.BuildState(func(s *states.SyncState) {
		s.SetResourceInstanceCurrent(
			addrs.Resource{
				Mode: addrs.ManagedResourceMode,
				Type: "test_instance",
				Name: "foo",
			}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance),
			&states.ResourceInstanceObjectSrc{
				// The weird whitespace here is reflective of how this would
				// get written out in a real state file, due to the indentation
				// of all of the containing wrapping objects and arrays.
				AttrsJSON:    []byte("{\n            \"id\": \"bar\"\n          }"),
				Status:       states.ObjectReady,
				Dependencies: []addrs.ConfigResource{},
			},
			addrs.RootModuleInstance.ProviderConfigAliased(addrs.NewDefaultProvider("test"), "alias"),
		)
	})

	statePath := testStateFile(t, testState)
	stateDir := filepath.Dir(statePath)
	defer os.RemoveAll(stateDir)
	defer testChdir(t, stateDir)()

	view, done := testView(t)
	c := &ShowCommand{
		Meta: Meta{
			testingOverrides: metaOverridesForProvider(showFixtureProvider()),
			View:             view,
		},
	}

	path := filepath.Base(statePath)
	args := []string{
		path,
		"-no-color",
	}
	code := c.Run(args)
	output := done(t)

	if code != 0 {
		t.Fatalf("unexpected exit status %d; want 0\ngot: %s", code, output.Stderr())
	}

	got := output.Stdout()
	want := `# missing schema for provider \"test.alias\"`
	if strings.Contains(got, want) {
		t.Fatalf("unexpected output\ngot: %s", got)
	}
}

func TestShow_argsPlanFileDoesNotExist(t *testing.T) {
	view, done := testView(t)
	c := &ShowCommand{
		Meta: Meta{
			testingOverrides: metaOverridesForProvider(testProvider()),
			View:             view,
		},
	}

	args := []string{
		"doesNotExist.tfplan",
		"-no-color",
	}
	code := c.Run(args)
	output := done(t)

	if code != 1 {
		t.Fatalf("unexpected exit status %d; want 1\ngot: %s", code, output.Stdout())
	}

	got := output.Stderr()
	want := `Plan read error: open doesNotExist.tfplan:`
	if !strings.Contains(got, want) {
		t.Errorf("unexpected output\ngot: %s\nwant:\n%s", got, want)
	}
}

func TestShow_argsStatefileDoesNotExist(t *testing.T) {
	view, done := testView(t)
	c := &ShowCommand{
		Meta: Meta{
			testingOverrides: metaOverridesForProvider(testProvider()),
			View:             view,
		},
	}

	args := []string{
		"doesNotExist.tfstate",
		"-no-color",
	}
	code := c.Run(args)
	output := done(t)

	if code != 1 {
		t.Fatalf("unexpected exit status %d; want 1\ngot: %s", code, output.Stdout())
	}

	got := output.Stderr()
	want := `State read error: Error loading statefile:`
	if !strings.Contains(got, want) {
		t.Errorf("unexpected output\ngot: %s\nwant:\n%s", got, want)
	}
}

func TestShow_json_argsPlanFileDoesNotExist(t *testing.T) {
	view, done := testView(t)
	c := &ShowCommand{
		Meta: Meta{
			testingOverrides: metaOverridesForProvider(testProvider()),
			View:             view,
		},
	}

	args := []string{
		"-json",
		"doesNotExist.tfplan",
		"-no-color",
	}
	code := c.Run(args)
	output := done(t)

	if code != 1 {
		t.Fatalf("unexpected exit status %d; want 1\ngot: %s", code, output.Stdout())
	}

	got := output.Stderr()
	want := `Plan read error: open doesNotExist.tfplan:`
	if !strings.Contains(got, want) {
		t.Errorf("unexpected output\ngot: %s\nwant:\n%s", got, want)
	}
}

func TestShow_json_argsStatefileDoesNotExist(t *testing.T) {
	view, done := testView(t)
	c := &ShowCommand{
		Meta: Meta{
			testingOverrides: metaOverridesForProvider(testProvider()),
			View:             view,
		},
	}

	args := []string{
		"-json",
		"doesNotExist.tfstate",
		"-no-color",
	}
	code := c.Run(args)
	output := done(t)

	if code != 1 {
		t.Fatalf("unexpected exit status %d; want 1\ngot: %s", code, output.Stdout())
	}

	got := output.Stderr()
	want := `State read error: Error loading statefile:`
	if !strings.Contains(got, want) {
		t.Errorf("unexpected output\ngot: %s\nwant:\n%s", got, want)
	}
}

func TestShow_planNoop(t *testing.T) {
	planPath := testPlanFileNoop(t)

	view, done := testView(t)
	c := &ShowCommand{
		Meta: Meta{
			testingOverrides: metaOverridesForProvider(testProvider()),
			View:             view,
		},
	}

	args := []string{
		planPath,
		"-no-color",
	}
	code := c.Run(args)
	output := done(t)

	if code != 0 {
		t.Fatalf("unexpected exit status %d; want 0\ngot: %s", code, output.Stderr())
	}

	got := output.Stdout()
	want := `No changes. Your infrastructure matches the configuration.`
	if !strings.Contains(got, want) {
		t.Errorf("unexpected output\ngot: %s\nwant:\n%s", got, want)
	}
}

func TestShow_planWithChanges(t *testing.T) {
	planPathWithChanges := showFixturePlanFile(t, plans.DeleteThenCreate)

	view, done := testView(t)
	c := &ShowCommand{
		Meta: Meta{
			testingOverrides: metaOverridesForProvider(showFixtureProvider()),
			View:             view,
		},
	}

	args := []string{
		planPathWithChanges,
		"-no-color",
	}
	code := c.Run(args)
	output := done(t)

	if code != 0 {
		t.Fatalf("unexpected exit status %d; want 0\ngot: %s", code, output.Stderr())
	}

	got := output.Stdout()
	want := `test_instance.foo must be replaced`
	if !strings.Contains(got, want) {
		t.Fatalf("unexpected output\ngot: %s\nwant: %s", got, want)
	}
}

func TestShow_planWithForceReplaceChange(t *testing.T) {
	// The main goal of this test is to see that the "replace by request"
	// resource instance action reason can round-trip through a plan file and
	// be reflected correctly in the "terraform show" output, the same way
	// as it would appear in "terraform plan" output.

	_, snap := testModuleWithSnapshot(t, "show")
	plannedVal := cty.ObjectVal(map[string]cty.Value{
		"id":  cty.UnknownVal(cty.String),
		"ami": cty.StringVal("bar"),
	})
	priorValRaw, err := plans.NewDynamicValue(cty.NullVal(plannedVal.Type()), plannedVal.Type())
	if err != nil {
		t.Fatal(err)
	}
	plannedValRaw, err := plans.NewDynamicValue(plannedVal, plannedVal.Type())
	if err != nil {
		t.Fatal(err)
	}
	plan := testPlan(t)
	plan.Changes.SyncWrapper().AppendResourceInstanceChange(&plans.ResourceInstanceChangeSrc{
		Addr: addrs.Resource{
			Mode: addrs.ManagedResourceMode,
			Type: "test_instance",
			Name: "foo",
		}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance),
		ProviderAddr: addrs.AbsProviderConfig{
			Provider: addrs.NewDefaultProvider("test"),
			Module:   addrs.RootModule,
		},
		ChangeSrc: plans.ChangeSrc{
			Action: plans.CreateThenDelete,
			Before: priorValRaw,
			After:  plannedValRaw,
		},
		ActionReason: plans.ResourceInstanceReplaceByRequest,
	})
	planFilePath := testPlanFile(
		t,
		snap,
		states.NewState(),
		plan,
	)

	view, done := testView(t)
	c := &ShowCommand{
		Meta: Meta{
			testingOverrides: metaOverridesForProvider(showFixtureProvider()),
			View:             view,
		},
	}

	args := []string{
		planFilePath,
		"-no-color",
	}
	code := c.Run(args)
	output := done(t)

	if code != 0 {
		t.Fatalf("unexpected exit status %d; want 0\ngot: %s", code, output.Stderr())
	}

	got := output.Stdout()
	want := `test_instance.foo will be replaced, as requested`
	if !strings.Contains(got, want) {
		t.Fatalf("unexpected output\ngot: %s\nwant: %s", got, want)
	}

	want = `Plan: 1 to add, 0 to change, 1 to destroy.`
	if !strings.Contains(got, want) {
		t.Fatalf("unexpected output\ngot: %s\nwant: %s", got, want)
	}

}

func TestShow_plan_json(t *testing.T) {
	planPath := showFixturePlanFile(t, plans.Create)

	view, done := testView(t)
	c := &ShowCommand{
		Meta: Meta{
			testingOverrides: metaOverridesForProvider(showFixtureProvider()),
			View:             view,
		},
	}

	args := []string{
		"-json",
		planPath,
		"-no-color",
	}
	code := c.Run(args)
	output := done(t)

	if code != 0 {
		t.Fatalf("unexpected exit status %d; want 0\ngot: %s", code, output.Stderr())
	}
}

func TestShow_state(t *testing.T) {
	originalState := testState()
	root := originalState.RootModule()
	root.SetOutputValue("test", cty.ObjectVal(map[string]cty.Value{
		"attr": cty.NullVal(cty.DynamicPseudoType),
		"null": cty.NullVal(cty.String),
		"list": cty.ListVal([]cty.Value{cty.NullVal(cty.Number)}),
	}), false)

	statePath := testStateFile(t, originalState)
	defer os.RemoveAll(filepath.Dir(statePath))

	view, done := testView(t)
	c := &ShowCommand{
		Meta: Meta{
			testingOverrides: metaOverridesForProvider(showFixtureProvider()),
			View:             view,
		},
	}

	args := []string{
		statePath,
		"-no-color",
	}
	code := c.Run(args)
	output := done(t)

	if code != 0 {
		t.Fatalf("unexpected exit status %d; want 0\ngot: %s", code, output.Stderr())
	}
}

func TestShow_json_output(t *testing.T) {
	fixtureDir := "testdata/show-json"
	testDirs, err := ioutil.ReadDir(fixtureDir)
	if err != nil {
		t.Fatal(err)
	}

	for _, entry := range testDirs {
		if !entry.IsDir() {
			continue
		}

		t.Run(entry.Name(), func(t *testing.T) {
			td := t.TempDir()
			inputDir := filepath.Join(fixtureDir, entry.Name())
			testCopyDir(t, inputDir, td)
			defer testChdir(t, td)()

			expectError := strings.Contains(entry.Name(), "error")

			providerSource, close := newMockProviderSource(t, map[string][]string{
				"test":            {"1.2.3"},
				"hashicorp2/test": {"1.2.3"},
			})
			defer close()

			p := showFixtureProvider()

			// init
			ui := new(cli.MockUi)
			ic := &InitCommand{
				Meta: Meta{
					testingOverrides: metaOverridesForProvider(p),
					Ui:               ui,
					ProviderSource:   providerSource,
				},
			}
			if code := ic.Run([]string{}); code != 0 {
				if expectError {
					// this should error, but not panic.
					return
				}
				t.Fatalf("init failed\n%s", ui.ErrorWriter)
			}

			// plan
			planView, planDone := testView(t)
			pc := &PlanCommand{
				Meta: Meta{
					testingOverrides: metaOverridesForProvider(p),
					View:             planView,
					ProviderSource:   providerSource,
				},
			}

			args := []string{
				"-out=terraform.plan",
			}

			code := pc.Run(args)
			planOutput := planDone(t)

			if code != 0 {
				t.Fatalf("unexpected exit status %d; want 0\ngot: %s", code, planOutput.Stderr())
			}

			// show
			showView, showDone := testView(t)
			sc := &ShowCommand{
				Meta: Meta{
					testingOverrides: metaOverridesForProvider(p),
					View:             showView,
					ProviderSource:   providerSource,
				},
			}

			args = []string{
				"-json",
				"terraform.plan",
			}
			defer os.Remove("terraform.plan")
			code = sc.Run(args)
			showOutput := showDone(t)

			if code != 0 {
				t.Fatalf("unexpected exit status %d; want 0\ngot: %s", code, showOutput.Stderr())
			}

			// compare view output to wanted output
			var got, want plan

			gotString := showOutput.Stdout()
			json.Unmarshal([]byte(gotString), &got)

			wantFile, err := os.Open("output.json")
			if err != nil {
				t.Fatalf("unexpected err: %s", err)
			}
			defer wantFile.Close()
			byteValue, err := ioutil.ReadAll(wantFile)
			if err != nil {
				t.Fatalf("unexpected err: %s", err)
			}
			json.Unmarshal([]byte(byteValue), &want)

			// Disregard format version to reduce needless test fixture churn
			want.FormatVersion = got.FormatVersion

			if !cmp.Equal(got, want) {
				t.Fatalf("wrong result:\n %v\n", cmp.Diff(got, want))
			}
		})
	}
}

func TestShow_json_output_sensitive(t *testing.T) {
	td := t.TempDir()
	inputDir := "testdata/show-json-sensitive"
	testCopyDir(t, inputDir, td)
	defer testChdir(t, td)()

	providerSource, close := newMockProviderSource(t, map[string][]string{"test": {"1.2.3"}})
	defer close()

	p := showFixtureSensitiveProvider()

	// init
	ui := new(cli.MockUi)
	ic := &InitCommand{
		Meta: Meta{
			testingOverrides: metaOverridesForProvider(p),
			Ui:               ui,
			ProviderSource:   providerSource,
		},
	}
	if code := ic.Run([]string{}); code != 0 {
		t.Fatalf("init failed\n%s", ui.ErrorWriter)
	}

	// plan
	planView, planDone := testView(t)
	pc := &PlanCommand{
		Meta: Meta{
			testingOverrides: metaOverridesForProvider(p),
			View:             planView,
			ProviderSource:   providerSource,
		},
	}

	args := []string{
		"-out=terraform.plan",
	}
	code := pc.Run(args)
	planOutput := planDone(t)

	if code != 0 {
		t.Fatalf("unexpected exit status %d; want 0\ngot: %s", code, planOutput.Stderr())
	}

	// show
	showView, showDone := testView(t)
	sc := &ShowCommand{
		Meta: Meta{
			testingOverrides: metaOverridesForProvider(p),
			View:             showView,
			ProviderSource:   providerSource,
		},
	}

	args = []string{
		"-json",
		"terraform.plan",
	}
	defer os.Remove("terraform.plan")
	code = sc.Run(args)
	showOutput := showDone(t)

	if code != 0 {
		t.Fatalf("unexpected exit status %d; want 0\ngot: %s", code, showOutput.Stderr())
	}

	// compare ui output to wanted output
	var got, want plan

	gotString := showOutput.Stdout()
	json.Unmarshal([]byte(gotString), &got)

	wantFile, err := os.Open("output.json")
	if err != nil {
		t.Fatalf("unexpected err: %s", err)
	}
	defer wantFile.Close()
	byteValue, err := ioutil.ReadAll(wantFile)
	if err != nil {
		t.Fatalf("unexpected err: %s", err)
	}
	json.Unmarshal([]byte(byteValue), &want)

	// Disregard format version to reduce needless test fixture churn
	want.FormatVersion = got.FormatVersion

	if !cmp.Equal(got, want) {
		t.Fatalf("wrong result:\n %v\n", cmp.Diff(got, want))
	}
}

// Failing conditions are only present in JSON output for refresh-only plans,
// so we test that separately here.
func TestShow_json_output_conditions_refresh_only(t *testing.T) {
	td := t.TempDir()
	inputDir := "testdata/show-json/conditions"
	testCopyDir(t, inputDir, td)
	defer testChdir(t, td)()

	providerSource, close := newMockProviderSource(t, map[string][]string{"test": {"1.2.3"}})
	defer close()

	p := showFixtureSensitiveProvider()

	// init
	ui := new(cli.MockUi)
	ic := &InitCommand{
		Meta: Meta{
			testingOverrides: metaOverridesForProvider(p),
			Ui:               ui,
			ProviderSource:   providerSource,
		},
	}
	if code := ic.Run([]string{}); code != 0 {
		t.Fatalf("init failed\n%s", ui.ErrorWriter)
	}

	// plan
	planView, planDone := testView(t)
	pc := &PlanCommand{
		Meta: Meta{
			testingOverrides: metaOverridesForProvider(p),
			View:             planView,
			ProviderSource:   providerSource,
		},
	}

	args := []string{
		"-refresh-only",
		"-out=terraform.plan",
		"-var=ami=bad-ami",
		"-state=for-refresh.tfstate",
	}
	code := pc.Run(args)
	planOutput := planDone(t)

	if code != 0 {
		t.Fatalf("unexpected exit status %d; want 0\ngot: %s", code, planOutput.Stderr())
	}

	// show
	showView, showDone := testView(t)
	sc := &ShowCommand{
		Meta: Meta{
			testingOverrides: metaOverridesForProvider(p),
			View:             showView,
			ProviderSource:   providerSource,
		},
	}

	args = []string{
		"-json",
		"terraform.plan",
	}
	defer os.Remove("terraform.plan")
	code = sc.Run(args)
	showOutput := showDone(t)

	if code != 0 {
		t.Fatalf("unexpected exit status %d; want 0\ngot: %s", code, showOutput.Stderr())
	}

	// compare JSON output to wanted output
	var got, want plan

	gotString := showOutput.Stdout()
	json.Unmarshal([]byte(gotString), &got)

	wantFile, err := os.Open("output-refresh-only.json")
	if err != nil {
		t.Fatalf("unexpected err: %s", err)
	}
	defer wantFile.Close()
	byteValue, err := ioutil.ReadAll(wantFile)
	if err != nil {
		t.Fatalf("unexpected err: %s", err)
	}
	json.Unmarshal([]byte(byteValue), &want)

	// Disregard format version to reduce needless test fixture churn
	want.FormatVersion = got.FormatVersion

	if !cmp.Equal(got, want) {
		t.Fatalf("wrong result:\n %v\n", cmp.Diff(got, want))
	}
}

// similar test as above, without the plan
func TestShow_json_output_state(t *testing.T) {
	fixtureDir := "testdata/show-json-state"
	testDirs, err := ioutil.ReadDir(fixtureDir)
	if err != nil {
		t.Fatal(err)
	}

	for _, entry := range testDirs {
		if !entry.IsDir() {
			continue
		}

		t.Run(entry.Name(), func(t *testing.T) {
			td := t.TempDir()
			inputDir := filepath.Join(fixtureDir, entry.Name())
			testCopyDir(t, inputDir, td)
			defer testChdir(t, td)()

			providerSource, close := newMockProviderSource(t, map[string][]string{
				"test": {"1.2.3"},
			})
			defer close()

			p := showFixtureProvider()

			// init
			ui := new(cli.MockUi)
			ic := &InitCommand{
				Meta: Meta{
					testingOverrides: metaOverridesForProvider(p),
					Ui:               ui,
					ProviderSource:   providerSource,
				},
			}
			if code := ic.Run([]string{}); code != 0 {
				t.Fatalf("init failed\n%s", ui.ErrorWriter)
			}

			// show
			showView, showDone := testView(t)
			sc := &ShowCommand{
				Meta: Meta{
					testingOverrides: metaOverridesForProvider(p),
					View:             showView,
					ProviderSource:   providerSource,
				},
			}

			code := sc.Run([]string{"-json"})
			showOutput := showDone(t)

			if code != 0 {
				t.Fatalf("unexpected exit status %d; want 0\ngot: %s", code, showOutput.Stderr())
			}

			// compare ui output to wanted output
			type state struct {
				FormatVersion    string                 `json:"format_version,omitempty"`
				TerraformVersion string                 `json:"terraform_version"`
				Values           map[string]interface{} `json:"values,omitempty"`
				SensitiveValues  map[string]bool        `json:"sensitive_values,omitempty"`
			}
			var got, want state

			gotString := showOutput.Stdout()
			json.Unmarshal([]byte(gotString), &got)

			wantFile, err := os.Open("output.json")
			if err != nil {
				t.Fatalf("unexpected error: %s", err)
			}
			defer wantFile.Close()
			byteValue, err := ioutil.ReadAll(wantFile)
			if err != nil {
				t.Fatalf("unexpected err: %s", err)
			}
			json.Unmarshal([]byte(byteValue), &want)

			if !cmp.Equal(got, want) {
				t.Fatalf("wrong result:\n %v\n", cmp.Diff(got, want))
			}
		})
	}
}

func TestShow_planWithNonDefaultStateLineage(t *testing.T) {
	// Create a temporary working directory that is empty
	td := t.TempDir()
	testCopyDir(t, testFixturePath("show"), td)
	defer testChdir(t, td)()

	// Write default state file with a testing lineage ("fake-for-testing")
	testStateFileDefault(t, testState())

	// Create a plan with a different lineage, which we should still be able
	// to show
	_, snap := testModuleWithSnapshot(t, "show")
	state := testState()
	plan := testPlan(t)
	stateMeta := statemgr.SnapshotMeta{
		Lineage:          "fake-for-plan",
		Serial:           1,
		TerraformVersion: version.SemVer,
	}
	planPath := testPlanFileMatchState(t, snap, state, plan, stateMeta)

	view, done := testView(t)
	c := &ShowCommand{
		Meta: Meta{
			testingOverrides: metaOverridesForProvider(testProvider()),
			View:             view,
		},
	}

	args := []string{
		planPath,
		"-no-color",
	}
	code := c.Run(args)
	output := done(t)

	if code != 0 {
		t.Fatalf("unexpected exit status %d; want 0\ngot: %s", code, output.Stderr())
	}

	got := output.Stdout()
	want := `No changes. Your infrastructure matches the configuration.`
	if !strings.Contains(got, want) {
		t.Fatalf("unexpected output\ngot: %s\nwant: %s", got, want)
	}
}

func TestShow_corruptStatefile(t *testing.T) {
	td := t.TempDir()
	inputDir := "testdata/show-corrupt-statefile"
	testCopyDir(t, inputDir, td)
	defer testChdir(t, td)()

	view, done := testView(t)
	c := &ShowCommand{
		Meta: Meta{
			testingOverrides: metaOverridesForProvider(testProvider()),
			View:             view,
		},
	}

	code := c.Run([]string{})
	output := done(t)

	if code != 1 {
		t.Fatalf("unexpected exit status %d; want 1\ngot: %s", code, output.Stdout())
	}

	got := output.Stderr()
	want := `Unsupported state file format`
	if !strings.Contains(got, want) {
		t.Errorf("unexpected output\ngot: %s\nwant:\n%s", got, want)
	}
}

// showFixtureSchema returns a schema suitable for processing the configuration
// in testdata/show. This schema should be assigned to a mock provider
// named "test".
func showFixtureSchema() *providers.GetProviderSchemaResponse {
	return &providers.GetProviderSchemaResponse{
		Provider: providers.Schema{
			Block: &configschema.Block{
				Attributes: map[string]*configschema.Attribute{
					"region": {Type: cty.String, Optional: true},
				},
			},
		},
		ResourceTypes: map[string]providers.Schema{
			"test_instance": {
				Block: &configschema.Block{
					Attributes: map[string]*configschema.Attribute{
						"id":  {Type: cty.String, Optional: true, Computed: true},
						"ami": {Type: cty.String, Optional: true},
					},
				},
			},
		},
	}
}

// showFixtureSensitiveSchema returns a schema suitable for processing the configuration
// in testdata/show. This schema should be assigned to a mock provider
// named "test". It includes a sensitive attribute.
func showFixtureSensitiveSchema() *providers.GetProviderSchemaResponse {
	return &providers.GetProviderSchemaResponse{
		Provider: providers.Schema{
			Block: &configschema.Block{
				Attributes: map[string]*configschema.Attribute{
					"region": {Type: cty.String, Optional: true},
				},
			},
		},
		ResourceTypes: map[string]providers.Schema{
			"test_instance": {
				Block: &configschema.Block{
					Attributes: map[string]*configschema.Attribute{
						"id":       {Type: cty.String, Optional: true, Computed: true},
						"ami":      {Type: cty.String, Optional: true},
						"password": {Type: cty.String, Optional: true, Sensitive: true},
					},
				},
			},
		},
	}
}

// showFixtureProvider returns a mock provider that is configured for basic
// operation with the configuration in testdata/show. This mock has
// GetSchemaResponse, PlanResourceChangeFn, and ApplyResourceChangeFn populated,
// with the plan/apply steps just passing through the data determined by
// Terraform Core.
func showFixtureProvider() *terraform.MockProvider {
	p := testProvider()
	p.GetProviderSchemaResponse = showFixtureSchema()
	p.ReadResourceFn = func(req providers.ReadResourceRequest) providers.ReadResourceResponse {
		idVal := req.PriorState.GetAttr("id")
		amiVal := req.PriorState.GetAttr("ami")
		if amiVal.RawEquals(cty.StringVal("refresh-me")) {
			amiVal = cty.StringVal("refreshed")
		}
		return providers.ReadResourceResponse{
			NewState: cty.ObjectVal(map[string]cty.Value{
				"id":  idVal,
				"ami": amiVal,
			}),
			Private: req.Private,
		}
	}
	p.PlanResourceChangeFn = func(req providers.PlanResourceChangeRequest) (resp providers.PlanResourceChangeResponse) {
		// this is a destroy plan,
		if req.ProposedNewState.IsNull() {
			resp.PlannedState = req.ProposedNewState
			resp.PlannedPrivate = req.PriorPrivate
			return resp
		}

		idVal := req.ProposedNewState.GetAttr("id")
		amiVal := req.ProposedNewState.GetAttr("ami")
		if idVal.IsNull() {
			idVal = cty.UnknownVal(cty.String)
		}
		var reqRep []cty.Path
		if amiVal.RawEquals(cty.StringVal("force-replace")) {
			reqRep = append(reqRep, cty.GetAttrPath("ami"))
		}
		return providers.PlanResourceChangeResponse{
			PlannedState: cty.ObjectVal(map[string]cty.Value{
				"id":  idVal,
				"ami": amiVal,
			}),
			RequiresReplace: reqRep,
		}
	}
	p.ApplyResourceChangeFn = func(req providers.ApplyResourceChangeRequest) providers.ApplyResourceChangeResponse {
		idVal := req.PlannedState.GetAttr("id")
		amiVal := req.PlannedState.GetAttr("ami")
		if !idVal.IsKnown() {
			idVal = cty.StringVal("placeholder")
		}
		return providers.ApplyResourceChangeResponse{
			NewState: cty.ObjectVal(map[string]cty.Value{
				"id":  idVal,
				"ami": amiVal,
			}),
		}
	}
	return p
}

// showFixtureSensitiveProvider returns a mock provider that is configured for basic
// operation with the configuration in testdata/show. This mock has
// GetSchemaResponse, PlanResourceChangeFn, and ApplyResourceChangeFn populated,
// with the plan/apply steps just passing through the data determined by
// Terraform Core. It also has a sensitive attribute in the provider schema.
func showFixtureSensitiveProvider() *terraform.MockProvider {
	p := testProvider()
	p.GetProviderSchemaResponse = showFixtureSensitiveSchema()
	p.PlanResourceChangeFn = func(req providers.PlanResourceChangeRequest) providers.PlanResourceChangeResponse {
		idVal := req.ProposedNewState.GetAttr("id")
		if idVal.IsNull() {
			idVal = cty.UnknownVal(cty.String)
		}
		return providers.PlanResourceChangeResponse{
			PlannedState: cty.ObjectVal(map[string]cty.Value{
				"id":       idVal,
				"ami":      req.ProposedNewState.GetAttr("ami"),
				"password": req.ProposedNewState.GetAttr("password"),
			}),
		}
	}
	p.ApplyResourceChangeFn = func(req providers.ApplyResourceChangeRequest) providers.ApplyResourceChangeResponse {
		idVal := req.PlannedState.GetAttr("id")
		if !idVal.IsKnown() {
			idVal = cty.StringVal("placeholder")
		}
		return providers.ApplyResourceChangeResponse{
			NewState: cty.ObjectVal(map[string]cty.Value{
				"id":       idVal,
				"ami":      req.PlannedState.GetAttr("ami"),
				"password": req.PlannedState.GetAttr("password"),
			}),
		}
	}
	return p
}

// showFixturePlanFile creates a plan file at a temporary location containing a
// single change to create or update the test_instance.foo that is included in the "show"
// test fixture, returning the location of that plan file.
// `action` is the planned change you would like to elicit
func showFixturePlanFile(t *testing.T, action plans.Action) string {
	_, snap := testModuleWithSnapshot(t, "show")
	plannedVal := cty.ObjectVal(map[string]cty.Value{
		"id":  cty.UnknownVal(cty.String),
		"ami": cty.StringVal("bar"),
	})
	priorValRaw, err := plans.NewDynamicValue(cty.NullVal(plannedVal.Type()), plannedVal.Type())
	if err != nil {
		t.Fatal(err)
	}
	plannedValRaw, err := plans.NewDynamicValue(plannedVal, plannedVal.Type())
	if err != nil {
		t.Fatal(err)
	}
	plan := testPlan(t)
	plan.Changes.SyncWrapper().AppendResourceInstanceChange(&plans.ResourceInstanceChangeSrc{
		Addr: addrs.Resource{
			Mode: addrs.ManagedResourceMode,
			Type: "test_instance",
			Name: "foo",
		}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance),
		ProviderAddr: addrs.AbsProviderConfig{
			Provider: addrs.NewDefaultProvider("test"),
			Module:   addrs.RootModule,
		},
		ChangeSrc: plans.ChangeSrc{
			Action: action,
			Before: priorValRaw,
			After:  plannedValRaw,
		},
	})
	return testPlanFile(
		t,
		snap,
		states.NewState(),
		plan,
	)
}

// this simplified plan struct allows us to preserve field order when marshaling
// the command output. NOTE: we are leaving "terraform_version" out of this test
// to avoid needing to constantly update the expected output; as a potential
// TODO we could write a jsonplan compare function.
type plan struct {
	FormatVersion   string                 `json:"format_version,omitempty"`
	Variables       map[string]interface{} `json:"variables,omitempty"`
	PlannedValues   map[string]interface{} `json:"planned_values,omitempty"`
	ResourceDrift   []interface{}          `json:"resource_drift,omitempty"`
	ResourceChanges []interface{}          `json:"resource_changes,omitempty"`
	OutputChanges   map[string]interface{} `json:"output_changes,omitempty"`
	PriorState      priorState             `json:"prior_state,omitempty"`
	Config          map[string]interface{} `json:"configuration,omitempty"`
}

type priorState struct {
	FormatVersion   string                 `json:"format_version,omitempty"`
	Values          map[string]interface{} `json:"values,omitempty"`
	SensitiveValues map[string]bool        `json:"sensitive_values,omitempty"`
}
