debian-forge-composer/internal/disk/disk_test.go
Achilleas Koutsou 437dd397cd disk: test for duplicate Entities when cloning PartitionTables
Collect all entities and compare pointers.
2022-02-28 23:05:45 +00:00

473 lines
11 KiB
Go

package disk
import (
"fmt"
"math/rand"
"testing"
"github.com/osbuild/osbuild-composer/internal/blueprint"
"github.com/stretchr/testify/assert"
)
func TestDisk_AlignUp(t *testing.T) {
pt := PartitionTable{}
firstAligned := DefaultGrainBytes
tests := []struct {
size uint64
want uint64
}{
{0, 0},
{1, firstAligned},
{firstAligned - 1, firstAligned},
{firstAligned, firstAligned}, // grain is already aligned => no change
{firstAligned / 2, firstAligned},
{firstAligned + 1, firstAligned * 2},
}
for _, tt := range tests {
got := pt.AlignUp(tt.size)
assert.Equal(t, tt.want, got, "Expected %d, got %d", tt.want, got)
}
}
func TestDisk_DynamicallyResizePartitionTable(t *testing.T) {
mountpoints := []blueprint.FilesystemCustomization{
{
MinSize: 2147483648,
Mountpoint: "/usr",
},
}
pt := PartitionTable{
UUID: "D209C89E-EA5E-4FBD-B161-B461CCE297E0",
Type: "gpt",
Partitions: []Partition{
{
Size: 2048,
Bootable: true,
Type: BIOSBootPartitionGUID,
UUID: BIOSBootPartitionUUID,
},
{
Type: FilesystemDataGUID,
UUID: RootPartitionUUID,
Payload: &Filesystem{
Type: "xfs",
Label: "root",
Mountpoint: "/",
FSTabOptions: "defaults",
FSTabFreq: 0,
FSTabPassNo: 0,
},
},
},
}
var expectedSize uint64 = 2147483648
// math/rand is good enough in this case
/* #nosec G404 */
rng := rand.New(rand.NewSource(0))
newpt, err := NewPartitionTable(&pt, mountpoints, 1024, false, rng)
assert.NoError(t, err)
assert.GreaterOrEqual(t, newpt.Size, expectedSize)
}
var testPartitionTables = map[string]PartitionTable{
"plain": {
UUID: "D209C89E-EA5E-4FBD-B161-B461CCE297E0",
Type: "gpt",
Partitions: []Partition{
{
Size: 1048576, // 1MB
Bootable: true,
Type: BIOSBootPartitionGUID,
UUID: BIOSBootPartitionUUID,
},
{
Size: 209715200, // 200 MB
Type: EFISystemPartitionGUID,
UUID: EFISystemPartitionUUID,
Payload: &Filesystem{
Type: "vfat",
UUID: EFIFilesystemUUID,
Mountpoint: "/boot/efi",
Label: "EFI-SYSTEM",
FSTabOptions: "defaults,uid=0,gid=0,umask=077,shortname=winnt",
FSTabFreq: 0,
FSTabPassNo: 2,
},
},
{
Size: 1024000, // 500 MB
Type: FilesystemDataGUID,
UUID: FilesystemDataUUID,
Payload: &Filesystem{
Type: "xfs",
Mountpoint: "/boot",
Label: "boot",
FSTabOptions: "defaults",
FSTabFreq: 0,
FSTabPassNo: 0,
},
},
{
Type: FilesystemDataGUID,
UUID: RootPartitionUUID,
Payload: &Filesystem{
Type: "xfs",
Label: "root",
Mountpoint: "/",
FSTabOptions: "defaults",
FSTabFreq: 0,
FSTabPassNo: 0,
},
},
},
},
"plain-noboot": {
UUID: "D209C89E-EA5E-4FBD-B161-B461CCE297E0",
Type: "gpt",
Partitions: []Partition{
{
Size: 1048576, // 1MB
Bootable: true,
Type: BIOSBootPartitionGUID,
UUID: BIOSBootPartitionUUID,
},
{
Size: 209715200, // 200 MB
Type: EFISystemPartitionGUID,
UUID: EFISystemPartitionUUID,
Payload: &Filesystem{
Type: "vfat",
UUID: EFIFilesystemUUID,
Mountpoint: "/boot/efi",
Label: "EFI-SYSTEM",
FSTabOptions: "defaults,uid=0,gid=0,umask=077,shortname=winnt",
FSTabFreq: 0,
FSTabPassNo: 2,
},
},
{
Type: FilesystemDataGUID,
UUID: RootPartitionUUID,
Payload: &Filesystem{
Type: "xfs",
Label: "root",
Mountpoint: "/",
FSTabOptions: "defaults",
FSTabFreq: 0,
FSTabPassNo: 0,
},
},
},
},
"luks": {
UUID: "D209C89E-EA5E-4FBD-B161-B461CCE297E0",
Type: "gpt",
Partitions: []Partition{
{
Size: 1048576, // 1MB
Bootable: true,
Type: BIOSBootPartitionGUID,
UUID: BIOSBootPartitionUUID,
},
{
Size: 209715200, // 200 MB
Type: EFISystemPartitionGUID,
UUID: EFISystemPartitionUUID,
Payload: &Filesystem{
Type: "vfat",
UUID: EFIFilesystemUUID,
Mountpoint: "/boot/efi",
Label: "EFI-SYSTEM",
FSTabOptions: "defaults,uid=0,gid=0,umask=077,shortname=winnt",
FSTabFreq: 0,
FSTabPassNo: 2,
},
},
{
Size: 1024000, // 500 MB
Type: FilesystemDataGUID,
UUID: FilesystemDataUUID,
Payload: &Filesystem{
Type: "xfs",
Mountpoint: "/boot",
Label: "boot",
FSTabOptions: "defaults",
FSTabFreq: 0,
FSTabPassNo: 0,
},
},
{
Type: FilesystemDataGUID,
UUID: RootPartitionUUID,
Payload: &LUKSContainer{
UUID: "",
Label: "crypt_root",
Payload: &Filesystem{
Type: "xfs",
Label: "root",
Mountpoint: "/",
FSTabOptions: "defaults",
FSTabFreq: 0,
FSTabPassNo: 0,
},
},
},
},
},
"luks+lvm": {
UUID: "D209C89E-EA5E-4FBD-B161-B461CCE297E0",
Type: "gpt",
Partitions: []Partition{
{
Size: 1048576, // 1MB
Bootable: true,
Type: BIOSBootPartitionGUID,
UUID: BIOSBootPartitionUUID,
},
{
Size: 209715200, // 200 MB
Type: EFISystemPartitionGUID,
UUID: EFISystemPartitionUUID,
Payload: &Filesystem{
Type: "vfat",
UUID: EFIFilesystemUUID,
Mountpoint: "/boot/efi",
Label: "EFI-SYSTEM",
FSTabOptions: "defaults,uid=0,gid=0,umask=077,shortname=winnt",
FSTabFreq: 0,
FSTabPassNo: 2,
},
},
{
Size: 1024000, // 500 MB
Type: FilesystemDataGUID,
UUID: FilesystemDataUUID,
Payload: &Filesystem{
Type: "xfs",
Mountpoint: "/boot",
Label: "boot",
FSTabOptions: "defaults",
FSTabFreq: 0,
FSTabPassNo: 0,
},
},
{
Type: FilesystemDataGUID,
UUID: RootPartitionUUID,
Size: 5 * 1024 * 1024 * 1024,
Payload: &LUKSContainer{
UUID: "",
Payload: &LVMVolumeGroup{
Name: "",
Description: "",
LogicalVolumes: []LVMLogicalVolume{
{
Size: 2 * 1024 * 1024 * 1024,
Payload: &Filesystem{
Type: "xfs",
Label: "root",
Mountpoint: "/",
FSTabOptions: "defaults",
FSTabFreq: 0,
FSTabPassNo: 0,
},
},
{
Size: 2 * 1024 * 1024 * 1024,
Payload: &Filesystem{
Type: "xfs",
Label: "root",
Mountpoint: "/home",
FSTabOptions: "defaults",
FSTabFreq: 0,
FSTabPassNo: 0,
},
},
},
},
},
},
},
},
"btrfs": {
UUID: "D209C89E-EA5E-4FBD-B161-B461CCE297E0",
Type: "gpt",
Partitions: []Partition{
{
Size: 1048576, // 1MB
Bootable: true,
Type: BIOSBootPartitionGUID,
UUID: BIOSBootPartitionUUID,
},
{
Size: 209715200, // 200 MB
Type: EFISystemPartitionGUID,
UUID: EFISystemPartitionUUID,
Payload: &Filesystem{
Type: "vfat",
UUID: EFIFilesystemUUID,
Mountpoint: "/boot/efi",
Label: "EFI-SYSTEM",
FSTabOptions: "defaults,uid=0,gid=0,umask=077,shortname=winnt",
FSTabFreq: 0,
FSTabPassNo: 2,
},
},
{
Size: 1024000, // 500 MB
Type: FilesystemDataGUID,
UUID: FilesystemDataUUID,
Payload: &Filesystem{
Type: "xfs",
Mountpoint: "/boot",
Label: "boot",
FSTabOptions: "defaults",
FSTabFreq: 0,
FSTabPassNo: 0,
},
},
{
Type: FilesystemDataGUID,
UUID: RootPartitionUUID,
Size: 10 * 1024 * 1024 * 1024,
Payload: &Btrfs{
UUID: "",
Label: "",
Mountpoint: "",
Subvolumes: []BtrfsSubvolume{
{
Size: 0,
Mountpoint: "/",
GroupID: 0,
},
{
Size: 5 * 1024 * 1024 * 1024,
Mountpoint: "/var",
GroupID: 0,
},
},
},
},
},
},
}
var bp = []blueprint.FilesystemCustomization{
{
Mountpoint: "/",
MinSize: 10 * 1024 * 1024 * 1024,
},
{
Mountpoint: "/home",
MinSize: 20 * 1024 * 1024 * 1024,
},
{
Mountpoint: "/opt",
MinSize: 7 * 1024 * 1024 * 1024,
},
}
func TestDisk_ForEachEntity(t *testing.T) {
count := 0
plain := testPartitionTables["plain"]
err := plain.ForEachEntity(func(e Entity, path []Entity) error {
assert.NotNil(t, e)
assert.NotNil(t, path)
count += 1
return nil
})
assert.NoError(t, err)
// PartitionTable, 4 partitions, 3 filesystems -> 8 entities
assert.Equal(t, 8, count)
}
func TestCreatePartitionTable(t *testing.T) {
assert := assert.New(t)
// math/rand is good enough in this case
/* #nosec G404 */
rng := rand.New(rand.NewSource(13))
for name := range testPartitionTables {
pt := testPartitionTables[name]
mpt, err := NewPartitionTable(&pt, bp, uint64(13*1024*1024), false, rng)
assert.NoError(err, "Partition table generation failed: %s (%s)", name, err)
assert.NotNil(mpt, "Partition table generation failed: %s (nil partition table)", name)
assert.Greater(mpt.GetSize(), uint64(37*1024*1024*1024))
assert.NotNil(mpt.Type, "Partition table generation failed: %s (nil partition table type)", name)
mnt := pt.FindMountable("/")
assert.NotNil(mnt, "Partition table '%s': failed to find root mountable", name)
}
}
func TestCreatePartitionTableLVMify(t *testing.T) {
assert := assert.New(t)
// math/rand is good enough in this case
/* #nosec G404 */
rng := rand.New(rand.NewSource(13))
for name := range testPartitionTables {
pt := testPartitionTables[name]
if name == "btrfs" || name == "luks" {
assert.Panics(func() {
_, _ = NewPartitionTable(&pt, bp, uint64(13*1024*1024), true, rng)
})
continue
}
mpt, err := NewPartitionTable(&pt, bp, uint64(13*1024*1024), true, rng)
assert.NoError(err, "Partition table generation failed: %s (%s)", name, err)
rootPath := entityPath(mpt, "/")
if rootPath == nil {
panic("no root mountpoint for PartitionTable")
}
bootPath := entityPath(mpt, "/boot")
if bootPath == nil {
panic("no boot mountpoint for PartitionTable")
}
parent := rootPath[1]
_, ok := parent.(*LVMLogicalVolume)
assert.True(ok, "Partition table '%s': root's parent (%q) is not an LVM logical volume", name, parent)
}
}
func collectEntities(pt *PartitionTable) []Entity {
entities := make([]Entity, 0)
collector := func(ent Entity, path []Entity) error {
entities = append(entities, ent)
return nil
}
_ = pt.ForEachEntity(collector)
return entities
}
func TestClone(t *testing.T) {
for name := range testPartitionTables {
basePT := testPartitionTables[name]
baseEntities := collectEntities(&basePT)
clonePT := basePT.Clone().(*PartitionTable)
cloneEntities := collectEntities(clonePT)
for idx := range baseEntities {
for jdx := range cloneEntities {
if fmt.Sprintf("%p", baseEntities[idx]) == fmt.Sprintf("%p", cloneEntities[jdx]) {
t.Fatalf("found reference to same entity %#v in list of clones for partition table %q", baseEntities[idx], name)
}
}
}
}
}