github.com/mvdan/u-root-coreutils@v0.0.0-20230122170626-c2eef2898555/pkg/efivarfs/varfs_test.go (about) 1 // Copyright 2022 the u-root Authors. All rights reserved 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package efivarfs 6 7 import ( 8 "bytes" 9 "encoding/binary" 10 "errors" 11 "os" 12 "path/filepath" 13 "strings" 14 "testing" 15 16 guid "github.com/google/uuid" 17 ) 18 19 func TestProbeAndReturn(t *testing.T) { 20 for _, tt := range []struct { 21 name string 22 path string 23 wantErr error 24 }{ 25 { 26 name: "wrong magic", 27 path: "/tmp", 28 wantErr: ErrNoFS, 29 }, 30 { 31 name: "wrong directory", 32 path: "/bogus", 33 wantErr: ErrNoFS, 34 }, 35 } { 36 t.Run(tt.name, func(t *testing.T) { 37 if _, err := NewPath(tt.path); !errors.Is(err, tt.wantErr) { 38 t.Errorf("Unexpected error: %v", err) 39 } 40 }) 41 } 42 } 43 44 func TestGet(t *testing.T) { 45 for _, tt := range []struct { 46 name string 47 vd VariableDescriptor 48 attr VariableAttributes 49 data []byte 50 setup func(path string, t *testing.T) 51 wantErr error 52 }{ 53 { 54 name: "get var", 55 vd: VariableDescriptor{ 56 Name: "TestVar", 57 GUID: func() guid.UUID { 58 g := guid.MustParse("bc54d3fb-ed45-462d-9df8-b9f736228350") 59 return g 60 }(), 61 }, 62 attr: AttributeNonVolatile, 63 data: []byte("testdata"), 64 setup: func(path string, t *testing.T) { 65 t.Helper() 66 f := createTestVar(path, "TestVar-bc54d3fb-ed45-462d-9df8-b9f736228350", t) 67 var buf bytes.Buffer 68 if err := binary.Write(&buf, binary.LittleEndian, AttributeNonVolatile); err != nil { 69 t.Errorf("Failed writing bytes: %v", err) 70 } 71 if _, err := buf.Write([]byte("testdata")); err != nil { 72 t.Errorf("Failed writing data: %v", err) 73 } 74 if _, err := buf.WriteTo(f); err != nil { 75 t.Errorf("Failed writing to file: %v", err) 76 } 77 if err := f.Close(); err != nil { 78 t.Errorf("Failed to close file: %v", err) 79 } 80 }, 81 wantErr: nil, 82 }, 83 { 84 name: "not exist", 85 vd: VariableDescriptor{ 86 Name: "TestVar", 87 GUID: func() guid.UUID { 88 g := guid.MustParse("bc54d3fb-ed45-462d-9df8-b9f736228350") 89 return g 90 }(), 91 }, 92 attr: 0, 93 data: nil, 94 setup: func(path string, t *testing.T) { t.Helper() }, 95 wantErr: ErrVarNotExist, 96 }, 97 /* TODO: this test seems utterly broken. I have no idea why it ever seemed it might work. 98 { 99 name: "no permission", 100 vd: VariableDescriptor{ 101 Name: "TestVar", 102 GUID: func() *guid.UUID { 103 g := guid.MustParse("bc54d3fb-ed45-462d-9df8-b9f736228350") 104 return &g 105 }(), 106 }, 107 attr: 0, 108 data: nil, 109 setup: func(path string, t *testing.T) { 110 t.Helper() 111 f := createTestVar(path, "TestVar-bc54d3fb-ed45-462d-9df8-b9f736228350", t) 112 if err := f.Chmod(0222); err != nil { 113 t.Errorf("Failed changing permissions: %v", err) 114 } 115 if err := f.Close(); err != nil { 116 t.Errorf("Failed to close file: %v", err) 117 } 118 }, 119 wantErr: ErrVarPermission, 120 }, 121 */ 122 { 123 name: "var empty", 124 vd: VariableDescriptor{ 125 Name: "TestVar", 126 GUID: func() guid.UUID { 127 g := guid.MustParse("bc54d3fb-ed45-462d-9df8-b9f736228350") 128 return g 129 }(), 130 }, 131 attr: 0, 132 data: nil, 133 setup: func(path string, t *testing.T) { 134 t.Helper() 135 if err := createTestVar(path, "TestVar-bc54d3fb-ed45-462d-9df8-b9f736228350", t).Close(); err != nil { 136 t.Errorf("Failed to close file: %v", err) 137 } 138 }, 139 wantErr: ErrVarNotExist, 140 }, 141 } { 142 t.Run(tt.name, func(t *testing.T) { 143 tmp := t.TempDir() 144 tt.setup(tmp, t) 145 // This setup bypasses all the tests for this fake varfs. 146 e := &EFIVarFS{path: tmp} 147 148 attr, data, err := e.Get(tt.vd) 149 if errors.Is(err, ErrNoFS) { 150 t.Logf("no EFIVarFS: %v; skipping this test", err) 151 return 152 } 153 if !errors.Is(err, tt.wantErr) { 154 t.Errorf("Expected: %q, got: %v", tt.wantErr, err) 155 } 156 if attr != tt.attr { 157 t.Errorf("Want %v, Got: %v", tt.attr, attr) 158 } 159 if !bytes.Equal(data, tt.data) { 160 t.Errorf("Want: %v, Got: %v", tt.data, data) 161 } 162 }) 163 } 164 } 165 166 func TestSet(t *testing.T) { 167 for _, tt := range []struct { 168 name string 169 vd VariableDescriptor 170 attr VariableAttributes 171 data []byte 172 setup func(path string, t *testing.T) 173 wantErr error 174 }{ 175 { 176 name: "set var", 177 vd: VariableDescriptor{ 178 Name: "TestVar", 179 GUID: func() guid.UUID { 180 g := guid.MustParse("bc54d3fb-ed45-462d-9df8-b9f736228350") 181 return g 182 }(), 183 }, 184 attr: 0, 185 data: nil, 186 setup: func(path string, t *testing.T) { t.Helper() }, 187 wantErr: nil, 188 }, 189 { 190 name: "append write", 191 vd: VariableDescriptor{ 192 Name: "TestVar", 193 GUID: func() guid.UUID { 194 g := guid.MustParse("bc54d3fb-ed45-462d-9df8-b9f736228350") 195 return g 196 }(), 197 }, 198 attr: AttributeAppendWrite, 199 data: nil, 200 setup: func(path string, t *testing.T) { t.Helper() }, 201 wantErr: nil, 202 }, 203 { 204 name: "no read permission", 205 vd: VariableDescriptor{ 206 Name: "TestVar", 207 GUID: func() guid.UUID { 208 g := guid.MustParse("bc54d3fb-ed45-462d-9df8-b9f736228350") 209 return g 210 }(), 211 }, 212 attr: 0, 213 data: nil, 214 setup: func(path string, t *testing.T) { 215 t.Helper() 216 f := createTestVar(path, "TestVar-bc54d3fb-ed45-462d-9df8-b9f736228350", t) 217 if err := f.Chmod(0222); err != nil { 218 t.Errorf("Failed changing permissions: %v", err) 219 } 220 if err := f.Close(); err != nil { 221 t.Errorf("Failed to close file: %v", err) 222 } 223 }, 224 wantErr: ErrVarPermission, 225 }, 226 { 227 name: "var exists", 228 vd: VariableDescriptor{ 229 Name: "TestVar", 230 GUID: func() guid.UUID { 231 g := guid.MustParse("bc54d3fb-ed45-462d-9df8-b9f736228350") 232 return g 233 }(), 234 }, 235 attr: 0, 236 data: nil, 237 setup: func(path string, t *testing.T) { 238 t.Helper() 239 f := createTestVar(path, "TestVar-bc54d3fb-ed45-462d-9df8-b9f736228350", t) 240 if err := f.Close(); err != nil { 241 t.Errorf("Failed to close file: %v", err) 242 } 243 }, 244 wantErr: errors.New("inappropriate ioctl for device"), 245 }, 246 { 247 name: "input data", 248 vd: VariableDescriptor{ 249 Name: "TestVar", 250 GUID: func() guid.UUID { 251 g := guid.MustParse("bc54d3fb-ed45-462d-9df8-b9f736228350") 252 return g 253 }(), 254 }, 255 attr: 0, 256 data: []byte("tests"), 257 setup: func(path string, t *testing.T) { t.Helper() }, 258 wantErr: nil, 259 }, 260 } { 261 t.Run(tt.name, func(t *testing.T) { 262 tmp := t.TempDir() 263 tt.setup(tmp, t) 264 // This setup bypasses all the tests for this fake varfs. 265 e := &EFIVarFS{path: tmp} 266 267 if err := e.Set(tt.vd, tt.attr, tt.data); err != nil { 268 if !errors.Is(err, tt.wantErr) { 269 // Needed as some errors include changing tmp directory names 270 if !strings.Contains(err.Error(), tt.wantErr.Error()) { 271 t.Errorf("Want: %v, Got: %v", tt.wantErr, err) 272 } 273 } 274 } 275 }) 276 } 277 } 278 279 func TestRemove(t *testing.T) { 280 for _, tt := range []struct { 281 name string 282 vd VariableDescriptor 283 setup func(path string, t *testing.T) 284 wantErr error 285 }{ 286 { 287 name: "remove var", 288 vd: VariableDescriptor{ 289 Name: "TestVar", 290 GUID: func() guid.UUID { 291 g := guid.MustParse("bc54d3fb-ed45-462d-9df8-b9f736228350") 292 return g 293 }(), 294 }, 295 setup: func(path string, t *testing.T) { 296 t.Helper() 297 if err := createTestVar(path, "TestVar-bc54d3fb-ed45-462d-9df8-b9f736228350", t).Close(); err != nil { 298 t.Errorf("Failed to close file: %v", err) 299 } 300 }, 301 wantErr: errors.New("inappropriate ioctl for device"), 302 }, 303 { 304 name: "no permission", 305 vd: VariableDescriptor{ 306 Name: "TestVar", 307 GUID: func() guid.UUID { 308 g := guid.MustParse("bc54d3fb-ed45-462d-9df8-b9f736228350") 309 return g 310 }(), 311 }, 312 setup: func(path string, t *testing.T) { 313 t.Helper() 314 f := createTestVar(path, "TestVar-bc54d3fb-ed45-462d-9df8-b9f736228350", t) 315 if err := f.Chmod(0444); err != nil { 316 t.Errorf("Failed changing permissions: %v", err) 317 } 318 if err := f.Close(); err != nil { 319 t.Errorf("Failed to close file: %v", err) 320 } 321 }, 322 wantErr: ErrVarPermission, 323 }, 324 { 325 name: "var not exist", 326 vd: VariableDescriptor{ 327 Name: "TestVar", 328 GUID: func() guid.UUID { 329 g := guid.MustParse("bc54d3fb-ed45-462d-9df8-b9f736228350") 330 return g 331 }(), 332 }, 333 setup: func(path string, t *testing.T) { t.Helper() }, 334 wantErr: ErrVarNotExist, 335 }, 336 } { 337 t.Run(tt.name, func(t *testing.T) { 338 tmp := t.TempDir() 339 tt.setup(tmp, t) 340 // This setup bypasses all the tests for this fake varfs. 341 e := &EFIVarFS{path: tmp} 342 343 if err := e.Remove(tt.vd); err != nil { 344 if !errors.Is(err, tt.wantErr) { 345 // Needed as some errors include changing tmp directory names 346 if !strings.Contains(err.Error(), tt.wantErr.Error()) { 347 t.Errorf("Want: %v, Got: %v", tt.wantErr, err) 348 } 349 } 350 } 351 }) 352 } 353 } 354 355 func TestList(t *testing.T) { 356 for _, tt := range []struct { 357 name string 358 vd VariableDescriptor 359 dir string 360 setup func(path string, t *testing.T) 361 wantErr error 362 }{ 363 { 364 name: "empty var", 365 vd: VariableDescriptor{ 366 Name: "TestVar", 367 GUID: func() guid.UUID { 368 g := guid.MustParse("bc54d3fb-ed45-462d-9df8-b9f736228350") 369 return g 370 }(), 371 }, 372 dir: t.TempDir(), 373 setup: func(path string, t *testing.T) { 374 t.Helper() 375 if err := createTestVar(path, "TestVar-bc54d3fb-ed45-462d-9df8-b9f736228350", t).Close(); err != nil { 376 t.Errorf("Failed to close file: %v", err) 377 } 378 }, 379 wantErr: nil, 380 }, 381 { 382 name: "var with data", 383 vd: VariableDescriptor{ 384 Name: "TestVar", 385 GUID: func() guid.UUID { 386 g := guid.MustParse("bc54d3fb-ed45-462d-9df8-b9f736228350") 387 return g 388 }(), 389 }, 390 dir: t.TempDir(), 391 setup: func(path string, t *testing.T) { 392 t.Helper() 393 f := createTestVar(path, "TestVar-bc54d3fb-ed45-462d-9df8-b9f736228350", t) 394 var buf bytes.Buffer 395 if err := binary.Write(&buf, binary.LittleEndian, AttributeNonVolatile); err != nil { 396 t.Errorf("Failed writing bytes: %v", err) 397 } 398 if _, err := buf.Write([]byte("testdata")); err != nil { 399 t.Errorf("Failed writing data: %v", err) 400 } 401 if _, err := buf.WriteTo(f); err != nil { 402 t.Errorf("Failed writing to file: %v", err) 403 } 404 if err := f.Close(); err != nil { 405 t.Errorf("Failed to close file: %v", err) 406 } 407 }, 408 wantErr: nil, 409 }, 410 { 411 name: "no regular files", 412 vd: VariableDescriptor{ 413 Name: "TestVar", 414 GUID: func() guid.UUID { 415 g := guid.MustParse("bc54d3fb-ed45-462d-9df8-b9f736228350") 416 return g 417 }(), 418 }, 419 dir: t.TempDir(), 420 setup: func(path string, t *testing.T) { 421 t.Helper() 422 if err := os.Mkdir(filepath.Join(path, "testdir"), 0644); err != nil { 423 t.Errorf("Failed to create directory: %v", err) 424 } 425 }, 426 wantErr: nil, 427 }, 428 { 429 name: "no permission", 430 vd: VariableDescriptor{ 431 Name: "TestVar", 432 GUID: func() guid.UUID { 433 g := guid.MustParse("bc54d3fb-ed45-462d-9df8-b9f736228350") 434 return g 435 }(), 436 }, 437 dir: t.TempDir(), 438 setup: func(path string, t *testing.T) { 439 t.Helper() 440 if err := os.Chmod(path, 0222); err != nil { 441 t.Errorf("Failed changing permissions: %v", err) 442 } 443 }, 444 wantErr: ErrVarPermission, 445 }, 446 { 447 name: "no dir", 448 vd: VariableDescriptor{ 449 Name: "TestVar", 450 GUID: func() guid.UUID { 451 g := guid.MustParse("bc54d3fb-ed45-462d-9df8-b9f736228350") 452 return g 453 }(), 454 }, 455 dir: "/bogus", 456 setup: func(path string, t *testing.T) { t.Helper() }, 457 wantErr: ErrVarNotExist, 458 }, 459 { 460 name: "malformed vars", 461 vd: VariableDescriptor{ 462 Name: "TestVar", 463 GUID: func() guid.UUID { 464 g := guid.MustParse("bc54d3fb-ed45-462d-9df8-b9f736228350") 465 return g 466 }(), 467 }, 468 dir: t.TempDir(), 469 setup: func(path string, t *testing.T) { 470 t.Helper() 471 if err := createTestVar(path, "TestVar-bc54d3fb-ed45-462d-9df8-b9f7362283500000", t).Close(); err != nil { 472 t.Errorf("Failed to close file: %v", err) 473 } 474 if err := createTestVar(path, "TestVar-bc54d3fb-ed45-462d-9df8-b", t).Close(); err != nil { 475 t.Errorf("Failed to close file: %v", err) 476 } 477 }, 478 wantErr: nil, 479 }, 480 } { 481 t.Run(tt.name, func(t *testing.T) { 482 tmp := t.TempDir() 483 tt.setup(tt.dir, t) 484 // This setup bypasses all the tests for this fake varfs. 485 e := &EFIVarFS{path: tmp} 486 487 if _, err := e.List(); err != nil { 488 if !errors.Is(err, tt.wantErr) { 489 // Needed as some errors include changing tmp directory names 490 if !strings.Contains(err.Error(), tt.wantErr.Error()) { 491 t.Errorf("Want: %v, Got: %v", tt.wantErr, err) 492 } 493 } 494 } 495 }) 496 } 497 } 498 499 func createTestVar(path, varFullName string, t *testing.T) *os.File { 500 t.Helper() 501 f, err := os.Create(filepath.Join(path, varFullName)) 502 if err != nil { 503 t.Errorf("Failed creating test var: %v", err) 504 } 505 return f 506 } 507 508 func TestNew(t *testing.T) { 509 // the EFI file system may not be available, but we call New 510 // anyway to at least get some coverage. 511 e, err := New() 512 t.Logf("New(): %v, %v", e, err) 513 }