summaryrefslogtreecommitdiff
path: root/tests/test_check_parallel.py
diff options
context:
space:
mode:
authorFrank Harrison <frank@doublethefish.com>2020-04-04 08:15:10 +0100
committerBryce Guinta <bryce.guinta@protonmail.com>2020-10-19 12:26:17 -0700
commitbccbbcda76b0a0d2ed78e7d67fd5dd85c7037864 (patch)
tree4e2678593d5eccddc518ab730b21cac305937e38 /tests/test_check_parallel.py
parentb2ef3f7174b7b9a0128da98ed6ed187c18428024 (diff)
downloadpylint-git-bccbbcda76b0a0d2ed78e7d67fd5dd85c7037864.tar.gz
check_parallel| Adds new test suite for multiple workers/check_parallel
These regression tests put check_parallel() and related functions under tests, ensuring that the functionality remains consistent ahead of any bug fixes and performance work we may do.
Diffstat (limited to 'tests/test_check_parallel.py')
-rw-r--r--tests/test_check_parallel.py262
1 files changed, 262 insertions, 0 deletions
diff --git a/tests/test_check_parallel.py b/tests/test_check_parallel.py
new file mode 100644
index 000000000..686941e6b
--- /dev/null
+++ b/tests/test_check_parallel.py
@@ -0,0 +1,262 @@
+""" Puts the check_parallel system under test """
+# Copyright (c) 2020 Frank Harrison <doublethefish@gmail.com>
+
+# Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+# For details: https://github.com/PyCQA/pylint/blob/master/COPYING
+
+# pylint: disable=protected-access,missing-function-docstring,no-self-use
+
+import collections
+import os
+
+import pytest
+
+import pylint.interfaces
+import pylint.lint.parallel
+from pylint.checkers.base_checker import BaseChecker
+from pylint.lint import PyLinter
+from pylint.lint.parallel import _worker_check_single_file as worker_check_single_file
+from pylint.lint.parallel import _worker_initialize as worker_initialize
+from pylint.lint.parallel import check_parallel
+from pylint.testutils import TestReporter as Reporter
+
+
+def _gen_file_data(idx=0):
+ """ Generates a file to use as a stream """
+ filepath = os.path.abspath(
+ os.path.join(os.path.dirname(__file__), "input", "similar1")
+ )
+ file_data = (
+ "--test-file_data-name-%d--" % idx,
+ filepath,
+ "--test-file_data-modname--",
+ )
+ return file_data
+
+
+def _gen_file_datas(count=1):
+ file_infos = [_gen_file_data(idx) for idx in range(count)]
+ return file_infos
+
+
+class SequentialTestChecker(BaseChecker):
+ """ A checker that does not need to consolidate data across run invocations """
+
+ __implements__ = (pylint.interfaces.IRawChecker,)
+
+ name = "sequential-checker"
+ test_data = "sequential"
+ msgs = {"R9999": ("Test", "sequential-test-check", "Some helpful text.",)}
+
+ def __init__(self, linter, *args, **kwargs):
+ super().__init__(linter, *args, **kwargs)
+ self.data = []
+ self.linter = linter
+
+ def process_module(self, _astroid):
+ """ Called once per stream/file/astroid object """
+ # record the number of invocations with the data object
+ record = self.test_data + str(len(self.data))
+ self.data.append(record)
+
+
+class TestCheckParallelFramework:
+ """ Tests the check_parallel() function's framework """
+
+ def setUp(self):
+ self._prev_global_linter = pylint.lint.parallel._worker_linter
+
+ def tearDown(self):
+ pylint.lint.parallel._worker_linter = self._prev_global_linter
+
+ def test_worker_initialize(self):
+ linter = PyLinter(reporter=Reporter())
+ worker_initialize(linter=linter)
+ assert pylint.lint.parallel._worker_linter == linter
+
+ def test_worker_check_single_file_uninitialised(self):
+ pylint.lint.parallel._worker_linter = None
+ with pytest.raises(AttributeError):
+ worker_check_single_file(_gen_file_data())
+
+ def test_worker_check_single_file_no_checkers(self):
+ linter = PyLinter(reporter=Reporter())
+ worker_initialize(linter=linter)
+ (name, msgs, stats, msg_status) = worker_check_single_file(_gen_file_data())
+ assert name == "--test-file_data-name-0--"
+ assert [] == msgs
+ no_errors_status = 0
+ assert no_errors_status == msg_status
+ assert {
+ "by_module": {
+ "--test-file_data-name-0--": {
+ "convention": 0,
+ "error": 0,
+ "fatal": 0,
+ "info": 0,
+ "refactor": 0,
+ "statement": 18,
+ "warning": 0,
+ }
+ },
+ "by_msg": {},
+ "convention": 0,
+ "error": 0,
+ "fatal": 0,
+ "info": 0,
+ "refactor": 0,
+ "statement": 18,
+ "warning": 0,
+ } == stats
+
+ def test_worker_check_sequential_checker(self):
+ """ Same as test_worker_check_single_file_no_checkers with SequentialTestChecker
+ """
+ linter = PyLinter(reporter=Reporter())
+ worker_initialize(linter=linter)
+
+ # Add the only checker we care about in this test
+ linter.register_checker(SequentialTestChecker(linter))
+
+ (name, msgs, stats, msg_status) = worker_check_single_file(_gen_file_data())
+
+ # Ensure we return the same data as the single_file_no_checkers test
+ assert name == "--test-file_data-name-0--"
+ assert [] == msgs
+ no_errors_status = 0
+ assert no_errors_status == msg_status
+ assert {
+ "by_module": {
+ "--test-file_data-name-0--": {
+ "convention": 0,
+ "error": 0,
+ "fatal": 0,
+ "info": 0,
+ "refactor": 0,
+ "statement": 18,
+ "warning": 0,
+ }
+ },
+ "by_msg": {},
+ "convention": 0,
+ "error": 0,
+ "fatal": 0,
+ "info": 0,
+ "refactor": 0,
+ "statement": 18,
+ "warning": 0,
+ } == stats
+
+
+class TestCheckParallel:
+ """ Tests the check_parallel() function """
+
+ def test_sequential_checkers_work(self):
+ """Tests original basic types of checker works as expected in -jN
+
+ This means that a sequential checker should return the same data for a given
+ file-stream irrespective of whether its run in -j1 or -jN
+ """
+ linter = PyLinter(reporter=Reporter())
+
+ # Add a sequential checker to ensure it records data against some streams
+ linter.register_checker(SequentialTestChecker(linter))
+ linter.enable("R9999")
+
+ # Create a dummy file, the actual contents of which will be ignored by the
+ # register test checkers, but it will trigger at least a single-job to be run.
+ single_file_container = _gen_file_datas(count=1)
+
+ # Invoke the lint process in a multiprocess way, although we only specify one
+ # job.
+ check_parallel(linter, jobs=1, files=single_file_container, arguments=None)
+ assert len(linter.get_checkers()) == 2, (
+ "We should only have the 'master' and 'sequential-checker' "
+ "checkers registered"
+ )
+ assert {
+ "by_module": {
+ "--test-file_data-name-0--": {
+ "convention": 0,
+ "error": 0,
+ "fatal": 0,
+ "info": 0,
+ "refactor": 0,
+ "statement": 18,
+ "warning": 0,
+ }
+ },
+ "by_msg": {},
+ "convention": 0,
+ "error": 0,
+ "fatal": 0,
+ "info": 0,
+ "refactor": 0,
+ "statement": 18,
+ "warning": 0,
+ } == linter.stats
+
+ # now run the regular mode of checking files and check that, in this proc, we
+ # collect the right data
+ filepath = single_file_container[0][1] # get the filepath element
+ linter.check(filepath)
+ assert {
+ "by_module": {
+ "input.similar1": { # module is the only change from previous
+ "convention": 0,
+ "error": 0,
+ "fatal": 0,
+ "info": 0,
+ "refactor": 0,
+ "statement": 18,
+ "warning": 0,
+ }
+ },
+ "by_msg": {},
+ "convention": 0,
+ "error": 0,
+ "fatal": 0,
+ "info": 0,
+ "refactor": 0,
+ "statement": 18,
+ "warning": 0,
+ } == linter.stats
+
+ def test_invoke_single_job(self):
+ """Tests basic checkers functionality using just a single workderdo
+
+ This is *not* the same -j1 and does not happen under normal operation """
+ linter = PyLinter(reporter=Reporter())
+
+ linter.register_checker(SequentialTestChecker(linter))
+
+ # Create a dummy file, the actual contents of which will be ignored by the
+ # register test checkers, but it will trigger at least a single-job to be run.
+ single_file_container = _gen_file_datas(count=1)
+
+ # Invoke the lint process in a multiprocess way, although we only specify one
+ # job.
+ check_parallel(linter, jobs=1, files=single_file_container, arguments=None)
+
+ assert {
+ "by_module": {
+ "--test-file_data-name-0--": {
+ "convention": 0,
+ "error": 0,
+ "fatal": 0,
+ "info": 0,
+ "refactor": 0,
+ "statement": 18,
+ "warning": 0,
+ }
+ },
+ "by_msg": collections.Counter(),
+ "convention": 0,
+ "error": 0,
+ "fatal": 0,
+ "info": 0,
+ "refactor": 0,
+ "statement": 18,
+ "warning": 0,
+ } == linter.stats
+ assert linter.msg_status == 0, "We expect a single-file check to exit cleanly"