blob: d3846817fed9ed594914c263a763558084a6d88a [file] [log] [blame]
Marcel van Lohuizen0d12c332020-06-10 12:36:58 +02001// Copyright 2020 CUE Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
Marcel van Lohuizen311f5bc2020-07-07 15:58:16 +020015package export_test
Marcel van Lohuizen0d12c332020-06-10 12:36:58 +020016
17import (
18 "flag"
19 "testing"
20
Marcel van Lohuizen845df052020-07-26 13:15:45 +020021 "cuelang.org/go/cue"
Marcel van Lohuizen0d12c332020-06-10 12:36:58 +020022 "cuelang.org/go/cue/ast"
23 "cuelang.org/go/cue/errors"
24 "cuelang.org/go/cue/format"
Marcel van Lohuizen1e1fe6f2020-09-17 13:34:29 +020025 "cuelang.org/go/cue/parser"
Marcel van Lohuizenf0df4df2020-09-18 17:52:03 +020026 "cuelang.org/go/encoding/gocode/gocodec"
Marcel van Lohuizenb9b2c542020-09-16 21:24:03 +020027 "cuelang.org/go/internal"
28 "cuelang.org/go/internal/core/adt"
Marcel van Lohuizen0d12c332020-06-10 12:36:58 +020029 "cuelang.org/go/internal/core/compile"
Marcel van Lohuizenb9b2c542020-09-16 21:24:03 +020030 "cuelang.org/go/internal/core/convert"
Marcel van Lohuizen18736bf2020-07-15 17:02:42 +020031 "cuelang.org/go/internal/core/eval"
Marcel van Lohuizen311f5bc2020-07-07 15:58:16 +020032 "cuelang.org/go/internal/core/export"
Marcel van Lohuizen0d12c332020-06-10 12:36:58 +020033 "cuelang.org/go/internal/core/runtime"
34 "cuelang.org/go/internal/cuetxtar"
35 "github.com/rogpeppe/go-internal/txtar"
36)
37
38var update = flag.Bool("update", false, "update the test files")
39
40func TestDefinition(t *testing.T) {
41 test := cuetxtar.TxTarTest{
42 Root: "./testdata",
43 Name: "definition",
44 Update: *update,
45 }
46
Marcel van Lohuizen311f5bc2020-07-07 15:58:16 +020047 r := cue.NewRuntime()
Marcel van Lohuizen0d12c332020-06-10 12:36:58 +020048
49 test.Run(t, func(t *cuetxtar.Test) {
50 a := t.ValidInstances()
51
52 v, errs := compile.Files(nil, r, a[0].Files...)
53 if errs != nil {
54 t.Fatal(errs)
55 }
Marcel van Lohuizen18736bf2020-07-15 17:02:42 +020056 v.Finalize(eval.NewContext(r, v))
57
58 // TODO: do we need to evaluate v? In principle not necessary.
59 // v.Finalize(eval.NewContext(r, v))
Marcel van Lohuizen0d12c332020-06-10 12:36:58 +020060
Marcel van Lohuizen311f5bc2020-07-07 15:58:16 +020061 file, errs := export.Def(r, v)
Marcel van Lohuizen0d12c332020-06-10 12:36:58 +020062 errors.Print(t, errs, nil)
63 _, _ = t.Write(formatNode(t.T, file))
64 })
65}
66
67func formatNode(t *testing.T, n ast.Node) []byte {
68 t.Helper()
69
70 b, err := format.Node(n)
71 if err != nil {
72 t.Fatal(err)
73 }
74 return b
75}
76
Marcel van Lohuizenb9b2c542020-09-16 21:24:03 +020077// TestGenerated tests conversions of generated Go structs, which may be
78// different from parsed or evaluated CUE, such as having Vertex values.
79func TestGenerated(t *testing.T) {
80 testCases := []struct {
Marcel van Lohuizen1e1fe6f2020-09-17 13:34:29 +020081 in func(ctx *adt.OpContext) (adt.Expr, error)
82 out string
Marcel van Lohuizenb9b2c542020-09-16 21:24:03 +020083 }{{
Marcel van Lohuizen1e1fe6f2020-09-17 13:34:29 +020084 in: func(ctx *adt.OpContext) (adt.Expr, error) {
85 in := &C{
86 Terminals: []*A{{Name: "Name", Description: "Desc"}},
87 }
88 return convert.GoValueToValue(ctx, in, false), nil
Marcel van Lohuizenb9b2c542020-09-16 21:24:03 +020089 },
Marcel van Lohuizen1e1fe6f2020-09-17 13:34:29 +020090 out: `{Terminals: [{Description: "Desc", Name: "Name"}]}`,
Marcel van Lohuizenb9b2c542020-09-16 21:24:03 +020091 }, {
Marcel van Lohuizen1e1fe6f2020-09-17 13:34:29 +020092 in: func(ctx *adt.OpContext) (adt.Expr, error) {
93 in := &C{
94 Terminals: []*A{{Name: "Name", Description: "Desc"}},
95 }
96 return convert.GoTypeToExpr(ctx, in)
Marcel van Lohuizenb9b2c542020-09-16 21:24:03 +020097 },
Marcel van Lohuizen1e1fe6f2020-09-17 13:34:29 +020098 out: `*null|{Terminals?: *null|[...*null|{Name: string, Description: string}]}`,
99 }, {
100 in: func(ctx *adt.OpContext) (adt.Expr, error) {
101 in := []*A{{Name: "Name", Description: "Desc"}}
102 return convert.GoValueToValue(ctx, in, false), nil
103 },
104 out: `[{Name: "Name", Description: "Desc"}]`,
105 }, {
106 in: func(ctx *adt.OpContext) (adt.Expr, error) {
107 in := []*A{{Name: "Name", Description: "Desc"}}
108 return convert.GoTypeToExpr(ctx, in)
109 },
110 out: `*null|[...*null|{Name: string, Description: string}]`,
111 }, {
112 in: func(ctx *adt.OpContext) (adt.Expr, error) {
113 expr, err := parser.ParseExpr("test", `{
114 x: Guide.#Terminal
115 Guide: {}
116 }`)
117 if err != nil {
118 return nil, err
119 }
120 c, err := compile.Expr(nil, ctx, expr)
121 if err != nil {
122 return nil, err
123 }
124 root := &adt.Vertex{}
125 root.AddConjunct(c)
126 root.Finalize(ctx)
127
128 // Simulate Value.Unify of Lookup("x") and Lookup("Guide").
129 n := &adt.Vertex{}
130 n.AddConjunct(adt.MakeRootConjunct(nil, root.Arcs[0]))
131 n.AddConjunct(adt.MakeRootConjunct(nil, root.Arcs[1]))
132 n.Finalize(ctx)
133
134 return n, nil
135 },
136 out: `<[l2// x: undefined field #Terminal] _|_>`,
Marcel van Lohuizenb9b2c542020-09-16 21:24:03 +0200137 }}
138 for _, tc := range testCases {
139 t.Run("", func(t *testing.T) {
140 r := runtime.New()
141 e := eval.New(r)
142 ctx := adt.NewContext(r, e, &adt.Vertex{})
143
Marcel van Lohuizen1e1fe6f2020-09-17 13:34:29 +0200144 v, err := tc.in(ctx)
145 if err != nil {
146 t.Fatal("failed test case: ", err)
147 }
Marcel van Lohuizenb9b2c542020-09-16 21:24:03 +0200148 expr, err := export.Expr(ctx, v)
149 if err != nil {
Marcel van Lohuizen1e1fe6f2020-09-17 13:34:29 +0200150 t.Fatal("failed export: ", err)
Marcel van Lohuizenb9b2c542020-09-16 21:24:03 +0200151 }
152 got := internal.DebugStr(expr)
Marcel van Lohuizen1e1fe6f2020-09-17 13:34:29 +0200153 if got != tc.out {
154 t.Errorf("got: %s\nwant: %s", got, tc.out)
Marcel van Lohuizenb9b2c542020-09-16 21:24:03 +0200155 }
Marcel van Lohuizenb9b2c542020-09-16 21:24:03 +0200156 })
157 }
158}
159
160type A struct {
161 Name string
162 Description string
163}
164
165type B struct {
166 Image string
167}
168
169type C struct {
170 Terminals []*A
171}
172
Marcel van Lohuizen0d12c332020-06-10 12:36:58 +0200173// For debugging purposes. Do not delete.
174func TestX(t *testing.T) {
175 t.Skip()
176
177 in := `
178-- in.cue --
179package test
180
Marcel van Lohuizen18736bf2020-07-15 17:02:42 +0200181// // Foo
182// a: [X=string]: [Y=string]: {
183// name: X+Y
184// }
Marcel van Lohuizen0d12c332020-06-10 12:36:58 +0200185
Marcel van Lohuizen18736bf2020-07-15 17:02:42 +0200186// [Y=string]: [X=string]: name: {Y+X}
187// {
188// name: X.other + Y
189// other: string
190// }
191
192// c: [X=string]: X
193
194// #pkg1: Object
195
196// "Hello \(#pkg1)!"
197
198
199// Object: "World"
200
201// // A Foo fooses stuff.
202// foos are instances of Foo.
203// foos: [string]: {}
204
205// // // My first little foo.
206// foos: MyFoo: {}
207
208bar: 3
209d2: C="foo\(bar)": {
210 name: "xx"
211 foo: C.name
212}
213
Marcel van Lohuizen0d12c332020-06-10 12:36:58 +0200214 `
215
216 archive := txtar.Parse([]byte(in))
217 a := cuetxtar.Load(archive, "/tmp/test")
Marcel van Lohuizen18736bf2020-07-15 17:02:42 +0200218 if err := a[0].Err; err != nil {
219 t.Fatal(err)
220 }
221
222 // x := a[0].Files[0]
223 // astutil.Sanitize(x)
Marcel van Lohuizen0d12c332020-06-10 12:36:58 +0200224
225 r := runtime.New()
226 v, errs := compile.Files(nil, r, a[0].Files...)
227 if errs != nil {
228 t.Fatal(errs)
229 }
Marcel van Lohuizen18736bf2020-07-15 17:02:42 +0200230 v.Finalize(eval.NewContext(r, v))
Marcel van Lohuizen0d12c332020-06-10 12:36:58 +0200231
Marcel van Lohuizen311f5bc2020-07-07 15:58:16 +0200232 file, errs := export.Def(r, v)
Marcel van Lohuizen0d12c332020-06-10 12:36:58 +0200233 if errs != nil {
234 t.Fatal(errs)
235 }
236
237 t.Error(string(formatNode(t, file)))
238}
Marcel van Lohuizenf0df4df2020-09-18 17:52:03 +0200239
240func TestFromGo(t *testing.T) {
241 type Struct struct {
242 A string
243 B string
244 }
245
246 m := make(map[string]Struct)
247 m["hello"] = Struct{
248 A: "a",
249 B: "b",
250 }
251 var r cue.Runtime
252 codec := gocodec.New(&r, nil)
253 v, err := codec.Decode(m)
254 if err != nil {
255 panic(err)
256 }
257
258 syn, _ := format.Node(v.Syntax())
259 if got := string(syn); got != `{
260 hello: {
261 A: "a"
262 B: "b"
263 }
264}` {
265 t.Errorf("incorrect ordering: %s\n", got)
266 }
267}