@@ -12,6 +12,7 @@ import (
1212
1313 "github.com/google/go-cmp/cmp"
1414 "github.com/google/go-cmp/cmp/cmpopts"
15+ "github.com/hashicorp/hcl/v2"
1516 "github.com/hashicorp/terraform/internal/addrs"
1617 "github.com/hashicorp/terraform/internal/configs/configschema"
1718 "github.com/hashicorp/terraform/internal/plans"
@@ -24,15 +25,16 @@ import (
2425
2526func TestContext2Plan_queryList (t * testing.T ) {
2627 cases := []struct {
27- name string
28- mainConfig string
29- queryConfig string
30- generatedPath string
31- diagCount int
32- expectedErrMsg []string
33- assertState func (* states.State )
34- assertChanges func (providers.ProviderSchema , * plans.ChangesSrc )
35- listResourceFn func (request providers.ListResourceRequest ) providers.ListResourceResponse
28+ name string
29+ mainConfig string
30+ queryConfig string
31+ generatedPath string
32+ expectedErrMsg []string
33+ transformSchema func (* providers.GetProviderSchemaResponse )
34+ assertState func (* states.State )
35+ assertValidateDiags func (t * testing.T , diags tfdiags.Diagnostics )
36+ assertChanges func (providers.ProviderSchema , * plans.ChangesSrc )
37+ listResourceFn func (request providers.ListResourceRequest ) providers.ListResourceResponse
3638 }{
3739 {
3840 name : "valid list reference - generates config" ,
@@ -262,7 +264,68 @@ func TestContext2Plan_queryList(t *testing.T) {
262264 },
263265 },
264266 {
265- name : "valid list with empty config" ,
267+ // want this to fail
268+ name : "with empty config when it is required" ,
269+ mainConfig : `
270+ terraform {
271+ required_providers {
272+ test = {
273+ source = "hashicorp/test"
274+ version = "1.0.0"
275+ }
276+ }
277+ }
278+ ` ,
279+ queryConfig : `
280+ variable "input" {
281+ type = string
282+ default = "foo"
283+ }
284+
285+ list "test_resource" "test" {
286+ provider = test
287+ }
288+ ` ,
289+
290+ transformSchema : func (schema * providers.GetProviderSchemaResponse ) {
291+ schema .ListResourceTypes ["test_resource" ].Body .BlockTypes = map [string ]* configschema.NestedBlock {
292+ "config" : {
293+ Block : configschema.Block {
294+ Attributes : map [string ]* configschema.Attribute {
295+ "filter" : {
296+ Required : true ,
297+ NestedType : & configschema.Object {
298+ Nesting : configschema .NestingSingle ,
299+ Attributes : map [string ]* configschema.Attribute {
300+ "attr" : {
301+ Type : cty .String ,
302+ Optional : true ,
303+ },
304+ },
305+ },
306+ },
307+ },
308+ },
309+ Nesting : configschema .NestingSingle ,
310+ MinItems : 1 ,
311+ MaxItems : 1 ,
312+ },
313+ }
314+
315+ },
316+ assertValidateDiags : func (t * testing.T , diags tfdiags.Diagnostics ) {
317+ tfdiags .AssertDiagnosticCount (t , diags , 1 )
318+ var exp tfdiags.Diagnostics
319+ exp = exp .Append (& hcl.Diagnostic {
320+ Summary : "Missing config block" ,
321+ Detail : "A block of type \" config\" is required here." ,
322+ Subject : diags [0 ].Source ().Subject .ToHCL ().Ptr (),
323+ })
324+ tfdiags .AssertDiagnosticsMatch (t , diags , exp )
325+ },
326+ },
327+ {
328+ name : "with empty optional config" ,
266329 mainConfig : `
267330 terraform {
268331 required_providers {
@@ -283,6 +346,30 @@ func TestContext2Plan_queryList(t *testing.T) {
283346 provider = test
284347 }
285348 ` ,
349+ transformSchema : func (schema * providers.GetProviderSchemaResponse ) {
350+ schema .ListResourceTypes ["test_resource" ].Body .BlockTypes = map [string ]* configschema.NestedBlock {
351+ "config" : {
352+ Block : configschema.Block {
353+ Attributes : map [string ]* configschema.Attribute {
354+ "filter" : {
355+ Optional : true ,
356+ NestedType : & configschema.Object {
357+ Nesting : configschema .NestingSingle ,
358+ Attributes : map [string ]* configschema.Attribute {
359+ "attr" : {
360+ Type : cty .String ,
361+ Optional : true ,
362+ },
363+ },
364+ },
365+ },
366+ },
367+ },
368+ Nesting : configschema .NestingSingle ,
369+ },
370+ }
371+
372+ },
286373 listResourceFn : func (request providers.ListResourceRequest ) providers.ListResourceResponse {
287374 madeUp := []cty.Value {
288375 cty .ObjectVal (map [string ]cty.Value {"instance_type" : cty .StringVal ("ami-123456" )}),
@@ -397,10 +484,17 @@ func TestContext2Plan_queryList(t *testing.T) {
397484 }
398485 }
399486 ` ,
400- diagCount : 1 ,
401- expectedErrMsg : []string {
402- "Invalid list resource traversal" ,
403- "The first step in the traversal for a list resource must be an attribute \" data\" " ,
487+ assertValidateDiags : func (t * testing.T , diags tfdiags.Diagnostics ) {
488+ tfdiags .AssertDiagnosticCount (t , diags , 1 )
489+ var exp tfdiags.Diagnostics
490+ exp = exp .Append (& hcl.Diagnostic {
491+ Severity : hcl .DiagError ,
492+ Summary : "Invalid list resource traversal" ,
493+ Detail : "The first step in the traversal for a list resource must be an attribute \" data\" ." ,
494+ Subject : diags [0 ].Source ().Subject .ToHCL ().Ptr (),
495+ })
496+
497+ tfdiags .AssertDiagnosticsMatch (t , diags , exp )
404498 },
405499 },
406500 {
@@ -428,9 +522,18 @@ func TestContext2Plan_queryList(t *testing.T) {
428522 }
429523 }
430524 ` ,
431- diagCount : 1 ,
432- expectedErrMsg : []string {
433- "A list resource \" non_existent\" \" attr\" has not been declared in the root module." ,
525+ assertValidateDiags : func (t * testing.T , diags tfdiags.Diagnostics ) {
526+ tfdiags .AssertDiagnosticCount (t , diags , 1 )
527+ var exp tfdiags.Diagnostics
528+
529+ exp = exp .Append (& hcl.Diagnostic {
530+ Severity : hcl .DiagError ,
531+ Summary : "Reference to undeclared resource" ,
532+ Detail : "A list resource \" non_existent\" \" attr\" has not been declared in the root module." ,
533+ Subject : diags [0 ].Source ().Subject .ToHCL ().Ptr (),
534+ })
535+
536+ tfdiags .AssertDiagnosticsMatch (t , diags , exp )
434537 },
435538 },
436539 {
@@ -469,9 +572,18 @@ func TestContext2Plan_queryList(t *testing.T) {
469572 }
470573 }
471574 ` ,
472- diagCount : 1 ,
473- expectedErrMsg : []string {
474- "Unsupported attribute: This object has no argument, nested block, or exported attribute named \" invalid_attr\" ." ,
575+ assertValidateDiags : func (t * testing.T , diags tfdiags.Diagnostics ) {
576+ tfdiags .AssertDiagnosticCount (t , diags , 1 )
577+ var exp tfdiags.Diagnostics
578+
579+ exp = exp .Append (& hcl.Diagnostic {
580+ Severity : hcl .DiagError ,
581+ Summary : "Unsupported attribute" ,
582+ Detail : "This object has no argument, nested block, or exported attribute named \" invalid_attr\" ." ,
583+ Subject : diags [0 ].Source ().Subject .ToHCL ().Ptr (),
584+ })
585+
586+ tfdiags .AssertDiagnosticsMatch (t , diags , exp )
475587 },
476588 listResourceFn : func (request providers.ListResourceRequest ) providers.ListResourceResponse {
477589 madeUp := []cty.Value {
@@ -540,9 +652,14 @@ func TestContext2Plan_queryList(t *testing.T) {
540652 }
541653 }
542654 ` ,
543- diagCount : 1 ,
544- expectedErrMsg : []string {
545- "Cycle: list.test_resource" ,
655+ assertValidateDiags : func (t * testing.T , diags tfdiags.Diagnostics ) {
656+ tfdiags .AssertDiagnosticCount (t , diags , 1 )
657+ if ! strings .Contains (diags [0 ].Description ().Summary , "Cycle: list.test_resource" ) {
658+ t .Errorf ("Expected error message to contain 'Cycle: list.test_resource', got %q" , diags [0 ].Description ().Summary )
659+ }
660+ if diags [0 ].Severity () != tfdiags .Error {
661+ t .Errorf ("Expected error severity to be Error, got %s" , diags [0 ].Severity ())
662+ }
546663 },
547664 },
548665 {
@@ -661,7 +778,7 @@ func TestContext2Plan_queryList(t *testing.T) {
661778 },
662779 {
663780 // Test list reference with index but without data field
664- name : "list reference with index but without data field " ,
781+ name : "list reference as for_each " ,
665782 mainConfig : `
666783 terraform {
667784 required_providers {
@@ -784,6 +901,9 @@ func TestContext2Plan_queryList(t *testing.T) {
784901 provider := testProvider ("test" )
785902 provider .ConfigureProvider (providers.ConfigureProviderRequest {})
786903 provider .GetProviderSchemaResponse = getListProviderSchemaResp ()
904+ if tc .transformSchema != nil {
905+ tc .transformSchema (provider .GetProviderSchemaResponse )
906+ }
787907 var requestConfigs = make (map [string ]cty.Value )
788908 provider .ListResourceFn = func (request providers.ListResourceRequest ) providers.ListResourceResponse {
789909 if request .Config .IsNull () || request .Config .GetAttr ("config" ).IsNull () {
@@ -804,15 +924,20 @@ func TestContext2Plan_queryList(t *testing.T) {
804924 })
805925 tfdiags .AssertNoDiagnostics (t , diags )
806926
927+ diags = ctx .Validate (mod , & ValidateOpts {})
928+ if tc .assertValidateDiags != nil {
929+ tc .assertValidateDiags (t , diags )
930+ return
931+ } else {
932+ tfdiags .AssertNoDiagnostics (t , diags )
933+ }
934+
807935 plan , diags := ctx .Plan (mod , states .NewState (), & PlanOpts {
808936 Mode : plans .NormalMode ,
809937 SetVariables : testInputValuesUnset (mod .Module .Variables ),
810938 Query : true ,
811939 GenerateConfigPath : tc .generatedPath ,
812940 })
813- if len (diags ) != tc .diagCount {
814- t .Fatalf ("expected %d diagnostics, got %d \n -diags: %s" , tc .diagCount , len (diags ), diags )
815- }
816941
817942 if tc .assertChanges != nil {
818943 sch , err := ctx .Schemas (mod , states .NewState ())
@@ -821,15 +946,6 @@ func TestContext2Plan_queryList(t *testing.T) {
821946 }
822947 tc .assertChanges (sch .Providers [providerAddr ], plan .Changes )
823948 }
824-
825- if tc .diagCount > 0 {
826- for _ , err := range tc .expectedErrMsg {
827- if ! strings .Contains (diags .Err ().Error (), err ) {
828- t .Fatalf ("expected error message %q, but got %q" , err , diags .Err ().Error ())
829- }
830- }
831- }
832-
833949 })
834950 }
835951}
0 commit comments