| #!/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 os |
| import sys |
| import unittest |
| |
| SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) |
| PARENT_DIR = os.path.dirname(SCRIPT_DIR) |
| |
| sys.path.append(PARENT_DIR) |
| |
| import quote |
| |
| verbose = False |
| |
| |
| # Wrapped versions of the functions that we're testing, so that during |
| # debugging we can more easily see what their inputs were. |
| |
| 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.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 quote.unquote(in_string, specials, *args, **kwargs) |
| |
| |
| class TestQuote(unittest.TestCase): |
| # test utilities |
| def generic_test(self, fn, in_args, expected_out_obj): |
| actual = apply(fn, in_args) |
| self.assertEqual(actual, expected_out_obj) |
| |
| def check_invertible(self, in_string, specials, escape='\\'): |
| q = VerboseQuote(in_string, specials, escape) |
| qq = VerboseUnquote(q, specials, escape) |
| self.assertEqual(''.join(qq), in_string) |
| |
| def run_test_tuples(self, test_tuples): |
| for func, in_args, expected in test_tuples: |
| self.generic_test(func, in_args, expected) |
| |
| def testQuote(self): |
| 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']] |
| self.run_test_tuples(test_tuples) |
| |
| def testUnquote(self): |
| test_tuples = [[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']], |
| ] |
| self.run_test_tuples(test_tuples) |
| |
| def testInvertible(self): |
| self.check_invertible('abcdefg', 'bc') |
| self.check_invertible('a\\bcdefg', 'bc') |
| self.check_invertible('ab\\cdefg', 'bc') |
| self.check_invertible('\\ab\\cdefg', 'abc') |
| self.check_invertible('abcde\\fg', 'efg') |
| self.check_invertible('a\\b', '') |
| |
| |
| # Invoke this file directly for simple manual testing. For running |
| # the unittests, use the -t flag. Any flags to be passed to the |
| # unittest module should be passed as after the optparse processing, |
| # e.g., "quote_test.py -t -- -v" to pass the -v flag to the unittest |
| # module. |
| |
| 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('-u', '--unquote-input', dest='unquote_input', |
| action='store_true', help='Unquote command line argument') |
| 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: |
| sys.argv = [sys.argv[0]] + args |
| unittest.main() |
| else: |
| for word in args: |
| # NB: there are inputs x for which quote(unquote(x) != x, but |
| # there should be no input x for which unquote(quote(x)) != x. |
| if options.unquote_input: |
| qq = quote.unquote(word, options.special_chars, options.quote) |
| sys.stdout.write('unquote(%s) = %s\n' |
| % (word, ''.join(qq))) |
| # There is no expected output for unquote -- this is just for |
| # manual testing, so it is okay that we do not (and cannot) |
| # update num_errors here. |
| else: |
| q = quote.quote(word, options.special_chars, options.quote) |
| qq = quote.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:])) |