|
1 # Copyright (C) 2010 Chris Jerdonek (cjerdonek@webkit.org) |
|
2 # |
|
3 # Redistribution and use in source and binary forms, with or without |
|
4 # modification, are permitted provided that the following conditions |
|
5 # are met: |
|
6 # 1. Redistributions of source code must retain the above copyright |
|
7 # notice, this list of conditions and the following disclaimer. |
|
8 # 2. Redistributions in binary form must reproduce the above copyright |
|
9 # notice, this list of conditions and the following disclaimer in the |
|
10 # documentation and/or other materials provided with the distribution. |
|
11 # |
|
12 # THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY |
|
13 # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
|
14 # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
|
15 # DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY |
|
16 # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
|
17 # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
|
18 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON |
|
19 # ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
|
20 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
|
21 # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|
22 |
|
23 """Unit tests for parser.py.""" |
|
24 |
|
25 import unittest |
|
26 |
|
27 from webkitpy.common.system.logtesting import LoggingTestCase |
|
28 from webkitpy.style.optparser import ArgumentParser |
|
29 from webkitpy.style.optparser import ArgumentPrinter |
|
30 from webkitpy.style.optparser import CommandOptionValues as ProcessorOptions |
|
31 from webkitpy.style.optparser import DefaultCommandOptionValues |
|
32 |
|
33 |
|
34 class ArgumentPrinterTest(unittest.TestCase): |
|
35 |
|
36 """Tests the ArgumentPrinter class.""" |
|
37 |
|
38 _printer = ArgumentPrinter() |
|
39 |
|
40 def _create_options(self, |
|
41 output_format='emacs', |
|
42 min_confidence=3, |
|
43 filter_rules=[], |
|
44 git_commit=None): |
|
45 return ProcessorOptions(filter_rules=filter_rules, |
|
46 git_commit=git_commit, |
|
47 min_confidence=min_confidence, |
|
48 output_format=output_format) |
|
49 |
|
50 def test_to_flag_string(self): |
|
51 options = self._create_options('vs7', 5, ['+foo', '-bar'], 'git') |
|
52 self.assertEquals('--filter=+foo,-bar --git-commit=git ' |
|
53 '--min-confidence=5 --output=vs7', |
|
54 self._printer.to_flag_string(options)) |
|
55 |
|
56 # This is to check that --filter and --git-commit do not |
|
57 # show up when not user-specified. |
|
58 options = self._create_options() |
|
59 self.assertEquals('--min-confidence=3 --output=emacs', |
|
60 self._printer.to_flag_string(options)) |
|
61 |
|
62 |
|
63 class ArgumentParserTest(LoggingTestCase): |
|
64 |
|
65 """Test the ArgumentParser class.""" |
|
66 |
|
67 class _MockStdErr(object): |
|
68 |
|
69 def write(self, message): |
|
70 # We do not want the usage string or style categories |
|
71 # to print during unit tests, so print nothing. |
|
72 return |
|
73 |
|
74 def _parse(self, args): |
|
75 """Call a test parser.parse().""" |
|
76 parser = self._create_parser() |
|
77 return parser.parse(args) |
|
78 |
|
79 def _create_defaults(self): |
|
80 """Return a DefaultCommandOptionValues instance for testing.""" |
|
81 base_filter_rules = ["-", "+whitespace"] |
|
82 return DefaultCommandOptionValues(min_confidence=3, |
|
83 output_format="vs7") |
|
84 |
|
85 def _create_parser(self): |
|
86 """Return an ArgumentParser instance for testing.""" |
|
87 default_options = self._create_defaults() |
|
88 |
|
89 all_categories = ["build" ,"whitespace"] |
|
90 |
|
91 mock_stderr = self._MockStdErr() |
|
92 |
|
93 return ArgumentParser(all_categories=all_categories, |
|
94 base_filter_rules=[], |
|
95 default_options=default_options, |
|
96 mock_stderr=mock_stderr, |
|
97 usage="test usage") |
|
98 |
|
99 def test_parse_documentation(self): |
|
100 parse = self._parse |
|
101 |
|
102 # FIXME: Test both the printing of the usage string and the |
|
103 # filter categories help. |
|
104 |
|
105 # Request the usage string. |
|
106 self.assertRaises(SystemExit, parse, ['--help']) |
|
107 # Request default filter rules and available style categories. |
|
108 self.assertRaises(SystemExit, parse, ['--filter=']) |
|
109 |
|
110 def test_parse_bad_values(self): |
|
111 parse = self._parse |
|
112 |
|
113 # Pass an unsupported argument. |
|
114 self.assertRaises(SystemExit, parse, ['--bad']) |
|
115 self.assertLog(['ERROR: no such option: --bad\n']) |
|
116 |
|
117 self.assertRaises(SystemExit, parse, ['--min-confidence=bad']) |
|
118 self.assertLog(['ERROR: option --min-confidence: ' |
|
119 "invalid integer value: 'bad'\n"]) |
|
120 self.assertRaises(SystemExit, parse, ['--min-confidence=0']) |
|
121 self.assertLog(['ERROR: option --min-confidence: invalid integer: 0: ' |
|
122 'value must be between 1 and 5\n']) |
|
123 self.assertRaises(SystemExit, parse, ['--min-confidence=6']) |
|
124 self.assertLog(['ERROR: option --min-confidence: invalid integer: 6: ' |
|
125 'value must be between 1 and 5\n']) |
|
126 parse(['--min-confidence=1']) # works |
|
127 parse(['--min-confidence=5']) # works |
|
128 |
|
129 self.assertRaises(SystemExit, parse, ['--output=bad']) |
|
130 self.assertLog(['ERROR: option --output-format: invalid choice: ' |
|
131 "'bad' (choose from 'emacs', 'vs7')\n"]) |
|
132 parse(['--output=vs7']) # works |
|
133 |
|
134 # Pass a filter rule not beginning with + or -. |
|
135 self.assertRaises(SystemExit, parse, ['--filter=build']) |
|
136 self.assertLog(['ERROR: Invalid filter rule "build": ' |
|
137 'every rule must start with + or -.\n']) |
|
138 parse(['--filter=+build']) # works |
|
139 # Pass files and git-commit at the same time. |
|
140 self.assertRaises(SystemExit, parse, ['--git-commit=committish', |
|
141 'file.txt']) |
|
142 self.assertLog(['ERROR: You cannot provide both paths and ' |
|
143 'a git commit at the same time.\n']) |
|
144 |
|
145 def test_parse_default_arguments(self): |
|
146 parse = self._parse |
|
147 |
|
148 (files, options) = parse([]) |
|
149 |
|
150 self.assertEquals(files, []) |
|
151 |
|
152 self.assertEquals(options.filter_rules, []) |
|
153 self.assertEquals(options.git_commit, None) |
|
154 self.assertEquals(options.is_verbose, False) |
|
155 self.assertEquals(options.min_confidence, 3) |
|
156 self.assertEquals(options.output_format, 'vs7') |
|
157 |
|
158 def test_parse_explicit_arguments(self): |
|
159 parse = self._parse |
|
160 |
|
161 # Pass non-default explicit values. |
|
162 (files, options) = parse(['--min-confidence=4']) |
|
163 self.assertEquals(options.min_confidence, 4) |
|
164 (files, options) = parse(['--output=emacs']) |
|
165 self.assertEquals(options.output_format, 'emacs') |
|
166 (files, options) = parse(['-g', 'commit']) |
|
167 self.assertEquals(options.git_commit, 'commit') |
|
168 (files, options) = parse(['--git-commit=commit']) |
|
169 self.assertEquals(options.git_commit, 'commit') |
|
170 (files, options) = parse(['--git-diff=commit']) |
|
171 self.assertEquals(options.git_commit, 'commit') |
|
172 (files, options) = parse(['--verbose']) |
|
173 self.assertEquals(options.is_verbose, True) |
|
174 |
|
175 # Pass user_rules. |
|
176 (files, options) = parse(['--filter=+build,-whitespace']) |
|
177 self.assertEquals(options.filter_rules, |
|
178 ["+build", "-whitespace"]) |
|
179 |
|
180 # Pass spurious white space in user rules. |
|
181 (files, options) = parse(['--filter=+build, -whitespace']) |
|
182 self.assertEquals(options.filter_rules, |
|
183 ["+build", "-whitespace"]) |
|
184 |
|
185 def test_parse_files(self): |
|
186 parse = self._parse |
|
187 |
|
188 (files, options) = parse(['foo.cpp']) |
|
189 self.assertEquals(files, ['foo.cpp']) |
|
190 |
|
191 # Pass multiple files. |
|
192 (files, options) = parse(['--output=emacs', 'foo.cpp', 'bar.cpp']) |
|
193 self.assertEquals(files, ['foo.cpp', 'bar.cpp']) |
|
194 |
|
195 |
|
196 class CommandOptionValuesTest(unittest.TestCase): |
|
197 |
|
198 """Tests CommandOptionValues class.""" |
|
199 |
|
200 def test_init(self): |
|
201 """Test __init__ constructor.""" |
|
202 # Check default parameters. |
|
203 options = ProcessorOptions() |
|
204 self.assertEquals(options.filter_rules, []) |
|
205 self.assertEquals(options.git_commit, None) |
|
206 self.assertEquals(options.is_verbose, False) |
|
207 self.assertEquals(options.min_confidence, 1) |
|
208 self.assertEquals(options.output_format, "emacs") |
|
209 |
|
210 # Check argument validation. |
|
211 self.assertRaises(ValueError, ProcessorOptions, output_format="bad") |
|
212 ProcessorOptions(output_format="emacs") # No ValueError: works |
|
213 ProcessorOptions(output_format="vs7") # works |
|
214 self.assertRaises(ValueError, ProcessorOptions, min_confidence=0) |
|
215 self.assertRaises(ValueError, ProcessorOptions, min_confidence=6) |
|
216 ProcessorOptions(min_confidence=1) # works |
|
217 ProcessorOptions(min_confidence=5) # works |
|
218 |
|
219 # Check attributes. |
|
220 options = ProcessorOptions(filter_rules=["+"], |
|
221 git_commit="commit", |
|
222 is_verbose=True, |
|
223 min_confidence=3, |
|
224 output_format="vs7") |
|
225 self.assertEquals(options.filter_rules, ["+"]) |
|
226 self.assertEquals(options.git_commit, "commit") |
|
227 self.assertEquals(options.is_verbose, True) |
|
228 self.assertEquals(options.min_confidence, 3) |
|
229 self.assertEquals(options.output_format, "vs7") |
|
230 |
|
231 def test_eq(self): |
|
232 """Test __eq__ equality function.""" |
|
233 self.assertTrue(ProcessorOptions().__eq__(ProcessorOptions())) |
|
234 |
|
235 # Also verify that a difference in any argument causes equality to fail. |
|
236 |
|
237 # Explicitly create a ProcessorOptions instance with all default |
|
238 # values. We do this to be sure we are assuming the right default |
|
239 # values in our self.assertFalse() calls below. |
|
240 options = ProcessorOptions(filter_rules=[], |
|
241 git_commit=None, |
|
242 is_verbose=False, |
|
243 min_confidence=1, |
|
244 output_format="emacs") |
|
245 # Verify that we created options correctly. |
|
246 self.assertTrue(options.__eq__(ProcessorOptions())) |
|
247 |
|
248 self.assertFalse(options.__eq__(ProcessorOptions(filter_rules=["+"]))) |
|
249 self.assertFalse(options.__eq__(ProcessorOptions(git_commit="commit"))) |
|
250 self.assertFalse(options.__eq__(ProcessorOptions(is_verbose=True))) |
|
251 self.assertFalse(options.__eq__(ProcessorOptions(min_confidence=2))) |
|
252 self.assertFalse(options.__eq__(ProcessorOptions(output_format="vs7"))) |
|
253 |
|
254 def test_ne(self): |
|
255 """Test __ne__ inequality function.""" |
|
256 # By default, __ne__ always returns true on different objects. |
|
257 # Thus, just check the distinguishing case to verify that the |
|
258 # code defines __ne__. |
|
259 self.assertFalse(ProcessorOptions().__ne__(ProcessorOptions())) |
|
260 |