summaryrefslogtreecommitdiff
path: root/test/py/tests/test_fs/test_squashfs/sqfs_common.py
blob: 8b84c2cdca855533ec1f8c9f4fb081c6e5b7c279 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
# SPDX-License-Identifier: GPL-2.0
# Copyright (C) 2020 Bootlin
# Author: Joao Marcos Costa <joaomarcos.costa@bootlin.com>

import os
import shutil
import subprocess

""" 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' : ''
}

""" EXTRA_TABLE: Set this table's keys and values if you want to make squashfs
images with your own customized options.
"""
EXTRA_TABLE = {}

# 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()

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].split('-')[0])

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)