diff options
| author | Peter Maydell <peter.maydell@linaro.org> | 2024-11-26 11:33:48 +0000 |
|---|---|---|
| committer | Peter Maydell <peter.maydell@linaro.org> | 2024-11-26 11:33:48 +0000 |
| commit | b8ee011e40e4b83a32ea0e7dca24e1ab089f1e7f (patch) | |
| tree | 3189b7317c4c6e1a2b2eb798e9d01043eb0caf52 /tests/functional/qemu_test/cmd.py | |
| parent | bd5629db935a6c17c86ffbb6a39aa85eed807346 (diff) | |
| parent | f8f5923808031e1335fc6d280a4b959ed5d28608 (diff) | |
| download | focaccia-qemu-b8ee011e40e4b83a32ea0e7dca24e1ab089f1e7f.tar.gz focaccia-qemu-b8ee011e40e4b83a32ea0e7dca24e1ab089f1e7f.zip | |
Merge tag 'pull-9.2-rc2-updates-251124-1' of https://gitlab.com/stsquad/qemu into staging
testing, docs and plugin updates for rc2 - cleanup leftover avocado bits from functional test - ensure we keep functional logs for tests - improve test console handling to detect prompts - remove hacking timer.sleep() usage in functional tests - convert Aarch64 tuxrun tests to functional test - update Aarch64 tuxrun images to avoid corrupt blk I/O ops - auto-generate the TCG plugin API symbols to avoid missing them - fix rust pl011 model handling of DeviceID regs - update docs to refer to "commonly known identity" - convert aspeed tests to functional framework and remove hacky sleeps # -----BEGIN PGP SIGNATURE----- # # iQEzBAABCgAdFiEEZoWumedRZ7yvyN81+9DbCVqeKkQFAmdEZXEACgkQ+9DbCVqe # KkRdMAf+JoSdKn3ck/eji270bZ2Y3evgDuP/qOZlcBtUJJ7+bUvhEOnBMApwKRD8 # u63hz7M4LIV5k3mezlEADf+oEpZ2FR3nIDM0dTY2CXYZm6av+0dNV0qFhXwjkslk # aqJLiJYgNl3wsyn/ftYNLiBhCid0sOGMvEOFZI6ELBh5KH8eiNdyrsaD0GSmpwZi # BsZUi8TOKy6EBeWnco/FLBV8ZVZUHuHNBl84jUY/8g7cxGMJfK8KoqMJ5XYoiQoJ # 1dYDqFmoP24iQRks6K6beFRdS/CBet36Nhsv7We/gf17Msw5uFo7Cho+touRCMrK # AmVKFdOX/OqJAHqlEKquYAD7bPjpaA== # =Xa/M # -----END PGP SIGNATURE----- # gpg: Signature made Mon 25 Nov 2024 11:54:25 GMT # gpg: using RSA key 6685AE99E75167BCAFC8DF35FBD0DB095A9E2A44 # gpg: Good signature from "Alex Bennée (Master Work Key) <alex.bennee@linaro.org>" [full] # Primary key fingerprint: 6685 AE99 E751 67BC AFC8 DF35 FBD0 DB09 5A9E 2A44 * tag 'pull-9.2-rc2-updates-251124-1' of https://gitlab.com/stsquad/qemu: (28 commits) tests/functional: Remove sleep workarounds from Aspeed tests tests/functional: Convert Aspeed arm SDK tests tests/functional: Convert Aspeed aarch64 SDK tests docs: explicitly permit a "commonly known identity" with SoB rust/pl011: Fix range checks for device ID accesses plugins: eradicate qemu-plugins.symbols static file plugins: detect qemu plugin API symbols from header plugins: add missing export for qemu_plugin_num_vcpus tests/functional: update the aarch64 tuxrun tests tests/functional: Convert the Avocado aarch64 tuxrun tests tests/functional: avoid accessing log_filename on earlier failures tests/functional: add a QMP backdoor for debugging stalled tests tests/functional: remove time.sleep usage from tuxrun tests tests/functional: rewrite console handling to be bytewise tests/functional: require non-NULL success_message for console wait tests/functional: don't try to wait for the empty string tests/functional: logs details of console interaction operations tests/functional: enable debug logging for QEMUMachine tests/functional: honour requested test VM name in QEMUMachine tests/functional: put QEMUMachine logs in testcase log directory ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'tests/functional/qemu_test/cmd.py')
| -rw-r--r-- | tests/functional/qemu_test/cmd.py | 89 |
1 files changed, 73 insertions, 16 deletions
diff --git a/tests/functional/qemu_test/cmd.py b/tests/functional/qemu_test/cmd.py index cbabb1ceed..11c8334a7c 100644 --- a/tests/functional/qemu_test/cmd.py +++ b/tests/functional/qemu_test/cmd.py @@ -78,13 +78,77 @@ def run_cmd(args): def is_readable_executable_file(path): return os.path.isfile(path) and os.access(path, os.R_OK | os.X_OK) +# @test: functional test to fail if @failure is seen +# @vm: the VM whose console to process +# @success: a non-None string to look for +# @failure: a string to look for that triggers test failure, or None +# +# Read up to 1 line of text from @vm, looking for @success +# and optionally @failure. +# +# If @success or @failure are seen, immediately return True, +# even if end of line is not yet seen. ie remainder of the +# line is left unread. +# +# If end of line is seen, with neither @success or @failure +# return False +# +# If @failure is seen, then mark @test as failed +def _console_read_line_until_match(test, vm, success, failure): + msg = bytes([]) + done = False + while True: + c = vm.console_socket.recv(1) + if c is None: + done = True + test.fail( + f"EOF in console, expected '{success}'") + break + msg += c + + if success in msg: + done = True + break + if failure and failure in msg: + done = True + vm.console_socket.close() + test.fail( + f"'{failure}' found in console, expected '{success}'") + + if c == b'\n': + break + + console_logger = logging.getLogger('console') + try: + console_logger.debug(msg.decode().strip()) + except: + console_logger.debug(msg) + + return done + def _console_interaction(test, success_message, failure_message, send_string, keep_sending=False, vm=None): assert not keep_sending or send_string + assert success_message or send_string + if vm is None: vm = test.vm - console = vm.console_file - console_logger = logging.getLogger('console') + + test.log.debug( + f"Console interaction: success_msg='{success_message}' " + + f"failure_msg='{failure_message}' send_string='{send_string}'") + + # We'll process console in bytes, to avoid having to + # deal with unicode decode errors from receiving + # partial utf8 byte sequences + success_message_b = None + if success_message is not None: + success_message_b = success_message.encode() + + failure_message_b = None + if failure_message is not None: + failure_message_b = failure_message.encode() + while True: if send_string: vm.console_socket.sendall(send_string.encode()) @@ -92,25 +156,15 @@ def _console_interaction(test, success_message, failure_message, send_string = None # send only once # Only consume console output if waiting for something - if success_message is None and failure_message is None: + if success_message is None: if send_string is None: break continue - try: - msg = console.readline().decode().strip() - except UnicodeDecodeError: - msg = None - if not msg: - continue - console_logger.debug(msg) - if success_message is None or success_message in msg: + if _console_read_line_until_match(test, vm, + success_message_b, + failure_message_b): break - if failure_message and failure_message in msg: - console.close() - fail = 'Failure message found in console: "%s". Expected: "%s"' % \ - (failure_message, success_message) - test.fail(fail) def interrupt_interactive_console_until_pattern(test, success_message, failure_message=None, @@ -135,6 +189,7 @@ def interrupt_interactive_console_until_pattern(test, success_message, :param interrupt_string: a string to send to the console before trying to read a new line """ + assert success_message _console_interaction(test, success_message, failure_message, interrupt_string, True) @@ -149,6 +204,7 @@ def wait_for_console_pattern(test, success_message, failure_message=None, :param success_message: if this message appears, test succeeds :param failure_message: if this message appears, test fails """ + assert success_message _console_interaction(test, success_message, failure_message, None, vm=vm) def exec_command(test, command): @@ -177,6 +233,7 @@ def exec_command_and_wait_for_pattern(test, command, :param success_message: if this message appears, test succeeds :param failure_message: if this message appears, test fails """ + assert success_message _console_interaction(test, success_message, failure_message, command + '\r') def get_qemu_img(test): |