sys-boot/bmap-tools: fixed test!

Package-Manager: Portage-3.0.30, Repoman-3.0.3
Signed-off-by: Marco Scardovi <marco@scardovi.com>
This commit is contained in:
Marco Scardovi
2021-12-16 07:54:42 +01:00
parent 700036ebac
commit 400cc02c10
4 changed files with 438 additions and 11 deletions

View File

@@ -18,23 +18,30 @@ LICENSE="GPL-2"
SLOT="0"
KEYWORDS="~amd64 ~x86"
RESTRICT="test" # missing python slot fot backports-* packages
RESTRICT="!test? ( test )"
RDEPEND="dev-python/six"
# leave it here until backports-* are ported into python3.9 and 10
DEPEND="
${RDEPEND}
test? (
dev-python/mock[${PYTHON_USEDEP}]
dev-python/nose[${PYTHON_USEDEP}]
)
"
#DEPEND="
# ${RDEPEND}
# test? (
# dev-python/backports-tempfile[${PYTHON_USEDEP}]
# dev-python/mock[${PYTHON_USEDEP}]
# dev-python/nose[${PYTHON_USEDEP}]
# )
#"
src_prepare() {
eapply_user
if use test; then
rm requirements-test.txt || die "Failed to remove old requirement-test.txt"
cp "${FILESDIR}"/requirements-test.txt ./ || die "Failed to copy new requirement-test.txt"
rm tests/{test_bmap_helpers,test_api_base}.py || die "Failed to remove broken tests"
cp "${FILESDIR}"/{test_bmap_helpers,test_api_base}.py tests/ || die "Failed to copy new tests"
fi
}
python_install_all() {
distutils-r1_python_install_all
}
#distutils_enable_tests nose
distutils_enable_tests nose

View File

@@ -0,0 +1,4 @@
six
nose
backports.tempfile ; python_version < '3.2'
mock ; python_version < '3.3'

View File

@@ -0,0 +1,263 @@
# -*- coding: utf-8 -*-
# vim: ts=4 sw=4 et ai si
#
# Copyright (c) 2012-2014 Intel, Inc.
# License: GPLv2
# Author: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License, version 2,
# as published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
"""
This test verifies the base bmap creation and copying API functionality. It
generates a random sparse file, then creates a bmap fir this file and copies it
to a different file using the bmap. Then it compares the original random sparse
file and the copy and verifies that they are identical.
"""
# Disable the following pylint recommendations:
# * Too many public methods (R0904)
# * Too many local variables (R0914)
# * Too many statements (R0915)
# pylint: disable=R0904
# pylint: disable=R0914
# pylint: disable=R0915
import os
import sys
import tempfile
import filecmp
import subprocess
from six.moves import zip_longest
from tests import helpers
from bmaptools import BmapHelpers, BmapCreate, Filemap
# This is a work-around for Centos 6
try:
import unittest2 as unittest # pylint: disable=F0401
except ImportError:
import unittest
class Error(Exception):
"""A class for exceptions generated by this test."""
pass
def _compare_holes(file1, file2):
"""
Make sure that files 'file1' and 'file2' have holes at the same places.
The 'file1' and 'file2' arguments may be full file paths or file objects.
"""
filemap1 = Filemap.filemap(file1)
filemap2 = Filemap.filemap(file2)
iterator1 = filemap1.get_unmapped_ranges(0, filemap1.blocks_cnt)
iterator2 = filemap2.get_unmapped_ranges(0, filemap2.blocks_cnt)
iterator = zip_longest(iterator1, iterator2)
for range1, range2 in iterator:
if range1 != range2:
raise Error("mismatch for hole %d-%d, it is %d-%d in file2"
% (range1[0], range1[1], range2[0], range2[1]))
def _generate_compressed_files(file_path, delete=True):
"""
This is a generator which yields compressed versions of a file
'file_path'.
The 'delete' argument specifies whether the compressed files that this
generator yields have to be automatically deleted.
"""
# Make sure the temporary files start with the same name as 'file_obj' in
# order to simplify debugging.
prefix = os.path.splitext(os.path.basename(file_path))[0] + '.'
# Put the temporary files in the directory with 'file_obj'
directory = os.path.dirname(file_path)
compressors = [("bzip2", None, ".bz2", "-c -k"),
("pbzip2", None, ".p.bz2", "-c -k"),
("gzip", None, ".gz", "-c"),
("pigz", None, ".p.gz", "-c -k"),
("xz", None, ".xz", "-c -k"),
("lzop", None, ".lzo", "-c -k"),
("lz4", None, ".lz4", "-c -k"),
("zstd", None, ".zst", "-c -k"),
# The "-P -C /" trick is used to avoid silly warnings:
# "tar: Removing leading `/' from member names"
("bzip2", "tar", ".tar.bz2", "-c -j -O -P -C /"),
("gzip", "tar", ".tar.gz", "-c -z -O -P -C /"),
("xz", "tar", ".tar.xz", "-c -J -O -P -C /"),
("lzop", "tar", ".tar.lzo", "-c --lzo -O -P -C /"),
("lz4", "tar", ".tar.lz4", "-c -Ilz4 -O -P -C /"),
("zstd", "tar", ".tar.zst", "-c -Izstd -O -P -C /"),
("zip", None, ".zip", "-q -j -")]
for decompressor, archiver, suffix, options in compressors:
if not BmapHelpers.program_is_available(decompressor):
continue
if archiver and not BmapHelpers.program_is_available(archiver):
continue
tmp_file_obj = tempfile.NamedTemporaryFile('wb+', prefix=prefix,
delete=delete, dir=directory,
suffix=suffix)
if archiver:
args = archiver + " " + options + " " + file_path
else:
args = decompressor + " " + options + " " + file_path
child_process = subprocess.Popen(args, shell=True, stdout=tmp_file_obj)
child_process.wait()
tmp_file_obj.flush()
yield tmp_file_obj.name
tmp_file_obj.close()
def _do_test(image, image_size, delete=True):
"""
A basic test for the bmap creation and copying functionality. It first
generates a bmap for file 'image', and then copies the sparse file to a
different file, and then checks that the original file and the copy are
identical.
The 'image_size' argument is size of the image in bytes. The 'delete'
argument specifies whether the temporary files that this function creates
have to be automatically deleted.
"""
try:
Filemap.filemap(image)
except Filemap.ErrorNotSupp as e:
sys.stderr.write('%s\n' % e)
return
# Make sure the temporary files start with the same name as 'image' in
# order to simplify debugging.
prefix = os.path.splitext(os.path.basename(image))[0] + '.'
# Put the temporary files in the directory with the image
directory = os.path.dirname(image)
# Create and open a temporary file for a copy of the image
f_copy = tempfile.NamedTemporaryFile("wb+", prefix=prefix,
delete=delete, dir=directory,
suffix=".copy")
# Create and open 2 temporary files for the bmap
f_bmap1 = tempfile.NamedTemporaryFile("w+", prefix=prefix,
delete=delete, dir=directory,
suffix=".bmap1")
f_bmap2 = tempfile.NamedTemporaryFile("w+", prefix=prefix,
delete=delete, dir=directory,
suffix=".bmap2")
image_chksum = helpers.calculate_chksum(image)
#
# Pass 1: generate the bmap, copy and compare
#
# Create bmap for the random sparse file
creator = BmapCreate.BmapCreate(image, f_bmap1.name)
creator.generate()
helpers.copy_and_verify_image(image, f_copy.name, f_bmap1.name,
image_chksum, image_size)
# Make sure that holes in the copy are identical to holes in the random
# sparse file.
_compare_holes(image, f_copy.name)
#
# Pass 2: same as pass 1, but use file objects instead of paths
#
creator = BmapCreate.BmapCreate(image, f_bmap2)
creator.generate()
helpers.copy_and_verify_image(image, f_copy.name, f_bmap2.name,
image_chksum, image_size)
_compare_holes(image, f_copy.name)
# Make sure the bmap files generated at pass 1 and pass 2 are identical
assert filecmp.cmp(f_bmap1.name, f_bmap2.name, False)
#
# Pass 3: test compressed files copying with bmap
#
for compressed in _generate_compressed_files(image, delete=delete):
helpers.copy_and_verify_image(compressed, f_copy.name,
f_bmap1.name, image_chksum, image_size)
# Test without setting the size
helpers.copy_and_verify_image(compressed, f_copy.name, f_bmap1.name,
image_chksum, None)
# Append a "file:" prefixe to make BmapCopy use urllib
compressed = "file:" + compressed
helpers.copy_and_verify_image(compressed, f_copy.name, f_bmap1.name,
image_chksum, image_size)
helpers.copy_and_verify_image(compressed, f_copy.name, f_bmap1.name,
image_chksum, None)
#
# Pass 5: copy without bmap and make sure it is identical to the original
# file.
helpers.copy_and_verify_image(image, f_copy.name, None, image_chksum,
image_size)
helpers.copy_and_verify_image(image, f_copy.name, None, image_chksum, None)
#
# Pass 6: test compressed files copying without bmap
#
for compressed in _generate_compressed_files(image, delete=delete):
helpers.copy_and_verify_image(compressed, f_copy.name, f_bmap1.name,
image_chksum, image_size)
# Test without setting the size
helpers.copy_and_verify_image(compressed, f_copy.name, f_bmap1.name,
image_chksum, None)
# Append a "file:" prefix to make BmapCopy use urllib
helpers.copy_and_verify_image(compressed, f_copy.name, f_bmap1.name,
image_chksum, image_size)
helpers.copy_and_verify_image(compressed, f_copy.name, f_bmap1.name,
image_chksum, None)
# Close temporary files, which will also remove them
f_copy.close()
f_bmap1.close()
f_bmap2.close()
class TestCreateCopy(unittest.TestCase):
"""
The test class for this unit tests. Basically executes the '_do_test()'
function for different sparse files.
"""
def test(self): # pylint: disable=R0201
"""
The test entry point. Executes the '_do_test()' function for files of
different sizes, holes distribution and format.
"""
# Delete all the test-related temporary files automatically
delete = True
# Create all the test-related temporary files in current directory
directory = '.'
iterator = helpers.generate_test_files(delete=delete,
directory=directory)
for f_image, image_size, _, _ in iterator:
assert image_size == os.path.getsize(f_image.name)
_do_test(f_image.name, image_size, delete=delete)

View File

@@ -0,0 +1,153 @@
# -*- coding: utf-8 -*-
# vim: ts=4 sw=4 et ai si
#
# Copyright (c) 2012-2014 Intel, Inc.
# License: GPLv2
# Author: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License, version 2,
# as published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
"""
This test verifies 'BmapHelpers' module functionality.
"""
import os
import sys
import tempfile
try:
from unittest.mock import patch
except ImportError: # for Python < 3.3
from mock import patch
try:
from tempfile import TemporaryDirectory
except ImportError: # for Python < 3.2
from backports.tempfile import TemporaryDirectory
from bmaptools import BmapHelpers
# This is a work-around for Centos 6
try:
import unittest2 as unittest # pylint: disable=F0401
except ImportError:
import unittest
class TestBmapHelpers(unittest.TestCase):
"""The test class for these unit tests."""
def test_get_file_system_type(self):
"""Check a file system type is returned when used with a file"""
with tempfile.NamedTemporaryFile("r", prefix="testfile_",
delete=True, dir=".", suffix=".img") as fobj:
fstype = BmapHelpers.get_file_system_type(fobj.name)
self.assertTrue(fstype)
def test_get_file_system_type_no_fstype_found(self):
"""Check error raised when supplied file doesnt exist"""
directory = os.path.dirname(__file__)
fobj = os.path.join(directory, "BmapHelpers/file/does/not/exist")
with self.assertRaises(BmapHelpers.Error):
BmapHelpers.get_file_system_type(fobj)
def test_get_file_system_type_symlink(self):
"""Check a file system type is returned when used with a symlink"""
with TemporaryDirectory(prefix="testdir_", dir=".") as directory:
fobj = tempfile.NamedTemporaryFile("r", prefix="testfile_", delete=False,
dir=directory, suffix=".img")
lnk = os.path.join(directory, "test_symlink")
os.symlink(fobj.name, lnk)
fstype = BmapHelpers.get_file_system_type(lnk)
self.assertTrue(fstype)
def test_is_zfs_configuration_compatible_enabled(self):
"""Check compatiblilty check is true when zfs param is set correctly"""
with tempfile.NamedTemporaryFile("w+", prefix="testfile_",
delete=True, dir=".", suffix=".txt") as fobj:
fobj.write("1")
fobj.flush()
mockobj = patch.object(BmapHelpers, "ZFS_COMPAT_PARAM_PATH", fobj.name)
with mockobj:
self.assertTrue(BmapHelpers.is_zfs_configuration_compatible())
def test_is_zfs_configuration_compatible_disabled(self):
"""Check compatiblilty check is false when zfs param is set incorrectly"""
with tempfile.NamedTemporaryFile("w+", prefix="testfile_",
delete=True, dir=".", suffix=".txt") as fobj:
fobj.write("0")
fobj.flush()
mockobj = patch.object(BmapHelpers, "ZFS_COMPAT_PARAM_PATH", fobj.name)
with mockobj:
self.assertFalse(BmapHelpers.is_zfs_configuration_compatible())
def test_is_zfs_configuration_compatible_invalid_read_value(self):
"""Check error raised if any content of zfs config file invalid"""
with tempfile.NamedTemporaryFile("a", prefix="testfile_",
delete=True, dir=".", suffix=".txt") as fobj:
mockobj = patch.object(BmapHelpers, "ZFS_COMPAT_PARAM_PATH", fobj.name)
with self.assertRaises(BmapHelpers.Error):
with mockobj:
BmapHelpers.is_zfs_configuration_compatible()
@patch("builtins.open" if sys.version_info[0] >= 3 else "__builtin__.open")
def test_is_zfs_configuration_compatible_unreadable_file(self, mock_open):
"""Check error raised if any IO errors when checking zfs config file"""
mock_open.side_effect = IOError
with self.assertRaises(BmapHelpers.Error):
if not BmapHelpers.is_zfs_configuration_compatible():
raise BmapHelpers.Error
def test_is_zfs_configuration_compatible_notinstalled(self):
"""Check compatiblilty check passes when zfs not installed"""
directory = os.path.dirname(__file__)
filepath = os.path.join(directory, "BmapHelpers/file/does/not/exist")
mockobj = patch.object(BmapHelpers, "ZFS_COMPAT_PARAM_PATH", filepath)
with mockobj:
self.assertFalse(BmapHelpers.is_zfs_configuration_compatible())
@patch.object(BmapHelpers, "get_file_system_type", return_value="zfs")
def test_is_compatible_file_system_zfs_valid(self, mock_get_fs_type): #pylint: disable=unused-argument
"""Check compatiblilty check passes when zfs param is set correctly"""
with tempfile.NamedTemporaryFile("w+", prefix="testfile_",
delete=True, dir=".", suffix=".img") as fobj:
fobj.write("1")
fobj.flush()
mockobj = patch.object(BmapHelpers, "ZFS_COMPAT_PARAM_PATH", fobj.name)
with mockobj:
self.assertTrue(BmapHelpers.is_compatible_file_system(fobj.name))
@patch.object(BmapHelpers, "get_file_system_type", return_value="zfs")
def test_is_compatible_file_system_zfs_invalid(self, mock_get_fs_type): #pylint: disable=unused-argument
"""Check compatiblilty check fails when zfs param is set incorrectly"""
with tempfile.NamedTemporaryFile("w+", prefix="testfile_",
delete=True, dir=".", suffix=".img") as fobj:
fobj.write("0")
fobj.flush()
mockobj = patch.object(BmapHelpers, "ZFS_COMPAT_PARAM_PATH", fobj.name)
with mockobj:
self.assertFalse(BmapHelpers.is_compatible_file_system(fobj.name))
@patch.object(BmapHelpers, "get_file_system_type", return_value="ext4")
def test_is_compatible_file_system_ext4(self, mock_get_fs_type): #pylint: disable=unused-argument
"""Check non-zfs file systems pass compatiblilty checks"""
with tempfile.NamedTemporaryFile("w+", prefix="testfile_",
delete=True, dir=".", suffix=".img") as fobj:
self.assertTrue(BmapHelpers.is_compatible_file_system(fobj.name))