blob: f5fb86639c90b5510af4906d73426796fee16b83 [file] [log] [blame]
#!/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:]))