Skip to content

Commit 44120de

Browse files
author
Dmitry Rozhkov
authored
Merge pull request intel#345 from bart0sh/PR0077-test-coverage-fpga-plugin
fpga plugin: increase test coverage
2 parents f4908a7 + cf731f3 commit 44120de

File tree

2 files changed

+190
-8
lines changed

2 files changed

+190
-8
lines changed

cmd/fpga_plugin/fpga_plugin.go

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ const (
4848
// When the device's firmware crashes the driver reports these values
4949
unhealthyAfuID = "ffffffffffffffffffffffffffffffff"
5050
unhealthyInterfaceID = "ffffffffffffffffffffffffffffffff"
51+
52+
// Frequency of device scans
53+
scanFrequency = 5 * time.Second
5154
)
5255

5356
type getDevTreeFunc func(devices []device) dpapi.DeviceTree
@@ -172,17 +175,36 @@ type devicePlugin struct {
172175
ignoreAfuIDs bool
173176
ignoreEmptyRegions bool
174177
annotationValue string
178+
179+
scanTicker *time.Ticker
180+
scanDone chan bool
175181
}
176182

177183
// newDevicePlugin returns new instance of devicePlugin
178-
func newDevicePlugin(mode string) (*devicePlugin, error) {
179-
if _, err := os.Stat(sysfsDirectoryOPAE); os.IsNotExist(err) {
180-
if _, err = os.Stat(sysfsDirectoryDFL); os.IsNotExist(err) {
181-
return nil, fmt.Errorf("kernel driver is not loaded: neither %s nor %s sysfs entry exists", sysfsDirectoryOPAE, sysfsDirectoryDFL)
184+
func newDevicePlugin(mode string, rootPath string) (*devicePlugin, error) {
185+
var dp *devicePlugin
186+
var err error
187+
188+
sysfsPathOPAE := path.Join(rootPath, sysfsDirectoryOPAE)
189+
devfsPath := path.Join(rootPath, devfsDirectory)
190+
if _, err = os.Stat(sysfsPathOPAE); os.IsNotExist(err) {
191+
sysfsPathDFL := path.Join(rootPath, sysfsDirectoryDFL)
192+
if _, err = os.Stat(sysfsPathDFL); os.IsNotExist(err) {
193+
return nil, fmt.Errorf("kernel driver is not loaded: neither %s nor %s sysfs entry exists", sysfsPathOPAE, sysfsPathDFL)
182194
}
183-
return newDevicePluginDFL(sysfsDirectoryDFL, devfsDirectory, mode)
195+
dp, err = newDevicePluginDFL(sysfsPathDFL, devfsPath, mode)
196+
} else {
197+
dp, err = newDevicePluginOPAE(sysfsPathOPAE, devfsPath, mode)
198+
}
199+
200+
if err != nil {
201+
return nil, err
184202
}
185-
return newDevicePluginOPAE(sysfsDirectoryOPAE, devfsDirectory, mode)
203+
204+
dp.scanTicker = time.NewTicker(scanFrequency)
205+
dp.scanDone = make(chan bool, 1) // buffered as we may send to it before Scan starts receiving from it
206+
207+
return dp, nil
186208
}
187209

188210
func (dp *devicePlugin) PostAllocate(response *pluginapi.AllocateResponse) error {
@@ -200,6 +222,7 @@ func (dp *devicePlugin) PostAllocate(response *pluginapi.AllocateResponse) error
200222

201223
// Scan starts scanning FPGA devices on the host
202224
func (dp *devicePlugin) Scan(notifier dpapi.Notifier) error {
225+
defer dp.scanTicker.Stop()
203226
for {
204227
devTree, err := dp.scanFPGAs()
205228
if err != nil {
@@ -208,7 +231,11 @@ func (dp *devicePlugin) Scan(notifier dpapi.Notifier) error {
208231

209232
notifier.Notify(devTree)
210233

211-
time.Sleep(5 * time.Second)
234+
select {
235+
case <-dp.scanDone:
236+
return nil
237+
case <-dp.scanTicker.C:
238+
}
212239
}
213240
}
214241

@@ -374,7 +401,7 @@ func main() {
374401
modeMessage = ""
375402
}
376403

377-
plugin, err := newDevicePlugin(mode)
404+
plugin, err := newDevicePlugin(mode, "")
378405
if err != nil {
379406
fatal(err)
380407
}

cmd/fpga_plugin/fpga_plugin_test.go

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import (
2525
pluginapi "k8s.io/kubelet/pkg/apis/deviceplugin/v1beta1"
2626

2727
"github.com/intel/intel-device-plugins-for-kubernetes/pkg/debug"
28+
dpapi "github.com/intel/intel-device-plugins-for-kubernetes/pkg/deviceplugin"
2829
)
2930

3031
func init() {
@@ -81,3 +82,157 @@ func TestPostAllocate(t *testing.T) {
8182
t.Fatalf("Set wrong annotation %s", annotation)
8283
}
8384
}
85+
86+
func TestNewDevicePlugin(t *testing.T) {
87+
root, err := ioutil.TempDir("", "test_new_device_plugin")
88+
if err != nil {
89+
t.Fatalf("can't create temporary directory: %+v", err)
90+
}
91+
defer os.RemoveAll(root)
92+
93+
tcases := []struct {
94+
name string
95+
mode string
96+
sysfs string
97+
sysfsdirs []string
98+
expectedErr bool
99+
}{
100+
{
101+
name: "valid OPAE af mode",
102+
mode: afMode,
103+
sysfs: path.Join(root, "sys", "class", "fpga"),
104+
sysfsdirs: []string{"intel-fpga-dev.0"},
105+
expectedErr: false,
106+
},
107+
{
108+
name: "valid DFL af mode",
109+
mode: afMode,
110+
sysfs: path.Join(root, "sys", "class", "fpga_region"),
111+
sysfsdirs: []string{"dfl-port.0"},
112+
expectedErr: false,
113+
},
114+
{
115+
name: "invalid: af mode: driver is not loaded",
116+
mode: afMode,
117+
sysfs: root,
118+
expectedErr: true,
119+
},
120+
{
121+
name: "invalid: region mode: driver is not loaded",
122+
mode: regionMode,
123+
sysfs: root,
124+
expectedErr: true,
125+
},
126+
{
127+
name: "invalid: regionDevel mode: driver is not loaded",
128+
mode: regionDevelMode,
129+
sysfs: root,
130+
expectedErr: true,
131+
},
132+
}
133+
134+
for _, tc := range tcases {
135+
t.Run(tc.name, func(t *testing.T) {
136+
err = createTestDirs("", tc.sysfs, nil, tc.sysfsdirs, nil)
137+
if err != nil {
138+
t.Fatal(err)
139+
}
140+
141+
_, err := newDevicePlugin(tc.mode, root)
142+
if tc.expectedErr && err == nil {
143+
t.Error("unexpected success")
144+
}
145+
if !tc.expectedErr && err != nil {
146+
t.Errorf("unexpected error: %+v", err)
147+
}
148+
149+
err = os.RemoveAll(path.Join(root, "sys"))
150+
if err != nil {
151+
t.Fatalf("Failed to remove fake sysfs directory: %+v", err)
152+
}
153+
})
154+
}
155+
}
156+
157+
// fakeNotifier implements Notifier interface.
158+
type fakeNotifier struct {
159+
scanDone chan bool
160+
}
161+
162+
// Notify stops plugin Scan
163+
func (n *fakeNotifier) Notify(newDeviceTree dpapi.DeviceTree) {
164+
n.scanDone <- true
165+
}
166+
167+
func TestScan(t *testing.T) {
168+
root, err := ioutil.TempDir("", "test_new_device_plugin")
169+
if err != nil {
170+
t.Fatalf("can't create temporary directory: %+v", err)
171+
}
172+
defer os.RemoveAll(root)
173+
174+
devfs := path.Join(root, "dev")
175+
176+
tcases := []struct {
177+
name string
178+
mode string
179+
sysfs string
180+
devfsdirs []string
181+
sysfsdirs []string
182+
sysfsfiles map[string][]byte
183+
expectedErr bool
184+
}{
185+
{
186+
name: "valid OPAE scan",
187+
mode: afMode,
188+
sysfs: path.Join(root, "sys", "class", "fpga"),
189+
sysfsdirs: []string{
190+
"intel-fpga-dev.0/intel-fpga-port.0",
191+
"intel-fpga-dev.0/intel-fpga-fme.0/pr",
192+
"intel-fpga-dev.1/intel-fpga-port.1",
193+
"intel-fpga-dev.1/intel-fpga-fme.1/pr",
194+
},
195+
sysfsfiles: map[string][]byte{
196+
"intel-fpga-dev.0/intel-fpga-port.0/afu_id": []byte("d8424dc4a4a3c413f89e433683f9040b\n"),
197+
"intel-fpga-dev.1/intel-fpga-port.1/afu_id": []byte("d8424dc4a4a3c413f89e433683f9040b\n"),
198+
"intel-fpga-dev.0/intel-fpga-fme.0/pr/interface_id": []byte("ce48969398f05f33946d560708be108a\n"),
199+
"intel-fpga-dev.1/intel-fpga-fme.1/pr/interface_id": []byte("ce48969398f05f33946d560708be108a\n"),
200+
},
201+
devfsdirs: []string{
202+
"intel-fpga-port.0", "intel-fpga-fme.0",
203+
"intel-fpga-port.1", "intel-fpga-fme.1",
204+
},
205+
expectedErr: false,
206+
},
207+
}
208+
209+
for _, tc := range tcases {
210+
t.Run(tc.name, func(t *testing.T) {
211+
err = createTestDirs(devfs, tc.sysfs, tc.devfsdirs, tc.sysfsdirs, tc.sysfsfiles)
212+
if err != nil {
213+
t.Fatal(err)
214+
}
215+
216+
plugin, err := newDevicePlugin(tc.mode, root)
217+
if err != nil {
218+
t.Fatalf("failed to create a device plugin: %+v", err)
219+
}
220+
221+
err = plugin.Scan(&fakeNotifier{plugin.scanDone})
222+
223+
if tc.expectedErr && err == nil {
224+
t.Error("unexpected success")
225+
}
226+
if !tc.expectedErr && err != nil {
227+
t.Errorf("unexpected error: %+v", err)
228+
}
229+
230+
for _, dir := range []string{"sys", "dev"} {
231+
err = os.RemoveAll(path.Join(root, dir))
232+
if err != nil {
233+
t.Fatalf("Failed to remove fake sysfs directory: %+v", err)
234+
}
235+
}
236+
})
237+
}
238+
}

0 commit comments

Comments
 (0)