blob: 38064840dabe7b895e59c5e6e8a238cbf9f174b9 [file] [log] [blame]
Alex Bennée267fe572023-02-28 19:06:39 +00001# Functional test that boots known good tuxboot images the same way
2# that tuxrun (www.tuxrun.org) does. This tool is used by things like
3# the LKFT project to run regression tests on kernels.
4#
5# Copyright (c) 2023 Linaro Ltd.
6#
7# Author:
8# Alex Bennée <alex.bennee@linaro.org>
9#
10# SPDX-License-Identifier: GPL-2.0-or-later
11
12import os
13import time
Kautuk Consul6ee36242023-04-24 10:22:43 +010014import tempfile
Alex Bennée267fe572023-02-28 19:06:39 +000015
Alex Bennée9b45cc92023-12-01 09:36:28 +000016from avocado import skip, skipUnless
Alex Bennée267fe572023-02-28 19:06:39 +000017from avocado_qemu import QemuSystemTest
18from avocado_qemu import exec_command, exec_command_and_wait_for_pattern
19from avocado_qemu import wait_for_console_pattern
20from avocado.utils import process
21from avocado.utils.path import find_command
22
23class TuxRunBaselineTest(QemuSystemTest):
24 """
25 :avocado: tags=accel:tcg
26 """
27
28 KERNEL_COMMON_COMMAND_LINE = 'printk.time=0'
29 # Tests are ~10-40s, allow for --debug/--enable-gcov overhead
30 timeout = 100
31
32 def get_tag(self, tagname, default=None):
33 """
34 Get the metadata tag or return the default.
35 """
36 utag = self._get_unique_tag_val(tagname)
37 print(f"{tagname}/{default} -> {utag}")
38 if utag:
39 return utag
40
41 return default
42
43 def setUp(self):
44 super().setUp()
45
46 # We need zstd for all the tuxrun tests
47 # See https://github.com/avocado-framework/avocado/issues/5609
48 zstd = find_command('zstd', False)
49 if zstd is False:
50 self.cancel('Could not find "zstd", which is required to '
51 'decompress rootfs')
52 self.zstd = zstd
53
54 # Process the TuxRun specific tags, most machines work with
55 # reasonable defaults but we sometimes need to tweak the
56 # config. To avoid open coding everything we store all these
57 # details in the metadata for each test.
58
59 # The tuxboot tag matches the root directory
60 self.tuxboot = self.get_tag('tuxboot')
61
62 # Most Linux's use ttyS0 for their serial port
63 self.console = self.get_tag('console', "ttyS0")
64
65 # Does the machine shutdown QEMU nicely on "halt"
66 self.shutdown = self.get_tag('shutdown')
67
68 # The name of the kernel Image file
69 self.image = self.get_tag('image', "Image")
70
Alex Bennée267fe572023-02-28 19:06:39 +000071 self.root = self.get_tag('root', "vda")
72
73 # Occasionally we need extra devices to hook things up
74 self.extradev = self.get_tag('extradev')
75
Kautuk Consul6ee36242023-04-24 10:22:43 +010076 self.qemu_img = super().get_qemu_img()
77
Alex Bennée267fe572023-02-28 19:06:39 +000078 def wait_for_console_pattern(self, success_message, vm=None):
79 wait_for_console_pattern(self, success_message,
80 failure_message='Kernel panic - not syncing',
81 vm=vm)
82
Alex Bennéefa6ecc92023-04-24 10:22:33 +010083 def fetch_tuxrun_assets(self, csums=None, dt=None):
Alex Bennée267fe572023-02-28 19:06:39 +000084 """
85 Fetch the TuxBoot assets. They are stored in a standard way so we
86 use the per-test tags to fetch details.
87 """
Alex Bennéefa6ecc92023-04-24 10:22:33 +010088 base_url = f"https://storage.tuxboot.com/20230331/{self.tuxboot}/"
89
90 # empty hash if we weren't passed one
91 csums = {} if csums is None else csums
92 ksum = csums.get(self.image, None)
93 isum = csums.get("rootfs.ext4.zst", None)
94
95 kernel_image = self.fetch_asset(base_url + self.image,
96 asset_hash = ksum,
97 algorithm = "sha256")
98 disk_image_zst = self.fetch_asset(base_url + "rootfs.ext4.zst",
99 asset_hash = isum,
100 algorithm = "sha256")
Alex Bennée267fe572023-02-28 19:06:39 +0000101
102 cmd = f"{self.zstd} -d {disk_image_zst} -o {self.workdir}/rootfs.ext4"
103 process.run(cmd)
104
105 if dt:
Alex Bennéefa6ecc92023-04-24 10:22:33 +0100106 dsum = csums.get(dt, None)
107 dtb = self.fetch_asset(base_url + dt,
108 asset_hash = dsum,
109 algorithm = "sha256")
Alex Bennée267fe572023-02-28 19:06:39 +0000110 else:
111 dtb = None
112
113 return (kernel_image, self.workdir + "/rootfs.ext4", dtb)
114
Alex Bennéefb3af2d2023-03-15 17:43:09 +0000115 def prepare_run(self, kernel, disk, drive, dtb=None, console_index=0):
Alex Bennée267fe572023-02-28 19:06:39 +0000116 """
117 Setup to run and add the common parameters to the system
118 """
119 self.vm.set_console(console_index=console_index)
120
121 # all block devices are raw ext4's
122 blockdev = "driver=raw,file.driver=file," \
123 + f"file.filename={disk},node-name=hd0"
124
125 kcmd_line = self.KERNEL_COMMON_COMMAND_LINE
126 kcmd_line += f" root=/dev/{self.root}"
127 kcmd_line += f" console={self.console}"
128
129 self.vm.add_args('-kernel', kernel,
130 '-append', kcmd_line,
131 '-blockdev', blockdev)
132
133 # Sometimes we need extra devices attached
134 if self.extradev:
135 self.vm.add_args('-device', self.extradev)
136
Alex Bennéefb3af2d2023-03-15 17:43:09 +0000137 self.vm.add_args('-device',
138 f"{drive},drive=hd0")
Alex Bennée267fe572023-02-28 19:06:39 +0000139
140 # Some machines need an explicit DTB
141 if dtb:
142 self.vm.add_args('-dtb', dtb)
143
144 def run_tuxtest_tests(self, haltmsg):
145 """
146 Wait for the system to boot up, wait for the login prompt and
147 then do a few things on the console. Trigger a shutdown and
148 wait to exit cleanly.
149 """
150 self.wait_for_console_pattern("Welcome to TuxTest")
151 time.sleep(0.2)
152 exec_command(self, 'root')
153 time.sleep(0.2)
154 exec_command(self, 'cat /proc/interrupts')
155 time.sleep(0.1)
156 exec_command(self, 'cat /proc/self/maps')
157 time.sleep(0.1)
158 exec_command(self, 'uname -a')
159 time.sleep(0.1)
160 exec_command_and_wait_for_pattern(self, 'halt', haltmsg)
161
162 # Wait for VM to shut down gracefully if it can
163 if self.shutdown == "nowait":
164 self.vm.shutdown()
165 else:
166 self.vm.wait()
167
Alex Bennéefa6ecc92023-04-24 10:22:33 +0100168 def common_tuxrun(self,
169 csums=None,
170 dt=None,
Alex Bennéefb3af2d2023-03-15 17:43:09 +0000171 drive="virtio-blk-device",
172 haltmsg="reboot: System halted",
Alex Bennée267fe572023-02-28 19:06:39 +0000173 console_index=0):
174 """
175 Common path for LKFT tests. Unless we need to do something
176 special with the command line we can process most things using
177 the tag metadata.
178 """
Alex Bennéefa6ecc92023-04-24 10:22:33 +0100179 (kernel, disk, dtb) = self.fetch_tuxrun_assets(csums, dt)
Alex Bennée267fe572023-02-28 19:06:39 +0000180
Alex Bennéefb3af2d2023-03-15 17:43:09 +0000181 self.prepare_run(kernel, disk, drive, dtb, console_index)
Alex Bennée267fe572023-02-28 19:06:39 +0000182 self.vm.launch()
183 self.run_tuxtest_tests(haltmsg)
184
Kautuk Consul6ee36242023-04-24 10:22:43 +0100185
Alex Bennée267fe572023-02-28 19:06:39 +0000186 #
187 # The tests themselves. The configuration is derived from how
188 # tuxrun invokes qemu (with minor tweaks like using -blockdev
189 # consistently). The tuxrun equivalent is something like:
190 #
191 # tuxrun --device qemu-{ARCH} \
192 # --kernel https://storage.tuxboot.com/{TUXBOOT}/{IMAGE}
193 #
194
195 def test_arm64(self):
196 """
197 :avocado: tags=arch:aarch64
198 :avocado: tags=cpu:cortex-a57
199 :avocado: tags=machine:virt
200 :avocado: tags=tuxboot:arm64
201 :avocado: tags=console:ttyAMA0
202 :avocado: tags=shutdown:nowait
203 """
Alex Bennéefa6ecc92023-04-24 10:22:33 +0100204 sums = {"Image" :
205 "ce95a7101a5fecebe0fe630deee6bd97b32ba41bc8754090e9ad8961ea8674c7",
206 "rootfs.ext4.zst" :
207 "bbd5ed4b9c7d3f4ca19ba71a323a843c6b585e880115df3b7765769dbd9dd061"}
208 self.common_tuxrun(csums=sums)
Alex Bennée267fe572023-02-28 19:06:39 +0000209
210 def test_arm64be(self):
211 """
212 :avocado: tags=arch:aarch64
213 :avocado: tags=cpu:cortex-a57
214 :avocado: tags=endian:big
215 :avocado: tags=machine:virt
216 :avocado: tags=tuxboot:arm64be
217 :avocado: tags=console:ttyAMA0
218 :avocado: tags=shutdown:nowait
219 """
Alex Bennéefa6ecc92023-04-24 10:22:33 +0100220 sums = { "Image" :
221 "e0df4425eb2cd9ea9a283e808037f805641c65d8fcecc8f6407d8f4f339561b4",
222 "rootfs.ext4.zst" :
223 "e6ffd8813c8a335bc15728f2835f90539c84be7f8f5f691a8b01451b47fb4bd7"}
224 self.common_tuxrun(csums=sums)