github.com/mvdan/u-root-coreutils@v0.0.0-20230122170626-c2eef2898555/pkg/boot/esxi/esxi_test.go (about) 1 // Copyright 2019 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 esxi 6 7 import ( 8 "encoding/hex" 9 "fmt" 10 "os" 11 "path/filepath" 12 "reflect" 13 "testing" 14 15 "github.com/mvdan/u-root-coreutils/pkg/boot" 16 "github.com/mvdan/u-root-coreutils/pkg/boot/multiboot" 17 "github.com/mvdan/u-root-coreutils/pkg/uio" 18 ) 19 20 func TestParse(t *testing.T) { 21 for _, tt := range []struct { 22 file string 23 want options 24 }{ 25 { 26 file: "testdata/kernel_cmdline_mods.cfg", 27 want: options{ 28 title: "VMware ESXi", 29 kernel: "testdata/b.b00", 30 args: "b.b00 zee", 31 modules: []module{ 32 { 33 path: "testdata/b.b00", 34 cmdline: "b.b00 blabla", 35 }, 36 { 37 path: "testdata/k.b00", 38 cmdline: "k.b00", 39 }, 40 { 41 path: "testdata/m.m00", 42 cmdline: "m.m00 marg marg2", 43 }, 44 }, 45 }, 46 }, 47 { 48 file: "testdata/kernelopt_first.cfg", 49 want: options{ 50 title: "VMware ESXi", 51 kernel: "testdata/b.b00", 52 args: "b.b00 zee", 53 }, 54 }, 55 { 56 file: "testdata/empty_mods.cfg", 57 want: options{ 58 title: "VMware ESXi", 59 kernel: "testdata/b.b00", 60 args: "b.b00 zee", 61 }, 62 }, 63 { 64 file: "testdata/no_mods.cfg", 65 want: options{ 66 title: "VMware ESXi", 67 kernel: "testdata/b.b00", 68 args: "b.b00 zee", 69 }, 70 }, 71 { 72 file: "testdata/no_cmdline.cfg", 73 want: options{ 74 title: "VMware ESXi", 75 kernel: "testdata/b.b00", 76 args: "b.b00 ", 77 }, 78 }, 79 { 80 file: "testdata/empty_cmdline.cfg", 81 want: options{ 82 title: "VMware ESXi", 83 kernel: "testdata/b.b00", 84 args: "b.b00 ", 85 }, 86 }, 87 { 88 file: "testdata/empty_updated.cfg", 89 want: options{ 90 title: "VMware ESXi", 91 kernel: "testdata/b.b00", 92 args: "b.b00 zee", 93 // Explicitly stating this as the wanted value. 94 updated: 0, 95 }, 96 }, 97 { 98 file: "testdata/updated_twice.cfg", 99 want: options{ 100 title: "VMware ESXi", 101 kernel: "testdata/b.b00", 102 args: "b.b00 zee", 103 // Explicitly stating this as the wanted value. 104 updated: 0, 105 }, 106 }, 107 { 108 file: "testdata/updated.cfg", 109 want: options{ 110 title: "VMware ESXi", 111 kernel: "testdata/b.b00", 112 args: "b.b00 zee", 113 updated: 4, 114 }, 115 }, 116 { 117 file: "testdata/empty_bootstate.cfg", 118 want: options{ 119 title: "VMware ESXi", 120 kernel: "testdata/b.b00", 121 args: "b.b00 zee", 122 // Explicitly stating this as the wanted value. 123 bootstate: bootValid, 124 }, 125 }, 126 { 127 file: "testdata/bootstate_twice.cfg", 128 want: options{ 129 title: "VMware ESXi", 130 kernel: "testdata/b.b00", 131 args: "b.b00 zee", 132 // Explicitly stating this as the wanted value. 133 bootstate: bootValid, 134 }, 135 }, 136 { 137 file: "testdata/bootstate.cfg", 138 want: options{ 139 title: "VMware ESXi", 140 kernel: "testdata/b.b00", 141 args: "b.b00 zee", 142 bootstate: bootDirty, 143 }, 144 }, 145 { 146 file: "testdata/bootstate_invalid.cfg", 147 want: options{ 148 title: "VMware ESXi", 149 kernel: "testdata/b.b00", 150 args: "b.b00 zee", 151 bootstate: bootInvalid, 152 }, 153 }, 154 { 155 file: "testdata/no_bootstate.cfg", 156 want: options{ 157 title: "VMware ESXi", 158 kernel: "testdata/b.b00", 159 args: "b.b00 zee", 160 bootstate: bootInvalid, 161 }, 162 }, 163 } { 164 got, err := parse(tt.file) 165 if err != nil { 166 t.Fatalf("cannot parse config at %s: %v", tt.file, err) 167 } 168 169 if !reflect.DeepEqual(got, tt.want) { 170 t.Errorf("LoadConfig(%s) = %#v want %#v", tt.file, got, tt.want) 171 } 172 } 173 } 174 175 // This is in the second block of testdata/dev5 and testdata/dev6. 176 var ( 177 dev5GUID = "aabbccddeeff0011" 178 dev6GUID = "00112233445566aa" 179 uuid5 = hex.EncodeToString([]byte(dev5GUID)) 180 uuid6 = hex.EncodeToString([]byte(dev6GUID)) 181 device = "testdata/dev" 182 ) 183 184 // Poor man's equal. 185 // 186 // the Kernel and Modules fields will be full of uio.NewLazyFiles. We just want 187 // them to be pointing to the same file name; we can't compare the function 188 // pointers obviously. Lazy files will always print their name. 189 func multibootEqual(a, b []*boot.MultibootImage) bool { 190 return fmt.Sprintf("%v", a) == fmt.Sprintf("%v", b) 191 } 192 193 func TestDev5Valid(t *testing.T) { 194 want := []*boot.MultibootImage{ 195 { 196 Name: "VMware ESXi from testdata/dev5", 197 Kernel: uio.NewLazyFile("testdata/k"), 198 Cmdline: fmt.Sprintf(" bootUUID=%s", uuid5), 199 Modules: []multiboot.Module{}, 200 }, 201 } 202 203 opts5 := &options{ 204 title: "VMware ESXi", 205 kernel: "testdata/k", 206 updated: 1, 207 bootstate: bootValid, 208 } 209 210 // No opts6 at all. 211 imgs, _ := getImages(device, opts5, nil) 212 if !multibootEqual(imgs, want) { 213 t.Fatalf("getImages(%s, %v, %v) = %v, want %v", device, opts5, nil, imgs, want) 214 } 215 216 // Invalid opts6. Higher updated, but invalid state. 217 invalidOpts6 := &options{ 218 title: "VMware ESXi", 219 kernel: "foobar", 220 updated: 2, 221 bootstate: bootInvalid, 222 } 223 imgs, _ = getImages(device, opts5, invalidOpts6) 224 if !multibootEqual(imgs, want) { 225 t.Fatalf("getImages(%s, %v, %v) = %v, want %v", device, opts5, invalidOpts6, imgs, want) 226 } 227 } 228 229 func TestDev6Valid(t *testing.T) { 230 want := []*boot.MultibootImage{ 231 { 232 Name: "VMware ESXi from testdata/dev6", 233 Kernel: uio.NewLazyFile("testdata/k"), 234 Cmdline: fmt.Sprintf(" bootUUID=%s", uuid6), 235 Modules: []multiboot.Module{}, 236 }, 237 } 238 239 opts6 := &options{ 240 title: "VMware ESXi", 241 kernel: "testdata/k", 242 updated: 1, 243 bootstate: bootValid, 244 } 245 246 // No opts5 at all. 247 imgs, err := getImages(device, nil, opts6) 248 if !multibootEqual(imgs, want) { 249 t.Fatalf("getImages(%s, %v, %v) = %v, want %v (err %v)", device, nil, opts6, imgs, want, err) 250 } 251 252 // Invalid opts5. Higher updated, but invalid state. 253 invalidOpts5 := &options{ 254 title: "VMware ESXi", 255 kernel: "foobar", 256 updated: 2, 257 bootstate: bootInvalid, 258 } 259 imgs, _ = getImages(device, invalidOpts5, opts6) 260 if !multibootEqual(imgs, want) { 261 t.Fatalf("getImages(%s, %v, %v) = %v, want %v", device, invalidOpts5, opts6, imgs, want) 262 } 263 } 264 265 func TestImageOrder(t *testing.T) { 266 prevGetBlockSize := getBlockSize 267 defer func() { 268 getBlockSize = prevGetBlockSize 269 }() 270 getBlockSize = func(dev string) (int, error) { 271 return 512, nil 272 } 273 274 opt5 := &options{ 275 title: "VMware ESXi", 276 kernel: "foobar", 277 updated: 2, 278 bootstate: bootValid, 279 } 280 want5 := &boot.MultibootImage{ 281 Name: "VMware ESXi from testdata/dev5", 282 Kernel: uio.NewLazyFile("foobar"), 283 Cmdline: fmt.Sprintf(" bootUUID=%s", uuid5), 284 Modules: []multiboot.Module{}, 285 } 286 287 opt6 := &options{ 288 title: "VMware ESXi", 289 kernel: "testdata/k", 290 updated: 1, 291 bootstate: bootValid, 292 } 293 want6 := &boot.MultibootImage{ 294 Name: "VMware ESXi from testdata/dev6", 295 Kernel: uio.NewLazyFile("testdata/k"), 296 Cmdline: fmt.Sprintf(" bootUUID=%s", uuid6), 297 Modules: []multiboot.Module{}, 298 } 299 300 // Way 1. 301 want := []*boot.MultibootImage{want5, want6} 302 imgs, _ := getImages(device, opt5, opt6) 303 if !multibootEqual(imgs, want) { 304 t.Fatalf("getImages(%s, %v, %v) = %v, want %v", device, opt5, opt6, imgs, want) 305 } 306 307 opt5.updated = 1 308 opt6.updated = 2 309 // Vice versa priority. 310 want = []*boot.MultibootImage{want6, want5} 311 imgs, _ = getImages(device, opt5, opt6) 312 if !multibootEqual(imgs, want) { 313 t.Fatalf("getImages(%s, %v, %v) = %v, want %v", device, opt5, opt6, imgs, want) 314 } 315 } 316 317 func FuzzParse(f *testing.F) { 318 seeds, err := filepath.Glob("testdata/*.cfg") 319 if err != nil { 320 f.Fatalf("failed to find seed corpora files: %v", err) 321 } 322 for _, seed := range seeds { 323 seedBytes, err := os.ReadFile(seed) 324 if err != nil { 325 f.Fatalf("failed read seed corpora from files %v: %v", seed, err) 326 } 327 328 f.Add(seedBytes) 329 } 330 f.Fuzz(func(t *testing.T, data []byte) { 331 if len(data) > 4096 { 332 return 333 } 334 335 parse(string(data)) 336 }) 337 }