1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package convert_test
16
17
18
19 import (
20 "encoding"
21 "math/big"
22 "reflect"
23 "testing"
24 "time"
25
26 "github.com/cockroachdb/apd/v3"
27 "github.com/google/go-cmp/cmp"
28
29 "cuelang.org/go/cue/errors"
30 "cuelang.org/go/internal/core/adt"
31 "cuelang.org/go/internal/core/convert"
32 "cuelang.org/go/internal/core/debug"
33 "cuelang.org/go/internal/core/runtime"
34 )
35
36 func mkBigInt(a int64) (v apd.Decimal) { v.SetInt64(a); return }
37
38 type textMarshaller struct {
39 b string
40 }
41
42 func (t *textMarshaller) MarshalText() (b []byte, err error) {
43 return []byte(t.b), nil
44 }
45
46 var _ encoding.TextMarshaler = &textMarshaller{}
47
48 func TestConvert(t *testing.T) {
49 type key struct {
50 a int
51 }
52 type stringType string
53 i34 := big.NewInt(34)
54 d35 := mkBigInt(35)
55 n36 := mkBigInt(-36)
56 f37 := big.NewFloat(37.0000)
57 testCases := []struct {
58 goVal interface{}
59 want string
60 }{{
61 nil, "(_){ _ }",
62 }, {
63 true, "(bool){ true }",
64 }, {
65 false, "(bool){ false }",
66 }, {
67 errors.New("oh noes"), "(_|_){\n // [eval] oh noes\n}",
68 }, {
69 "foo", `(string){ "foo" }`,
70 }, {
71 "\x80", `(string){ "�" }`,
72 }, {
73 3, "(int){ 3 }",
74 }, {
75 uint(3), "(int){ 3 }",
76 }, {
77 uint8(3), "(int){ 3 }",
78 }, {
79 uint16(3), "(int){ 3 }",
80 }, {
81 uint32(3), "(int){ 3 }",
82 }, {
83 uint64(3), "(int){ 3 }",
84 }, {
85 int8(-3), "(int){ -3 }",
86 }, {
87 int16(-3), "(int){ -3 }",
88 }, {
89 int32(-3), "(int){ -3 }",
90 }, {
91 int64(-3), "(int){ -3 }",
92 }, {
93 float64(3), "(float){ 3 }",
94 }, {
95 float64(3.1), "(float){ 3.1 }",
96 }, {
97 float32(3.1), "(float){ 3.1 }",
98 }, {
99 uintptr(3), "(int){ 3 }",
100 }, {
101 &i34, "(int){ 34 }",
102 }, {
103 &f37, "(float){ 37 }",
104 }, {
105 &d35, "(int){ 35 }",
106 }, {
107 &n36, "(int){ -36 }",
108 }, {
109 []int{1, 2, 3, 4}, `(#list){
110 0: (int){ 1 }
111 1: (int){ 2 }
112 2: (int){ 3 }
113 3: (int){ 4 }
114 }`,
115 }, {
116 struct {
117 A int
118 B *int
119 }{3, nil},
120 "(struct){\n A: (int){ 3 }\n}",
121 }, {
122 []interface{}{}, "(#list){\n}",
123 }, {
124 []interface{}{nil}, "(#list){\n 0: (_){ _ }\n}",
125 }, {
126 map[string]interface{}{"a": 1, "x": nil}, `(struct){
127 a: (int){ 1 }
128 x: (_){ _ }
129 }`,
130 }, {
131 map[string][]int{
132 "a": {1},
133 "b": {3, 4},
134 }, `(struct){
135 a: (#list){
136 0: (int){ 1 }
137 }
138 b: (#list){
139 0: (int){ 3 }
140 1: (int){ 4 }
141 }
142 }`,
143 }, {
144 map[bool]int{}, "(_|_){\n // [eval] unsupported Go type for map key (bool)\n}",
145 }, {
146 map[struct{}]int{{}: 2}, "(_|_){\n // [eval] unsupported Go type for map key (struct {})\n}",
147 }, {
148 map[int]int{1: 2}, `(struct){
149 "1": (int){ 2 }
150 }`,
151 }, {
152 struct {
153 a int
154 b int
155 }{3, 4},
156 "(struct){\n}",
157 }, {
158 struct {
159 A int
160 B int `json:"-"`
161 C int `json:",omitempty"`
162 }{3, 4, 0},
163 `(struct){
164 A: (int){ 3 }
165 }`,
166 }, {
167 struct {
168 A int
169 B int
170 }{3, 4},
171 `(struct){
172 A: (int){ 3 }
173 B: (int){ 4 }
174 }`,
175 }, {
176 struct {
177 A int `json:"a"`
178 B int `yaml:"b"`
179 }{3, 4},
180 `(struct){
181 a: (int){ 3 }
182 b: (int){ 4 }
183 }`,
184 }, {
185 struct {
186 A int `json:"" yaml:"" protobuf:"aa"`
187 B int `yaml:"cc" json:"bb" protobuf:"aa"`
188 }{3, 4},
189 `(struct){
190 aa: (int){ 3 }
191 bb: (int){ 4 }
192 }`,
193 }, {
194 &struct{ A int }{3}, `(struct){
195 A: (int){ 3 }
196 }`,
197 }, {
198 (*struct{ A int })(nil), "(_){ _ }",
199 }, {
200 reflect.ValueOf(3), "(int){ 3 }",
201 }, {
202 time.Date(2019, 4, 1, 0, 0, 0, 0, time.UTC), `(string){ "2019-04-01T00:00:00Z" }`,
203 }, {
204 func() interface{} {
205 type T struct {
206 B int
207 }
208 type S struct {
209 A string
210 T
211 }
212 return S{}
213 }(),
214 `(struct){
215 A: (string){ "" }
216 B: (int){ 0 }
217 }`,
218 },
219 {map[key]string{{a: 1}: "foo"},
220 "(_|_){\n // [eval] unsupported Go type for map key (convert_test.key)\n}"},
221 {map[*textMarshaller]string{{b: "bar"}: "foo"},
222 "(struct){\n \"&{bar}\": (string){ \"foo\" }\n}"},
223 {map[int]string{1: "foo"},
224 "(struct){\n \"1\": (string){ \"foo\" }\n}"},
225 {map[string]encoding.TextMarshaler{"foo": nil},
226 "(struct){\n foo: (_){ _ }\n}"},
227 {make(chan int),
228 "(_|_){\n // [eval] unsupported Go type (chan int)\n}"},
229 {[]interface{}{func() {}},
230 "(_|_){\n // [eval] unsupported Go type (func())\n}"},
231 {stringType("\x80"), `(string){ "�" }`},
232 }
233 r := runtime.New()
234 for _, tc := range testCases {
235 ctx := adt.NewContext(r, &adt.Vertex{})
236 t.Run("", func(t *testing.T) {
237 v := convert.GoValueToValue(ctx, tc.goVal, true)
238 n, ok := v.(*adt.Vertex)
239 if !ok {
240 n = &adt.Vertex{BaseValue: v}
241 }
242 got := debug.NodeString(ctx, n, nil)
243 if got != tc.want {
244 t.Error(cmp.Diff(got, tc.want))
245 }
246 })
247 }
248 }
249
250 func TestX(t *testing.T) {
251 t.Skip()
252
253 x := []string{}
254
255 r := runtime.New()
256 ctx := adt.NewContext(r, &adt.Vertex{})
257
258 v := convert.GoValueToValue(ctx, x, false)
259
260
261
262 got := debug.NodeString(ctx, v, nil)
263 t.Error(got)
264 }
265
266 func TestConvertType(t *testing.T) {
267 testCases := []struct {
268 goTyp interface{}
269 want string
270 }{{
271 struct {
272 A int `cue:">=0&<100"`
273 B *big.Int `cue:">=0"`
274 C *big.Int
275 D big.Int
276 F *big.Float
277 }{},
278
279 `{
280 A: (((int & >=-9223372036854775808) & <=9223372036854775807) & (>=0 & <100))
281 B: (int & >=0)
282 C?: int
283 D: int
284 F?: number
285 }`,
286 }, {
287 &struct {
288 A int16 `cue:">=0&<100"`
289 B error `json:"b,"`
290 C string
291 D bool
292 F float64
293 L []byte
294 T time.Time
295 G func()
296 }{},
297 `(*null|{
298 A: (((int & >=-32768) & <=32767) & (>=0 & <100))
299 b: null
300 C: string
301 D: bool
302 F: number
303 L?: (*null|bytes)
304 T: _
305 })`,
306 }, {
307 struct {
308 A int `cue:"<"`
309 }{},
310 "_|_(invalid tag \"<\" for field \"A\": expected operand, found 'EOF' (and 1 more errors))",
311 }, {
312 struct {
313 A int `json:"-"`
314 D *apd.Decimal
315 P ***apd.Decimal
316 I interface{ Foo() }
317 T string `cue:""`
318 h int
319 }{},
320 `{
321 D?: number
322 P?: (*null|number)
323 I?: _
324 T: (string & _)
325 }`,
326 }, {
327 struct {
328 A int8 `cue:"C-B"`
329 B int8 `cue:"C-A,opt"`
330 C int8 `cue:"A+B"`
331 }{},
332
333 `{
334 A: (((int & >=-128) & <=127) & (〈0;C〉 - 〈0;B〉))
335 B?: (((int & >=-128) & <=127) & (〈0;C〉 - 〈0;A〉))
336 C: (((int & >=-128) & <=127) & (〈0;A〉 + 〈0;B〉))
337 }`,
338 }, {
339 []string{},
340 `(*null|[
341 ...string,
342 ])`,
343 }, {
344 [4]string{},
345 `(4 * [
346 string,
347 ])`,
348 }, {
349 []func(){},
350 "_|_(unsupported Go type (func()))",
351 }, {
352 map[string]struct{ A map[string]uint }{},
353 `(*null|{
354 [string]: {
355 A?: (*null|{
356 [string]: ((int & >=0) & <=18446744073709551615)
357 })
358 }
359 })`,
360 }, {
361 map[float32]int{},
362 `_|_(unsupported Go type for map key (float32))`,
363 }, {
364 map[int]map[float32]int{},
365 `_|_(unsupported Go type for map key (float32))`,
366 }, {
367 map[int]func(){},
368 `_|_(unsupported Go type (func()))`,
369 }, {
370 time.Now,
371 "_|_(unsupported Go type (func() time.Time))",
372 }, {
373 struct {
374 Foobar string `cue:"\"foo,bar\",opt"`
375 }{},
376 `{
377 Foobar?: (string & "foo,bar")
378 }`,
379 }, {
380 struct {
381 Foobar string `cue:"\"foo,opt,bar\""`
382 }{},
383 `{
384 Foobar: (string & "foo,opt,bar")
385 }`,
386 }}
387
388 r := runtime.New()
389
390 for _, tc := range testCases {
391 t.Run("", func(t *testing.T) {
392 ctx := adt.NewContext(r, &adt.Vertex{})
393 v, _ := convert.GoTypeToExpr(ctx, tc.goTyp)
394 got := debug.NodeString(ctx, v, nil)
395 if got != tc.want {
396 t.Errorf("\n got %q;\nwant %q", got, tc.want)
397 }
398 })
399 }
400 }
401
View as plain text