4fabad7f61
The `nomad fmt -check` command incorrectly writes to file because we didn't return before writing the file on a diff. Fix this bug and update the command internals to differentiate between the write-to-file and write-to-stdout code paths, which are activated by different combinations of options and flags. The docstring for the `-list` and `-write` flags is also unclear and can be easily misread to be the opposite of the actual behavior. Clarify this and fix up the docs to match. This changeset also refactors the tests quite a bit so as to make the test outputs clear when something is incorrect.
287 lines
5.7 KiB
Go
287 lines
5.7 KiB
Go
package command
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
|
|
"github.com/hashicorp/nomad/ci"
|
|
"github.com/mitchellh/cli"
|
|
"github.com/shoenig/test/must"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestFmtCommand(t *testing.T) {
|
|
ci.Parallel(t)
|
|
|
|
const inSuffix = ".in.hcl"
|
|
const expectedSuffix = ".out.hcl"
|
|
|
|
tests := []struct {
|
|
name string
|
|
testFile string
|
|
flags []string
|
|
expectWrite bool
|
|
expectCode int
|
|
}{
|
|
{
|
|
name: "config with check",
|
|
testFile: "nomad",
|
|
flags: []string{"-check"},
|
|
expectCode: 1,
|
|
},
|
|
{
|
|
name: "config without check",
|
|
testFile: "nomad",
|
|
flags: []string{},
|
|
expectWrite: true,
|
|
expectCode: 0,
|
|
},
|
|
{
|
|
name: "job with check",
|
|
testFile: "job",
|
|
flags: []string{"-check"},
|
|
expectCode: 1,
|
|
},
|
|
{
|
|
name: "job without check",
|
|
testFile: "job",
|
|
flags: []string{},
|
|
expectWrite: true,
|
|
expectCode: 0,
|
|
},
|
|
}
|
|
|
|
for _, tc := range tests {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
tc := tc
|
|
ci.Parallel(t)
|
|
|
|
tmpDir := t.TempDir()
|
|
inFile := filepath.Join("testdata", "fmt", tc.testFile+inSuffix)
|
|
expectedFile := filepath.Join("testdata", "fmt", tc.testFile+expectedSuffix)
|
|
fmtFile := filepath.Join(tmpDir, tc.testFile+".hcl")
|
|
|
|
expected, err := os.ReadFile(expectedFile)
|
|
must.NoError(t, err)
|
|
|
|
// copy the input file to the test tempdir so that we don't
|
|
// overwrite the test input in source control
|
|
input, err := os.ReadFile(inFile)
|
|
must.NoError(t, err)
|
|
must.NoError(t, os.WriteFile(fmtFile, input, 0644))
|
|
|
|
ui := cli.NewMockUi()
|
|
cmd := &FormatCommand{
|
|
Meta: Meta{Ui: ui},
|
|
}
|
|
|
|
flags := append(tc.flags, fmtFile)
|
|
|
|
code := cmd.Run(flags)
|
|
must.Eq(t, tc.expectCode, code)
|
|
|
|
// compare the maybe-overwritten file contents
|
|
actual, err := os.ReadFile(fmtFile)
|
|
must.NoError(t, err)
|
|
|
|
if tc.expectWrite {
|
|
must.Eq(t, string(expected), string(actual))
|
|
} else {
|
|
must.Eq(t, string(input), string(actual))
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestFmtCommand_FromStdin(t *testing.T) {
|
|
ci.Parallel(t)
|
|
|
|
tests := []struct {
|
|
name string
|
|
flags []string
|
|
expectCode int
|
|
}{
|
|
{
|
|
name: "with check",
|
|
flags: []string{"-check", "-"},
|
|
expectCode: 1,
|
|
},
|
|
{
|
|
name: "without check",
|
|
flags: []string{"-"},
|
|
expectCode: 0,
|
|
},
|
|
}
|
|
|
|
for _, tc := range tests {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
|
|
stdinFake := bytes.NewBuffer(fmtFixture.input)
|
|
ui := cli.NewMockUi()
|
|
cmd := &FormatCommand{
|
|
Meta: Meta{Ui: ui},
|
|
stdin: stdinFake,
|
|
}
|
|
|
|
code := cmd.Run(tc.flags)
|
|
must.Eq(t, tc.expectCode, code)
|
|
must.StrContains(t, string(fmtFixture.golden), ui.OutputWriter.String())
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestFmtCommand_FromWorkingDirectory(t *testing.T) {
|
|
tmpDir := fmtFixtureWriteDir(t)
|
|
|
|
cwd, err := os.Getwd()
|
|
require.NoError(t, err)
|
|
|
|
err = os.Chdir(tmpDir)
|
|
require.NoError(t, err)
|
|
defer os.Chdir(cwd)
|
|
|
|
tests := []struct {
|
|
name string
|
|
flags []string
|
|
expectCode int
|
|
}{
|
|
{
|
|
name: "with check",
|
|
flags: []string{"-check"},
|
|
expectCode: 1,
|
|
},
|
|
{
|
|
name: "without check",
|
|
flags: []string{},
|
|
expectCode: 0,
|
|
},
|
|
}
|
|
|
|
for _, tc := range tests {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
ui := cli.NewMockUi()
|
|
cmd := &FormatCommand{Meta: Meta{Ui: ui}}
|
|
code := cmd.Run(tc.flags)
|
|
must.Eq(t, tc.expectCode, code)
|
|
must.Eq(t, fmt.Sprintf("%s\n", fmtFixture.filename), ui.OutputWriter.String())
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestFmtCommand_FromDirectoryArgument(t *testing.T) {
|
|
tmpDir := fmtFixtureWriteDir(t)
|
|
|
|
tests := []struct {
|
|
name string
|
|
flags []string
|
|
expectCode int
|
|
}{
|
|
{
|
|
name: "with check",
|
|
flags: []string{"-check", tmpDir},
|
|
expectCode: 1,
|
|
},
|
|
{
|
|
name: "without check",
|
|
flags: []string{tmpDir},
|
|
expectCode: 0,
|
|
},
|
|
}
|
|
|
|
for _, tc := range tests {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
ui := cli.NewMockUi()
|
|
cmd := &FormatCommand{Meta: Meta{Ui: ui}}
|
|
|
|
code := cmd.Run(tc.flags)
|
|
must.Eq(t, tc.expectCode, code)
|
|
must.Eq(t,
|
|
fmt.Sprintf("%s\n", filepath.Join(tmpDir, fmtFixture.filename)),
|
|
ui.OutputWriter.String())
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestFmtCommand_FromFileArgument(t *testing.T) {
|
|
tmpDir := fmtFixtureWriteDir(t)
|
|
path := filepath.Join(tmpDir, fmtFixture.filename)
|
|
|
|
tests := []struct {
|
|
name string
|
|
flags []string
|
|
expectCode int
|
|
}{
|
|
{
|
|
name: "with check",
|
|
flags: []string{"-check", path},
|
|
expectCode: 1,
|
|
},
|
|
{
|
|
name: "without check",
|
|
flags: []string{path},
|
|
expectCode: 0,
|
|
},
|
|
}
|
|
|
|
for _, tc := range tests {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
ui := cli.NewMockUi()
|
|
cmd := &FormatCommand{Meta: Meta{Ui: ui}}
|
|
|
|
code := cmd.Run(tc.flags)
|
|
must.Eq(t, tc.expectCode, code)
|
|
must.Eq(t, fmt.Sprintf("%s\n", path), ui.OutputWriter.String())
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestFmtCommand_FileDoesNotExist(t *testing.T) {
|
|
ci.Parallel(t)
|
|
|
|
ui := cli.NewMockUi()
|
|
cmd := &FormatCommand{
|
|
Meta: Meta{Ui: ui},
|
|
}
|
|
|
|
code := cmd.Run([]string{"file/does/not/exist.hcl"})
|
|
assert.Equal(t, 1, code)
|
|
}
|
|
|
|
func TestFmtCommand_InvalidSyntax(t *testing.T) {
|
|
ci.Parallel(t)
|
|
|
|
stdinFake := bytes.NewBufferString(`client {enabled true }`)
|
|
|
|
ui := cli.NewMockUi()
|
|
cmd := &FormatCommand{
|
|
Meta: Meta{Ui: ui},
|
|
stdin: stdinFake,
|
|
}
|
|
|
|
code := cmd.Run([]string{"-"})
|
|
assert.Equal(t, 1, code)
|
|
}
|
|
|
|
func fmtFixtureWriteDir(t *testing.T) string {
|
|
dir := t.TempDir()
|
|
|
|
err := os.WriteFile(filepath.Join(dir, fmtFixture.filename), fmtFixture.input, 0644)
|
|
require.NoError(t, err)
|
|
|
|
return dir
|
|
}
|
|
|
|
var fmtFixture = struct {
|
|
filename string
|
|
input []byte
|
|
golden []byte
|
|
}{
|
|
filename: "nomad.hcl",
|
|
input: []byte("client {enabled = true}"),
|
|
golden: []byte("client { enabled = true }\n\n"),
|
|
}
|