kubeform.dev/terraform-backend-sdk@v0.0.0-20220310143633-45f07fe731c5/configs/parser_test.go (about) 1 package configs 2 3 import ( 4 "fmt" 5 "os" 6 "path" 7 "path/filepath" 8 "reflect" 9 "testing" 10 11 "github.com/davecgh/go-spew/spew" 12 13 version "github.com/hashicorp/go-version" 14 "github.com/hashicorp/hcl/v2" 15 "github.com/spf13/afero" 16 ) 17 18 // testParser returns a parser that reads files from the given map, which 19 // is from paths to file contents. 20 // 21 // Since this function uses only in-memory objects, it should never fail. 22 // If any errors are encountered in practice, this function will panic. 23 func testParser(files map[string]string) *Parser { 24 fs := afero.Afero{Fs: afero.NewMemMapFs()} 25 26 for filePath, contents := range files { 27 dirPath := path.Dir(filePath) 28 err := fs.MkdirAll(dirPath, os.ModePerm) 29 if err != nil { 30 panic(err) 31 } 32 err = fs.WriteFile(filePath, []byte(contents), os.ModePerm) 33 if err != nil { 34 panic(err) 35 } 36 } 37 38 return NewParser(fs) 39 } 40 41 // testModuleConfigFrom File reads a single file from the given path as a 42 // module and returns its configuration. This is a helper for use in unit tests. 43 func testModuleConfigFromFile(filename string) (*Config, hcl.Diagnostics) { 44 parser := NewParser(nil) 45 f, diags := parser.LoadConfigFile(filename) 46 mod, modDiags := NewModule([]*File{f}, nil) 47 diags = append(diags, modDiags...) 48 cfg, moreDiags := BuildConfig(mod, nil) 49 return cfg, append(diags, moreDiags...) 50 } 51 52 // testModuleFromDir reads configuration from the given directory path as 53 // a module and returns it. This is a helper for use in unit tests. 54 func testModuleFromDir(path string) (*Module, hcl.Diagnostics) { 55 parser := NewParser(nil) 56 return parser.LoadConfigDir(path) 57 } 58 59 // testModuleFromDir reads configuration from the given directory path as a 60 // module and returns its configuration. This is a helper for use in unit tests. 61 func testModuleConfigFromDir(path string) (*Config, hcl.Diagnostics) { 62 parser := NewParser(nil) 63 mod, diags := parser.LoadConfigDir(path) 64 cfg, moreDiags := BuildConfig(mod, nil) 65 return cfg, append(diags, moreDiags...) 66 } 67 68 // testNestedModuleConfigFromDir reads configuration from the given directory path as 69 // a module with (optional) submodules and returns its configuration. This is a 70 // helper for use in unit tests. 71 func testNestedModuleConfigFromDir(t *testing.T, path string) (*Config, hcl.Diagnostics) { 72 t.Helper() 73 74 parser := NewParser(nil) 75 mod, diags := parser.LoadConfigDir(path) 76 if mod == nil { 77 t.Fatal("got nil root module; want non-nil") 78 } 79 80 versionI := 0 81 cfg, nestedDiags := BuildConfig(mod, ModuleWalkerFunc( 82 func(req *ModuleRequest) (*Module, *version.Version, hcl.Diagnostics) { 83 // For the sake of this test we're going to just treat our 84 // SourceAddr as a path relative to the calling module. 85 // A "real" implementation of ModuleWalker should accept the 86 // various different source address syntaxes Terraform supports. 87 88 // Build a full path by walking up the module tree, prepending each 89 // source address path until we hit the root 90 paths := []string{req.SourceAddr.String()} 91 for config := req.Parent; config != nil && config.Parent != nil; config = config.Parent { 92 paths = append([]string{config.SourceAddr.String()}, paths...) 93 } 94 paths = append([]string{path}, paths...) 95 sourcePath := filepath.Join(paths...) 96 97 mod, diags := parser.LoadConfigDir(sourcePath) 98 version, _ := version.NewVersion(fmt.Sprintf("1.0.%d", versionI)) 99 versionI++ 100 return mod, version, diags 101 }, 102 )) 103 104 diags = append(diags, nestedDiags...) 105 return cfg, diags 106 } 107 108 func assertNoDiagnostics(t *testing.T, diags hcl.Diagnostics) bool { 109 t.Helper() 110 return assertDiagnosticCount(t, diags, 0) 111 } 112 113 func assertDiagnosticCount(t *testing.T, diags hcl.Diagnostics, want int) bool { 114 t.Helper() 115 if len(diags) != want { 116 t.Errorf("wrong number of diagnostics %d; want %d", len(diags), want) 117 for _, diag := range diags { 118 t.Logf("- %s", diag) 119 } 120 return true 121 } 122 return false 123 } 124 125 func assertDiagnosticSummary(t *testing.T, diags hcl.Diagnostics, want string) bool { 126 t.Helper() 127 128 for _, diag := range diags { 129 if diag.Summary == want { 130 return false 131 } 132 } 133 134 t.Errorf("missing diagnostic summary %q", want) 135 for _, diag := range diags { 136 t.Logf("- %s", diag) 137 } 138 return true 139 } 140 141 func assertExactDiagnostics(t *testing.T, diags hcl.Diagnostics, want []string) bool { 142 t.Helper() 143 144 gotDiags := map[string]bool{} 145 wantDiags := map[string]bool{} 146 147 for _, diag := range diags { 148 gotDiags[diag.Error()] = true 149 } 150 for _, msg := range want { 151 wantDiags[msg] = true 152 } 153 154 bad := false 155 for got := range gotDiags { 156 if _, exists := wantDiags[got]; !exists { 157 t.Errorf("unexpected diagnostic: %s", got) 158 bad = true 159 } 160 } 161 for want := range wantDiags { 162 if _, exists := gotDiags[want]; !exists { 163 t.Errorf("missing expected diagnostic: %s", want) 164 bad = true 165 } 166 } 167 168 return bad 169 } 170 171 func assertResultDeepEqual(t *testing.T, got, want interface{}) bool { 172 t.Helper() 173 if !reflect.DeepEqual(got, want) { 174 t.Errorf("wrong result\ngot: %swant: %s", spew.Sdump(got), spew.Sdump(want)) 175 return true 176 } 177 return false 178 } 179 180 func stringPtr(s string) *string { 181 return &s 182 }