Fix the issue when memoryview obj gets to subunit parser
Change-Id: I26bf6a5847d1852ebd3badbb976320a01c49aa86
This commit is contained in:
@@ -20,6 +20,12 @@ Changelog
|
|||||||
[unreleased]
|
[unreleased]
|
||||||
------------
|
------------
|
||||||
|
|
||||||
|
Fixed
|
||||||
|
~~~~~
|
||||||
|
|
||||||
|
* Parsing subunit v2 stream (rally-verify component) when the result is
|
||||||
|
wrapped by ``memoryview`` python object.
|
||||||
|
|
||||||
Added
|
Added
|
||||||
~~~~~
|
~~~~~
|
||||||
|
|
||||||
|
|||||||
@@ -25,33 +25,22 @@ _IGNORE_LIST = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
def prepare_input_args(func):
|
class TestID(str):
|
||||||
# NOTE(andreykurilin): Variables 'runnable', 'eof', 'route_code' are not
|
|
||||||
# used in parser.
|
|
||||||
def inner(self, test_id=None, test_status=None, timestamp=None,
|
|
||||||
file_name=None, file_bytes=None, mime_type=None, test_tags=None,
|
|
||||||
runnable=True, eof=False, route_code=None):
|
|
||||||
if not test_id or test_id in _IGNORE_LIST:
|
|
||||||
return
|
|
||||||
|
|
||||||
if (test_id.startswith("setUpClass (")
|
@staticmethod
|
||||||
or test_id.startswith("tearDown (")):
|
def __new__(cls, value):
|
||||||
test_id = test_id[test_id.find("(") + 1:-1]
|
if (value.startswith("setUpClass (")
|
||||||
|
or value.startswith("tearDown (")):
|
||||||
|
value = value[value.find("(") + 1:-1]
|
||||||
|
return super(TestID, cls).__new__(cls, value)
|
||||||
|
|
||||||
tags = _parse_test_tags(test_id)
|
def __init__(self, value):
|
||||||
|
if self.find("[") > -1:
|
||||||
func(self, test_id, test_status, timestamp, tags,
|
self.name, tags = self.split("[", 1)
|
||||||
file_name, file_bytes, test_tags, mime_type)
|
self.tags = tags[:-1].split(",")
|
||||||
|
else:
|
||||||
return inner
|
self.name = value
|
||||||
|
self.tags = []
|
||||||
|
|
||||||
def _parse_test_tags(test_id):
|
|
||||||
tags = []
|
|
||||||
if test_id.find("[") > -1:
|
|
||||||
tags = test_id.split("[")[1][:-1].split(",")
|
|
||||||
|
|
||||||
return tags
|
|
||||||
|
|
||||||
|
|
||||||
class SubunitV2StreamResult(object):
|
class SubunitV2StreamResult(object):
|
||||||
@@ -75,13 +64,9 @@ class SubunitV2StreamResult(object):
|
|||||||
self._unknown_entities = {}
|
self._unknown_entities = {}
|
||||||
self._is_parsed = False
|
self._is_parsed = False
|
||||||
|
|
||||||
@staticmethod
|
def _check_expected_failure(self, test_id: TestID):
|
||||||
def _get_test_name(test_id):
|
|
||||||
return test_id.split("[")[0] if test_id.find("[") > -1 else test_id
|
|
||||||
|
|
||||||
def _check_expected_failure(self, test_id):
|
|
||||||
if (test_id in self._expected_failures
|
if (test_id in self._expected_failures
|
||||||
or self._get_test_name(test_id) in self._expected_failures):
|
or test_id.name in self._expected_failures):
|
||||||
if self._tests[test_id]["status"] == "fail":
|
if self._tests[test_id]["status"] == "fail":
|
||||||
self._tests[test_id]["status"] = "xfail"
|
self._tests[test_id]["status"] = "xfail"
|
||||||
if self._expected_failures[test_id]:
|
if self._expected_failures[test_id]:
|
||||||
@@ -94,16 +79,16 @@ class SubunitV2StreamResult(object):
|
|||||||
for t_id in self._skipped_tests.copy():
|
for t_id in self._skipped_tests.copy():
|
||||||
if t_id not in self._tests:
|
if t_id not in self._tests:
|
||||||
status = "skip"
|
status = "skip"
|
||||||
name = self._get_test_name(t_id)
|
t_id = TestID(t_id)
|
||||||
self._tests[t_id] = {"status": status,
|
self._tests[t_id] = {"status": status,
|
||||||
"name": name,
|
"name": t_id.name,
|
||||||
"duration": "%.3f" % 0,
|
"duration": "%.3f" % 0,
|
||||||
"tags": _parse_test_tags(t_id)}
|
"tags": t_id.tags}
|
||||||
if self._skipped_tests[t_id]:
|
if self._skipped_tests[t_id]:
|
||||||
self._tests[t_id]["reason"] = self._skipped_tests[t_id]
|
self._tests[t_id]["reason"] = self._skipped_tests[t_id]
|
||||||
status += ": %s" % self._tests[t_id]["reason"]
|
status += ": %s" % self._tests[t_id]["reason"]
|
||||||
if self._live:
|
if self._live:
|
||||||
self._logger.info("{-} %s ... %s" % (name, status))
|
self._logger.info("{-} %s ... %s" % (t_id.name, status))
|
||||||
|
|
||||||
self._skipped_tests.pop(t_id)
|
self._skipped_tests.pop(t_id)
|
||||||
|
|
||||||
@@ -158,9 +143,17 @@ class SubunitV2StreamResult(object):
|
|||||||
"unexpected_success": len(self.filter_tests("uxsuccess")),
|
"unexpected_success": len(self.filter_tests("uxsuccess")),
|
||||||
"expected_failures": len(self.filter_tests("xfail"))}
|
"expected_failures": len(self.filter_tests("xfail"))}
|
||||||
|
|
||||||
@prepare_input_args
|
def status(self, test_id=None, test_status=None, timestamp=None,
|
||||||
def status(self, test_id=None, test_status=None, timestamp=None, tags=None,
|
file_name=None, file_bytes=None, mime_type=None, test_tags=None,
|
||||||
file_name=None, file_bytes=None, worker=None, mime_type=None):
|
runnable=True, eof=False, route_code=None):
|
||||||
|
|
||||||
|
if not test_id or test_id in _IGNORE_LIST:
|
||||||
|
return
|
||||||
|
|
||||||
|
test_id = TestID(test_id)
|
||||||
|
if isinstance(file_bytes, memoryview):
|
||||||
|
file_bytes = file_bytes.tobytes()
|
||||||
|
|
||||||
if timestamp:
|
if timestamp:
|
||||||
if not self._first_timestamp:
|
if not self._first_timestamp:
|
||||||
self._first_timestamp = timestamp
|
self._first_timestamp = timestamp
|
||||||
@@ -168,9 +161,9 @@ class SubunitV2StreamResult(object):
|
|||||||
|
|
||||||
if test_status == "exists":
|
if test_status == "exists":
|
||||||
self._tests[test_id] = {"status": "init",
|
self._tests[test_id] = {"status": "init",
|
||||||
"name": self._get_test_name(test_id),
|
"name": test_id.name,
|
||||||
"duration": "%.3f" % 0,
|
"duration": "%.3f" % 0,
|
||||||
"tags": tags if tags else []}
|
"tags": test_id.tags}
|
||||||
elif test_id in self._tests:
|
elif test_id in self._tests:
|
||||||
if test_status == "inprogress":
|
if test_status == "inprogress":
|
||||||
# timestamp of test start
|
# timestamp of test start
|
||||||
@@ -219,9 +212,8 @@ class SubunitV2StreamResult(object):
|
|||||||
if reason:
|
if reason:
|
||||||
status += ": %s" % reason
|
status += ": %s" % reason
|
||||||
|
|
||||||
w = "{%s} " % worker.pop().split("-")[1] if worker else "-"
|
w = "{%s} " % test_tags.pop().split("-")[1] if test_tags else "-"
|
||||||
self._logger.info("%s ... %s"
|
self._logger.info(f"{w}{test_id.name} ... {status}")
|
||||||
% (w + self._get_test_name(test_id), status))
|
|
||||||
|
|
||||||
def filter_tests(self, status):
|
def filter_tests(self, status):
|
||||||
"""Filter tests by given status."""
|
"""Filter tests by given status."""
|
||||||
|
|||||||
@@ -12,7 +12,6 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
import os
|
import os
|
||||||
from unittest import mock
|
|
||||||
|
|
||||||
from rally.common.io import subunit_v2
|
from rally.common.io import subunit_v2
|
||||||
from tests.unit import test
|
from tests.unit import test
|
||||||
@@ -93,23 +92,6 @@ RuntimeError: broken setUp method
|
|||||||
|
|
||||||
self.assertTrue(results._is_parsed)
|
self.assertTrue(results._is_parsed)
|
||||||
|
|
||||||
def test_prepare_input_args(self):
|
|
||||||
some_mock = mock.MagicMock()
|
|
||||||
|
|
||||||
@subunit_v2.prepare_input_args
|
|
||||||
def some_a(self_, test_id, test_status, timestamp, test_tags,
|
|
||||||
file_name, file_bytes, worker, mime_type):
|
|
||||||
some_mock(test_id, test_tags)
|
|
||||||
|
|
||||||
some_a("", "setUpClass (some_test[tag1,tag2])")
|
|
||||||
some_mock.assert_called_once_with(
|
|
||||||
"some_test[tag1,tag2]", ["tag1", "tag2"])
|
|
||||||
|
|
||||||
some_mock.reset_mock()
|
|
||||||
some_a("", "tearDown (some_test[tag1,tag2])")
|
|
||||||
some_mock.assert_called_once_with(
|
|
||||||
"some_test[tag1,tag2]", ["tag1", "tag2"])
|
|
||||||
|
|
||||||
def test_no_status_called(self):
|
def test_no_status_called(self):
|
||||||
self.assertEqual({"tests_count": 0, "tests_duration": "%.3f" % 0,
|
self.assertEqual({"tests_count": 0, "tests_duration": "%.3f" % 0,
|
||||||
"failures": 0, "skipped": 0, "success": 0,
|
"failures": 0, "skipped": 0, "success": 0,
|
||||||
@@ -144,3 +126,10 @@ RuntimeError: broken setUp method
|
|||||||
self.assertEqual("skip", tests[test_id]["status"])
|
self.assertEqual("skip", tests[test_id]["status"])
|
||||||
self.assertEqual("Some details why this test skipped",
|
self.assertEqual("Some details why this test skipped",
|
||||||
tests[test_id]["reason"])
|
tests[test_id]["reason"])
|
||||||
|
|
||||||
|
|
||||||
|
class TestIDTestCase(test.TestCase):
|
||||||
|
def test_id_processing(self):
|
||||||
|
value = subunit_v2.TestID("setUpClass (some_test[tag1,tag2])")
|
||||||
|
self.assertEqual("some_test", value.name)
|
||||||
|
self.assertEqual(["tag1", "tag2"], value.tags)
|
||||||
|
|||||||
Reference in New Issue
Block a user