xref: /qemu/tests/functional/qemu_test/tuxruntest.py (revision c9daf680d1ea34097f367527046a9229279aa1e9)
1c1b24f0fSThomas Huth# Functional test that boots known good tuxboot images the same way
2c1b24f0fSThomas Huth# that tuxrun (www.tuxrun.org) does. This tool is used by things like
3c1b24f0fSThomas Huth# the LKFT project to run regression tests on kernels.
4c1b24f0fSThomas Huth#
5c1b24f0fSThomas Huth# Copyright (c) 2023 Linaro Ltd.
6c1b24f0fSThomas Huth#
7c1b24f0fSThomas Huth# Author:
8c1b24f0fSThomas Huth#  Alex Bennée <alex.bennee@linaro.org>
9c1b24f0fSThomas Huth#
10c1b24f0fSThomas Huth# SPDX-License-Identifier: GPL-2.0-or-later
11c1b24f0fSThomas Huth
12c1b24f0fSThomas Huthimport os
13*c9daf680SDaniel P. Berrangéimport stat
14c1b24f0fSThomas Huthimport time
15c1b24f0fSThomas Huth
16c1b24f0fSThomas Huthfrom qemu_test import QemuSystemTest
17c1b24f0fSThomas Huthfrom qemu_test import exec_command, exec_command_and_wait_for_pattern
18c1b24f0fSThomas Huthfrom qemu_test import wait_for_console_pattern
19c1b24f0fSThomas Huthfrom qemu_test import has_cmd, run_cmd, get_qemu_img
20c1b24f0fSThomas Huth
21c1b24f0fSThomas Huthclass TuxRunBaselineTest(QemuSystemTest):
22c1b24f0fSThomas Huth
23c1b24f0fSThomas Huth    KERNEL_COMMON_COMMAND_LINE = 'printk.time=0'
24c1b24f0fSThomas Huth    # Tests are ~10-40s, allow for --debug/--enable-gcov overhead
25c1b24f0fSThomas Huth    timeout = 100
26c1b24f0fSThomas Huth
27c1b24f0fSThomas Huth    def get_tag(self, tagname, default=None):
28c1b24f0fSThomas Huth        """
29c1b24f0fSThomas Huth        Get the metadata tag or return the default.
30c1b24f0fSThomas Huth        """
31c1b24f0fSThomas Huth        utag = self._get_unique_tag_val(tagname)
32c1b24f0fSThomas Huth        print(f"{tagname}/{default} -> {utag}")
33c1b24f0fSThomas Huth        if utag:
34c1b24f0fSThomas Huth            return utag
35c1b24f0fSThomas Huth
36c1b24f0fSThomas Huth        return default
37c1b24f0fSThomas Huth
38c1b24f0fSThomas Huth    def setUp(self):
39c1b24f0fSThomas Huth        super().setUp()
40c1b24f0fSThomas Huth
41c1b24f0fSThomas Huth        # We need zstd for all the tuxrun tests
42c1b24f0fSThomas Huth        # See https://github.com/avocado-framework/avocado/issues/5609
43c1b24f0fSThomas Huth        (has_zstd, msg) = has_cmd('zstd')
44c1b24f0fSThomas Huth        if has_zstd is False:
45c1b24f0fSThomas Huth            self.skipTest(msg)
46c1b24f0fSThomas Huth        self.zstd = 'zstd'
47c1b24f0fSThomas Huth
48c1b24f0fSThomas Huth        # Pre-init TuxRun specific settings: Most machines work with
49c1b24f0fSThomas Huth        # reasonable defaults but we sometimes need to tweak the
50c1b24f0fSThomas Huth        # config. To avoid open coding everything we store all these
51c1b24f0fSThomas Huth        # details in the metadata for each test.
52c1b24f0fSThomas Huth
53c1b24f0fSThomas Huth        # The tuxboot tag matches the root directory
54c1b24f0fSThomas Huth        self.tuxboot = self.arch
55c1b24f0fSThomas Huth
56c1b24f0fSThomas Huth        # Most Linux's use ttyS0 for their serial port
57c1b24f0fSThomas Huth        self.console = "ttyS0"
58c1b24f0fSThomas Huth
59c1b24f0fSThomas Huth        # Does the machine shutdown QEMU nicely on "halt"
60c1b24f0fSThomas Huth        self.wait_for_shutdown = True
61c1b24f0fSThomas Huth
62c1b24f0fSThomas Huth        self.root = "vda"
63c1b24f0fSThomas Huth
64c1b24f0fSThomas Huth        # Occasionally we need extra devices to hook things up
65c1b24f0fSThomas Huth        self.extradev = None
66c1b24f0fSThomas Huth
67c1b24f0fSThomas Huth        self.qemu_img = get_qemu_img(self)
68c1b24f0fSThomas Huth
69c1b24f0fSThomas Huth    def wait_for_console_pattern(self, success_message, vm=None):
70c1b24f0fSThomas Huth        wait_for_console_pattern(self, success_message,
71c1b24f0fSThomas Huth                                 failure_message='Kernel panic - not syncing',
72c1b24f0fSThomas Huth                                 vm=vm)
73c1b24f0fSThomas Huth
74c1b24f0fSThomas Huth    def fetch_tuxrun_assets(self, kernel_asset, rootfs_asset, dtb_asset=None):
75c1b24f0fSThomas Huth        """
76c1b24f0fSThomas Huth        Fetch the TuxBoot assets.
77c1b24f0fSThomas Huth        """
78c1b24f0fSThomas Huth        kernel_image =  kernel_asset.fetch()
79c1b24f0fSThomas Huth        disk_image_zst = rootfs_asset.fetch()
80c1b24f0fSThomas Huth
81*c9daf680SDaniel P. Berrangé        disk_image = self.workdir + "/rootfs.ext4"
82*c9daf680SDaniel P. Berrangé
83c1b24f0fSThomas Huth        run_cmd([self.zstd, "-f", "-d", disk_image_zst,
84*c9daf680SDaniel P. Berrangé                 "-o", disk_image])
85*c9daf680SDaniel P. Berrangé        # zstd copies source archive permissions for the output
86*c9daf680SDaniel P. Berrangé        # file, so must make this writable for QEMU
87*c9daf680SDaniel P. Berrangé        os.chmod(disk_image, stat.S_IRUSR | stat.S_IWUSR)
88c1b24f0fSThomas Huth
89c1b24f0fSThomas Huth        dtb = dtb_asset.fetch() if dtb_asset is not None else None
90c1b24f0fSThomas Huth
91*c9daf680SDaniel P. Berrangé        return (kernel_image, disk_image, dtb)
92c1b24f0fSThomas Huth
93c1b24f0fSThomas Huth    def prepare_run(self, kernel, disk, drive, dtb=None, console_index=0):
94c1b24f0fSThomas Huth        """
95c1b24f0fSThomas Huth        Setup to run and add the common parameters to the system
96c1b24f0fSThomas Huth        """
97c1b24f0fSThomas Huth        self.vm.set_console(console_index=console_index)
98c1b24f0fSThomas Huth
99c1b24f0fSThomas Huth        # all block devices are raw ext4's
100c1b24f0fSThomas Huth        blockdev = "driver=raw,file.driver=file," \
101c1b24f0fSThomas Huth            + f"file.filename={disk},node-name=hd0"
102c1b24f0fSThomas Huth
103c1b24f0fSThomas Huth        kcmd_line = self.KERNEL_COMMON_COMMAND_LINE
104c1b24f0fSThomas Huth        kcmd_line += f" root=/dev/{self.root}"
105c1b24f0fSThomas Huth        kcmd_line += f" console={self.console}"
106c1b24f0fSThomas Huth
107c1b24f0fSThomas Huth        self.vm.add_args('-kernel', kernel,
108c1b24f0fSThomas Huth                         '-append', kcmd_line,
109c1b24f0fSThomas Huth                         '-blockdev', blockdev)
110c1b24f0fSThomas Huth
111c1b24f0fSThomas Huth        # Sometimes we need extra devices attached
112c1b24f0fSThomas Huth        if self.extradev:
113c1b24f0fSThomas Huth            self.vm.add_args('-device', self.extradev)
114c1b24f0fSThomas Huth
115c1b24f0fSThomas Huth        self.vm.add_args('-device',
116c1b24f0fSThomas Huth                         f"{drive},drive=hd0")
117c1b24f0fSThomas Huth
118c1b24f0fSThomas Huth        # Some machines need an explicit DTB
119c1b24f0fSThomas Huth        if dtb:
120c1b24f0fSThomas Huth            self.vm.add_args('-dtb', dtb)
121c1b24f0fSThomas Huth
122c1b24f0fSThomas Huth    def run_tuxtest_tests(self, haltmsg):
123c1b24f0fSThomas Huth        """
124c1b24f0fSThomas Huth        Wait for the system to boot up, wait for the login prompt and
125c1b24f0fSThomas Huth        then do a few things on the console. Trigger a shutdown and
126c1b24f0fSThomas Huth        wait to exit cleanly.
127c1b24f0fSThomas Huth        """
128c1b24f0fSThomas Huth        self.wait_for_console_pattern("Welcome to TuxTest")
129c1b24f0fSThomas Huth        time.sleep(0.2)
130c1b24f0fSThomas Huth        exec_command(self, 'root')
131c1b24f0fSThomas Huth        time.sleep(0.2)
132c1b24f0fSThomas Huth        exec_command(self, 'cat /proc/interrupts')
133c1b24f0fSThomas Huth        time.sleep(0.1)
134c1b24f0fSThomas Huth        exec_command(self, 'cat /proc/self/maps')
135c1b24f0fSThomas Huth        time.sleep(0.1)
136c1b24f0fSThomas Huth        exec_command(self, 'uname -a')
137c1b24f0fSThomas Huth        time.sleep(0.1)
138c1b24f0fSThomas Huth        exec_command_and_wait_for_pattern(self, 'halt', haltmsg)
139c1b24f0fSThomas Huth
140c1b24f0fSThomas Huth        # Wait for VM to shut down gracefully if it can
141c1b24f0fSThomas Huth        if self.wait_for_shutdown:
142c1b24f0fSThomas Huth            self.vm.wait()
143c1b24f0fSThomas Huth        else:
144c1b24f0fSThomas Huth            self.vm.shutdown()
145c1b24f0fSThomas Huth
146c1b24f0fSThomas Huth    def common_tuxrun(self,
147c1b24f0fSThomas Huth                      kernel_asset,
148c1b24f0fSThomas Huth                      rootfs_asset,
149c1b24f0fSThomas Huth                      dtb_asset=None,
150c1b24f0fSThomas Huth                      drive="virtio-blk-device",
151c1b24f0fSThomas Huth                      haltmsg="reboot: System halted",
152c1b24f0fSThomas Huth                      console_index=0):
153c1b24f0fSThomas Huth        """
154c1b24f0fSThomas Huth        Common path for LKFT tests. Unless we need to do something
155c1b24f0fSThomas Huth        special with the command line we can process most things using
156c1b24f0fSThomas Huth        the tag metadata.
157c1b24f0fSThomas Huth        """
158c1b24f0fSThomas Huth        (kernel, disk, dtb) = self.fetch_tuxrun_assets(kernel_asset, rootfs_asset,
159c1b24f0fSThomas Huth                                                       dtb_asset)
160c1b24f0fSThomas Huth
161c1b24f0fSThomas Huth        self.prepare_run(kernel, disk, drive, dtb, console_index)
162c1b24f0fSThomas Huth        self.vm.launch()
163c1b24f0fSThomas Huth        self.run_tuxtest_tests(haltmsg)
164c1b24f0fSThomas Huth        os.remove(disk)
165