1package stdlib
2
3import (
4	"fmt"
5	"testing"
6
7	"github.com/zclconf/go-cty/cty"
8)
9
10func TestTo(t *testing.T) {
11	tests := []struct {
12		Value    cty.Value
13		TargetTy cty.Type
14		Want     cty.Value
15		Err      string
16	}{
17		{
18			cty.StringVal("a"),
19			cty.String,
20			cty.StringVal("a"),
21			``,
22		},
23		{
24			cty.UnknownVal(cty.String),
25			cty.String,
26			cty.UnknownVal(cty.String),
27			``,
28		},
29		{
30			cty.NullVal(cty.String),
31			cty.String,
32			cty.NullVal(cty.String),
33			``,
34		},
35		{
36			cty.True,
37			cty.String,
38			cty.StringVal("true"),
39			``,
40		},
41		{
42			cty.StringVal("a"),
43			cty.Bool,
44			cty.DynamicVal,
45			`cannot convert "a" to bool; only the strings "true" or "false" are allowed`,
46		},
47		{
48			cty.StringVal("a"),
49			cty.Number,
50			cty.DynamicVal,
51			`cannot convert "a" to number; given string must be a decimal representation of a number`,
52		},
53		{
54			cty.NullVal(cty.String),
55			cty.Number,
56			cty.NullVal(cty.Number),
57			``,
58		},
59		{
60			cty.UnknownVal(cty.Bool),
61			cty.String,
62			cty.UnknownVal(cty.String),
63			``,
64		},
65		{
66			cty.UnknownVal(cty.String),
67			cty.Bool,
68			cty.UnknownVal(cty.Bool), // conversion is optimistic
69			``,
70		},
71		{
72			cty.TupleVal([]cty.Value{cty.StringVal("hello"), cty.True}),
73			cty.List(cty.String),
74			cty.ListVal([]cty.Value{cty.StringVal("hello"), cty.StringVal("true")}),
75			``,
76		},
77		{
78			cty.TupleVal([]cty.Value{cty.StringVal("hello"), cty.True}),
79			cty.Set(cty.String),
80			cty.SetVal([]cty.Value{cty.StringVal("hello"), cty.StringVal("true")}),
81			``,
82		},
83		{
84			cty.ObjectVal(map[string]cty.Value{"foo": cty.StringVal("hello"), "bar": cty.True}),
85			cty.Map(cty.String),
86			cty.MapVal(map[string]cty.Value{"foo": cty.StringVal("hello"), "bar": cty.StringVal("true")}),
87			``,
88		},
89		{
90			cty.EmptyTupleVal,
91			cty.String,
92			cty.DynamicVal,
93			`cannot convert tuple to string`,
94		},
95		{
96			cty.UnknownVal(cty.EmptyTuple),
97			cty.String,
98			cty.DynamicVal,
99			`cannot convert tuple to string`,
100		},
101		{
102			cty.EmptyObjectVal,
103			cty.Object(map[string]cty.Type{"foo": cty.String}),
104			cty.DynamicVal,
105			`incompatible object type for conversion: attribute "foo" is required`,
106		},
107	}
108
109	for _, test := range tests {
110		t.Run(fmt.Sprintf("to %s(%#v)", test.TargetTy.FriendlyNameForConstraint(), test.Value), func(t *testing.T) {
111			f := MakeToFunc(test.TargetTy)
112			got, err := f.Call([]cty.Value{test.Value})
113
114			if test.Err != "" {
115				if err == nil {
116					t.Fatal("succeeded; want error")
117				}
118				if got, want := err.Error(), test.Err; got != want {
119					t.Fatalf("wrong error\ngot:  %s\nwant: %s", got, want)
120				}
121				return
122			} else if err != nil {
123				t.Fatalf("unexpected error: %s", err)
124			}
125
126			if !got.RawEquals(test.Want) {
127				t.Errorf("wrong result\ngot:  %#v\nwant: %#v", got, test.Want)
128			}
129		})
130	}
131}
132