# Copyright (C) 2010 Chris Jerdonek (cjerdonek@webkit.org) # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON # ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Unit tests for parser.py.""" import unittest from optparser import _create_usage from optparser import ArgumentParser from optparser import ArgumentPrinter from optparser import CommandOptionValues as ProcessorOptions from optparser import DefaultCommandOptionValues class CreateUsageTest(unittest.TestCase): """Tests the _create_usage() function.""" def test_create_usage(self): default_options = DefaultCommandOptionValues(output_format="vs7", verbosity=3) # Exercise the code path to make sure the function does not error out. _create_usage(default_options) class ArgumentPrinterTest(unittest.TestCase): """Tests the ArgumentPrinter class.""" _printer = ArgumentPrinter() def _create_options(self, output_format='emacs', verbosity=3, filter_rules=[], git_commit=None, extra_flag_values={}): return ProcessorOptions(extra_flag_values=extra_flag_values, filter_rules=filter_rules, git_commit=git_commit, output_format=output_format, verbosity=verbosity) def test_to_flag_string(self): options = self._create_options('vs7', 5, ['+foo', '-bar'], 'git', {'a': 0, 'z': 1}) self.assertEquals('--a=0 --filter=+foo,-bar --git-commit=git ' '--output=vs7 --verbose=5 --z=1', self._printer.to_flag_string(options)) # This is to check that --filter and --git-commit do not # show up when not user-specified. options = self._create_options() self.assertEquals('--output=emacs --verbose=3', self._printer.to_flag_string(options)) class ArgumentParserTest(unittest.TestCase): """Test the ArgumentParser class.""" def _parse(self): """Return a default parse() function for testing.""" return self._create_parser().parse def _create_defaults(self): """Return a DefaultCommandOptionValues instance for testing.""" base_filter_rules = ["-", "+whitespace"] return DefaultCommandOptionValues(output_format="vs7", verbosity=3) def _create_parser(self): """Return an ArgumentParser instance for testing.""" def stderr_write(message): # We do not want the usage string or style categories # to print during unit tests, so print nothing. return default_options = self._create_defaults() all_categories = ["build" ,"whitespace"] return ArgumentParser(all_categories=all_categories, base_filter_rules=[], default_options=default_options, stderr_write=stderr_write) def test_parse_documentation(self): parse = self._parse() # FIXME: Test both the printing of the usage string and the # filter categories help. # Request the usage string. self.assertRaises(SystemExit, parse, ['--help']) # Request default filter rules and available style categories. self.assertRaises(SystemExit, parse, ['--filter=']) def test_parse_bad_values(self): parse = self._parse() # Pass an unsupported argument. self.assertRaises(SystemExit, parse, ['--bad']) self.assertRaises(ValueError, parse, ['--verbose=bad']) self.assertRaises(ValueError, parse, ['--verbose=0']) self.assertRaises(ValueError, parse, ['--verbose=6']) parse(['--verbose=1']) # works parse(['--verbose=5']) # works self.assertRaises(ValueError, parse, ['--output=bad']) parse(['--output=vs7']) # works # Pass a filter rule not beginning with + or -. self.assertRaises(ValueError, parse, ['--filter=build']) parse(['--filter=+build']) # works # Pass files and git-commit at the same time. self.assertRaises(SystemExit, parse, ['--git-commit=', 'file.txt']) # Pass an extra flag already supported. self.assertRaises(ValueError, parse, [], ['filter=']) parse([], ['extra=']) # works # Pass an extra flag with typo. self.assertRaises(SystemExit, parse, ['--extratypo='], ['extra=']) parse(['--extra='], ['extra=']) # works self.assertRaises(ValueError, parse, [], ['extra=', 'extra=']) def test_parse_default_arguments(self): parse = self._parse() (files, options) = parse([]) self.assertEquals(files, []) self.assertEquals(options.output_format, 'vs7') self.assertEquals(options.verbosity, 3) self.assertEquals(options.filter_rules, []) self.assertEquals(options.git_commit, None) def test_parse_explicit_arguments(self): parse = self._parse() # Pass non-default explicit values. (files, options) = parse(['--output=emacs']) self.assertEquals(options.output_format, 'emacs') (files, options) = parse(['--verbose=4']) self.assertEquals(options.verbosity, 4) (files, options) = parse(['--git-commit=commit']) self.assertEquals(options.git_commit, 'commit') # Pass user_rules. (files, options) = parse(['--filter=+build,-whitespace']) self.assertEquals(options.filter_rules, ["+build", "-whitespace"]) # Pass spurious white space in user rules. (files, options) = parse(['--filter=+build, -whitespace']) self.assertEquals(options.filter_rules, ["+build", "-whitespace"]) # Pass extra flag values. (files, options) = parse(['--extra'], ['extra']) self.assertEquals(options.extra_flag_values, {'--extra': ''}) (files, options) = parse(['--extra='], ['extra=']) self.assertEquals(options.extra_flag_values, {'--extra': ''}) (files, options) = parse(['--extra=x'], ['extra=']) self.assertEquals(options.extra_flag_values, {'--extra': 'x'}) def test_parse_files(self): parse = self._parse() (files, options) = parse(['foo.cpp']) self.assertEquals(files, ['foo.cpp']) # Pass multiple files. (files, options) = parse(['--output=emacs', 'foo.cpp', 'bar.cpp']) self.assertEquals(files, ['foo.cpp', 'bar.cpp']) class CommandOptionValuesTest(unittest.TestCase): """Tests CommandOptionValues class.""" def test_init(self): """Test __init__ constructor.""" # Check default parameters. options = ProcessorOptions() self.assertEquals(options.extra_flag_values, {}) self.assertEquals(options.filter_rules, []) self.assertEquals(options.git_commit, None) self.assertEquals(options.output_format, "emacs") self.assertEquals(options.verbosity, 1) # Check argument validation. self.assertRaises(ValueError, ProcessorOptions, output_format="bad") ProcessorOptions(output_format="emacs") # No ValueError: works ProcessorOptions(output_format="vs7") # works self.assertRaises(ValueError, ProcessorOptions, verbosity=0) self.assertRaises(ValueError, ProcessorOptions, verbosity=6) ProcessorOptions(verbosity=1) # works ProcessorOptions(verbosity=5) # works # Check attributes. options = ProcessorOptions(extra_flag_values={"extra_value" : 2}, filter_rules=["+"], git_commit="commit", output_format="vs7", verbosity=3) self.assertEquals(options.extra_flag_values, {"extra_value" : 2}) self.assertEquals(options.filter_rules, ["+"]) self.assertEquals(options.git_commit, "commit") self.assertEquals(options.output_format, "vs7") self.assertEquals(options.verbosity, 3) def test_eq(self): """Test __eq__ equality function.""" # == calls __eq__. self.assertTrue(ProcessorOptions() == ProcessorOptions()) # Verify that a difference in any argument causes equality to fail. options = ProcessorOptions(extra_flag_values={"extra_value" : 1}, filter_rules=["+"], git_commit="commit", output_format="vs7", verbosity=1) self.assertFalse(options == ProcessorOptions(extra_flag_values= {"extra_value" : 2})) self.assertFalse(options == ProcessorOptions(filter_rules=["-"])) self.assertFalse(options == ProcessorOptions(git_commit="commit2")) self.assertFalse(options == ProcessorOptions(output_format="emacs")) self.assertFalse(options == ProcessorOptions(verbosity=2)) def test_ne(self): """Test __ne__ inequality function.""" # != calls __ne__. # By default, __ne__ always returns true on different objects. # Thus, just check the distinguishing case to verify that the # code defines __ne__. self.assertFalse(ProcessorOptions() != ProcessorOptions())