summaryrefslogtreecommitdiff
path: root/scripts
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2020-02-14 12:58:39 -0500
committerNick Mathewson <nickm@torproject.org>2020-03-26 12:17:53 -0400
commita40d539f7cce851a4a66c68a14917e1681972475 (patch)
tree18ace1b5dd8cf5d9808dcba0134fbd454b69455d /scripts
parentc323cc0913bae31a0b70c94bf5fd685acd3d1c07 (diff)
downloadtor-a40d539f7cce851a4a66c68a14917e1681972475.tar.gz
tor-a40d539f7cce851a4a66c68a14917e1681972475.zip
Extend includes.py to compare topology with subsystem init order.
Diffstat (limited to 'scripts')
-rwxr-xr-xscripts/maint/practracker/includes.py50
1 files changed, 48 insertions, 2 deletions
diff --git a/scripts/maint/practracker/includes.py b/scripts/maint/practracker/includes.py
index e9b02c35b0..7af378d5c0 100755
--- a/scripts/maint/practracker/includes.py
+++ b/scripts/maint/practracker/includes.py
@@ -173,6 +173,27 @@ def remove_self_edges(graph):
for k in list(graph):
graph[k] = [ d for d in graph[k] if d != k ]
+def closure(graph):
+ """Takes a directed graph in as an adjacency mapping (a mapping from
+ node to a list of the nodes to which it connects), and completes
+ its closure.
+ """
+ graph = graph.copy()
+ changed = False
+ for k in graph.keys():
+ graph[k] = set(graph[k])
+ while True:
+ for k in graph.keys():
+ sz = len(graph[k])
+ for v in list(graph[k]):
+ graph[k].update(graph.get(v, []))
+ if sz != len(graph[k]):
+ changed = True
+
+ if not changed:
+ return graph
+ changed = False
+
def toposort(graph, limit=100):
"""Takes a directed graph in as an adjacency mapping (a mapping from
node to a list of the nodes to which it connects). Tries to
@@ -233,8 +254,25 @@ def walk_c_files(topdir="src"):
for err in consider_include_rules(fullpath, f):
yield err
+def check_subsys_file(fname, uses_dirs):
+ uses_closure = closure(uses_dirs)
+ ok = True
+ previous_subsystems = []
+ with open(fname) as f:
+ for line in f:
+ _, name, fname = line.split()
+ fname = re.sub(r'^.*/src/', "", fname)
+ fname = re.sub(r'^src/', "", fname)
+ fname = re.sub(r'/[^/]*\.c', "", fname)
+ for prev in previous_subsystems:
+ if fname in uses_closure[prev]:
+ print("INVERSION: {} uses {}".format(prev,fname))
+ ok = False
+ previous_subsystems.append(fname)
+ return not ok
+
def run_check_includes(topdir, list_unused=False, log_sorted_levels=False,
- list_advisories=False):
+ list_advisories=False, check_subsystem_order=None):
trouble = False
for err in walk_c_files(topdir):
@@ -259,6 +297,11 @@ def run_check_includes(topdir, list_unused=False, log_sorted_levels=False,
uses_dirs[rules.incpath] = rules.getAllowedDirectories()
remove_self_edges(uses_dirs)
+
+ if check_subsystem_order:
+ if check_subsys_file(check_subsystem_order, uses_dirs):
+ sys.exit(1)
+
all_levels = toposort(uses_dirs)
if log_sorted_levels:
@@ -282,6 +325,8 @@ def main(argv):
help="List unused lines in .may_include files.")
parser.add_argument("--list-advisories", action="store_true",
help="List advisories as well as forbidden includes")
+ parser.add_argument("--check-subsystem-order", action="store",
+ help="Check a list of subsystems for ordering")
parser.add_argument("topdir", default="src", nargs="?",
help="Top-level directory for the tor source")
args = parser.parse_args(argv[1:])
@@ -289,7 +334,8 @@ def main(argv):
run_check_includes(topdir=args.topdir,
log_sorted_levels=args.toposort,
list_unused=args.list_unused,
- list_advisories=args.list_advisories)
+ list_advisories=args.list_advisories,
+ check_subsystem_order=args.check_subsystem_order)
if __name__ == '__main__':
main(sys.argv)