提交 04c9813e 编写于 作者: J Joao Marcos Costa 提交者: Tom Rini

test/py: rewrite common tools for SquashFS tests

Remove the previous OOP approach, which was confusing and incomplete.
Add more test cases by making SquashFS images with various options,
concerning file fragmentation and its compression. Add comments to
properly document the code.
Reviewed-by: NSimon Glass <sjg@chromium.org>
Tested-by: Simon Glass <sjg@chromium.org> [on sandbox]
Signed-off-by: NJoao Marcos Costa <jmcosta944@gmail.com>
上级 e22ec9c6
......@@ -3,74 +3,203 @@
# Author: Joao Marcos Costa <joaomarcos.costa@bootlin.com>
import os
import random
import string
import shutil
import subprocess
def sqfs_get_random_letters(size):
letters = []
for i in range(0, size):
letters.append(random.choice(string.ascii_letters))
""" standard test images table: Each table item is a key:value pair
representing the output image name and its respective mksquashfs options.
This table should be modified only when adding support for new compression
algorithms. The 'default' case takes no options but the input and output
names, so it must be assigned with an empty string.
"""
STANDARD_TABLE = {
'default' : '',
'lzo_comp_frag' : '',
'lzo_frag' : '',
'lzo_no_frag' : '',
'zstd_comp_frag' : '',
'zstd_frag' : '',
'zstd_no_frag' : '',
'gzip_comp_frag' : '',
'gzip_frag' : '',
'gzip_no_frag' : ''
}
return ''.join(letters)
""" EXTRA_TABLE: Set this table's keys and values if you want to make squashfs
images with your own customized options.
"""
EXTRA_TABLE = {}
def sqfs_generate_file(path, size):
content = sqfs_get_random_letters(size)
file = open(path, "w")
# path to source directory used to make squashfs test images
SQFS_SRC_DIR = 'sqfs_src_dir'
def get_opts_list():
""" Combines fragmentation and compression options into a list of strings.
opts_list's firts item is an empty string as STANDARD_TABLE's first item is
the 'default' case.
Returns:
A list of strings whose items are formed by a compression and a
fragmentation option joined by a whitespace.
"""
# supported compression options only
comp_opts = ['-comp lzo', '-comp zstd', '-comp gzip']
# file fragmentation options
frag_opts = ['-always-use-fragments', '-always-use-fragments -noF', '-no-fragments']
opts_list = [' ']
for comp_opt in comp_opts:
for frag_opt in frag_opts:
opts_list.append(' '.join([comp_opt, frag_opt]))
return opts_list
def init_standard_table():
""" Initializes STANDARD_TABLE values.
STANDARD_TABLE's keys are pre-defined, and init_standard_table() assigns
the right value for each one of them.
"""
opts_list = get_opts_list()
for key, value in zip(STANDARD_TABLE.keys(), opts_list):
STANDARD_TABLE[key] = value
def generate_file(file_name, file_size):
""" Generates a file filled with 'x'.
Args:
file_name: the file's name.
file_size: the content's length and therefore the file size.
"""
content = 'x' * file_size
file = open(file_name, 'w')
file.write(content)
file.close()
class Compression:
def __init__(self, name, files, sizes, block_size = 4096):
self.name = name
self.files = files
self.sizes = sizes
self.mksquashfs_opts = " -b " + str(block_size) + " -comp " + self.name
def add_opt(self, opt):
self.mksquashfs_opts += " " + opt
def gen_image(self, build_dir):
src = os.path.join(build_dir, "sqfs_src/")
os.mkdir(src)
for (f, s) in zip(self.files, self.sizes):
sqfs_generate_file(src + f, s)
# the symbolic link always targets the first file
os.symlink(self.files[0], src + "sym")
sqfs_img = os.path.join(build_dir, "sqfs-" + self.name)
i_o = src + " " + sqfs_img
opts = self.mksquashfs_opts
try:
subprocess.run(["mksquashfs " + i_o + opts], shell = True, check = True)
except:
print("mksquashfs error. Compression type: " + self.name)
raise RuntimeError
def clean_source(self, build_dir):
src = os.path.join(build_dir, "sqfs_src/")
for f in self.files:
os.remove(src + f)
os.remove(src + "sym")
os.rmdir(src)
def cleanup(self, build_dir):
self.clean_source(build_dir)
sqfs_img = os.path.join(build_dir, "sqfs-" + self.name)
os.remove(sqfs_img)
files = ["blks_only", "blks_frag", "frag_only"]
sizes = [4096, 5100, 100]
gzip = Compression("gzip", files, sizes)
zstd = Compression("zstd", files, sizes)
lzo = Compression("lzo", files, sizes)
# use fragment blocks for files larger than block_size
gzip.add_opt("-always-use-fragments")
zstd.add_opt("-always-use-fragments")
# avoid fragments if lzo is used
lzo.add_opt("-no-fragments")
comp_opts = [gzip, zstd, lzo]
def generate_sqfs_src_dir(build_dir):
""" Generates the source directory used to make the SquashFS images.
The source directory is generated at build_dir, and it has the following
structure:
sqfs_src_dir/
├── empty-dir/
├── f1000
├── f4096
├── f5096
├── subdir/
│   └── subdir-file
└── sym -> subdir
3 directories, 4 files
The files in the root dir. are prefixed with an 'f' followed by its size.
Args:
build_dir: u-boot's build-sandbox directory.
"""
root = os.path.join(build_dir, SQFS_SRC_DIR)
# make root directory
os.makedirs(root)
# 4096: minimum block size
file_name = 'f4096'
generate_file(os.path.join(root, file_name), 4096)
# 5096: minimum block size + 1000 chars (fragment)
file_name = 'f5096'
generate_file(os.path.join(root, file_name), 5096)
# 1000: less than minimum block size (fragment only)
file_name = 'f1000'
generate_file(os.path.join(root, file_name), 1000)
# sub-directory with a single file inside
subdir_path = os.path.join(root, 'subdir')
os.makedirs(subdir_path)
generate_file(os.path.join(subdir_path, 'subdir-file'), 100)
# symlink (target: sub-directory)
os.symlink('subdir', os.path.join(root, 'sym'))
# empty directory
os.makedirs(os.path.join(root, 'empty-dir'))
def mksquashfs(args):
""" Runs mksquashfs command.
Args:
args: mksquashfs options (e.g.: compression and fragmentation).
"""
subprocess.run(['mksquashfs ' + args], shell=True, check=True,
stdout=subprocess.DEVNULL)
def get_mksquashfs_version():
""" Parses the output of mksquashfs -version.
Returns:
mksquashfs's version as a float.
"""
out = subprocess.run(['mksquashfs -version'], shell=True, check=True,
capture_output=True, text=True)
# 'out' is: mksquashfs version X (yyyy/mm/dd) ...
return float(out.stdout.split()[2])
def check_mksquashfs_version():
""" Checks if mksquashfs meets the required version. """
required_version = 4.4
if get_mksquashfs_version() < required_version:
print('Error: mksquashfs is too old.')
print('Required version: {}'.format(required_version))
raise AssertionError
def make_all_images(build_dir):
""" Makes the SquashFS images used in the test suite.
The image names and respective mksquashfs options are defined in STANDARD_TABLE
and EXTRA_TABLE. The destination is defined by 'build_dir'.
Args:
build_dir: u-boot's build-sandbox directory.
"""
init_standard_table()
input_path = os.path.join(build_dir, SQFS_SRC_DIR)
# make squashfs images according to STANDARD_TABLE
for out, opts in zip(STANDARD_TABLE.keys(), STANDARD_TABLE.values()):
output_path = os.path.join(build_dir, out)
mksquashfs(' '.join([input_path, output_path, opts]))
# make squashfs images according to EXTRA_TABLE
for out, opts in zip(EXTRA_TABLE.keys(), EXTRA_TABLE.values()):
output_path = os.path.join(build_dir, out)
mksquashfs(' '.join([input_path, output_path, opts]))
def clean_all_images(build_dir):
""" Deletes the SquashFS images at build_dir.
Args:
build_dir: u-boot's build-sandbox directory.
"""
for image_name in STANDARD_TABLE:
image_path = os.path.join(build_dir, image_name)
os.remove(image_path)
for image_name in EXTRA_TABLE:
image_path = os.path.join(build_dir, image_name)
os.remove(image_path)
def clean_sqfs_src_dir(build_dir):
""" Deletes the source directory at build_dir.
Args:
build_dir: u-boot's build-sandbox directory.
"""
path = os.path.join(build_dir, SQFS_SRC_DIR)
shutil.rmtree(path)
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册