github.com/google/syzkaller@v0.0.0-20240517125934-c0f1611a36d6/syz-verifier/execresult_test.go (about)

     1  // Copyright 2021 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 main
     5  
     6  import (
     7  	"testing"
     8  
     9  	"github.com/google/go-cmp/cmp"
    10  	"github.com/google/syzkaller/prog"
    11  )
    12  
    13  func TestIsEqual(t *testing.T) {
    14  	tests := []struct {
    15  		name string
    16  		res  []*ExecResult
    17  		want bool
    18  	}{
    19  		{
    20  			name: "only crashes",
    21  			res: []*ExecResult{
    22  				makeExecResultCrashed(1),
    23  				makeExecResultCrashed(4),
    24  			},
    25  			want: false,
    26  		},
    27  		{
    28  			name: "mismatch because result and crash",
    29  			res: []*ExecResult{
    30  				makeExecResultCrashed(1),
    31  				makeExecResult(2, []int{11, 33, 22}, []int{1, 3, 3}...),
    32  			},
    33  			want: false,
    34  		},
    35  		{
    36  			name: "mismatches because of diffent length",
    37  			res: []*ExecResult{
    38  				makeExecResult(2, []int{11, 33}, []int{1, 3}...),
    39  				makeExecResult(4, []int{11, 33, 22}, []int{1, 3, 3}...)},
    40  			want: false,
    41  		},
    42  		{
    43  			name: "mismatches not found",
    44  			res: []*ExecResult{
    45  				makeExecResult(2, []int{11, 33, 22}, []int{1, 3, 3}...),
    46  				makeExecResult(4, []int{11, 33, 22}, []int{1, 3, 3}...)},
    47  			want: true,
    48  		},
    49  		{
    50  			name: "mismatches found in results",
    51  			res: []*ExecResult{
    52  				makeExecResult(1, []int{1, 3, 2}, []int{4, 7, 7}...),
    53  				makeExecResult(4, []int{1, 3, 5}, []int{4, 7, 3}...),
    54  			},
    55  			want: false,
    56  		}}
    57  
    58  	for _, test := range tests {
    59  		t.Run(test.name, func(t *testing.T) {
    60  			got := test.res[0].IsEqual(test.res[1])
    61  			if diff := cmp.Diff(test.want, got); diff != "" {
    62  				t.Errorf("ExecResult.IsEqual failure (-want +got):\n%s", diff)
    63  			}
    64  		})
    65  	}
    66  }
    67  
    68  func TestCompareResults(t *testing.T) {
    69  	p := "breaks_returns()\n" +
    70  		"minimize$0(0x1, 0x1)\n" +
    71  		"test$res0()\n"
    72  	tests := []struct {
    73  		name       string
    74  		res        []*ExecResult
    75  		wantReport *ResultReport
    76  		wantStats  []*CallStats
    77  	}{
    78  		{
    79  			name: "only crashes",
    80  			res: []*ExecResult{
    81  				makeExecResultCrashed(1),
    82  				makeExecResultCrashed(4),
    83  			},
    84  			wantReport: &ResultReport{
    85  				Prog: p,
    86  				Reports: []*CallReport{
    87  					{Call: "breaks_returns", States: map[int]ReturnState{
    88  						1: crashedReturnState(),
    89  						4: crashedReturnState()},
    90  					},
    91  					{Call: "minimize$0", States: map[int]ReturnState{
    92  						1: crashedReturnState(),
    93  						4: crashedReturnState()},
    94  					},
    95  					{Call: "test$res0", States: map[int]ReturnState{
    96  						1: crashedReturnState(),
    97  						4: crashedReturnState()},
    98  					},
    99  				},
   100  				Mismatch: false,
   101  			},
   102  		},
   103  		{
   104  			name: "mismatches because results and crashes",
   105  			res: []*ExecResult{
   106  				makeExecResultCrashed(1),
   107  				makeExecResult(2, []int{11, 33, 22}, []int{1, 3, 3}...),
   108  				makeExecResult(4, []int{11, 33, 22}, []int{1, 3, 3}...),
   109  			},
   110  			wantReport: &ResultReport{
   111  				Prog: p,
   112  				Reports: []*CallReport{
   113  					{Call: "breaks_returns", States: map[int]ReturnState{
   114  						1: crashedReturnState(),
   115  						2: returnState(11, 1),
   116  						4: returnState(11, 1)},
   117  						Mismatch: true},
   118  					{Call: "minimize$0", States: map[int]ReturnState{
   119  						1: crashedReturnState(),
   120  						2: returnState(33, 3),
   121  						4: returnState(33, 3)},
   122  						Mismatch: true},
   123  					{Call: "test$res0", States: map[int]ReturnState{
   124  						1: crashedReturnState(),
   125  						2: returnState(22, 3),
   126  						4: returnState(22, 3)},
   127  						Mismatch: true},
   128  				},
   129  				Mismatch: true,
   130  			},
   131  		},
   132  		{
   133  			name: "mismatches not found in results",
   134  			res: []*ExecResult{
   135  				makeExecResult(2, []int{11, 33, 22}, []int{1, 3, 3}...),
   136  				makeExecResult(4, []int{11, 33, 22}, []int{1, 3, 3}...)},
   137  			wantReport: &ResultReport{
   138  				Prog: p,
   139  				Reports: []*CallReport{
   140  					{Call: "breaks_returns", States: map[int]ReturnState{2: {Errno: 11, Flags: 1}, 4: {Errno: 11, Flags: 1}}},
   141  					{Call: "minimize$0", States: map[int]ReturnState{2: {Errno: 33, Flags: 3}, 4: {Errno: 33, Flags: 3}}},
   142  					{Call: "test$res0", States: map[int]ReturnState{2: {Errno: 22, Flags: 3}, 4: {Errno: 22, Flags: 3}}},
   143  				},
   144  				Mismatch: false,
   145  			},
   146  		},
   147  		{
   148  			name: "mismatches found in results",
   149  			res: []*ExecResult{
   150  				makeExecResult(1, []int{1, 3, 2}, []int{4, 7, 7}...),
   151  				makeExecResult(4, []int{1, 3, 5}, []int{4, 7, 3}...),
   152  			},
   153  			wantReport: &ResultReport{
   154  				Prog: p,
   155  				Reports: []*CallReport{
   156  					{Call: "breaks_returns", States: map[int]ReturnState{1: {Errno: 1, Flags: 4}, 4: {Errno: 1, Flags: 4}}},
   157  					{Call: "minimize$0", States: map[int]ReturnState{1: {Errno: 3, Flags: 7}, 4: {Errno: 3, Flags: 7}}},
   158  					{Call: "test$res0", States: map[int]ReturnState{1: {Errno: 2, Flags: 7}, 4: {Errno: 5, Flags: 3}}, Mismatch: true},
   159  				},
   160  				Mismatch: true,
   161  			},
   162  		}}
   163  
   164  	for _, test := range tests {
   165  		test := test // TODO: remove for gover >= 1.22
   166  		t.Run(test.name, func(t *testing.T) {
   167  			target := prog.InitTargetTest(t, "test", "64")
   168  			prog, err := target.Deserialize([]byte(p), prog.Strict)
   169  			if err != nil {
   170  				t.Fatalf("failed to deserialise test program: %v", err)
   171  			}
   172  			got := CompareResults(test.res, prog)
   173  			if diff := cmp.Diff(test.wantReport, got); diff != "" {
   174  				t.Errorf("verify report mismatch (-want +got):\n%s", diff)
   175  			}
   176  		})
   177  	}
   178  }