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 }