Skip to content

Commit dcd12de

Browse files
tkatilapfl
authored andcommitted
nm: add unit tests
Signed-off-by: Tuomas Katila <[email protected]>
1 parent 7bae673 commit dcd12de

File tree

3 files changed

+232
-5
lines changed

3 files changed

+232
-5
lines changed

cmd/discover/main.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,12 @@ func cmdRun(config *cmdConfig) error {
184184
}
185185

186186
if config.disableNM {
187-
err := nm.DisableNetworkManagerForInterfaces(allInterfaces)
187+
nmapi, err := nm.NewNetworkManager()
188+
if err != nil {
189+
return fmt.Errorf("Failed to create NetworkManager: %v", err)
190+
}
191+
192+
err = nm.DisableNetworkManagerForInterfaces(nmapi, allInterfaces)
188193
if err != nil {
189194
return fmt.Errorf("Failed to disable interfaces in NetworkManager: %v", err)
190195
}

internal/nm/networkmanager.go

Lines changed: 51 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,62 @@ import (
2323
"k8s.io/klog/v2"
2424
)
2525

26-
func DisableNetworkManagerForInterfaces(interfaces []string) error {
26+
type NetworkManagerIf interface {
27+
GetPropertyVersion() (string, error)
28+
GetAllDevices() ([]DeviceWrapperIf, error)
29+
}
30+
31+
type DeviceWrapperIf interface {
32+
GetPropertyInterface() (string, error)
33+
SetPropertyManaged(managed bool) error
34+
}
35+
36+
type DeviceWrapper struct {
37+
device gonetworkmanager.Device
38+
}
39+
40+
type NetworkManager struct {
41+
nm gonetworkmanager.NetworkManager
42+
}
43+
44+
func NewNetworkManager() (NetworkManagerIf, error) {
2745
nm, err := gonetworkmanager.NewNetworkManager()
2846
if err != nil {
29-
// This means that the DBus connection failed.
30-
return err
47+
// Typically means there's no DBus connection
48+
return nil, err
49+
}
50+
return &NetworkManager{nm: nm}, nil
51+
}
52+
53+
func (r *NetworkManager) GetPropertyVersion() (string, error) {
54+
return r.nm.GetPropertyVersion()
55+
}
56+
57+
func (r *NetworkManager) GetAllDevices() ([]DeviceWrapperIf, error) {
58+
devices, err := r.nm.GetAllDevices()
59+
if err != nil {
60+
return nil, err
61+
}
62+
63+
wrappedDevices := make([]DeviceWrapperIf, 0, len(devices))
64+
for _, device := range devices {
65+
wrappedDevices = append(wrappedDevices, &DeviceWrapper{device: device})
3166
}
3267

68+
return wrappedDevices, nil
69+
}
70+
71+
func (d *DeviceWrapper) GetPropertyInterface() (string, error) {
72+
return d.device.GetPropertyInterface()
73+
}
74+
75+
func (d *DeviceWrapper) SetPropertyManaged(managed bool) error {
76+
return d.device.SetPropertyManaged(managed)
77+
}
78+
79+
func DisableNetworkManagerForInterfaces(nm NetworkManagerIf, interfaces []string) error {
3380
// Check if NetworkManager is accessible
34-
_, err = nm.GetPropertyVersion()
81+
_, err := nm.GetPropertyVersion()
3582
if err != nil {
3683
klog.Info("Couldn't read NetworkManager version. It's probably not running.")
3784

internal/nm/networkmanager_test.go

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
/*
2+
* Copyright (C) 2025 Intel Corporation
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package networkmanager
18+
19+
import (
20+
"errors"
21+
"os"
22+
"testing"
23+
)
24+
25+
type MockNetworkManager struct {
26+
mockVersionQuery func() (string, error)
27+
mockGetAllDevices func() ([]DeviceWrapperIf, error)
28+
}
29+
30+
func (m *MockNetworkManager) GetPropertyVersion() (string, error) {
31+
return m.mockVersionQuery()
32+
}
33+
func (m *MockNetworkManager) GetAllDevices() ([]DeviceWrapperIf, error) {
34+
return m.mockGetAllDevices()
35+
}
36+
37+
type MockDevice struct {
38+
mockIface func() (string, error)
39+
mockSetManaged func(bool) error
40+
}
41+
42+
func (d *MockDevice) GetPropertyInterface() (string, error) {
43+
return d.mockIface()
44+
}
45+
func (d *MockDevice) SetPropertyManaged(manage bool) error {
46+
return d.mockSetManaged(manage)
47+
}
48+
49+
// Not sure if this works in CI, but it takes the coverage from ~50% to 90%.
50+
func TestDisableNetworkManagerForInterfacesOnHost(t *testing.T) {
51+
interfaces := []string{"ethXYZ", "ethZYX"}
52+
53+
nm, err := NewNetworkManager()
54+
if nm == nil || err != nil {
55+
t.Fatalf("NewNetworkManager failed")
56+
}
57+
58+
err = DisableNetworkManagerForInterfaces(nm, interfaces)
59+
if err != nil {
60+
t.Errorf("DisableNetworkManagerForInterfaces failed: %v", err)
61+
}
62+
}
63+
64+
func TestDisableNetworkManagerForInterfaces(t *testing.T) {
65+
interfaces := []string{"ethXYZ", "ethZYX"}
66+
67+
nm := &MockNetworkManager{
68+
mockVersionQuery: func() (string, error) {
69+
return "1.0.0", nil
70+
},
71+
mockGetAllDevices: func() ([]DeviceWrapperIf, error) {
72+
return []DeviceWrapperIf{
73+
&MockDevice{
74+
mockIface: func() (string, error) {
75+
return "ethXYZ", nil
76+
},
77+
mockSetManaged: func(manage bool) error {
78+
return nil
79+
},
80+
},
81+
&MockDevice{
82+
mockIface: func() (string, error) {
83+
return "ethZYX", nil
84+
},
85+
mockSetManaged: func(manage bool) error {
86+
return nil
87+
},
88+
},
89+
}, nil
90+
},
91+
}
92+
93+
err := DisableNetworkManagerForInterfaces(nm, interfaces)
94+
if err != nil {
95+
t.Errorf("DisableNetworkManagerForInterfaces failed: %v", err)
96+
}
97+
}
98+
99+
type TestCase struct {
100+
name string
101+
ifaces []string
102+
versionErr error
103+
getDevicesErr error
104+
ifaceErr error
105+
setManagedErr error
106+
expectedErr error
107+
}
108+
109+
var testCases = []TestCase{
110+
{
111+
name: "TestDisableNetworkManagerVersionQueryFails",
112+
versionErr: os.ErrInvalid,
113+
expectedErr: nil,
114+
},
115+
{
116+
name: "TestDisableNetworkManagerGetDevicesFails",
117+
getDevicesErr: os.ErrDeadlineExceeded,
118+
expectedErr: os.ErrDeadlineExceeded,
119+
},
120+
{
121+
name: "TestDisableNetworkManagerGetDeviceInterfaceFails",
122+
ifaces: []string{"ethXYZ", "ethZYX"},
123+
ifaceErr: os.ErrPermission,
124+
expectedErr: os.ErrPermission,
125+
},
126+
{
127+
name: "TestDisableNetworkManagerSetDeviceManagedFails",
128+
ifaces: []string{"ethXYZ", "ethZYX"},
129+
setManagedErr: os.ErrProcessDone,
130+
expectedErr: os.ErrProcessDone,
131+
},
132+
}
133+
134+
func TestDisableNetworkManagerForInterfacesError(t *testing.T) {
135+
interfaces := []string{"ethXYZ", "ethZYX"}
136+
137+
for _, tc := range testCases {
138+
139+
nm := &MockNetworkManager{
140+
mockVersionQuery: func() (string, error) {
141+
return "1.0.0", tc.versionErr
142+
},
143+
mockGetAllDevices: func() ([]DeviceWrapperIf, error) {
144+
if tc.getDevicesErr != nil {
145+
return nil, tc.getDevicesErr
146+
}
147+
148+
ret := []DeviceWrapperIf{}
149+
for _, iface := range tc.ifaces {
150+
ret = append(ret, &MockDevice{
151+
mockIface: func() (string, error) {
152+
if tc.ifaceErr != nil {
153+
return "", tc.ifaceErr
154+
}
155+
return iface, nil
156+
},
157+
mockSetManaged: func(manage bool) error {
158+
if tc.setManagedErr != nil {
159+
return tc.setManagedErr
160+
}
161+
return nil
162+
},
163+
})
164+
}
165+
166+
return ret, nil
167+
},
168+
}
169+
170+
err := DisableNetworkManagerForInterfaces(nm, interfaces)
171+
if !errors.Is(err, tc.expectedErr) {
172+
t.Errorf("%s should have failed: %v", tc.name, err)
173+
}
174+
}
175+
}

0 commit comments

Comments
 (0)