[tor-commits] [tor/master] Use Doctests to test the behavior of annotate_ifdef_directives.

asn at torproject.org asn at torproject.org
Mon Sep 30 10:45:36 UTC 2019


commit 6f0e697e4155ca567ddfd46a7f4e7c013287c42a
Author: Nick Mathewson <nickm at torproject.org>
Date:   Thu Sep 26 10:03:28 2019 -0400

    Use Doctests to test the behavior of annotate_ifdef_directives.
---
 scripts/maint/annotate_ifdef_directives | 115 ++++++++++++++++++++++++++------
 1 file changed, 94 insertions(+), 21 deletions(-)

diff --git a/scripts/maint/annotate_ifdef_directives b/scripts/maint/annotate_ifdef_directives
index f88dd4fdf..514b5e58b 100755
--- a/scripts/maint/annotate_ifdef_directives
+++ b/scripts/maint/annotate_ifdef_directives
@@ -2,24 +2,60 @@
 # Copyright (c) 2017-2019, The Tor Project, Inc.
 # See LICENSE for licensing information
 
-# This script iterates over a list of C files. For each file, it looks at the
-# #if/#else C macros, and annotates them with comments explaining what they
-# match.
-#
-# For example, it replaces this:
-#
-#  #ifdef HAVE_OCELOT
-#   // 500 lines of ocelot code
-#  #endif
-#
-# with this:
-#
-#  #ifdef HAVE_OCELOT
-#   // 500 lines of ocelot code
-#  #endif /* defined(HAVE_OCELOT) */
-#
-# Note that only #else and #endif lines are annotated.  Existing comments
-# on those lines are removed.
+r"""
+This script iterates over a list of C files. For each file, it looks at the
+#if/#else C macros, and annotates them with comments explaining what they
+match.
+
+For example, it replaces this kind of input...
+
+>>> INPUT = '''
+... #ifdef HAVE_OCELOT
+...   C code here
+... #if MIMSY == BOROGROVE
+...   block 1
+...   block 1
+...   block 1
+...   block 1
+... #else
+...   block 2
+...   block 2
+...   block 2
+...   block 2
+... #endif
+... #endif
+... '''
+
+With this kind of output:
+>>> EXPECTED_OUTPUT = '''
+... #ifdef HAVE_OCELOT
+...   C code here
+... #if MIMSY == BOROGROVE
+...   block 1
+...   block 1
+...   block 1
+...   block 1
+... #else /* !(MIMSY == BOROGROVE) */
+...   block 2
+...   block 2
+...   block 2
+...   block 2
+... #endif /* MIMSY == BOROGROVE */
+... #endif /* defined(HAVE_OCELOT) */
+... '''
+
+Here's how to use it:
+>>> import sys
+>>> if sys.version_info.major < 3: from cStringIO import StringIO
+>>> if sys.version_info.major >= 3: from io import StringIO
+
+>>> OUTPUT = StringIO()
+>>> translate(StringIO(INPUT), OUTPUT)
+>>> assert OUTPUT.getvalue() == EXPECTED_OUTPUT
+
+Note that only #else and #endif lines are annotated.  Existing comments
+on those lines are removed.
+"""
 
 import re
 
@@ -38,6 +74,17 @@ class Problem(Exception):
 def close_parens_needed(expr):
     """Return the number of left-parentheses needed to make 'expr'
        balanced.
+
+    >>> close_parens_needed("1+2")
+    0
+    >>> close_parens_needed("(1 + 2)")
+    0
+    >>> close_parens_needed("(1 + 2")
+    1
+    >>> close_parens_needed("(1 + (2 *")
+    2
+    >>> close_parens_needed("(1 + (2 * 3) + (4")
+    2
     """
     return expr.count("(") - expr.count(")")
 
@@ -47,6 +94,17 @@ def truncate_expression(expr, new_width):
        characters long.
 
        Try to return an expression with balanced parentheses.
+
+    >>> truncate_expression("1+2+3", 8)
+    '1+2+3'
+    >>> truncate_expression("1+2+3+4+5", 8)
+    '1+2+3...'
+    >>> truncate_expression("(1+2+3+4)", 8)
+    '(1+2...)'
+    >>> truncate_expression("(1+(2+3+4))", 8)
+    '(1+...)'
+    >>> truncate_expression("(((((((((", 8)
+    '((...))'
     """
     if len(expr) <= new_width:
         # The expression is already short enough.
@@ -69,14 +127,23 @@ def truncate_expression(expr, new_width):
     return ellipsis
 
 def commented_line(fmt, argument, maxwidth=LINE_WIDTH):
-
-    """
+    # (This is a raw docstring so that our doctests can use \.)
+    r"""
     Return fmt%argument, for use as a commented line.  If the line would
-    be longer than maxwidth, truncate argument.
+    be longer than maxwidth, truncate argument but try to keep its
+    parentheses balanced.
 
     Requires that fmt%"..." will fit into maxwidth characters.
 
     Requires that fmt ends with a newline.
+
+    >>> commented_line("/* %s */\n", "hello world", 32)
+    '/* hello world */\n'
+    >>> commented_line("/* %s */\n", "hello world", 15)
+    '/* hello... */\n'
+    >>> commented_line("#endif /* %s */\n", "((1+2) && defined(FOO))", 32)
+    '#endif /* ((1+2) && defi...) */\n'
+
     """
     assert fmt.endswith("\n")
     result = fmt % argument
@@ -208,6 +275,12 @@ def translate(f_in, f_out):
         raise Problem("Missing #endif")
 
 import sys,os
+
+if sys.argv[1] == "--self-test":
+    import doctest
+    doctest.testmod()
+    sys.exit(0)
+
 for fn in sys.argv[1:]:
     with open(fn+"_OUT", 'w') as output_file:
         translate(open(fn, 'r'), output_file)





More information about the tor-commits mailing list