practracker: a violation of a .may_include rule is now a problem.

We treat "0" as the expected number, and warn about everything
else.  The problem type is "dependency-violation".
This commit is contained in:
Nick Mathewson 2019-08-05 17:17:50 -04:00
parent 720951f056
commit 6b26281b50
2 changed files with 33 additions and 1 deletions

View File

@ -25,6 +25,7 @@ import os, sys
import metrics import metrics
import util import util
import problem import problem
import includes
# The filename of the exceptions file (it should be placed in the practracker directory) # The filename of the exceptions file (it should be placed in the practracker directory)
EXCEPTIONS_FNAME = "./exceptions.txt" EXCEPTIONS_FNAME = "./exceptions.txt"
@ -35,12 +36,15 @@ MAX_FILE_SIZE = 3000 # lines
MAX_FUNCTION_SIZE = 100 # lines MAX_FUNCTION_SIZE = 100 # lines
# Recommended number of #includes # Recommended number of #includes
MAX_INCLUDE_COUNT = 50 MAX_INCLUDE_COUNT = 50
# Recommended number of dependency violations
MAX_DEP_VIOLATIONS = 0
# Map from problem type to functions that adjust for tolerance # Map from problem type to functions that adjust for tolerance
TOLERANCE_FNS = { TOLERANCE_FNS = {
'include-count': lambda n: int(n*1.1), 'include-count': lambda n: int(n*1.1),
'function-size': lambda n: int(n*1.1), 'function-size': lambda n: int(n*1.1),
'file-size': lambda n: int(n*1.02) 'file-size': lambda n: int(n*1.02),
'dependency-violation': lambda n: (n+2)
} }
####################################################### #######################################################
@ -94,6 +98,7 @@ def consider_metrics_for_file(fname, f):
Yield a sequence of problem.Item objects for all of the metrics in Yield a sequence of problem.Item objects for all of the metrics in
'f'. 'f'.
""" """
real_fname = fname
# Strip the useless part of the path # Strip the useless part of the path
if fname.startswith(TOR_TOPDIR): if fname.startswith(TOR_TOPDIR):
fname = fname[len(TOR_TOPDIR):] fname = fname[len(TOR_TOPDIR):]
@ -112,6 +117,13 @@ def consider_metrics_for_file(fname, f):
for item in consider_function_size(fname, f): for item in consider_function_size(fname, f):
yield item yield item
n = 0
for item in includes.consider_include_rules(real_fname):
n += 1
if n:
yield problem.DependencyViolationItem(fname, n)
HEADER="""\ HEADER="""\
# Welcome to the exceptions file for Tor's best-practices tracker! # Welcome to the exceptions file for Tor's best-practices tracker!
# #
@ -167,6 +179,8 @@ def main(argv):
help="Maximum includes per C file") help="Maximum includes per C file")
parser.add_argument("--max-function-size", default=MAX_FUNCTION_SIZE, parser.add_argument("--max-function-size", default=MAX_FUNCTION_SIZE,
help="Maximum lines per function") help="Maximum lines per function")
parser.add_argument("--max-dependency-violations", default=MAX_DEP_VIOLATIONS,
help="Maximum number of dependency violations to allow")
parser.add_argument("topdir", default=".", nargs="?", parser.add_argument("topdir", default=".", nargs="?",
help="Top-level directory for the tor source") help="Top-level directory for the tor source")
args = parser.parse_args(argv[1:]) args = parser.parse_args(argv[1:])
@ -183,6 +197,7 @@ def main(argv):
filt.addThreshold(problem.FileSizeItem("*", int(args.max_file_size))) filt.addThreshold(problem.FileSizeItem("*", int(args.max_file_size)))
filt.addThreshold(problem.IncludeCountItem("*", int(args.max_include_count))) filt.addThreshold(problem.IncludeCountItem("*", int(args.max_include_count)))
filt.addThreshold(problem.FunctionSizeItem("*", int(args.max_function_size))) filt.addThreshold(problem.FunctionSizeItem("*", int(args.max_function_size)))
filt.addThreshold(problem.DependencyViolationItem("*", int(args.max_dependency_violations)))
# 1) Get all the .c files we care about # 1) Get all the .c files we care about
files_list = util.get_tor_c_files(TOR_TOPDIR) files_list = util.get_tor_c_files(TOR_TOPDIR)

View File

@ -191,6 +191,21 @@ class FunctionSizeItem(Item):
def __init__(self, problem_location, metric_value): def __init__(self, problem_location, metric_value):
super(FunctionSizeItem, self).__init__("function-size", problem_location, metric_value) super(FunctionSizeItem, self).__init__("function-size", problem_location, metric_value)
class DependencyViolationItem(Item):
"""
Denotes a dependency violation in a .c or .h file. A dependency violation
occurs when a file includes a file from some module that is not listed
in its .may_include file.
The 'problem_location' is the file that contains the problem.
The 'metric_value' is the number of forbidden includes.
"""
def __init__(self, problem_location, metric_value):
super(DependencyViolationItem, self).__init__("dependency-violation",
problem_location,
metric_value)
comment_re = re.compile(r'#.*$') comment_re = re.compile(r'#.*$')
def get_old_problem_from_exception_str(exception_str): def get_old_problem_from_exception_str(exception_str):
@ -212,5 +227,7 @@ def get_old_problem_from_exception_str(exception_str):
return IncludeCountItem(problem_location, metric_value) return IncludeCountItem(problem_location, metric_value)
elif problem_type == "function-size": elif problem_type == "function-size":
return FunctionSizeItem(problem_location, metric_value) return FunctionSizeItem(problem_location, metric_value)
elif problem_type == "dependency-violation":
return DependencyViolationItem(problem_location, metric_value)
else: else:
raise ValueError("Unknown exception type {!r}".format(orig_str)) raise ValueError("Unknown exception type {!r}".format(orig_str))