xref: /aosp_15_r20/external/lz4/tests/test-lz4-list.py (revision 27162e4e17433d5aa7cb38e7b6a433a09405fc7f)
1*27162e4eSAndroid Build Coastguard Worker#!/usr/bin/env python3
2*27162e4eSAndroid Build Coastguard Workerimport subprocess
3*27162e4eSAndroid Build Coastguard Workerimport time
4*27162e4eSAndroid Build Coastguard Workerimport glob
5*27162e4eSAndroid Build Coastguard Workerimport os
6*27162e4eSAndroid Build Coastguard Workerimport tempfile
7*27162e4eSAndroid Build Coastguard Workerimport unittest
8*27162e4eSAndroid Build Coastguard Workerimport sys
9*27162e4eSAndroid Build Coastguard Worker
10*27162e4eSAndroid Build Coastguard WorkerSIZES = [3, 11]  # Always 2 sizes
11*27162e4eSAndroid Build Coastguard WorkerMIB = 1048576
12*27162e4eSAndroid Build Coastguard WorkerLZ4 = os.path.abspath(os.path.dirname(os.path.realpath(__file__)) + "/../lz4")
13*27162e4eSAndroid Build Coastguard Workerif not os.path.exists(LZ4):
14*27162e4eSAndroid Build Coastguard Worker    LZ4 = os.path.abspath(os.path.dirname(os.path.realpath(__file__)) + "/../programs/lz4")
15*27162e4eSAndroid Build Coastguard WorkerTEMP = tempfile.gettempdir()
16*27162e4eSAndroid Build Coastguard Worker
17*27162e4eSAndroid Build Coastguard Worker
18*27162e4eSAndroid Build Coastguard Workerclass NVerboseFileInfo:
19*27162e4eSAndroid Build Coastguard Worker    def __init__(self, line_in):
20*27162e4eSAndroid Build Coastguard Worker        self.line = line_in
21*27162e4eSAndroid Build Coastguard Worker        splitlines = line_in.split()
22*27162e4eSAndroid Build Coastguard Worker        if len(splitlines) != 7:
23*27162e4eSAndroid Build Coastguard Worker            errout(f"Unexpected line: {line_in}")
24*27162e4eSAndroid Build Coastguard Worker        self.frames, self.type, self.block, self.compressed, self.uncompressed, self.ratio, self.filename = splitlines
25*27162e4eSAndroid Build Coastguard Worker        self.exp_unc_size = 0
26*27162e4eSAndroid Build Coastguard Worker        # Get real file sizes
27*27162e4eSAndroid Build Coastguard Worker        if "concat-all" in self.filename or "2f--content-size" in self.filename:
28*27162e4eSAndroid Build Coastguard Worker            for i in SIZES:
29*27162e4eSAndroid Build Coastguard Worker                self.exp_unc_size += os.path.getsize(f"{TEMP}/test_list_{i}M")
30*27162e4eSAndroid Build Coastguard Worker        else:
31*27162e4eSAndroid Build Coastguard Worker            uncompressed_filename = self.filename.split("-")[0]
32*27162e4eSAndroid Build Coastguard Worker            self.exp_unc_size += os.path.getsize(f"{TEMP}/{uncompressed_filename}")
33*27162e4eSAndroid Build Coastguard Worker        self.exp_comp_size = os.path.getsize(f"{TEMP}/{self.filename}")
34*27162e4eSAndroid Build Coastguard Worker
35*27162e4eSAndroid Build Coastguard Worker
36*27162e4eSAndroid Build Coastguard Workerclass TestNonVerbose(unittest.TestCase):
37*27162e4eSAndroid Build Coastguard Worker    @classmethod
38*27162e4eSAndroid Build Coastguard Worker    def setUpClass(self):
39*27162e4eSAndroid Build Coastguard Worker        self.nvinfo_list = []
40*27162e4eSAndroid Build Coastguard Worker        test_list_files = glob.glob(f"{TEMP}/test_list_*.lz4")
41*27162e4eSAndroid Build Coastguard Worker        # One of the files has 2 frames so duplicate it in this list to map each frame 1 to a single file
42*27162e4eSAndroid Build Coastguard Worker        for i, filename in enumerate(test_list_files):
43*27162e4eSAndroid Build Coastguard Worker            for i, line in enumerate(execute(f"{LZ4} --list -m {filename}", print_output=True)):
44*27162e4eSAndroid Build Coastguard Worker                if i > 0:
45*27162e4eSAndroid Build Coastguard Worker                    self.nvinfo_list.append(NVerboseFileInfo(line))
46*27162e4eSAndroid Build Coastguard Worker
47*27162e4eSAndroid Build Coastguard Worker    def test_frames(self):
48*27162e4eSAndroid Build Coastguard Worker        all_concat_frames = 0
49*27162e4eSAndroid Build Coastguard Worker        all_concat_index = None
50*27162e4eSAndroid Build Coastguard Worker        for i, nvinfo in enumerate(self.nvinfo_list):
51*27162e4eSAndroid Build Coastguard Worker            if "concat-all" in nvinfo.filename:
52*27162e4eSAndroid Build Coastguard Worker                all_concat_index = i
53*27162e4eSAndroid Build Coastguard Worker            elif "2f--content-size" in nvinfo.filename:
54*27162e4eSAndroid Build Coastguard Worker                self.assertEqual("2", nvinfo.frames, nvinfo.line)
55*27162e4eSAndroid Build Coastguard Worker                all_concat_frames += 2
56*27162e4eSAndroid Build Coastguard Worker            else:
57*27162e4eSAndroid Build Coastguard Worker                self.assertEqual("1", nvinfo.frames, nvinfo.line)
58*27162e4eSAndroid Build Coastguard Worker                all_concat_frames += 1
59*27162e4eSAndroid Build Coastguard Worker        self.assertNotEqual(None, all_concat_index, "Couldn't find concat-all file index.")
60*27162e4eSAndroid Build Coastguard Worker        self.assertEqual(self.nvinfo_list[all_concat_index].frames, str(all_concat_frames), self.nvinfo_list[all_concat_index].line)
61*27162e4eSAndroid Build Coastguard Worker
62*27162e4eSAndroid Build Coastguard Worker    def test_frame_types(self):
63*27162e4eSAndroid Build Coastguard Worker        for nvinfo in self.nvinfo_list:
64*27162e4eSAndroid Build Coastguard Worker            if "-lz4f-" in nvinfo.filename:
65*27162e4eSAndroid Build Coastguard Worker                self.assertEqual(nvinfo.type, "LZ4Frame", nvinfo.line)
66*27162e4eSAndroid Build Coastguard Worker            elif "-legc-" in nvinfo.filename:
67*27162e4eSAndroid Build Coastguard Worker                self.assertEqual(nvinfo.type, "LegacyFrame", nvinfo.line)
68*27162e4eSAndroid Build Coastguard Worker            elif "-skip-" in nvinfo.filename:
69*27162e4eSAndroid Build Coastguard Worker                self.assertEqual(nvinfo.type, "SkippableFrame", nvinfo.line)
70*27162e4eSAndroid Build Coastguard Worker
71*27162e4eSAndroid Build Coastguard Worker    def test_block(self):
72*27162e4eSAndroid Build Coastguard Worker        for nvinfo in self.nvinfo_list:
73*27162e4eSAndroid Build Coastguard Worker            # if "-leg" in nvinfo.filename or "-skip" in nvinfo.filename:
74*27162e4eSAndroid Build Coastguard Worker            #     self.assertEqual(nvinfo.block, "-", nvinfo.line)
75*27162e4eSAndroid Build Coastguard Worker            if "--BD" in nvinfo.filename:
76*27162e4eSAndroid Build Coastguard Worker                self.assertRegex(nvinfo.block, "^B[0-9]+D$", nvinfo.line)
77*27162e4eSAndroid Build Coastguard Worker            elif "--BI" in nvinfo.filename:
78*27162e4eSAndroid Build Coastguard Worker                self.assertRegex(nvinfo.block, "^B[0-9]+I$", nvinfo.line)
79*27162e4eSAndroid Build Coastguard Worker
80*27162e4eSAndroid Build Coastguard Worker    def test_compressed_size(self):
81*27162e4eSAndroid Build Coastguard Worker        for nvinfo in self.nvinfo_list:
82*27162e4eSAndroid Build Coastguard Worker            self.assertEqual(nvinfo.compressed, to_human(nvinfo.exp_comp_size), nvinfo.line)
83*27162e4eSAndroid Build Coastguard Worker
84*27162e4eSAndroid Build Coastguard Worker    def test_ratio(self):
85*27162e4eSAndroid Build Coastguard Worker        for nvinfo in self.nvinfo_list:
86*27162e4eSAndroid Build Coastguard Worker            if "--content-size" in nvinfo.filename:
87*27162e4eSAndroid Build Coastguard Worker                self.assertEqual(nvinfo.ratio, f"{float(nvinfo.exp_comp_size) / float(nvinfo.exp_unc_size) * 100:.2f}%", nvinfo.line)
88*27162e4eSAndroid Build Coastguard Worker
89*27162e4eSAndroid Build Coastguard Worker    def test_uncompressed_size(self):
90*27162e4eSAndroid Build Coastguard Worker        for nvinfo in self.nvinfo_list:
91*27162e4eSAndroid Build Coastguard Worker            if "--content-size" in nvinfo.filename:
92*27162e4eSAndroid Build Coastguard Worker                self.assertEqual(nvinfo.uncompressed, to_human(nvinfo.exp_unc_size), nvinfo.line)
93*27162e4eSAndroid Build Coastguard Worker
94*27162e4eSAndroid Build Coastguard Worker
95*27162e4eSAndroid Build Coastguard Workerclass VerboseFileInfo:
96*27162e4eSAndroid Build Coastguard Worker    def __init__(self, lines):
97*27162e4eSAndroid Build Coastguard Worker        # Parse lines
98*27162e4eSAndroid Build Coastguard Worker        self.frame_list = []
99*27162e4eSAndroid Build Coastguard Worker        self.file_frame_map = []
100*27162e4eSAndroid Build Coastguard Worker        for i, line in enumerate(lines):
101*27162e4eSAndroid Build Coastguard Worker            if i == 0:
102*27162e4eSAndroid Build Coastguard Worker                self.filename = line
103*27162e4eSAndroid Build Coastguard Worker                continue
104*27162e4eSAndroid Build Coastguard Worker            elif i == 1:
105*27162e4eSAndroid Build Coastguard Worker                # Skip header
106*27162e4eSAndroid Build Coastguard Worker                continue
107*27162e4eSAndroid Build Coastguard Worker            frame_info = dict(zip(["frame", "type", "block", "checksum", "compressed", "uncompressed", "ratio"], line.split()))
108*27162e4eSAndroid Build Coastguard Worker            frame_info["line"] = line
109*27162e4eSAndroid Build Coastguard Worker            self.frame_list.append(frame_info)
110*27162e4eSAndroid Build Coastguard Worker
111*27162e4eSAndroid Build Coastguard Worker
112*27162e4eSAndroid Build Coastguard Workerclass TestVerbose(unittest.TestCase):
113*27162e4eSAndroid Build Coastguard Worker    @classmethod
114*27162e4eSAndroid Build Coastguard Worker    def setUpClass(self):
115*27162e4eSAndroid Build Coastguard Worker        # Even do we're listing 2 files to test multiline working as expected.
116*27162e4eSAndroid Build Coastguard Worker        # we're only really interested in testing the output of the concat-all file.
117*27162e4eSAndroid Build Coastguard Worker        self.vinfo_list = []
118*27162e4eSAndroid Build Coastguard Worker        start = end = 0
119*27162e4eSAndroid Build Coastguard Worker        test_list_SM_lz4f = glob.glob(f"{TEMP}/test_list_*M-lz4f-2f--content-size.lz4")
120*27162e4eSAndroid Build Coastguard Worker        for i, filename in enumerate(test_list_SM_lz4f):
121*27162e4eSAndroid Build Coastguard Worker            output = execute(f"{LZ4} --list -m -v {TEMP}/test_list_concat-all.lz4 {filename}", print_output=True)
122*27162e4eSAndroid Build Coastguard Worker            for i, line in enumerate(output):
123*27162e4eSAndroid Build Coastguard Worker                if line.startswith("test_list"):
124*27162e4eSAndroid Build Coastguard Worker                    if start != 0 and end != 0:
125*27162e4eSAndroid Build Coastguard Worker                        self.vinfo_list.append(VerboseFileInfo(output[start:end]))
126*27162e4eSAndroid Build Coastguard Worker                    start = i
127*27162e4eSAndroid Build Coastguard Worker                if not line:
128*27162e4eSAndroid Build Coastguard Worker                    end = i
129*27162e4eSAndroid Build Coastguard Worker        self.vinfo_list.append(VerboseFileInfo(output[start:end]))
130*27162e4eSAndroid Build Coastguard Worker        # Populate file_frame_map as a reference of the expected info
131*27162e4eSAndroid Build Coastguard Worker        concat_file_list = glob.glob(f"{TEMP}/test_list_[!concat]*.lz4")
132*27162e4eSAndroid Build Coastguard Worker        # One of the files has 2 frames so duplicate it in this list to map each frame 1 to a single file
133*27162e4eSAndroid Build Coastguard Worker        for i, filename in enumerate(concat_file_list):
134*27162e4eSAndroid Build Coastguard Worker            if "2f--content-size" in filename:
135*27162e4eSAndroid Build Coastguard Worker                concat_file_list.insert(i, filename)
136*27162e4eSAndroid Build Coastguard Worker                break
137*27162e4eSAndroid Build Coastguard Worker        self.cvinfo = self.vinfo_list[0]
138*27162e4eSAndroid Build Coastguard Worker        self.cvinfo.file_frame_map = concat_file_list
139*27162e4eSAndroid Build Coastguard Worker        self.cvinfo.compressed_size = os.path.getsize(f"{TEMP}/test_list_concat-all.lz4")
140*27162e4eSAndroid Build Coastguard Worker
141*27162e4eSAndroid Build Coastguard Worker    def test_frame_number(self):
142*27162e4eSAndroid Build Coastguard Worker        for vinfo in self.vinfo_list:
143*27162e4eSAndroid Build Coastguard Worker            for i, frame_info in enumerate(vinfo.frame_list):
144*27162e4eSAndroid Build Coastguard Worker                self.assertEqual(frame_info["frame"], str(i + 1), frame_info["line"])
145*27162e4eSAndroid Build Coastguard Worker
146*27162e4eSAndroid Build Coastguard Worker    def test_block(self):
147*27162e4eSAndroid Build Coastguard Worker        for i, frame_info in enumerate(self.cvinfo.frame_list):
148*27162e4eSAndroid Build Coastguard Worker            if "--BD" in self.cvinfo.file_frame_map[i]:
149*27162e4eSAndroid Build Coastguard Worker                self.assertRegex(self.cvinfo.frame_list[i]["block"], "^B[0-9]+D$", self.cvinfo.frame_list[i]["line"])
150*27162e4eSAndroid Build Coastguard Worker            elif "--BI" in self.cvinfo.file_frame_map[i]:
151*27162e4eSAndroid Build Coastguard Worker                self.assertEqual(self.cvinfo.frame_list[i]["block"], "^B[0-9]+I$", self.cvinfo.frame_list[i]["line"])
152*27162e4eSAndroid Build Coastguard Worker
153*27162e4eSAndroid Build Coastguard Worker    def test_checksum(self):
154*27162e4eSAndroid Build Coastguard Worker        for i, frame_info in enumerate(self.cvinfo.frame_list):
155*27162e4eSAndroid Build Coastguard Worker            if "-lz4f-" in self.cvinfo.file_frame_map[i] and "--no-frame-crc" not in self.cvinfo.file_frame_map[i]:
156*27162e4eSAndroid Build Coastguard Worker                self.assertEqual(self.cvinfo.frame_list[i]["checksum"], "XXH32", self.cvinfo.frame_list[i]["line"])
157*27162e4eSAndroid Build Coastguard Worker
158*27162e4eSAndroid Build Coastguard Worker    def test_uncompressed(self):
159*27162e4eSAndroid Build Coastguard Worker        for i, frame_info in enumerate(self.cvinfo.frame_list):
160*27162e4eSAndroid Build Coastguard Worker            ffm = self.cvinfo.file_frame_map[i]
161*27162e4eSAndroid Build Coastguard Worker            if "-2f-" not in ffm and "--content-size" in ffm:
162*27162e4eSAndroid Build Coastguard Worker                expected_size_unc = int(ffm[ffm.rindex("_") + 1:ffm.index("M")]) * 1048576
163*27162e4eSAndroid Build Coastguard Worker                self.assertEqual(self.cvinfo.frame_list[i]["uncompressed"], str(expected_size_unc), self.cvinfo.frame_list[i]["line"])
164*27162e4eSAndroid Build Coastguard Worker
165*27162e4eSAndroid Build Coastguard Worker    def test_ratio(self):
166*27162e4eSAndroid Build Coastguard Worker        for i, frame_info in enumerate(self.cvinfo.frame_list):
167*27162e4eSAndroid Build Coastguard Worker            if "--content-size" in self.cvinfo.file_frame_map[i]:
168*27162e4eSAndroid Build Coastguard Worker                self.assertEqual(self.cvinfo.frame_list[i]['ratio'],
169*27162e4eSAndroid Build Coastguard Worker                                 f"{float(self.cvinfo.frame_list[i]['compressed']) / float(self.cvinfo.frame_list[i]['uncompressed']) * 100:.2f}%",
170*27162e4eSAndroid Build Coastguard Worker                                 self.cvinfo.frame_list[i]["line"])
171*27162e4eSAndroid Build Coastguard Worker
172*27162e4eSAndroid Build Coastguard Worker
173*27162e4eSAndroid Build Coastguard Workerdef to_human(size):
174*27162e4eSAndroid Build Coastguard Worker    for unit in ['', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y']:
175*27162e4eSAndroid Build Coastguard Worker        if size < 1024.0:
176*27162e4eSAndroid Build Coastguard Worker            break
177*27162e4eSAndroid Build Coastguard Worker        size /= 1024.0
178*27162e4eSAndroid Build Coastguard Worker    return f"{size:.2f}{unit}"
179*27162e4eSAndroid Build Coastguard Worker
180*27162e4eSAndroid Build Coastguard Worker
181*27162e4eSAndroid Build Coastguard Workerdef log(text):
182*27162e4eSAndroid Build Coastguard Worker    print(time.strftime("%Y/%m/%d %H:%M:%S") + ' - ' + text)
183*27162e4eSAndroid Build Coastguard Worker
184*27162e4eSAndroid Build Coastguard Worker
185*27162e4eSAndroid Build Coastguard Workerdef errout(text, err=1):
186*27162e4eSAndroid Build Coastguard Worker    log(text)
187*27162e4eSAndroid Build Coastguard Worker    exit(err)
188*27162e4eSAndroid Build Coastguard Worker
189*27162e4eSAndroid Build Coastguard Worker
190*27162e4eSAndroid Build Coastguard Workerdef execute(command, print_command=True, print_output=False, print_error=True):
191*27162e4eSAndroid Build Coastguard Worker    if os.environ.get('QEMU_SYS'):
192*27162e4eSAndroid Build Coastguard Worker        command = f"{os.environ['QEMU_SYS']} {command}"
193*27162e4eSAndroid Build Coastguard Worker    if print_command:
194*27162e4eSAndroid Build Coastguard Worker        log("> " + command)
195*27162e4eSAndroid Build Coastguard Worker    popen = subprocess.Popen(command.split(" "), stdout=subprocess.PIPE, stderr=subprocess.PIPE)
196*27162e4eSAndroid Build Coastguard Worker    stdout_lines, stderr_lines = popen.communicate()
197*27162e4eSAndroid Build Coastguard Worker    stderr_lines = stderr_lines.decode("utf-8")
198*27162e4eSAndroid Build Coastguard Worker    stdout_lines = stdout_lines.decode("utf-8")
199*27162e4eSAndroid Build Coastguard Worker    if print_output:
200*27162e4eSAndroid Build Coastguard Worker        if stdout_lines:
201*27162e4eSAndroid Build Coastguard Worker            print(stdout_lines)
202*27162e4eSAndroid Build Coastguard Worker        if stderr_lines:
203*27162e4eSAndroid Build Coastguard Worker            print(stderr_lines)
204*27162e4eSAndroid Build Coastguard Worker    if popen.returncode is not None and popen.returncode != 0:
205*27162e4eSAndroid Build Coastguard Worker        if stderr_lines and not print_output and print_error:
206*27162e4eSAndroid Build Coastguard Worker            print(stderr_lines)
207*27162e4eSAndroid Build Coastguard Worker        errout(f"Failed to run: {command}, {stdout_lines + stderr_lines}\n")
208*27162e4eSAndroid Build Coastguard Worker    return (stdout_lines).splitlines()
209*27162e4eSAndroid Build Coastguard Worker
210*27162e4eSAndroid Build Coastguard Worker
211*27162e4eSAndroid Build Coastguard Workerdef cleanup(silent=False):
212*27162e4eSAndroid Build Coastguard Worker    for f in glob.glob(f"{TEMP}/test_list*"):
213*27162e4eSAndroid Build Coastguard Worker        if not silent:
214*27162e4eSAndroid Build Coastguard Worker            log(f"Deleting {f}")
215*27162e4eSAndroid Build Coastguard Worker        os.unlink(f)
216*27162e4eSAndroid Build Coastguard Worker
217*27162e4eSAndroid Build Coastguard Worker
218*27162e4eSAndroid Build Coastguard Workerdef datagen(file_name, size):
219*27162e4eSAndroid Build Coastguard Worker    non_sparse_size = size // 2
220*27162e4eSAndroid Build Coastguard Worker    sparse_size = size - non_sparse_size
221*27162e4eSAndroid Build Coastguard Worker    with open(file_name, "wb") as f:
222*27162e4eSAndroid Build Coastguard Worker        f.seek(sparse_size)
223*27162e4eSAndroid Build Coastguard Worker        f.write(os.urandom(non_sparse_size))
224*27162e4eSAndroid Build Coastguard Worker
225*27162e4eSAndroid Build Coastguard Worker
226*27162e4eSAndroid Build Coastguard Workerdef generate_files():
227*27162e4eSAndroid Build Coastguard Worker    # file format  ~ test_list<frametype>-<no_frames>f<create-args>.lz4 ~
228*27162e4eSAndroid Build Coastguard Worker    # Generate LZ4Frames
229*27162e4eSAndroid Build Coastguard Worker    for i in SIZES:
230*27162e4eSAndroid Build Coastguard Worker        filename = f"{TEMP}/test_list_{i}M"
231*27162e4eSAndroid Build Coastguard Worker        log(f"Generating {filename}")
232*27162e4eSAndroid Build Coastguard Worker        datagen(filename, i * MIB)
233*27162e4eSAndroid Build Coastguard Worker        for j in ["--content-size", "-BI", "-BD", "-BX", "--no-frame-crc"]:
234*27162e4eSAndroid Build Coastguard Worker            lz4file = f"{filename}-lz4f-1f{j}.lz4"
235*27162e4eSAndroid Build Coastguard Worker            execute(f"{LZ4} {j} {filename} {lz4file}")
236*27162e4eSAndroid Build Coastguard Worker        # Generate skippable frames
237*27162e4eSAndroid Build Coastguard Worker        lz4file = f"{filename}-skip-1f.lz4"
238*27162e4eSAndroid Build Coastguard Worker        skipsize = i * 1024
239*27162e4eSAndroid Build Coastguard Worker        skipbytes = bytes([80, 42, 77, 24]) + skipsize.to_bytes(4, byteorder='little', signed=False)
240*27162e4eSAndroid Build Coastguard Worker        with open(lz4file, 'wb') as f:
241*27162e4eSAndroid Build Coastguard Worker            f.write(skipbytes)
242*27162e4eSAndroid Build Coastguard Worker            f.write(os.urandom(skipsize))
243*27162e4eSAndroid Build Coastguard Worker        # Generate legacy frames
244*27162e4eSAndroid Build Coastguard Worker        lz4file = f"{filename}-legc-1f.lz4"
245*27162e4eSAndroid Build Coastguard Worker        execute(f"{LZ4} -l {filename} {lz4file}")
246*27162e4eSAndroid Build Coastguard Worker
247*27162e4eSAndroid Build Coastguard Worker    # Concatenate --content-size files
248*27162e4eSAndroid Build Coastguard Worker    file_list = glob.glob(f"{TEMP}/test_list_*-lz4f-1f--content-size.lz4")
249*27162e4eSAndroid Build Coastguard Worker    with open(f"{TEMP}/test_list_{sum(SIZES)}M-lz4f-2f--content-size.lz4", 'ab') as outfile:
250*27162e4eSAndroid Build Coastguard Worker        for fname in file_list:
251*27162e4eSAndroid Build Coastguard Worker            with open(fname, 'rb') as infile:
252*27162e4eSAndroid Build Coastguard Worker                outfile.write(infile.read())
253*27162e4eSAndroid Build Coastguard Worker
254*27162e4eSAndroid Build Coastguard Worker    # Concatenate all files
255*27162e4eSAndroid Build Coastguard Worker    file_list = glob.glob(f"{TEMP}/test_list_*.lz4")
256*27162e4eSAndroid Build Coastguard Worker    with open(f"{TEMP}/test_list_concat-all.lz4", 'ab') as outfile:
257*27162e4eSAndroid Build Coastguard Worker        for fname in file_list:
258*27162e4eSAndroid Build Coastguard Worker            with open(fname, 'rb') as infile:
259*27162e4eSAndroid Build Coastguard Worker                outfile.write(infile.read())
260*27162e4eSAndroid Build Coastguard Worker
261*27162e4eSAndroid Build Coastguard Worker
262*27162e4eSAndroid Build Coastguard Workerif __name__ == '__main__':
263*27162e4eSAndroid Build Coastguard Worker    cleanup()
264*27162e4eSAndroid Build Coastguard Worker    generate_files()
265*27162e4eSAndroid Build Coastguard Worker    ret = unittest.main(verbosity=2, exit=False)
266*27162e4eSAndroid Build Coastguard Worker    cleanup(silent=True)
267*27162e4eSAndroid Build Coastguard Worker    sys.exit(not ret.result.wasSuccessful())
268