Skip to content

Commit 9b30743

Browse files
committed
unit tests around pathing for validation API
1 parent 071f904 commit 9b30743

File tree

1 file changed

+169
-0
lines changed

1 file changed

+169
-0
lines changed

helper/schema/provider_test.go

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,175 @@ func TestProviderValidate(t *testing.T) {
290290
}
291291
}
292292

293+
func TestProviderValidate_attributePath(t *testing.T) {
294+
cases := []struct {
295+
P *Provider
296+
Config map[string]interface{}
297+
ExpectedDiags diag.Diagnostics
298+
}{
299+
{ // validate path automatically built across list
300+
P: &Provider{
301+
Schema: map[string]*Schema{
302+
"foo": {
303+
Type: TypeList,
304+
Required: true,
305+
Elem: &Resource{
306+
Schema: map[string]*Schema{
307+
"bar": {
308+
Type: TypeString,
309+
Required: true,
310+
ValidateFunc: func(v interface{}, k string) ([]string, []error) {
311+
return []string{"warn"}, []error{fmt.Errorf("error")}
312+
},
313+
},
314+
},
315+
},
316+
},
317+
},
318+
},
319+
Config: map[string]interface{}{
320+
"foo": []interface{}{
321+
map[string]interface{}{
322+
"bar": "baz",
323+
},
324+
},
325+
},
326+
ExpectedDiags: diag.Diagnostics{
327+
{
328+
Severity: diag.Warning,
329+
AttributePath: cty.Path{cty.GetAttrStep{Name: "foo"}, cty.IndexStep{Key: cty.NumberIntVal(0)}, cty.GetAttrStep{Name: "bar"}},
330+
},
331+
{
332+
Severity: diag.Error,
333+
AttributePath: cty.Path{cty.GetAttrStep{Name: "foo"}, cty.IndexStep{Key: cty.NumberIntVal(0)}, cty.GetAttrStep{Name: "bar"}},
334+
},
335+
},
336+
},
337+
{ // path is truncated at typeset
338+
P: &Provider{
339+
Schema: map[string]*Schema{
340+
"foo": {
341+
Type: TypeSet,
342+
Required: true,
343+
Elem: &Resource{
344+
Schema: map[string]*Schema{
345+
"bar": {
346+
Type: TypeString,
347+
Required: true,
348+
ValidateDiagFunc: func(v interface{}, path cty.Path) diag.Diagnostics {
349+
return diag.Diagnostics{{Severity: diag.Error, AttributePath: cty.Path{cty.GetAttrStep{Name: "doesnotmatter"}}}}
350+
},
351+
},
352+
},
353+
},
354+
},
355+
},
356+
},
357+
Config: map[string]interface{}{
358+
"foo": []interface{}{
359+
map[string]interface{}{
360+
"bar": "baz",
361+
},
362+
},
363+
},
364+
ExpectedDiags: diag.Diagnostics{
365+
{
366+
Severity: diag.Error,
367+
AttributePath: cty.Path{cty.GetAttrStep{Name: "foo"}},
368+
},
369+
},
370+
},
371+
{ // relative path is appended
372+
P: &Provider{
373+
Schema: map[string]*Schema{
374+
"foo": {
375+
Type: TypeList,
376+
Required: true,
377+
Elem: &Resource{
378+
Schema: map[string]*Schema{
379+
"bar": {
380+
Type: TypeMap,
381+
Required: true,
382+
ValidateDiagFunc: func(v interface{}, path cty.Path) diag.Diagnostics {
383+
return diag.Diagnostics{{Severity: diag.Error, AttributePath: cty.Path{cty.IndexStep{Key: cty.StringVal("mapkey")}}}}
384+
},
385+
},
386+
},
387+
},
388+
},
389+
},
390+
},
391+
Config: map[string]interface{}{
392+
"foo": []interface{}{
393+
map[string]interface{}{
394+
"bar": map[string]interface{}{
395+
"mapkey": "val",
396+
},
397+
},
398+
},
399+
},
400+
ExpectedDiags: diag.Diagnostics{
401+
{
402+
Severity: diag.Error,
403+
AttributePath: cty.Path{cty.GetAttrStep{Name: "foo"}, cty.IndexStep{Key: cty.NumberIntVal(0)}, cty.GetAttrStep{Name: "bar"}, cty.IndexStep{Key: cty.StringVal("mapkey")}},
404+
},
405+
},
406+
},
407+
{ // absolute path is not altered
408+
P: &Provider{
409+
Schema: map[string]*Schema{
410+
"foo": {
411+
Type: TypeList,
412+
Required: true,
413+
Elem: &Resource{
414+
Schema: map[string]*Schema{
415+
"bar": {
416+
Type: TypeMap,
417+
Required: true,
418+
ValidateDiagFunc: func(v interface{}, path cty.Path) diag.Diagnostics {
419+
return diag.Diagnostics{{Severity: diag.Error, AttributePath: append(path, cty.IndexStep{Key: cty.StringVal("mapkey")})}}
420+
},
421+
},
422+
},
423+
},
424+
},
425+
},
426+
},
427+
Config: map[string]interface{}{
428+
"foo": []interface{}{
429+
map[string]interface{}{
430+
"bar": map[string]interface{}{
431+
"mapkey": "val",
432+
},
433+
},
434+
},
435+
},
436+
ExpectedDiags: diag.Diagnostics{
437+
{
438+
Severity: diag.Error,
439+
AttributePath: cty.Path{cty.GetAttrStep{Name: "foo"}, cty.IndexStep{Key: cty.NumberIntVal(0)}, cty.GetAttrStep{Name: "bar"}, cty.IndexStep{Key: cty.StringVal("mapkey")}},
440+
},
441+
},
442+
},
443+
}
444+
445+
for i, tc := range cases {
446+
c := terraform.NewResourceConfigRaw(tc.Config)
447+
diags := tc.P.Validate(c)
448+
if len(diags) != len(tc.ExpectedDiags) {
449+
t.Fatalf("%d: wrong number of diags, expected %d, got %d", i, len(tc.ExpectedDiags), len(diags))
450+
}
451+
for j := range diags {
452+
if diags[j].Severity != tc.ExpectedDiags[j].Severity {
453+
t.Fatalf("%d: expected severity %v, got %v", i, tc.ExpectedDiags[j].Severity, diags[j].Severity)
454+
}
455+
if !diags[j].AttributePath.Equals(tc.ExpectedDiags[j].AttributePath) {
456+
t.Fatalf("%d: attribute paths do not match expected: %v, got %v", i, tc.ExpectedDiags[j].AttributePath, diags[j].AttributePath)
457+
}
458+
}
459+
}
460+
}
461+
293462
func TestProviderDiff_legacyTimeoutType(t *testing.T) {
294463
p := &Provider{
295464
ResourcesMap: map[string]*Resource{

0 commit comments

Comments
 (0)