Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make runner.create_output_path a member of TestRunner class #682

Merged
merged 3 commits into from
Sep 30, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 22 additions & 16 deletions tests/unit/test_test_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from unittest import mock
from tests.common import with_tempdir
from vunit.hashing import hash_string
from vunit.test.runner import TestRunner, create_output_path
from vunit.test.runner import TestRunner
from vunit.test.report import TestReport
from vunit.test.list import TestList

Expand All @@ -37,9 +37,9 @@ def test_runs_testcases_in_order(self, tempdir):
test_list.add_test(test_case2)
test_list.add_test(test_case3)
runner.run(test_list)
self.assertEqual(test_case1.output_path, create_output_path(tempdir, "test1"))
self.assertEqual(test_case2.output_path, create_output_path(tempdir, "test2"))
self.assertEqual(test_case3.output_path, create_output_path(tempdir, "test3"))
self.assertEqual(test_case1.output_path, runner._get_output_path("test1"))
self.assertEqual(test_case2.output_path, runner._get_output_path("test2"))
self.assertEqual(test_case3.output_path, runner._get_output_path("test3"))
self.assertEqual(order, ["test1", "test2", "test3"])
self.assertTrue(report.result_of("test1").passed)
self.assertTrue(report.result_of("test2").failed)
Expand All @@ -62,8 +62,8 @@ def test_fail_fast(self, tempdir):
runner.run(test_list)
except KeyboardInterrupt:
pass
self.assertEqual(test_case1.output_path, create_output_path(tempdir, "test1"))
self.assertEqual(test_case2.output_path, create_output_path(tempdir, "test2"))
self.assertEqual(test_case1.output_path, runner._get_output_path("test1"))
self.assertEqual(test_case2.output_path, runner._get_output_path("test2"))
self.assertEqual(test_case3.called, False)
self.assertEqual(order, ["test1", "test2"])
self.assertTrue(report.result_of("test1").passed)
Expand Down Expand Up @@ -135,12 +135,15 @@ def side_effect(read_output, **kwargs): # pylint: disable=unused-argument
self.assertTrue(report.result_of("test").passed)
self.assertEqual(report.result_of("test").output, "out1out2out3out4out5")

def test_create_output_path_on_linux(self):
def test_get_output_path_on_linux(self):
output_path = "output_path"
report = TestReport()
runner = TestRunner(report, output_path)

with mock.patch("sys.platform", new="linux"):
with mock.patch("os.environ", new={}):
output_path = "output_path"
test_name = "_" * 400
test_output = create_output_path(output_path, test_name)
test_output = runner._get_output_path(test_name)
self.assertEqual(
test_output,
str(
Expand All @@ -151,7 +154,7 @@ def test_create_output_path_on_linux(self):

output_path = "output_path"
test_name = "123._-+"
test_output = create_output_path(output_path, test_name)
test_output = runner._get_output_path(test_name)
self.assertEqual(
test_output,
str(
Expand All @@ -163,7 +166,7 @@ def test_create_output_path_on_linux(self):
output_path = "output_path"
test_name = "#<>:"
safe_name = "____"
test_output = create_output_path(output_path, test_name)
test_output = runner._get_output_path(test_name)
self.assertEqual(
test_output,
str(
Expand All @@ -172,20 +175,23 @@ def test_create_output_path_on_linux(self):
),
)

def test_create_output_path_on_windows(self):
def test_get_output_path_on_windows(self):
output_path = "output_path"
report = TestReport()
runner = TestRunner(report, output_path)

with mock.patch("sys.platform", new="win32"):
with mock.patch("os.environ", new={}):
output_path = "output_path"
test_name = "_" * 400
test_output = create_output_path(output_path, test_name)
test_output = runner._get_output_path(test_name)
self.assertEqual(len(test_output), 260 - 100 + 1)

with mock.patch(
"os.environ", new={"VUNIT_TEST_OUTPUT_PATH_MARGIN": "-1000"}
):
output_path = "output_path"
test_name = "_" * 400
test_output = create_output_path(output_path, test_name)
test_output = runner._get_output_path(test_name)
self.assertEqual(
test_output,
str(
Expand All @@ -197,7 +203,7 @@ def test_create_output_path_on_windows(self):
with mock.patch("os.environ", new={"VUNIT_SHORT_TEST_OUTPUT_PATHS": ""}):
output_path = "output_path"
test_name = "_" * 400
test_output = create_output_path(output_path, test_name)
test_output = runner._get_output_path(test_name)
self.assertEqual(
test_output,
str(Path(output_path).resolve() / hash_string(test_name)),
Expand Down
72 changes: 40 additions & 32 deletions vunit/test/runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ def _run_thread(self, write_stdout, scheduler, num_tests, is_main):
try:
test_suite = scheduler.next()

output_path = create_output_path(self._output_path, test_suite.name)
output_path = self._get_output_path(test_suite.name)
output_file_name = str(Path(output_path) / "output.txt")

with self._stdout_lock():
Expand All @@ -171,6 +171,36 @@ def _run_thread(self, write_stdout, scheduler, num_tests, is_main):
if test_suite is not None:
scheduler.test_done()

def _get_output_path(self, test_suite_name):
"""
Construct the full output path of a test case.
Ensure no bad characters and no long path names.
"""
output_path = str(Path(self._output_path).resolve())
safe_name = (
"".join(char if _is_legal(char) else "_" for char in test_suite_name) + "_"
)
hash_name = hash_string(test_suite_name)

if "VUNIT_SHORT_TEST_OUTPUT_PATHS" in os.environ:
full_name = hash_name
elif sys.platform == "win32":
max_path = 260
margin = int(os.environ.get("VUNIT_TEST_OUTPUT_PATH_MARGIN", "100"))
prefix_len = len(output_path)
full_name = (
safe_name[
: min(
max_path - margin - prefix_len - len(hash_name), len(safe_name)
)
]
+ hash_name
)
else:
full_name = safe_name + hash_name

return str(Path(output_path) / full_name)

def _add_skipped_tests(
self, test_suite, results, start_time, num_tests, output_file_name
):
Expand All @@ -196,7 +226,7 @@ def _run_test_suite(
results = self._fail_suite(test_suite)

try:
ostools.renew_path(output_path)
self._prepare_test_suite_output_path(output_path)
output_file = wrap(open(output_file_name, "a+"), use_color=False)
output_file.seek(0)
output_file.truncate()
Expand Down Expand Up @@ -258,6 +288,13 @@ def read_output():
if self._fail_fast and any_not_passed:
self._abort = True

@staticmethod
def _prepare_test_suite_output_path(output_path):
"""
Make sure the directory exists and is empty before running test.
"""
ostools.renew_path(output_path)

def _create_test_mapping_file(self, test_suites):
"""
Create a file mapping test name to test output folder.
Expand All @@ -276,7 +313,7 @@ def _create_test_mapping_file(self, test_suites):
mapping = set()

for test_suite in test_suites:
test_output = create_output_path(self._output_path, test_suite.name)
test_output = self._get_output_path(test_suite.name)
mapping.add("%s %s" % (Path(test_output).name, test_suite.name))

# Sort by everything except hash
Expand Down Expand Up @@ -430,35 +467,6 @@ def _is_legal(char):
return (char in LEGAL_CHARS) and (char not in ILLEGAL_CHARS)


def create_output_path(output_path, test_suite_name):
"""
Create the full output path of a test case.
Ensure no bad characters and no long path names.
"""
output_path = str(Path(output_path).resolve())
safe_name = (
"".join(char if _is_legal(char) else "_" for char in test_suite_name) + "_"
)
hash_name = hash_string(test_suite_name)

if "VUNIT_SHORT_TEST_OUTPUT_PATHS" in os.environ:
full_name = hash_name
elif sys.platform == "win32":
max_path = 260
margin = int(os.environ.get("VUNIT_TEST_OUTPUT_PATH_MARGIN", "100"))
prefix_len = len(output_path)
full_name = (
safe_name[
: min(max_path - margin - prefix_len - len(hash_name), len(safe_name))
]
+ hash_name
)
else:
full_name = safe_name + hash_name

return str(Path(output_path) / full_name)


def wrap(file_obj, use_color=True):
"""
Wrap file_obj in another stream which handles ANSI color codes using colorama
Expand Down