Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(33)

Unified Diff: native_client_sdk/src/tools/quote.py

Issue 11571032: [NaCl SDK] cleanup python unittests (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « native_client_sdk/src/tools/create_nmf.py ('k') | native_client_sdk/src/tools/tests/httpd_test.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: native_client_sdk/src/tools/quote.py
diff --git a/native_client_sdk/src/tools/quote.py b/native_client_sdk/src/tools/quote.py
new file mode 100755
index 0000000000000000000000000000000000000000..aae81bf4a684fa71c55e786a30a0efb090030edf
--- /dev/null
+++ b/native_client_sdk/src/tools/quote.py
@@ -0,0 +1,190 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import optparse
+import re
+import sys
+
+
+verbose = False
+
+
+def quote(input_str, specials, escape='\\'):
+ """Returns a quoted version of |str|, where every character in the
+ iterable |specials| (usually a set or a string) and the escape
+ character |escape| is replaced by the original character preceded by
+ the escape character."""
+
+ assert len(escape) == 1
+
+ # Since escape is used in replacement pattern context, so we need to
+ # ensure that it stays a simple literal and cannot affect the \1
+ # that will follow it.
+ if escape == '\\':
+ escape = '\\\\'
+ if len(specials) > 0:
+ return re.sub(r'(' + r'|'.join(specials)+r'|'+escape + r')',
+ escape + r'\1', input_str)
+ return re.sub(r'(' + escape + r')', escape + r'\1', input_str)
+
+
+def unquote(input_str, specials, escape='\\'):
+ """Splits the input string |input_str| where special characters in
+ the input |specials| are, if not quoted by |escape|, used as
+ delimiters to split the string. The returned value is a list of
+ strings of alternating non-specials and specials used to break the
+ string. The list will always begin with a possibly empty string of
+ non-specials, but may end with either specials or non-specials."""
+
+ assert len(escape) == 1
+
+ out = []
+ cur_out = []
+ cur_special = False
+ lit_next = False
+ for c in input_str:
+ if cur_special:
+ lit_next = (c == escape)
+ if c not in specials or lit_next:
+ cur_special = False
+ out.append(''.join(cur_out))
+ if not lit_next:
+ cur_out = [c]
+ else:
+ cur_out = []
+ else:
+ cur_out.append(c)
+ else:
+ if lit_next:
+ cur_out.append(c)
+ lit_next = False
+ else:
+ lit_next = c == escape
+ if c not in specials:
+ if not lit_next:
+ cur_out.append(c)
+ else:
+ out.append(''.join(cur_out))
+ cur_out = [c]
+ cur_special = True
+ out.append(''.join(cur_out))
+ return out
+
+
+# Test code
+
+def VerboseQuote(in_string, specials, *args, **kwargs):
+ if verbose:
+ sys.stdout.write('Invoking quote(%s, %s, %s)\n' %
+ (repr(in_string), repr(specials),
+ ', '.join([repr(a) for a in args] +
+ [repr(k) + ':' + repr(v)
+ for k, v in kwargs])))
+ return quote(in_string, specials, *args, **kwargs)
+
+
+def VerboseUnquote(in_string, specials, *args, **kwargs):
+ if verbose:
+ sys.stdout.write('Invoking unquote(%s, %s, %s)\n' %
+ (repr(in_string), repr(specials),
+ ', '.join([repr(a) for a in args] +
+ [repr(k) + ':' + repr(v)
+ for k, v in kwargs])))
+ return unquote(in_string, specials, *args, **kwargs)
+
+
+def TestGeneric(fn, in_args, expected_out_obj):
+ sys.stdout.write('[ RUN ] %s(%s, %s)\n' %
+ (fn.func_name, repr(in_args), repr(expected_out_obj)))
+ actual = apply(fn, in_args)
+ if actual != expected_out_obj:
+ sys.stdout.write('[ ERROR ] expected %s, got %s\n' %
+ (str(expected_out_obj), str(actual)))
+ return 1
+ sys.stdout.write('[ OK ]\n')
+ return 0
+
+
+def TestInvertible(in_string, specials, escape='\\'):
+ sys.stdout.write('[ RUN ] TestInvertible(%s, %s, %s)\n' %
+ (repr(in_string), repr(specials), repr(escape)))
+ q = VerboseQuote(in_string, specials, escape)
+ qq = VerboseUnquote(q, specials, escape)
+ if in_string != ''.join(qq):
+ sys.stdout.write(('[ ERROR ] TestInvertible(%s, %s, %s) failed, '
+ 'expected %s, got %s\n') %
+ (repr(in_string), repr(specials), repr(escape),
+ repr(in_string), repr(''.join(qq))))
+ return 1
+ return 0
+
+
+def RunAllTests():
+ test_tuples = [[VerboseQuote,
+ ['foo, bar, baz, and quux too!', 'abc'],
+ 'foo, \\b\\ar, \\b\\az, \\and quux too!'],
+ [VerboseQuote,
+ ['when \\ appears in the input', 'a'],
+ 'when \\\\ \\appe\\ars in the input'],
+ [VerboseUnquote,
+ ['key\\:still_key:value\\:more_value', ':'],
+ ['key:still_key', ':', 'value:more_value']],
+ [VerboseUnquote,
+ ['about that sep\\ar\\ator in the beginning', 'ab'],
+ ['', 'ab', 'out th', 'a', 't separator in the ',
+ 'b', 'eginning']],
+ [VerboseUnquote,
+ ['the rain in spain fall\\s ma\\i\\nly on the plains', 'ins'],
+ ['the ra', 'in', ' ', 'in', ' ', 's', 'pa', 'in',
+ ' falls mainly o', 'n', ' the pla', 'ins']],
+ ]
+ num_errors = 0
+ for func, in_args, expected in test_tuples:
+ num_errors += TestGeneric(func, in_args, expected)
+ num_errors += TestInvertible('abcdefg', 'bc')
+ num_errors += TestInvertible('a\\bcdefg', 'bc')
+ num_errors += TestInvertible('ab\\cdefg', 'bc')
+ num_errors += TestInvertible('\\ab\\cdefg', 'abc')
+ num_errors += TestInvertible('abcde\\fg', 'efg')
+ num_errors += TestInvertible('a\\b', '')
+ return num_errors
+
+
+# Invoke this file directly for simple testing.
+
+def main(argv):
+ global verbose
+ parser = optparse.OptionParser(
+ usage='Usage: %prog [options] word...')
+ parser.add_option('-s', '--special-chars', dest='special_chars', default=':',
+ help='Special characters to quote (default is ":")')
+ parser.add_option('-q', '--quote', dest='quote', default='\\',
+ help='Quote or escape character (default is "\")')
+ parser.add_option('-t', '--run-tests', dest='tests', action='store_true',
+ help='Run built-in tests\n')
+ parser.add_option('-v', '--verbose', dest='verbose', action='store_true',
+ help='Verbose test output')
+ options, args = parser.parse_args(argv)
+
+ if options.verbose:
+ verbose = True
+
+ num_errors = 0
+ if options.tests:
+ num_errors = RunAllTests()
+ for word in args:
+ q = quote(word, options.special_chars, options.quote)
+ qq = unquote(q, options.special_chars, options.quote)
+ sys.stdout.write('quote(%s) = %s, unquote(%s) = %s\n'
+ % (word, q, q, ''.join(qq)))
+ if word != ''.join(qq):
+ num_errors += 1
+ if num_errors > 0:
+ sys.stderr.write('[ FAILED ] %d test failures\n' % num_errors)
+ return num_errors
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv[1:]))
+
« no previous file with comments | « native_client_sdk/src/tools/create_nmf.py ('k') | native_client_sdk/src/tools/tests/httpd_test.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698