github.com/graywolf-at-work-2/terraform-vendor@v1.4.5/internal/lang/funcs/conversion_test.go (about) 1 package funcs 2 3 import ( 4 "fmt" 5 "testing" 6 7 "github.com/hashicorp/terraform/internal/lang/marks" 8 "github.com/zclconf/go-cty/cty" 9 ) 10 11 func TestTo(t *testing.T) { 12 tests := []struct { 13 Value cty.Value 14 TargetTy cty.Type 15 Want cty.Value 16 Err string 17 }{ 18 { 19 cty.StringVal("a"), 20 cty.String, 21 cty.StringVal("a"), 22 ``, 23 }, 24 { 25 cty.UnknownVal(cty.String), 26 cty.String, 27 cty.UnknownVal(cty.String), 28 ``, 29 }, 30 { 31 cty.NullVal(cty.String), 32 cty.String, 33 cty.NullVal(cty.String), 34 ``, 35 }, 36 { 37 // This test case represents evaluating the expression tostring(null) 38 // from HCL, since null in HCL is cty.NullVal(cty.DynamicPseudoType). 39 // The result in that case should still be null, but a null specifically 40 // of type string. 41 cty.NullVal(cty.DynamicPseudoType), 42 cty.String, 43 cty.NullVal(cty.String), 44 ``, 45 }, 46 { 47 cty.StringVal("a").Mark("boop"), 48 cty.String, 49 cty.StringVal("a").Mark("boop"), 50 ``, 51 }, 52 { 53 cty.NullVal(cty.String).Mark("boop"), 54 cty.String, 55 cty.NullVal(cty.String).Mark("boop"), 56 ``, 57 }, 58 { 59 cty.True, 60 cty.String, 61 cty.StringVal("true"), 62 ``, 63 }, 64 { 65 cty.StringVal("a"), 66 cty.Bool, 67 cty.DynamicVal, 68 `cannot convert "a" to bool; only the strings "true" or "false" are allowed`, 69 }, 70 { 71 cty.StringVal("a").Mark("boop"), 72 cty.Bool, 73 cty.DynamicVal, 74 `cannot convert "a" to bool; only the strings "true" or "false" are allowed`, 75 }, 76 { 77 cty.StringVal("a").Mark(marks.Sensitive), 78 cty.Bool, 79 cty.DynamicVal, 80 `cannot convert this sensitive string to bool`, 81 }, 82 { 83 cty.StringVal("a"), 84 cty.Number, 85 cty.DynamicVal, 86 `cannot convert "a" to number; given string must be a decimal representation of a number`, 87 }, 88 { 89 cty.StringVal("a").Mark("boop"), 90 cty.Number, 91 cty.DynamicVal, 92 `cannot convert "a" to number; given string must be a decimal representation of a number`, 93 }, 94 { 95 cty.StringVal("a").Mark(marks.Sensitive), 96 cty.Number, 97 cty.DynamicVal, 98 `cannot convert this sensitive string to number`, 99 }, 100 { 101 cty.NullVal(cty.String), 102 cty.Number, 103 cty.NullVal(cty.Number), 104 ``, 105 }, 106 { 107 cty.UnknownVal(cty.Bool), 108 cty.String, 109 cty.UnknownVal(cty.String), 110 ``, 111 }, 112 { 113 cty.UnknownVal(cty.String), 114 cty.Bool, 115 cty.UnknownVal(cty.Bool), // conversion is optimistic 116 ``, 117 }, 118 { 119 cty.TupleVal([]cty.Value{cty.StringVal("hello"), cty.True}), 120 cty.List(cty.String), 121 cty.ListVal([]cty.Value{cty.StringVal("hello"), cty.StringVal("true")}), 122 ``, 123 }, 124 { 125 cty.TupleVal([]cty.Value{cty.StringVal("hello"), cty.True}), 126 cty.Set(cty.String), 127 cty.SetVal([]cty.Value{cty.StringVal("hello"), cty.StringVal("true")}), 128 ``, 129 }, 130 { 131 cty.ObjectVal(map[string]cty.Value{"foo": cty.StringVal("hello"), "bar": cty.True}), 132 cty.Map(cty.String), 133 cty.MapVal(map[string]cty.Value{"foo": cty.StringVal("hello"), "bar": cty.StringVal("true")}), 134 ``, 135 }, 136 { 137 cty.ObjectVal(map[string]cty.Value{"foo": cty.StringVal("hello"), "bar": cty.StringVal("world").Mark("boop")}), 138 cty.Map(cty.String), 139 cty.MapVal(map[string]cty.Value{"foo": cty.StringVal("hello"), "bar": cty.StringVal("world").Mark("boop")}), 140 ``, 141 }, 142 { 143 cty.ObjectVal(map[string]cty.Value{"foo": cty.StringVal("hello"), "bar": cty.StringVal("world")}).Mark("boop"), 144 cty.Map(cty.String), 145 cty.MapVal(map[string]cty.Value{"foo": cty.StringVal("hello"), "bar": cty.StringVal("world")}).Mark("boop"), 146 ``, 147 }, 148 { 149 cty.TupleVal([]cty.Value{cty.StringVal("hello"), cty.StringVal("world").Mark("boop")}), 150 cty.List(cty.String), 151 cty.ListVal([]cty.Value{cty.StringVal("hello"), cty.StringVal("world").Mark("boop")}), 152 ``, 153 }, 154 { 155 cty.TupleVal([]cty.Value{cty.StringVal("hello"), cty.StringVal("world")}).Mark("boop"), 156 cty.List(cty.String), 157 cty.ListVal([]cty.Value{cty.StringVal("hello"), cty.StringVal("world")}).Mark("boop"), 158 ``, 159 }, 160 { 161 cty.EmptyTupleVal, 162 cty.String, 163 cty.DynamicVal, 164 `cannot convert tuple to string`, 165 }, 166 { 167 cty.UnknownVal(cty.EmptyTuple), 168 cty.String, 169 cty.DynamicVal, 170 `cannot convert tuple to string`, 171 }, 172 { 173 cty.EmptyObjectVal, 174 cty.Object(map[string]cty.Type{"foo": cty.String}), 175 cty.DynamicVal, 176 `incompatible object type for conversion: attribute "foo" is required`, 177 }, 178 } 179 180 for _, test := range tests { 181 t.Run(fmt.Sprintf("to %s(%#v)", test.TargetTy.FriendlyNameForConstraint(), test.Value), func(t *testing.T) { 182 f := MakeToFunc(test.TargetTy) 183 got, err := f.Call([]cty.Value{test.Value}) 184 185 if test.Err != "" { 186 if err == nil { 187 t.Fatal("succeeded; want error") 188 } 189 if got, want := err.Error(), test.Err; got != want { 190 t.Fatalf("wrong error\ngot: %s\nwant: %s", got, want) 191 } 192 return 193 } else if err != nil { 194 t.Fatalf("unexpected error: %s", err) 195 } 196 197 if !got.RawEquals(test.Want) { 198 t.Errorf("wrong result\ngot: %#v\nwant: %#v", got, test.Want) 199 } 200 }) 201 } 202 }