Skip to content

Commit 17052d8

Browse files
committed
test: Improve csv modifier tests
Signed-off-by: Evan Lezar <elezar@nvidia.com>
1 parent da18cef commit 17052d8

2 files changed

Lines changed: 111 additions & 23 deletions

File tree

internal/modifier/cdi/spec.go

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,29 +20,51 @@ import (
2020
"fmt"
2121

2222
"github.com/opencontainers/runtime-spec/specs-go"
23-
"tags.cncf.io/container-device-interface/pkg/cdi"
23+
cdiapi "tags.cncf.io/container-device-interface/pkg/cdi"
24+
cdi "tags.cncf.io/container-device-interface/specs-go"
2425

26+
"github.com/NVIDIA/nvidia-container-toolkit/internal/devices"
2527
"github.com/NVIDIA/nvidia-container-toolkit/internal/oci"
2628
)
2729

2830
// fromCDISpec represents the modifications performed from a raw CDI spec.
2931
type fromCDISpec struct {
30-
cdiSpec *cdi.Spec
32+
cdiSpec *cdiapi.Spec
3133
}
3234

3335
var _ oci.SpecModifier = (*fromCDISpec)(nil)
3436

3537
// Modify applies the mofiications defined by the raw CDI spec to the incomming OCI spec.
3638
func (m fromCDISpec) Modify(spec *specs.Spec) error {
3739
for _, device := range m.cdiSpec.Devices {
38-
device := device
39-
cdiDevice := cdi.Device{
40+
device := m.enrichDevice(device)
41+
cdiDevice := cdiapi.Device{
4042
Device: &device,
4143
}
4244
if err := cdiDevice.ApplyEdits(spec); err != nil {
43-
return fmt.Errorf("failed to apply edits for device %q: %v", cdiDevice.GetQualifiedName(), err)
45+
return fmt.Errorf("failed to apply edits for device %q: %v", m.cdiSpec.Kind+"="+device.Name, err)
4446
}
4547
}
4648

4749
return m.cdiSpec.ApplyEdits(spec)
4850
}
51+
52+
func (m fromCDISpec) enrichDevice(device cdi.Device) cdi.Device {
53+
if !devices.IsOverrideApplied() {
54+
return device
55+
}
56+
// For testing we need to override the device node information to ensure
57+
// that we don't trigger the CDI modification that requires the device node
58+
// to exist and be a character device.
59+
// The following condition is used to determine whether a failure to get
60+
// the info is fatal:
61+
// hasMinimalSpecification := d.Type != "" && (d.Major != 0 || d.Type == fifoDevice)
62+
for i, dn := range device.ContainerEdits.DeviceNodes {
63+
dn.Type = "c"
64+
if dn.Major == 0 {
65+
dn.Major = 99
66+
}
67+
device.ContainerEdits.DeviceNodes[i] = dn
68+
}
69+
return device
70+
}

internal/modifier/csv_test.go

Lines changed: 84 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -17,40 +17,89 @@
1717
package modifier
1818

1919
import (
20+
"path/filepath"
2021
"testing"
2122

23+
"github.com/opencontainers/runtime-spec/specs-go"
2224
testlog "github.com/sirupsen/logrus/hooks/test"
2325
"github.com/stretchr/testify/require"
2426

2527
"github.com/NVIDIA/nvidia-container-toolkit/api/config/v1"
2628
"github.com/NVIDIA/nvidia-container-toolkit/internal/config/image"
29+
"github.com/NVIDIA/nvidia-container-toolkit/internal/devices"
2730
"github.com/NVIDIA/nvidia-container-toolkit/internal/lookup/root"
31+
"github.com/NVIDIA/nvidia-container-toolkit/internal/test"
32+
"github.com/NVIDIA/nvidia-container-toolkit/internal/test/to"
2833
)
2934

3035
func TestNewCSVModifier(t *testing.T) {
3136
logger, _ := testlog.NewNullLogger()
3237

38+
defer devices.SetAllForTest()()
39+
40+
moduleRoot, err := test.GetModuleRoot()
41+
require.NoError(t, err)
42+
43+
lookupRoot := filepath.Join(moduleRoot, "testdata", "lookup")
44+
3345
testCases := []struct {
34-
description string
35-
cfg *config.Config
36-
envmap map[string]string
37-
expectedError error
38-
expectedNil bool
46+
description string
47+
cfg config.Config
48+
envmap map[string]string
49+
driverRootfs string
50+
devRootfs string
51+
expectedErrorString string
52+
expectedSpec specs.Spec
3953
}{
4054
{
4155
description: "visible devices not set returns nil",
4256
envmap: map[string]string{},
43-
expectedNil: true,
4457
},
4558
{
4659
description: "visible devices empty returns nil",
4760
envmap: map[string]string{"NVIDIA_VISIBLE_DEVICES": ""},
48-
expectedNil: true,
4961
},
5062
{
5163
description: "visible devices 'void' returns nil",
5264
envmap: map[string]string{"NVIDIA_VISIBLE_DEVICES": "void"},
53-
expectedNil: true,
65+
},
66+
{
67+
description: "visible devices all",
68+
envmap: map[string]string{"NVIDIA_VISIBLE_DEVICES": "all"},
69+
driverRootfs: "rootfs-orin",
70+
expectedSpec: specs.Spec{
71+
Process: &specs.Process{
72+
Env: []string{"NVIDIA_VISIBLE_DEVICES=void"},
73+
},
74+
Mounts: []specs.Mount{
75+
{Source: "/usr/lib/aarch64-linux-gnu/nvidia/libcuda.so.1.1", Destination: "/usr/lib/aarch64-linux-gnu/nvidia/libcuda.so.1.1", Options: []string{"ro", "nosuid", "nodev", "rbind", "rprivate"}},
76+
{Source: "/usr/lib/aarch64-linux-gnu/nvidia/libnvidia-ml.so.1", Destination: "/usr/lib/aarch64-linux-gnu/nvidia/libnvidia-ml.so.1", Options: []string{"ro", "nosuid", "nodev", "rbind", "rprivate"}},
77+
},
78+
Hooks: &specs.Hooks{
79+
CreateContainer: []specs.Hook{
80+
{
81+
Path: "/usr/bin/nvidia-cdi-hook",
82+
Args: []string{"nvidia-cdi-hook", "create-symlinks", "--link", "libcuda.so.1::/usr/lib/aarch64-linux-gnu/nvidia/libcuda.so"},
83+
Env: []string{"NVIDIA_CTK_DEBUG=false"},
84+
},
85+
{
86+
Path: "/usr/bin/nvidia-cdi-hook",
87+
Args: []string{"nvidia-cdi-hook", "update-ldcache", "--folder", "/usr/lib/aarch64-linux-gnu/nvidia"},
88+
Env: []string{"NVIDIA_CTK_DEBUG=false"},
89+
},
90+
},
91+
},
92+
Linux: &specs.Linux{
93+
Devices: []specs.LinuxDevice{
94+
{Path: "/dev/nvidia0", Type: "c", Major: 99},
95+
},
96+
Resources: &specs.LinuxResources{
97+
Devices: []specs.LinuxDeviceCgroup{
98+
{Allow: true, Type: "c", Major: to.Ptr[int64](99), Minor: to.Ptr[int64](0), Access: "rwm"},
99+
},
100+
},
101+
},
102+
},
54103
},
55104
}
56105

@@ -59,24 +108,41 @@ func TestNewCSVModifier(t *testing.T) {
59108
image, _ := image.New(
60109
image.WithEnvMap(tc.envmap),
61110
)
111+
driverRoot := tc.driverRootfs
112+
if driverRoot != "" {
113+
driverRoot = filepath.Join(lookupRoot, tc.driverRootfs)
114+
}
115+
devRoot := tc.devRootfs
116+
if devRoot != "" {
117+
devRoot = filepath.Join(lookupRoot, tc.devRootfs)
118+
}
119+
driver := root.New(root.WithDriverRoot(driverRoot), root.WithDevRoot(devRoot))
120+
// TODO: We should point to the factory root here.
121+
tc.cfg.NVIDIAContainerCLIConfig.Root = driverRoot
122+
// Override the CSV file search path for this root.
123+
tc.cfg.NVIDIAContainerRuntimeConfig.Modes.CSV.MountSpecPath = filepath.Join(driverRoot, "/etc/nvidia-container-runtime/host-files-for-container.d")
124+
tc.cfg.NVIDIACTKConfig.Path = "/usr/bin/nvidia-cdi-hook"
125+
62126
f := createFactory(
63127
WithLogger(logger),
64-
WithDriver(root.New()),
65-
WithConfig(tc.cfg),
128+
WithDriver(driver),
129+
WithLogger(logger),
130+
WithConfig(&tc.cfg),
66131
WithImage(&image),
67132
)
68133
m, err := f.newCSVModifier()
69-
if tc.expectedError != nil {
70-
require.Error(t, err)
71-
} else {
134+
if tc.expectedErrorString == "" {
72135
require.NoError(t, err)
73-
}
74-
75-
if tc.expectedNil || tc.expectedError != nil {
76-
require.Nil(t, m)
77136
} else {
78-
require.NotNil(t, m)
137+
require.EqualError(t, err, tc.expectedErrorString)
138+
return
79139
}
140+
141+
s := specs.Spec{}
142+
err = list{m}.Modify(&s)
143+
require.NoError(t, err)
144+
145+
require.EqualValues(t, tc.expectedSpec, test.StripRoot(s, driverRoot))
80146
})
81147
}
82148
}

0 commit comments

Comments
 (0)