blob: da8569c43404f44f4f3bb305ea76aa5c80a24acb [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 "strings"
19 "testing"
20
21 "cuelang.org/go/cue/build"
22)
23
24func toString(t *testing.T, v Value) string {
25 t.Helper()
26
27 b, err := v.MarshalJSON()
28 if err != nil {
29 t.Fatal(err)
30 }
31
32 return strings.Replace(string(b), `"`, "", -1)
33}
34
35func TestMerge(t *testing.T) {
36 insts := func(s ...string) []string { return s }
37 testCases := []struct {
38 desc string
39 instances []string
40 out string
41 isErr bool
42 }{{
43 desc: "single",
44 instances: insts(`a: 1, b: 2`),
45 out: `{a:1,b:2}`,
46 }, {
47 desc: "multiple",
48 instances: insts(
49 `a: 1`,
50 `b: 2`,
51 `a: int`,
52 ),
53 out: `{a:1,b:2}`,
54 }, {
55 desc: "templates",
56 instances: insts(`
57 obj <X>: { a: "A" }
58 obj alpha: { b: 2 }
59 `,
60 `
61 obj <X>: { a: "B" }
62 obj beta: { b: 3 }
63 `,
64 ),
65 out: `{obj:{alpha:{a:A,b:2},beta:{a:B,b:3}}}`,
66 }, {
67 // Structs that are shared in templates may have conflicting results.
68 // However, this is not an issue as long as these value are not
69 // referenced during evaluation. For generating JSON this is not an
70 // issue as such fields are typically hidden.
71 desc: "shared struct",
72 instances: insts(`
73 _shared: { a: "A" }
74 obj <X>: _shared & {}
75 obj alpha: { b: 2 }
76 `,
77 `
78 _shared: { a: "B" }
79 obj <X>: _shared & {}
80 obj beta: { b: 3 }
81 `,
82 ),
83 out: `{obj:{alpha:{a:A,b:2},beta:{a:B,b:3}}}`,
84 }, {
Marcel van Lohuizen6c58f252019-04-24 23:08:16 +020085 desc: "top-level comprehensions",
86 instances: insts(`
87 t: {"\(k)": 10 for k, x in s}
88 s <Name>: {}
89 s foo a: 1
90 `,
91 `
92 t: {"\(k)": 10 for k, x in s}
93 s <Name>: {}
94 s bar b: 2
95 `,
96 ),
97 out: `{t:{foo:10,bar:10},s:{foo:{a:1},bar:{b:2}}}`,
98 }, {
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +010099 desc: "error",
100 instances: insts(`a:`),
101 out: `{}`,
102 isErr: true,
103 }}
104
105 for _, tc := range testCases {
106 t.Run(tc.desc, func(t *testing.T) {
107 ctx := build.NewContext()
108 in := []*build.Instance{}
109 for _, str := range tc.instances {
110 bi := ctx.NewInstance("dir", nil) // no packages
111 bi.AddFile("file", str)
112 in = append(in, bi)
113 }
114 merged := Merge(Build(in)...)
115 if err := merged.Err; err != nil {
116 if !tc.isErr {
117 t.Fatal(err)
118 }
119 }
120
121 if got := toString(t, merged.Value()); got != tc.out {
122 t.Errorf("\n got: %s\nwant: %s", got, tc.out)
123 }
124 })
125 }
126}
127
128func TestInstance_Build(t *testing.T) {
129 testCases := []struct {
130 desc string
131 instance string
132 overlay string
133 out string
134 }{{
135 desc: "single",
136 instance: `a: {b: 1, c: 2}`,
137 overlay: `res: a`,
138 out: `{res:{b:1,c:2}}`,
139 }}
140
141 for _, tc := range testCases {
142 t.Run(tc.desc, func(t *testing.T) {
143 ctx := build.NewContext()
144
145 bi := ctx.NewInstance("main", nil) // no packages
146 bi.AddFile("file", tc.instance)
147 main := Build([]*build.Instance{bi})
148 if err := main[0].Err; err != nil {
149 t.Fatal(err)
150 }
151
152 bi = ctx.NewInstance("overlay", nil) // no packages
153 bi.AddFile("file", tc.overlay)
154
155 overlay := main[0].Build(bi)
156
157 if got := toString(t, overlay.Value()); got != tc.out {
158 t.Errorf("\n got: %s\nwant: %s", got, tc.out)
159 }
160 })
161 }
162}