github.com/terramate-io/tf@v0.0.0-20230830114523-fce866b4dfcd/configs/configschema/path_test.go (about) 1 // Copyright (c) HashiCorp, Inc. 2 // SPDX-License-Identifier: MPL-2.0 3 4 package configschema 5 6 import ( 7 "testing" 8 9 "github.com/zclconf/go-cty/cty" 10 ) 11 12 func TestAttributeByPath(t *testing.T) { 13 schema := &Block{ 14 Attributes: map[string]*Attribute{ 15 "a1": {Description: "a1"}, 16 "a2": {Description: "a2"}, 17 "a3": { 18 Description: "a3", 19 NestedType: &Object{ 20 Nesting: NestingList, 21 Attributes: map[string]*Attribute{ 22 "nt1": {Description: "nt1"}, 23 "nt2": { 24 Description: "nt2", 25 NestedType: &Object{ 26 Nesting: NestingSingle, 27 Attributes: map[string]*Attribute{ 28 "deeply_nested": {Description: "deeply_nested"}, 29 }, 30 }, 31 }, 32 }, 33 }, 34 }, 35 }, 36 BlockTypes: map[string]*NestedBlock{ 37 "b1": { 38 Nesting: NestingList, 39 Block: Block{ 40 Attributes: map[string]*Attribute{ 41 "a3": {Description: "a3"}, 42 "a4": {Description: "a4"}, 43 }, 44 BlockTypes: map[string]*NestedBlock{ 45 "b2": { 46 Nesting: NestingMap, 47 Block: Block{ 48 Attributes: map[string]*Attribute{ 49 "a5": {Description: "a5"}, 50 "a6": {Description: "a6"}, 51 }, 52 }, 53 }, 54 }, 55 }, 56 }, 57 "b3": { 58 Nesting: NestingMap, 59 Block: Block{ 60 Attributes: map[string]*Attribute{ 61 "a7": {Description: "a7"}, 62 "a8": {Description: "a8"}, 63 }, 64 BlockTypes: map[string]*NestedBlock{ 65 "b4": { 66 Nesting: NestingSet, 67 Block: Block{ 68 Attributes: map[string]*Attribute{ 69 "a9": {Description: "a9"}, 70 "a10": {Description: "a10"}, 71 }, 72 }, 73 }, 74 }, 75 }, 76 }, 77 }, 78 } 79 80 for _, tc := range []struct { 81 path cty.Path 82 attrDescription string 83 exists bool 84 }{ 85 { 86 cty.GetAttrPath("a2"), 87 "a2", 88 true, 89 }, 90 { 91 cty.GetAttrPath("a3").IndexInt(1).GetAttr("nt2"), 92 "nt2", 93 true, 94 }, 95 { 96 cty.GetAttrPath("a3").IndexInt(1).GetAttr("b2").IndexString("foo").GetAttr("no"), 97 "missing", 98 false, 99 }, 100 { 101 cty.GetAttrPath("b1"), 102 "block", 103 false, 104 }, 105 { 106 cty.GetAttrPath("b1").IndexInt(1).GetAttr("a3"), 107 "a3", 108 true, 109 }, 110 { 111 cty.GetAttrPath("b1").IndexInt(1).GetAttr("b2").IndexString("foo").GetAttr("a7"), 112 "missing", 113 false, 114 }, 115 { 116 cty.GetAttrPath("b1").IndexInt(1).GetAttr("b2").IndexString("foo").GetAttr("a6"), 117 "a6", 118 true, 119 }, 120 { 121 cty.GetAttrPath("b3").IndexString("foo").GetAttr("b2").IndexString("foo").GetAttr("a7"), 122 "missing_block", 123 false, 124 }, 125 { 126 cty.GetAttrPath("b3").IndexString("foo").GetAttr("a7"), 127 "a7", 128 true, 129 }, 130 { 131 // Index steps don't apply to the schema, so the set Index value doesn't matter. 132 cty.GetAttrPath("b3").IndexString("foo").GetAttr("b4").Index(cty.EmptyObjectVal).GetAttr("a9"), 133 "a9", 134 true, 135 }, 136 } { 137 t.Run(tc.attrDescription, func(t *testing.T) { 138 attr := schema.AttributeByPath(tc.path) 139 if !tc.exists && attr == nil { 140 return 141 } 142 143 if attr == nil { 144 t.Fatalf("missing attribute from path %#v\n", tc.path) 145 } 146 147 if attr.Description != tc.attrDescription { 148 t.Fatalf("expected Attribute for %q, got %#v\n", tc.attrDescription, attr) 149 } 150 }) 151 } 152 } 153 154 func TestObject_AttributeByPath(t *testing.T) { 155 obj := &Object{ 156 Nesting: NestingList, 157 Attributes: map[string]*Attribute{ 158 "a1": {Description: "a1"}, 159 "a2": { 160 Description: "a2", 161 NestedType: &Object{ 162 Nesting: NestingSingle, 163 Attributes: map[string]*Attribute{ 164 "n1": {Description: "n1"}, 165 "n2": { 166 Description: "n2", 167 NestedType: &Object{ 168 Attributes: map[string]*Attribute{ 169 "dn1": {Description: "dn1"}, 170 }, 171 }, 172 }, 173 }, 174 }, 175 }, 176 }, 177 } 178 179 tests := []struct { 180 path cty.Path 181 attrDescription string 182 exists bool 183 }{ 184 { 185 cty.GetAttrPath("a2"), 186 "a2", 187 true, 188 }, 189 { 190 cty.GetAttrPath("a3"), 191 "missing", 192 false, 193 }, 194 { 195 cty.GetAttrPath("a2").IndexString("foo").GetAttr("n1"), 196 "n1", 197 true, 198 }, 199 { 200 cty.GetAttrPath("a2").IndexString("foo").GetAttr("n2").IndexInt(11).GetAttr("dn1"), 201 "dn1", 202 true, 203 }, 204 { 205 cty.GetAttrPath("a2").IndexString("foo").GetAttr("n2").IndexInt(11).GetAttr("dn1").IndexString("hello").GetAttr("nope"), 206 "missing_nested", 207 false, 208 }, 209 } 210 211 for _, tc := range tests { 212 t.Run(tc.attrDescription, func(t *testing.T) { 213 attr := obj.AttributeByPath(tc.path) 214 if !tc.exists && attr == nil { 215 return 216 } 217 218 if !tc.exists && attr != nil { 219 t.Fatalf("found Attribute, expected nil from path %#v\n", tc.path) 220 } 221 222 if attr == nil { 223 t.Fatalf("missing attribute from path %#v\n", tc.path) 224 } 225 226 if attr.Description != tc.attrDescription { 227 t.Fatalf("expected Attribute for %q, got %#v\n", tc.attrDescription, attr) 228 } 229 }) 230 } 231 232 }