Skip to content

Commit e1f3384

Browse files
committed
Extract qemuimg package in a test module
The module includes the qemuimg package, providing now only qemuimg.Convert(). I plan to add qemuimg.Create(), qemuimg.Info(), qemuimg.Map(), and qemuimg.Compare(). This makes the code nicer to work with, but adds a test only dependency. The qcow2reader tests use now qemu2reader_test package, so the dependency should be built only for tests. The qemuimg test package will also be useful for other project using this library, since testing code using the library typically requires creating, converting and comparing qcow2 images. Signed-off-by: Nir Soffer <[email protected]>
1 parent b008ef1 commit e1f3384

File tree

5 files changed

+62
-38
lines changed

5 files changed

+62
-38
lines changed

go.mod

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
11
module github.com/lima-vm/go-qcow2reader
22

33
go 1.20
4+
5+
// Testing requirements
6+
require github.com/lima-vm/go-qcow2reader/test v0.4.0
7+
8+
replace github.com/lima-vm/go-qcow2reader/test v0.4.0 => ./test

qcow2reader_test.go

Lines changed: 11 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,21 @@
1-
package qcow2reader
1+
package qcow2reader_test
22

33
import (
4-
"bytes"
5-
"errors"
64
"fmt"
75
"io"
86
"math/rand"
97
"os"
10-
"os/exec"
118
"path/filepath"
129
"testing"
1310

11+
"github.com/lima-vm/go-qcow2reader"
1412
"github.com/lima-vm/go-qcow2reader/convert"
15-
"github.com/lima-vm/go-qcow2reader/image"
16-
"github.com/lima-vm/go-qcow2reader/image/qcow2"
13+
"github.com/lima-vm/go-qcow2reader/test/qemuimg"
1714
)
1815

1916
const (
2017
MiB = int64(1) << 20
2118
GiB = int64(1) << 30
22-
23-
CompressionTypeNone = qcow2.CompressionType(255)
2419
)
2520

2621
// Benchmark completely empty sparse image (0% utilization). This is the best
@@ -33,7 +28,7 @@ func Benchmark0p(b *testing.B) {
3328
}
3429
b.Run("qcow2", func(b *testing.B) {
3530
img := base + ".qocw2"
36-
if err := qemuImgConvert(base, img, qcow2.Type, CompressionTypeNone); err != nil {
31+
if err := qemuimg.Convert(base, img, qemuimg.FormatQcow2, qemuimg.CompressionNone); err != nil {
3732
b.Fatal(err)
3833
}
3934
b.Run("read", func(b *testing.B) {
@@ -51,7 +46,7 @@ func Benchmark0p(b *testing.B) {
5146
})
5247
b.Run("qcow2 zlib", func(b *testing.B) {
5348
img := base + ".zlib.qcow2"
54-
if err := qemuImgConvert(base, img, qcow2.Type, qcow2.CompressionTypeZlib); err != nil {
49+
if err := qemuimg.Convert(base, img, qemuimg.FormatQcow2, qemuimg.CompressionZlib); err != nil {
5550
b.Fatal(err)
5651
}
5752
b.Run("read", func(b *testing.B) {
@@ -79,7 +74,7 @@ func Benchmark50p(b *testing.B) {
7974
}
8075
b.Run("qcow2", func(b *testing.B) {
8176
img := base + ".qocw2"
82-
if err := qemuImgConvert(base, img, qcow2.Type, CompressionTypeNone); err != nil {
77+
if err := qemuimg.Convert(base, img, qemuimg.FormatQcow2, qemuimg.CompressionNone); err != nil {
8378
b.Fatal(err)
8479
}
8580
b.Run("read", func(b *testing.B) {
@@ -97,7 +92,7 @@ func Benchmark50p(b *testing.B) {
9792
})
9893
b.Run("qcow2 zlib", func(b *testing.B) {
9994
img := base + ".zlib.qcow2"
100-
if err := qemuImgConvert(base, img, qcow2.Type, qcow2.CompressionTypeZlib); err != nil {
95+
if err := qemuimg.Convert(base, img, qemuimg.FormatQcow2, qemuimg.CompressionZlib); err != nil {
10196
b.Fatal(err)
10297
}
10398
b.Run("read", func(b *testing.B) {
@@ -126,7 +121,7 @@ func Benchmark100p(b *testing.B) {
126121
}
127122
b.Run("qcow2", func(b *testing.B) {
128123
img := base + ".qocw2"
129-
if err := qemuImgConvert(base, img, qcow2.Type, CompressionTypeNone); err != nil {
124+
if err := qemuimg.Convert(base, img, qemuimg.FormatQcow2, qemuimg.CompressionNone); err != nil {
130125
b.Fatal(err)
131126
}
132127
b.Run("read", func(b *testing.B) {
@@ -144,7 +139,7 @@ func Benchmark100p(b *testing.B) {
144139
})
145140
b.Run("qcow2 zlib", func(b *testing.B) {
146141
img := base + ".zlib.qcow2"
147-
if err := qemuImgConvert(base, img, qcow2.Type, qcow2.CompressionTypeZlib); err != nil {
142+
if err := qemuimg.Convert(base, img, qemuimg.FormatQcow2, qemuimg.CompressionZlib); err != nil {
148143
b.Fatal(err)
149144
}
150145
b.Run("read", func(b *testing.B) {
@@ -171,7 +166,7 @@ func benchmarkRead(b *testing.B, filename string) {
171166
b.Fatal(err)
172167
}
173168
defer f.Close()
174-
img, err := Open(f)
169+
img, err := qcow2reader.Open(f)
175170
if err != nil {
176171
b.Fatal(err)
177172
}
@@ -198,7 +193,7 @@ func benchmarkConvert(b *testing.B, filename string) {
198193
b.Fatal(err)
199194
}
200195
defer f.Close()
201-
img, err := Open(f)
196+
img, err := qcow2reader.Open(f)
202197
if err != nil {
203198
b.Fatal(err)
204199
}
@@ -289,25 +284,3 @@ func (g *Generator) Read(b []byte) (int, error) {
289284
})
290285
return len(b), nil
291286
}
292-
293-
func qemuImgConvert(src, dst string, dstFormat image.Type, compressionType qcow2.CompressionType) error {
294-
args := []string{"convert", "-O", string(dstFormat)}
295-
if compressionType != CompressionTypeNone {
296-
args = append(args, "-c", "-o", "compression_type="+compressionType.String())
297-
}
298-
args = append(args, src, dst)
299-
cmd := exec.Command("qemu-img", args...)
300-
301-
var stderr bytes.Buffer
302-
cmd.Stderr = &stderr
303-
304-
if err := cmd.Run(); err != nil {
305-
// Return qemu-img stderr instead of the unhelpful default error (exited
306-
// with status 1).
307-
if _, ok := err.(*exec.ExitError); ok {
308-
return errors.New(stderr.String())
309-
}
310-
return err
311-
}
312-
return nil
313-
}

test/go.mod

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module github.com/lima-vm/go-qcow2reader/test
2+
3+
go 1.20

test/go.sum

Whitespace-only changes.

test/qemuimg/qemuimg.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package qemuimg
2+
3+
import (
4+
"bytes"
5+
"errors"
6+
"os/exec"
7+
)
8+
9+
type Compression string
10+
type Format string
11+
12+
const (
13+
// Compression types.
14+
CompressionNone = Compression("")
15+
CompressionZlib = Compression("zlib")
16+
CompressionZstd = Compression("zstd")
17+
18+
// Image formats.
19+
FormatQcow2 = Format("qcow2")
20+
FormatRaw = Format("raw")
21+
)
22+
23+
func Convert(src, dst string, dstFormat Format, compressionType Compression) error {
24+
args := []string{"convert", "-O", string(dstFormat)}
25+
if compressionType != CompressionNone {
26+
args = append(args, "-c", "-o", "compression_type="+string(compressionType))
27+
}
28+
args = append(args, src, dst)
29+
cmd := exec.Command("qemu-img", args...)
30+
31+
var stderr bytes.Buffer
32+
cmd.Stderr = &stderr
33+
34+
if err := cmd.Run(); err != nil {
35+
// Return qemu-img stderr instead of the unhelpful default error (exited
36+
// with status 1).
37+
if _, ok := err.(*exec.ExitError); ok {
38+
return errors.New(stderr.String())
39+
}
40+
return err
41+
}
42+
return nil
43+
}

0 commit comments

Comments
 (0)