github.com/google/syzkaller@v0.0.0-20240517125934-c0f1611a36d6/tools/syz-trace2syz/parser/parser_test.go (about)

     1  // Copyright 2018 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  //go:build !codeanalysis
     5  
     6  package parser
     7  
     8  import (
     9  	"testing"
    10  
    11  	_ "github.com/google/syzkaller/sys"
    12  )
    13  
    14  func TestParseLoopBasic(t *testing.T) {
    15  	tests := []string{
    16  		`open() = 3
    17  		fstat() = 0`,
    18  		`open() = 0x73ffddabc
    19  		fstat() = 0`,
    20  		`open() = -1 ENOSPEC (something)
    21  		fstat() = 0`,
    22  		`open( ,  <unfinished ...>
    23  		<... open resumed>) = 3
    24  		fstat() = 0`,
    25  		`open( ,  <unfinished ...>
    26  		<... open resumed> , 2) = 3
    27  		fstat() = 0`,
    28  		`open( <unfinished ...>
    29  		<... open resumed>) = 3
    30  		fstat() = 0`,
    31  		`open( <unfinished ...>
    32  		<... open resumed>) = 0x44277ffff
    33  		fstat() = 0`,
    34  		`open( <unfinished ...>
    35  		<... open resumed>) = ?
    36  		fstat() = 0`,
    37  		`open( <unfinished ...>
    38  		<... open resumed>) = -1 FLAG (sdfjfjfjf)
    39  		fstat() = 0`,
    40  		`open(1,  <unfinished ...>
    41  		<... open resumed> , 0x1|0x2) = -1 FLAG (sdfjfjfjf)
    42  		fstat() = 0`,
    43  		`open([0x1, 0x2], NULL, {tv_sec=5, tv_nsec=0}, 8 <unfinished ...>
    44  		<... rt_sigtimedwait resumed> )   = 10 (SIGUSR1)
    45  		fstat() = 0`,
    46  		`open(0, 536892418, {c_cc[VMIN]=1, c_cc[VTIME]=0} <unfinished ...>
    47  		<... open resumed> , 0x1|0x2) = -1 FLAG (sdfjfjfjf)
    48  		fstat() = 0`,
    49  		`open(-19) = 0
    50  		 fstat() = 0`,
    51  		`open(1 + 2) = 0
    52  		 fstat() = 0`,
    53  		`open(3 - 1) = 0
    54  		 fstat() = 0`,
    55  		`open(1075599392, 0x20000000) = -1 EBADF (Bad file descriptor)
    56  		 fstat() = 0`,
    57  		`open() = -1 EIO (Input/output error)
    58  		 fstat() = 0`,
    59  		`open(113->114) = -1 EIO (Input/output error)
    60  		 fstat() = 0`,
    61  	}
    62  
    63  	for _, test := range tests {
    64  		tree, err := ParseData([]byte(test))
    65  		if err != nil {
    66  			t.Fatal(err)
    67  		}
    68  		if tree.RootPid != -1 {
    69  			t.Fatalf("Incorrect Root Pid: %d", tree.RootPid)
    70  		}
    71  
    72  		calls := tree.TraceMap[tree.RootPid].Calls
    73  		if len(calls) != 2 {
    74  			t.Fatalf("expected 2 calls. Got %d instead", len(calls))
    75  		}
    76  		if calls[0].CallName != "open" || calls[1].CallName != "fstat" {
    77  			t.Fatalf("call list should be open->fstat. Got %s->%s", calls[0].CallName, calls[1].CallName)
    78  		}
    79  	}
    80  }
    81  
    82  func TestEvaluateExpressions(t *testing.T) {
    83  	type ExprTest struct {
    84  		line         string
    85  		expectedEval uint64
    86  	}
    87  	tests := []ExprTest{
    88  		{"open(0x1) = 0", 1},
    89  		{"open(1) = 0", 1},
    90  		{"open(0x1|0x2) = 0", 3},
    91  		{"open(0x1|2) = 0", 3},
    92  		{"open(1 << 5) = 0", 32},
    93  		{"open(1 << 5|1) = 0", 33},
    94  		{"open(1 & 0) = 0", 0},
    95  		{"open(1 + 2) = 0", 3},
    96  		{"open(1-2) = 0", ^uint64(0)},
    97  		{"open(4 >> 1) = 0", 2},
    98  		{"open(0700) = 0", 448},
    99  		{"open(0) = 0", 0},
   100  	}
   101  	for i, test := range tests {
   102  		tree, err := ParseData([]byte(test.line))
   103  		if err != nil {
   104  			t.Fatal(err)
   105  		}
   106  		if tree.RootPid != -1 {
   107  			t.Fatalf("failed test: %d. Incorrect Root Pid: %d", i, tree.RootPid)
   108  		}
   109  		calls := tree.TraceMap[tree.RootPid].Calls
   110  		if len(calls) != 1 {
   111  			t.Fatalf("failed test: %d. Expected 1 call. Got %d instead", i, len(calls))
   112  		}
   113  		arg, ok := calls[0].Args[0].(Constant)
   114  		if !ok {
   115  			t.Fatalf("first argument expected to be constant. Got: %s", arg.String())
   116  		}
   117  		if arg.Val() != test.expectedEval {
   118  			t.Fatalf("expected %v != %v", test.expectedEval, arg.Val())
   119  		}
   120  	}
   121  }
   122  
   123  func TestParseLoopPid(t *testing.T) {
   124  	data := `1  open() = 3
   125  			 1  fstat() = 0`
   126  
   127  	tree, err := ParseData([]byte(data))
   128  	if err != nil {
   129  		t.Fatal(err)
   130  	}
   131  	if tree.RootPid != 1 {
   132  		t.Fatalf("Incorrect Root Pid: %d", tree.RootPid)
   133  	}
   134  
   135  	calls := tree.TraceMap[tree.RootPid].Calls
   136  	if len(calls) != 2 {
   137  		t.Fatalf("Expect 2 calls. Got %d instead", len(calls))
   138  	}
   139  	if calls[0].CallName != "open" || calls[1].CallName != "fstat" {
   140  		t.Fatalf("call list should be open->fstat. Got %s->%s", calls[0].CallName, calls[1].CallName)
   141  	}
   142  }
   143  
   144  func TestParseLoop1Child(t *testing.T) {
   145  	data1Child := `1 open() = 3
   146  				   1 clone() = 2
   147                     2 read() = 16`
   148  
   149  	tree, err := ParseData([]byte(data1Child))
   150  	if err != nil {
   151  		t.Fatal(err)
   152  	}
   153  	if len(tree.TraceMap) != 2 {
   154  		t.Fatalf("Incorrect Root Pid. Expected: 2, Got %d", tree.RootPid)
   155  	}
   156  	if tree.RootPid != 1 {
   157  		t.Fatalf("Incorrect Root Pid. Expected: 1, Got %d", tree.RootPid)
   158  	}
   159  	if tree.Ptree[tree.RootPid][0] != 2 {
   160  		t.Fatalf("Expected child to have pid: 2. Got %d", tree.Ptree[tree.RootPid][0])
   161  	} else {
   162  		if len(tree.TraceMap[2].Calls) != 1 {
   163  			t.Fatalf("Child trace should have only 1 call. Got %d", len(tree.TraceMap[2].Calls))
   164  		}
   165  	}
   166  }
   167  
   168  func TestParseLoop2Childs(t *testing.T) {
   169  	data2Childs := `1 open() = 3
   170                      1 clone() = 2
   171                      2 read() = 16
   172                      1 clone() = 3
   173                      3 open() = 3`
   174  	tree, err := ParseData([]byte(data2Childs))
   175  	if err != nil {
   176  		t.Fatal(err)
   177  	}
   178  	if len(tree.TraceMap) != 3 {
   179  		t.Fatalf("Incorrect Root Pid. Expected: 3, Got %d", tree.RootPid)
   180  	}
   181  	if len(tree.Ptree[tree.RootPid]) != 2 {
   182  		t.Fatalf("Expected Pid 1 to have 2 children: Got %d", len(tree.Ptree[tree.RootPid]))
   183  	}
   184  }
   185  
   186  func TestParseLoop1Grandchild(t *testing.T) {
   187  	data1Grandchild := `1 open() = 3
   188  						1 clone() = 2
   189  						2 clone() = 3
   190  						3 open() = 4`
   191  	tree, err := ParseData([]byte(data1Grandchild))
   192  	if err != nil {
   193  		t.Fatal(err)
   194  	}
   195  	if len(tree.Ptree[tree.RootPid]) != 1 {
   196  		t.Fatalf("Expect RootPid to have 1 child. Got %d", tree.RootPid)
   197  	}
   198  	if len(tree.Ptree[2]) != 1 {
   199  		t.Fatalf("Incorrect Root Pid. Expected: 3, Got %d", tree.RootPid)
   200  
   201  	}
   202  }
   203  
   204  func TestParseGroupType(t *testing.T) {
   205  	type irTest struct {
   206  		test string
   207  	}
   208  	tests := []irTest{
   209  		{`open({1, 2, 3}) = 0`},
   210  		{`open([1, 2, 3]) = 0`},
   211  		{`open([1 2 3]) = 0`},
   212  	}
   213  	for _, test := range tests {
   214  		tree, err := ParseData([]byte(test.test))
   215  		if err != nil {
   216  			t.Fatal(err)
   217  		}
   218  		call := tree.TraceMap[tree.RootPid].Calls[0]
   219  		_, ok := call.Args[0].(*GroupType)
   220  		if !ok {
   221  			t.Fatalf("Expected Group type. Got: %#v", call.Args[0])
   222  		}
   223  	}
   224  }