lin
2025-08-14 dae8bad597b6607a449b32bf76c523423f7720ed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
// Copyright 2017 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
 
package ast
 
import (
   "bytes"
   "io/ioutil"
   "path/filepath"
   "reflect"
   "strings"
   "testing"
)
 
func TestParseAll(t *testing.T) {
   files, err := filepath.Glob(filepath.Join("..", "..", "sys", "linux", "*.txt"))
   if err != nil || len(files) == 0 {
       t.Fatalf("failed to read sys dir: %v", err)
   }
   for _, file := range files {
       data, err := ioutil.ReadFile(file)
       if err != nil {
           t.Fatalf("failed to read file: %v", err)
       }
       t.Run(file, func(t *testing.T) {
           eh := func(pos Pos, msg string) {
               t.Fatalf("%v: %v", pos, msg)
           }
           desc := Parse(data, file, eh)
           if desc == nil {
               t.Fatalf("parsing failed, but no error produced")
           }
           data2 := Format(desc)
           desc2 := Parse(data2, file, eh)
           if desc2 == nil {
               t.Fatalf("parsing failed, but no error produced")
           }
           if len(desc.Nodes) != len(desc2.Nodes) {
               t.Fatalf("formatting number of top level decls: %v/%v",
                   len(desc.Nodes), len(desc2.Nodes))
           }
           for i := range desc.Nodes {
               n1, n2 := desc.Nodes[i], desc2.Nodes[i]
               if n1 == nil {
                   t.Fatalf("got nil node")
               }
               if !reflect.DeepEqual(n1, n2) {
                   t.Fatalf("formatting changed code:\n%#v\nvs:\n%#v", n1, n2)
               }
           }
           data3 := Format(desc.Clone())
           if !bytes.Equal(data, data3) {
               t.Fatalf("Clone lost data")
           }
       })
   }
}
 
func TestParse(t *testing.T) {
   for _, test := range parseTests {
       t.Run(test.name, func(t *testing.T) {
           errorHandler := func(pos Pos, msg string) {
               t.Logf("%v: %v", pos, msg)
           }
           Parse([]byte(test.input), "foo", errorHandler)
       })
   }
}
 
var parseTests = []struct {
   name   string
   input  string
   result []interface{}
}{
   {
       "empty",
       ``,
       []interface{}{},
   },
   {
       "new-line",
       `
 
`,
       []interface{}{},
   },
   {
       "nil",
       "\x00",
       []interface{}{},
   },
}
 
func TestErrors(t *testing.T) {
   files, err := ioutil.ReadDir("testdata")
   if err != nil {
       t.Fatal(err)
   }
   if len(files) == 0 {
       t.Fatal("no input files")
   }
   for _, f := range files {
       if !strings.HasSuffix(f.Name(), ".txt") {
           continue
       }
       name := f.Name()
       t.Run(name, func(t *testing.T) {
           em := NewErrorMatcher(t, filepath.Join("testdata", name))
           desc := Parse(em.Data, name, em.ErrorHandler)
           if desc != nil && em.Count() != 0 {
               em.DumpErrors(t)
               t.Fatalf("parsing succeed, but got errors")
           }
           if desc == nil && em.Count() == 0 {
               t.Fatalf("parsing failed, but got no errors")
           }
           em.Check(t)
       })
   }
}