OSDN Git Service

new repo
[bytom/vapor.git] / vendor / github.com / hashicorp / hcl / json / parser / parser_test.go
1 package parser
2
3 import (
4         "fmt"
5         "io/ioutil"
6         "path/filepath"
7         "reflect"
8         "runtime"
9         "testing"
10
11         "github.com/hashicorp/hcl/hcl/ast"
12         "github.com/hashicorp/hcl/hcl/token"
13 )
14
15 func TestType(t *testing.T) {
16         var literals = []struct {
17                 typ token.Type
18                 src string
19         }{
20                 {token.STRING, `"foo": "bar"`},
21                 {token.NUMBER, `"foo": 123`},
22                 {token.FLOAT, `"foo": 123.12`},
23                 {token.FLOAT, `"foo": -123.12`},
24                 {token.BOOL, `"foo": true`},
25                 {token.STRING, `"foo": null`},
26         }
27
28         for _, l := range literals {
29                 t.Logf("Testing: %s", l.src)
30
31                 p := newParser([]byte(l.src))
32                 item, err := p.objectItem()
33                 if err != nil {
34                         t.Error(err)
35                 }
36
37                 lit, ok := item.Val.(*ast.LiteralType)
38                 if !ok {
39                         t.Errorf("node should be of type LiteralType, got: %T", item.Val)
40                 }
41
42                 if lit.Token.Type != l.typ {
43                         t.Errorf("want: %s, got: %s", l.typ, lit.Token.Type)
44                 }
45         }
46 }
47
48 func TestListType(t *testing.T) {
49         var literals = []struct {
50                 src    string
51                 tokens []token.Type
52         }{
53                 {
54                         `"foo": ["123", 123]`,
55                         []token.Type{token.STRING, token.NUMBER},
56                 },
57                 {
58                         `"foo": [123, "123",]`,
59                         []token.Type{token.NUMBER, token.STRING},
60                 },
61                 {
62                         `"foo": []`,
63                         []token.Type{},
64                 },
65                 {
66                         `"foo": ["123", 123]`,
67                         []token.Type{token.STRING, token.NUMBER},
68                 },
69                 {
70                         `"foo": ["123", {}]`,
71                         []token.Type{token.STRING, token.LBRACE},
72                 },
73         }
74
75         for _, l := range literals {
76                 t.Logf("Testing: %s", l.src)
77
78                 p := newParser([]byte(l.src))
79                 item, err := p.objectItem()
80                 if err != nil {
81                         t.Error(err)
82                 }
83
84                 list, ok := item.Val.(*ast.ListType)
85                 if !ok {
86                         t.Errorf("node should be of type LiteralType, got: %T", item.Val)
87                 }
88
89                 tokens := []token.Type{}
90                 for _, li := range list.List {
91                         switch v := li.(type) {
92                         case *ast.LiteralType:
93                                 tokens = append(tokens, v.Token.Type)
94                         case *ast.ObjectType:
95                                 tokens = append(tokens, token.LBRACE)
96                         }
97                 }
98
99                 equals(t, l.tokens, tokens)
100         }
101 }
102
103 func TestObjectType(t *testing.T) {
104         var literals = []struct {
105                 src      string
106                 nodeType []ast.Node
107                 itemLen  int
108         }{
109                 {
110                         `"foo": {}`,
111                         nil,
112                         0,
113                 },
114                 {
115                         `"foo": {
116                                 "bar": "fatih"
117                          }`,
118                         []ast.Node{&ast.LiteralType{}},
119                         1,
120                 },
121                 {
122                         `"foo": {
123                                 "bar": "fatih",
124                                 "baz": ["arslan"]
125                          }`,
126                         []ast.Node{
127                                 &ast.LiteralType{},
128                                 &ast.ListType{},
129                         },
130                         2,
131                 },
132                 {
133                         `"foo": {
134                                 "bar": {}
135                          }`,
136                         []ast.Node{
137                                 &ast.ObjectType{},
138                         },
139                         1,
140                 },
141                 {
142                         `"foo": {
143                                 "bar": {},
144                                 "foo": true
145                          }`,
146                         []ast.Node{
147                                 &ast.ObjectType{},
148                                 &ast.LiteralType{},
149                         },
150                         2,
151                 },
152         }
153
154         for _, l := range literals {
155                 t.Logf("Testing:\n%s\n", l.src)
156
157                 p := newParser([]byte(l.src))
158                 // p.enableTrace = true
159                 item, err := p.objectItem()
160                 if err != nil {
161                         t.Error(err)
162                 }
163
164                 // we know that the ObjectKey name is foo for all cases, what matters
165                 // is the object
166                 obj, ok := item.Val.(*ast.ObjectType)
167                 if !ok {
168                         t.Errorf("node should be of type LiteralType, got: %T", item.Val)
169                 }
170
171                 // check if the total length of items are correct
172                 equals(t, l.itemLen, len(obj.List.Items))
173
174                 // check if the types are correct
175                 for i, item := range obj.List.Items {
176                         equals(t, reflect.TypeOf(l.nodeType[i]), reflect.TypeOf(item.Val))
177                 }
178         }
179 }
180
181 func TestFlattenObjects(t *testing.T) {
182         var literals = []struct {
183                 src      string
184                 nodeType []ast.Node
185                 itemLen  int
186         }{
187                 {
188                         `{
189                                         "foo": [
190                                                 {
191                                                         "foo": "svh",
192                                                         "bar": "fatih"
193                                                 }
194                                         ]
195                                 }`,
196                         []ast.Node{
197                                 &ast.ObjectType{},
198                                 &ast.LiteralType{},
199                                 &ast.LiteralType{},
200                         },
201                         3,
202                 },
203                 {
204                         `{
205                                         "variable": {
206                                                 "foo": {}
207                                         }
208                                 }`,
209                         []ast.Node{
210                                 &ast.ObjectType{},
211                         },
212                         1,
213                 },
214                 {
215                         `{
216                                 "empty": []
217                         }`,
218                         []ast.Node{
219                                 &ast.ListType{},
220                         },
221                         1,
222                 },
223                 {
224                         `{
225                                 "basic": [1, 2, 3]
226                         }`,
227                         []ast.Node{
228                                 &ast.ListType{},
229                         },
230                         1,
231                 },
232         }
233
234         for _, l := range literals {
235                 t.Logf("Testing:\n%s\n", l.src)
236
237                 f, err := Parse([]byte(l.src))
238                 if err != nil {
239                         t.Error(err)
240                 }
241
242                 // the first object is always an ObjectList so just assert that one
243                 // so we can use it as such
244                 obj, ok := f.Node.(*ast.ObjectList)
245                 if !ok {
246                         t.Errorf("node should be *ast.ObjectList, got: %T", f.Node)
247                 }
248
249                 // check if the types are correct
250                 var i int
251                 for _, item := range obj.Items {
252                         equals(t, reflect.TypeOf(l.nodeType[i]), reflect.TypeOf(item.Val))
253                         i++
254
255                         if obj, ok := item.Val.(*ast.ObjectType); ok {
256                                 for _, item := range obj.List.Items {
257                                         equals(t, reflect.TypeOf(l.nodeType[i]), reflect.TypeOf(item.Val))
258                                         i++
259                                 }
260                         }
261                 }
262
263                 // check if the number of items is correct
264                 equals(t, l.itemLen, i)
265
266         }
267 }
268
269 func TestObjectKey(t *testing.T) {
270         keys := []struct {
271                 exp []token.Type
272                 src string
273         }{
274                 {[]token.Type{token.STRING}, `"foo": {}`},
275         }
276
277         for _, k := range keys {
278                 p := newParser([]byte(k.src))
279                 keys, err := p.objectKey()
280                 if err != nil {
281                         t.Fatal(err)
282                 }
283
284                 tokens := []token.Type{}
285                 for _, o := range keys {
286                         tokens = append(tokens, o.Token.Type)
287                 }
288
289                 equals(t, k.exp, tokens)
290         }
291
292         errKeys := []struct {
293                 src string
294         }{
295                 {`foo 12 {}`},
296                 {`foo bar = {}`},
297                 {`foo []`},
298                 {`12 {}`},
299         }
300
301         for _, k := range errKeys {
302                 p := newParser([]byte(k.src))
303                 _, err := p.objectKey()
304                 if err == nil {
305                         t.Errorf("case '%s' should give an error", k.src)
306                 }
307         }
308 }
309
310 // Official HCL tests
311 func TestParse(t *testing.T) {
312         cases := []struct {
313                 Name string
314                 Err  bool
315         }{
316                 {
317                         "array.json",
318                         false,
319                 },
320                 {
321                         "basic.json",
322                         false,
323                 },
324                 {
325                         "object.json",
326                         false,
327                 },
328                 {
329                         "types.json",
330                         false,
331                 },
332                 {
333                         "bad_input_128.json",
334                         true,
335                 },
336                 {
337                         "bad_input_tf_8110.json",
338                         true,
339                 },
340                 {
341                         "good_input_tf_8110.json",
342                         false,
343                 },
344         }
345
346         const fixtureDir = "./test-fixtures"
347
348         for _, tc := range cases {
349                 d, err := ioutil.ReadFile(filepath.Join(fixtureDir, tc.Name))
350                 if err != nil {
351                         t.Fatalf("err: %s", err)
352                 }
353
354                 _, err = Parse(d)
355                 if (err != nil) != tc.Err {
356                         t.Fatalf("Input: %s\n\nError: %s", tc.Name, err)
357                 }
358         }
359 }
360
361 func TestParse_inline(t *testing.T) {
362         cases := []struct {
363                 Value string
364                 Err   bool
365         }{
366                 {"{:{", true},
367         }
368
369         for _, tc := range cases {
370                 _, err := Parse([]byte(tc.Value))
371                 if (err != nil) != tc.Err {
372                         t.Fatalf("Input: %q\n\nError: %s", tc.Value, err)
373                 }
374         }
375 }
376
377 // equals fails the test if exp is not equal to act.
378 func equals(tb testing.TB, exp, act interface{}) {
379         if !reflect.DeepEqual(exp, act) {
380                 _, file, line, _ := runtime.Caller(1)
381                 fmt.Printf("\033[31m%s:%d:\n\n\texp: %s\n\n\tgot: %s\033[39m\n\n", filepath.Base(file), line, exp, act)
382                 tb.FailNow()
383         }
384 }