From nobody Sun Sep 28 16:32:33 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1757701434; cv=none; d=zohomail.com; s=zohoarc; b=hYlDHSP3e5f0/b6tfyVW4xokRzjCbgH4pdvwzYZLuhoGe5TRnKd/sFKCVygNK3Co7buJ/DuLbJzUj2tjBZPL97XVrBkI0Di0Y+yujKnQm4VRTsvieRAuMrh49GLLdS8QORr1407SypBoY9d8Pue3iWVWUGbkaQ5Ez8MtFHOSV0E= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1757701434; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=qIORJberizBZ1QFQWihvovMmrYhgEpRz/6jxhp5LxgY=; b=HyAVQhNq9M26Ox7gRJ4MG+dftpBtw2bsYRo235S+KQlFAlBLGxz1XaKxWIWEPauWGz6L375LSqVQVwSK66o3AaqZcW0+eqip3jNwqTiS4XaSdLgQDlLaV39j4UsZRJdIY2wD6HnnW5daIZcR4NwNDo3SpuOEf81vlqNEWKPAoak= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1757701434690296.3848642811081; Fri, 12 Sep 2025 11:23:54 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ux8Pe-0004Ww-Cu; Fri, 12 Sep 2025 14:22:22 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ux8Pa-0004VL-5g for qemu-devel@nongnu.org; Fri, 12 Sep 2025 14:22:18 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ux8PU-0005Fe-ER for qemu-devel@nongnu.org; Fri, 12 Sep 2025 14:22:17 -0400 Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-693-nYnPnRElOtO3AdMqWAdTIQ-1; Fri, 12 Sep 2025 14:22:07 -0400 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id E9DFA1800359 for ; Fri, 12 Sep 2025 18:22:06 +0000 (UTC) Received: from toolbx.redhat.com (unknown [10.42.28.154]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id E8C4C18003FC; Fri, 12 Sep 2025 18:22:04 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1757701331; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=qIORJberizBZ1QFQWihvovMmrYhgEpRz/6jxhp5LxgY=; b=W9wGaNBDxjgNWTboQ4oxjTc4PduxddjH6uW367WW2Hxb+aSeQvyOccPECOW9P5OoLCfL5I /fk73neDEnFRKChzsIxdfJdFK/89vakdgxaGt038IP7iDHo8Y3Z6+kzLdlzK/YWL8gd9Bm OBit9SHP0prOsZC9A6DbiJm1QSvoQLI= X-MC-Unique: nYnPnRElOtO3AdMqWAdTIQ-1 X-Mimecast-MFC-AGG-ID: nYnPnRElOtO3AdMqWAdTIQ_1757701327 From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= To: qemu-devel@nongnu.org Cc: Thomas Huth , =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= Subject: [PATCH 1/6] tests/functional: import GDB remote code from avocado Date: Fri, 12 Sep 2025 19:21:55 +0100 Message-ID: <20250912182200.643909-2-berrange@redhat.com> In-Reply-To: <20250912182200.643909-1-berrange@redhat.com> References: <20250912182200.643909-1-berrange@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.129.124; envelope-from=berrange@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1757701437408116600 The gdbmi_parser.py and spark.py modules originated in projects that pre-date avocado and are imported unchanged aside from the 'import' statement in gdbmi_parser.py The gdb.py module is original avocado code that is imported with all classes except GDBRemote removed. Signed-off-by: Daniel P. Berrang=C3=A9 Acked-by: Alex Benn=C3=A9e --- tests/functional/qemu_test/gdb.py | 233 ++++++ tests/functional/qemu_test/gdbmi_parser.py | 419 ++++++++++ tests/functional/qemu_test/spark.py | 850 +++++++++++++++++++++ 3 files changed, 1502 insertions(+) create mode 100644 tests/functional/qemu_test/gdb.py create mode 100644 tests/functional/qemu_test/gdbmi_parser.py create mode 100644 tests/functional/qemu_test/spark.py diff --git a/tests/functional/qemu_test/gdb.py b/tests/functional/qemu_test= /gdb.py new file mode 100644 index 0000000000..913e3b65ab --- /dev/null +++ b/tests/functional/qemu_test/gdb.py @@ -0,0 +1,233 @@ +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# +# A cut-down copy of gdb.py from the avocado project: +# +# Copyright: Red Hat Inc. 2014 +# Authors: Cleber Rosa + +__all__ =3D ["GDB", "GDBServer", "GDBRemote"] + + +import socket + +from . import gdbmi_parser + +#: How the remote protocol signals a transmission success (in ACK mode) +REMOTE_TRANSMISSION_SUCCESS =3D "+" + +#: How the remote protocol signals a transmission failure (in ACK mode) +REMOTE_TRANSMISSION_FAILURE =3D "-" + +#: How the remote protocol flags the start of a packet +REMOTE_PREFIX =3D b"$" + +#: How the remote protocol flags the end of the packet payload, and that t= he +#: two digits checksum follow +REMOTE_DELIMITER =3D b"#" + +#: Rather conservative default maximum packet size for clients using the +#: remote protocol. Individual connections can ask (and do so by default) +#: the server about the maximum packet size they can handle. +REMOTE_MAX_PACKET_SIZE =3D 1024 + + +class UnexpectedResponseError(Exception): + """A response different from the one expected was received from GDB""" + + +class ServerInitTimeoutError(Exception): + """Server took longer than expected to initialize itself properly""" + + +class InvalidPacketError(Exception): + """Packet received has invalid format""" + + +class NotConnectedError(Exception): + """GDBRemote is not connected to a remote GDB server""" + + +class RetransmissionRequestedError(Exception): + """Message integrity was not validated and retransmission is being req= uested""" + + + +class GDBRemote: + """A GDBRemote acts like a client that speaks the GDB remote protocol, + documented at: + + https://sourceware.org/gdb/current/onlinedocs/gdb/Remote-Protocol.html + + Caveat: we currently do not support communicating with devices, only + with TCP sockets. This limitation is basically due to the lack of + use cases that justify an implementation, but not due to any technical + shortcoming. + """ + + def __init__(self, host, port, no_ack_mode=3DTrue, extended_mode=3DTru= e): + """Initializes a new GDBRemote object. + + :param host: the IP address or host name + :type host: str + :param port: the port number where the the remote GDB is listening= on + :type port: int + :param no_ack_mode: if the packet transmission confirmation mode s= hould + be disabled + :type no_ack_mode: bool + :param extended_mode: if the remote extended mode should be enabled + :type param extended_mode: bool + """ + self.host =3D host + self.port =3D port + + # Temporary holder for the class init attributes + self._no_ack_mode =3D no_ack_mode + self.no_ack_mode =3D False + self._extended_mode =3D extended_mode + self.extended_mode =3D False + + self._socket =3D None + + @staticmethod + def checksum(input_message): + """Calculates a remote message checksum. + + More details are available at: + https://sourceware.org/gdb/current/onlinedocs/gdb/Overview.html + + :param input_message: the message input payload, without the + start and end markers + :type input_message: bytes + :returns: two byte checksum + :rtype: bytes + """ + total =3D 0 + for i in input_message: + total +=3D i + result =3D total % 256 + + return b"%02x" % result + + @staticmethod + def encode(data): + """Encodes a command. + + That is, add prefix, suffix and checksum. + + More details are available at: + https://sourceware.org/gdb/current/onlinedocs/gdb/Overview.html + + :param data: the command data payload + :type data: bytes + :returns: the encoded command, ready to be sent to a remote GDB + :rtype: bytes + """ + return b"$%b#%b" % (data, GDBRemote.checksum(data)) + + @staticmethod + def decode(data): + """Decodes a packet and returns its payload. + + More details are available at: + https://sourceware.org/gdb/current/onlinedocs/gdb/Overview.html + + :param data: the command data payload + :type data: bytes + :returns: the encoded command, ready to be sent to a remote GDB + :rtype: bytes + :raises InvalidPacketError: if the packet is not well constructed, + like in checksum mismatches + """ + if data[0:1] !=3D REMOTE_PREFIX: + raise InvalidPacketError + + if data[-3:-2] !=3D REMOTE_DELIMITER: + raise InvalidPacketError + + payload =3D data[1:-3] + checksum =3D data[-2:] + + if payload =3D=3D b"": + expected_checksum =3D b"00" + else: + expected_checksum =3D GDBRemote.checksum(payload) + + if checksum !=3D expected_checksum: + raise InvalidPacketError + + return payload + + def cmd(self, command_data, expected_response=3DNone): + """Sends a command data to a remote gdb server + + Limitations: the current version does not deal with retransmission= s. + + :param command_data: the remote command to send the the remote stub + :type command_data: str + :param expected_response: the (optional) response that is expected + as a response for the command sent + :type expected_response: str + :raises: RetransmissionRequestedError, UnexpectedResponseError + :returns: raw data read from from the remote server + :rtype: str + :raises NotConnectedError: if the socket is not initialized + :raises RetransmissionRequestedError: if there was a failure while + reading the result of the co= mmand + :raises UnexpectedResponseError: if response is unexpected + """ + if self._socket is None: + raise NotConnectedError + + data =3D self.encode(command_data) + self._socket.send(data) + + if not self.no_ack_mode: + transmission_result =3D self._socket.recv(1) + if transmission_result =3D=3D REMOTE_TRANSMISSION_FAILURE: + raise RetransmissionRequestedError + + result =3D self._socket.recv(REMOTE_MAX_PACKET_SIZE) + response_payload =3D self.decode(result) + + if expected_response is not None: + if expected_response !=3D response_payload: + raise UnexpectedResponseError + + return response_payload + + def set_extended_mode(self): + """Enable extended mode. In extended mode, the remote server is ma= de + persistent. The 'R' packet is used to restart the program being + debugged. Original documentation at: + + https://sourceware.org/gdb/current/onlinedocs/gdb/Packets.html#ext= ended-mode + """ + self.cmd(b"!", b"OK") + self.extended_mode =3D True + + def start_no_ack_mode(self): + """Request that the remote stub disable the normal +/- protocol + acknowledgments. Original documentation at: + + https://sourceware.org/gdb/current/onlinedocs/gdb/General-Query-Pa= ckets.html#QStartNoAckMode + """ + self.cmd(b"QStartNoAckMode", b"OK") + self.no_ack_mode =3D True + + def connect(self): + """Connects to the remote target and initializes the chosen modes"= "" + self._socket =3D socket.socket(socket.AF_INET, socket.SOCK_STREAM) + self._socket.connect((self.host, self.port)) + + if self._no_ack_mode: + self.start_no_ack_mode() + + if self._extended_mode: + self.set_extended_mode() diff --git a/tests/functional/qemu_test/gdbmi_parser.py b/tests/functional/= qemu_test/gdbmi_parser.py new file mode 100644 index 0000000000..476e824b72 --- /dev/null +++ b/tests/functional/qemu_test/gdbmi_parser.py @@ -0,0 +1,419 @@ +# +# Copyright (c) 2008 Michael Eddington +# +# Permission is hereby granted, free of charge, to any person obtaining a = copy +# of this software and associated documentation files (the "Software"), to= deal +# in the Software without restriction, including without limitation the ri= ghts +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included = in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS = OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL = THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING = FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS I= N THE +# SOFTWARE. +# +# Authors: +# Frank Laub (frank.laub@gmail.com) +# Michael Eddington (mike@phed.org) + + +import pprint +import re + +from . import spark + + +class GdbMiError(Exception): + """ + Exception raised when there is an error parsing GDB/MI output. + """ + + +class Token: + def __init__(self, token_type, value=3DNone): + self.type =3D token_type + self.value =3D value + + def __lt__(self, o): + return self.type < o + + def __gt__(self, o): + return self.type > o + + def __le__(self, o): + return self.type <=3D o + + def __ge__(self, o): + return self.type >=3D o + + def __eq__(self, o): + return self.type =3D=3D o + + def __ne__(self, o): + return self.type !=3D o + + def __repr__(self): + return self.value or self.type + + +class AST: + def __init__(self, ast_type): + self.type =3D ast_type + self._kids =3D [] + + def __getitem__(self, i): + return self._kids[i] + + def __setitem__(self, i, k): + self._kids[i] =3D k + + def __len__(self): + return len(self._kids) + + def __lt__(self, o): + return self.type < o + + def __gt__(self, o): + return self.type > o + + def __le__(self, o): + return self.type <=3D o + + def __ge__(self, o): + return self.type >=3D o + + def __eq__(self, o): + return self.type =3D=3D o + + def __ne__(self, o): + return self.type !=3D o + + +class GdbMiScannerBase(spark.GenericScanner): + def tokenize(self, s): # pylint: disable=3DW0221 + self.rv =3D [] # pylint: disable=3DW0201 + spark.GenericScanner.tokenize(self, s) + return self.rv + + def t_nl(self, s): # pylint: disable=3DW0613 + r"\n|\r\n" + self.rv.append(Token("nl")) + + def t_whitespace(self, s): # pylint: disable=3DW0613 + r"[ \t\f\v]+" + + def t_symbol(self, s): + r",|\{|\}|\[|\]|\=3D" + self.rv.append(Token(s, s)) + + def t_result_type(self, s): + r"\*|\+|\^" + self.rv.append(Token("result_type", s)) + + def t_stream_type(self, s): + r"\@|\&|\~" + self.rv.append(Token("stream_type", s)) + + def t_string(self, s): + r"[\w-]+" + self.rv.append(Token("string", s)) + + def t_c_string(self, s): + r"\".*?(? 2: + print(f"{tokens[i - 3]} {tokens[i - 2]} " f"{tokens[i - 1]} {t= okens[i]}") + raise GdbMiError(f"Syntax error at or near {int(i)}:'{token}' toke= n") + + +class GdbMiInterpreter(spark.GenericASTTraversal): + def __init__(self, ast): + spark.GenericASTTraversal.__init__(self, ast) + self.postorder() + + @staticmethod + def __translate_type(token_type): + table =3D { + "^": "result", + "=3D": "notify", + "+": "status", + "*": "exec", + "~": "console", + "@": "target", + "&": "log", + } + return table[token_type] + + @staticmethod + def n_result(node): + # result ::=3D variable =3D value + node.value =3D {node[0].value: node[2].value} + # print 'result: %s' % node.value + + @staticmethod + def n_tuple(node): + if len(node) =3D=3D 2: + # tuple ::=3D {} + node.value =3D {} + elif len(node) =3D=3D 3: + # tuple ::=3D { result } + node.value =3D node[1].value + elif len(node) =3D=3D 4: + # tuple ::=3D { result result_list } + node.value =3D node[1].value + for result in node[2].value: + for n, v in list(result.items()): + if n in node.value: + # print '**********list conversion: [%s] %s -> %s'= % (n, node.value[n], v) + old =3D node.value[n] + if not isinstance(old, list): + node.value[n] =3D [node.value[n]] + node.value[n].append(v) + else: + node.value[n] =3D v + else: + raise GdbMiError("Invalid tuple") + # print 'tuple: %s' % node.value + + @staticmethod + def n_list(node): + if len(node) =3D=3D 2: + # list ::=3D [] + node.value =3D [] + elif len(node) =3D=3D 3: + # list ::=3D [ value ] + node.value =3D [node[1].value] + elif len(node) =3D=3D 4: + # list ::=3D [ value value_list ] + node.value =3D [node[1].value] + node[2].value + # list ::=3D [ result ] + # list ::=3D [ result result_list ] + # list ::=3D { value } + # list ::=3D { value value_list } + # print 'list %s' % node.value + + @staticmethod + def n_value_list(node): + if len(node) =3D=3D 2: + # value_list ::=3D , value + node.value =3D [node[1].value] + elif len(node) =3D=3D 3: + # value_list ::=3D , value value_list + node.value =3D [node[1].value] + node[2].value + + @staticmethod + def n_result_list(node): + if len(node) =3D=3D 2: + # result_list ::=3D , result + node.value =3D [node[1].value] + else: + # result_list ::=3D , result result_list + node.value =3D [node[1].value] + node[2].value + # print 'result_list: %s' % node.value + + @staticmethod + def n_result_record(node): + node.value =3D node[0].value + if len(node) =3D=3D 3: + # result_record ::=3D result_header result_list nl + node.value["results"] =3D node[1].value + elif len(node) =3D=3D 2: + # result_record ::=3D result_header nl + pass + # print 'result_record: %s' % (node.value) + + def n_result_header(self, node): + if len(node) =3D=3D 3: + # result_header ::=3D token result_type class + node.value =3D { + "token": node[0].value, + "type": self.__translate_type(node[1].value), + "class_": node[2].value, + "record_type": "result", + } + elif len(node) =3D=3D 2: + # result_header ::=3D result_type class + node.value =3D { + "token": None, + "type": self.__translate_type(node[0].value), + "class_": node[1].value, + "record_type": "result", + } + + def n_stream_record(self, node): + # stream_record ::=3D stream_type c_string nl + node.value =3D { + "type": self.__translate_type(node[0].value), + "value": node[1].value, + "record_type": "stream", + } + # print 'stream_record: %s' % node.value + + @staticmethod + def n_record_list(node): + if len(node) =3D=3D 1: + # record_list ::=3D generic_record + node.value =3D [node[0].value] + elif len(node) =3D=3D 2: + # record_list ::=3D generic_record record_list + node.value =3D [node[0].value] + node[1].value + # print 'record_list: %s' % node.value + + # def default(self, node): + # print 'default: ' + node.type + + +class GdbDynamicObject: + def __init__(self, dict_): + self.graft(dict_) + + def __repr__(self): + return pprint.pformat(self.__dict__) + + def __bool__(self): + return len(self.__dict__) > 0 + + def __getitem__(self, i): + if not i and len(self.__dict__) > 0: + return self + raise IndexError + + def __getattr__(self, name): + if name.startswith("__"): + raise AttributeError + + def graft(self, dict_): + for name, value in list(dict_.items()): + name =3D name.replace("-", "_") + if isinstance(value, dict): + value =3D GdbDynamicObject(value) + elif isinstance(value, list): + x =3D value + value =3D [] + for item in x: + if isinstance(item, dict): + item =3D GdbDynamicObject(item) + value.append(item) + setattr(self, name, value) + + +class GdbMiRecord: + def __init__(self, record): + self.result =3D None + for name, value in list(record[0].items()): + name =3D name.replace("-", "_") + if name =3D=3D "results": + for result in value: + if not self.result: + self.result =3D GdbDynamicObject(result) + else: + # graft this result to self.results + self.result.graft(result) + else: + setattr(self, name, value) + + def __repr__(self): + return pprint.pformat(self.__dict__) + + +class session: # pylint: disable=3DC0103 + def __init__(self): + self.the_scanner =3D GdbMiScanner() + self.the_parser =3D GdbMiParser() + self.the_interpreter =3D GdbMiInterpreter + self.the_output =3D GdbMiRecord + + def scan(self, data_input): + return self.the_scanner.tokenize(data_input) + + def parse(self, tokens): + return self.the_parser.parse(tokens) + + def process(self, data_input): + tokens =3D self.scan(data_input) + ast =3D self.parse(tokens) + self.the_interpreter(ast) + return self.the_output(ast.value) diff --git a/tests/functional/qemu_test/spark.py b/tests/functional/qemu_te= st/spark.py new file mode 100644 index 0000000000..1f98b9508c --- /dev/null +++ b/tests/functional/qemu_test/spark.py @@ -0,0 +1,850 @@ +# Copyright (c) 1998-2002 John Aycock +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +__version__ =3D "SPARK-0.7 (pre-alpha-7)" + +import re + + +def _namelist(instance): + namelist, namedict, classlist =3D [], {}, [instance.__class__] + for c in classlist: + for b in c.__bases__: + classlist.append(b) # pylint: disable=3DW4701 + for name in c.__dict__.keys(): + if name not in namedict: + namelist.append(name) + namedict[name] =3D 1 + return namelist + + +class GenericScanner: + def __init__(self, flags=3D0): + pattern =3D self.reflect() + self.re =3D re.compile(pattern, re.VERBOSE | flags) + + self.index2func =3D {} + for name, number in self.re.groupindex.items(): + self.index2func[number - 1] =3D getattr(self, "t_" + name) + + def makeRE(self, name): # pylint: disable=3DC0103 + doc =3D getattr(self, name).__doc__ + rv =3D f"(?P<{name[2:]}>{doc})" + return rv + + def reflect(self): + rv =3D [] + for name in _namelist(self): + if name[:2] =3D=3D "t_" and name !=3D "t_default": + rv.append(self.makeRE(name)) + + rv.append(self.makeRE("t_default")) + return "|".join(rv) + + @staticmethod + def error(s, pos): # pylint: disable=3DW0613 + print(f"Lexical error at position {pos}") + raise SystemExit + + def tokenize(self, s): + pos =3D 0 + n =3D len(s) + while pos < n: + m =3D self.re.match(s, pos) + if m is None: + self.error(s, pos) + + groups =3D m.groups() + for i, group in enumerate(groups): + if group and i in self.index2func: + self.index2func[i](group) + pos =3D m.end() + + @staticmethod + def t_default(s): # pylint: disable=3DW0613 + r"( . | \n )+" + print("Specification error: unmatched input") + raise SystemExit + + +# +# Extracted from GenericParser and made global so that [un]picking works. +# + + +class _State: + def __init__(self, stateno, items): + self.t, self.complete, self.items =3D [], [], items + self.stateno =3D stateno + + +# pylint: disable=3DR0902,R0904 +class GenericParser: + # + # An Earley parser, as per J. Earley, "An Efficient Context-Free + # Parsing Algorithm", CACM 13(2), pp. 94-102. Also J. C. Earley, + # "An Efficient Context-Free Parsing Algorithm", Ph.D. thesis, + # Carnegie-Mellon University, August 1968. New formulation of + # the parser according to J. Aycock, "Practical Earley Parsing + # and the SPARK Toolkit", Ph.D. thesis, University of Victoria, + # 2001, and J. Aycock and R. N. Horspool, "Practical Earley + # Parsing", unpublished paper, 2001. + # + + def __init__(self, start): + self.rules =3D {} + self.rule2func =3D {} + self.rule2name =3D {} + self.collectRules() + self.augment(start) + self.ruleschanged =3D 1 + + _NULLABLE =3D r"\e_" + _START =3D "START" + _BOF =3D "|-" + + # + # When pickling, take the time to generate the full state machine; + # some information is then extraneous, too. Unfortunately we + # can't save the rule2func map. + # + def __getstate__(self): + if self.ruleschanged: + # + # FIX ME - duplicated from parse() + # + self.computeNull() + self.newrules =3D {} # pylint: disable=3DW0201 + self.new2old =3D {} # pylint: disable=3DW0201 + self.makeNewRules() + self.ruleschanged =3D 0 + self.edges, self.cores =3D {}, {} # pylint: disable=3DW0201 + self.states =3D {0: self.makeState0()} # pylint: disable=3DW0= 201 + self.makeState(0, self._BOF) + # + # FIX ME - should find a better way to do this.. + # + changes =3D 1 + while changes: + changes =3D 0 + for k, v in self.edges.items(): + if v is None: + state, sym =3D k + if state in self.states: + self.goto(state, sym) + changes =3D 1 + rv =3D self.__dict__.copy() + for s in self.states.values(): + del s.items + del rv["rule2func"] + del rv["nullable"] + del rv["cores"] + return rv + + def __setstate__(self, d): + self.rules =3D {} + self.rule2func =3D {} + self.rule2name =3D {} + self.collectRules() + start =3D d["rules"][self._START][0][1][1] # Blech. + self.augment(start) + d["rule2func"] =3D self.rule2func + d["makeSet"] =3D self.makeSet_fast + self.__dict__ =3D d # pylint: disable=3DW0201 + + # + # A hook for GenericASTBuilder and GenericASTMatcher. Mess + # thee not with this; nor shall thee toucheth the _preprocess + # argument to addRule. + # + @staticmethod + def preprocess(rule, func): + return rule, func + + def addRule(self, doc, func, _preprocess=3D1): # pylint: disable=3DC0= 103 + fn =3D func + rules =3D doc.split() + + index =3D [] + for i, rule in enumerate(rules): + if rule =3D=3D "::=3D": + index.append(i - 1) + index.append(len(rules)) + + for i in range(len(index) - 1): + lhs =3D rules[index[i]] + rhs =3D rules[index[i] + 2 : index[i + 1]] + rule =3D (lhs, tuple(rhs)) + + if _preprocess: + rule, fn =3D self.preprocess(rule, func) + + if lhs in self.rules: + self.rules[lhs].append(rule) + else: + self.rules[lhs] =3D [rule] + self.rule2func[rule] =3D fn + self.rule2name[rule] =3D func.__name__[2:] + self.ruleschanged =3D 1 + + def collectRules(self): # pylint: disable=3DC0103 + for name in _namelist(self): + if name[:2] =3D=3D "p_": + func =3D getattr(self, name) + doc =3D func.__doc__ + self.addRule(doc, func) + + def augment(self, start): + rule =3D f"{self._START} ::=3D {self._BOF} {start}" + self.addRule(rule, lambda args: args[1], 0) + + def computeNull(self): # pylint: disable=3DC0103 + self.nullable =3D {} # pylint: disable=3DW0201 + tbd =3D [] + + for rulelist in self.rules.values(): + lhs =3D rulelist[0][0] + self.nullable[lhs] =3D 0 + for rule in rulelist: + rhs =3D rule[1] + if not rhs: + self.nullable[lhs] =3D 1 + continue + # + # We only need to consider rules which + # consist entirely of nonterminal symbols. + # This should be a savings on typical + # grammars. + # + for sym in rhs: + if sym not in self.rules: + break + else: + tbd.append(rule) + changes =3D 1 + while changes: + changes =3D 0 + for lhs, rhs in tbd: + if self.nullable[lhs]: + continue + for sym in rhs: + if not self.nullable[sym]: + break + else: + self.nullable[lhs] =3D 1 + changes =3D 1 + + def makeState0(self): # pylint: disable=3DC0103 + s0 =3D _State(0, []) + for rule in self.newrules[self._START]: + s0.items.append((rule, 0)) + return s0 + + def finalState(self, tokens): # pylint: disable=3DC0103 + # + # Yuck. + # + if len(self.newrules[self._START]) =3D=3D 2 and not tokens: + return 1 + start =3D self.rules[self._START][0][1][1] + return self.goto(1, start) + + def makeNewRules(self): # pylint: disable=3DC0103 + worklist =3D [] + for rulelist in self.rules.values(): + for rule in rulelist: + worklist.append((rule, 0, 1, rule)) + + for rule, i, candidate, oldrule in worklist: + lhs, rhs =3D rule + n =3D len(rhs) + while i < n: + sym =3D rhs[i] + if sym not in self.rules or not self.nullable[sym]: + candidate =3D 0 + i +=3D 1 + continue + + newrhs =3D list(rhs) + newrhs[i] =3D self._NULLABLE + sym + newrule =3D (lhs, tuple(newrhs)) + # pylint: disable=3DW4701 + worklist.append((newrule, i + 1, candidate, oldrule)) + candidate =3D 0 + i +=3D 1 + else: # pylint: disable=3DW0120 + if candidate: + lhs =3D self._NULLABLE + lhs + rule =3D (lhs, rhs) + if lhs in self.newrules: + self.newrules[lhs].append(rule) + else: + self.newrules[lhs] =3D [rule] + self.new2old[rule] =3D oldrule + + @staticmethod + def typestring(token): # pylint: disable=3DW0613 + return None + + @staticmethod + def error(token): + print(f"Syntax error at or near `{token}' token") + raise SystemExit + + def parse(self, tokens): + sets =3D [[(1, 0), (2, 0)]] + self.links =3D {} # pylint: disable=3DW0201 + + if self.ruleschanged: + self.computeNull() + self.newrules =3D {} # pylint: disable=3DW0201 + self.new2old =3D {} # pylint: disable=3DW0201 + self.makeNewRules() + self.ruleschanged =3D 0 + self.edges, self.cores =3D {}, {} # pylint: disable=3DW0201 + self.states =3D {0: self.makeState0()} # pylint: disable=3DW0= 201 + self.makeState(0, self._BOF) + + for i, token in enumerate(tokens): + sets.append([]) + + if sets[i] =3D=3D []: + break + self.makeSet(token, sets, i) + else: + sets.append([]) + self.makeSet(None, sets, len(tokens)) + + finalitem =3D (self.finalState(tokens), 0) + if finalitem not in sets[-2]: + if len(tokens) > 0: + self.error(tokens[i - 1]) # pylint: disable=3DW0631 + else: + self.error(None) + + return self.buildTree(self._START, finalitem, tokens, len(sets) - = 2) + + def isnullable(self, sym): + # + # For symbols in G_e only. If we weren't supporting 1.5, + # could just use sym.startswith(). + # + return self._NULLABLE =3D=3D sym[0 : len(self._NULLABLE)] + + def skip(self, hs, pos=3D0): + n =3D len(hs[1]) + while pos < n: + if not self.isnullable(hs[1][pos]): + break + pos +=3D 1 + return pos + + def makeState(self, state, sym): # pylint: disable=3DR0914, R0912, C0= 103 + assert sym is not None + # + # Compute \epsilon-kernel state's core and see if + # it exists already. + # + kitems =3D [] + for rule, pos in self.states[state].items: + _, rhs =3D rule + if rhs[pos : pos + 1] =3D=3D (sym,): + kitems.append((rule, self.skip(rule, pos + 1))) + core =3D kitems + + core.sort() + tcore =3D tuple(core) + if tcore in self.cores: + return self.cores[tcore] + # + # Nope, doesn't exist. Compute it and the associated + # \epsilon-nonkernel state together; we'll need it right away. + # + k =3D self.cores[tcore] =3D len(self.states) + ks, nk =3D _State(k, kitems), _State(k + 1, []) + self.states[k] =3D ks + predicted =3D {} + + edges =3D self.edges + rules =3D self.newrules + for x in ks, nk: + worklist =3D x.items + for item in worklist: + rule, pos =3D item + _, rhs =3D rule + if pos =3D=3D len(rhs): + x.complete.append(rule) + continue + + next_sym =3D rhs[pos] + key =3D (x.stateno, next_sym) + if next_sym not in rules: + if key not in edges: + edges[key] =3D None + x.t.append(next_sym) + else: + edges[key] =3D None + if next_sym not in predicted: + predicted[next_sym] =3D 1 + for prule in rules[next_sym]: + ppos =3D self.skip(prule) + new =3D (prule, ppos) + nk.items.append(new) + # + # Problem: we know K needs generating, but we + # don't yet know about NK. Can't commit anything + # regarding NK to self.edges until we're sure. Should + # we delay committing on both K and NK to avoid this + # hacky code? This creates other problems.. + # + if x is ks: + edges =3D {} + + if nk.items =3D=3D []: + return k + + # + # Check for \epsilon-nonkernel's core. Unfortunately we + # need to know the entire set of predicted nonterminals + # to do this without accidentally duplicating states. + # + core =3D sorted(predicted.keys()) + tcore =3D tuple(core) + if tcore in self.cores: + self.edges[(k, None)] =3D self.cores[tcore] + return k + + nk =3D self.cores[tcore] =3D self.edges[(k, None)] =3D nk.stateno + self.edges.update(edges) + self.states[nk] =3D nk + return k + + def goto(self, state, sym): + key =3D (state, sym) + if key not in self.edges: + # + # No transitions from state on sym. + # + return None + + rv =3D self.edges[key] + if rv is None: + # + # Target state isn't generated yet. Remedy this. + # + rv =3D self.makeState(state, sym) + self.edges[key] =3D rv + return rv + + def gotoT(self, state, t): # pylint: disable=3DC0103 + return [self.goto(state, t)] + + def gotoST(self, state, st): # pylint: disable=3DC0103 + rv =3D [] + for t in self.states[state].t: + if st =3D=3D t: + rv.append(self.goto(state, t)) + return rv + + # pylint: disable=3DR0913 + def add(self, input_set, item, i=3DNone, predecessor=3DNone, causal=3D= None): + if predecessor is None: + if item not in input_set: + input_set.append(item) + else: + key =3D (item, i) + if item not in input_set: + self.links[key] =3D [] + input_set.append(item) + self.links[key].append((predecessor, causal)) + + def makeSet(self, token, sets, i): # pylint: disable=3DR0914,C0103 + cur, next_item =3D sets[i], sets[i + 1] + + ttype =3D ( # pylint: disable=3DR1709 + token is not None and self.typestring(token) or None + ) + if ttype is not None: + fn, arg =3D self.gotoT, ttype + else: + fn, arg =3D self.gotoST, token + + for item in cur: + ptr =3D (item, i) + state, parent =3D item + add =3D fn(state, arg) + for k in add: + if k is not None: + self.add(next_item, (k, parent), i + 1, ptr) + nk =3D self.goto(k, None) + if nk is not None: + self.add(next_item, (nk, i + 1)) + + if parent =3D=3D i: + continue + + for rule in self.states[state].complete: + lhs, _ =3D rule + for pitem in sets[parent]: + pstate, pparent =3D pitem + k =3D self.goto(pstate, lhs) + if k is not None: + why =3D (item, i, rule) + pptr =3D (pitem, parent) + self.add(cur, (k, pparent), i, pptr, why) + nk =3D self.goto(k, None) + if nk is not None: + self.add(cur, (nk, i)) + + def makeSet_fast(self, token, sets, i): # pylint: disable=3DR0914, R0= 912, C0103 + # + # Call *only* when the entire state machine has been built! + # It relies on self.edges being filled in completely, and + # then duplicates and inlines code to boost speed at the + # cost of extreme ugliness. + # + cur, next_item =3D sets[i], sets[i + 1] + ttype =3D ( # pylint: disable=3DR1709 + token is not None and self.typestring(token) or None + ) + + for item in cur: # pylint: disable=3DR1702 + ptr =3D (item, i) + state, parent =3D item + if ttype is not None: + k =3D self.edges.get((state, ttype), None) + if k is not None: + # self.add(next_item, (k, parent), i + 1, ptr) + # INLINED --v + new =3D (k, parent) + key =3D (new, i + 1) + if new not in next_item: + self.links[key] =3D [] + next_item.append(new) + self.links[key].append((ptr, None)) + # INLINED --^ + # nk =3D self.goto(k, None) + nk =3D self.edges.get((k, None), None) + if nk is not None: + # self.add(next_item, (nk, i + 1)) + # INLINED --v + new =3D (nk, i + 1) + if new not in next_item: + next_item.append(new) + # INLINED --^ + else: + add =3D self.gotoST(state, token) + for k in add: + if k is not None: + self.add(next_item, (k, parent), i + 1, ptr) + # nk =3D self.goto(k, None) + nk =3D self.edges.get((k, None), None) + if nk is not None: + self.add(next_item, (nk, i + 1)) + + if parent =3D=3D i: + continue + + for rule in self.states[state].complete: + lhs, _ =3D rule + for pitem in sets[parent]: + pstate, pparent =3D pitem + # k =3D self.goto(pstate, lhs) + k =3D self.edges.get((pstate, lhs), None) + if k is not None: + why =3D (item, i, rule) + pptr =3D (pitem, parent) + # self.add(cur, (k, pparent), + # i, pptr, why) + # INLINED --v + new =3D (k, pparent) + key =3D (new, i) + if new not in cur: + self.links[key] =3D [] + cur.append(new) + self.links[key].append((pptr, why)) + # INLINED --^ + # nk =3D self.goto(k, None) + nk =3D self.edges.get((k, None), None) + if nk is not None: + # self.add(cur, (nk, i)) + # INLINED --v + new =3D (nk, i) + if new not in cur: + cur.append(new) + # INLINED --^ + + def predecessor(self, key, causal): + for p, c in self.links[key]: + if c =3D=3D causal: + return p + assert 0 + + def causal(self, key): + links =3D self.links[key] + if len(links) =3D=3D 1: + return links[0][1] + choices =3D [] + rule2cause =3D {} + for _, c in links: + rule =3D c[2] + choices.append(rule) + rule2cause[rule] =3D c + return rule2cause[self.ambiguity(choices)] + + def deriveEpsilon(self, nt): # pylint: disable=3DC0103 + if len(self.newrules[nt]) > 1: + rule =3D self.ambiguity(self.newrules[nt]) + else: + rule =3D self.newrules[nt][0] + + rhs =3D rule[1] + attr =3D [None] * len(rhs) + + for i in range(len(rhs) - 1, -1, -1): + attr[i] =3D self.deriveEpsilon(rhs[i]) + return self.rule2func[self.new2old[rule]](attr) + + def buildTree(self, nt, item, tokens, k): # pylint: disable=3DC0103 + state, _ =3D item + + choices =3D [] + for rule in self.states[state].complete: + if rule[0] =3D=3D nt: + choices.append(rule) + rule =3D choices[0] + if len(choices) > 1: + rule =3D self.ambiguity(choices) + + rhs =3D rule[1] + attr =3D [None] * len(rhs) + + for i in range(len(rhs) - 1, -1, -1): + sym =3D rhs[i] + if sym not in self.newrules: + if sym !=3D self._BOF: + attr[i] =3D tokens[k - 1] + key =3D (item, k) + item, k =3D self.predecessor(key, None) + # elif self.isnullable(sym): + elif self._NULLABLE =3D=3D sym[0 : len(self._NULLABLE)]: + attr[i] =3D self.deriveEpsilon(sym) + else: + key =3D (item, k) + why =3D self.causal(key) + attr[i] =3D self.buildTree(sym, why[0], tokens, why[1]) + item, k =3D self.predecessor(key, why) + return self.rule2func[self.new2old[rule]](attr) + + def ambiguity(self, rules): + # + # FIX ME - problem here and in collectRules() if the same rule + # appears in >1 method. Also undefined results if rules + # causing the ambiguity appear in the same method. + # + sortlist =3D [] + name2index =3D {} + for i, rule in enumerate(rules): + _, rhs =3D rule =3D rule + name =3D self.rule2name[self.new2old[rule]] + sortlist.append((len(rhs), name)) + name2index[name] =3D i + sortlist.sort() + result_list =3D [name for _, name in sortlist] + return rules[name2index[self.resolve(result_list)]] + + @staticmethod + def resolve(input_list): + # + # Resolve ambiguity in favor of the shortest RHS. + # Since we walk the tree from the top down, this + # should effectively resolve in favor of a "shift". + # + return input_list[0] + + +# +# GenericASTBuilder automagically constructs a concrete/abstract syntax t= ree +# for a given input. The extra argument is a class (not an instance!) +# which supports the "__setslice__" and "__len__" methods. +# +# FIX ME - silently overrides any user code in methods. +# + + +class GenericASTBuilder(GenericParser): + def __init__(self, AST, start): + GenericParser.__init__(self, start) + self.ast =3D AST + + def preprocess(self, rule, func): # pylint: disable=3DW0221 + # pylint: disable=3DC3001 + rebind =3D ( + lambda lhs, self=3Dself: lambda args, lhs=3Dlhs, self=3Dself: = self.buildASTNode( + args, lhs + ) + ) + lhs, _ =3D rule + return rule, rebind(lhs) + + def buildASTNode(self, args, lhs): # pylint: disable=3DC0103 + children =3D [] + for arg in args: + if isinstance(arg, self.ast): + children.append(arg) + else: + children.append(self.terminal(arg)) + return self.nonterminal(lhs, children) + + @staticmethod + def terminal(token): + return token + + def nonterminal(self, token_type, args): + rv =3D self.ast(token_type) + rv[: len(args)] =3D args + return rv + + +# +# GenericASTTraversal is a Visitor pattern according to Design Patterns. = For +# each node it attempts to invoke the method n_, falling +# back onto the default() method if the n_* can't be found. The preorder +# traversal also looks for an exit hook named n__exit (no defa= ult +# routine is called if it's not found). To prematurely halt traversal +# of a subtree, call the prune() method -- this only makes sense for a +# preorder traversal. Node type is determined via the typestring() metho= d. +# + + +class GenericASTTraversalPruningException(Exception): + pass + + +class GenericASTTraversal: + def __init__(self, ast): + self.ast =3D ast + + @staticmethod + def typestring(node): + return node.type + + @staticmethod + def prune(): + raise GenericASTTraversalPruningException + + def preorder(self, node=3DNone): + if node is None: + node =3D self.ast + + try: + name =3D "n_" + self.typestring(node) + if hasattr(self, name): + func =3D getattr(self, name) + func(node) + else: + self.default(node) + except GenericASTTraversalPruningException: + return + + for kid in node: + self.preorder(kid) + + name =3D name + "_exit" + if hasattr(self, name): + func =3D getattr(self, name) + func(node) + + def postorder(self, node=3DNone): + if node is None: + node =3D self.ast + + for kid in node: + self.postorder(kid) + + name =3D "n_" + self.typestring(node) + if hasattr(self, name): + func =3D getattr(self, name) + func(node) + else: + self.default(node) + + def default(self, node): + pass + + +# +# GenericASTMatcher. AST nodes must have "__getitem__" and "__cmp__" +# implemented. +# +# FIX ME - makes assumptions about how GenericParser walks the parse tree. +# + + +class GenericASTMatcher(GenericParser): + def __init__(self, start, ast): + GenericParser.__init__(self, start) + self.ast =3D ast + + def preprocess(self, rule, func): # pylint: disable=3DW0221 + # pylint: disable=3DC3001 + rebind =3D ( + lambda func, self=3Dself: lambda args, func=3Dfunc, self=3Dsel= f: self.foundMatch( + args, func + ) + ) + lhs, rhs =3D rule + rhslist =3D list(rhs) + rhslist.reverse() + + return (lhs, tuple(rhslist)), rebind(func) + + @staticmethod + def foundMatch(args, func): # pylint: disable=3DC0103 + func(args[-1]) + return args[-1] + + def match_r(self, node): + self.input.insert(0, node) + children =3D 0 + + for child in node: + if not children: + self.input.insert(0, "(") + children +=3D 1 + self.match_r(child) + + if children > 0: + self.input.insert(0, ")") + + def match(self, ast=3DNone): + if ast is None: + ast =3D self.ast + self.input =3D [] # pylint: disable=3DW0201 + + self.match_r(ast) + self.parse(self.input) + + def resolve(self, input_list): # pylint: disable=3DW0221 + # + # Resolve ambiguity in favor of the longest RHS. + # + return input_list[-1] --=20 2.50.1 From nobody Sun Sep 28 16:32:33 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1757701425; cv=none; d=zohomail.com; s=zohoarc; b=OjRoUqV+HsvbsjvXryhp8F5VWKYNTM/ypDxJarBu2RMoELromNEhdc+y/WPy2zm6wswMFW5Cf7orz2UfBdzQzTIgs2lqjh7Z6mIwq2oBOSovFGmga7+usoQZ4k4UfXd+mN5sU+N8JF1pjNJ9TPwqIXsLZ3XrXRxDsuXRr1JqCxg= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1757701425; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=kiMGSSuNGIWwi1MU28oMqey9bflNqrOuT55auRAEEaY=; b=BQzuw/FLR2mCnxctBgsyhZOQHLKyWR6Qy5F8QfRBV8044H5FWRWbSbWk2umbz4XP7zgaPik+nF4O4+yuPWlbOl6B4BfE+a6HSZNFTRyngSbFSDZVZDjt753HKaaeOI+zcMRKNy+VETcnDe5EnXS850G9pEo+oqur/uPkCGGQl4k= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1757701425085924.1829227418402; Fri, 12 Sep 2025 11:23:45 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ux8Pf-0004XH-55; Fri, 12 Sep 2025 14:22:23 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ux8Pb-0004Vx-IS for qemu-devel@nongnu.org; Fri, 12 Sep 2025 14:22:19 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ux8PU-0005FZ-Fm for qemu-devel@nongnu.org; Fri, 12 Sep 2025 14:22:19 -0400 Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-380-kGnqJBLgMuGQpKeIO6JH2g-1; Fri, 12 Sep 2025 14:22:09 -0400 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id BFBD81800562 for ; Fri, 12 Sep 2025 18:22:08 +0000 (UTC) Received: from toolbx.redhat.com (unknown [10.42.28.154]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 6C51718003FC; Fri, 12 Sep 2025 18:22:07 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1757701331; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=kiMGSSuNGIWwi1MU28oMqey9bflNqrOuT55auRAEEaY=; b=dZr66vrith/6EqEGzlR9x4xTlJzjRr4tZEWuoaib+ZIwkkkUL2XW3nAxcQAeqGRQSeMjbs 5m7woR0xPbBzeOHU3dR/w5mlD000bmFyb8XhDmbz1vOL9glBNn608Qg/V5Vv6nLH9CzCiD z0tYII350vXNAkwdr6msf76ptT0Gasg= X-MC-Unique: kGnqJBLgMuGQpKeIO6JH2g-1 X-Mimecast-MFC-AGG-ID: kGnqJBLgMuGQpKeIO6JH2g_1757701329 From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= To: qemu-devel@nongnu.org Cc: Thomas Huth , =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= Subject: [PATCH 2/6] tests/functional: convert reverse debug test to local gdb module Date: Fri, 12 Sep 2025 19:21:56 +0100 Message-ID: <20250912182200.643909-3-berrange@redhat.com> In-Reply-To: <20250912182200.643909-1-berrange@redhat.com> References: <20250912182200.643909-1-berrange@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.133.124; envelope-from=berrange@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1757701426845116600 This replaces the use of Avocado for the GDBRemote class with our in-tree copy. Signed-off-by: Daniel P. Berrang=C3=A9 Reviewed-by: Alex Benn=C3=A9e --- tests/functional/reverse_debugging.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/functional/reverse_debugging.py b/tests/functional/rever= se_debugging.py index f9a1d395f1..405eb6b3b7 100644 --- a/tests/functional/reverse_debugging.py +++ b/tests/functional/reverse_debugging.py @@ -14,6 +14,7 @@ =20 from qemu_test import LinuxKernelTest, get_qemu_img from qemu_test.ports import Ports +from qemu_test.gdb import GDBRemote =20 =20 class ReverseDebugging(LinuxKernelTest): @@ -99,7 +100,6 @@ def vm_get_icount(vm): return vm.qmp('query-replay')['return']['icount'] =20 def reverse_debugging(self, shift=3D7, args=3DNone): - from avocado.utils import gdb from avocado.utils import process =20 logger =3D logging.getLogger('replay') @@ -130,7 +130,7 @@ def reverse_debugging(self, shift=3D7, args=3DNone): port =3D ports.find_free_port() vm =3D self.run_vm(False, shift, args, replay_path, image_path= , port) logger.info('connecting to gdbstub') - g =3D gdb.GDBRemote('127.0.0.1', port, False, False) + g =3D GDBRemote('127.0.0.1', port, False, False) g.connect() r =3D g.cmd(b'qSupported') if b'qXfer:features:read+' in r: --=20 2.50.1 From nobody Sun Sep 28 16:32:33 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1757701426; cv=none; d=zohomail.com; s=zohoarc; b=RvVZ14UTM/W2++4hwMbkffEz7VT3zHGmS0jk7aSop5MhZmr62WWjW2KPtNm+xBKPy3jt6TcQFD/7OhkwIQvQZM9OddS39nY3XfEcE5SdCMZDQ7eHy/eN9OFazZUtIf6exuexLmx0Gyco86f+XZhtASfIsA8KnqRgiI+rC9rjIzQ= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1757701426; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=tE82+/gc49jV7lxFy1jmA8hoihzee202gsVD7g/JEEk=; b=WU+C7lEoPydNhwI8S+ZLSEB3FjRQRZggA9SauK0/aTfO1WJ/9bFxGgx9zI5+Ht7JbH0TDpP041U+feJXJsm4flaQExByLXPO3+ES9fxvCiKumS9QEUJ+789cg1efWX29jGAi0B6RjyKlahPdxXNVbWpgxJFUm+0s/k0Aqg5uaYE= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1757701426804464.03114131607674; Fri, 12 Sep 2025 11:23:46 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ux8Pa-0004VK-KA; Fri, 12 Sep 2025 14:22:18 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ux8PY-0004V2-VG for qemu-devel@nongnu.org; Fri, 12 Sep 2025 14:22:16 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ux8PX-0005GJ-9Q for qemu-devel@nongnu.org; Fri, 12 Sep 2025 14:22:16 -0400 Received: from mx-prod-mc-02.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-562-Oat8Vj6aMwe6qtSwaHC0Ng-1; Fri, 12 Sep 2025 14:22:11 -0400 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id B32251956086 for ; Fri, 12 Sep 2025 18:22:10 +0000 (UTC) Received: from toolbx.redhat.com (unknown [10.42.28.154]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 4982C18003FC; Fri, 12 Sep 2025 18:22:08 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1757701332; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=tE82+/gc49jV7lxFy1jmA8hoihzee202gsVD7g/JEEk=; b=jOcoKTISInKo5Zl/OsUSKLUOak+cUcvBueE4fYYzzyLiglhquyrp2dQqWRUaxZzNMdlgdE j1ov6L1H65EretNh0ynhqV5CO2ncih8BhQq7rI5KLak//r6cZMSoaxQPOt7dgo/eJ+VTue u7aBfsuPH7HiPwP8br9VYEkNn6ZietI= X-MC-Unique: Oat8Vj6aMwe6qtSwaHC0Ng-1 X-Mimecast-MFC-AGG-ID: Oat8Vj6aMwe6qtSwaHC0Ng_1757701330 From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= To: qemu-devel@nongnu.org Cc: Thomas Huth , =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= Subject: [PATCH 3/6] tests/functional: replace avocado process with subprocess Date: Fri, 12 Sep 2025 19:21:57 +0100 Message-ID: <20250912182200.643909-4-berrange@redhat.com> In-Reply-To: <20250912182200.643909-1-berrange@redhat.com> References: <20250912182200.643909-1-berrange@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.133.124; envelope-from=berrange@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: 12 X-Spam_score: 1.2 X-Spam_bar: + X-Spam_report: (1.2 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_SBL_CSS=3.335, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1757701428916116600 The standard python subprocess.check_call method is better than avocado.utils.process as it doesn't require stuffing all args into a single string. Signed-off-by: Daniel P. Berrang=C3=A9 Reviewed-by: Alex Benn=C3=A9e --- tests/functional/reverse_debugging.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/functional/reverse_debugging.py b/tests/functional/rever= se_debugging.py index 405eb6b3b7..1b880cda8f 100644 --- a/tests/functional/reverse_debugging.py +++ b/tests/functional/reverse_debugging.py @@ -11,6 +11,7 @@ # later. See the COPYING file in the top-level directory. import os import logging +from subprocess import check_output =20 from qemu_test import LinuxKernelTest, get_qemu_img from qemu_test.ports import Ports @@ -100,8 +101,6 @@ def vm_get_icount(vm): return vm.qmp('query-replay')['return']['icount'] =20 def reverse_debugging(self, shift=3D7, args=3DNone): - from avocado.utils import process - logger =3D logging.getLogger('replay') =20 # create qcow2 for snapshots @@ -111,8 +110,9 @@ def reverse_debugging(self, shift=3D7, args=3DNone): if qemu_img is None: self.skipTest('Could not find "qemu-img", which is required to= ' 'create the temporary qcow2 image') - cmd =3D '%s create -f qcow2 %s 128M' % (qemu_img, image_path) - process.run(cmd) + out =3D check_output([qemu_img, 'create', '-f', 'qcow2', image_pat= h, '128M'], + encoding=3D'utf8') + logger.info("qemu-img: %s" % out) =20 replay_path =3D os.path.join(self.workdir, 'replay.bin') =20 --=20 2.50.1 From nobody Sun Sep 28 16:32:33 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1757701393; cv=none; d=zohomail.com; s=zohoarc; b=L7ByHskvoaYg7F5X4ker+P7ReXctMA5tQ5sxYDhvDK1cBYKLXefHIi7gIZ5FCl0POHWw29Rz+qDyRi+tZV7N3NHnlMLMTYr8x/VpMFVmvjv/upLPzUBzeqaZeFB2miOfSNsmiuMRA/kcbdBZOf2QoYcKBm/1y1xLtAgwphvMJZo= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1757701393; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=Tg7kqLnBqit3uOyogtL53AIWh7HfdrmXAVznNEj0HFI=; b=eU5WeWKiXsihM+ERJ6agQ1Hsz3RJNV1AN/zNIFTsjVsD9/eVh41H4OSBAQpXkVKpmUKC7WT0Ss7cJsEOt8rpaPGHwlhoKp+cpQrkAzTY2qCx/ufBNlbQAbjeZ+MCCJS0XkV2uTHJ4ihnEcx6CPpukqNxz1NSJKNWGGIS5nAnZf4= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1757701393091950.103120516205; Fri, 12 Sep 2025 11:23:13 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ux8Pc-0004Wl-To; Fri, 12 Sep 2025 14:22:21 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ux8Pa-0004Vk-P9 for qemu-devel@nongnu.org; Fri, 12 Sep 2025 14:22:18 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ux8PY-0005H8-UC for qemu-devel@nongnu.org; Fri, 12 Sep 2025 14:22:18 -0400 Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-619-VBZT7ghOO1uOGHNGhq2C6g-1; Fri, 12 Sep 2025 14:22:13 -0400 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id BD0941800577 for ; Fri, 12 Sep 2025 18:22:12 +0000 (UTC) Received: from toolbx.redhat.com (unknown [10.42.28.154]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 3940B18003FC; Fri, 12 Sep 2025 18:22:11 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1757701336; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Tg7kqLnBqit3uOyogtL53AIWh7HfdrmXAVznNEj0HFI=; b=jDuGnx8AEJ3VA92QJ7/OyX+DaO4HyDwA/HErOGTYu+1KnilUuVQhsIsEwwyHfT+dl+2h2W FypydogwCyH0P7srL5UniLtI9LrLURcy5UwfbGQcz6ahziP5KFu9ptZwP3RX3gUXvXk9XD XmMF0Vlu/Fptgky6QOk5BX4aMiluc0c= X-MC-Unique: VBZT7ghOO1uOGHNGhq2C6g-1 X-Mimecast-MFC-AGG-ID: VBZT7ghOO1uOGHNGhq2C6g_1757701333 From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= To: qemu-devel@nongnu.org Cc: Thomas Huth , =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= Subject: [PATCH 4/6] tests/functional: drop datadrainer class in reverse debugging Date: Fri, 12 Sep 2025 19:21:58 +0100 Message-ID: <20250912182200.643909-5-berrange@redhat.com> In-Reply-To: <20250912182200.643909-1-berrange@redhat.com> References: <20250912182200.643909-1-berrange@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.129.124; envelope-from=berrange@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1757701394710116600 The reverse debugging test uses the avocado datadrainer class to create a background thread that reads from the console socket and dumps it via python logger. Most tests log console output as a side effect of doing calls to match strings, but this test never tries to match anything. This isn't critical, so just drop the functionality. Signed-off-by: Daniel P. Berrang=C3=A9 Reviewed-by: Alex Benn=C3=A9e --- tests/functional/reverse_debugging.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/tests/functional/reverse_debugging.py b/tests/functional/rever= se_debugging.py index 1b880cda8f..9c89f5c897 100644 --- a/tests/functional/reverse_debugging.py +++ b/tests/functional/reverse_debugging.py @@ -35,8 +35,6 @@ class ReverseDebugging(LinuxKernelTest): endian_is_le =3D True =20 def run_vm(self, record, shift, args, replay_path, image_path, port): - from avocado.utils import datadrainer - logger =3D logging.getLogger('replay') vm =3D self.get_vm(name=3D'record' if record else 'replay') vm.set_console() @@ -54,10 +52,6 @@ def run_vm(self, record, shift, args, replay_path, image= _path, port): if args: vm.add_args(*args) vm.launch() - console_drainer =3D datadrainer.LineLogger(vm.console_socket.filen= o(), - logger=3Dself.log.getChild('console'), - stop_check=3D(lambda : not vm.is_runni= ng())) - console_drainer.start() return vm =20 @staticmethod --=20 2.50.1 From nobody Sun Sep 28 16:32:33 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1757701425; cv=none; d=zohomail.com; s=zohoarc; b=aNcHxdqVggxtDrnPGewqEQ6b2mucmGy+vstxZWz6RjhKxFAGN6BKmgHX8FmP1cmlwu2CGqCyQewblGB2c/fxse1Nw1kCph30vahR1NoA41WOcYubxKrBgq4AOZmnyLmJr5YMS7TFpyELMEnkgUmokFLt/OrMODexi45WwEwCXJs= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1757701425; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=6+W630tOCA0+rx9/rJ5njZf90sXPW8yYXnWYXhKmUo4=; b=A6Z0D9MgXwJP+pXi98786NLh/F9kfHSCo+and7FROV3q9Vc2hN7pxqoXW3Ose5ZFrjJEco5zXHPncNHi56TadCpRCxecraflUKGS171eJUWSE9Ik1bZXuINLT83F7jw5UhRgkROJlzQ7/gg56w31S2YL5WQeY1UORW4eeQssZ00= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 175770142490070.7247826656369; Fri, 12 Sep 2025 11:23:44 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ux8Pf-0004XO-Mg; Fri, 12 Sep 2025 14:22:23 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ux8Pc-0004WS-B0 for qemu-devel@nongnu.org; Fri, 12 Sep 2025 14:22:20 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ux8Pa-0005HW-Hm for qemu-devel@nongnu.org; Fri, 12 Sep 2025 14:22:20 -0400 Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-563-ZpfGRvMmNYSkz9kFap6OoQ-1; Fri, 12 Sep 2025 14:22:15 -0400 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 98A151800451 for ; Fri, 12 Sep 2025 18:22:14 +0000 (UTC) Received: from toolbx.redhat.com (unknown [10.42.28.154]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 41D3018003FC; Fri, 12 Sep 2025 18:22:12 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1757701337; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=6+W630tOCA0+rx9/rJ5njZf90sXPW8yYXnWYXhKmUo4=; b=WWGhKXv7aOcGUGHqlRxD6n7TSsmTBhyxgFp0DpZw0RlLg2ciSwdkA9yg7L2C3xoKNcIXXW /lByYyL3R5fSPbEPQkXzk0BGgQcKliZyYyBmwUInMuTHCABzBulXDWssk1c5OZrPlEE4ra Nl1z0W0eg/iqpT2O91Gwwu2JFMtG9Qo= X-MC-Unique: ZpfGRvMmNYSkz9kFap6OoQ-1 X-Mimecast-MFC-AGG-ID: ZpfGRvMmNYSkz9kFap6OoQ_1757701334 From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= To: qemu-devel@nongnu.org Cc: Thomas Huth , =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= Subject: [PATCH 5/6] tests/functional: close GDB socket in reverse debugging test Date: Fri, 12 Sep 2025 19:21:59 +0100 Message-ID: <20250912182200.643909-6-berrange@redhat.com> In-Reply-To: <20250912182200.643909-1-berrange@redhat.com> References: <20250912182200.643909-1-berrange@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.129.124; envelope-from=berrange@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1757701426823116600 The GDB socket FD is leaked currently resulting in a warning from python about the unclosed resource. Signed-off-by: Daniel P. Berrang=C3=A9 Reviewed-by: Alex Benn=C3=A9e --- tests/functional/qemu_test/gdb.py | 4 ++++ tests/functional/reverse_debugging.py | 2 ++ 2 files changed, 6 insertions(+) diff --git a/tests/functional/qemu_test/gdb.py b/tests/functional/qemu_test= /gdb.py index 913e3b65ab..1b463e8a82 100644 --- a/tests/functional/qemu_test/gdb.py +++ b/tests/functional/qemu_test/gdb.py @@ -231,3 +231,7 @@ def connect(self): =20 if self._extended_mode: self.set_extended_mode() + + def close(self): + self._socket.close() + self._socket =3D None diff --git a/tests/functional/reverse_debugging.py b/tests/functional/rever= se_debugging.py index 9c89f5c897..fbb5adbcce 100644 --- a/tests/functional/reverse_debugging.py +++ b/tests/functional/reverse_debugging.py @@ -186,5 +186,7 @@ def reverse_debugging(self, shift=3D7, args=3DNone): self.check_pc(g, steps[-1]) logger.info('successfully reached %x' % steps[-1]) =20 + g.close() + logger.info('exiting gdb and qemu') vm.shutdown() --=20 2.50.1 From nobody Sun Sep 28 16:32:33 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1757701424; cv=none; d=zohomail.com; s=zohoarc; b=k/46xBBjXhGbhGjLwi0qMTjXICNPYO7JIOBwEla+WDwVikGFSNj2OgO2nPaSFTokMKu8KPqLgLkP9vzFd4mWUN3+twjw+csXlbEP4r+yGOSqlG0i2B17AMiMvNh8RX8mepCQXvB0wmpmxQOUJwWV4RwjTylO0Z+MQBvdonG61fA= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1757701424; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=k9PIrwR8q/fff+NsbcIl3VpywrA9+n/btYb7Q5rBJ1I=; b=JUki0oFYuQ7XWInNnGMwsX9MlT7TDjgewzzFneNOmoxRcqIr+ZKsfrinFdJgdNAXiKHqu3IHO+H/jg2s57M+vb6jHuvfkpqr7WSN/kPhQsfX33ki/nYY1Htv1dgOuYmp6UORmwJAlkdyQzj6vtnx896efQGSncVDYEFgjaf3JJs= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 17577014243701.7610996575409672; Fri, 12 Sep 2025 11:23:44 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ux8Ph-0004YI-FJ; Fri, 12 Sep 2025 14:22:25 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ux8Pe-0004X5-GW for qemu-devel@nongnu.org; Fri, 12 Sep 2025 14:22:22 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ux8Pb-0005Hu-S1 for qemu-devel@nongnu.org; Fri, 12 Sep 2025 14:22:22 -0400 Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-612-0N50121DPxyi5d9sCNfSng-1; Fri, 12 Sep 2025 14:22:17 -0400 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 73E041800288 for ; Fri, 12 Sep 2025 18:22:16 +0000 (UTC) Received: from toolbx.redhat.com (unknown [10.42.28.154]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 342041800446; Fri, 12 Sep 2025 18:22:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1757701339; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=k9PIrwR8q/fff+NsbcIl3VpywrA9+n/btYb7Q5rBJ1I=; b=MZFCMiV2u2XlaDMGtUSznuJJaWV7IQV4rNBbh4bJ1+KYt8GSs624KRCveh/7yQ4Q+tEo2I sQxvJy9NJy4H+PRdB4TI4RbsM9TWr+bH/YvIHFJUhn+OC8HEYwV/GxEJ7WtNr8O1LsgJ25 +XY4b9nBipt+GOLBFkGo0f8blHQ1rLs= X-MC-Unique: 0N50121DPxyi5d9sCNfSng-1 X-Mimecast-MFC-AGG-ID: 0N50121DPxyi5d9sCNfSng_1757701336 From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= To: qemu-devel@nongnu.org Cc: Thomas Huth , =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= Subject: [PATCH 6/6] tests/functional: use self.log for all logging Date: Fri, 12 Sep 2025 19:22:00 +0100 Message-ID: <20250912182200.643909-7-berrange@redhat.com> In-Reply-To: <20250912182200.643909-1-berrange@redhat.com> References: <20250912182200.643909-1-berrange@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.133.124; envelope-from=berrange@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1757701427138116600 Some tests are creating their on logger category which means any output they log is not captured in base.log. Signed-off-by: Daniel P. Berrang=C3=A9 Reviewed-by: Alex Benn=C3=A9e --- tests/functional/aarch64/test_virt.py | 4 +-- tests/functional/arm/test_integratorcp.py | 3 +- tests/functional/mips64el/test_malta.py | 3 +- tests/functional/replay_kernel.py | 16 ++++----- tests/functional/reverse_debugging.py | 41 +++++++++++------------ tests/functional/x86_64/test_acpi_bits.py | 31 +++++++++-------- 6 files changed, 44 insertions(+), 54 deletions(-) diff --git a/tests/functional/aarch64/test_virt.py b/tests/functional/aarch= 64/test_virt.py index 4d0ad90ff8..63071f9b51 100755 --- a/tests/functional/aarch64/test_virt.py +++ b/tests/functional/aarch64/test_virt.py @@ -72,8 +72,6 @@ def common_aarch64_virt(self, machine): self.set_machine('virt') self.require_accelerator("tcg") =20 - logger =3D logging.getLogger('aarch64_virt') - kernel_path =3D self.ASSET_KERNEL.fetch() =20 self.vm.set_console() @@ -91,7 +89,7 @@ def common_aarch64_virt(self, machine): 'rng-random,id=3Drng0,filename=3D/dev/urandom') =20 # Also add a scratch block device - logger.info('creating scratch qcow2 image') + self.log.info('creating scratch qcow2 image') image_path =3D self.scratch_file('scratch.qcow2') qemu_img =3D get_qemu_img(self) check_call([qemu_img, 'create', '-f', 'qcow2', image_path, '8M'], diff --git a/tests/functional/arm/test_integratorcp.py b/tests/functional/a= rm/test_integratorcp.py index 4f00924aa0..23ae919359 100755 --- a/tests/functional/arm/test_integratorcp.py +++ b/tests/functional/arm/test_integratorcp.py @@ -77,7 +77,6 @@ def test_framebuffer_tux_logo(self): command_line=3D'screendump %s' % screendump_path) if 'unknown command' in res: self.skipTest('screendump not available') - logger =3D logging.getLogger('framebuffer') =20 cpu_count =3D 1 match_threshold =3D 0.92 @@ -88,7 +87,7 @@ def test_framebuffer_tux_logo(self): loc =3D np.where(result >=3D match_threshold) tux_count =3D 0 for tux_count, pt in enumerate(zip(*loc[::-1]), start=3D1): - logger.debug('found Tux at position [x, y] =3D %s', pt) + self.log.debug('found Tux at position [x, y] =3D %s', pt) self.assertGreaterEqual(tux_count, cpu_count) =20 if __name__ =3D=3D '__main__': diff --git a/tests/functional/mips64el/test_malta.py b/tests/functional/mip= s64el/test_malta.py index 8fdc49b300..170147bfcc 100755 --- a/tests/functional/mips64el/test_malta.py +++ b/tests/functional/mips64el/test_malta.py @@ -159,7 +159,6 @@ def do_test_i6400_framebuffer_logo(self, cpu_cores_coun= t): command_line=3D'screendump %s' % screendump_path) if 'unknown command' in res: self.skipTest('screendump not available') - logger =3D logging.getLogger('framebuffer') =20 match_threshold =3D 0.95 screendump_bgr =3D cv2.imread(screendump_path, cv2.IMREAD_COLOR) @@ -171,7 +170,7 @@ def do_test_i6400_framebuffer_logo(self, cpu_cores_coun= t): h, w =3D tuxlogo_bgr.shape[:2] debug_png =3D os.getenv('QEMU_TEST_CV2_SCREENDUMP_PNG_PATH') for tuxlogo_count, pt in enumerate(zip(*loc[::-1]), start=3D1): - logger.debug('found Tux at position (x, y) =3D %s', pt) + self.log.debug('found Tux at position (x, y) =3D %s', pt) cv2.rectangle(screendump_bgr, pt, (pt[0] + w, pt[1] + h), (0, 0, 255), 2) if debug_png: diff --git a/tests/functional/replay_kernel.py b/tests/functional/replay_ke= rnel.py index 80795eb052..acb1d29a1b 100644 --- a/tests/functional/replay_kernel.py +++ b/tests/functional/replay_kernel.py @@ -32,15 +32,14 @@ def run_vm(self, kernel_path, kernel_command_line, cons= ole_pattern, # icount requires TCG to be available self.require_accelerator('tcg') =20 - logger =3D logging.getLogger('replay') start_time =3D time.time() vm =3D self.get_vm(name=3D'recording' if record else 'replay') vm.set_console() if record: - logger.info('recording the execution...') + self.log.info('recording the execution...') mode =3D 'record' else: - logger.info('replaying the execution...') + self.log.info('replaying the execution...') mode =3D 'replay' vm.add_args('-icount', 'shift=3D%s,rr=3D%s,rrfile=3D%s' % (shift, mode, replay_path), @@ -54,15 +53,15 @@ def run_vm(self, kernel_path, kernel_command_line, cons= ole_pattern, self.wait_for_console_pattern(console_pattern, vm) if record: vm.shutdown() - logger.info('finished the recording with log size %s bytes' + self.log.info('finished the recording with log size %s bytes' % os.path.getsize(replay_path)) self.run_replay_dump(replay_path) - logger.info('successfully tested replay-dump.py') + self.log.info('successfully tested replay-dump.py') else: vm.wait() - logger.info('successfully finished the replay') + self.log.info('successfully finished the replay') elapsed =3D time.time() - start_time - logger.info('elapsed time %.2f sec' % elapsed) + self.log.info('elapsed time %.2f sec' % elapsed) return elapsed =20 def run_replay_dump(self, replay_path): @@ -80,5 +79,4 @@ def run_rr(self, kernel_path, kernel_command_line, consol= e_pattern, True, shift, args, replay_path) t2 =3D self.run_vm(kernel_path, kernel_command_line, console_patte= rn, False, shift, args, replay_path) - logger =3D logging.getLogger('replay') - logger.info('replay overhead {:.2%}'.format(t2 / t1 - 1)) + self.log.info('replay overhead {:.2%}'.format(t2 / t1 - 1)) diff --git a/tests/functional/reverse_debugging.py b/tests/functional/rever= se_debugging.py index fbb5adbcce..be5d70f97f 100644 --- a/tests/functional/reverse_debugging.py +++ b/tests/functional/reverse_debugging.py @@ -35,14 +35,13 @@ class ReverseDebugging(LinuxKernelTest): endian_is_le =3D True =20 def run_vm(self, record, shift, args, replay_path, image_path, port): - logger =3D logging.getLogger('replay') vm =3D self.get_vm(name=3D'record' if record else 'replay') vm.set_console() if record: - logger.info('recording the execution...') + self.log.info('recording the execution...') mode =3D 'record' else: - logger.info('replaying the execution...') + self.log.info('replaying the execution...') mode =3D 'replay' vm.add_args('-gdb', 'tcp::%d' % port, '-S') vm.add_args('-icount', 'shift=3D%s,rr=3D%s,rrfile=3D%s,rrsnapshot= =3Dinit' % @@ -95,10 +94,8 @@ def vm_get_icount(vm): return vm.qmp('query-replay')['return']['icount'] =20 def reverse_debugging(self, shift=3D7, args=3DNone): - logger =3D logging.getLogger('replay') - # create qcow2 for snapshots - logger.info('creating qcow2 image for VM snapshots') + self.log.info('creating qcow2 image for VM snapshots') image_path =3D os.path.join(self.workdir, 'disk.qcow2') qemu_img =3D get_qemu_img(self) if qemu_img is None: @@ -106,7 +103,7 @@ def reverse_debugging(self, shift=3D7, args=3DNone): 'create the temporary qcow2 image') out =3D check_output([qemu_img, 'create', '-f', 'qcow2', image_pat= h, '128M'], encoding=3D'utf8') - logger.info("qemu-img: %s" % out) + self.log.info("qemu-img: %s" % out) =20 replay_path =3D os.path.join(self.workdir, 'replay.bin') =20 @@ -117,13 +114,13 @@ def reverse_debugging(self, shift=3D7, args=3DNone): last_icount =3D self.vm_get_icount(vm) vm.shutdown() =20 - logger.info("recorded log with %s+ steps" % last_icount) + self.log.info("recorded log with %s+ steps" % last_icount) =20 # replay and run debug commands with Ports() as ports: port =3D ports.find_free_port() vm =3D self.run_vm(False, shift, args, replay_path, image_path= , port) - logger.info('connecting to gdbstub') + self.log.info('connecting to gdbstub') g =3D GDBRemote('127.0.0.1', port, False, False) g.connect() r =3D g.cmd(b'qSupported') @@ -134,59 +131,59 @@ def reverse_debugging(self, shift=3D7, args=3DNone): if b'ReverseContinue+' not in r: self.fail('Reverse continue is not supported by QEMU') =20 - logger.info('stepping forward') + self.log.info('stepping forward') steps =3D [] # record first instruction addresses for _ in range(self.STEPS): pc =3D self.get_pc(g) - logger.info('saving position %x' % pc) + self.log.info('saving position %x' % pc) steps.append(pc) self.gdb_step(g) =20 # visit the recorded instruction in reverse order - logger.info('stepping backward') + self.log.info('stepping backward') for addr in steps[::-1]: self.gdb_bstep(g) self.check_pc(g, addr) - logger.info('found position %x' % addr) + self.log.info('found position %x' % addr) =20 # visit the recorded instruction in forward order - logger.info('stepping forward') + self.log.info('stepping forward') for addr in steps: self.check_pc(g, addr) self.gdb_step(g) - logger.info('found position %x' % addr) + self.log.info('found position %x' % addr) =20 # set breakpoints for the instructions just stepped over - logger.info('setting breakpoints') + self.log.info('setting breakpoints') for addr in steps: # hardware breakpoint at addr with len=3D1 g.cmd(b'Z1,%x,1' % addr, b'OK') =20 # this may hit a breakpoint if first instructions are executed # again - logger.info('continuing execution') + self.log.info('continuing execution') vm.qmp('replay-break', icount=3Dlast_icount - 1) # continue - will return after pausing # This could stop at the end and get a T02 return, or by # re-executing one of the breakpoints and get a T05 return. g.cmd(b'c') if self.vm_get_icount(vm) =3D=3D last_icount - 1: - logger.info('reached the end (icount %s)' % (last_icount - 1)) + self.log.info('reached the end (icount %s)' % (last_icount - 1= )) else: - logger.info('hit a breakpoint again at %x (icount %s)' % + self.log.info('hit a breakpoint again at %x (icount %s)' % (self.get_pc(g), self.vm_get_icount(vm))) =20 - logger.info('running reverse continue to reach %x' % steps[-1]) + self.log.info('running reverse continue to reach %x' % steps[-1]) # reverse continue - will return after stopping at the breakpoint g.cmd(b'bc', b'T05thread:01;') =20 # assume that none of the first instructions is executed again # breaking the order of the breakpoints self.check_pc(g, steps[-1]) - logger.info('successfully reached %x' % steps[-1]) + self.log.info('successfully reached %x' % steps[-1]) =20 g.close() =20 - logger.info('exiting gdb and qemu') + self.log.info('exiting gdb and qemu') vm.shutdown() diff --git a/tests/functional/x86_64/test_acpi_bits.py b/tests/functional/x= 86_64/test_acpi_bits.py index 8e0563a97b..9a2816533d 100755 --- a/tests/functional/x86_64/test_acpi_bits.py +++ b/tests/functional/x86_64/test_acpi_bits.py @@ -121,10 +121,10 @@ def __init__(self, *args, **kwargs): self._debugcon_log =3D 'debugcon-log.txt' =20 def _print_log(self, log): - self.logger.info('\nlogs from biosbits follows:') - self.logger.info('=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D\n') - self.logger.info(log) - self.logger.info('=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D\n') + self.log.info('\nlogs from biosbits follows:') + self.log.info('=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= \n') + self.log.info(log) + self.log.info('=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= \n') =20 def copy_bits_config(self): """ copies the bios bits config file into bits. @@ -138,8 +138,8 @@ def copy_bits_config(self): self.assertTrue(os.path.exists(bits_config_file)) self.assertTrue(os.path.exists(target_config_dir)) shutil.copy2(bits_config_file, target_config_dir) - self.logger.info('copied config file %s to %s', - bits_config_file, target_config_dir) + self.log.info('copied config file %s to %s', + bits_config_file, target_config_dir) =20 def copy_test_scripts(self): """copies the python test scripts into bits. """ @@ -163,8 +163,8 @@ def copy_test_scripts(self): newfilename =3D os.path.splitext(filename)[0] + '.py' shutil.copy2(os.path.join(bits_test_dir, filename), os.path.join(target_test_dir, newfilename)) - self.logger.info('copied test file %s to %s', - filename, target_test_dir) + self.log.info('copied test file %s to %s', + filename, target_test_dir) =20 # now remove the pyc test file if it exists, otherwise the # changes in the python test script won't be executed. @@ -172,9 +172,9 @@ def copy_test_scripts(self): if os.access(os.path.join(target_test_dir, testfile_pyc), os.F_OK): os.remove(os.path.join(target_test_dir, testfile_pyc)) - self.logger.info('removed compiled file %s', - os.path.join(target_test_dir, - testfile_pyc)) + self.log.info('removed compiled file %s', + os.path.join(target_test_dir, + testfile_pyc)) =20 def fix_mkrescue(self, mkrescue): """ grub-mkrescue is a bash script with two variables, 'prefix' and @@ -216,7 +216,7 @@ def generate_bits_iso(self): =20 self.fix_mkrescue(mkrescue_script) =20 - self.logger.info('using grub-mkrescue for generating biosbits iso = ...') + self.log.info('using grub-mkrescue for generating biosbits iso ...= ') =20 try: if os.getenv('V') or os.getenv('BITS_DEBUG'): @@ -225,7 +225,7 @@ def generate_bits_iso(self): stdout=3Dsubprocess.PIPE, stderr=3Dsubprocess.STDOUT, check=3DTrue) - self.logger.info("grub-mkrescue output %s" % proc.stdout) + self.log.info("grub-mkrescue output %s" % proc.stdout) else: subprocess.check_call([mkrescue_script, '-o', iso_file, bits_dir], @@ -238,11 +238,10 @@ def generate_bits_iso(self): =20 self.assertTrue(os.access(iso_file, os.R_OK)) =20 - self.logger.info('iso file %s successfully generated.', iso_file) + self.log.info('iso file %s successfully generated.', iso_file) =20 def setUp(self): # pylint: disable=3Darguments-differ super().setUp() - self.logger =3D self.log =20 prebuiltDir =3D self.scratch_file('prebuilt') if not os.path.isdir(prebuiltDir): @@ -333,7 +332,7 @@ def test_acpi_smbios_bits(self): # in batch mode and then automatically initiate a vm shutdown. self._vm.event_wait('SHUTDOWN', timeout=3DBITS_TIMEOUT) self._vm.wait(timeout=3DNone) - self.logger.debug("Checking console output ...") + self.log.debug("Checking console output ...") self.parse_log() =20 if __name__ =3D=3D '__main__': --=20 2.50.1