github.com/hashicorp/terraform-plugin-sdk@v1.17.2/internal/plans/planfile/planfile_test.go (about)

     1  package planfile
     2  
     3  import (
     4  	"io/ioutil"
     5  	"path/filepath"
     6  	"reflect"
     7  	"testing"
     8  
     9  	"github.com/davecgh/go-spew/spew"
    10  
    11  	"github.com/hashicorp/terraform-plugin-sdk/internal/configs/configload"
    12  	"github.com/hashicorp/terraform-plugin-sdk/internal/plans"
    13  	"github.com/hashicorp/terraform-plugin-sdk/internal/states"
    14  	"github.com/hashicorp/terraform-plugin-sdk/internal/states/statefile"
    15  	tfversion "github.com/hashicorp/terraform-plugin-sdk/internal/version"
    16  )
    17  
    18  func TestRoundtrip(t *testing.T) {
    19  	fixtureDir := filepath.Join("testdata", "test-config")
    20  	loader, err := configload.NewLoader(&configload.Config{
    21  		ModulesDir: filepath.Join(fixtureDir, ".terraform", "modules"),
    22  	})
    23  	if err != nil {
    24  		t.Fatal(err)
    25  	}
    26  
    27  	_, snapIn, diags := loader.LoadConfigWithSnapshot(fixtureDir)
    28  	if diags.HasErrors() {
    29  		t.Fatal(diags.Error())
    30  	}
    31  
    32  	// Just a minimal state file so we can test that it comes out again at all.
    33  	// We don't need to test the entire thing because the state file
    34  	// serialization is already tested in its own package.
    35  	stateFileIn := &statefile.File{
    36  		TerraformVersion: tfversion.SemVer,
    37  		Serial:           1,
    38  		Lineage:          "abc123",
    39  		State:            states.NewState(),
    40  	}
    41  
    42  	// Minimal plan too, since the serialization of the tfplan portion of the
    43  	// file is tested more fully in tfplan_test.go .
    44  	planIn := &plans.Plan{
    45  		Changes: &plans.Changes{
    46  			Resources: []*plans.ResourceInstanceChangeSrc{},
    47  			Outputs:   []*plans.OutputChangeSrc{},
    48  		},
    49  		ProviderSHA256s: map[string][]byte{},
    50  		VariableValues: map[string]plans.DynamicValue{
    51  			"foo": plans.DynamicValue([]byte("foo placeholder")),
    52  		},
    53  		Backend: plans.Backend{
    54  			Type:      "local",
    55  			Config:    plans.DynamicValue([]byte("config placeholder")),
    56  			Workspace: "default",
    57  		},
    58  	}
    59  
    60  	workDir, err := ioutil.TempDir("", "tf-planfile")
    61  	if err != nil {
    62  		t.Fatal(err)
    63  	}
    64  	planFn := filepath.Join(workDir, "tfplan")
    65  
    66  	err = Create(planFn, snapIn, stateFileIn, planIn)
    67  	if err != nil {
    68  		t.Fatalf("failed to create plan file: %s", err)
    69  	}
    70  
    71  	pr, err := Open(planFn)
    72  	if err != nil {
    73  		t.Fatalf("failed to open plan file for reading: %s", err)
    74  	}
    75  
    76  	t.Run("ReadPlan", func(t *testing.T) {
    77  		planOut, err := pr.ReadPlan()
    78  		if err != nil {
    79  			t.Fatalf("failed to read plan: %s", err)
    80  		}
    81  		if !reflect.DeepEqual(planIn, planOut) {
    82  			t.Errorf("plan did not survive round-trip\nresult: %sinput: %s", spew.Sdump(planOut), spew.Sdump(planIn))
    83  		}
    84  	})
    85  
    86  	t.Run("ReadStateFile", func(t *testing.T) {
    87  		stateFileOut, err := pr.ReadStateFile()
    88  		if err != nil {
    89  			t.Fatalf("failed to read state: %s", err)
    90  		}
    91  		if !reflect.DeepEqual(stateFileIn, stateFileOut) {
    92  			t.Errorf("state file did not survive round-trip\nresult: %sinput: %s", spew.Sdump(stateFileOut), spew.Sdump(stateFileIn))
    93  		}
    94  	})
    95  
    96  	t.Run("ReadConfigSnapshot", func(t *testing.T) {
    97  		snapOut, err := pr.ReadConfigSnapshot()
    98  		if err != nil {
    99  			t.Fatalf("failed to read config snapshot: %s", err)
   100  		}
   101  		if !reflect.DeepEqual(snapIn, snapOut) {
   102  			t.Errorf("config snapshot did not survive round-trip\nresult: %sinput: %s", spew.Sdump(snapOut), spew.Sdump(snapIn))
   103  		}
   104  	})
   105  
   106  	t.Run("ReadConfig", func(t *testing.T) {
   107  		// Reading from snapshots is tested in the configload package, so
   108  		// here we'll just test that we can successfully do it, to see if the
   109  		// glue code in _this_ package is correct.
   110  		_, diags := pr.ReadConfig()
   111  		if diags.HasErrors() {
   112  			t.Errorf("when reading config: %s", diags.Err())
   113  		}
   114  	})
   115  }