github.com/iaas-resource-provision/iaas-rpc@v1.0.7-0.20211021023331-ed21f798c408/internal/lang/funcs/sensitive_test.go (about)

     1  package funcs
     2  
     3  import (
     4  	"fmt"
     5  	"testing"
     6  
     7  	"github.com/zclconf/go-cty/cty"
     8  )
     9  
    10  func TestSensitive(t *testing.T) {
    11  	tests := []struct {
    12  		Input   cty.Value
    13  		WantErr string
    14  	}{
    15  		{
    16  			cty.NumberIntVal(1),
    17  			``,
    18  		},
    19  		{
    20  			// Unknown values stay unknown while becoming sensitive
    21  			cty.UnknownVal(cty.String),
    22  			``,
    23  		},
    24  		{
    25  			// Null values stay unknown while becoming sensitive
    26  			cty.NullVal(cty.String),
    27  			``,
    28  		},
    29  		{
    30  			// DynamicVal can be marked as sensitive
    31  			cty.DynamicVal,
    32  			``,
    33  		},
    34  		{
    35  			// The marking is shallow only
    36  			cty.ListVal([]cty.Value{cty.NumberIntVal(1)}),
    37  			``,
    38  		},
    39  		{
    40  			// A value already marked is allowed and stays marked
    41  			cty.NumberIntVal(1).Mark("sensitive"),
    42  			``,
    43  		},
    44  		{
    45  			// A value with some non-standard mark gets "fixed" to be marked
    46  			// with the standard "sensitive" mark. (This situation occurring
    47  			// would imply an inconsistency/bug elsewhere, so we're just
    48  			// being robust about it here.)
    49  			cty.NumberIntVal(1).Mark("bloop"),
    50  			``,
    51  		},
    52  		{
    53  			// A value deep already marked is allowed and stays marked,
    54  			// _and_ we'll also mark the outer collection as sensitive.
    55  			cty.ListVal([]cty.Value{cty.NumberIntVal(1).Mark("sensitive")}),
    56  			``,
    57  		},
    58  	}
    59  
    60  	for _, test := range tests {
    61  		t.Run(fmt.Sprintf("sensitive(%#v)", test.Input), func(t *testing.T) {
    62  			got, err := Sensitive(test.Input)
    63  
    64  			if test.WantErr != "" {
    65  				if err == nil {
    66  					t.Fatal("succeeded; want error")
    67  				}
    68  				if got, want := err.Error(), test.WantErr; got != want {
    69  					t.Fatalf("wrong error\ngot:  %s\nwant: %s", got, want)
    70  				}
    71  				return
    72  			} else if err != nil {
    73  				t.Fatalf("unexpected error: %s", err)
    74  			}
    75  
    76  			if !got.HasMark("sensitive") {
    77  				t.Errorf("result is not marked sensitive")
    78  			}
    79  
    80  			gotRaw, gotMarks := got.Unmark()
    81  			if len(gotMarks) != 1 {
    82  				// We're only expecting to have the "sensitive" mark we checked
    83  				// above. Any others are an error, even if they happen to
    84  				// appear alongside "sensitive". (We might change this rule
    85  				// if someday we decide to use marks for some additional
    86  				// unrelated thing in Terraform, but currently we assume that
    87  				// _all_ marks imply sensitive, and so returning any other
    88  				// marks would be confusing.)
    89  				t.Errorf("extraneous marks %#v", gotMarks)
    90  			}
    91  
    92  			// Disregarding shallow marks, the result should have the same
    93  			// effective value as the input.
    94  			wantRaw, _ := test.Input.Unmark()
    95  			if !gotRaw.RawEquals(wantRaw) {
    96  				t.Errorf("wrong unmarked result\ngot:  %#v\nwant: %#v", got, wantRaw)
    97  			}
    98  		})
    99  	}
   100  }
   101  
   102  func TestNonsensitive(t *testing.T) {
   103  	tests := []struct {
   104  		Input   cty.Value
   105  		WantErr string
   106  	}{
   107  		{
   108  			cty.NumberIntVal(1).Mark("sensitive"),
   109  			``,
   110  		},
   111  		{
   112  			cty.DynamicVal.Mark("sensitive"),
   113  			``,
   114  		},
   115  		{
   116  			cty.UnknownVal(cty.String).Mark("sensitive"),
   117  			``,
   118  		},
   119  		{
   120  			cty.NullVal(cty.EmptyObject).Mark("sensitive"),
   121  			``,
   122  		},
   123  		{
   124  			// The inner sensitive remains afterwards
   125  			cty.ListVal([]cty.Value{cty.NumberIntVal(1).Mark("sensitive")}).Mark("sensitive"),
   126  			``,
   127  		},
   128  
   129  		// Passing a value that is already non-sensitive is an error,
   130  		// because this function should always be used with specific
   131  		// intention, not just as a "make everything visible" hammer.
   132  		{
   133  			cty.NumberIntVal(1),
   134  			`the given value is not sensitive, so this call is redundant`,
   135  		},
   136  		{
   137  			cty.NullVal(cty.String),
   138  			`the given value is not sensitive, so this call is redundant`,
   139  		},
   140  
   141  		// Unknown values may become sensitive once they are known, so we
   142  		// permit them to be marked nonsensitive.
   143  		{
   144  			cty.DynamicVal,
   145  			``,
   146  		},
   147  		{
   148  			cty.UnknownVal(cty.String),
   149  			``,
   150  		},
   151  	}
   152  
   153  	for _, test := range tests {
   154  		t.Run(fmt.Sprintf("nonsensitive(%#v)", test.Input), func(t *testing.T) {
   155  			got, err := Nonsensitive(test.Input)
   156  
   157  			if test.WantErr != "" {
   158  				if err == nil {
   159  					t.Fatal("succeeded; want error")
   160  				}
   161  				if got, want := err.Error(), test.WantErr; got != want {
   162  					t.Fatalf("wrong error\ngot:  %s\nwant: %s", got, want)
   163  				}
   164  				return
   165  			} else if err != nil {
   166  				t.Fatalf("unexpected error: %s", err)
   167  			}
   168  
   169  			if got.HasMark("sensitive") {
   170  				t.Errorf("result is still marked sensitive")
   171  			}
   172  			wantRaw, _ := test.Input.Unmark()
   173  			if !got.RawEquals(wantRaw) {
   174  				t.Errorf("wrong result\ngot:  %#v\nwant: %#v", got, test.Input)
   175  			}
   176  		})
   177  	}
   178  }