Changeset 52849 in webkit
- Timestamp:
- Jan 5, 2010 10:37:56 PM (14 years ago)
- Location:
- trunk/WebKitTools
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/WebKitTools/ChangeLog
r52829 r52849 1 2010-01-05 Chris Jerdonek <chris.jerdonek@gmail.com> 2 3 Reviewed by David Levin. 4 5 Refactored check-webkit-style's argument parser to not rely 6 on global state, and improved its error handling and unit 7 test coverage. 8 9 https://bugs.webkit.org/show_bug.cgi?id=32966 10 11 * Scripts/check-webkit-style: 12 - Adjusted to use new argument parser. 13 14 * Scripts/webkitpy/cpp_style.py: 15 - Changed _CppStyleState to accept an array of filter rules 16 instead of a comma-delimited string. 17 - Eliminated cpp_style._DEFAULT_FILTER_RULES. 18 - Eliminated cpp_style._USAGE. 19 20 * Scripts/webkitpy/cpp_style_unittest.py: 21 - Updated test_filter() and test_default_filter(). 22 23 * Scripts/webkitpy/style.py: 24 - Converted style._USAGE to create_usage(). 25 - Corrected usage instructions by removing 0 as a valid 26 --verbose flag value. 27 - Removed use_webkit_styles(). 28 - Added ProcessorOptions class. 29 - Added ArgumentDefaults class. 30 - Added ArgumentPrinter class. 31 - Removed parse_arguments and added ArgumentParser class. 32 - Moved exit_with_usage() and exit_with_categories() into 33 ArgumentParser. 34 - Refactored parse_arguments() as ArgumentParser.parse(). 35 - Improved parser error handling. 36 37 * Scripts/webkitpy/style_unittest.py: 38 - Added DefaultArgumentsTest class. 39 - Addressed FIXME to check style.WEBKIT_FILTER_RULES 40 against style.STYLE_CATEGORIES. 41 - Added ArgumentPrinterTest class. 42 - Added ArgumentParserTest class and rewrote parser unit tests. 43 1 44 2010-01-05 Adam Roben <aroben@apple.com> 2 45 -
trunk/WebKitTools/Scripts/check-webkit-style
r52703 r52849 2 2 # 3 3 # Copyright (C) 2009 Google Inc. All rights reserved. 4 # Copyright (C) 2010 Chris Jerdonek (chris.jerdonek@gmail.com) 4 5 # 5 6 # Redistribution and use in source and binary forms, with or without … … 52 53 53 54 def main(): 54 style.use_webkit_styles()55 56 (files, flags) = style.parse_arguments(sys.argv[1:], ["git-commit="],57 display_help=True)58 59 55 # Change stderr to write with replacement characters so we don't die 60 56 # if we try to print something containing non-ASCII characters. … … 64 60 'replace') 65 61 66 if files and "--git-commit" in flags: 67 style.exit_with_usage('It is not possible to check files and a ' 68 'specific commit at the same time.', 69 display_help=True) 62 defaults = style.ArgumentDefaults(style.DEFAULT_OUTPUT_FORMAT, 63 style.DEFAULT_VERBOSITY, 64 style.WEBKIT_FILTER_RULES) 65 66 parser = style.ArgumentParser(defaults) 67 (files, options) = parser.parse(sys.argv[1:]) 68 69 # FIXME: Eliminate the need to call this function. 70 # Options should be passed into process_file instead. 71 style.set_options(options) 70 72 71 73 if files: … … 77 79 scm = detect_scm_system(cwd) 78 80 79 if "--git-commit" in flags:80 commit = flags["--git-commit"]81 if options.git_commit: 82 commit = options.git_commit 81 83 if '..' in commit: 82 84 # FIXME: If the range is a "...", the code should find the common ancestor and -
trunk/WebKitTools/Scripts/webkitpy/cpp_style.py
r52808 r52849 48 48 49 49 50 _USAGE = ''51 52 53 # The default state of the category filter. This is overrided by the --filter=54 # flag. By default all errors are on, so only add here categories that should be55 # off by default (i.e., categories that must be enabled by the --filter= flags).56 # All entries here should start with a '-' or '+', as in the --filter= flag.57 _DEFAULT_FILTER_RULES = []58 59 50 # Headers that we consider STL headers. 60 51 _STL_HEADERS = frozenset([ … … 259 250 self.error_count = 0 # global count of reported errors 260 251 # filters to apply when emitting error messages 261 self.filters = _DEFAULT_FILTER_RULES[:]252 self.filters = [] 262 253 263 254 # output format: … … 283 274 284 275 Args: 285 filters: A string of comma-separated filters (eg "+whitespace/indent"). 286 Each filter should start with + or -; else we die. 276 filters: A list of strings that are boolean filter rules used 277 to determine whether a style category should be checked. 278 Each string should start with + or -. An example 279 string is "+whitespace/indent". The list includes any 280 prepended default filter rules. 287 281 288 282 Raises: 289 ValueError: The comma-separated filters did not all start with '+' or '-'.290 E.g."-,+whitespace,-whitespace/indent,whitespace/badfilter"283 ValueError: Not all filters started with '+' or '-'. For example, 284 "-,+whitespace,-whitespace/indent,whitespace/badfilter" 291 285 """ 292 # Default filters always have less priority than the flag ones. 293 self.filters = _DEFAULT_FILTER_RULES[:] 294 for filter in filters.split(','): 286 self.filters = [] 287 for filter in filters: 295 288 clean_filter = filter.strip() 296 289 if clean_filter: … … 345 338 346 339 Args: 347 filters: A string of comma-separated filters (eg "whitespace/indent"). 348 Each filter should start with + or -; else we die. 340 filters: A list of strings that are boolean filter rules used 341 to determine whether a style category should be checked. 342 Each string should start with + or -. An example 343 string is "+whitespace/indent". The list includes any 344 prepended default filter rules. 349 345 """ 350 346 _cpp_style_state.set_filters(filters) -
trunk/WebKitTools/Scripts/webkitpy/cpp_style_unittest.py
r52808 r52849 42 42 import unittest 43 43 import cpp_style 44 # FIXME: Remove the need to import something from style. 45 from style import _STYLE_CATEGORIES 44 # FIXME: Remove the need to import something from style. See the 45 # FIXME notes near the STYLE_CATEGORIES definition for a 46 # suggestion on how to best do this. 47 from style import STYLE_CATEGORIES 46 48 47 49 # This class works as an error collector and replaces cpp_style.Error 48 50 # function for the unit tests. We also verify each category we see 49 # is in cpp_style._STYLE_CATEGORIES, to help keep that list up to date.51 # is in STYLE_CATEGORIES, to help keep that list up to date. 50 52 class ErrorCollector: 51 _all_style_categories = _STYLE_CATEGORIES53 _all_style_categories = STYLE_CATEGORIES 52 54 # This a list including all categories seen in any unit test. 53 55 _seen_style_categories = {} … … 62 64 self._assert_fn(category in self._all_style_categories, 63 65 'Message "%s" has category "%s",' 64 ' which is not in _STYLE_CATEGORIES' % (message, category))66 ' which is not in STYLE_CATEGORIES' % (message, category)) 65 67 self._seen_style_categories[category] = 1 66 68 if cpp_style._should_print_error(category, confidence): … … 1572 1574 old_filters = cpp_style._cpp_style_state.filters 1573 1575 try: 1574 cpp_style._cpp_style_state.set_filters( '-,+whitespace,-whitespace/indent')1576 cpp_style._cpp_style_state.set_filters(['-', '+whitespace', '-whitespace/indent']) 1575 1577 self.assert_lint( 1576 1578 '// Hello there ', … … 1582 1584 cpp_style._cpp_style_state.filters = old_filters 1583 1585 1584 def test_default_filter(self): 1585 default_filter_rules = cpp_style._DEFAULT_FILTER_RULES 1586 def test_filter_appending(self): 1586 1587 old_filters = cpp_style._cpp_style_state.filters 1587 cpp_style._DEFAULT_FILTER_RULES = [ '-whitespace' ]1588 1588 try: 1589 1589 # Reset filters 1590 cpp_style._cpp_style_state.set_filters( '')1590 cpp_style._cpp_style_state.set_filters(['-whitespace']) 1591 1591 self.assert_lint('// Hello there ', '') 1592 cpp_style._cpp_style_state.set_filters( '+whitespace/end_of_line')1592 cpp_style._cpp_style_state.set_filters(['-whitespace', '+whitespace/end_of_line']) 1593 1593 self.assert_lint( 1594 1594 '// Hello there ', … … 1598 1598 finally: 1599 1599 cpp_style._cpp_style_state.filters = old_filters 1600 cpp_style._DEFAULT_FILTER_RULES = default_filter_rules1601 1600 1602 1601 def test_unnamed_namespaces_in_headers(self): -
trunk/WebKitTools/Scripts/webkitpy/style.py
r52541 r52849 1 1 # Copyright (C) 2009 Google Inc. All rights reserved. 2 # Copyright (C) 2010 Chris Jerdonek (chris.jerdonek@gmail.com) 2 3 # 3 4 # Redistribution and use in source and binary forms, with or without … … 30 31 31 32 # FIXME: Move more code from cpp_style to here. 32 # check-webkit-style should not refer cpp_style directly.33 33 34 34 import getopt … … 41 41 42 42 43 # Default options44 _DEFAULT_VERBOSITY = 145 _DEFAULT_OUTPUT_FORMAT = 'emacs'43 # These defaults are used by check-webkit-style. 44 DEFAULT_VERBOSITY = 1 45 DEFAULT_OUTPUT_FORMAT = 'emacs' 46 46 47 47 … … 49 49 # For categories for which we want to have similar functionality, 50 50 # modify the implementation and enable them. 51 # FIXME: Add a unit test to ensure the corresponding categories52 # are elements of _STYLE_CATEGORIES.53 51 # 54 # For unambiguous terminology, we use "filter rule" rather than "filter" 55 # for an individual boolean filter flag like "+foo". This allows us to 56 # reserve "filter" for what one gets by collectively applying all of 57 # the filter rules as specified by a --filter flag. 58 _WEBKIT_FILTER_RULES = [ 52 # Throughout this module, we use "filter rule" rather than "filter" 53 # for an individual boolean filter flag like "+foo". This allows us to 54 # reserve "filter" for what one gets by collectively applying all of 55 # the filter rules. 56 # 57 # The _WEBKIT_FILTER_RULES are prepended to any user-specified filter 58 # rules. Since by default all errors are on, only include rules that 59 # begin with a - sign. 60 WEBKIT_FILTER_RULES = [ 59 61 '-build/endif_comment', 60 62 '-build/include_what_you_use', # <string> for std::string … … 80 82 81 83 84 # FIXME: The STYLE_CATEGORIES show up in both file types cpp_style.py 85 # and text_style.py. Break this list into possibly overlapping 86 # sub-lists, and store each sub-list in the corresponding .py 87 # file. The file style.py can obtain the master list by taking 88 # the union. This will allow the unit tests for each file type 89 # to check that all of their respective style categories are 90 # represented -- without having to reference style.py or be 91 # aware of the existence of other file types. 92 # 82 93 # We categorize each style rule we print. Here are the categories. 83 # We want an explicit list so we can list them all in cpp_style --filter=.94 # We want an explicit list so we can display a full list to the user. 84 95 # If you add a new error message with a new category, add it to the list 85 96 # here! cpp_style_unittest.py should tell you if you forget to do this. 86 _STYLE_CATEGORIES = [97 STYLE_CATEGORIES = [ 87 98 'build/class', 88 99 'build/deprecated', … … 148 159 149 160 150 _USAGE = """ 161 def _create_usage(defaults): 162 """Return the usage string to display for command help. 163 164 Args: 165 defaults: An ArgumentDefaults instance. 166 167 """ 168 usage = """ 151 169 Syntax: %(program_name)s [--verbose=#] [--git-commit=<SingleCommit>] [--output=vs7] 152 170 [--filter=-x,+y,...] [file] ... … … 172 190 173 191 verbose=# 174 A number 0-5 to restrict errors to certain verbosity levels. 175 Defaults to %(default_verbosity)s. 192 A number 1-5 that restricts output to errors with a confidence 193 score at or above this value. In particular, the value 1 displays 194 all errors. The default is %(default_verbosity)s. 176 195 177 196 git-commit=<SingleCommit> … … 205 224 the empty filter as follows: 206 225 --filter= 207 """ % { 208 'program_name': os.path.basename(sys.argv[0]), 209 'default_verbosity': _DEFAULT_VERBOSITY, 210 'default_output_format': _DEFAULT_OUTPUT_FORMAT 211 } 212 213 214 def use_webkit_styles(): 215 """Configures this module for WebKit style.""" 216 cpp_style._DEFAULT_FILTER_RULES = _WEBKIT_FILTER_RULES 217 218 219 def exit_with_usage(error_message, display_help=False): 220 """Exit and print a usage string with an optional error message. 226 """ % {'program_name': os.path.basename(sys.argv[0]), 227 'default_verbosity': defaults.verbosity, 228 'default_output_format': defaults.output_format} 229 230 return usage 231 232 233 # This class should not have knowledge of the flag key names. 234 class ProcessorOptions(object): 235 236 """A container to store options to use when checking style. 237 238 Attributes: 239 output_format: A string that is the output format. The supported 240 output formats are "emacs" which emacs can parse 241 and "vs7" which Microsoft Visual Studio 7 can parse. 242 243 verbosity: An integer 1-5 that restricts output to errors with a 244 confidence score at or above this value. 245 The default is 1, which displays all errors. 246 247 filter_rules: A list of strings that are boolean filter rules used 248 to determine whether a style category should be checked. 249 Each string should start with + or -. An example 250 string is "+whitespace/indent". The list includes any 251 prepended default filter rules. The default is the 252 empty list, which includes all categories. 253 254 git_commit: A string representing the git commit to check. 255 The default is None. 256 257 extra_flag_values: A string-string dictionary of all flag key-value 258 pairs that are not otherwise represented by this 259 class. The default is the empty dictionary. 260 """ 261 262 def __init__(self, output_format, verbosity=1, filter_rules=None, 263 git_commit=None, extra_flag_values=None): 264 if filter_rules is None: 265 filter_rules = [] 266 if extra_flag_values is None: 267 extra_flag_values = {} 268 269 self.output_format = output_format 270 self.verbosity = verbosity 271 self.filter_rules = filter_rules 272 self.git_commit = git_commit 273 self.extra_flag_values = extra_flag_values 274 275 276 # FIXME: Eliminate the need for this function. 277 # Options should be passed into process_file instead. 278 def set_options(options): 279 """Initialize global _CppStyleState instance. 280 281 This needs to be called before calling process_file. 221 282 222 283 Args: 223 error_message: The optional error message. 224 display_help: Whether to display help output. Suppressing help 225 output is useful for unit tests. 226 """ 227 if display_help: 228 sys.stderr.write(_USAGE) 229 if error_message: 230 sys.exit('\nFATAL ERROR: ' + error_message) 231 else: 232 sys.exit(1) 233 234 235 def exit_with_categories(display_help=False): 236 """Exit and print all style categories, along with the default filter. 237 238 These category names appear in error messages. They can be filtered 239 using the --filter flag. 240 241 Args: 242 display_help: Whether to display help output. Suppressing help 243 output is useful for unit tests. 244 """ 245 if display_help: 246 sys.stderr.write('\nAll categories:\n') 247 for category in sorted(_STYLE_CATEGORIES): 248 sys.stderr.write(' ' + category + '\n') 249 250 sys.stderr.write('\nDefault filter rules**:\n') 251 for filter_rule in sorted(_WEBKIT_FILTER_RULES): 252 sys.stderr.write(' ' + filter_rule + '\n') 253 sys.stderr.write('\n**The command always evaluates the above ' 254 'rules, and before any --filter flag.\n\n') 255 256 sys.exit(0) 257 258 259 def parse_arguments(args, additional_flags=[], display_help=False): 260 """Parses the command line arguments. 261 262 This may set the output format and verbosity level as side-effects. 263 264 Args: 265 args: The command line arguments: 266 additional_flags: A list of strings which specifies flags we allow. 267 display_help: Whether to display help output. Suppressing help 268 output is useful for unit tests. 269 270 Returns: 271 A tuple of (filenames, flags) 272 273 filenames: The list of filenames to lint. 274 flags: The dict of the flag names and the flag values. 275 """ 276 flags = ['help', 'output=', 'verbose=', 'filter='] + additional_flags 277 additional_flag_values = {} 278 try: 279 (opts, filenames) = getopt.getopt(args, '', flags) 280 except getopt.GetoptError: 281 exit_with_usage('Invalid arguments.', display_help) 282 283 verbosity = _DEFAULT_VERBOSITY 284 output_format = _DEFAULT_OUTPUT_FORMAT 285 filters = '' 286 287 for (opt, val) in opts: 288 if opt == '--help': 289 exit_with_usage(None, display_help) 290 elif opt == '--output': 291 if not val in ('emacs', 'vs7'): 292 exit_with_usage('The only allowed output formats are emacs and vs7.', 293 display_help) 294 output_format = val 295 elif opt == '--verbose': 296 verbosity = int(val) 297 elif opt == '--filter': 298 filters = val 299 if not filters: 300 exit_with_categories(display_help) 284 options: A ProcessorOptions instance. 285 """ 286 cpp_style._set_output_format(options.output_format) 287 cpp_style._set_verbose_level(options.verbosity) 288 cpp_style._set_filters(options.filter_rules) 289 290 291 # This class should not have knowledge of the flag key names. 292 class ArgumentDefaults(object): 293 294 """A container to store default argument values. 295 296 Attributes: 297 output_format: A string that is the default output format. 298 verbosity: An integer that is the default verbosity level. 299 filter_rules: A list of strings that are boolean filter rules 300 to prepend to any user-specified rules. 301 302 """ 303 304 def __init__(self, default_output_format, default_verbosity, 305 default_filter_rules): 306 self.output_format = default_output_format 307 self.verbosity = default_verbosity 308 self.filter_rules = default_filter_rules 309 310 311 class ArgumentPrinter(object): 312 313 """Supports the printing of check-webkit-style command arguments.""" 314 315 def _flag_pair_to_string(self, flag_key, flag_value): 316 return '--%(key)s=%(val)s' % {'key': flag_key, 'val': flag_value } 317 318 def to_flag_string(self, options): 319 """Return a flag string yielding the given ProcessorOptions instance. 320 321 This method orders the flag values alphabetically by the flag key. 322 323 Args: 324 options: A ProcessorOptions instance. 325 326 """ 327 flags = options.extra_flag_values.copy() 328 329 flags['output'] = options.output_format 330 flags['verbose'] = options.verbosity 331 if options.filter_rules: 332 flags['filter'] = ','.join(options.filter_rules) 333 if options.git_commit: 334 flags['git-commit'] = options.git_commit 335 336 flag_string = '' 337 # Alphabetizing lets us unit test this method. 338 for key in sorted(flags.keys()): 339 flag_string += self._flag_pair_to_string(key, flags[key]) + ' ' 340 341 return flag_string.strip() 342 343 344 class ArgumentParser(object): 345 346 """Supports the parsing of check-webkit-style command arguments. 347 348 Attributes: 349 defaults: An ArgumentDefaults instance. 350 create_usage: A function that accepts an ArgumentDefaults instance 351 and returns a string of usage instructions. 352 This defaults to the function used to generate the 353 usage string for check-webkit-style. 354 doc_print: A function that accepts a string parameter and that is 355 called to display help messages. This defaults to 356 sys.stderr.write(). 357 358 """ 359 360 def __init__(self, argument_defaults, create_usage=None, doc_print=None): 361 if create_usage is None: 362 create_usage = _create_usage 363 if doc_print is None: 364 doc_print = sys.stderr.write 365 366 self.defaults = argument_defaults 367 self.create_usage = create_usage 368 self.doc_print = doc_print 369 370 def _exit_with_usage(self, error_message=''): 371 """Exit and print a usage string with an optional error message. 372 373 Args: 374 error_message: A string that is an error message to print. 375 """ 376 usage = self.create_usage(self.defaults) 377 self.doc_print(usage) 378 if error_message: 379 sys.exit('\nFATAL ERROR: ' + error_message) 301 380 else: 302 additional_flag_values[opt] = val 303 304 cpp_style._set_output_format(output_format) 305 cpp_style._set_verbose_level(verbosity) 306 cpp_style._set_filters(filters) 307 308 return (filenames, additional_flag_values) 381 sys.exit(1) 382 383 def _exit_with_categories(self): 384 """Exit and print the style categories and default filter rules.""" 385 self.doc_print('\nAll categories:\n') 386 for category in sorted(STYLE_CATEGORIES): 387 self.doc_print(' ' + category + '\n') 388 389 self.doc_print('\nDefault filter rules**:\n') 390 for filter_rule in sorted(self.defaults.filter_rules): 391 self.doc_print(' ' + filter_rule + '\n') 392 self.doc_print('\n**The command always evaluates the above rules, ' 393 'and before any --filter flag.\n\n') 394 395 sys.exit(0) 396 397 def _parse_filter_flag(self, flag_value): 398 """Parse the value of the --filter flag. 399 400 These filters are applied when deciding whether to emit a given 401 error message. 402 403 Args: 404 flag_value: A string of comma-separated filter rules, for 405 example "-whitespace,+whitespace/indent". 406 407 """ 408 filters = [] 409 for uncleaned_filter in flag_value.split(','): 410 filter = uncleaned_filter.strip() 411 if not filter: 412 continue 413 filters.append(filter) 414 return filters 415 416 def parse(self, args, extra_flags=None): 417 """Parse the command line arguments to check-webkit-style. 418 419 Args: 420 args: A list of command-line arguments as returned by sys.argv[1:]. 421 extra_flags: A list of flags whose values we want to extract, but 422 are not supported by the ProcessorOptions class. 423 An example flag "new_flag=". This defaults to the 424 empty list. 425 426 Returns: 427 A tuple of (filenames, options) 428 429 filenames: The list of filenames to check. 430 options: A ProcessorOptions instance. 431 432 """ 433 if extra_flags is None: 434 extra_flags = [] 435 436 output_format = self.defaults.output_format 437 verbosity = self.defaults.verbosity 438 filter_rules = self.defaults.filter_rules 439 440 # The flags already supported by the ProcessorOptions class. 441 flags = ['help', 'output=', 'verbose=', 'filter=', 'git-commit='] 442 443 for extra_flag in extra_flags: 444 if extra_flag in flags: 445 raise ValueError('Flag \'%(extra_flag)s is duplicated ' 446 'or already supported.' % 447 {'extra_flag': extra_flag}) 448 flags.append(extra_flag) 449 450 try: 451 (opts, filenames) = getopt.getopt(args, '', flags) 452 except getopt.GetoptError: 453 # FIXME: Settle on an error handling approach: come up 454 # with a consistent guideline as to when and whether 455 # a ValueError should be raised versus calling 456 # sys.exit when needing to interrupt execution. 457 self._exit_with_usage('Invalid arguments.') 458 459 extra_flag_values = {} 460 git_commit = None 461 462 for (opt, val) in opts: 463 if opt == '--help': 464 self._exit_with_usage() 465 elif opt == '--output': 466 output_format = val 467 elif opt == '--verbose': 468 verbosity = val 469 elif opt == '--git-commit': 470 git_commit = val 471 elif opt == '--filter': 472 if not val: 473 self._exit_with_categories() 474 # Prepend the defaults. 475 filter_rules = filter_rules + self._parse_filter_flag(val) 476 else: 477 extra_flag_values[opt] = val 478 479 # Check validity of resulting values. 480 if filenames and (git_commit != None): 481 self._exit_with_usage('It is not possible to check files and a ' 482 'specific commit at the same time.') 483 484 if output_format not in ('emacs', 'vs7'): 485 raise ValueError('Invalid --output value "%s": The only ' 486 'allowed output formats are emacs and vs7.' % 487 output_format) 488 489 verbosity = int(verbosity) 490 if ((verbosity < 1) or (verbosity > 5)): 491 raise ValueError('Invalid --verbose value %s: value must ' 492 'be between 1-5.' % verbosity) 493 494 for rule in filter_rules: 495 if not (rule.startswith('+') or rule.startswith('-')): 496 raise ValueError('Invalid filter rule "%s": every rule ' 497 'rule in the --filter flag must start ' 498 'with + or -.' % rule) 499 500 options = ProcessorOptions(output_format, verbosity, filter_rules, 501 git_commit, extra_flag_values) 502 503 return (filenames, options) 309 504 310 505 -
trunk/WebKitTools/Scripts/webkitpy/style_unittest.py
r52583 r52849 5 5 # Copyright (C) 2009 Torch Mobile Inc. 6 6 # Copyright (C) 2009 Apple Inc. All rights reserved. 7 # Copyright (C) 2010 Chris Jerdonek (chris.jerdonek@gmail.com) 7 8 # 8 9 # Redistribution and use in source and binary forms, with or without … … 37 38 38 39 import style 39 # FIXME: Eliminate cpp_style dependency. 40 import cpp_style 40 41 42 class DefaultArgumentsTest(unittest.TestCase): 43 44 """Tests validity of default arguments used by check-webkit-style.""" 45 46 def test_filter_rules(self): 47 already_seen = [] 48 for rule in style.WEBKIT_FILTER_RULES: 49 # All categories are on by default, so defaults should 50 # begin with -. 51 self.assertTrue(rule.startswith('-')) 52 self.assertTrue(rule[1:] in style.STYLE_CATEGORIES) 53 self.assertFalse(rule in already_seen) 54 already_seen.append(rule) 55 56 def test_defaults(self): 57 """Check that default arguments are valid.""" 58 defaults = style.ArgumentDefaults(style.DEFAULT_OUTPUT_FORMAT, 59 style.DEFAULT_VERBOSITY, 60 style.WEBKIT_FILTER_RULES) 61 # FIXME: We should not need to call parse() to determine 62 # whether the default arguments are valid. 63 parser = style.ArgumentParser(defaults) 64 # No need to test the return value here since we test parse() 65 # on valid arguments elsewhere. 66 parser.parse([]) # arguments valid: no error or SystemExit 67 68 69 class ArgumentPrinterTest(unittest.TestCase): 70 71 """Tests the ArgumentPrinter class.""" 72 73 _printer = style.ArgumentPrinter() 74 75 def _create_options(self, output_format='emacs', verbosity=3, 76 filter_rules=[], git_commit=None, 77 extra_flag_values={}): 78 return style.ProcessorOptions(output_format, verbosity, filter_rules, 79 git_commit, extra_flag_values) 80 81 def test_to_flag_string(self): 82 options = self._create_options('vs7', 5, ['+foo', '-bar'], 'git', 83 {'a': 0, 'z': 1}) 84 self.assertEquals('--a=0 --filter=+foo,-bar --git-commit=git ' 85 '--output=vs7 --verbose=5 --z=1', 86 self._printer.to_flag_string(options)) 87 88 # This is to check that --filter and --git-commit do not 89 # show up when not user-specified. 90 options = self._create_options() 91 self.assertEquals('--output=emacs --verbose=3', 92 self._printer.to_flag_string(options)) 41 93 42 94 43 95 class ArgumentParserTest(unittest.TestCase): 44 """Tests argument parsing.""" 45 def test_parse_arguments(self): 46 old_usage = style._USAGE 47 old_style_categories = style._STYLE_CATEGORIES 48 old_webkit_filter_rules = style._WEBKIT_FILTER_RULES 49 old_output_format = cpp_style._cpp_style_state.output_format 50 old_verbose_level = cpp_style._cpp_style_state.verbose_level 51 old_filters = cpp_style._cpp_style_state.filters 52 try: 53 # Don't print usage during the tests, or filter categories 54 style._USAGE = '' 55 style._STYLE_CATEGORIES = [] 56 style._WEBKIT_FILTER_RULES = [] 57 58 self.assertRaises(SystemExit, style.parse_arguments, ['--badopt']) 59 self.assertRaises(SystemExit, style.parse_arguments, ['--help']) 60 self.assertRaises(SystemExit, style.parse_arguments, ['--filter=']) 61 # This is illegal because all filters must start with + or - 62 self.assertRaises(ValueError, style.parse_arguments, ['--filter=foo']) 63 self.assertRaises(ValueError, style.parse_arguments, 64 ['--filter=+a,b,-c']) 65 66 self.assertEquals((['foo.cpp'], {}), style.parse_arguments(['foo.cpp'])) 67 self.assertEquals(old_output_format, cpp_style._cpp_style_state.output_format) 68 self.assertEquals(old_verbose_level, cpp_style._cpp_style_state.verbose_level) 69 70 self.assertEquals(([], {}), style.parse_arguments([])) 71 self.assertEquals(([], {}), style.parse_arguments(['--v=0'])) 72 73 self.assertEquals((['foo.cpp'], {}), 74 style.parse_arguments(['--v=1', 'foo.cpp'])) 75 self.assertEquals(1, cpp_style._cpp_style_state.verbose_level) 76 self.assertEquals((['foo.h'], {}), 77 style.parse_arguments(['--v=3', 'foo.h'])) 78 self.assertEquals(3, cpp_style._cpp_style_state.verbose_level) 79 self.assertEquals((['foo.cpp'], {}), 80 style.parse_arguments(['--verbose=5', 'foo.cpp'])) 81 self.assertEquals(5, cpp_style._cpp_style_state.verbose_level) 82 self.assertRaises(ValueError, 83 style.parse_arguments, ['--v=f', 'foo.cpp']) 84 85 self.assertEquals((['foo.cpp'], {}), 86 style.parse_arguments(['--output=emacs', 'foo.cpp'])) 87 self.assertEquals('emacs', cpp_style._cpp_style_state.output_format) 88 self.assertEquals((['foo.h'], {}), 89 style.parse_arguments(['--output=vs7', 'foo.h'])) 90 self.assertEquals('vs7', cpp_style._cpp_style_state.output_format) 91 self.assertRaises(SystemExit, 92 style.parse_arguments, ['--output=blah', 'foo.cpp']) 93 94 filt = '-,+whitespace,-whitespace/indent' 95 self.assertEquals((['foo.h'], {}), 96 style.parse_arguments(['--filter='+filt, 'foo.h'])) 97 self.assertEquals(['-', '+whitespace', '-whitespace/indent'], 98 cpp_style._cpp_style_state.filters) 99 100 self.assertEquals((['foo.cpp', 'foo.h'], {}), 101 style.parse_arguments(['foo.cpp', 'foo.h'])) 102 103 self.assertEquals((['foo.cpp'], {'--foo': ''}), 104 style.parse_arguments(['--foo', 'foo.cpp'], ['foo'])) 105 self.assertEquals((['foo.cpp'], {'--foo': 'bar'}), 106 style.parse_arguments(['--foo=bar', 'foo.cpp'], ['foo='])) 107 self.assertEquals((['foo.cpp'], {}), 108 style.parse_arguments(['foo.cpp'], ['foo='])) 109 self.assertRaises(SystemExit, 110 style.parse_arguments, 111 ['--footypo=bar', 'foo.cpp'], ['foo=']) 112 finally: 113 style._USAGE = old_usage 114 style._STYLE_CATEGORIES = old_style_categories 115 style._WEBKIT_FILTER_RULES = old_webkit_filter_rules 116 cpp_style._cpp_style_state.output_format = old_output_format 117 cpp_style._cpp_style_state.verbose_level = old_verbose_level 118 cpp_style._cpp_style_state.filters = old_filters 96 97 """Test the ArgumentParser class.""" 98 99 def _parse(self): 100 """Return a default parse() function for testing.""" 101 return self._create_parser().parse 102 103 def _create_defaults(self, default_output_format='vs7', 104 default_verbosity=3, 105 default_filter_rules=['-', '+whitespace']): 106 """"Return a default ArgumentDefaults instance for testing.""" 107 return style.ArgumentDefaults(default_output_format, 108 default_verbosity, 109 default_filter_rules) 110 111 def _create_parser(self, defaults=None): 112 """"Return an ArgumentParser instance for testing.""" 113 def create_usage(_defaults): 114 """Return a usage string for testing.""" 115 return "usage" 116 117 def doc_print(message): 118 # We do not want the usage string or style categories 119 # to print during unit tests, so print nothing. 120 return 121 122 if defaults is None: 123 defaults = self._create_defaults() 124 125 return style.ArgumentParser(defaults, create_usage, doc_print) 126 127 def test_parse_documentation(self): 128 parse = self._parse() 129 130 # FIXME: Test both the printing of the usage string and the 131 # filter categories help. 132 133 # Request the usage string. 134 self.assertRaises(SystemExit, parse, ['--help']) 135 # Request default filter rules and available style categories. 136 self.assertRaises(SystemExit, parse, ['--filter=']) 137 138 def test_parse_bad_values(self): 139 parse = self._parse() 140 141 # Pass an unsupported argument. 142 self.assertRaises(SystemExit, parse, ['--bad']) 143 144 self.assertRaises(ValueError, parse, ['--verbose=bad']) 145 self.assertRaises(ValueError, parse, ['--verbose=0']) 146 self.assertRaises(ValueError, parse, ['--verbose=6']) 147 parse(['--verbose=1']) # works 148 parse(['--verbose=5']) # works 149 150 self.assertRaises(ValueError, parse, ['--output=bad']) 151 parse(['--output=vs7']) # works 152 153 # Pass a filter rule not beginning with + or -. 154 self.assertRaises(ValueError, parse, ['--filter=foo']) 155 parse(['--filter=+foo']) # works 156 # Pass files and git-commit at the same time. 157 self.assertRaises(SystemExit, parse, ['--git-commit=', 'file.txt']) 158 # Pass an extra flag already supported. 159 self.assertRaises(ValueError, parse, [], ['filter=']) 160 parse([], ['extra=']) # works 161 # Pass an extra flag with typo. 162 self.assertRaises(SystemExit, parse, ['--extratypo='], ['extra=']) 163 parse(['--extra='], ['extra=']) # works 164 self.assertRaises(ValueError, parse, [], ['extra=', 'extra=']) 165 166 167 def test_parse_default_arguments(self): 168 parse = self._parse() 169 170 (files, options) = parse([]) 171 172 self.assertEquals(files, []) 173 174 self.assertEquals(options.output_format, 'vs7') 175 self.assertEquals(options.verbosity, 3) 176 self.assertEquals(options.filter_rules, ['-', '+whitespace']) 177 self.assertEquals(options.git_commit, None) 178 179 def test_parse_explicit_arguments(self): 180 parse = self._parse() 181 182 # Pass non-default explicit values. 183 (files, options) = parse(['--output=emacs']) 184 self.assertEquals(options.output_format, 'emacs') 185 (files, options) = parse(['--verbose=4']) 186 self.assertEquals(options.verbosity, 4) 187 (files, options) = parse(['--git-commit=commit']) 188 self.assertEquals(options.git_commit, 'commit') 189 (files, options) = parse(['--filter=+foo,-bar']) 190 self.assertEquals(options.filter_rules, 191 ['-', '+whitespace', '+foo', '-bar']) 192 193 # Pass extra flag values. 194 (files, options) = parse(['--extra'], ['extra']) 195 self.assertEquals(options.extra_flag_values, {'--extra': ''}) 196 (files, options) = parse(['--extra='], ['extra=']) 197 self.assertEquals(options.extra_flag_values, {'--extra': ''}) 198 (files, options) = parse(['--extra=x'], ['extra=']) 199 self.assertEquals(options.extra_flag_values, {'--extra': 'x'}) 200 201 def test_parse_files(self): 202 parse = self._parse() 203 204 (files, options) = parse(['foo.cpp']) 205 self.assertEquals(files, ['foo.cpp']) 206 207 # Pass multiple files. 208 (files, options) = parse(['--output=emacs', 'foo.cpp', 'bar.cpp']) 209 self.assertEquals(files, ['foo.cpp', 'bar.cpp']) 119 210 120 211
Note: See TracChangeset
for help on using the changeset viewer.