1
// This Source Code Form is subject to the terms of the Mozilla Public
2
// License, v. 2.0. If a copy of the MPL was not distributed with this
3
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
5
// Package partition provides common utils for system partition format.
14
"github.com/siderolabs/go-blockdevice/blockdevice"
15
"github.com/siderolabs/go-blockdevice/blockdevice/loopback"
16
"github.com/siderolabs/go-blockdevice/blockdevice/partition/gpt"
17
"github.com/stretchr/testify/suite"
19
"github.com/aenix-io/talm/internal/pkg/partition"
22
type manifestSuite struct {
26
loopbackDevice *os.File
30
diskSize = 10 * 1024 * 1024 // 10 MiB
33
func TestManifestSuite(t *testing.T) {
34
suite.Run(t, new(manifestSuite))
37
func (suite *manifestSuite) SetupTest() {
42
suite.disk, err = os.CreateTemp("", "talos")
43
suite.Require().NoError(err)
45
suite.Require().NoError(suite.disk.Truncate(diskSize))
47
suite.loopbackDevice, err = loopback.NextLoopDevice()
48
suite.Require().NoError(err)
50
suite.T().Logf("Using %s", suite.loopbackDevice.Name())
52
suite.Require().NoError(loopback.Loop(suite.loopbackDevice, suite.disk))
54
suite.Require().NoError(loopback.LoopSetReadWrite(suite.loopbackDevice))
57
func (suite *manifestSuite) TearDownTest() {
58
if suite.loopbackDevice != nil {
59
suite.Assert().NoError(loopback.Unloop(suite.loopbackDevice))
62
if suite.disk != nil {
63
suite.Assert().NoError(os.Remove(suite.disk.Name()))
64
suite.Assert().NoError(suite.disk.Close())
68
func (suite *manifestSuite) skipIfNotRoot() {
70
suite.T().Skip("can't run the test as non-root")
74
func (suite *manifestSuite) skipUnderBuildkit() {
75
hostname, _ := os.Hostname() //nolint:errcheck
77
if hostname == "buildkitsandbox" {
78
suite.T().Skip("test not supported under buildkit as partition devices are not propagated from /dev")
82
func (suite *manifestSuite) TestZeroPartition() {
83
suite.skipUnderBuildkit()
85
bd, err := blockdevice.Open(suite.loopbackDevice.Name(), blockdevice.WithExclusiveLock(true))
86
suite.Require().NoError(err)
88
defer bd.Close() //nolint:errcheck
90
pt, err := gpt.New(bd.Device(), gpt.WithMarkMBRBootable(false))
91
suite.Require().NoError(err)
93
// Create a partition table with a single partition.
94
_, err = pt.Add(0, gpt.WithMaximumSize(true), gpt.WithPartitionName("zerofill"))
95
suite.Require().NoError(err)
97
suite.Require().NoError(pt.Write())
98
suite.Require().NoError(bd.Close())
100
bd, err = blockdevice.Open(suite.loopbackDevice.Name(), blockdevice.WithExclusiveLock(true))
101
suite.Require().NoError(err)
103
defer bd.Close() //nolint:errcheck
105
fills := bytes.NewBuffer(bytes.Repeat([]byte{1}, 10))
107
parts, err := bd.GetPartition("zerofill")
108
suite.Require().NoError(err)
110
part, err := parts.Path()
111
suite.Require().NoError(err)
113
// open the partition as read write
114
dst, err := os.OpenFile(part, os.O_WRONLY, 0o644)
115
suite.Require().NoError(err)
117
defer dst.Close() //nolint:errcheck
119
// Write some data to the partition.
120
_, err = io.Copy(dst, fills)
121
suite.Require().NoError(err)
123
data, err := os.Open(part)
124
suite.Require().NoError(err)
126
defer data.Close() //nolint:errcheck
128
read := make([]byte, fills.Len())
130
_, err = data.Read(read)
131
suite.Require().NoError(err)
132
suite.Require().NoError(data.Close())
134
suite.Assert().True(bytes.Equal(fills.Bytes(), read))
136
suite.Require().NoError(bd.Close())
138
err = partition.Format(part, &partition.FormatOptions{
139
FileSystemType: partition.FilesystemTypeNone,
141
suite.Require().NoError(err)
143
// reading 10 times more than what we wrote should still return 0 since the partition is wiped
144
zerofills := bytes.NewBuffer(bytes.Repeat([]byte{0}, 100))
146
data, err = os.Open(part)
147
suite.Require().NoError(err)
149
defer data.Close() //nolint:errcheck
151
read = make([]byte, zerofills.Len())
153
_, err = data.Read(read)
154
suite.Require().NoError(err)
156
suite.Assert().True(bytes.Equal(zerofills.Bytes(), read))