mirror of
https://github.com/kubevirt/containerized-data-importer.git
synced 2025-06-03 06:30:22 +00:00

The io/ioutil package has been deprecated as of Go 1.16 [1]. This commit replaces the existing io/ioutil functions with their new definitions in io and os packages. [1]: https://golang.org/doc/go1.16#ioutil Signed-off-by: Eng Zer Jun <engzerjun@gmail.com>
261 lines
9.8 KiB
Go
261 lines
9.8 KiB
Go
package util
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/base64"
|
|
"os"
|
|
"path/filepath"
|
|
"regexp"
|
|
|
|
. "github.com/onsi/ginkgo"
|
|
"github.com/onsi/ginkgo/extensions/table"
|
|
. "github.com/onsi/gomega"
|
|
|
|
"k8s.io/apimachinery/pkg/api/resource"
|
|
)
|
|
|
|
const (
|
|
pattern = "^[a-zA-Z0-9]+$"
|
|
TestImagesDir = "../../tests/images"
|
|
)
|
|
|
|
var (
|
|
fileDir, _ = filepath.Abs(TestImagesDir)
|
|
)
|
|
|
|
var _ = Describe("Util", func() {
|
|
It("Should match RandAlphaNum", func() {
|
|
got := RandAlphaNum(8)
|
|
Expect(len(got)).To(Equal(8))
|
|
Expect(regexp.MustCompile(pattern).Match([]byte(got))).To(BeTrue())
|
|
})
|
|
|
|
table.DescribeTable("Round down", func(input, multiple, expectedResult int64) {
|
|
result := RoundDown(input, multiple)
|
|
Expect(result).To(Equal(expectedResult))
|
|
},
|
|
table.Entry("Round down 513 to nearest multiple of 512", int64(513), int64(512), int64(512)),
|
|
table.Entry("Round down 512 to nearest multiple of 512", int64(512), int64(512), int64(512)),
|
|
table.Entry("Round down 510 to nearest multiple of 512", int64(510), int64(512), int64(0)),
|
|
table.Entry("Round down 0 to nearest multiple of 512", int64(0), int64(512), int64(0)),
|
|
table.Entry("Round down 513 to nearest multiple of 2", int64(513), int64(2), int64(512)),
|
|
table.Entry("Round down 512 to nearest multiple of 2", int64(512), int64(2), int64(512)),
|
|
table.Entry("Round down 510 to nearest multiple of 2", int64(510), int64(2), int64(510)),
|
|
)
|
|
|
|
table.DescribeTable("Round up", func(input, multiple, expectedResult int64) {
|
|
result := RoundUp(input, multiple)
|
|
Expect(result).To(Equal(expectedResult))
|
|
},
|
|
table.Entry("Round up 513 to nearest multiple of 512", int64(513), int64(512), int64(1024)),
|
|
table.Entry("Round up 512 to nearest multiple of 512", int64(512), int64(512), int64(512)),
|
|
table.Entry("Round up 510 to nearest multiple of 512", int64(510), int64(512), int64(512)),
|
|
table.Entry("Round up 0 to nearest multiple of 512", int64(0), int64(512), int64(0)),
|
|
table.Entry("Round up 513 to nearest multiple of 2", int64(513), int64(2), int64(514)),
|
|
table.Entry("Round up 512 to nearest multiple of 2", int64(512), int64(2), int64(512)),
|
|
table.Entry("Round up 510 to nearest multiple of 2", int64(510), int64(2), int64(510)),
|
|
)
|
|
|
|
table.DescribeTable("Find Namespace", func(inputFile, expectedResult string) {
|
|
result := getNamespace(inputFile)
|
|
Expect(result).To(Equal(expectedResult))
|
|
},
|
|
table.Entry("Valid namespace", filepath.Join(fileDir, "namespace.txt"), "test-namespace"),
|
|
table.Entry("Invalid file", "doesnotexist", "cdi"),
|
|
)
|
|
})
|
|
|
|
var _ = Describe("GetNameSpace", func() {
|
|
It("Report default namespace outside container", func() {
|
|
Expect("cdi").To(Equal(GetNamespace()))
|
|
})
|
|
})
|
|
|
|
var _ = Describe("ParseEnv", func() {
|
|
BeforeEach(func() {
|
|
os.Setenv("value1", "value1")
|
|
os.Setenv("value2", base64.StdEncoding.EncodeToString([]byte("value2")))
|
|
os.Setenv("value3", "invalid --- *** &&&")
|
|
})
|
|
|
|
AfterEach(func() {
|
|
os.Unsetenv("value1")
|
|
os.Unsetenv("value2")
|
|
os.Unsetenv("value3")
|
|
})
|
|
|
|
It("Parse environment unencoded variables", func() {
|
|
result, err := ParseEnvVar("value1", false)
|
|
Expect(result).To(Equal("value1"))
|
|
Expect(err).ToNot(HaveOccurred())
|
|
result, err = ParseEnvVar("value1", true)
|
|
Expect(result).ToNot(Equal("value1"))
|
|
Expect(err).To(HaveOccurred())
|
|
|
|
result, err = ParseEnvVar("value2", false)
|
|
Expect(result).ToNot(Equal("value2"))
|
|
Expect(err).ToNot(HaveOccurred())
|
|
result, err = ParseEnvVar("value2", true)
|
|
Expect(result).To(Equal("value2"))
|
|
Expect(err).ToNot(HaveOccurred())
|
|
|
|
_, err = ParseEnvVar("value3", true)
|
|
Expect(err).To(HaveOccurred())
|
|
})
|
|
})
|
|
|
|
var _ = Describe("Compare quantities", func() {
|
|
It("Should properly compare quantities", func() {
|
|
small := resource.NewScaledQuantity(int64(1000), 0)
|
|
big := resource.NewScaledQuantity(int64(10000), 0)
|
|
result := MinQuantity(small, big)
|
|
Expect(result).To(Equal(*small))
|
|
result = MinQuantity(big, small)
|
|
Expect(result).To(Equal(*small))
|
|
})
|
|
})
|
|
|
|
var _ = Describe("Copy files", func() {
|
|
var destTmp string
|
|
var err error
|
|
|
|
BeforeEach(func() {
|
|
destTmp, err = os.MkdirTemp("", "dest")
|
|
Expect(err).NotTo(HaveOccurred())
|
|
})
|
|
|
|
AfterEach(func() {
|
|
err = os.RemoveAll(destTmp)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
os.Remove("test.txt")
|
|
})
|
|
|
|
It("Should copy file from source to dest, with valid source and dest", func() {
|
|
err = CopyFile(filepath.Join(TestImagesDir, "content.tar"), filepath.Join(destTmp, "target.tar"))
|
|
Expect(err).ToNot(HaveOccurred())
|
|
sourceMd5, err := Md5sum(filepath.Join(TestImagesDir, "content.tar"))
|
|
Expect(err).ToNot(HaveOccurred())
|
|
targetMd5, err := Md5sum(filepath.Join(destTmp, "target.tar"))
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(sourceMd5).Should(Equal(targetMd5))
|
|
})
|
|
|
|
It("Should not copy file from source to dest, with invalid source", func() {
|
|
err = CopyFile(filepath.Join(TestImagesDir, "content.tar22"), filepath.Join(destTmp, "target.tar"))
|
|
Expect(err).To(HaveOccurred())
|
|
})
|
|
|
|
It("Should not copy file from source to dest, with invalid target", func() {
|
|
err = CopyFile(filepath.Join(TestImagesDir, "content.tar"), filepath.Join("/invalidpath", "target.tar"))
|
|
Expect(err).To(HaveOccurred())
|
|
})
|
|
})
|
|
|
|
var _ = Describe("Zero out ranges in files", func() {
|
|
var testFile *os.File
|
|
var testData []byte
|
|
testData = append(testData, bytes.Repeat([]byte{0x55}, 1024)...)
|
|
testData = append(testData, bytes.Repeat([]byte{0xAA}, 1024)...)
|
|
testData = append(testData, bytes.Repeat([]byte{0xFF}, 1024)...)
|
|
|
|
BeforeEach(func() {
|
|
var err error
|
|
|
|
testFile, err = os.CreateTemp("", "test")
|
|
Expect(err).ToNot(HaveOccurred())
|
|
written, err := testFile.Write(testData)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(written).To(Equal(len(testData)))
|
|
})
|
|
|
|
AfterEach(func() {
|
|
testFile.Close()
|
|
os.Remove(testFile.Name())
|
|
})
|
|
|
|
It("Should successfully zero a range with fallocate", func() {
|
|
start := 512
|
|
length := 100
|
|
end := start + length
|
|
err := PunchHole(testFile, int64(start), int64(length))
|
|
Expect(err).ToNot(HaveOccurred())
|
|
err = testFile.Sync()
|
|
Expect(err).ToNot(HaveOccurred())
|
|
err = testFile.Close()
|
|
Expect(err).ToNot(HaveOccurred())
|
|
data, err := os.ReadFile(testFile.Name())
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(len(data)).To(Equal(len(testData)))
|
|
comparison := bytes.Compare(data[start:end], bytes.Repeat([]byte{0}, length))
|
|
Expect(comparison).To(Equal(0))
|
|
comparison = bytes.Compare(data[0:start], testData[0:start])
|
|
Expect(comparison).To(Equal(0))
|
|
comparison = bytes.Compare(data[end:], testData[end:])
|
|
Expect(comparison).To(Equal(0))
|
|
})
|
|
|
|
table.DescribeTable("Should successfully append zeroes to a file", func(appendFunction func(f *os.File, start, length int64) error) {
|
|
length := 1024
|
|
err := appendFunction(testFile, int64(len(testData)), int64(length))
|
|
Expect(err).ToNot(HaveOccurred())
|
|
err = testFile.Sync()
|
|
Expect(err).ToNot(HaveOccurred())
|
|
err = testFile.Close()
|
|
Expect(err).ToNot(HaveOccurred())
|
|
data, err := os.ReadFile(testFile.Name())
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(len(data)).To(Equal(len(testData) + length))
|
|
comparison := bytes.Compare(data[:len(testData)], testData)
|
|
Expect(comparison).To(Equal(0))
|
|
comparison = bytes.Compare(data[len(testData):], bytes.Repeat([]byte{0}, length))
|
|
Expect(comparison).To(Equal(0))
|
|
},
|
|
table.Entry("using truncate", AppendZeroWithTruncate),
|
|
table.Entry("using write", AppendZeroWithWrite),
|
|
)
|
|
|
|
table.DescribeTable("Should fail to append zeroes to a file using seek if it already has data at the specified starting index", func(appendFunction func(f *os.File, start, length int64) error) {
|
|
length := 1024
|
|
err := appendFunction(testFile, 0, int64(length))
|
|
Expect(err).To(HaveOccurred())
|
|
Expect(err.Error()).Should(MatchRegexp(".*cannot safely append.*"))
|
|
},
|
|
table.Entry("using truncate", AppendZeroWithTruncate),
|
|
table.Entry("using write", AppendZeroWithWrite),
|
|
)
|
|
})
|
|
var _ = Describe("Usable Space calculation", func() {
|
|
|
|
const (
|
|
Mi = int64(1024 * 1024)
|
|
Gi = 1024 * Mi
|
|
noOverhead = float64(0)
|
|
defaultOverhead = float64(0.055)
|
|
largeOverhead = float64(0.75)
|
|
)
|
|
table.DescribeTable("getusablespace should return properly aligned sizes,", func(virtualSize int64, overhead float64) {
|
|
for i := int64(virtualSize - 1024); i < virtualSize+1024; i++ {
|
|
// Requested space is virtualSize rounded up to 1Mi alignment / (1 - overhead) rounded up
|
|
requestedSpace := int64(float64(RoundUp(i, DefaultAlignBlockSize)+1) / float64(1-overhead))
|
|
if i <= virtualSize {
|
|
Expect(GetUsableSpace(overhead, requestedSpace)).To(Equal(virtualSize))
|
|
} else {
|
|
Expect(GetUsableSpace(overhead, requestedSpace)).To(Equal(virtualSize + Mi))
|
|
}
|
|
}
|
|
},
|
|
table.Entry("1Mi virtual size, 0 overhead to be 1Mi if <= 1Mi and 2Mi if > 1Mi", Mi, noOverhead),
|
|
table.Entry("1Mi virtual size, default overhead to be 1Mi if <= 1Mi and 2Mi if > 1Mi", Mi, defaultOverhead),
|
|
table.Entry("1Mi virtual size, large overhead to be 1Mi if <= 1Mi and 2Mi if > 1Mi", Mi, largeOverhead),
|
|
table.Entry("40Mi virtual size, 0 overhead to be 40Mi if <= 1Mi and 41Mi if > 40Mi", 40*Mi, noOverhead),
|
|
table.Entry("40Mi virtual size, default overhead to be 40Mi if <= 1Mi and 41Mi if > 40Mi", 40*Mi, defaultOverhead),
|
|
table.Entry("40Mi virtual size, large overhead to be 40Mi if <= 40Mi and 41Mi if > 40Mi", 40*Mi, largeOverhead),
|
|
table.Entry("1Gi virtual size, 0 overhead to be 1Gi if <= 1Gi and 2Gi if > 1Gi", Gi, noOverhead),
|
|
table.Entry("1Gi virtual size, default overhead to be 1Gi if <= 1Gi and 2Gi if > 1Gi", Gi, defaultOverhead),
|
|
table.Entry("1Gi virtual size, large overhead to be 1Gi if <= 1Gi and 2Gi if > 1Gi", Gi, largeOverhead),
|
|
table.Entry("40Gi virtual size, 0 overhead to be 40Gi if <= 1Gi and 41Gi if > 40Gi", 40*Gi, noOverhead),
|
|
table.Entry("40Gi virtual size, default overhead to be 40Gi if <= 1Gi and 41Gi if > 40Gi", 40*Gi, defaultOverhead),
|
|
table.Entry("40Gi virtual size, large overhead to be 40Gi if <= 40Gi and 41Gi if > 40Gi", 40*Gi, largeOverhead),
|
|
)
|
|
})
|