aboutsummaryrefslogtreecommitdiffstats
path: root/pkg/subsystem/extractor_test.go
diff options
context:
space:
mode:
authorAleksandr Nogikh <nogikh@google.com>2023-01-31 13:38:10 +0100
committerAleksandr Nogikh <wp32pw@gmail.com>2023-02-10 14:34:44 +0100
commitad871703d4fcd9ed84544dd6f5c4221aa5df5feb (patch)
treee56c0441a09c3d6d3cd90ec9e290b9abe65f3d82 /pkg/subsystem/extractor_test.go
parent9a724c34f06b47f05b36c5292b107e9b06048667 (diff)
pkg/subsystem: extract subsystems from a crash list
For now, let's use a straightforward approach: 1) Extract all subsystems for each guilty path and syz reproducer. 2) If there are both parents and children in the list, remove parents. 3) Count the remaining subsystems. 4) Pick the ones that appear most often.
Diffstat (limited to 'pkg/subsystem/extractor_test.go')
-rw-r--r--pkg/subsystem/extractor_test.go126
1 files changed, 126 insertions, 0 deletions
diff --git a/pkg/subsystem/extractor_test.go b/pkg/subsystem/extractor_test.go
new file mode 100644
index 000000000..5dedd0b1a
--- /dev/null
+++ b/pkg/subsystem/extractor_test.go
@@ -0,0 +1,126 @@
+// Copyright 2023 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 subsystem
+
+import (
+ "reflect"
+ "testing"
+
+ "github.com/google/syzkaller/pkg/subsystem/entity"
+ "github.com/stretchr/testify/assert"
+)
+
+func TestExtractor(t *testing.T) {
+ // Objects used in tests.
+ fsPath := "fs/"
+ extProg, nfsProg := []byte("ext prog"), []byte("nfs prog")
+ fs := &entity.Subsystem{Name: "fs"}
+ ext := &entity.Subsystem{Name: "ext", Parents: []*entity.Subsystem{fs}}
+ nfs := &entity.Subsystem{Name: "nfs", Parents: []*entity.Subsystem{fs}}
+ // Tests themselves.
+ tests := []struct {
+ name string
+ crashes []*Crash
+ want []*entity.Subsystem
+ }{
+ {
+ name: `Make sure it works fine with just a single path`,
+ crashes: []*Crash{
+ {
+ GuiltyPath: fsPath,
+ },
+ },
+ want: []*entity.Subsystem{fs},
+ },
+ {
+ name: `Make sure a child shadows its parent`,
+ crashes: []*Crash{
+ {
+ GuiltyPath: fsPath,
+ },
+ {
+ GuiltyPath: fsPath,
+ SyzRepro: extProg,
+ },
+ },
+ want: []*entity.Subsystem{ext},
+ },
+ {
+ name: `Two equally present children`,
+ crashes: []*Crash{
+ {
+ GuiltyPath: fsPath,
+ },
+ {
+ GuiltyPath: fsPath,
+ SyzRepro: extProg,
+ },
+ {
+ GuiltyPath: fsPath,
+ SyzRepro: nfsProg,
+ },
+ },
+ want: []*entity.Subsystem{nfs, ext},
+ },
+ {
+ name: `One child is more present than another`,
+ crashes: []*Crash{
+ {
+ GuiltyPath: fsPath,
+ },
+ {
+ GuiltyPath: fsPath,
+ SyzRepro: extProg,
+ },
+ {
+ GuiltyPath: fsPath,
+ SyzRepro: nfsProg,
+ },
+ {
+ GuiltyPath: fsPath,
+ SyzRepro: extProg,
+ },
+ },
+ want: []*entity.Subsystem{ext},
+ },
+ }
+ extractor := &Extractor{
+ raw: &testRawExtractor{
+ perPath: map[string][]*entity.Subsystem{
+ fsPath: {fs},
+ },
+ perProg: []progSubsystems{
+ {extProg, []*entity.Subsystem{ext}},
+ {nfsProg, []*entity.Subsystem{nfs}},
+ },
+ },
+ }
+ for _, test := range tests {
+ ret := extractor.Extract(test.crashes)
+ assert.ElementsMatch(t, ret, test.want, test.name)
+ }
+}
+
+type testRawExtractor struct {
+ perPath map[string][]*entity.Subsystem
+ perProg []progSubsystems
+}
+
+type progSubsystems struct {
+ prog []byte
+ ret []*entity.Subsystem
+}
+
+func (e *testRawExtractor) FromPath(path string) []*entity.Subsystem {
+ return e.perPath[path]
+}
+
+func (e *testRawExtractor) FromProg(progBytes []byte) []*entity.Subsystem {
+ for _, obj := range e.perProg {
+ if reflect.DeepEqual(progBytes, obj.prog) {
+ return obj.ret
+ }
+ }
+ return nil
+}