github.com/google/syzkaller@v0.0.0-20240517125934-c0f1611a36d6/pkg/ast/parser_test.go (about)

     1  // Copyright 2017 syzkaller project authors. All rights reserved.
     2  // Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
     3  
     4  package ast
     5  
     6  import (
     7  	"os"
     8  	"path/filepath"
     9  	"strings"
    10  	"testing"
    11  
    12  	"github.com/google/syzkaller/sys/targets"
    13  	"github.com/stretchr/testify/assert"
    14  )
    15  
    16  func TestParseAll(t *testing.T) {
    17  	files, err := filepath.Glob(filepath.Join("..", "..", "sys", targets.Linux, "*.txt"))
    18  	if err != nil || len(files) == 0 {
    19  		t.Fatalf("failed to read sys dir: %v", err)
    20  	}
    21  	files = append(files, filepath.FromSlash("testdata/all.txt"))
    22  	for _, file := range files {
    23  		data, err := os.ReadFile(file)
    24  		if err != nil {
    25  			t.Fatalf("failed to read file: %v", err)
    26  		}
    27  		t.Run(file, func(t *testing.T) {
    28  			eh := func(pos Pos, msg string) {
    29  				t.Fatalf("%v: %v", pos, msg)
    30  			}
    31  			desc := Parse(data, file, eh)
    32  			if desc == nil {
    33  				t.Fatalf("parsing failed, but no error produced")
    34  			}
    35  			data2 := Format(desc)
    36  			desc2 := Parse(data2, file, eh)
    37  			if desc2 == nil {
    38  				t.Fatalf("parsing failed, but no error produced")
    39  			}
    40  			if len(desc.Nodes) != len(desc2.Nodes) {
    41  				t.Fatalf("formatting number of top level decls: %v/%v",
    42  					len(desc.Nodes), len(desc2.Nodes))
    43  			}
    44  			for i := range desc.Nodes {
    45  				n1, n2 := desc.Nodes[i], desc2.Nodes[i]
    46  				if n1 == nil {
    47  					t.Fatalf("got nil node")
    48  				}
    49  				assert.Equal(t, n1, n2, "formating changed code")
    50  			}
    51  			assert.Equal(t, string(data), string(Format(desc.Clone())))
    52  			nodes0 := 0
    53  			desc.Walk(func(n Node) {
    54  				nodes0++
    55  				if SerializeNode(n) == "" {
    56  					t.Fatalf("empty serialized node: %#v", n)
    57  				}
    58  			})
    59  			nodes1 := 0
    60  			desc.Walk(Recursive(func(n Node) bool {
    61  				nodes1++
    62  				pos, typ, _ := n.Info()
    63  				if typ == "" {
    64  					t.Fatalf("%v: node has empty typ=%q: %#v", pos, typ, n)
    65  				}
    66  				return true
    67  			}))
    68  			nodes2 := 0
    69  			desc.Walk(PostRecursive(func(n Node) {
    70  				nodes2++
    71  			}))
    72  			if nodes0 != len(desc.Nodes) || nodes1 <= len(desc.Nodes) || nodes1 != nodes2 {
    73  				t.Fatalf("bad walk: desc=%v, top=%v recursive=%v, postrecursive=%v",
    74  					len(desc.Nodes), nodes0, nodes1, nodes2)
    75  			}
    76  			desc4 := desc.Filter(func(n Node) bool { return true })
    77  			desc5 := desc.Filter(func(n Node) bool { return false })
    78  			if len(desc4.Nodes) != len(desc.Nodes) || len(desc5.Nodes) != 0 {
    79  				t.Fatalf("filter is broken: desc=%v desc4=%v desc5=%v",
    80  					len(desc.Nodes), len(desc4.Nodes), len(desc5.Nodes))
    81  			}
    82  		})
    83  	}
    84  }
    85  
    86  func TestParse(t *testing.T) {
    87  	for _, test := range parseTests {
    88  		t.Run(test.name, func(t *testing.T) {
    89  			errorHandler := func(pos Pos, msg string) {
    90  				t.Logf("%v: %v", pos, msg)
    91  			}
    92  			Parse([]byte(test.input), "foo", errorHandler)
    93  		})
    94  	}
    95  }
    96  
    97  var parseTests = []struct {
    98  	name   string
    99  	input  string
   100  	result []interface{}
   101  }{
   102  	{
   103  		"empty",
   104  		``,
   105  		[]interface{}{},
   106  	},
   107  	{
   108  		"new-line",
   109  		`
   110  
   111  `,
   112  		[]interface{}{},
   113  	},
   114  	{
   115  		"nil",
   116  		"\x00",
   117  		[]interface{}{},
   118  	},
   119  }
   120  
   121  func TestErrors(t *testing.T) {
   122  	files, err := os.ReadDir("testdata")
   123  	if err != nil {
   124  		t.Fatal(err)
   125  	}
   126  	if len(files) == 0 {
   127  		t.Fatal("no input files")
   128  	}
   129  	for _, f := range files {
   130  		if !strings.HasSuffix(f.Name(), ".txt") {
   131  			continue
   132  		}
   133  		name := f.Name()
   134  		t.Run(name, func(t *testing.T) {
   135  			em := NewErrorMatcher(t, filepath.Join("testdata", name))
   136  			desc := Parse(em.Data, name, em.ErrorHandler)
   137  			if desc != nil && em.Count() != 0 {
   138  				em.DumpErrors()
   139  				t.Fatalf("parsing succeed, but got errors")
   140  			}
   141  			if desc == nil && em.Count() == 0 {
   142  				t.Fatalf("parsing failed, but got no errors")
   143  			}
   144  			em.Check()
   145  		})
   146  	}
   147  }