github.com/graywolf-at-work-2/terraform-vendor@v1.4.5/internal/command/jsonformat/computed/renderers/testing.go (about) 1 package renderers 2 3 import ( 4 "sort" 5 "testing" 6 7 "github.com/google/go-cmp/cmp" 8 9 "github.com/hashicorp/terraform/internal/command/jsonformat/computed" 10 "github.com/hashicorp/terraform/internal/plans" 11 ) 12 13 type ValidateDiffFunction func(t *testing.T, diff computed.Diff) 14 15 func validateDiff(t *testing.T, diff computed.Diff, expectedAction plans.Action, expectedReplace bool) { 16 if diff.Replace != expectedReplace || diff.Action != expectedAction { 17 t.Errorf("\nreplace:\n\texpected:%t\n\tactual:%t\naction:\n\texpected:%s\n\tactual:%s", expectedReplace, diff.Replace, expectedAction, diff.Action) 18 } 19 } 20 21 func ValidatePrimitive(before, after interface{}, action plans.Action, replace bool) ValidateDiffFunction { 22 return func(t *testing.T, diff computed.Diff) { 23 validateDiff(t, diff, action, replace) 24 25 primitive, ok := diff.Renderer.(*primitiveRenderer) 26 if !ok { 27 t.Errorf("invalid renderer type: %T", diff.Renderer) 28 return 29 } 30 31 beforeDiff := cmp.Diff(primitive.before, before) 32 afterDiff := cmp.Diff(primitive.after, after) 33 34 if len(beforeDiff) > 0 || len(afterDiff) > 0 { 35 t.Errorf("before diff: (%s), after diff: (%s)", beforeDiff, afterDiff) 36 } 37 } 38 } 39 40 func ValidateObject(attributes map[string]ValidateDiffFunction, action plans.Action, replace bool) ValidateDiffFunction { 41 return func(t *testing.T, diff computed.Diff) { 42 validateDiff(t, diff, action, replace) 43 44 object, ok := diff.Renderer.(*objectRenderer) 45 if !ok { 46 t.Errorf("invalid renderer type: %T", diff.Renderer) 47 return 48 } 49 50 if !object.overrideNullSuffix { 51 t.Errorf("created the wrong type of object renderer") 52 } 53 54 validateMapType(t, object.attributes, attributes) 55 } 56 } 57 58 func ValidateNestedObject(attributes map[string]ValidateDiffFunction, action plans.Action, replace bool) ValidateDiffFunction { 59 return func(t *testing.T, diff computed.Diff) { 60 validateDiff(t, diff, action, replace) 61 62 object, ok := diff.Renderer.(*objectRenderer) 63 if !ok { 64 t.Errorf("invalid renderer type: %T", diff.Renderer) 65 return 66 } 67 68 if object.overrideNullSuffix { 69 t.Errorf("created the wrong type of object renderer") 70 } 71 72 validateMapType(t, object.attributes, attributes) 73 } 74 } 75 76 func ValidateMap(elements map[string]ValidateDiffFunction, action plans.Action, replace bool) ValidateDiffFunction { 77 return func(t *testing.T, diff computed.Diff) { 78 validateDiff(t, diff, action, replace) 79 80 m, ok := diff.Renderer.(*mapRenderer) 81 if !ok { 82 t.Errorf("invalid renderer type: %T", diff.Renderer) 83 return 84 } 85 86 validateMapType(t, m.elements, elements) 87 } 88 } 89 90 func validateMapType(t *testing.T, actual map[string]computed.Diff, expected map[string]ValidateDiffFunction) { 91 validateKeys(t, actual, expected) 92 93 for key, expected := range expected { 94 if actual, ok := actual[key]; ok { 95 expected(t, actual) 96 } 97 } 98 } 99 100 func validateKeys[C, V any](t *testing.T, actual map[string]C, expected map[string]V) { 101 if len(actual) != len(expected) { 102 103 var actualAttributes []string 104 var expectedAttributes []string 105 106 for key := range actual { 107 actualAttributes = append(actualAttributes, key) 108 } 109 for key := range expected { 110 expectedAttributes = append(expectedAttributes, key) 111 } 112 113 sort.Strings(actualAttributes) 114 sort.Strings(expectedAttributes) 115 116 if diff := cmp.Diff(actualAttributes, expectedAttributes); len(diff) > 0 { 117 t.Errorf("actual and expected attributes did not match: %s", diff) 118 } 119 } 120 } 121 122 func ValidateList(elements []ValidateDiffFunction, action plans.Action, replace bool) ValidateDiffFunction { 123 return func(t *testing.T, diff computed.Diff) { 124 validateDiff(t, diff, action, replace) 125 126 list, ok := diff.Renderer.(*listRenderer) 127 if !ok { 128 t.Errorf("invalid renderer type: %T", diff.Renderer) 129 return 130 } 131 132 if !list.displayContext { 133 t.Errorf("created the wrong type of list renderer") 134 } 135 136 validateSliceType(t, list.elements, elements) 137 } 138 } 139 140 func ValidateNestedList(elements []ValidateDiffFunction, action plans.Action, replace bool) ValidateDiffFunction { 141 return func(t *testing.T, diff computed.Diff) { 142 validateDiff(t, diff, action, replace) 143 144 list, ok := diff.Renderer.(*listRenderer) 145 if !ok { 146 t.Errorf("invalid renderer type: %T", diff.Renderer) 147 return 148 } 149 150 if list.displayContext { 151 t.Errorf("created the wrong type of list renderer") 152 } 153 154 validateSliceType(t, list.elements, elements) 155 } 156 } 157 158 func ValidateSet(elements []ValidateDiffFunction, action plans.Action, replace bool) ValidateDiffFunction { 159 return func(t *testing.T, diff computed.Diff) { 160 validateDiff(t, diff, action, replace) 161 162 set, ok := diff.Renderer.(*setRenderer) 163 if !ok { 164 t.Errorf("invalid renderer type: %T", diff.Renderer) 165 return 166 } 167 168 validateSliceType(t, set.elements, elements) 169 } 170 } 171 172 func validateSliceType(t *testing.T, actual []computed.Diff, expected []ValidateDiffFunction) { 173 if len(actual) != len(expected) { 174 t.Errorf("expected %d elements but found %d elements", len(expected), len(actual)) 175 return 176 } 177 178 for ix := 0; ix < len(expected); ix++ { 179 expected[ix](t, actual[ix]) 180 } 181 } 182 183 func ValidateBlock( 184 attributes map[string]ValidateDiffFunction, 185 singleBlocks map[string]ValidateDiffFunction, 186 listBlocks map[string][]ValidateDiffFunction, 187 mapBlocks map[string]map[string]ValidateDiffFunction, 188 setBlocks map[string][]ValidateDiffFunction, 189 action plans.Action, 190 replace bool) ValidateDiffFunction { 191 return func(t *testing.T, diff computed.Diff) { 192 validateDiff(t, diff, action, replace) 193 194 block, ok := diff.Renderer.(*blockRenderer) 195 if !ok { 196 t.Errorf("invalid renderer type: %T", diff.Renderer) 197 return 198 } 199 200 validateKeys(t, block.attributes, attributes) 201 validateKeys(t, block.blocks.SingleBlocks, singleBlocks) 202 validateKeys(t, block.blocks.ListBlocks, listBlocks) 203 validateKeys(t, block.blocks.MapBlocks, mapBlocks) 204 validateKeys(t, block.blocks.SetBlocks, setBlocks) 205 206 for key, expected := range attributes { 207 if actual, ok := block.attributes[key]; ok { 208 expected(t, actual) 209 } 210 } 211 212 for key, expected := range singleBlocks { 213 expected(t, block.blocks.SingleBlocks[key]) 214 } 215 216 for key, expected := range listBlocks { 217 if actual, ok := block.blocks.ListBlocks[key]; ok { 218 if len(actual) != len(expected) { 219 t.Errorf("expected %d blocks within %s but found %d elements", len(expected), key, len(actual)) 220 } 221 for ix := range expected { 222 expected[ix](t, actual[ix]) 223 } 224 } 225 } 226 227 for key, expected := range setBlocks { 228 if actual, ok := block.blocks.SetBlocks[key]; ok { 229 if len(actual) != len(expected) { 230 t.Errorf("expected %d blocks within %s but found %d elements", len(expected), key, len(actual)) 231 } 232 for ix := range expected { 233 expected[ix](t, actual[ix]) 234 } 235 } 236 } 237 238 for key, expected := range setBlocks { 239 if actual, ok := block.blocks.SetBlocks[key]; ok { 240 if len(actual) != len(expected) { 241 t.Errorf("expected %d blocks within %s but found %d elements", len(expected), key, len(actual)) 242 } 243 for ix := range expected { 244 expected[ix](t, actual[ix]) 245 } 246 } 247 } 248 249 for key, expected := range mapBlocks { 250 if actual, ok := block.blocks.MapBlocks[key]; ok { 251 if len(actual) != len(expected) { 252 t.Errorf("expected %d blocks within %s but found %d elements", len(expected), key, len(actual)) 253 } 254 for dKey := range expected { 255 expected[dKey](t, actual[dKey]) 256 } 257 } 258 } 259 } 260 } 261 262 func ValidateTypeChange(before, after ValidateDiffFunction, action plans.Action, replace bool) ValidateDiffFunction { 263 return func(t *testing.T, diff computed.Diff) { 264 validateDiff(t, diff, action, replace) 265 266 typeChange, ok := diff.Renderer.(*typeChangeRenderer) 267 if !ok { 268 t.Errorf("invalid renderer type: %T", diff.Renderer) 269 return 270 } 271 272 before(t, typeChange.before) 273 after(t, typeChange.after) 274 } 275 } 276 277 func ValidateSensitive(inner ValidateDiffFunction, beforeSensitive, afterSensitive bool, action plans.Action, replace bool) ValidateDiffFunction { 278 return func(t *testing.T, diff computed.Diff) { 279 validateDiff(t, diff, action, replace) 280 281 sensitive, ok := diff.Renderer.(*sensitiveRenderer) 282 if !ok { 283 t.Errorf("invalid renderer type: %T", diff.Renderer) 284 return 285 } 286 287 if beforeSensitive != sensitive.beforeSensitive || afterSensitive != sensitive.afterSensitive { 288 t.Errorf("before or after sensitive values don't match:\n\texpected; before: %t after: %t\n\tactual; before: %t, after: %t", beforeSensitive, afterSensitive, sensitive.beforeSensitive, sensitive.afterSensitive) 289 } 290 291 inner(t, sensitive.inner) 292 } 293 } 294 295 func ValidateUnknown(before ValidateDiffFunction, action plans.Action, replace bool) ValidateDiffFunction { 296 return func(t *testing.T, diff computed.Diff) { 297 validateDiff(t, diff, action, replace) 298 299 unknown, ok := diff.Renderer.(*unknownRenderer) 300 if !ok { 301 t.Errorf("invalid renderer type: %T", diff.Renderer) 302 return 303 } 304 305 if before == nil { 306 if unknown.before.Renderer != nil { 307 t.Errorf("did not expect a before renderer, but found one") 308 } 309 return 310 } 311 312 if unknown.before.Renderer == nil { 313 t.Errorf("expected a before renderer, but found none") 314 } 315 316 before(t, unknown.before) 317 } 318 }