aboutsummaryrefslogtreecommitdiffstats
path: root/pkg/ast/parser_test.go
blob: c7018b24364a11c5c6e96204955d212b0aa701f8 (plain)
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(Clone(desc))
			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)
		})
	}
}