Skip to content

Commit cfa7dd6

Browse files
committed
test(driverutil): add EnsureDisk tests for ISO and non-ISO base images
Add pkg/driverutil/disk_test.go covering: - Base image is ISO: EnsureDisk creates/keeps diffdisk and converts to asif and raw; base ISO remains unchanged (content hash and ISO signature). - Base image is non-ISO: EnsureDisk converts diffdisk to raw and asif. Signed-off-by: ashwat287 <[email protected]>
1 parent 65f9ec3 commit cfa7dd6

File tree

1 file changed

+176
-0
lines changed

1 file changed

+176
-0
lines changed

pkg/driverutil/disk_test.go

Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
// SPDX-FileCopyrightText: Copyright The Lima Authors
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package driverutil
5+
6+
import (
7+
"crypto/sha256"
8+
"encoding/hex"
9+
"os"
10+
"os/exec"
11+
"path/filepath"
12+
"runtime"
13+
"strings"
14+
"sync"
15+
"testing"
16+
17+
"github.com/coreos/go-semver/semver"
18+
"github.com/lima-vm/go-qcow2reader"
19+
"github.com/lima-vm/go-qcow2reader/image"
20+
"gotest.tools/v3/assert"
21+
22+
"github.com/lima-vm/lima/v2/pkg/iso9660util"
23+
"github.com/lima-vm/lima/v2/pkg/limatype/filenames"
24+
)
25+
26+
const (
27+
typeRAW = image.Type("raw")
28+
typeASIF = image.Type("asif")
29+
)
30+
31+
func writeMinimalISO(t *testing.T, path string) {
32+
t.Helper()
33+
entries := []iso9660util.Entry{
34+
{Path: "/hello.txt", Reader: strings.NewReader("hello world")},
35+
}
36+
assert.NilError(t, iso9660util.Write(path, "TESTISO", entries))
37+
}
38+
39+
func writeNonISO(t *testing.T, path string) {
40+
t.Helper()
41+
size := 64 * 1024
42+
buf := make([]byte, size)
43+
copy(buf[0x8001:], "XXXXX")
44+
assert.NilError(t, os.WriteFile(path, buf, 0o644))
45+
}
46+
47+
func sha256File(t *testing.T, path string) string {
48+
t.Helper()
49+
b, err := os.ReadFile(path)
50+
assert.NilError(t, err)
51+
sum := sha256.Sum256(b)
52+
return hex.EncodeToString(sum[:])
53+
}
54+
55+
func detectImageType(t *testing.T, path string) image.Type {
56+
t.Helper()
57+
f, err := os.Open(path)
58+
assert.NilError(t, err)
59+
defer f.Close()
60+
img, err := qcow2reader.Open(f)
61+
assert.NilError(t, err)
62+
return img.Type()
63+
}
64+
65+
func checkDisk(t *testing.T, diff string, expectedType image.Type) {
66+
t.Helper()
67+
fi, err := os.Stat(diff)
68+
assert.NilError(t, err)
69+
assert.Assert(t, fi.Size() > 0)
70+
assert.Equal(t, detectImageType(t, diff), expectedType)
71+
}
72+
73+
func removeAndCheck(t *testing.T, path string) {
74+
t.Helper()
75+
assert.NilError(t, os.Remove(path))
76+
_, err := os.Stat(path)
77+
assert.ErrorIs(t, err, os.ErrNotExist)
78+
}
79+
80+
var ProductVersion = sync.OnceValues(func() (*semver.Version, error) {
81+
out, err := exec.Command("sw_vers", "-productVersion").Output()
82+
if err != nil {
83+
return nil, err
84+
}
85+
vStr := strings.TrimSpace(string(out))
86+
// Normalize "14.5" -> "14.5.0" so semver accepts it.
87+
if strings.Count(vStr, ".") == 1 {
88+
vStr += ".0"
89+
}
90+
return semver.NewVersion(vStr)
91+
})
92+
93+
func isMacOS26OrHigher() bool {
94+
if runtime.GOOS != "darwin" {
95+
return false
96+
}
97+
version, err := ProductVersion()
98+
if err != nil {
99+
return false
100+
}
101+
return version.Major >= 26
102+
}
103+
104+
func TestEnsureDisk_WithISOBaseImage(t *testing.T) {
105+
instDir := t.TempDir()
106+
base := filepath.Join(instDir, filenames.BaseDisk)
107+
diff := filepath.Join(instDir, filenames.DiffDisk)
108+
109+
writeMinimalISO(t, base)
110+
isISO, err := iso9660util.IsISO9660(base)
111+
assert.NilError(t, err)
112+
assert.Assert(t, isISO)
113+
baseHashBefore := sha256File(t, base)
114+
115+
formats := []image.Type{typeRAW}
116+
if isMacOS26OrHigher() {
117+
formats = append(formats, typeASIF)
118+
}
119+
120+
for _, format := range formats {
121+
assert.NilError(t, EnsureDisk(t.Context(), instDir, "2MiB", format))
122+
isISO, err = iso9660util.IsISO9660(base)
123+
assert.NilError(t, err)
124+
assert.Assert(t, isISO)
125+
assert.Equal(t, baseHashBefore, sha256File(t, base))
126+
checkDisk(t, diff, format)
127+
if format != formats[len(formats)-1] {
128+
removeAndCheck(t, diff)
129+
}
130+
}
131+
}
132+
133+
func TestEnsureDisk_WithNonISOBaseImage(t *testing.T) {
134+
instDir := t.TempDir()
135+
base := filepath.Join(instDir, filenames.BaseDisk)
136+
diff := filepath.Join(instDir, filenames.DiffDisk)
137+
138+
writeNonISO(t, base)
139+
isISO, err := iso9660util.IsISO9660(base)
140+
assert.NilError(t, err)
141+
assert.Assert(t, !isISO)
142+
143+
formats := []image.Type{typeRAW}
144+
if isMacOS26OrHigher() {
145+
formats = append(formats, typeASIF)
146+
}
147+
148+
for _, format := range formats {
149+
assert.NilError(t, EnsureDisk(t.Context(), instDir, "2MiB", format))
150+
checkDisk(t, diff, format)
151+
if format != formats[len(formats)-1] {
152+
removeAndCheck(t, diff)
153+
}
154+
}
155+
}
156+
157+
func TestEnsureDisk_ExistingDiffDisk(t *testing.T) {
158+
instDir := t.TempDir()
159+
base := filepath.Join(instDir, filenames.BaseDisk)
160+
diff := filepath.Join(instDir, filenames.DiffDisk)
161+
162+
writeNonISO(t, base)
163+
164+
formats := []image.Type{typeRAW}
165+
if isMacOS26OrHigher() {
166+
formats = append(formats, typeASIF)
167+
}
168+
169+
for _, format := range formats {
170+
assert.NilError(t, os.WriteFile(diff, []byte("preexisting"), 0o644))
171+
origHash := sha256File(t, diff)
172+
assert.NilError(t, EnsureDisk(t.Context(), instDir, "2MiB", format))
173+
assert.Equal(t, sha256File(t, diff), origHash)
174+
removeAndCheck(t, diff)
175+
}
176+
}

0 commit comments

Comments
 (0)