aboutsummaryrefslogtreecommitdiffstats
path: root/pkg/subsystem/linux/parents_test.go
diff options
context:
space:
mode:
authorAleksandr Nogikh <nogikh@google.com>2023-01-18 18:45:55 +0100
committerAleksandr Nogikh <wp32pw@gmail.com>2023-02-10 14:34:44 +0100
commit3a4c5e2da302d43152f2e8b1362d8568c0d57e6e (patch)
tree87327b1f4d350392c22b6941a34bd4c9ae48aed9 /pkg/subsystem/linux/parents_test.go
parent8d41190df0b6184bac7d8b34765fc84395f27cf4 (diff)
pkg/subsystem/linux: determine parent-child relations
For that, extract a coincidence count matrix from a path coverage, then apply the following rule. Subsystem A is a child of B if both hold true: 1) More than 2/3 of paths that relate to A also relate to B. 2) B covers more directory tree entities than A.
Diffstat (limited to 'pkg/subsystem/linux/parents_test.go')
-rw-r--r--pkg/subsystem/linux/parents_test.go90
1 files changed, 90 insertions, 0 deletions
diff --git a/pkg/subsystem/linux/parents_test.go b/pkg/subsystem/linux/parents_test.go
new file mode 100644
index 000000000..2ef6e2b07
--- /dev/null
+++ b/pkg/subsystem/linux/parents_test.go
@@ -0,0 +1,90 @@
+// 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 linux
+
+import (
+ "testing"
+ "testing/fstest"
+
+ "github.com/google/syzkaller/pkg/subsystem/entity"
+ "github.com/google/syzkaller/pkg/subsystem/match"
+ "github.com/stretchr/testify/assert"
+)
+
+func TestLoopsDoExist(t *testing.T) {
+ a := &entity.Subsystem{}
+ b := &entity.Subsystem{Parents: []*entity.Subsystem{a}}
+ c := &entity.Subsystem{Parents: []*entity.Subsystem{b}}
+ a.Parents = []*entity.Subsystem{c}
+ assert.True(t, loopsExist([]*entity.Subsystem{a, b, c}))
+}
+
+func TestLoopsDoNotExist(t *testing.T) {
+ a := &entity.Subsystem{}
+ b := &entity.Subsystem{Parents: []*entity.Subsystem{a}}
+ c := &entity.Subsystem{Parents: []*entity.Subsystem{b}}
+ assert.False(t, loopsExist([]*entity.Subsystem{a, b, c}))
+}
+
+func TestTransitiveReduction(t *testing.T) {
+ // (d, c), (c, b), (b, a)
+ // (d, a)
+ // (d, b)
+ // (d, e)
+ // (c, a)
+ a := &entity.Subsystem{}
+ b := &entity.Subsystem{Parents: []*entity.Subsystem{a}}
+ c := &entity.Subsystem{Parents: []*entity.Subsystem{a, b}}
+ e := &entity.Subsystem{}
+ d := &entity.Subsystem{Parents: []*entity.Subsystem{a, b, c, e}}
+ transitiveReduction([]*entity.Subsystem{a, b, c, d, e})
+
+ // The result should be:
+ // (d, c), (c, b), (b, a)
+ // (d, e)
+ assert.ElementsMatch(t, d.Parents, []*entity.Subsystem{c, e})
+ assert.ElementsMatch(t, c.Parents, []*entity.Subsystem{b})
+}
+
+func TestSetParents(t *testing.T) {
+ kernel := &entity.Subsystem{PathRules: []entity.PathRule{{
+ IncludeRegexp: `.*`,
+ }}}
+ net := &entity.Subsystem{PathRules: []entity.PathRule{{
+ IncludeRegexp: `^net/`,
+ }}}
+ wireless := &entity.Subsystem{PathRules: []entity.PathRule{{
+ IncludeRegexp: `^net/wireless`,
+ }}}
+ drivers := &entity.Subsystem{PathRules: []entity.PathRule{{
+ IncludeRegexp: `^drivers/`,
+ }}}
+
+ tree := fstest.MapFS{
+ "include/net/cfg80211.h": {},
+ "net/socket.c": {},
+ "net/nfc/core.c": {},
+ "net/wireless/nl80211.c": {},
+ "net/wireless/sysfs.c": {},
+ "net/ipv4/arp.c": {},
+ "drivers/usb/host/xhci.c": {},
+ "drivers/android/binder.c": {},
+ }
+
+ matrix, err := match.BuildCoincidenceMatrix(tree,
+ []*entity.Subsystem{kernel, net, wireless, drivers}, nil)
+ assert.NoError(t, err)
+
+ // Calculate parents.
+ err = SetParents(matrix, []*entity.Subsystem{kernel, net, wireless, drivers})
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ // Verify parents.
+ assert.ElementsMatch(t, net.Parents, []*entity.Subsystem{kernel})
+ assert.ElementsMatch(t, wireless.Parents, []*entity.Subsystem{net})
+ assert.ElementsMatch(t, drivers.Parents, []*entity.Subsystem{kernel})
+ assert.ElementsMatch(t, kernel.Parents, []*entity.Subsystem{})
+}