import os from io import StringIO from unittest import TestCase from unittest.mock import patch from zulint.custom_rules import RuleList from tools.linter_lib.custom_check import non_py_rules, python_rules ROOT_DIR = os.path.abspath(os.path.join(__file__, "..", "..", "..")) CHECK_MESSAGE = "Fix the corresponding rule in `tools/linter_lib/custom_check.py`." class TestRuleList(TestCase): def setUp(self) -> None: all_rules = list(python_rules.rules) for rule in non_py_rules: all_rules.extend(rule.rules) self.all_rules = all_rules def test_paths_in_rules(self) -> None: """Verifies that the paths mentioned in linter rules actually exist""" for rule in self.all_rules: for path in rule.get("exclude", {}): abs_path = os.path.abspath(os.path.join(ROOT_DIR, path)) self.assertTrue( os.path.exists(abs_path), f"'{path}' is neither an existing file, nor a directory. {CHECK_MESSAGE}", ) for line_tuple in rule.get("exclude_line", {}): path = line_tuple[0] abs_path = os.path.abspath(os.path.join(ROOT_DIR, path)) self.assertTrue( os.path.isfile(abs_path), f"The file '{path}' doesn't exist. {CHECK_MESSAGE}" ) for path in rule.get("include_only", {}): if not os.path.splitext(path)[1]: self.assertTrue( path.endswith("/"), f"The path '{path}' should end with '/'. {CHECK_MESSAGE}", ) def test_rule_patterns(self) -> None: """Verifies that the search regex specified in a custom rule actually matches the expectation and doesn't throw false positives.""" for rule in self.all_rules: pattern = rule["pattern"] for line in rule.get("good_lines", []): # create=True is superfluous when mocking built-ins in Python >= 3.5 with patch( "builtins.open", return_value=StringIO(line + "\n\n"), create=True, autospec=True, ): self.assertFalse( RuleList([], [rule]).custom_check_file("foo.bar", "baz", ""), f"The pattern '{pattern}' matched the line '{line}' while it shouldn't.", ) for line in rule.get("bad_lines", []): # create=True is superfluous when mocking built-ins in Python >= 3.5 with patch( "builtins.open", return_value=StringIO(line + "\n\n"), create=True, autospec=True, ), patch("builtins.print"): filename = list(rule.get("include_only", {"foo.bar"}))[0] self.assertTrue( RuleList([], [rule]).custom_check_file(filename, "baz", ""), f"The pattern '{pattern}' didn't match the line '{line}' while it should.", )