|
| 1 | +# Record/replay test that boots a Linux kernel |
| 2 | +# |
| 3 | +# Copyright (c) 2020 ISP RAS |
| 4 | +# |
| 5 | +# Author: |
| 6 | +# Pavel Dovgalyuk <[email protected]> |
| 7 | +# |
| 8 | +# This work is licensed under the terms of the GNU GPL, version 2 or |
| 9 | +# later. See the COPYING file in the top-level directory. |
| 10 | + |
| 11 | +import os |
| 12 | +import logging |
| 13 | +import time |
| 14 | + |
| 15 | +from avocado_qemu import wait_for_console_pattern |
| 16 | +from avocado.utils import archive |
| 17 | +from avocado.utils import process |
| 18 | +from boot_linux_console import LinuxKernelTest |
| 19 | + |
| 20 | +class ReplayKernel(LinuxKernelTest): |
| 21 | + """ |
| 22 | + Boots a Linux kernel in record mode and checks that the console |
| 23 | + is operational and the kernel command line is properly passed |
| 24 | + from QEMU to the kernel. |
| 25 | + Then replays the same scenario and verifies, that QEMU correctly |
| 26 | + terminates. |
| 27 | + """ |
| 28 | + |
| 29 | + timeout = 90 |
| 30 | + KERNEL_COMMON_COMMAND_LINE = 'printk.time=1 panic=-1 ' |
| 31 | + |
| 32 | + def run_vm(self, kernel_path, kernel_command_line, console_pattern, |
| 33 | + record, shift, args, replay_path): |
| 34 | + logger = logging.getLogger('replay') |
| 35 | + start_time = time.time() |
| 36 | + vm = self.get_vm() |
| 37 | + vm.set_console() |
| 38 | + if record: |
| 39 | + logger.info('recording the execution...') |
| 40 | + mode = 'record' |
| 41 | + else: |
| 42 | + logger.info('replaying the execution...') |
| 43 | + mode = 'replay' |
| 44 | + vm.add_args('-icount', 'shift=%s,rr=%s,rrfile=%s' % |
| 45 | + (shift, mode, replay_path), |
| 46 | + '-kernel', kernel_path, |
| 47 | + '-append', kernel_command_line, |
| 48 | + '-net', 'none', |
| 49 | + '-no-reboot') |
| 50 | + if args: |
| 51 | + vm.add_args(*args) |
| 52 | + vm.launch() |
| 53 | + self.wait_for_console_pattern(console_pattern, vm) |
| 54 | + if record: |
| 55 | + vm.shutdown() |
| 56 | + logger.info('finished the recording with log size %s bytes' |
| 57 | + % os.path.getsize(replay_path)) |
| 58 | + else: |
| 59 | + vm.wait() |
| 60 | + logger.info('successfully finished the replay') |
| 61 | + elapsed = time.time() - start_time |
| 62 | + logger.info('elapsed time %.2f sec' % elapsed) |
| 63 | + return elapsed |
| 64 | + |
| 65 | + def run_rr(self, kernel_path, kernel_command_line, console_pattern, |
| 66 | + shift=7, args=None): |
| 67 | + replay_path = os.path.join(self.workdir, 'replay.bin') |
| 68 | + t1 = self.run_vm(kernel_path, kernel_command_line, console_pattern, |
| 69 | + True, shift, args, replay_path) |
| 70 | + t2 = self.run_vm(kernel_path, kernel_command_line, console_pattern, |
| 71 | + False, shift, args, replay_path) |
| 72 | + logger = logging.getLogger('replay') |
| 73 | + logger.info('replay overhead {:.2%}'.format(t2 / t1 - 1)) |
0 commit comments