blob: 4e711c42b5ef1a1b1e3a5ca25948d08007e47853 [file] [log] [blame]
# 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 blinkpy.common.system.log_testing import LoggingTestCase
from blinkpy.style.optparser import ArgumentParser
from blinkpy.style.optparser import ArgumentPrinter
from blinkpy.style.optparser import CommandOptionValues as ProcessorOptions
from blinkpy.style.optparser import DefaultCommandOptionValues
class ArgumentPrinterTest(unittest.TestCase):
"""Tests the ArgumentPrinter class."""
_printer = ArgumentPrinter()
def _create_options(self,
output_format='emacs',
min_confidence=3,
filter_rules=None,
git_commit=None):
return ProcessorOptions(
filter_rules=filter_rules,
git_commit=git_commit,
min_confidence=min_confidence,
output_format=output_format)
def test_to_flag_string(self):
options = self._create_options('vs7', 5, ['+foo', '-bar'], 'git')
self.assertEqual(
'--filter=+foo,-bar --git-commit=git '
'--min-confidence=5 --output=vs7',
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.assertEqual('--min-confidence=3 --output=emacs',
self._printer.to_flag_string(options))
class ArgumentParserTest(LoggingTestCase):
"""Test the ArgumentParser class."""
class _MockStdErr(object):
def write(self, _):
# We do not want the usage string or style categories
# to print during unit tests, so print nothing.
return
def _parse(self, args):
"""Call a test parser.parse()."""
parser = self._create_parser()
return parser.parse(args)
def _create_defaults(self):
"""Return a DefaultCommandOptionValues instance for testing."""
return DefaultCommandOptionValues(
min_confidence=3, output_format='vs7')
def _create_parser(self):
"""Return an ArgumentParser instance for testing."""
default_options = self._create_defaults()
all_categories = ['build', 'whitespace']
mock_stderr = self._MockStdErr()
return ArgumentParser(
all_categories=all_categories,
base_filter_rules=[],
default_options=default_options,
mock_stderr=mock_stderr,
usage='test usage')
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.
with self.assertRaises(SystemExit):
parse(['--help'])
# Request default filter rules and available style categories.
with self.assertRaises(SystemExit):
parse(['--filter='])
def test_parse_bad_values(self):
parse = self._parse
# Pass an unsupported argument.
with self.assertRaises(SystemExit):
parse(['--bad'])
self.assertLog(['ERROR: no such option: --bad\n'])
with self.assertRaises(SystemExit):
parse(['--min-confidence=bad'])
self.assertLog([
'ERROR: option --min-confidence: '
"invalid integer value: 'bad'\n"
])
with self.assertRaises(SystemExit):
parse(['--min-confidence=0'])
self.assertLog([
'ERROR: option --min-confidence: invalid integer: 0: '
'value must be between 1 and 5\n'
])
with self.assertRaises(SystemExit):
parse(['--min-confidence=6'])
self.assertLog([
'ERROR: option --min-confidence: invalid integer: 6: '
'value must be between 1 and 5\n'
])
parse(['--min-confidence=1']) # works
parse(['--min-confidence=5']) # works
with self.assertRaises(SystemExit):
parse(['--output=bad'])
self.assertLog([
'ERROR: option --output-format: invalid choice: '
"'bad' (choose from 'emacs', 'vs7')\n"
])
parse(['--output=vs7']) # works
# Pass a filter rule not beginning with + or -.
with self.assertRaises(SystemExit):
parse(['--filter=build'])
self.assertLog([
'ERROR: Invalid filter rule "build": '
'every rule must start with + or -.\n'
])
parse(['--filter=+build']) # works
def test_parse_default_arguments(self):
parse = self._parse
(files, options) = parse([])
self.assertEqual(files, [])
self.assertEqual(options.filter_rules, [])
self.assertIsNone(options.git_commit)
self.assertFalse(options.diff_files)
self.assertFalse(options.is_verbose)
self.assertEqual(options.min_confidence, 3)
self.assertEqual(options.output_format, 'vs7')
def test_parse_explicit_arguments(self):
parse = self._parse
# Pass non-default explicit values.
_, options = parse(['--min-confidence=4'])
self.assertEqual(options.min_confidence, 4)
_, options = parse(['--output=emacs'])
self.assertEqual(options.output_format, 'emacs')
_, options = parse(['-g', 'commit'])
self.assertEqual(options.git_commit, 'commit')
_, options = parse(['--git-commit=commit'])
self.assertEqual(options.git_commit, 'commit')
_, options = parse(['--git-diff=commit'])
self.assertEqual(options.git_commit, 'commit')
_, options = parse(['--verbose'])
self.assertTrue(options.is_verbose)
_, options = parse(['--diff-files', 'file.txt'])
self.assertTrue(options.diff_files)
# Pass user_rules.
_, options = parse(['--filter=+build,-whitespace'])
self.assertEqual(options.filter_rules, ['+build', '-whitespace'])
# Pass spurious white space in user rules.
_, options = parse(['--filter=+build, -whitespace'])
self.assertEqual(options.filter_rules, ['+build', '-whitespace'])
def test_parse_files(self):
parse = self._parse
files, _ = parse(['foo.cpp'])
self.assertEqual(files, ['foo.cpp'])
# Pass multiple files.
files, _ = parse(['--output=emacs', 'foo.cpp', 'bar.cpp'])
self.assertEqual(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.assertEqual(options.filter_rules, [])
self.assertIsNone(options.git_commit)
self.assertFalse(options.is_verbose)
self.assertEqual(options.min_confidence, 1)
self.assertEqual(options.output_format, 'emacs')
# 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, min_confidence=0)
self.assertRaises(ValueError, ProcessorOptions, min_confidence=6)
ProcessorOptions(min_confidence=1) # works
ProcessorOptions(min_confidence=5) # works
# Check attributes.
options = ProcessorOptions(
filter_rules=['+'],
git_commit='commit',
is_verbose=True,
min_confidence=3,
output_format='vs7')
self.assertEqual(options.filter_rules, ['+'])
self.assertEqual(options.git_commit, 'commit')
self.assertTrue(options.is_verbose)
self.assertEqual(options.min_confidence, 3)
self.assertEqual(options.output_format, 'vs7')
def test_eq(self):
"""Test __eq__ equality function."""
self.assertTrue(ProcessorOptions().__eq__(ProcessorOptions()))
# Also verify that a difference in any argument causes equality to fail.
# Explicitly create a ProcessorOptions instance with all default
# values. We do this to be sure we are assuming the right default
# values in our self.assertFalse() calls below.
options = ProcessorOptions(
filter_rules=[],
git_commit=None,
is_verbose=False,
min_confidence=1,
output_format='emacs')
# Verify that we created options correctly.
self.assertTrue(options.__eq__(ProcessorOptions()))
self.assertFalse(options.__eq__(ProcessorOptions(filter_rules=['+'])))
self.assertFalse(options.__eq__(ProcessorOptions(git_commit='commit')))
self.assertFalse(options.__eq__(ProcessorOptions(is_verbose=True)))
self.assertFalse(options.__eq__(ProcessorOptions(min_confidence=2)))
self.assertFalse(options.__eq__(ProcessorOptions(output_format='vs7')))
def test_ne(self):
"""Test __ne__ inequality function."""
# 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().__ne__(ProcessorOptions()))