github.com/insomniacslk/u-root@v0.0.0-20200717035308-96b791510d76/pkg/mount/mount_linux_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 mount_test 6 7 import ( 8 "io/ioutil" 9 "os" 10 "path/filepath" 11 "reflect" 12 "strings" 13 "syscall" 14 "testing" 15 16 "github.com/rekby/gpt" 17 "github.com/u-root/u-root/pkg/mount" 18 "github.com/u-root/u-root/pkg/mount/block" 19 "github.com/u-root/u-root/pkg/mount/scuzz" 20 "github.com/u-root/u-root/pkg/testutil" 21 ) 22 23 // Assumptions: 24 // 25 // /dev/sda is ./testdata/1MB.ext4_vfat 26 // /dev/sda1 is ext4 27 // /dev/sda2 is vfat 28 // 29 // /dev/sdb is ./testdata/12Kzeros 30 // /dev/sdb1 exists, but is not formatted. 31 // 32 // /dev/sdc is ./testdata/gptdisk 33 // /dev/sdc1 exists (EFI system partition), but is not formatted 34 // /dev/sdc2 exists (Linux), but is not formatted 35 36 func TestGPT(t *testing.T) { 37 testutil.SkipIfNotRoot(t) 38 39 sdcDisk, err := block.Device("/dev/sdc") 40 if err != nil { 41 t.Fatal(err) 42 } 43 44 parts, err := sdcDisk.GPTTable() 45 if err != nil { 46 t.Fatal(err) 47 } 48 wantParts := []gpt.Partition{ 49 {FirstLBA: 34, LastLBA: 200}, 50 {FirstLBA: 201, LastLBA: 366}, 51 } 52 for i, p := range parts.Partitions { 53 if !p.IsEmpty() { 54 want := wantParts[i] 55 if p.FirstLBA != want.FirstLBA { 56 t.Errorf("partition %d: got FirstLBA %d want %d", i, p.FirstLBA, want.FirstLBA) 57 } 58 if p.LastLBA != want.LastLBA { 59 t.Errorf("partition %d: got LastLBA %d want %d", i, p.LastLBA, want.LastLBA) 60 } 61 62 t.Logf("partition: %v", p) 63 } 64 } 65 } 66 67 func TestFilterPartID(t *testing.T) { 68 testutil.SkipIfNotRoot(t) 69 70 devs, err := block.GetBlockDevices() 71 if err != nil { 72 t.Fatal(err) 73 } 74 devs = devs.FilterZeroSize() 75 76 for _, tt := range []struct { 77 guid string 78 want block.BlockDevices 79 }{ 80 { 81 guid: "C9865081-266C-4A23-A948-C03DAB506198", 82 want: block.BlockDevices{ 83 &block.BlockDev{Name: "sdc2"}, 84 }, 85 }, 86 { 87 guid: "c9865081-266c-4a23-a948-c03dab506198", 88 want: block.BlockDevices{ 89 &block.BlockDev{Name: "sdc2"}, 90 }, 91 }, 92 { 93 guid: "", 94 want: nil, 95 }, 96 } { 97 parts := devs.FilterPartID(tt.guid) 98 if !reflect.DeepEqual(parts, tt.want) { 99 t.Errorf("FilterPartID(%s) = %v, want %v", tt.guid, parts, tt.want) 100 } 101 } 102 } 103 104 func TestFilterPartType(t *testing.T) { 105 testutil.SkipIfNotRoot(t) 106 107 devs, err := block.GetBlockDevices() 108 if err != nil { 109 t.Fatal(err) 110 } 111 devs = devs.FilterZeroSize() 112 113 for _, tt := range []struct { 114 guid string 115 want block.BlockDevices 116 }{ 117 { 118 // EFI system partition. 119 guid: "C12A7328-F81F-11D2-BA4B-00A0C93EC93B", 120 want: block.BlockDevices{ 121 &block.BlockDev{Name: "sdc1"}, 122 }, 123 }, 124 { 125 // EFI system partition. mixed case. 126 guid: "c12a7328-f81F-11D2-BA4B-00A0C93ec93B", 127 want: block.BlockDevices{ 128 &block.BlockDev{Name: "sdc1"}, 129 }, 130 }, 131 { 132 // This is some random Linux GUID. 133 guid: "0FC63DAF-8483-4772-8E79-3D69D8477DE4", 134 want: block.BlockDevices{ 135 &block.BlockDev{Name: "sdc2"}, 136 }, 137 }, 138 } { 139 parts := devs.FilterPartType(tt.guid) 140 if !reflect.DeepEqual(parts, tt.want) { 141 t.Errorf("FilterPartType(%s) = %v, want %v", tt.guid, parts, tt.want) 142 } 143 } 144 } 145 146 func TestIdentify(t *testing.T) { 147 testutil.SkipIfNotRoot(t) 148 149 disk, err := scuzz.NewSGDisk("/dev/sda") 150 if err != nil { 151 t.Fatal(err) 152 } 153 defer disk.Close() 154 155 info, err := disk.Identify() 156 if err != nil { 157 t.Fatal(err) 158 } 159 t.Logf("Identify(/dev/sda): %v", info) 160 161 device, err := block.Device("/dev/sda") 162 if err != nil { 163 t.Fatal(err) 164 } 165 size, err := device.Size() 166 if err != nil { 167 t.Fatal(err) 168 } 169 170 if info.NumberSectors != size/512 { 171 t.Errorf("Identify(/dev/sda).NumberSectors = %d, want %d", info.NumberSectors, size/512) 172 } 173 } 174 175 func TestBlockDevices(t *testing.T) { 176 testutil.SkipIfNotRoot(t) 177 178 devs, err := block.GetBlockDevices() 179 if err != nil { 180 t.Fatal(err) 181 } 182 devs = devs.FilterZeroSize() 183 184 want := block.BlockDevices{ 185 &block.BlockDev{Name: "sda"}, 186 &block.BlockDev{Name: "sda1", FsUUID: "2183ead8-a510-4b3d-9777-19c7090f66d9"}, 187 &block.BlockDev{Name: "sda2", FsUUID: "ace5-5144"}, 188 &block.BlockDev{Name: "sdb"}, 189 &block.BlockDev{Name: "sdb1"}, 190 &block.BlockDev{Name: "sdc"}, 191 &block.BlockDev{Name: "sdc1"}, 192 &block.BlockDev{Name: "sdc2"}, 193 } 194 if !reflect.DeepEqual(devs, want) { 195 t.Fatalf("BlockDevices() = \n\t%v want\n\t%v", devs, want) 196 } 197 198 sizes := map[string]uint64{ 199 "sda": 2048 * 512, 200 "sda1": 1024 * 512, 201 "sda2": 1023 * 512, 202 "sdb": 24 * 512, 203 "sdb1": 23 * 512, 204 "sdc": 50 * 4096, 205 "sdc1": 167 * 512, 206 "sdc2": 166 * 512, 207 } 208 for _, dev := range devs { 209 size, err := dev.Size() 210 if err != nil { 211 t.Errorf("Size(%s) error: %v", dev, err) 212 } 213 if size != sizes[dev.Name] { 214 t.Errorf("Size(%s) = %v, want %v", dev, size, sizes[dev.Name]) 215 } 216 } 217 218 wantBlkSize := 512 219 for _, dev := range devs { 220 size, err := dev.BlockSize() 221 if err != nil { 222 t.Errorf("BlockSize(%s) = %v", dev, err) 223 } 224 if size != wantBlkSize { 225 t.Errorf("BlockSize(%s) = %d, want %d", dev, size, wantBlkSize) 226 } 227 228 pSize, err := dev.PhysicalBlockSize() 229 if err != nil { 230 t.Errorf("PhysicalBlockSize(%s) = %v", dev, err) 231 } 232 if pSize != wantBlkSize { 233 t.Errorf("PhysicalBlockSize(%s) = %d, want %d", dev, pSize, wantBlkSize) 234 } 235 } 236 237 wantRR := map[string]error{ 238 "sda": nil, 239 "sda1": syscall.EINVAL, 240 "sda2": syscall.EINVAL, 241 "sdb": nil, 242 "sdb1": syscall.EINVAL, 243 "sdc": nil, 244 "sdc1": syscall.EINVAL, 245 "sdc2": syscall.EINVAL, 246 } 247 for _, dev := range devs { 248 if err := dev.ReadPartitionTable(); err != wantRR[dev.Name] { 249 t.Errorf("ReadPartitionTable(%s) = %v, want %v", dev, err, wantRR[dev.Name]) 250 } 251 } 252 } 253 254 func TestTryMount(t *testing.T) { 255 testutil.SkipIfNotRoot(t) 256 257 d, err := ioutil.TempDir("", "test-") 258 if err != nil { 259 t.Fatal(err) 260 } 261 defer os.RemoveAll(d) 262 263 sda1 := filepath.Join(d, "sda1") 264 if mp, err := mount.TryMount("/dev/sda1", sda1, "", mount.ReadOnly); err != nil { 265 t.Errorf("TryMount(/dev/sda1) = %v, want nil", err) 266 } else { 267 want := &mount.MountPoint{ 268 Path: sda1, 269 Device: "/dev/sda1", 270 FSType: "ext4", 271 Flags: mount.ReadOnly, 272 } 273 if !reflect.DeepEqual(mp, want) { 274 t.Errorf("TryMount(/dev/sda1) = %v, want %v", mp, want) 275 } 276 277 if err := mp.Unmount(0); err != nil { 278 t.Errorf("Unmount(%q) = %v, want nil", sda1, err) 279 } 280 } 281 282 sda2 := filepath.Join(d, "sda2") 283 if mp, err := mount.TryMount("/dev/sda2", sda2, "", mount.ReadOnly); err != nil { 284 t.Errorf("TryMount(/dev/sda2) = %v, want nil", err) 285 } else { 286 want := &mount.MountPoint{ 287 Path: sda2, 288 Device: "/dev/sda2", 289 FSType: "vfat", 290 Flags: mount.ReadOnly, 291 } 292 if !reflect.DeepEqual(mp, want) { 293 t.Errorf("TryMount(/dev/sda2) = %v, want %v", mp, want) 294 } 295 296 if err := mp.Unmount(0); err != nil { 297 t.Errorf("Unmount(%q) = %v, want nil", sda1, err) 298 } 299 } 300 301 sdb1 := filepath.Join(d, "sdb1") 302 if _, err := mount.TryMount("/dev/sdb1", sdb1, "", mount.ReadOnly); !strings.Contains(err.Error(), "no suitable filesystem") { 303 t.Errorf("TryMount(/dev/sdb1) = %v, want an error containing 'no suitable filesystem'", err) 304 } 305 306 sdz1 := filepath.Join(d, "sdz1") 307 if _, err := mount.TryMount("/dev/sdz1", sdz1, "", mount.ReadOnly); !os.IsNotExist(err) { 308 t.Errorf("TryMount(/dev/sdz1) = %v, want an error equivalent to Does Not Exist", err) 309 } 310 }