Merge https://source.denx.de/u-boot/custodians/u-boot-sunxi
[platform/kernel/u-boot.git] / test / py / tests / test_fs / test_squashfs / sqfs_common.py
1 # SPDX-License-Identifier: GPL-2.0
2 # Copyright (C) 2020 Bootlin
3 # Author: Joao Marcos Costa <joaomarcos.costa@bootlin.com>
4
5 import os
6 import shutil
7 import subprocess
8
9 """ standard test images table: Each table item is a key:value pair
10 representing the output image name and its respective mksquashfs options.
11 This table should be modified only when adding support for new compression
12 algorithms. The 'default' case takes no options but the input and output
13 names, so it must be assigned with an empty string.
14 """
15 STANDARD_TABLE = {
16         'default' : '',
17         'lzo_comp_frag' : '',
18         'lzo_frag' : '',
19         'lzo_no_frag' : '',
20         'zstd_comp_frag' : '',
21         'zstd_frag' : '',
22         'zstd_no_frag' : '',
23         'gzip_comp_frag' : '',
24         'gzip_frag' : '',
25         'gzip_no_frag' : ''
26 }
27
28 """ EXTRA_TABLE: Set this table's keys and values if you want to make squashfs
29 images with your own customized options.
30 """
31 EXTRA_TABLE = {}
32
33 # path to source directory used to make squashfs test images
34 SQFS_SRC_DIR = 'sqfs_src_dir'
35
36 def get_opts_list():
37     """ Combines fragmentation and compression options into a list of strings.
38
39     opts_list's firts item is an empty string as STANDARD_TABLE's first item is
40     the 'default' case.
41
42     Returns:
43         A list of strings whose items are formed by a compression and a
44         fragmentation option joined by a whitespace.
45     """
46     # supported compression options only
47     comp_opts = ['-comp lzo', '-comp zstd', '-comp gzip']
48     # file fragmentation options
49     frag_opts = ['-always-use-fragments', '-always-use-fragments -noF', '-no-fragments']
50
51     opts_list = [' ']
52     for comp_opt in comp_opts:
53         for frag_opt in frag_opts:
54             opts_list.append(' '.join([comp_opt, frag_opt]))
55
56     return opts_list
57
58 def init_standard_table():
59     """ Initializes STANDARD_TABLE values.
60
61     STANDARD_TABLE's keys are pre-defined, and init_standard_table() assigns
62     the right value for each one of them.
63     """
64     opts_list = get_opts_list()
65
66     for key, value in zip(STANDARD_TABLE.keys(), opts_list):
67         STANDARD_TABLE[key] = value
68
69 def generate_file(file_name, file_size):
70     """ Generates a file filled with 'x'.
71
72     Args:
73         file_name: the file's name.
74         file_size: the content's length and therefore the file size.
75     """
76     content = 'x' * file_size
77
78     file = open(file_name, 'w')
79     file.write(content)
80     file.close()
81
82 def generate_sqfs_src_dir(build_dir):
83     """ Generates the source directory used to make the SquashFS images.
84
85     The source directory is generated at build_dir, and it has the following
86     structure:
87     sqfs_src_dir/
88     ├── empty-dir/
89     ├── f1000
90     ├── f4096
91     ├── f5096
92     ├── subdir/
93     │   └── subdir-file
94     └── sym -> subdir
95
96     3 directories, 4 files
97
98     The files in the root dir. are prefixed with an 'f' followed by its size.
99
100     Args:
101         build_dir: u-boot's build-sandbox directory.
102     """
103
104     root = os.path.join(build_dir, SQFS_SRC_DIR)
105     # make root directory
106     os.makedirs(root)
107
108     # 4096: minimum block size
109     file_name = 'f4096'
110     generate_file(os.path.join(root, file_name), 4096)
111
112     # 5096: minimum block size + 1000 chars (fragment)
113     file_name = 'f5096'
114     generate_file(os.path.join(root, file_name), 5096)
115
116     # 1000: less than minimum block size (fragment only)
117     file_name = 'f1000'
118     generate_file(os.path.join(root, file_name), 1000)
119
120     # sub-directory with a single file inside
121     subdir_path = os.path.join(root, 'subdir')
122     os.makedirs(subdir_path)
123     generate_file(os.path.join(subdir_path, 'subdir-file'), 100)
124
125     # symlink (target: sub-directory)
126     os.symlink('subdir', os.path.join(root, 'sym'))
127
128     # empty directory
129     os.makedirs(os.path.join(root, 'empty-dir'))
130
131 def mksquashfs(args):
132     """ Runs mksquashfs command.
133
134     Args:
135         args: mksquashfs options (e.g.: compression and fragmentation).
136     """
137     subprocess.run(['mksquashfs ' + args], shell=True, check=True,
138                    stdout=subprocess.DEVNULL)
139
140 def get_mksquashfs_version():
141     """ Parses the output of mksquashfs -version.
142
143     Returns:
144         mksquashfs's version as a float.
145     """
146     out = subprocess.run(['mksquashfs -version'], shell=True, check=True,
147                          capture_output=True, text=True)
148     # 'out' is: mksquashfs version X (yyyy/mm/dd) ...
149     return float(out.stdout.split()[2].split('-')[0])
150
151 def check_mksquashfs_version():
152     """ Checks if mksquashfs meets the required version. """
153
154     required_version = 4.4
155     if get_mksquashfs_version() < required_version:
156         print('Error: mksquashfs is too old.')
157         print('Required version: {}'.format(required_version))
158         raise AssertionError
159
160 def make_all_images(build_dir):
161     """ Makes the SquashFS images used in the test suite.
162
163     The image names and respective mksquashfs options are defined in STANDARD_TABLE
164     and EXTRA_TABLE. The destination is defined by 'build_dir'.
165
166     Args:
167         build_dir: u-boot's build-sandbox directory.
168     """
169
170     init_standard_table()
171     input_path = os.path.join(build_dir, SQFS_SRC_DIR)
172
173     # make squashfs images according to STANDARD_TABLE
174     for out, opts in zip(STANDARD_TABLE.keys(), STANDARD_TABLE.values()):
175         output_path = os.path.join(build_dir, out)
176         mksquashfs(' '.join([input_path, output_path, opts]))
177
178     # make squashfs images according to EXTRA_TABLE
179     for out, opts in zip(EXTRA_TABLE.keys(), EXTRA_TABLE.values()):
180         output_path = os.path.join(build_dir, out)
181         mksquashfs(' '.join([input_path, output_path, opts]))
182
183 def clean_all_images(build_dir):
184     """ Deletes the SquashFS images at build_dir.
185
186     Args:
187         build_dir: u-boot's build-sandbox directory.
188     """
189
190     for image_name in STANDARD_TABLE:
191         image_path = os.path.join(build_dir, image_name)
192         os.remove(image_path)
193
194     for image_name in EXTRA_TABLE:
195         image_path = os.path.join(build_dir, image_name)
196         os.remove(image_path)
197
198 def clean_sqfs_src_dir(build_dir):
199     """ Deletes the source directory at build_dir.
200
201     Args:
202         build_dir: u-boot's build-sandbox directory.
203     """
204     path = os.path.join(build_dir, SQFS_SRC_DIR)
205     shutil.rmtree(path)