-
Notifications
You must be signed in to change notification settings - Fork 80
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: add terramate fmt #351
Changes from all commits
70949a6
331de56
df90f3f
1adb846
b0a045e
015e69e
6a7e026
2f51327
a6def35
69b1eca
8b9e99a
45d1c60
7008447
0d53a2f
d21fec6
22c868b
1aea15f
7160f5c
dff097f
47d1f1f
3911bd8
5cc555f
2bbf873
622755b
22bf5cc
f22439e
a7e4405
54fa336
8bda361
77e589f
0416c76
fbf01da
41a8911
8e23219
e2015f7
0860d8b
b9ab265
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,180 @@ | ||
// Copyright 2022 Mineiros GmbH | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
package e2etest | ||
|
||
import ( | ||
"fmt" | ||
"path/filepath" | ||
"strings" | ||
"testing" | ||
|
||
"github.com/madlambda/spells/assert" | ||
"github.com/mineiros-io/terramate/hcl" | ||
"github.com/mineiros-io/terramate/test/sandbox" | ||
) | ||
|
||
func TestFormatRecursively(t *testing.T) { | ||
const unformattedHCL = ` | ||
globals { | ||
name = "name" | ||
description = "desc" | ||
test = true | ||
} | ||
` | ||
formattedHCL, err := hcl.Format(unformattedHCL, "") | ||
assert.NoError(t, err) | ||
|
||
s := sandbox.New(t) | ||
cli := newCLI(t, s.RootDir()) | ||
|
||
t.Run("checking succeeds when there is no Terramate files", func(t *testing.T) { | ||
assertRunResult(t, cli.run("fmt", "--check"), runExpected{}) | ||
}) | ||
|
||
t.Run("formatting succeeds when there is no Terramate files", func(t *testing.T) { | ||
assertRunResult(t, cli.run("fmt"), runExpected{}) | ||
}) | ||
|
||
sprintf := fmt.Sprintf | ||
writeUnformattedFiles := func() { | ||
s.BuildTree([]string{ | ||
sprintf("f:globals.tm:%s", unformattedHCL), | ||
sprintf("f:another-stacks/globals.tm.hcl:%s", unformattedHCL), | ||
sprintf("f:another-stacks/stack-1/globals.tm.hcl:%s", unformattedHCL), | ||
sprintf("f:another-stacks/stack-2/globals.tm.hcl:%s", unformattedHCL), | ||
sprintf("f:stacks/globals.tm:%s", unformattedHCL), | ||
sprintf("f:stacks/stack-1/globals.tm:%s", unformattedHCL), | ||
sprintf("f:stacks/stack-2/globals.tm:%s", unformattedHCL), | ||
}) | ||
} | ||
|
||
writeUnformattedFiles() | ||
|
||
wantedFiles := []string{ | ||
"globals.tm", | ||
"another-stacks/globals.tm.hcl", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. maybe add a test with There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done, thanks for catching this (actually I was aware the tests were lacking and went into rush mode anyway, but it is good investment to improve that now, it didn't even take that long 😆 ) |
||
"another-stacks/stack-1/globals.tm.hcl", | ||
"another-stacks/stack-2/globals.tm.hcl", | ||
"stacks/globals.tm", | ||
"stacks/stack-1/globals.tm", | ||
"stacks/stack-2/globals.tm", | ||
} | ||
filesListOutput := func(files []string) string { | ||
return strings.Join(files, "\n") + "\n" | ||
} | ||
wantedFilesStr := filesListOutput(wantedFiles) | ||
|
||
assertFileContents := func(t *testing.T, path string, want string) { | ||
t.Helper() | ||
got := s.RootEntry().ReadFile(path) | ||
assert.EqualStrings(t, want, string(got)) | ||
} | ||
|
||
assertWantedFilesContents := func(t *testing.T, want string) { | ||
t.Helper() | ||
|
||
for _, file := range wantedFiles { | ||
assertFileContents(t, file, want) | ||
} | ||
} | ||
|
||
t.Run("checking fails with unformatted files", func(t *testing.T) { | ||
assertRunResult(t, cli.run("fmt", "--check"), runExpected{ | ||
Status: 1, | ||
Stdout: wantedFilesStr, | ||
}) | ||
assertWantedFilesContents(t, unformattedHCL) | ||
}) | ||
|
||
t.Run("checking fails with unformatted files on subdirs", func(t *testing.T) { | ||
subdir := filepath.Join(s.RootDir(), "another-stacks") | ||
cli := newCLI(t, subdir) | ||
assertRunResult(t, cli.run("fmt", "--check"), runExpected{ | ||
Status: 1, | ||
Stdout: filesListOutput([]string{ | ||
"globals.tm.hcl", | ||
"stack-1/globals.tm.hcl", | ||
"stack-2/globals.tm.hcl", | ||
}), | ||
}) | ||
assertWantedFilesContents(t, unformattedHCL) | ||
}) | ||
|
||
t.Run("update unformatted files in place", func(t *testing.T) { | ||
assertRunResult(t, cli.run("fmt"), runExpected{ | ||
Stdout: wantedFilesStr, | ||
}) | ||
assertWantedFilesContents(t, formattedHCL) | ||
}) | ||
|
||
t.Run("checking succeeds when all files are formatted", func(t *testing.T) { | ||
assertRunResult(t, cli.run("fmt", "--check"), runExpected{}) | ||
assertWantedFilesContents(t, formattedHCL) | ||
}) | ||
|
||
t.Run("formatting succeeds when all files are formatted", func(t *testing.T) { | ||
assertRunResult(t, cli.run("fmt"), runExpected{}) | ||
assertWantedFilesContents(t, formattedHCL) | ||
}) | ||
|
||
t.Run("update unformatted files in subdirs", func(t *testing.T) { | ||
writeUnformattedFiles() | ||
|
||
anotherStacks := filepath.Join(s.RootDir(), "another-stacks") | ||
cli := newCLI(t, anotherStacks) | ||
assertRunResult(t, cli.run("fmt"), runExpected{ | ||
Stdout: filesListOutput([]string{ | ||
"globals.tm.hcl", | ||
"stack-1/globals.tm.hcl", | ||
"stack-2/globals.tm.hcl", | ||
}), | ||
}) | ||
|
||
assertFileContents(t, "another-stacks/globals.tm.hcl", formattedHCL) | ||
assertFileContents(t, "another-stacks/stack-1/globals.tm.hcl", formattedHCL) | ||
assertFileContents(t, "another-stacks/stack-2/globals.tm.hcl", formattedHCL) | ||
|
||
assertFileContents(t, "globals.tm", unformattedHCL) | ||
assertFileContents(t, "stacks/globals.tm", unformattedHCL) | ||
assertFileContents(t, "stacks/stack-1/globals.tm", unformattedHCL) | ||
assertFileContents(t, "stacks/stack-2/globals.tm", unformattedHCL) | ||
|
||
stacks := filepath.Join(s.RootDir(), "stacks") | ||
cli = newCLI(t, stacks) | ||
assertRunResult(t, cli.run("fmt"), runExpected{ | ||
Stdout: filesListOutput([]string{ | ||
"globals.tm", | ||
"stack-1/globals.tm", | ||
"stack-2/globals.tm", | ||
}), | ||
}) | ||
|
||
assertFileContents(t, "another-stacks/globals.tm.hcl", formattedHCL) | ||
assertFileContents(t, "another-stacks/stack-1/globals.tm.hcl", formattedHCL) | ||
assertFileContents(t, "another-stacks/stack-2/globals.tm.hcl", formattedHCL) | ||
assertFileContents(t, "stacks/globals.tm", formattedHCL) | ||
assertFileContents(t, "stacks/stack-1/globals.tm", formattedHCL) | ||
assertFileContents(t, "stacks/stack-2/globals.tm", formattedHCL) | ||
|
||
assertFileContents(t, "globals.tm", unformattedHCL) | ||
|
||
cli = newCLI(t, s.RootDir()) | ||
assertRunResult(t, cli.run("fmt"), runExpected{ | ||
Stdout: filesListOutput([]string{"globals.tm"}), | ||
}) | ||
|
||
assertWantedFilesContents(t, formattedHCL) | ||
}) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -31,8 +31,6 @@ import ( | |
"github.com/madlambda/spells/assert" | ||
"github.com/rs/zerolog" | ||
"github.com/zclconf/go-cty/cty" | ||
|
||
tmhclwrite "github.com/mineiros-io/terramate/test/hclwrite" | ||
) | ||
|
||
func FuzzPartialEval(f *testing.F) { | ||
|
@@ -92,13 +90,9 @@ func FuzzPartialEval(f *testing.F) { | |
|
||
const testattr = "attr" | ||
|
||
cfg := hcldoc( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Now hclwriter always produces valid HCL, so if you use it to build invalid HCL files it panics, seemed like the way to go since it is what we want on 99% of the tests, we use it to build some valid HCL file for testing. But here we generate possibly invalid HCLs and that would cause panics, so it seemed easier to just create the HCL with a string since it is a pretty straithforward attr = val. |
||
expr(testattr, str), | ||
) | ||
|
||
cfgString := cfg.String() | ||
cfg := fmt.Sprintf("%s = %s", testattr, str) | ||
parser := hclparse.NewParser() | ||
file, diags := parser.ParseHCL([]byte(cfgString), "fuzz") | ||
file, diags := parser.ParseHCL([]byte(cfg), "fuzz") | ||
if diags.HasErrors() { | ||
return | ||
} | ||
|
@@ -108,7 +102,7 @@ func FuzzPartialEval(f *testing.F) { | |
parsedExpr := attr.Expr | ||
|
||
exprRange := parsedExpr.Range() | ||
exprBytes := cfgString[exprRange.Start.Byte:exprRange.End.Byte] | ||
exprBytes := cfg[exprRange.Start.Byte:exprRange.End.Byte] | ||
|
||
parsedTokens, diags := hclsyntax.LexExpression([]byte(exprBytes), "fuzz", hcl.Pos{}) | ||
if diags.HasErrors() { | ||
|
@@ -123,9 +117,9 @@ func FuzzPartialEval(f *testing.F) { | |
engine := newPartialEvalEngine(want, ctx) | ||
got, err := engine.Eval() | ||
|
||
if strings.Contains(cfgString, "global") || | ||
strings.Contains(cfgString, "terramate") || | ||
strings.Contains(cfgString, "tm_") { | ||
if strings.Contains(cfg, "global") || | ||
strings.Contains(cfg, "terramate") || | ||
strings.Contains(cfg, "tm_") { | ||
// TODO(katcipis): Validate generated code properties when | ||
// substitution is in play. | ||
return | ||
|
@@ -156,14 +150,6 @@ func tokensStr(t hclwrite.Tokens) string { | |
return "[" + strings.Join(tokensStrs, ",") + "]" | ||
} | ||
|
||
func hcldoc(builders ...tmhclwrite.BlockBuilder) *tmhclwrite.Block { | ||
return tmhclwrite.BuildHCL(builders...) | ||
} | ||
|
||
func expr(name string, expr string) tmhclwrite.BlockBuilder { | ||
return tmhclwrite.Expression(name, expr) | ||
} | ||
|
||
func init() { | ||
zerolog.SetGlobalLevel(zerolog.Disabled) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
top