github.com/hernad/nomad@v1.6.112/command/fmt_test.go (about)

     1  // Copyright (c) HashiCorp, Inc.
     2  // SPDX-License-Identifier: MPL-2.0
     3  
     4  package command
     5  
     6  import (
     7  	"bytes"
     8  	"fmt"
     9  	"os"
    10  	"path/filepath"
    11  	"testing"
    12  
    13  	"github.com/hernad/nomad/ci"
    14  	"github.com/mitchellh/cli"
    15  	"github.com/shoenig/test/must"
    16  	"github.com/stretchr/testify/assert"
    17  	"github.com/stretchr/testify/require"
    18  )
    19  
    20  func TestFmtCommand(t *testing.T) {
    21  	ci.Parallel(t)
    22  
    23  	const inSuffix = ".in.hcl"
    24  	const expectedSuffix = ".out.hcl"
    25  
    26  	tests := []struct {
    27  		name        string
    28  		testFile    string
    29  		flags       []string
    30  		expectWrite bool
    31  		expectCode  int
    32  	}{
    33  		{
    34  			name:       "config with check",
    35  			testFile:   "nomad",
    36  			flags:      []string{"-check"},
    37  			expectCode: 1,
    38  		},
    39  		{
    40  			name:        "config without check",
    41  			testFile:    "nomad",
    42  			flags:       []string{},
    43  			expectWrite: true,
    44  			expectCode:  0,
    45  		},
    46  		{
    47  			name:       "job with check",
    48  			testFile:   "job",
    49  			flags:      []string{"-check"},
    50  			expectCode: 1,
    51  		},
    52  		{
    53  			name:        "job without check",
    54  			testFile:    "job",
    55  			flags:       []string{},
    56  			expectWrite: true,
    57  			expectCode:  0,
    58  		},
    59  	}
    60  
    61  	for _, tc := range tests {
    62  		t.Run(tc.name, func(t *testing.T) {
    63  			tc := tc
    64  			ci.Parallel(t)
    65  
    66  			tmpDir := t.TempDir()
    67  			inFile := filepath.Join("testdata", "fmt", tc.testFile+inSuffix)
    68  			expectedFile := filepath.Join("testdata", "fmt", tc.testFile+expectedSuffix)
    69  			fmtFile := filepath.Join(tmpDir, tc.testFile+".hcl")
    70  
    71  			expected, err := os.ReadFile(expectedFile)
    72  			must.NoError(t, err)
    73  
    74  			// copy the input file to the test tempdir so that we don't
    75  			// overwrite the test input in source control
    76  			input, err := os.ReadFile(inFile)
    77  			must.NoError(t, err)
    78  			must.NoError(t, os.WriteFile(fmtFile, input, 0644))
    79  
    80  			ui := cli.NewMockUi()
    81  			cmd := &FormatCommand{
    82  				Meta: Meta{Ui: ui},
    83  			}
    84  
    85  			flags := append(tc.flags, fmtFile)
    86  
    87  			code := cmd.Run(flags)
    88  			must.Eq(t, tc.expectCode, code)
    89  
    90  			// compare the maybe-overwritten file contents
    91  			actual, err := os.ReadFile(fmtFile)
    92  			must.NoError(t, err)
    93  
    94  			if tc.expectWrite {
    95  				must.Eq(t, string(expected), string(actual))
    96  			} else {
    97  				must.Eq(t, string(input), string(actual))
    98  			}
    99  		})
   100  	}
   101  }
   102  
   103  func TestFmtCommand_FromStdin(t *testing.T) {
   104  	ci.Parallel(t)
   105  
   106  	tests := []struct {
   107  		name       string
   108  		flags      []string
   109  		expectCode int
   110  	}{
   111  		{
   112  			name:       "with check",
   113  			flags:      []string{"-check", "-"},
   114  			expectCode: 1,
   115  		},
   116  		{
   117  			name:       "without check",
   118  			flags:      []string{"-"},
   119  			expectCode: 0,
   120  		},
   121  	}
   122  
   123  	for _, tc := range tests {
   124  		t.Run(tc.name, func(t *testing.T) {
   125  
   126  			stdinFake := bytes.NewBuffer(fmtFixture.input)
   127  			ui := cli.NewMockUi()
   128  			cmd := &FormatCommand{
   129  				Meta:  Meta{Ui: ui},
   130  				stdin: stdinFake,
   131  			}
   132  
   133  			code := cmd.Run(tc.flags)
   134  			must.Eq(t, tc.expectCode, code)
   135  			must.StrContains(t, string(fmtFixture.golden), ui.OutputWriter.String())
   136  		})
   137  	}
   138  }
   139  
   140  func TestFmtCommand_FromWorkingDirectory(t *testing.T) {
   141  	tmpDir := fmtFixtureWriteDir(t)
   142  
   143  	cwd, err := os.Getwd()
   144  	require.NoError(t, err)
   145  
   146  	err = os.Chdir(tmpDir)
   147  	require.NoError(t, err)
   148  	defer os.Chdir(cwd)
   149  
   150  	tests := []struct {
   151  		name       string
   152  		flags      []string
   153  		expectCode int
   154  	}{
   155  		{
   156  			name:       "with check",
   157  			flags:      []string{"-check"},
   158  			expectCode: 1,
   159  		},
   160  		{
   161  			name:       "without check",
   162  			flags:      []string{},
   163  			expectCode: 0,
   164  		},
   165  	}
   166  
   167  	for _, tc := range tests {
   168  		t.Run(tc.name, func(t *testing.T) {
   169  			ui := cli.NewMockUi()
   170  			cmd := &FormatCommand{Meta: Meta{Ui: ui}}
   171  			code := cmd.Run(tc.flags)
   172  			must.Eq(t, tc.expectCode, code)
   173  			must.Eq(t, fmt.Sprintf("%s\n", fmtFixture.filename), ui.OutputWriter.String())
   174  		})
   175  	}
   176  }
   177  
   178  func TestFmtCommand_FromDirectoryArgument(t *testing.T) {
   179  	tmpDir := fmtFixtureWriteDir(t)
   180  
   181  	tests := []struct {
   182  		name       string
   183  		flags      []string
   184  		expectCode int
   185  	}{
   186  		{
   187  			name:       "with check",
   188  			flags:      []string{"-check", tmpDir},
   189  			expectCode: 1,
   190  		},
   191  		{
   192  			name:       "without check",
   193  			flags:      []string{tmpDir},
   194  			expectCode: 0,
   195  		},
   196  	}
   197  
   198  	for _, tc := range tests {
   199  		t.Run(tc.name, func(t *testing.T) {
   200  			ui := cli.NewMockUi()
   201  			cmd := &FormatCommand{Meta: Meta{Ui: ui}}
   202  
   203  			code := cmd.Run(tc.flags)
   204  			must.Eq(t, tc.expectCode, code)
   205  			must.Eq(t,
   206  				fmt.Sprintf("%s\n", filepath.Join(tmpDir, fmtFixture.filename)),
   207  				ui.OutputWriter.String())
   208  		})
   209  	}
   210  }
   211  
   212  func TestFmtCommand_FromFileArgument(t *testing.T) {
   213  	tmpDir := fmtFixtureWriteDir(t)
   214  	path := filepath.Join(tmpDir, fmtFixture.filename)
   215  
   216  	tests := []struct {
   217  		name       string
   218  		flags      []string
   219  		expectCode int
   220  	}{
   221  		{
   222  			name:       "with check",
   223  			flags:      []string{"-check", path},
   224  			expectCode: 1,
   225  		},
   226  		{
   227  			name:       "without check",
   228  			flags:      []string{path},
   229  			expectCode: 0,
   230  		},
   231  	}
   232  
   233  	for _, tc := range tests {
   234  		t.Run(tc.name, func(t *testing.T) {
   235  			ui := cli.NewMockUi()
   236  			cmd := &FormatCommand{Meta: Meta{Ui: ui}}
   237  
   238  			code := cmd.Run(tc.flags)
   239  			must.Eq(t, tc.expectCode, code)
   240  			must.Eq(t, fmt.Sprintf("%s\n", path), ui.OutputWriter.String())
   241  		})
   242  	}
   243  }
   244  
   245  func TestFmtCommand_FileDoesNotExist(t *testing.T) {
   246  	ci.Parallel(t)
   247  
   248  	ui := cli.NewMockUi()
   249  	cmd := &FormatCommand{
   250  		Meta: Meta{Ui: ui},
   251  	}
   252  
   253  	code := cmd.Run([]string{"file/does/not/exist.hcl"})
   254  	assert.Equal(t, 1, code)
   255  }
   256  
   257  func TestFmtCommand_InvalidSyntax(t *testing.T) {
   258  	ci.Parallel(t)
   259  
   260  	stdinFake := bytes.NewBufferString(`client {enabled true }`)
   261  
   262  	ui := cli.NewMockUi()
   263  	cmd := &FormatCommand{
   264  		Meta:  Meta{Ui: ui},
   265  		stdin: stdinFake,
   266  	}
   267  
   268  	code := cmd.Run([]string{"-"})
   269  	assert.Equal(t, 1, code)
   270  }
   271  
   272  func fmtFixtureWriteDir(t *testing.T) string {
   273  	dir := t.TempDir()
   274  
   275  	err := os.WriteFile(filepath.Join(dir, fmtFixture.filename), fmtFixture.input, 0644)
   276  	require.NoError(t, err)
   277  
   278  	return dir
   279  }
   280  
   281  var fmtFixture = struct {
   282  	filename string
   283  	input    []byte
   284  	golden   []byte
   285  }{
   286  	filename: "nomad.hcl",
   287  	input:    []byte("client   {enabled = true}"),
   288  	golden:   []byte("client { enabled = true }\n\n"),
   289  }