1// Copyright 2019 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	"github.com/google/go-cmp/cmp"
23)
24
25func TestMarshalling(t *testing.T) {
26	testCases := []struct {
27		filename string
28		input    string
29		pkg      string
30	}{{
31		filename: "foo.cue",
32		pkg:      "foo",
33		input: `package foo
34
35		A: int
36		B: string
37		`,
38	}, {
39		filename: "bar.cue",
40		pkg:      "bar",
41		input: `package bar
42
43		"Hello world!"
44		`,
45	}, {
46		filename: "qux.cue",
47		input: `
48			"Hello world!"
49		`,
50	}, {
51		filename: "baz.cue",
52		pkg:      "baz",
53		input: `package baz
54
55		import "strings"
56
57		a: strings.TrimSpace("  Hello world!  ")
58		`}}
59	for _, tc := range testCases {
60		t.Run(tc.filename, func(t *testing.T) {
61			r := &Runtime{}
62			inst, err := r.Compile(tc.filename, tc.input)
63			if err != nil {
64				t.Fatal(err)
65			}
66			inst.ImportPath = "test/pkg"
67			want := fmt.Sprint(inst.Value())
68
69			b, err := r.Marshal(inst)
70			if err != nil {
71				t.Fatal(err)
72			}
73
74			r2 := &Runtime{}
75			instances, err := r2.Unmarshal(b)
76			if err != nil {
77				t.Fatal(err)
78			}
79			inst = instances[0]
80
81			if inst.ImportPath != "test/pkg" {
82				t.Error("import path was not restored")
83			}
84			got := fmt.Sprint(inst.Value())
85
86			if got != want {
87				t.Errorf("\ngot:  %q;\nwant: %q", got, want)
88			}
89		})
90	}
91}
92
93func TestMarshalMultiPackage(t *testing.T) {
94	files := func(s ...string) (a []fileData) {
95		for i, s := range s {
96			a = append(a, fileData{fmt.Sprintf("file%d.cue", i), []byte(s)})
97		}
98		return a
99	}
100	insts := func(i ...*instanceData) []*instanceData { return i }
101	pkg1 := &instanceData{
102		true,
103		"example.com/foo/pkg1",
104		files(`
105		package pkg1
106
107		Object: "World"
108		`),
109	}
110	pkg2 := &instanceData{
111		true,
112		"example.com/foo/pkg2",
113		files(`
114		package pkg
115
116		Number: 12
117		`),
118	}
119
120	testCases := []struct {
121		instances []*instanceData
122		emit      string
123	}{{
124		insts(&instanceData{true, "", files(`test: "ok"`)}),
125		`{test: "ok"}`,
126	}, {
127		insts(&instanceData{true, "",
128			files(
129				`package test
130
131		import math2 "math"
132
133		"Pi: \(math2.Pi)!"`)}),
134		`"Pi: 3.14159265358979323846264338327950288419716939937510582097494459!"`,
135	}, {
136		insts(pkg1, &instanceData{true, "",
137			files(
138				`package test
139
140			import "example.com/foo/pkg1"
141
142			"Hello \(pkg1.Object)!"`),
143		}),
144		`"Hello World!"`,
145	}, {
146		insts(pkg1, &instanceData{true, "",
147			files(
148				`package test
149
150		import pkg2 "example.com/foo/pkg1"
151		"Hello \(pkg1)!"
152
153		pkg1: pkg2.Object`),
154		}),
155		`"Hello World!"`,
156	}, {
157		insts(pkg2, &instanceData{true, "",
158			files(
159				`package test
160
161		import "example.com/foo/pkg2"
162
163		"Hello \(pkg.Number)!"`),
164		}),
165		`"Hello 12!"`,
166	}}
167
168	strValue := func(a []*Instance) (ret []string) {
169		for _, i := range a {
170			ret = append(ret, strings.TrimSpace((fmt.Sprint(i.Value()))))
171		}
172		return ret
173	}
174
175	for _, tc := range testCases {
176		t.Run("", func(t *testing.T) {
177			r := &Runtime{}
178
179			insts, err := compileInstances(r, tc.instances)
180			if err != nil {
181				t.Fatal(err)
182			}
183			want := strValue(insts)
184
185			b, err := r.Marshal(insts...)
186			if err != nil {
187				t.Fatal(err)
188			}
189
190			r2 := &Runtime{}
191			insts, err = r2.Unmarshal(b)
192			if err != nil {
193				t.Fatal(err)
194			}
195			got := strValue(insts)
196
197			if !cmp.Equal(got, want) {
198				t.Error(cmp.Diff(got, want))
199			}
200		})
201	}
202}
203