blob: bb5004a67b654862cef5e4d371985fe50b1485f7 [file] [log] [blame]
Marcel van Lohuizenbc4d65d2018-12-10 15:40:02 +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 load
16
17import (
18 "io"
19 "strings"
20 "testing"
21)
22
23const quote = "`"
24
25type readTest struct {
26 // Test input contains ℙ where readImports should stop.
27 in string
28 err string
29}
30
31var readImportsTests = []readTest{
32 {
33 `package p`,
34 "",
35 },
36 {
37 `package p; import "x"`,
38 "",
39 },
40 {
41 `package p; import . "x"`,
42 "",
43 },
44 {
45 `package p; import "x";ℙvar x = 1`,
46 "",
47 },
48 {
49 `package p
50
51 // comment
52
53 import "x"
54 import _ "x"
55 import a "x"
56
57 /* comment */
58
59 import (
60 "x" /* comment */
61 _ "x"
62 a "x" // comment
63 ` + quote + `x` + quote + `
64 _ /*comment*/ ` + quote + `x` + quote + `
65 a ` + quote + `x` + quote + `
66 )
67 import (
68 )
69 import ()
70 import()import()import()
71 import();import();import()
72
73 ℙvar x = 1
74 `,
75 "",
76 },
77}
78
79var readCommentsTests = []readTest{
80 {
81 `ℙpackage p`,
82 "",
83 },
84 {
85 `ℙpackage p; import "x"`,
86 "",
87 },
88 {
89 `ℙpackage p; import . "x"`,
90 "",
91 },
92 {
93 `// foo
94
95 /* bar */
96
97 /* quux */ // baz
98
99 /*/ zot */
100
101 // asdf
102 ℙHello, world`,
103 "",
104 },
105}
106
107func testRead(t *testing.T, tests []readTest, read func(io.Reader) ([]byte, error)) {
108 for i, tt := range tests {
109 var in, testOut string
110 j := strings.Index(tt.in, "ℙ")
111 if j < 0 {
112 in = tt.in
113 testOut = tt.in
114 } else {
115 in = tt.in[:j] + tt.in[j+len("ℙ"):]
116 testOut = tt.in[:j]
117 }
118 r := strings.NewReader(in)
119 buf, err := read(r)
120 if err != nil {
121 if tt.err == "" {
122 t.Errorf("#%d: err=%q, expected success (%q)", i, err, string(buf))
123 continue
124 }
125 if !strings.Contains(err.Error(), tt.err) {
126 t.Errorf("#%d: err=%q, expected %q", i, err, tt.err)
127 continue
128 }
129 continue
130 }
131 if err == nil && tt.err != "" {
132 t.Errorf("#%d: success, expected %q", i, tt.err)
133 continue
134 }
135
136 out := string(buf)
137 if out != testOut {
138 t.Errorf("#%d: wrong output:\nhave %q\nwant %q\n", i, out, testOut)
139 }
140 }
141}
142
143func TestReadImports(t *testing.T) {
144 testRead(t, readImportsTests, func(r io.Reader) ([]byte, error) { return readImports(r, true, nil) })
145}
146
147func TestReadComments(t *testing.T) {
148 testRead(t, readCommentsTests, readComments)
149}
150
151var readFailuresTests = []readTest{
152 {
153 `package`,
154 "syntax error",
155 },
156 {
157 "package p\n\x00\nimport `math`\n",
158 "unexpected NUL in input",
159 },
160 {
161 `package p; import`,
162 "syntax error",
163 },
164 {
165 `package p; import "`,
166 "syntax error",
167 },
168 {
169 "package p; import ` \n\n",
170 "syntax error",
171 },
172 {
173 `package p; import "x`,
174 "syntax error",
175 },
176 {
177 `package p; import _`,
178 "syntax error",
179 },
180 {
181 `package p; import _ "`,
182 "syntax error",
183 },
184 {
185 `package p; import _ "x`,
186 "syntax error",
187 },
188 {
189 `package p; import .`,
190 "syntax error",
191 },
192 {
193 `package p; import . "`,
194 "syntax error",
195 },
196 {
197 `package p; import . "x`,
198 "syntax error",
199 },
200 {
201 `package p; import (`,
202 "syntax error",
203 },
204 {
205 `package p; import ("`,
206 "syntax error",
207 },
208 {
209 `package p; import ("x`,
210 "syntax error",
211 },
212 {
213 `package p; import ("x"`,
214 "syntax error",
215 },
216}
217
218func TestReadFailures(t *testing.T) {
219 // Errors should be reported (true arg to readImports).
220 testRead(t, readFailuresTests, func(r io.Reader) ([]byte, error) { return readImports(r, true, nil) })
221}
222
223func TestReadFailuresIgnored(t *testing.T) {
224 // Syntax errors should not be reported (false arg to readImports).
225 // Instead, entire file should be the output and no error.
226 // Convert tests not to return syntax errors.
227 tests := make([]readTest, len(readFailuresTests))
228 copy(tests, readFailuresTests)
229 for i := range tests {
230 tt := &tests[i]
231 if !strings.Contains(tt.err, "NUL") {
232 tt.err = ""
233 }
234 }
235 testRead(t, tests, func(r io.Reader) ([]byte, error) { return readImports(r, false, nil) })
236}