blob: e5d4f3040a79d7d70741ebf1e3fdb922d6064241 [file] [log] [blame]
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +01001// Copyright 2018 The 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
15package cue
16
17import (
18 "fmt"
19 "strings"
20 "testing"
21
22 "cuelang.org/go/cue/ast"
23 "cuelang.org/go/cue/build"
24 "cuelang.org/go/cue/token"
25)
26
27func TestFromExpr(t *testing.T) {
28 testCases := []struct {
29 expr ast.Expr
30 out string
31 }{{
32 expr: &ast.BasicLit{Kind: token.STRING, Value: `"Hello"`},
33 out: `"Hello"`,
34 }, {
35 expr: &ast.ListLit{Elts: []ast.Expr{
36 &ast.BasicLit{Kind: token.STRING, Value: `"Hello"`},
37 &ast.BasicLit{Kind: token.STRING, Value: `"World"`},
38 }},
39 out: `["Hello","World"]`,
40 }}
41 for _, tc := range testCases {
42 t.Run("", func(t *testing.T) {
43 inst, err := FromExpr(nil, tc.expr)
44 if err != nil {
45 t.Fatal(err)
46 }
47 ctx := inst.newContext()
48 if got := debugStr(ctx, inst.eval(ctx)); got != tc.out {
49 t.Errorf("\n got: %v; want %v", got, tc.out)
50 }
51 })
52 }
53}
54
55func TestBuild(t *testing.T) {
56 files := func(s ...string) []string { return s }
57 insts := func(i ...*bimport) []*bimport { return i }
58 pkg1 := &bimport{
59 "pkg1",
60 files(`
61 package pkg1
62
63 Object: "World"
64 `),
65 }
66 pkg2 := &bimport{
67 "example.com/foo/pkg2",
68 files(`
69 package pkg
70
71 Number: 12
72 `),
73 }
74 insts(pkg1, pkg2)
75
76 testCases := []struct {
77 instances []*bimport
78 emit string
79 }{{
80 insts(&bimport{"", files(`test: "ok"`)}),
81 `<0>{test: "ok"}`,
82 // }, {
83 // insts(pkg1, &bimport{"",
84 // files(
85 // `package test
86
87 // import "math"
88
89 // "Pi: \(math.Pi)!"`)}),
90 // `"Pi: 3.14159265358979323846264338327950288419716939937510582097494459!"`,
91 }, {
92 insts(pkg1, &bimport{"",
93 files(
94 `package test
95
96 import "pkg1"
97
98 "Hello \(pkg1.Object)!"`),
99 }),
100 `"Hello World!"`,
101 }, {
102 insts(pkg1, &bimport{"",
103 files(
104 `package test
105
106 import "pkg1"
107 pkg1: 1
108
109 "Hello \(pkg1.Object)!"`),
110 }),
111 `pkg1 redeclared as imported package name
112 previous declaration at file0.cue:4:5`,
113 }, {
114 insts(pkg1, &bimport{"",
115 files(
116 `package test
117
118 import bar "pkg1"
119
120 pkg1 Object: 3
121 "Hello \(pkg1.Object)!"`),
122 }),
123 `imported and not used: "pkg1" as bar`,
124 }, {
125 insts(pkg2, &bimport{"",
126 files(
127 `package test
128
129 import "example.com/foo/pkg2"
130
131 "Hello \(pkg2.Number)!"`),
132 }),
133 `imported and not used: "example.com/foo/pkg2"`,
134 // `file0.cue:5:14: unresolved reference pkg2`,
135 }, {
136 insts(pkg2, &bimport{"",
137 files(
138 `package test
139
140 import "example.com/foo/pkg2"
141
142 "Hello \(pkg.Number)!"`),
143 }),
144 `"Hello 12!"`,
145 }}
146 for _, tc := range testCases {
147 t.Run("", func(t *testing.T) {
148 insts := Build(makeInstances(tc.instances))
149 var got string
150 if err := insts[0].Err; err != nil {
151 got = err.Error()
152 } else {
153 got = strings.TrimSpace(fmt.Sprintf("%s\n", insts[0].Value()))
154 }
155 if got != tc.emit {
156 t.Errorf("\n got: %s\nwant: %s", got, tc.emit)
157 }
158 })
159 }
160}
161
162type builder struct {
163 ctxt *build.Context
164 imports map[string]*bimport
165}
166
167func (b *builder) load(path string) *build.Instance {
168 p := b.ctxt.NewInstance(path, b.load)
169 bi := b.imports[path]
170 if bi == nil {
171 return nil
172 }
173 buildInstance(b.imports[path], p)
174 return p
175}
176
177type bimport struct {
178 path string // "" means top-level
179 files []string
180}
181
182func makeInstances(insts []*bimport) (instances []*build.Instance) {
183 b := builder{
184 ctxt: build.NewContext(),
185 imports: map[string]*bimport{},
186 }
187 for _, bi := range insts {
188 if bi.path != "" {
189 b.imports[bi.path] = bi
190 }
191 }
192 for _, bi := range insts {
193 if bi.path == "" {
194 p := b.ctxt.NewInstance("dir", b.load)
195 buildInstance(bi, p)
196 instances = append(instances, p)
197 }
198 }
199 return
200}
201
202func buildInstance(bi *bimport, p *build.Instance) {
203 for i, f := range bi.files {
204 p.AddFile(fmt.Sprintf("file%d.cue", i), f)
205 }
206 p.Complete()
207}