github.com/terraform-linters/tflint@v0.51.2-0.20240520175844-3750771571b6/integrationtest/autofix/autofix_test.go (about)

     1  package main
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/json"
     6  	"io"
     7  	"io/fs"
     8  	"log"
     9  	"os"
    10  	"path/filepath"
    11  	"runtime"
    12  	"strings"
    13  	"testing"
    14  
    15  	"github.com/google/go-cmp/cmp"
    16  	"github.com/terraform-linters/tflint/cmd"
    17  	"github.com/terraform-linters/tflint/formatter"
    18  	"github.com/terraform-linters/tflint/tflint"
    19  )
    20  
    21  func TestMain(m *testing.M) {
    22  	log.SetOutput(io.Discard)
    23  	os.Exit(m.Run())
    24  }
    25  
    26  func TestIntegration(t *testing.T) {
    27  	cases := []struct {
    28  		Name    string
    29  		Command string
    30  		Env     map[string]string
    31  		Dir     string
    32  	}{
    33  		{
    34  			Name:    "simple fix",
    35  			Command: "./tflint --format json --fix",
    36  			Dir:     "simple",
    37  		},
    38  		{
    39  			Name:    "multiple fix in a file",
    40  			Command: "./tflint --format json --fix",
    41  			Dir:     "multiple_fix",
    42  		},
    43  		{
    44  			Name:    "ignore by annotation",
    45  			Command: "./tflint --format json --fix",
    46  			Dir:     "ignore_by_annotation",
    47  		},
    48  		{
    49  			Name:    "multiple fix by multiple rules",
    50  			Command: "./tflint --format json --fix",
    51  			Dir:     "fix_by_multiple_rules",
    52  		},
    53  		{
    54  			Name:    "conflict fix by multiple rules",
    55  			Command: "./tflint --format json --fix",
    56  			Dir:     "conflict_fix",
    57  		},
    58  		{
    59  			Name:    "fix in multiple files",
    60  			Command: "./tflint --format json --fix",
    61  			Dir:     "multiple_files",
    62  		},
    63  		{
    64  			Name:    "calling modules",
    65  			Command: "./tflint --format json --fix",
    66  			Dir:     "module",
    67  		},
    68  		{
    69  			Name:    "--chdir",
    70  			Command: "./tflint --chdir=dir --format json --fix",
    71  			Dir:     "chdir",
    72  		},
    73  		{
    74  			Name:    "--chdir with conflict",
    75  			Command: "./tflint --chdir=dir --format json --fix",
    76  			Dir:     "chdir_with_conflict",
    77  		},
    78  		{
    79  			Name:    "--filter",
    80  			Command: "./tflint --format json --fix --filter=main.tf",
    81  			Dir:     "filter",
    82  		},
    83  	}
    84  
    85  	// Disable the bundled plugin because the `os.Executable()` is go(1) in the tests
    86  	tflint.DisableBundledPlugin = true
    87  	defer func() {
    88  		tflint.DisableBundledPlugin = false
    89  	}()
    90  
    91  	dir, _ := os.Getwd()
    92  	for _, tc := range cases {
    93  		t.Run(tc.Name, func(t *testing.T) {
    94  			testDir := filepath.Join(dir, tc.Dir)
    95  
    96  			defer func() {
    97  				if err := os.Chdir(dir); err != nil {
    98  					t.Fatal(err)
    99  				}
   100  			}()
   101  			if err := os.Chdir(testDir); err != nil {
   102  				t.Fatal(err)
   103  			}
   104  
   105  			tfFiles := map[string][]byte{}
   106  			err := filepath.Walk(".", func(path string, info fs.FileInfo, err error) error {
   107  				if info.IsDir() {
   108  					return nil
   109  				}
   110  				if strings.HasSuffix(path, ".tf") {
   111  					sources, err := os.ReadFile(path)
   112  					if err != nil {
   113  						return err
   114  					}
   115  					tfFiles[path] = sources
   116  				}
   117  				return nil
   118  			})
   119  			if err != nil {
   120  				t.Fatal(err)
   121  			}
   122  			defer func() {
   123  				// restore original files
   124  				for path := range tfFiles {
   125  					if err := os.WriteFile(path, tfFiles[path], 0644); err != nil {
   126  						t.Fatal(err)
   127  					}
   128  				}
   129  			}()
   130  
   131  			resultFile := "result.json"
   132  			if runtime.GOOS == "windows" && IsWindowsResultExist() {
   133  				resultFile = "result_windows.json"
   134  			}
   135  
   136  			if tc.Env != nil {
   137  				for k, v := range tc.Env {
   138  					t.Setenv(k, v)
   139  				}
   140  			}
   141  
   142  			outStream, errStream := new(bytes.Buffer), new(bytes.Buffer)
   143  			cli, err := cmd.NewCLI(outStream, errStream)
   144  			if err != nil {
   145  				t.Fatal(err)
   146  			}
   147  			args := strings.Split(tc.Command, " ")
   148  
   149  			cli.Run(args)
   150  
   151  			b, err := os.ReadFile(filepath.Join(testDir, resultFile))
   152  			if err != nil {
   153  				t.Fatal(err)
   154  			}
   155  
   156  			var expected *formatter.JSONOutput
   157  			if err := json.Unmarshal(b, &expected); err != nil {
   158  				t.Fatal(err)
   159  			}
   160  
   161  			var got *formatter.JSONOutput
   162  			if err := json.Unmarshal(outStream.Bytes(), &got); err != nil {
   163  				t.Fatal(err)
   164  			}
   165  
   166  			if diff := cmp.Diff(got, expected); diff != "" {
   167  				t.Fatal(diff)
   168  			}
   169  
   170  			// test autofixed files
   171  			for path := range tfFiles {
   172  				_, err := os.Stat(path + ".fixed")
   173  				if os.IsNotExist(err) {
   174  					// should be unchanged
   175  					got, err := os.ReadFile(path)
   176  					if err != nil {
   177  						t.Fatal(err)
   178  					}
   179  					if diff := cmp.Diff(string(got), string(tfFiles[path])); diff != "" {
   180  						t.Fatal(diff)
   181  					}
   182  				} else if err == nil {
   183  					// should be changed
   184  					got, err := os.ReadFile(path)
   185  					if err != nil {
   186  						t.Fatal(err)
   187  					}
   188  					want, err := os.ReadFile(path + ".fixed")
   189  					if err != nil {
   190  						t.Fatal(err)
   191  					}
   192  					if diff := cmp.Diff(string(got), string(want)); diff != "" {
   193  						t.Fatal(diff)
   194  					}
   195  				} else {
   196  					t.Fatal(err)
   197  				}
   198  			}
   199  		})
   200  	}
   201  }
   202  
   203  func IsWindowsResultExist() bool {
   204  	_, err := os.Stat("result_windows.json")
   205  	return !os.IsNotExist(err)
   206  }