|
10 | 10 | package pci |
11 | 11 |
|
12 | 12 | import ( |
| 13 | + "context" |
13 | 14 | "encoding/binary" |
14 | 15 | "errors" |
| 16 | + "os" |
| 17 | + "path/filepath" |
15 | 18 | "reflect" |
16 | 19 | "testing" |
| 20 | + |
| 21 | + "github.com/jaypipes/ghw/internal/config" |
| 22 | + "github.com/jaypipes/ghw/pkg/option" |
17 | 23 | ) |
18 | 24 |
|
19 | 25 | // buildVPD assembles a synthetic VPD byte stream from a sequence of |
@@ -211,7 +217,59 @@ func TestDeviceVPDUnavailableForParsedDevice(t *testing.T) { |
211 | 217 | // Info.ParseDevice) must surface ErrVPDUnavailable rather than |
212 | 218 | // trying to read a path-less file. |
213 | 219 | d := &Device{} |
214 | | - if _, err := d.VPD(); !errors.Is(err, ErrVPDUnavailable) { |
| 220 | + if _, err := d.VPD(context.Background()); !errors.Is(err, ErrVPDUnavailable) { |
215 | 221 | t.Errorf("got %v, want ErrVPDUnavailable", err) |
216 | 222 | } |
217 | 223 | } |
| 224 | + |
| 225 | +// TestDeviceVPDHonorsChroot is the regression test for Device.VPD |
| 226 | +// reading the live /sys regardless of option.WithChroot. |
| 227 | +func TestDeviceVPDHonorsChroot(t *testing.T) { |
| 228 | + chroot := t.TempDir() |
| 229 | + const addr = "0000:00:00.0" |
| 230 | + realDir := filepath.Join(chroot, "sys", "devices", "pci0000:00", addr) |
| 231 | + if err := os.MkdirAll(realDir, 0o755); err != nil { |
| 232 | + t.Fatal(err) |
| 233 | + } |
| 234 | + devsDir := filepath.Join(chroot, "sys", "bus", "pci", "devices") |
| 235 | + if err := os.MkdirAll(devsDir, 0o755); err != nil { |
| 236 | + t.Fatal(err) |
| 237 | + } |
| 238 | + const modalias = "pci:v000010DEd000022B1sv00000000sd00000000bc06sc04i00" |
| 239 | + if err := os.WriteFile(filepath.Join(realDir, "modalias"), []byte(modalias+"\n"), 0o644); err != nil { |
| 240 | + t.Fatal(err) |
| 241 | + } |
| 242 | + rel, err := filepath.Rel(devsDir, realDir) |
| 243 | + if err != nil { |
| 244 | + t.Fatal(err) |
| 245 | + } |
| 246 | + if err := os.Symlink(rel, filepath.Join(devsDir, addr)); err != nil { |
| 247 | + t.Fatal(err) |
| 248 | + } |
| 249 | + vpd := buildVPD([]struct { |
| 250 | + tag byte |
| 251 | + body []byte |
| 252 | + }{ |
| 253 | + {vpdTagLargeIdent, []byte("chroot-test")}, |
| 254 | + }) |
| 255 | + if err := os.WriteFile(filepath.Join(realDir, "vpd"), vpd, 0o644); err != nil { |
| 256 | + t.Fatal(err) |
| 257 | + } |
| 258 | + |
| 259 | + ctx := config.ContextFromArgs(option.WithChroot(chroot), config.WithDisableTopology()) |
| 260 | + info, err := New(ctx) |
| 261 | + if err != nil { |
| 262 | + t.Fatalf("pci.New: %v", err) |
| 263 | + } |
| 264 | + if len(info.Devices) != 1 || info.Devices[0].Address != addr { |
| 265 | + t.Fatalf("expected one device at %s, got %+v", addr, info.Devices) |
| 266 | + } |
| 267 | + |
| 268 | + v, err := info.Devices[0].VPD(ctx) |
| 269 | + if err != nil { |
| 270 | + t.Fatalf("VPD: %v", err) |
| 271 | + } |
| 272 | + if v.Identifier != "chroot-test" { |
| 273 | + t.Errorf("got identifier %q, want %q", v.Identifier, "chroot-test") |
| 274 | + } |
| 275 | +} |
0 commit comments