github.com/mvdan/u-root-coreutils@v0.0.0-20230122170626-c2eef2898555/pkg/boot/grub/config_test.go (about) 1 // Copyright 2017-2020 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 grub 6 7 import ( 8 "bytes" 9 "context" 10 "io" 11 "log" 12 "os" 13 "path/filepath" 14 "strings" 15 "testing" 16 17 "github.com/mvdan/u-root-coreutils/pkg/boot/boottest" 18 "github.com/mvdan/u-root-coreutils/pkg/mount" 19 "github.com/mvdan/u-root-coreutils/pkg/mount/block" 20 ) 21 22 // fakeDevices returns a list of fake block devices and a pool of mount points. 23 // The pool is pre-populated so that Mount is never called. 24 func fakeDevices() (block.BlockDevices, *mount.Pool, error) { 25 // For some reason, Glob("testdata_new/*/") does not work here. 26 files, err := os.ReadDir("testdata_new") 27 if err != nil { 28 return nil, nil, err 29 } 30 dirs := []string{} 31 for _, f := range files { 32 if f.IsDir() { 33 dirs = append(dirs, filepath.Join("testdata_new", f.Name())) 34 } 35 } 36 37 devices := block.BlockDevices{} 38 mountPool := &mount.Pool{} 39 for _, dir := range dirs { 40 // TODO: Also add LABEL to BlockDev 41 fsUUID, _ := os.ReadFile(filepath.Join(dir, "UUID")) 42 devices = append(devices, &block.BlockDev{ 43 Name: dir, 44 FSType: "test", 45 FsUUID: strings.TrimSpace(string(fsUUID)), 46 }) 47 mountPool.Add(&mount.MountPoint{ 48 Path: dir, 49 Device: filepath.Join("/dev", dir), 50 FSType: "test", 51 }) 52 } 53 return devices, mountPool, nil 54 } 55 56 // Enable this to generate new configs. 57 func DISABLEDTestGenerateConfigs(t *testing.T) { 58 tests, err := filepath.Glob("testdata_new/*.json") 59 if err != nil { 60 t.Error("Failed to find test config files:", err) 61 } 62 63 for _, test := range tests { 64 configPath := strings.TrimSuffix(test, ".json") 65 t.Run(configPath, func(t *testing.T) { 66 devices, mountPool, err := fakeDevices() 67 if err != nil { 68 t.Fatal(err) 69 } 70 imgs, err := ParseLocalConfig(context.Background(), configPath, devices, mountPool) 71 if err != nil { 72 t.Fatalf("Failed to parse %s: %v", test, err) 73 } 74 75 if err := boottest.ToJSONFile(imgs, test); err != nil { 76 t.Errorf("failed to generate file: %v", err) 77 } 78 }) 79 } 80 } 81 82 func TestConfigs(t *testing.T) { 83 // find all saved configs 84 tests, err := filepath.Glob("testdata_new/*.json") 85 if err != nil { 86 t.Error("Failed to find test config files:", err) 87 } 88 89 for _, test := range tests { 90 configPath := strings.TrimSuffix(test, ".json") 91 t.Run(configPath, func(t *testing.T) { 92 want, err := os.ReadFile(test) 93 if err != nil { 94 t.Errorf("Failed to read test json '%v':%v", test, err) 95 } 96 97 devices, mountPool, err := fakeDevices() 98 if err != nil { 99 t.Fatal(err) 100 } 101 imgs, err := ParseLocalConfig(context.Background(), configPath, devices, mountPool) 102 if err != nil { 103 t.Fatalf("Failed to parse %s: %v", test, err) 104 } 105 106 if err := boottest.CompareImagesToJSON(imgs, want); err != nil { 107 t.Errorf("ParseLocalConfig(): %v", err) 108 } 109 }) 110 } 111 } 112 113 func FuzzParseGrubConfig(f *testing.F) { 114 115 baseDir := f.TempDir() 116 117 dirPath := filepath.Join(baseDir, "EFI", "uefi") 118 err := os.MkdirAll(dirPath, 0o777) 119 if err != nil { 120 f.Fatalf("failed %v: %v", dirPath, err) 121 } 122 123 path := filepath.Join(dirPath, "grub.cfg") 124 devices := block.BlockDevices{&block.BlockDev{ 125 Name: dirPath, 126 FSType: "test", 127 FsUUID: strings.TrimSpace("07338180-4a96-4611-aa6a-a452600e4cfe"), 128 }} 129 mountPool := &mount.Pool{} 130 mountPool.Add(&mount.MountPoint{ 131 Path: dirPath, 132 Device: filepath.Join("/dev", dirPath), 133 FSType: "test", 134 }) 135 136 //no log output 137 log.SetOutput(io.Discard) 138 log.SetFlags(0) 139 140 // get seed corpora from testdata_new files 141 seeds, err := filepath.Glob("testdata_new/*/*/*/grub.cfg") 142 if err != nil { 143 f.Fatalf("failed to find seed corpora files: %v", err) 144 } 145 146 seeds2, err := filepath.Glob("testdata_new/*/*/grub.cfg") 147 if err != nil { 148 f.Fatalf("failed to find seed corpora files: %v", err) 149 } 150 151 seeds = append(seeds, seeds2...) 152 for _, seed := range seeds { 153 seedBytes, err := os.ReadFile(seed) 154 if err != nil { 155 f.Fatalf("failed read seed corpora from files %v: %v", seed, err) 156 } 157 158 f.Add(seedBytes) 159 } 160 161 f.Add([]byte("multiBoot 0\nmodule --nounzip")) 162 f.Fuzz(func(t *testing.T, data []byte) { 163 if len(data) > 4096 { 164 return 165 } 166 167 // do not allow arbitrary files reads 168 if bytes.Contains(data, []byte("include")) { 169 return 170 } 171 172 err = os.WriteFile(path, data, 0o777) 173 if err != nil { 174 t.Fatalf("Failed to create configfile '%v':%v", path, err) 175 } 176 177 ParseLocalConfig(context.Background(), baseDir, devices, mountPool) 178 }) 179 }