github.com/cycloidio/terraform@v1.1.10-0.20220513142504-76d5c768dc63/command/fmt_test.go (about)

     1  package command
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"io/ioutil"
     7  	"os"
     8  	"path/filepath"
     9  	"strings"
    10  	"testing"
    11  
    12  	"github.com/google/go-cmp/cmp"
    13  	"github.com/mitchellh/cli"
    14  )
    15  
    16  func TestFmt(t *testing.T) {
    17  	const inSuffix = "_in.tf"
    18  	const outSuffix = "_out.tf"
    19  	const gotSuffix = "_got.tf"
    20  	entries, err := ioutil.ReadDir("testdata/fmt")
    21  	if err != nil {
    22  		t.Fatal(err)
    23  	}
    24  
    25  	td, err := ioutil.TempDir("", "terraform-fmt-test")
    26  	if err != nil {
    27  		t.Fatal(err)
    28  	}
    29  	tmpDir, err := filepath.EvalSymlinks(td)
    30  	if err != nil {
    31  		t.Fatal(err)
    32  	}
    33  	defer os.RemoveAll(td)
    34  
    35  	for _, info := range entries {
    36  		if info.IsDir() {
    37  			continue
    38  		}
    39  		filename := info.Name()
    40  		if !strings.HasSuffix(filename, inSuffix) {
    41  			continue
    42  		}
    43  		testName := filename[:len(filename)-len(inSuffix)]
    44  		t.Run(testName, func(t *testing.T) {
    45  			inFile := filepath.Join("testdata", "fmt", testName+inSuffix)
    46  			wantFile := filepath.Join("testdata", "fmt", testName+outSuffix)
    47  			gotFile := filepath.Join(tmpDir, testName+gotSuffix)
    48  			input, err := ioutil.ReadFile(inFile)
    49  			if err != nil {
    50  				t.Fatal(err)
    51  			}
    52  			want, err := ioutil.ReadFile(wantFile)
    53  			if err != nil {
    54  				t.Fatal(err)
    55  			}
    56  			err = ioutil.WriteFile(gotFile, input, 0700)
    57  			if err != nil {
    58  				t.Fatal(err)
    59  			}
    60  
    61  			ui := cli.NewMockUi()
    62  			c := &FmtCommand{
    63  				Meta: Meta{
    64  					testingOverrides: metaOverridesForProvider(testProvider()),
    65  					Ui:               ui,
    66  				},
    67  			}
    68  			args := []string{gotFile}
    69  			if code := c.Run(args); code != 0 {
    70  				t.Fatalf("fmt command was unsuccessful:\n%s", ui.ErrorWriter.String())
    71  			}
    72  
    73  			got, err := ioutil.ReadFile(gotFile)
    74  			if err != nil {
    75  				t.Fatal(err)
    76  			}
    77  
    78  			if diff := cmp.Diff(string(want), string(got)); diff != "" {
    79  				t.Errorf("wrong result\n%s", diff)
    80  			}
    81  		})
    82  	}
    83  }
    84  
    85  func TestFmt_nonexist(t *testing.T) {
    86  	tempDir := fmtFixtureWriteDir(t)
    87  
    88  	ui := new(cli.MockUi)
    89  	c := &FmtCommand{
    90  		Meta: Meta{
    91  			testingOverrides: metaOverridesForProvider(testProvider()),
    92  			Ui:               ui,
    93  		},
    94  	}
    95  
    96  	missingDir := filepath.Join(tempDir, "doesnotexist")
    97  	args := []string{missingDir}
    98  	if code := c.Run(args); code != 2 {
    99  		t.Fatalf("wrong exit code. errors: \n%s", ui.ErrorWriter.String())
   100  	}
   101  
   102  	expected := "No file or directory at"
   103  	if actual := ui.ErrorWriter.String(); !strings.Contains(actual, expected) {
   104  		t.Fatalf("expected:\n%s\n\nto include: %q", actual, expected)
   105  	}
   106  }
   107  
   108  func TestFmt_syntaxError(t *testing.T) {
   109  	tempDir := testTempDir(t)
   110  
   111  	invalidSrc := `
   112  a = 1 +
   113  `
   114  
   115  	err := ioutil.WriteFile(filepath.Join(tempDir, "invalid.tf"), []byte(invalidSrc), 0644)
   116  	if err != nil {
   117  		t.Fatal(err)
   118  	}
   119  
   120  	ui := new(cli.MockUi)
   121  	c := &FmtCommand{
   122  		Meta: Meta{
   123  			testingOverrides: metaOverridesForProvider(testProvider()),
   124  			Ui:               ui,
   125  		},
   126  	}
   127  
   128  	args := []string{tempDir}
   129  	if code := c.Run(args); code != 2 {
   130  		t.Fatalf("wrong exit code. errors: \n%s", ui.ErrorWriter.String())
   131  	}
   132  
   133  	expected := "Invalid expression"
   134  	if actual := ui.ErrorWriter.String(); !strings.Contains(actual, expected) {
   135  		t.Fatalf("expected:\n%s\n\nto include: %q", actual, expected)
   136  	}
   137  }
   138  
   139  func TestFmt_snippetInError(t *testing.T) {
   140  	tempDir := testTempDir(t)
   141  
   142  	backendSrc := `terraform {backend "s3" {}}`
   143  
   144  	err := ioutil.WriteFile(filepath.Join(tempDir, "backend.tf"), []byte(backendSrc), 0644)
   145  	if err != nil {
   146  		t.Fatal(err)
   147  	}
   148  
   149  	ui := new(cli.MockUi)
   150  	c := &FmtCommand{
   151  		Meta: Meta{
   152  			testingOverrides: metaOverridesForProvider(testProvider()),
   153  			Ui:               ui,
   154  		},
   155  	}
   156  
   157  	args := []string{tempDir}
   158  	if code := c.Run(args); code != 2 {
   159  		t.Fatalf("wrong exit code. errors: \n%s", ui.ErrorWriter.String())
   160  	}
   161  
   162  	substrings := []string{
   163  		"Argument definition required",
   164  		"line 1, in terraform",
   165  		`1: terraform {backend "s3" {}}`,
   166  	}
   167  	for _, substring := range substrings {
   168  		if actual := ui.ErrorWriter.String(); !strings.Contains(actual, substring) {
   169  			t.Errorf("expected:\n%s\n\nto include: %q", actual, substring)
   170  		}
   171  	}
   172  }
   173  
   174  func TestFmt_tooManyArgs(t *testing.T) {
   175  	ui := new(cli.MockUi)
   176  	c := &FmtCommand{
   177  		Meta: Meta{
   178  			testingOverrides: metaOverridesForProvider(testProvider()),
   179  			Ui:               ui,
   180  		},
   181  	}
   182  
   183  	args := []string{
   184  		"one",
   185  		"two",
   186  	}
   187  	if code := c.Run(args); code != 1 {
   188  		t.Fatalf("wrong exit code. errors: \n%s", ui.ErrorWriter.String())
   189  	}
   190  
   191  	expected := "The fmt command expects at most one argument."
   192  	if actual := ui.ErrorWriter.String(); !strings.Contains(actual, expected) {
   193  		t.Fatalf("expected:\n%s\n\nto include: %q", actual, expected)
   194  	}
   195  }
   196  
   197  func TestFmt_workingDirectory(t *testing.T) {
   198  	tempDir := fmtFixtureWriteDir(t)
   199  
   200  	cwd, err := os.Getwd()
   201  	if err != nil {
   202  		t.Fatalf("err: %s", err)
   203  	}
   204  	err = os.Chdir(tempDir)
   205  	if err != nil {
   206  		t.Fatalf("err: %s", err)
   207  	}
   208  	defer os.Chdir(cwd)
   209  
   210  	ui := new(cli.MockUi)
   211  	c := &FmtCommand{
   212  		Meta: Meta{
   213  			testingOverrides: metaOverridesForProvider(testProvider()),
   214  			Ui:               ui,
   215  		},
   216  	}
   217  
   218  	args := []string{}
   219  	if code := c.Run(args); code != 0 {
   220  		t.Fatalf("wrong exit code. errors: \n%s", ui.ErrorWriter.String())
   221  	}
   222  
   223  	expected := fmt.Sprintf("%s\n", fmtFixture.filename)
   224  	if actual := ui.OutputWriter.String(); actual != expected {
   225  		t.Fatalf("got: %q\nexpected: %q", actual, expected)
   226  	}
   227  }
   228  
   229  func TestFmt_directoryArg(t *testing.T) {
   230  	tempDir := fmtFixtureWriteDir(t)
   231  
   232  	ui := new(cli.MockUi)
   233  	c := &FmtCommand{
   234  		Meta: Meta{
   235  			testingOverrides: metaOverridesForProvider(testProvider()),
   236  			Ui:               ui,
   237  		},
   238  	}
   239  
   240  	args := []string{tempDir}
   241  	if code := c.Run(args); code != 0 {
   242  		t.Fatalf("wrong exit code. errors: \n%s", ui.ErrorWriter.String())
   243  	}
   244  
   245  	got, err := filepath.Abs(strings.TrimSpace(ui.OutputWriter.String()))
   246  	if err != nil {
   247  		t.Fatal(err)
   248  	}
   249  	want := filepath.Join(tempDir, fmtFixture.filename)
   250  
   251  	if got != want {
   252  		t.Fatalf("wrong output\ngot:  %s\nwant: %s", got, want)
   253  	}
   254  }
   255  
   256  func TestFmt_fileArg(t *testing.T) {
   257  	tempDir := fmtFixtureWriteDir(t)
   258  
   259  	ui := new(cli.MockUi)
   260  	c := &FmtCommand{
   261  		Meta: Meta{
   262  			testingOverrides: metaOverridesForProvider(testProvider()),
   263  			Ui:               ui,
   264  		},
   265  	}
   266  
   267  	args := []string{filepath.Join(tempDir, fmtFixture.filename)}
   268  	if code := c.Run(args); code != 0 {
   269  		t.Fatalf("wrong exit code. errors: \n%s", ui.ErrorWriter.String())
   270  	}
   271  
   272  	got, err := filepath.Abs(strings.TrimSpace(ui.OutputWriter.String()))
   273  	if err != nil {
   274  		t.Fatal(err)
   275  	}
   276  	want := filepath.Join(tempDir, fmtFixture.filename)
   277  
   278  	if got != want {
   279  		t.Fatalf("wrong output\ngot:  %s\nwant: %s", got, want)
   280  	}
   281  }
   282  
   283  func TestFmt_stdinArg(t *testing.T) {
   284  	input := new(bytes.Buffer)
   285  	input.Write(fmtFixture.input)
   286  
   287  	ui := new(cli.MockUi)
   288  	c := &FmtCommand{
   289  		Meta: Meta{
   290  			testingOverrides: metaOverridesForProvider(testProvider()),
   291  			Ui:               ui,
   292  		},
   293  		input: input,
   294  	}
   295  
   296  	args := []string{"-"}
   297  	if code := c.Run(args); code != 0 {
   298  		t.Fatalf("wrong exit code. errors: \n%s", ui.ErrorWriter.String())
   299  	}
   300  
   301  	expected := fmtFixture.golden
   302  	if actual := ui.OutputWriter.Bytes(); !bytes.Equal(actual, expected) {
   303  		t.Fatalf("got: %q\nexpected: %q", actual, expected)
   304  	}
   305  }
   306  
   307  func TestFmt_nonDefaultOptions(t *testing.T) {
   308  	tempDir := fmtFixtureWriteDir(t)
   309  
   310  	ui := new(cli.MockUi)
   311  	c := &FmtCommand{
   312  		Meta: Meta{
   313  			testingOverrides: metaOverridesForProvider(testProvider()),
   314  			Ui:               ui,
   315  		},
   316  	}
   317  
   318  	args := []string{
   319  		"-list=false",
   320  		"-write=false",
   321  		"-diff",
   322  		tempDir,
   323  	}
   324  	if code := c.Run(args); code != 0 {
   325  		t.Fatalf("wrong exit code. errors: \n%s", ui.ErrorWriter.String())
   326  	}
   327  
   328  	expected := fmt.Sprintf("-%s+%s", fmtFixture.input, fmtFixture.golden)
   329  	if actual := ui.OutputWriter.String(); !strings.Contains(actual, expected) {
   330  		t.Fatalf("expected:\n%s\n\nto include: %q", actual, expected)
   331  	}
   332  }
   333  
   334  func TestFmt_check(t *testing.T) {
   335  	tempDir := fmtFixtureWriteDir(t)
   336  
   337  	ui := new(cli.MockUi)
   338  	c := &FmtCommand{
   339  		Meta: Meta{
   340  			testingOverrides: metaOverridesForProvider(testProvider()),
   341  			Ui:               ui,
   342  		},
   343  	}
   344  
   345  	args := []string{
   346  		"-check",
   347  		tempDir,
   348  	}
   349  	if code := c.Run(args); code != 3 {
   350  		t.Fatalf("wrong exit code. expected 3")
   351  	}
   352  
   353  	// Given that we give relative paths back to the user, normalize this temp
   354  	// dir so that we're comparing against a relative-ized (normalized) path
   355  	tempDir = c.normalizePath(tempDir)
   356  
   357  	if actual := ui.OutputWriter.String(); !strings.Contains(actual, tempDir) {
   358  		t.Fatalf("expected:\n%s\n\nto include: %q", actual, tempDir)
   359  	}
   360  }
   361  
   362  func TestFmt_checkStdin(t *testing.T) {
   363  	input := new(bytes.Buffer)
   364  	input.Write(fmtFixture.input)
   365  
   366  	ui := new(cli.MockUi)
   367  	c := &FmtCommand{
   368  		Meta: Meta{
   369  			testingOverrides: metaOverridesForProvider(testProvider()),
   370  			Ui:               ui,
   371  		},
   372  		input: input,
   373  	}
   374  
   375  	args := []string{
   376  		"-check",
   377  		"-",
   378  	}
   379  	if code := c.Run(args); code != 3 {
   380  		t.Fatalf("wrong exit code. expected 3, got %d", code)
   381  	}
   382  
   383  	if ui.OutputWriter != nil {
   384  		t.Fatalf("expected no output, got: %q", ui.OutputWriter.String())
   385  	}
   386  }
   387  
   388  var fmtFixture = struct {
   389  	filename      string
   390  	input, golden []byte
   391  }{
   392  	"main.tf",
   393  	[]byte(`  foo  =  "bar"
   394  `),
   395  	[]byte(`foo = "bar"
   396  `),
   397  }
   398  
   399  func fmtFixtureWriteDir(t *testing.T) string {
   400  	dir := testTempDir(t)
   401  
   402  	err := ioutil.WriteFile(filepath.Join(dir, fmtFixture.filename), fmtFixture.input, 0644)
   403  	if err != nil {
   404  		t.Fatal(err)
   405  	}
   406  
   407  	return dir
   408  }