瀏覽代碼

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".
Nick Mathewson 5 年之前
父節點
當前提交
6b26281b50
共有 2 個文件被更改,包括 33 次插入1 次删除
  1. 16 1
      scripts/maint/practracker/practracker.py
  2. 17 0
      scripts/maint/practracker/problem.py

+ 16 - 1
scripts/maint/practracker/practracker.py

@@ -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)

+ 17 - 0
scripts/maint/practracker/problem.py

@@ -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))