1 package kmod
2
3 import (
4 "bytes"
5 "log"
6 "os"
7 "path/filepath"
8 "testing"
9
10 "golang.org/x/sys/unix"
11 )
12
13 func createFiles() (string, []module) {
14 writeFile := func(path, text string) {
15 if err := os.WriteFile(path, []byte(text), 0o600); err != nil {
16 log.Fatal(err)
17 }
18 }
19 var u unix.Utsname
20 if err := unix.Uname(&u); err != nil {
21 log.Fatal(err)
22 }
23 kernelVersion := string(u.Release[:bytes.IndexByte(u.Release[:], 0)])
24
25 rootdir, err := os.MkdirTemp("", "kmod")
26 if err != nil {
27 log.Fatal(err)
28 }
29
30 moddir := filepath.Join(rootdir, kernelVersion)
31 if err := os.Mkdir(moddir, 0o700); err != nil {
32 log.Fatal(err)
33 }
34
35 text := "kernel/a/foo.ko:\n"
36 text += "kernel/a/bar.ko: kernel/a/foo.ko\n"
37 text += "kernel/a/baz.ko: kernel/a/bar.ko kernel/a/foo.ko\n"
38 writeFile(filepath.Join(moddir, "modules.dep"), text)
39
40 text = "kernel/a/foo_bi.ko\n"
41 text += "kernel/a/bar-bi.ko.gz\n"
42 writeFile(filepath.Join(moddir, "modules.builtin"), text)
43
44 text = "alias ignore ignore\n"
45 text += "alias foo_a foo\n"
46 text += "alias bar-a bar\n"
47 writeFile(filepath.Join(moddir, "modules.alias"), text)
48
49 text = "options foo foo1 foo2\n"
50 text += "options bar bar1\n"
51 writeFile(filepath.Join(rootdir, "modprobe.conf"), text)
52
53 modules := []module{
54 {name: "foo", path: "kernel/a/foo.ko", params: "foo1 foo2"},
55 {name: "bar", path: "kernel/a/bar.ko", params: "bar1"},
56 {name: "baz", path: "kernel/a/baz.ko"},
57 }
58 return rootdir, modules
59 }
60
61 func TestIsBuiltin(t *testing.T) {
62 rootdir, _ := createFiles()
63 defer os.RemoveAll(rootdir)
64
65 k, err := New(SetRootDir(rootdir))
66 if err != nil {
67 t.Fatal(err)
68 }
69
70 tests := []struct {
71 name string
72 want bool
73 }{
74 {"", false},
75 {"none", false},
76 {"foo_bi", true},
77 {"bar_bi", true},
78 }
79
80 for _, tt := range tests {
81 ok, err := k.isBuiltin(tt.name)
82 if err != nil {
83 t.Fatal(err)
84 }
85 if ok != tt.want {
86 t.Fatalf("%s want:%t got:%t", tt.name, tt.want, ok)
87 }
88 }
89 }
90
91 func TestApplyConfig(t *testing.T) {
92 rootdir, modules := createFiles()
93 defer os.RemoveAll(rootdir)
94
95 path := filepath.Join(rootdir, "modprobe.conf")
96 k, err := New(SetRootDir(rootdir), SetConfigFile(path))
97 if err != nil {
98 t.Fatal(err)
99 }
100
101 var tests []module
102 for _, m := range modules {
103 m.params = ""
104 tests = append(tests, m)
105 }
106
107 if err := k.applyConfig(tests); err != nil {
108 t.Fatal(err)
109 }
110
111 for i := range tests {
112 if modules[i] != tests[i] {
113 t.Fatalf("want:%v got:%v", modules[i], tests[i])
114 }
115 }
116 }
117
118 func TestOptionIgnoreStatus(t *testing.T) {
119 rootdir, _ := createFiles()
120 defer os.RemoveAll(rootdir)
121
122 {
123 k, err := New(SetRootDir(rootdir))
124 if err != nil {
125 t.Fatal(err)
126 }
127
128 want := unloaded
129 status, err := k.modStatus("foo")
130 if err != nil {
131 t.Fatal(err)
132 }
133 if status != want {
134 t.Fatalf("want:%v got:%v", want, status)
135 }
136 }
137
138 {
139 k, err := New(SetRootDir(rootdir), SetIgnoreStatus())
140 if err != nil {
141 t.Fatal(err)
142 }
143
144 want := unknown
145 status, err := k.modStatus("foo")
146 if err != nil {
147 t.Fatal(err)
148 }
149 if status != want {
150 t.Fatalf("want:%v got:%v", want, status)
151 }
152 }
153 }
154
155 func TestDependencies(t *testing.T) {
156 rootdir, modules := createFiles()
157 defer os.RemoveAll(rootdir)
158
159 k, err := New(SetRootDir(rootdir))
160 if err != nil {
161 t.Fatal(err)
162 }
163
164 list, err := k.Dependencies("baz")
165 if err != nil {
166 t.Fatal(err)
167 }
168
169 if len(list) != len(modules) {
170 t.Fatalf("len(dependency list) want: %d got:%d", len(modules), len(list))
171 }
172
173 for i := len(modules) - 2; i <= 0; i-- {
174 if modules[i].path != list[i] {
175 t.Fatalf("want:%v got:%v", modules[i].path, list[i])
176 }
177 }
178 }
179
View as plain text