1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package cue_test
16
17 import (
18 "fmt"
19 "testing"
20
21 "cuelang.org/go/cue"
22 "cuelang.org/go/cue/ast"
23 "cuelang.org/go/cue/build"
24 "cuelang.org/go/cue/cuecontext"
25 "cuelang.org/go/cue/token"
26 "cuelang.org/go/internal/core/debug"
27 "cuelang.org/go/internal/value"
28 )
29
30 func TestFromExpr(t *testing.T) {
31 testCases := []struct {
32 expr ast.Expr
33 out string
34 }{{
35 expr: ast.NewString("Hello"),
36 out: `"Hello"`,
37 }, {
38 expr: ast.NewList(
39 ast.NewString("Hello"),
40 ast.NewString("World"),
41 ),
42 out: `["Hello", "World"]`,
43 }}
44 for _, tc := range testCases {
45 t.Run("", func(t *testing.T) {
46 r := cuecontext.New()
47 v := r.BuildExpr(tc.expr)
48 if err := v.Err(); err != nil {
49 t.Fatal(err)
50 }
51 if got := fmt.Sprint(v); got != tc.out {
52 t.Errorf("\n got: %v; want %v", got, tc.out)
53 }
54 })
55 }
56 }
57
58 func TestBuild(t *testing.T) {
59 files := func(s ...string) []string { return s }
60 insts := func(i ...*bimport) []*bimport { return i }
61 pkg1 := &bimport{
62 "pkg1",
63 files(`
64 package pkg1
65
66 Object: "World"
67 `),
68 }
69 pkg2 := &bimport{
70 "mod.test/foo/pkg2:pkg",
71 files(`
72 package pkg
73
74 Number: 12
75 `),
76 }
77 pkg3 := &bimport{
78 "mod.test/foo/v1:pkg3",
79 files(`
80 package pkg3
81
82 List: [1,2,3]
83 `),
84 }
85
86 testCases := []struct {
87 instances []*bimport
88 emit string
89 }{{
90 insts(&bimport{"", files(`test: "ok"`)}),
91 `{test:"ok"}`,
92 }, {
93 insts(&bimport{"",
94 files(
95 `package test
96
97 import "math"
98
99 "Pi: \(math.Pi)!"`)}),
100 `"Pi: 3.14159265358979323846264338327950288419716939937510582097494459!"`,
101 }, {
102 insts(&bimport{"",
103 files(
104 `package test
105
106 import math2 "math"
107
108 "Pi: \(math2.Pi)!"`)}),
109 `"Pi: 3.14159265358979323846264338327950288419716939937510582097494459!"`,
110 }, {
111 insts(pkg1, &bimport{"",
112 files(
113 `package test
114
115 import "pkg1"
116
117 "Hello \(pkg1.Object)!"`),
118 }),
119 `"Hello World!"`,
120 }, {
121 insts(pkg1, &bimport{"",
122 files(
123 `package test
124
125 import "pkg1"
126
127 "Hello \(pkg1.Object)!"`),
128 }),
129 `"Hello World!"`,
130 }, {
131 insts(pkg1, &bimport{"",
132 files(
133 `package test
134
135 import pkg2 "pkg1"
136 #pkg1: pkg2.Object
137
138 "Hello \(#pkg1)!"`),
139 }),
140 `"Hello World!"`,
141 }, {
142 insts(pkg1, pkg2, &bimport{"",
143 files(
144 `package test
145
146 import bar "pkg1"
147 import baz "mod.test/foo/pkg2:pkg"
148
149 pkg1: Object: 3
150 "Hello \(pkg1.Object)!"`),
151 }),
152 `imported and not used: "pkg1" as bar (and 1 more errors)`,
153 }, {
154 insts(pkg2, &bimport{"",
155 files(
156 `package test
157
158 import "mod.test/foo/pkg2:pkg"
159
160 "Hello \(pkg2.Number)!"`),
161 }),
162 `imported and not used: "mod.test/foo/pkg2:pkg" (and 1 more errors)`,
163
164 }, {
165 insts(pkg2, &bimport{"",
166 files(
167 `package test
168
169 import "mod.test/foo/pkg2:pkg"
170
171 "Hello \(pkg.Number)!"`),
172 }),
173 `"Hello 12!"`,
174 }, {
175 insts(pkg3, &bimport{"",
176 files(
177 `package test
178
179 import "mod.test/foo/v1:pkg3"
180
181 "Hello \(pkg3.List[1])!"`),
182 }),
183 `"Hello 2!"`,
184 }, {
185 insts(pkg3, &bimport{"",
186 files(
187 `package test
188
189 import "mod.test/foo/v1:pkg3"
190
191 pkg3: 3
192
193 "Hello \(pkg3.List[1])!"`),
194 }),
195 `pkg3 redeclared as imported package name
196 previous declaration at file0.cue:5:5`,
197 }}
198 for _, tc := range testCases {
199 t.Run("", func(t *testing.T) {
200 insts := cue.Build(makeInstances(tc.instances))
201 var got string
202 if err := insts[0].Err; err != nil {
203 got = err.Error()
204 } else {
205 cfg := &debug.Config{Compact: true}
206 r, v := value.ToInternal(insts[0].Value())
207 got = debug.NodeString(r, v, cfg)
208 }
209 if got != tc.emit {
210 t.Errorf("\n got: %s\nwant: %s", got, tc.emit)
211 }
212 })
213 }
214 }
215
216 type builder struct {
217 ctxt *build.Context
218 imports map[string]*bimport
219 }
220
221 func (b *builder) load(pos token.Pos, path string) *build.Instance {
222 bi := b.imports[path]
223 if bi == nil {
224 return nil
225 }
226 return b.build(bi)
227 }
228
229 type bimport struct {
230 path string
231 files []string
232 }
233
234 func makeInstances(insts []*bimport) (instances []*build.Instance) {
235 b := builder{
236 ctxt: build.NewContext(),
237 imports: map[string]*bimport{},
238 }
239 for _, bi := range insts {
240 if bi.path != "" {
241 b.imports[bi.path] = bi
242 }
243 }
244 for _, bi := range insts {
245 if bi.path == "" {
246 instances = append(instances, b.build(bi))
247 }
248 }
249 return
250 }
251
252 func (b *builder) build(bi *bimport) *build.Instance {
253 path := bi.path
254 if path == "" {
255 path = "dir"
256 }
257 p := b.ctxt.NewInstance(path, b.load)
258 for i, f := range bi.files {
259 _ = p.AddFile(fmt.Sprintf("file%d.cue", i), f)
260 }
261 _ = p.Complete()
262 return p
263 }
264
View as plain text