github.com/terramate-io/tf@v0.0.0-20230830114523-fce866b4dfcd/command/jsonchecks/checks_test.go (about)

     1  // Copyright (c) HashiCorp, Inc.
     2  // SPDX-License-Identifier: MPL-2.0
     3  
     4  package jsonchecks
     5  
     6  import (
     7  	"encoding/json"
     8  	"testing"
     9  
    10  	"github.com/google/go-cmp/cmp"
    11  	"github.com/terramate-io/tf/addrs"
    12  	"github.com/terramate-io/tf/checks"
    13  	"github.com/terramate-io/tf/states"
    14  )
    15  
    16  func TestMarshalCheckStates(t *testing.T) {
    17  	resourceAAddr := addrs.ConfigCheckable(addrs.Resource{
    18  		Mode: addrs.ManagedResourceMode,
    19  		Type: "test",
    20  		Name: "a",
    21  	}.InModule(addrs.RootModule))
    22  	resourceAInstAddr := addrs.Checkable(addrs.Resource{
    23  		Mode: addrs.ManagedResourceMode,
    24  		Type: "test",
    25  		Name: "a",
    26  	}.Instance(addrs.StringKey("foo")).Absolute(addrs.RootModuleInstance))
    27  	moduleChildAddr := addrs.RootModuleInstance.Child("child", addrs.IntKey(0))
    28  	resourceBAddr := addrs.ConfigCheckable(addrs.Resource{
    29  		Mode: addrs.ManagedResourceMode,
    30  		Type: "test",
    31  		Name: "b",
    32  	}.InModule(moduleChildAddr.Module()))
    33  	resourceBInstAddr := addrs.Checkable(addrs.Resource{
    34  		Mode: addrs.ManagedResourceMode,
    35  		Type: "test",
    36  		Name: "b",
    37  	}.Instance(addrs.NoKey).Absolute(moduleChildAddr))
    38  	outputAAddr := addrs.ConfigCheckable(addrs.OutputValue{Name: "a"}.InModule(addrs.RootModule))
    39  	outputAInstAddr := addrs.Checkable(addrs.OutputValue{Name: "a"}.Absolute(addrs.RootModuleInstance))
    40  	outputBAddr := addrs.ConfigCheckable(addrs.OutputValue{Name: "b"}.InModule(moduleChildAddr.Module()))
    41  	outputBInstAddr := addrs.Checkable(addrs.OutputValue{Name: "b"}.Absolute(moduleChildAddr))
    42  	checkBlockAAddr := addrs.ConfigCheckable(addrs.Check{Name: "a"}.InModule(addrs.RootModule))
    43  	checkBlockAInstAddr := addrs.Checkable(addrs.Check{Name: "a"}.Absolute(addrs.RootModuleInstance))
    44  
    45  	tests := map[string]struct {
    46  		Input *states.CheckResults
    47  		Want  any
    48  	}{
    49  		"empty": {
    50  			&states.CheckResults{},
    51  			[]any{},
    52  		},
    53  		"failures": {
    54  			&states.CheckResults{
    55  				ConfigResults: addrs.MakeMap(
    56  					addrs.MakeMapElem(resourceAAddr, &states.CheckResultAggregate{
    57  						Status: checks.StatusFail,
    58  						ObjectResults: addrs.MakeMap(
    59  							addrs.MakeMapElem(resourceAInstAddr, &states.CheckResultObject{
    60  								Status: checks.StatusFail,
    61  								FailureMessages: []string{
    62  									"Not enough boops.",
    63  									"Too many beeps.",
    64  								},
    65  							}),
    66  						),
    67  					}),
    68  					addrs.MakeMapElem(resourceBAddr, &states.CheckResultAggregate{
    69  						Status: checks.StatusFail,
    70  						ObjectResults: addrs.MakeMap(
    71  							addrs.MakeMapElem(resourceBInstAddr, &states.CheckResultObject{
    72  								Status: checks.StatusFail,
    73  								FailureMessages: []string{
    74  									"Splines are too pointy.",
    75  								},
    76  							}),
    77  						),
    78  					}),
    79  					addrs.MakeMapElem(outputAAddr, &states.CheckResultAggregate{
    80  						Status: checks.StatusFail,
    81  						ObjectResults: addrs.MakeMap(
    82  							addrs.MakeMapElem(outputAInstAddr, &states.CheckResultObject{
    83  								Status: checks.StatusFail,
    84  							}),
    85  						),
    86  					}),
    87  					addrs.MakeMapElem(outputBAddr, &states.CheckResultAggregate{
    88  						Status: checks.StatusFail,
    89  						ObjectResults: addrs.MakeMap(
    90  							addrs.MakeMapElem(outputBInstAddr, &states.CheckResultObject{
    91  								Status: checks.StatusFail,
    92  								FailureMessages: []string{
    93  									"Not object-oriented enough.",
    94  								},
    95  							}),
    96  						),
    97  					}),
    98  					addrs.MakeMapElem(checkBlockAAddr, &states.CheckResultAggregate{
    99  						Status: checks.StatusFail,
   100  						ObjectResults: addrs.MakeMap(
   101  							addrs.MakeMapElem(checkBlockAInstAddr, &states.CheckResultObject{
   102  								Status: checks.StatusFail,
   103  								FailureMessages: []string{
   104  									"Couldn't reverse the polarity.",
   105  								},
   106  							}),
   107  						),
   108  					}),
   109  				),
   110  			},
   111  			[]any{
   112  				map[string]any{
   113  					"address": map[string]any{
   114  						"kind":       "check",
   115  						"to_display": "check.a",
   116  						"name":       "a",
   117  					},
   118  					"instances": []any{
   119  						map[string]any{
   120  							"address": map[string]any{
   121  								"to_display": `check.a`,
   122  							},
   123  							"problems": []any{
   124  								map[string]any{
   125  									"message": "Couldn't reverse the polarity.",
   126  								},
   127  							},
   128  							"status": "fail",
   129  						},
   130  					},
   131  					"status": "fail",
   132  				},
   133  				map[string]any{
   134  					"address": map[string]any{
   135  						"kind":       "output_value",
   136  						"module":     "module.child",
   137  						"name":       "b",
   138  						"to_display": "module.child.output.b",
   139  					},
   140  					"instances": []any{
   141  						map[string]any{
   142  							"address": map[string]any{
   143  								"module":     "module.child[0]",
   144  								"to_display": "module.child[0].output.b",
   145  							},
   146  							"problems": []any{
   147  								map[string]any{
   148  									"message": "Not object-oriented enough.",
   149  								},
   150  							},
   151  							"status": "fail",
   152  						},
   153  					},
   154  					"status": "fail",
   155  				},
   156  				map[string]any{
   157  					"address": map[string]any{
   158  						"kind":       "resource",
   159  						"mode":       "managed",
   160  						"module":     "module.child",
   161  						"name":       "b",
   162  						"to_display": "module.child.test.b",
   163  						"type":       "test",
   164  					},
   165  					"instances": []any{
   166  						map[string]any{
   167  							"address": map[string]any{
   168  								"module":     "module.child[0]",
   169  								"to_display": "module.child[0].test.b",
   170  							},
   171  							"problems": []any{
   172  								map[string]any{
   173  									"message": "Splines are too pointy.",
   174  								},
   175  							},
   176  							"status": "fail",
   177  						},
   178  					},
   179  					"status": "fail",
   180  				},
   181  				map[string]any{
   182  					"address": map[string]any{
   183  						"kind":       "output_value",
   184  						"name":       "a",
   185  						"to_display": "output.a",
   186  					},
   187  					"instances": []any{
   188  						map[string]any{
   189  							"address": map[string]any{
   190  								"to_display": "output.a",
   191  							},
   192  							"status": "fail",
   193  						},
   194  					},
   195  					"status": "fail",
   196  				},
   197  				map[string]any{
   198  					"address": map[string]any{
   199  						"kind":       "resource",
   200  						"mode":       "managed",
   201  						"name":       "a",
   202  						"to_display": "test.a",
   203  						"type":       "test",
   204  					},
   205  					"instances": []any{
   206  						map[string]any{
   207  							"address": map[string]any{
   208  								"to_display":   `test.a["foo"]`,
   209  								"instance_key": "foo",
   210  							},
   211  							"problems": []any{
   212  								map[string]any{
   213  									"message": "Not enough boops.",
   214  								},
   215  								map[string]any{
   216  									"message": "Too many beeps.",
   217  								},
   218  							},
   219  							"status": "fail",
   220  						},
   221  					},
   222  					"status": "fail",
   223  				},
   224  			},
   225  		},
   226  	}
   227  
   228  	for name, test := range tests {
   229  		t.Run(name, func(t *testing.T) {
   230  			gotBytes := MarshalCheckStates(test.Input)
   231  
   232  			var got any
   233  			err := json.Unmarshal(gotBytes, &got)
   234  			if err != nil {
   235  				t.Fatal(err)
   236  			}
   237  
   238  			if diff := cmp.Diff(test.Want, got); diff != "" {
   239  				t.Errorf("wrong result\n%s", diff)
   240  			}
   241  		})
   242  	}
   243  }