github.com/muratcelep/terraform@v1.1.0-beta2-not-internal-4/not-internal/configs/parser_config_test.go (about) 1 package configs 2 3 import ( 4 "bufio" 5 "bytes" 6 "io/ioutil" 7 "path/filepath" 8 "strings" 9 "testing" 10 11 "github.com/google/go-cmp/cmp" 12 13 "github.com/hashicorp/hcl/v2" 14 ) 15 16 // TestParseLoadConfigFileSuccess is a simple test that just verifies that 17 // a number of test configuration files (in testdata/valid-files) can 18 // be parsed without raising any diagnostics. 19 // 20 // This test does not verify that reading these files produces the correct 21 // file element contents. More detailed assertions may be made on some subset 22 // of these configuration files in other tests. 23 func TestParserLoadConfigFileSuccess(t *testing.T) { 24 files, err := ioutil.ReadDir("testdata/valid-files") 25 if err != nil { 26 t.Fatal(err) 27 } 28 29 for _, info := range files { 30 name := info.Name() 31 t.Run(name, func(t *testing.T) { 32 src, err := ioutil.ReadFile(filepath.Join("testdata/valid-files", name)) 33 if err != nil { 34 t.Fatal(err) 35 } 36 37 parser := testParser(map[string]string{ 38 name: string(src), 39 }) 40 41 _, diags := parser.LoadConfigFile(name) 42 if len(diags) != 0 { 43 t.Errorf("unexpected diagnostics") 44 for _, diag := range diags { 45 t.Logf("- %s", diag) 46 } 47 } 48 }) 49 } 50 } 51 52 // TestParseLoadConfigFileFailure is a simple test that just verifies that 53 // a number of test configuration files (in testdata/invalid-files) 54 // produce errors as expected. 55 // 56 // This test does not verify specific error messages, so more detailed 57 // assertions should be made on some subset of these configuration files in 58 // other tests. 59 func TestParserLoadConfigFileFailure(t *testing.T) { 60 files, err := ioutil.ReadDir("testdata/invalid-files") 61 if err != nil { 62 t.Fatal(err) 63 } 64 65 for _, info := range files { 66 name := info.Name() 67 t.Run(name, func(t *testing.T) { 68 src, err := ioutil.ReadFile(filepath.Join("testdata/invalid-files", name)) 69 if err != nil { 70 t.Fatal(err) 71 } 72 73 parser := testParser(map[string]string{ 74 name: string(src), 75 }) 76 77 _, diags := parser.LoadConfigFile(name) 78 if !diags.HasErrors() { 79 t.Errorf("LoadConfigFile succeeded; want errors") 80 } 81 for _, diag := range diags { 82 t.Logf("- %s", diag) 83 } 84 }) 85 } 86 } 87 88 // This test uses a subset of the same fixture files as 89 // TestParserLoadConfigFileFailure, but additionally verifies that each 90 // file produces the expected diagnostic summary. 91 func TestParserLoadConfigFileFailureMessages(t *testing.T) { 92 tests := []struct { 93 Filename string 94 WantSeverity hcl.DiagnosticSeverity 95 WantDiag string 96 }{ 97 { 98 "invalid-files/data-resource-lifecycle.tf", 99 hcl.DiagError, 100 "Unsupported lifecycle block", 101 }, 102 { 103 "invalid-files/variable-type-unknown.tf", 104 hcl.DiagError, 105 "Invalid type specification", 106 }, 107 { 108 "invalid-files/unexpected-attr.tf", 109 hcl.DiagError, 110 "Unsupported argument", 111 }, 112 { 113 "invalid-files/unexpected-block.tf", 114 hcl.DiagError, 115 "Unsupported block type", 116 }, 117 { 118 "invalid-files/resource-count-and-for_each.tf", 119 hcl.DiagError, 120 `Invalid combination of "count" and "for_each"`, 121 }, 122 { 123 "invalid-files/data-count-and-for_each.tf", 124 hcl.DiagError, 125 `Invalid combination of "count" and "for_each"`, 126 }, 127 { 128 "invalid-files/resource-lifecycle-badbool.tf", 129 hcl.DiagError, 130 "Unsuitable value type", 131 }, 132 } 133 134 for _, test := range tests { 135 t.Run(test.Filename, func(t *testing.T) { 136 src, err := ioutil.ReadFile(filepath.Join("testdata", test.Filename)) 137 if err != nil { 138 t.Fatal(err) 139 } 140 141 parser := testParser(map[string]string{ 142 test.Filename: string(src), 143 }) 144 145 _, diags := parser.LoadConfigFile(test.Filename) 146 if len(diags) != 1 { 147 t.Errorf("Wrong number of diagnostics %d; want 1", len(diags)) 148 for _, diag := range diags { 149 t.Logf("- %s", diag) 150 } 151 return 152 } 153 if diags[0].Severity != test.WantSeverity { 154 t.Errorf("Wrong diagnostic severity %#v; want %#v", diags[0].Severity, test.WantSeverity) 155 } 156 if diags[0].Summary != test.WantDiag { 157 t.Errorf("Wrong diagnostic summary\ngot: %s\nwant: %s", diags[0].Summary, test.WantDiag) 158 } 159 }) 160 } 161 } 162 163 // TestParseLoadConfigFileWarning is a test that verifies files from 164 // testdata/warning-files produce particular warnings. 165 // 166 // This test does not verify that reading these files produces the correct 167 // file element contents in spite of those warnings. More detailed assertions 168 // may be made on some subset of these configuration files in other tests. 169 func TestParserLoadConfigFileWarning(t *testing.T) { 170 files, err := ioutil.ReadDir("testdata/warning-files") 171 if err != nil { 172 t.Fatal(err) 173 } 174 175 for _, info := range files { 176 name := info.Name() 177 t.Run(name, func(t *testing.T) { 178 src, err := ioutil.ReadFile(filepath.Join("testdata/warning-files", name)) 179 if err != nil { 180 t.Fatal(err) 181 } 182 183 // First we'll scan the file to see what warnings are expected. 184 // That's declared inside the files themselves by using the 185 // string "WARNING: " somewhere on each line that is expected 186 // to produce a warning, followed by the expected warning summary 187 // text. A single-line comment (with #) is the main way to do that. 188 const marker = "WARNING: " 189 sc := bufio.NewScanner(bytes.NewReader(src)) 190 wantWarnings := make(map[int]string) 191 lineNum := 1 192 for sc.Scan() { 193 lineText := sc.Text() 194 if idx := strings.Index(lineText, marker); idx != -1 { 195 summaryText := lineText[idx+len(marker):] 196 wantWarnings[lineNum] = summaryText 197 } 198 lineNum++ 199 } 200 201 parser := testParser(map[string]string{ 202 name: string(src), 203 }) 204 205 _, diags := parser.LoadConfigFile(name) 206 if diags.HasErrors() { 207 t.Errorf("unexpected error diagnostics") 208 for _, diag := range diags { 209 t.Logf("- %s", diag) 210 } 211 } 212 213 gotWarnings := make(map[int]string) 214 for _, diag := range diags { 215 if diag.Severity != hcl.DiagWarning || diag.Subject == nil { 216 continue 217 } 218 gotWarnings[diag.Subject.Start.Line] = diag.Summary 219 } 220 221 if diff := cmp.Diff(wantWarnings, gotWarnings); diff != "" { 222 t.Errorf("wrong warnings\n%s", diff) 223 } 224 }) 225 } 226 } 227 228 // TestParseLoadConfigFileError is a test that verifies files from 229 // testdata/warning-files produce particular errors. 230 // 231 // This test does not verify that reading these files produces the correct 232 // file element contents in spite of those errors. More detailed assertions 233 // may be made on some subset of these configuration files in other tests. 234 func TestParserLoadConfigFileError(t *testing.T) { 235 files, err := ioutil.ReadDir("testdata/error-files") 236 if err != nil { 237 t.Fatal(err) 238 } 239 240 for _, info := range files { 241 name := info.Name() 242 t.Run(name, func(t *testing.T) { 243 src, err := ioutil.ReadFile(filepath.Join("testdata/error-files", name)) 244 if err != nil { 245 t.Fatal(err) 246 } 247 248 // First we'll scan the file to see what warnings are expected. 249 // That's declared inside the files themselves by using the 250 // string "ERROR: " somewhere on each line that is expected 251 // to produce a warning, followed by the expected warning summary 252 // text. A single-line comment (with #) is the main way to do that. 253 const marker = "ERROR: " 254 sc := bufio.NewScanner(bytes.NewReader(src)) 255 wantErrors := make(map[int]string) 256 lineNum := 1 257 for sc.Scan() { 258 lineText := sc.Text() 259 if idx := strings.Index(lineText, marker); idx != -1 { 260 summaryText := lineText[idx+len(marker):] 261 wantErrors[lineNum] = summaryText 262 } 263 lineNum++ 264 } 265 266 parser := testParser(map[string]string{ 267 name: string(src), 268 }) 269 270 _, diags := parser.LoadConfigFile(name) 271 272 gotErrors := make(map[int]string) 273 for _, diag := range diags { 274 if diag.Severity != hcl.DiagError || diag.Subject == nil { 275 continue 276 } 277 gotErrors[diag.Subject.Start.Line] = diag.Summary 278 } 279 280 if diff := cmp.Diff(wantErrors, gotErrors); diff != "" { 281 t.Errorf("wrong errors\n%s", diff) 282 } 283 }) 284 } 285 }