Skip to content

Commit

Permalink
Extract qemuimg test package
Browse files Browse the repository at this point in the history
The qemuimg package provides 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]>
  • Loading branch information
nirs committed Nov 2, 2024
1 parent b008ef1 commit 49305c7
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 38 deletions.
50 changes: 12 additions & 38 deletions qcow2reader_test.go
Original file line number Diff line number Diff line change
@@ -1,26 +1,22 @@
package qcow2reader
// Package qcow2reader_test keeps blackbox tests for qcow2reader.
package qcow2reader_test

import (
"bytes"
"errors"
"fmt"
"io"
"math/rand"
"os"
"os/exec"
"path/filepath"
"testing"

"github.com/lima-vm/go-qcow2reader"
"github.com/lima-vm/go-qcow2reader/convert"
"github.com/lima-vm/go-qcow2reader/image"
"github.com/lima-vm/go-qcow2reader/image/qcow2"
"github.com/lima-vm/go-qcow2reader/test/qemuimg"
)

const (
MiB = int64(1) << 20
GiB = int64(1) << 30

CompressionTypeNone = qcow2.CompressionType(255)
)

// Benchmark completely empty sparse image (0% utilization). This is the best
Expand All @@ -33,7 +29,7 @@ func Benchmark0p(b *testing.B) {
}
b.Run("qcow2", func(b *testing.B) {
img := base + ".qocw2"
if err := qemuImgConvert(base, img, qcow2.Type, CompressionTypeNone); err != nil {
if err := qemuimg.Convert(base, img, qemuimg.FormatQcow2, qemuimg.CompressionNone); err != nil {
b.Fatal(err)
}
b.Run("read", func(b *testing.B) {
Expand All @@ -51,7 +47,7 @@ func Benchmark0p(b *testing.B) {
})
b.Run("qcow2 zlib", func(b *testing.B) {
img := base + ".zlib.qcow2"
if err := qemuImgConvert(base, img, qcow2.Type, qcow2.CompressionTypeZlib); err != nil {
if err := qemuimg.Convert(base, img, qemuimg.FormatQcow2, qemuimg.CompressionZlib); err != nil {
b.Fatal(err)
}
b.Run("read", func(b *testing.B) {
Expand Down Expand Up @@ -79,7 +75,7 @@ func Benchmark50p(b *testing.B) {
}
b.Run("qcow2", func(b *testing.B) {
img := base + ".qocw2"
if err := qemuImgConvert(base, img, qcow2.Type, CompressionTypeNone); err != nil {
if err := qemuimg.Convert(base, img, qemuimg.FormatQcow2, qemuimg.CompressionNone); err != nil {
b.Fatal(err)
}
b.Run("read", func(b *testing.B) {
Expand All @@ -97,7 +93,7 @@ func Benchmark50p(b *testing.B) {
})
b.Run("qcow2 zlib", func(b *testing.B) {
img := base + ".zlib.qcow2"
if err := qemuImgConvert(base, img, qcow2.Type, qcow2.CompressionTypeZlib); err != nil {
if err := qemuimg.Convert(base, img, qemuimg.FormatQcow2, qemuimg.CompressionZlib); err != nil {
b.Fatal(err)
}
b.Run("read", func(b *testing.B) {
Expand Down Expand Up @@ -126,7 +122,7 @@ func Benchmark100p(b *testing.B) {
}
b.Run("qcow2", func(b *testing.B) {
img := base + ".qocw2"
if err := qemuImgConvert(base, img, qcow2.Type, CompressionTypeNone); err != nil {
if err := qemuimg.Convert(base, img, qemuimg.FormatQcow2, qemuimg.CompressionNone); err != nil {
b.Fatal(err)
}
b.Run("read", func(b *testing.B) {
Expand All @@ -144,7 +140,7 @@ func Benchmark100p(b *testing.B) {
})
b.Run("qcow2 zlib", func(b *testing.B) {
img := base + ".zlib.qcow2"
if err := qemuImgConvert(base, img, qcow2.Type, qcow2.CompressionTypeZlib); err != nil {
if err := qemuimg.Convert(base, img, qemuimg.FormatQcow2, qemuimg.CompressionZlib); err != nil {
b.Fatal(err)
}
b.Run("read", func(b *testing.B) {
Expand All @@ -171,7 +167,7 @@ func benchmarkRead(b *testing.B, filename string) {
b.Fatal(err)
}
defer f.Close()
img, err := Open(f)
img, err := qcow2reader.Open(f)
if err != nil {
b.Fatal(err)
}
Expand All @@ -198,7 +194,7 @@ func benchmarkConvert(b *testing.B, filename string) {
b.Fatal(err)
}
defer f.Close()
img, err := Open(f)
img, err := qcow2reader.Open(f)
if err != nil {
b.Fatal(err)
}
Expand Down Expand Up @@ -289,25 +285,3 @@ func (g *Generator) Read(b []byte) (int, error) {
})
return len(b), nil
}

func qemuImgConvert(src, dst string, dstFormat image.Type, compressionType qcow2.CompressionType) error {
args := []string{"convert", "-O", string(dstFormat)}
if compressionType != CompressionTypeNone {
args = append(args, "-c", "-o", "compression_type="+compressionType.String())
}
args = append(args, src, dst)
cmd := exec.Command("qemu-img", args...)

var stderr bytes.Buffer
cmd.Stderr = &stderr

if err := cmd.Run(); err != nil {
// Return qemu-img stderr instead of the unhelpful default error (exited
// with status 1).
if _, ok := err.(*exec.ExitError); ok {
return errors.New(stderr.String())
}
return err
}
return nil
}
43 changes: 43 additions & 0 deletions test/qemuimg/qemuimg.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package qemuimg

import (
"bytes"
"errors"
"os/exec"
)

type CompressionType string
type Format string

const (
// Compression types.
CompressionNone = CompressionType("")
CompressionZlib = CompressionType("zlib")
CompressionZstd = CompressionType("zstd")

// Image formats.
FormatQcow2 = Format("qcow2")
FormatRaw = Format("raw")
)

func Convert(src, dst string, dstFormat Format, compressionType CompressionType) error {
args := []string{"convert", "-O", string(dstFormat)}
if compressionType != CompressionNone {
args = append(args, "-c", "-o", "compression_type="+string(compressionType))
}
args = append(args, src, dst)
cmd := exec.Command("qemu-img", args...)

var stderr bytes.Buffer
cmd.Stderr = &stderr

if err := cmd.Run(); err != nil {
// Return qemu-img stderr instead of the unhelpful default error (exited
// with status 1).
if _, ok := err.(*exec.ExitError); ok {
return errors.New(stderr.String())
}
return err
}
return nil
}

0 comments on commit 49305c7

Please sign in to comment.