From: John Snow <jsnow@redhat.com>
To: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>,
"qemu-devel@nongnu.org" <qemu-devel@nongnu.org>
Cc: Kevin Wolf <kwolf@redhat.com>,
"qemu-block@nongnu.org" <qemu-block@nongnu.org>,
Max Reitz <mreitz@redhat.com>
Subject: Re: [Qemu-devel] [PATCH v5 5/5] iotests: use python logging for iotests.log()
Date: Wed, 18 Sep 2019 13:11:31 -0400 [thread overview]
Message-ID: <f181725a-1f67-6592-f636-3d7cab41bfc7@redhat.com> (raw)
In-Reply-To: <9ef7ce1f-def1-046b-5e90-b2facec617e2@virtuozzo.com>
On 9/18/19 10:52 AM, Vladimir Sementsov-Ogievskiy wrote:
> 18.09.2019 2:45, John Snow wrote:
>> We can turn logging on/off globally instead of per-function.
>>
>> Remove use_log from run_job, and use python logging to turn on
>> diffable output when we run through a script entry point.
>>
>> iotest 245 changes output order due to buffering reasons.
>
> Interesting, how can that be? pre-patch logging goes to stdout of test-case
> and after-patch logging goes to stdout of test-case.. What's the difference
> from tests/qemu-iotest/check point of view?
>
>>
>> Signed-off-by: John Snow <jsnow@redhat.com>
>> ---
>> tests/qemu-iotests/030 | 4 +--
>> tests/qemu-iotests/245 | 1 +
>> tests/qemu-iotests/245.out | 24 ++++++++---------
>> tests/qemu-iotests/iotests.py | 49 +++++++++++++++++++++--------------
>> 4 files changed, 44 insertions(+), 34 deletions(-)
>>
>> diff --git a/tests/qemu-iotests/030 b/tests/qemu-iotests/030
>> index f3766f2a81..01aa96ed16 100755
>> --- a/tests/qemu-iotests/030
>> +++ b/tests/qemu-iotests/030
>> @@ -411,8 +411,8 @@ class TestParallelOps(iotests.QMPTestCase):
>> result = self.vm.qmp('block-job-set-speed', device='drive0', speed=0)
>> self.assert_qmp(result, 'return', {})
>>
>> - self.vm.run_job(job='drive0', auto_dismiss=True, use_log=False)
>> - self.vm.run_job(job='node4', auto_dismiss=True, use_log=False)
>> + self.vm.run_job(job='drive0', auto_dismiss=True)
>> + self.vm.run_job(job='node4', auto_dismiss=True)
>> self.assert_no_active_block_jobs()
>>
>> # Test a block-stream and a block-commit job in parallel
>> diff --git a/tests/qemu-iotests/245 b/tests/qemu-iotests/245
>> index 41218d5f1d..eba2157cff 100644
>> --- a/tests/qemu-iotests/245
>> +++ b/tests/qemu-iotests/245
>> @@ -1000,5 +1000,6 @@ class TestBlockdevReopen(iotests.QMPTestCase):
>> self.reopen(opts, {'backing': 'hd2'})
>>
>> if __name__ == '__main__':
>> + iotests.activate_logging()
>> iotests.main(supported_fmts=["qcow2"],
>> supported_protocols=["file"])
>> diff --git a/tests/qemu-iotests/245.out b/tests/qemu-iotests/245.out
>> index a19de5214d..15c3630e92 100644
>> --- a/tests/qemu-iotests/245.out
>> +++ b/tests/qemu-iotests/245.out
>> @@ -1,17 +1,17 @@
>> +{"execute": "job-finalize", "arguments": {"id": "commit0"}}
>> +{"return": {}}
>> +{"data": {"id": "commit0", "type": "commit"}, "event": "BLOCK_JOB_PENDING", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
>> +{"data": {"device": "commit0", "len": 3145728, "offset": 3145728, "speed": 0, "type": "commit"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
>> +{"execute": "job-finalize", "arguments": {"id": "stream0"}}
>> +{"return": {}}
>> +{"data": {"id": "stream0", "type": "stream"}, "event": "BLOCK_JOB_PENDING", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
>> +{"data": {"device": "stream0", "len": 3145728, "offset": 3145728, "speed": 0, "type": "stream"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
>> +{"execute": "job-finalize", "arguments": {"id": "stream0"}}
>> +{"return": {}}
>> +{"data": {"id": "stream0", "type": "stream"}, "event": "BLOCK_JOB_PENDING", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
>> +{"data": {"device": "stream0", "len": 3145728, "offset": 3145728, "speed": 0, "type": "stream"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
>> ..................
>> ----------------------------------------------------------------------
>> Ran 18 tests
>>
>> OK
>> -{"execute": "job-finalize", "arguments": {"id": "commit0"}}
>> -{"return": {}}
>> -{"data": {"id": "commit0", "type": "commit"}, "event": "BLOCK_JOB_PENDING", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
>> -{"data": {"device": "commit0", "len": 3145728, "offset": 3145728, "speed": 0, "type": "commit"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
>> -{"execute": "job-finalize", "arguments": {"id": "stream0"}}
>> -{"return": {}}
>> -{"data": {"id": "stream0", "type": "stream"}, "event": "BLOCK_JOB_PENDING", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
>> -{"data": {"device": "stream0", "len": 3145728, "offset": 3145728, "speed": 0, "type": "stream"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
>> -{"execute": "job-finalize", "arguments": {"id": "stream0"}}
>> -{"return": {}}
>> -{"data": {"id": "stream0", "type": "stream"}, "event": "BLOCK_JOB_PENDING", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
>> -{"data": {"device": "stream0", "len": 3145728, "offset": 3145728, "speed": 0, "type": "stream"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
>> diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
>> index e28d75e018..5a501f0529 100644
>> --- a/tests/qemu-iotests/iotests.py
>> +++ b/tests/qemu-iotests/iotests.py
>> @@ -35,6 +35,13 @@ from collections import OrderedDict
>> sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'python'))
>> from qemu import qtest
>>
>> +# Use this logger for logging messages directly from the iotests module
>> +logger = logging.getLogger(__name__)
>> +logger.addHandler(logging.NullHandler())
>> +
>> +# Use this logger for messages that ought to be used for diff output.
>> +test_logger = logging.getLogger('.'.join((__name__, 'iotest')))
>> +test_logger.addHandler(logging.NullHandler())
>>
>> # This will not work if arguments contain spaces but is necessary if we
>> # want to support the override options that ./check supports.
>> @@ -343,10 +350,10 @@ def log(msg, filters=[], indent=None):
>> separators = (', ', ': ') if indent is None else (',', ': ')
>> # Don't sort if it's already sorted
>> do_sort = not isinstance(msg, OrderedDict)
>> - print(json.dumps(msg, sort_keys=do_sort,
>> - indent=indent, separators=separators))
>> + test_logger.info(json.dumps(msg, sort_keys=do_sort,
>> + indent=indent, separators=separators))
>> else:
>> - print(msg)
>> + test_logger.info(msg)
>>
>> class Timeout:
>> def __init__(self, seconds, errmsg = "Timeout"):
>> @@ -559,7 +566,7 @@ class VM(qtest.QEMUQtestMachine):
>>
>> # Returns None on success, and an error string on failure
>> def run_job(self, job, auto_finalize=True, auto_dismiss=False,
>> - pre_finalize=None, cancel=False, use_log=True, wait=60.0):
>> + pre_finalize=None, cancel=False, wait=60.0):
>> """
>> run_job moves a job from creation through to dismissal.
>>
>> @@ -572,7 +579,6 @@ class VM(qtest.QEMUQtestMachine):
>> invoked prior to issuing job-finalize, if any.
>> :param cancel: Bool. When true, cancels the job after the pre_finalize
>> callback.
>> - :param use_log: Bool. When false, does not log QMP messages.
>> :param wait: Float. Timeout value specifying how long to wait for any
>> event, in seconds. Defaults to 60.0.
>> """
>> @@ -590,8 +596,7 @@ class VM(qtest.QEMUQtestMachine):
>> while True:
>> ev = filter_qmp_event(self.events_wait(events))
>> if ev['event'] != 'JOB_STATUS_CHANGE':
>> - if use_log:
>> - log(ev)
>> + log(ev)
>> continue
>> status = ev['data']['status']
>> if status == 'aborting':
>> @@ -599,24 +604,16 @@ class VM(qtest.QEMUQtestMachine):
>> for j in result['return']:
>> if j['id'] == job:
>> error = j['error']
>> - if use_log:
>> - log('Job failed: %s' % (j['error']))
>> + log('Job failed: %s' % (j['error']))
>> elif status == 'pending' and not auto_finalize:
>> if pre_finalize:
>> pre_finalize()
>> - if cancel and use_log:
>> + if cancel:
>> self.qmp_log('job-cancel', id=job)
>> - elif cancel:
>> - self.qmp('job-cancel', id=job)
>> - elif use_log:
>> + else:
>> self.qmp_log('job-finalize', id=job)
>> - else:
>> - self.qmp('job-finalize', id=job)
>> elif status == 'concluded' and not auto_dismiss:
>> - if use_log:
>> - self.qmp_log('job-dismiss', id=job)
>> - else:
>> - self.qmp('job-dismiss', id=job)
>> + self.qmp_log('job-dismiss', id=job)
>> elif status == 'null':
>> return error
>>
>> @@ -809,7 +806,7 @@ def notrun(reason):
>> seq = os.path.basename(sys.argv[0])
>>
>> open('%s/%s.notrun' % (output_dir, seq), 'w').write(reason + '\n')
>> - print('%s not run: %s' % (seq, reason))
>> + logger.warning("%s not run: %s", seq, reason)
>> sys.exit(0)
>>
>> def case_notrun(reason):
>> @@ -954,6 +951,7 @@ def execute_setup_common(supported_fmts=[],
>> if debug:
>> sys.argv.remove('-d')
>> logging.basicConfig(level=(logging.DEBUG if debug else logging.WARN))
>> + logger.debug("iotests debugging messages active")
>>
>> return debug
>>
>> @@ -966,14 +964,25 @@ def execute_test(test_function=None, *args, **kwargs):
>> else:
>> test_function()
>>
>> +def activate_logging():
>> + """Activate iotests.log() output to stdout for script-style tests."""
>> + handler = logging.StreamHandler(stream=sys.stdout)
>> + formatter = logging.Formatter('%(message)s')
>> + handler.setFormatter(formatter)
>
> Hmm, it seems this formatter is default behavior, and it's not necessary to
> create and set it..
>
You might be right; I think it's OK to set it explicitly.
>> + test_logger.addHandler(handler)
>
> possibly, we want to remove old handler (null), as it's not needed anymore.
>
Right, it's there as an "event sink" in the case that no caller sets up
a root logger. I'll look into this if/when I pursue an idempotent
enable/disable toggle.
At this point, if there's no major issues, I'd rather get the fiddly
bits checked in before continuing on this cleanup; I can always start
sending some "part 2" patches along this line.
>> + test_logger.setLevel(logging.INFO)
>
> Should it be DEBUG if -d given?
>
There's no reason to yet, because there's no use of the test_logger that
uses debug-level statements. That is, regardless of the "debug level",
we're going to log the same exact things to the diff output.
We COULD complicate this in the future if we wanted to. That is, we can
utilize debug-level loggers and create nnn.out.debug; but there's no
reason to do that yet.
>> + test_logger.propagate = False
>> +
>> # This is called from script-style iotests without a single point of entry
>> def script_initialize(*args, **kwargs):
>> """Initialize script-style tests without running any tests."""
>> + activate_logging()
>> execute_setup_common(*args, **kwargs)
>>
>> # This is called from script-style iotests with a single point of entry
>> def script_main(test_function, *args, **kwargs):
>> """Run script-style tests outside of the unittest framework"""
>> + activate_logging()
>> execute_test(test_function, *args, **kwargs)
>>
>> # This is called from unittest style iotests
>>
>
> anyway, it seems OK for me as is:
>
> Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
>
>
Oh, and I forgot to clean up the comment strings, sorry about that...
I'll send a fixup patch.
--js
next prev parent reply other threads:[~2019-09-18 17:45 UTC|newest]
Thread overview: 44+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-09-17 23:45 [Qemu-devel] [PATCH v5 0/5] iotests: use python logging John Snow
2019-09-17 23:45 ` [Qemu-devel] [PATCH v5 1/5] iotests: remove 'linux' from default supported platforms John Snow
2019-09-18 13:16 ` Vladimir Sementsov-Ogievskiy
2019-09-23 13:09 ` Max Reitz
2019-09-23 17:21 ` John Snow
2019-09-27 23:35 ` John Snow
2019-10-01 18:44 ` Max Reitz
2019-10-02 4:46 ` Thomas Huth
2019-10-02 11:57 ` Max Reitz
2019-10-02 13:11 ` Thomas Huth
2019-10-02 13:36 ` Max Reitz
2019-10-02 14:26 ` Thomas Huth
2019-10-02 16:44 ` Kevin Wolf
2019-10-02 17:47 ` Max Reitz
2019-10-04 10:19 ` Kevin Wolf
2019-10-04 12:44 ` Max Reitz
2019-10-04 13:16 ` Peter Maydell
2019-10-04 13:50 ` Max Reitz
2019-10-04 14:05 ` Peter Maydell
2019-10-04 14:40 ` Max Reitz
2019-10-07 12:16 ` Thomas Huth
2019-10-07 12:38 ` Peter Maydell
2019-10-07 12:52 ` Max Reitz
2019-10-07 13:11 ` Thomas Huth
2019-10-07 16:28 ` Thomas Huth
2019-10-07 16:55 ` Max Reitz
2019-10-02 17:54 ` Thomas Huth
2019-10-03 0:16 ` John Snow
2019-09-17 23:45 ` [Qemu-devel] [PATCH v5 2/5] iotests: add script_initialize John Snow
2019-09-18 13:48 ` Vladimir Sementsov-Ogievskiy
2019-09-23 13:30 ` Max Reitz
2019-09-23 13:34 ` Max Reitz
2019-09-17 23:45 ` [Qemu-devel] [PATCH v5 3/5] iotest 258: use script_main John Snow
2019-09-23 13:33 ` Max Reitz
2019-09-17 23:45 ` [Qemu-devel] [PATCH v5 4/5] iotests: specify protocol support via initialization info John Snow
2019-09-23 13:35 ` Max Reitz
2019-09-17 23:45 ` [Qemu-devel] [PATCH v5 5/5] iotests: use python logging for iotests.log() John Snow
2019-09-18 14:52 ` Vladimir Sementsov-Ogievskiy
2019-09-18 17:11 ` John Snow [this message]
2019-09-23 13:57 ` Max Reitz
2019-10-04 15:39 ` [PATCH v5 0/5] iotests: use python logging Max Reitz
2019-10-11 23:39 ` John Snow
2020-02-24 11:15 ` Max Reitz
2020-02-25 21:50 ` John Snow
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=f181725a-1f67-6592-f636-3d7cab41bfc7@redhat.com \
--to=jsnow@redhat.com \
--cc=kwolf@redhat.com \
--cc=mreitz@redhat.com \
--cc=qemu-block@nongnu.org \
--cc=qemu-devel@nongnu.org \
--cc=vsementsov@virtuozzo.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).