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  }