1#!/usr/bin/python
2# -*- coding: utf-8; -*-
3#
4# Copyright (C) 2009 Google Inc. All rights reserved.
5# Copyright (C) 2009 Torch Mobile Inc.
6# Copyright (C) 2009 Apple Inc. All rights reserved.
7# Copyright (C) 2010 Chris Jerdonek (chris.jerdonek@gmail.com)
8#
9# Redistribution and use in source and binary forms, with or without
10# modification, are permitted provided that the following conditions are
11# met:
12#
13#    * Redistributions of source code must retain the above copyright
14# notice, this list of conditions and the following disclaimer.
15#    * Redistributions in binary form must reproduce the above
16# copyright notice, this list of conditions and the following disclaimer
17# in the documentation and/or other materials provided with the
18# distribution.
19#    * Neither the name of Google Inc. nor the names of its
20# contributors may be used to endorse or promote products derived from
21# this software without specific prior written permission.
22#
23# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
33# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35"""Unit tests for style.py."""
36
37import unittest
38
39import checker as style
40from checker import _PATH_RULES_SPECIFIER as PATH_RULES_SPECIFIER
41from checker import style_categories
42from checker import ProcessorDispatcher
43from checker import ProcessorOptions
44from checker import StyleChecker
45from filter import validate_filter_rules
46from filter import FilterConfiguration
47from processors.cpp import CppProcessor
48from processors.text import TextProcessor
49
50
51class ProcessorOptionsTest(unittest.TestCase):
52
53    """Tests ProcessorOptions class."""
54
55    def test_init(self):
56        """Test __init__ constructor."""
57        # Check default parameters.
58        options = ProcessorOptions()
59        self.assertEquals(options.extra_flag_values, {})
60        self.assertEquals(options.filter_configuration, FilterConfiguration())
61        self.assertEquals(options.git_commit, None)
62        self.assertEquals(options.max_reports_per_category, {})
63        self.assertEquals(options.output_format, "emacs")
64        self.assertEquals(options.verbosity, 1)
65
66        # Check argument validation.
67        self.assertRaises(ValueError, ProcessorOptions, output_format="bad")
68        ProcessorOptions(output_format="emacs") # No ValueError: works
69        ProcessorOptions(output_format="vs7") # works
70        self.assertRaises(ValueError, ProcessorOptions, verbosity=0)
71        self.assertRaises(ValueError, ProcessorOptions, verbosity=6)
72        ProcessorOptions(verbosity=1) # works
73        ProcessorOptions(verbosity=5) # works
74
75        # Check attributes.
76        filter_configuration = FilterConfiguration(base_rules=["+"])
77        options = ProcessorOptions(extra_flag_values={"extra_value" : 2},
78                                   filter_configuration=filter_configuration,
79                                   git_commit="commit",
80                                   max_reports_per_category={"category": 3},
81                                   output_format="vs7",
82                                   verbosity=3)
83        self.assertEquals(options.extra_flag_values, {"extra_value" : 2})
84        self.assertEquals(options.filter_configuration, filter_configuration)
85        self.assertEquals(options.git_commit, "commit")
86        self.assertEquals(options.max_reports_per_category, {"category": 3})
87        self.assertEquals(options.output_format, "vs7")
88        self.assertEquals(options.verbosity, 3)
89
90    def test_eq(self):
91        """Test __eq__ equality function."""
92        # == calls __eq__.
93        self.assertTrue(ProcessorOptions() == ProcessorOptions())
94
95        # Verify that a difference in any argument causes equality to fail.
96        filter_configuration = FilterConfiguration(base_rules=["+"])
97        options = ProcessorOptions(extra_flag_values={"extra_value" : 1},
98                                   filter_configuration=filter_configuration,
99                                   git_commit="commit",
100                                   max_reports_per_category={"category": 3},
101                                   output_format="vs7",
102                                   verbosity=1)
103        self.assertFalse(options == ProcessorOptions(extra_flag_values={"extra_value" : 2}))
104        new_config = FilterConfiguration(base_rules=["-"])
105        self.assertFalse(options ==
106                         ProcessorOptions(filter_configuration=new_config))
107        self.assertFalse(options == ProcessorOptions(git_commit="commit2"))
108        self.assertFalse(options == ProcessorOptions(max_reports_per_category=
109                                                     {"category": 2}))
110        self.assertFalse(options == ProcessorOptions(output_format="emacs"))
111        self.assertFalse(options == ProcessorOptions(verbosity=2))
112
113    def test_ne(self):
114        """Test __ne__ inequality function."""
115        # != calls __ne__.
116        # By default, __ne__ always returns true on different objects.
117        # Thus, just check the distinguishing case to verify that the
118        # code defines __ne__.
119        self.assertFalse(ProcessorOptions() != ProcessorOptions())
120
121    def test_is_reportable(self):
122        """Test is_reportable()."""
123        filter_configuration = FilterConfiguration(base_rules=["-xyz"])
124        options = ProcessorOptions(filter_configuration=filter_configuration,
125                                   verbosity=3)
126
127        # Test verbosity
128        self.assertTrue(options.is_reportable("abc", 3, "foo.h"))
129        self.assertFalse(options.is_reportable("abc", 2, "foo.h"))
130
131        # Test filter
132        self.assertTrue(options.is_reportable("xy", 3, "foo.h"))
133        self.assertFalse(options.is_reportable("xyz", 3, "foo.h"))
134
135
136class GlobalVariablesTest(unittest.TestCase):
137
138    """Tests validity of the global variables."""
139
140    def _all_categories(self):
141        return style.style_categories()
142
143    def defaults(self):
144        return style.webkit_argument_defaults()
145
146    def test_filter_rules(self):
147        defaults = self.defaults()
148        already_seen = []
149        validate_filter_rules(defaults.base_filter_rules,
150                              self._all_categories())
151        # Also do some additional checks.
152        for rule in defaults.base_filter_rules:
153            # Check no leading or trailing white space.
154            self.assertEquals(rule, rule.strip())
155            # All categories are on by default, so defaults should
156            # begin with -.
157            self.assertTrue(rule.startswith('-'))
158            # Check no rule occurs twice.
159            self.assertFalse(rule in already_seen)
160            already_seen.append(rule)
161
162    def test_defaults(self):
163        """Check that default arguments are valid."""
164        defaults = self.defaults()
165
166        # FIXME: We should not need to call parse() to determine
167        #        whether the default arguments are valid.
168        parser = style.ArgumentParser(defaults)
169        # No need to test the return value here since we test parse()
170        # on valid arguments elsewhere.
171        parser.parse([]) # arguments valid: no error or SystemExit
172
173    def test_path_rules_specifier(self):
174        all_categories = style_categories()
175        for (sub_paths, path_rules) in PATH_RULES_SPECIFIER:
176            self.assertTrue(isinstance(path_rules, tuple),
177                            "Checking: " + str(path_rules))
178            validate_filter_rules(path_rules, self._all_categories())
179
180        # Try using the path specifier (as an "end-to-end" check).
181        config = FilterConfiguration(path_specific=PATH_RULES_SPECIFIER)
182        self.assertTrue(config.should_check("xxx_any_category",
183                                            "xxx_non_matching_path"))
184        self.assertTrue(config.should_check("xxx_any_category",
185                                            "WebKitTools/WebKitAPITest/"))
186        self.assertFalse(config.should_check("build/include",
187                                             "WebKitTools/WebKitAPITest/"))
188        self.assertFalse(config.should_check("readability/naming",
189                             "WebKit/qt/tests/qwebelement/tst_qwebelement.cpp"))
190
191    def test_max_reports_per_category(self):
192        """Check that MAX_REPORTS_PER_CATEGORY is valid."""
193        all_categories = self._all_categories()
194        for category in style.MAX_REPORTS_PER_CATEGORY.iterkeys():
195            self.assertTrue(category in all_categories,
196                            'Key "%s" is not a category' % category)
197
198
199class ArgumentPrinterTest(unittest.TestCase):
200
201    """Tests the ArgumentPrinter class."""
202
203    _printer = style.ArgumentPrinter()
204
205    def _create_options(self,
206                        output_format='emacs',
207                        verbosity=3,
208                        user_rules=[],
209                        git_commit=None,
210                        extra_flag_values={}):
211        filter_configuration = FilterConfiguration(user_rules=user_rules)
212        return style.ProcessorOptions(extra_flag_values=extra_flag_values,
213                                      filter_configuration=filter_configuration,
214                                      git_commit=git_commit,
215                                      output_format=output_format,
216                                      verbosity=verbosity)
217
218    def test_to_flag_string(self):
219        options = self._create_options('vs7', 5, ['+foo', '-bar'], 'git',
220                                       {'a': 0, 'z': 1})
221        self.assertEquals('--a=0 --filter=+foo,-bar --git-commit=git '
222                          '--output=vs7 --verbose=5 --z=1',
223                          self._printer.to_flag_string(options))
224
225        # This is to check that --filter and --git-commit do not
226        # show up when not user-specified.
227        options = self._create_options()
228        self.assertEquals('--output=emacs --verbose=3',
229                          self._printer.to_flag_string(options))
230
231
232class ArgumentParserTest(unittest.TestCase):
233
234    """Test the ArgumentParser class."""
235
236    def _parse(self):
237        """Return a default parse() function for testing."""
238        return self._create_parser().parse
239
240    def _create_defaults(self, default_output_format='vs7',
241                         default_verbosity=3,
242                         default_filter_rules=['-', '+whitespace']):
243        """Return a default ArgumentDefaults instance for testing."""
244        return style.ArgumentDefaults(default_output_format,
245                                      default_verbosity,
246                                      default_filter_rules)
247
248    def _create_parser(self, defaults=None):
249        """Return an ArgumentParser instance for testing."""
250        def create_usage(_defaults):
251            """Return a usage string for testing."""
252            return "usage"
253
254        def doc_print(message):
255            # We do not want the usage string or style categories
256            # to print during unit tests, so print nothing.
257            return
258
259        if defaults is None:
260            defaults = self._create_defaults()
261
262        return style.ArgumentParser(defaults, create_usage, doc_print)
263
264    def test_parse_documentation(self):
265        parse = self._parse()
266
267        # FIXME: Test both the printing of the usage string and the
268        #        filter categories help.
269
270        # Request the usage string.
271        self.assertRaises(SystemExit, parse, ['--help'])
272        # Request default filter rules and available style categories.
273        self.assertRaises(SystemExit, parse, ['--filter='])
274
275    def test_parse_bad_values(self):
276        parse = self._parse()
277
278        # Pass an unsupported argument.
279        self.assertRaises(SystemExit, parse, ['--bad'])
280
281        self.assertRaises(ValueError, parse, ['--verbose=bad'])
282        self.assertRaises(ValueError, parse, ['--verbose=0'])
283        self.assertRaises(ValueError, parse, ['--verbose=6'])
284        parse(['--verbose=1']) # works
285        parse(['--verbose=5']) # works
286
287        self.assertRaises(ValueError, parse, ['--output=bad'])
288        parse(['--output=vs7']) # works
289
290        # Pass a filter rule not beginning with + or -.
291        self.assertRaises(ValueError, parse, ['--filter=build'])
292        parse(['--filter=+build']) # works
293        # Pass files and git-commit at the same time.
294        self.assertRaises(SystemExit, parse, ['--git-commit=', 'file.txt'])
295        # Pass an extra flag already supported.
296        self.assertRaises(ValueError, parse, [], ['filter='])
297        parse([], ['extra=']) # works
298        # Pass an extra flag with typo.
299        self.assertRaises(SystemExit, parse, ['--extratypo='], ['extra='])
300        parse(['--extra='], ['extra=']) # works
301        self.assertRaises(ValueError, parse, [], ['extra=', 'extra='])
302
303
304    def test_parse_default_arguments(self):
305        parse = self._parse()
306
307        (files, options) = parse([])
308
309        self.assertEquals(files, [])
310
311        self.assertEquals(options.output_format, 'vs7')
312        self.assertEquals(options.verbosity, 3)
313        self.assertEquals(options.filter_configuration,
314                          FilterConfiguration(base_rules=["-", "+whitespace"],
315                              path_specific=PATH_RULES_SPECIFIER))
316        self.assertEquals(options.git_commit, None)
317
318    def test_parse_explicit_arguments(self):
319        parse = self._parse()
320
321        # Pass non-default explicit values.
322        (files, options) = parse(['--output=emacs'])
323        self.assertEquals(options.output_format, 'emacs')
324        (files, options) = parse(['--verbose=4'])
325        self.assertEquals(options.verbosity, 4)
326        (files, options) = parse(['--git-commit=commit'])
327        self.assertEquals(options.git_commit, 'commit')
328
329        # Pass user_rules.
330        (files, options) = parse(['--filter=+build,-whitespace'])
331        config = options.filter_configuration
332        self.assertEquals(options.filter_configuration,
333                          FilterConfiguration(base_rules=["-", "+whitespace"],
334                              path_specific=PATH_RULES_SPECIFIER,
335                              user_rules=["+build", "-whitespace"]))
336
337        # Pass spurious white space in user rules.
338        (files, options) = parse(['--filter=+build, -whitespace'])
339        self.assertEquals(options.filter_configuration,
340                          FilterConfiguration(base_rules=["-", "+whitespace"],
341                              path_specific=PATH_RULES_SPECIFIER,
342                              user_rules=["+build", "-whitespace"]))
343
344        # Pass extra flag values.
345        (files, options) = parse(['--extra'], ['extra'])
346        self.assertEquals(options.extra_flag_values, {'--extra': ''})
347        (files, options) = parse(['--extra='], ['extra='])
348        self.assertEquals(options.extra_flag_values, {'--extra': ''})
349        (files, options) = parse(['--extra=x'], ['extra='])
350        self.assertEquals(options.extra_flag_values, {'--extra': 'x'})
351
352    def test_parse_files(self):
353        parse = self._parse()
354
355        (files, options) = parse(['foo.cpp'])
356        self.assertEquals(files, ['foo.cpp'])
357
358        # Pass multiple files.
359        (files, options) = parse(['--output=emacs', 'foo.cpp', 'bar.cpp'])
360        self.assertEquals(files, ['foo.cpp', 'bar.cpp'])
361
362
363class ProcessorDispatcherSkipTest(unittest.TestCase):
364
365    """Tests the "should skip" methods of the ProcessorDispatcher class."""
366
367    def test_should_skip_with_warning(self):
368        """Test should_skip_with_warning()."""
369        dispatcher = ProcessorDispatcher()
370
371        # Check a non-skipped file.
372        self.assertFalse(dispatcher.should_skip_with_warning("foo.txt"))
373
374        # Check skipped files.
375        paths_to_skip = [
376           "gtk2drawing.c",
377           "gtk2drawing.h",
378           "JavaScriptCore/qt/api/qscriptengine_p.h",
379           "WebCore/platform/gtk/gtk2drawing.c",
380           "WebCore/platform/gtk/gtk2drawing.h",
381           "WebKit/gtk/tests/testatk.c",
382           "WebKit/qt/Api/qwebpage.h",
383           "WebKit/qt/tests/qwebsecurityorigin/tst_qwebsecurityorigin.cpp",
384            ]
385
386        for path in paths_to_skip:
387            self.assertTrue(dispatcher.should_skip_with_warning(path),
388                            "Checking: " + path)
389
390    def test_should_skip_without_warning(self):
391        """Test should_skip_without_warning()."""
392        dispatcher = ProcessorDispatcher()
393
394        # Check a non-skipped file.
395        self.assertFalse(dispatcher.should_skip_without_warning("foo.txt"))
396
397        # Check skipped files.
398        paths_to_skip = [
399           # LayoutTests folder
400           "LayoutTests/foo.txt",
401            ]
402
403        for path in paths_to_skip:
404            self.assertTrue(dispatcher.should_skip_without_warning(path),
405                            "Checking: " + path)
406
407
408class ProcessorDispatcherDispatchTest(unittest.TestCase):
409
410    """Tests dispatch_processor() method of ProcessorDispatcher class."""
411
412    def mock_handle_style_error(self):
413        pass
414
415    def dispatch_processor(self, file_path):
416        """Call dispatch_processor() with the given file path."""
417        dispatcher = ProcessorDispatcher()
418        processor = dispatcher.dispatch_processor(file_path,
419                                                  self.mock_handle_style_error,
420                                                  verbosity=3)
421        return processor
422
423    def assert_processor_none(self, file_path):
424        """Assert that the dispatched processor is None."""
425        processor = self.dispatch_processor(file_path)
426        self.assertTrue(processor is None, 'Checking: "%s"' % file_path)
427
428    def assert_processor(self, file_path, expected_class):
429        """Assert the type of the dispatched processor."""
430        processor = self.dispatch_processor(file_path)
431        got_class = processor.__class__
432        self.assertEquals(got_class, expected_class,
433                          'For path "%(file_path)s" got %(got_class)s when '
434                          "expecting %(expected_class)s."
435                          % {"file_path": file_path,
436                             "got_class": got_class,
437                             "expected_class": expected_class})
438
439    def assert_processor_cpp(self, file_path):
440        """Assert that the dispatched processor is a CppProcessor."""
441        self.assert_processor(file_path, CppProcessor)
442
443    def assert_processor_text(self, file_path):
444        """Assert that the dispatched processor is a TextProcessor."""
445        self.assert_processor(file_path, TextProcessor)
446
447    def test_cpp_paths(self):
448        """Test paths that should be checked as C++."""
449        paths = [
450            "-",
451            "foo.c",
452            "foo.cpp",
453            "foo.h",
454            ]
455
456        for path in paths:
457            self.assert_processor_cpp(path)
458
459        # Check processor attributes on a typical input.
460        file_base = "foo"
461        file_extension = "c"
462        file_path = file_base + "." + file_extension
463        self.assert_processor_cpp(file_path)
464        processor = self.dispatch_processor(file_path)
465        self.assertEquals(processor.file_extension, file_extension)
466        self.assertEquals(processor.file_path, file_path)
467        self.assertEquals(processor.handle_style_error, self.mock_handle_style_error)
468        self.assertEquals(processor.verbosity, 3)
469        # Check "-" for good measure.
470        file_base = "-"
471        file_extension = ""
472        file_path = file_base
473        self.assert_processor_cpp(file_path)
474        processor = self.dispatch_processor(file_path)
475        self.assertEquals(processor.file_extension, file_extension)
476        self.assertEquals(processor.file_path, file_path)
477
478    def test_text_paths(self):
479        """Test paths that should be checked as text."""
480        paths = [
481           "ChangeLog",
482           "foo.css",
483           "foo.html",
484           "foo.idl",
485           "foo.js",
486           "foo.mm",
487           "foo.php",
488           "foo.pm",
489           "foo.py",
490           "foo.txt",
491           "FooChangeLog.bak",
492           "WebCore/ChangeLog",
493           "WebCore/inspector/front-end/inspector.js",
494           "WebKitTools/Scripts/check-webkit=style",
495           "WebKitTools/Scripts/modules/text_style.py",
496            ]
497
498        for path in paths:
499            self.assert_processor_text(path)
500
501        # Check processor attributes on a typical input.
502        file_base = "foo"
503        file_extension = "css"
504        file_path = file_base + "." + file_extension
505        self.assert_processor_text(file_path)
506        processor = self.dispatch_processor(file_path)
507        self.assertEquals(processor.file_path, file_path)
508        self.assertEquals(processor.handle_style_error, self.mock_handle_style_error)
509
510    def test_none_paths(self):
511        """Test paths that have no file type.."""
512        paths = [
513           "Makefile",
514           "foo.png",
515           "foo.exe",
516            ]
517
518        for path in paths:
519            self.assert_processor_none(path)
520
521
522class StyleCheckerTest(unittest.TestCase):
523
524    """Test the StyleChecker class.
525
526    Attributes:
527      error_messages: A string containing all of the warning messages
528                      written to the mock_stderr_write method of
529                      this class.
530
531    """
532
533    def _mock_stderr_write(self, message):
534        pass
535
536    def _style_checker(self, options):
537        return StyleChecker(options, self._mock_stderr_write)
538
539    def test_init(self):
540        """Test __init__ constructor."""
541        options = ProcessorOptions()
542        style_checker = self._style_checker(options)
543
544        self.assertEquals(style_checker.error_count, 0)
545        self.assertEquals(style_checker.options, options)
546
547
548class StyleCheckerCheckFileTest(unittest.TestCase):
549
550    """Test the check_file() method of the StyleChecker class.
551
552    The check_file() method calls its process_file parameter when
553    given a file that should not be skipped.
554
555    The "got_*" attributes of this class are the parameters passed
556    to process_file by calls to check_file() made by this test
557    class. These attributes allow us to check the parameter values
558    passed internally to the process_file function.
559
560    Attributes:
561      got_file_path: The file_path parameter passed by check_file()
562                     to its process_file parameter.
563      got_handle_style_error: The handle_style_error parameter passed
564                              by check_file() to its process_file
565                              parameter.
566      got_processor: The processor parameter passed by check_file() to
567                     its process_file parameter.
568      warning_messages: A string containing all of the warning messages
569                        written to the mock_stderr_write method of
570                        this class.
571
572    """
573    def setUp(self):
574        self.got_file_path = None
575        self.got_handle_style_error = None
576        self.got_processor = None
577        self.warning_messages = ""
578
579    def mock_stderr_write(self, warning_message):
580        self.warning_messages += warning_message
581
582    def mock_handle_style_error(self):
583        pass
584
585    def mock_process_file(self, processor, file_path, handle_style_error):
586        """A mock _process_file().
587
588        See the documentation for this class for more information
589        on this function.
590
591        """
592        self.got_file_path = file_path
593        self.got_handle_style_error = handle_style_error
594        self.got_processor = processor
595
596    def assert_attributes(self,
597                          expected_file_path,
598                          expected_handle_style_error,
599                          expected_processor,
600                          expected_warning_messages):
601        """Assert that the attributes of this class equal the given values."""
602        self.assertEquals(self.got_file_path, expected_file_path)
603        self.assertEquals(self.got_handle_style_error, expected_handle_style_error)
604        self.assertEquals(self.got_processor, expected_processor)
605        self.assertEquals(self.warning_messages, expected_warning_messages)
606
607    def call_check_file(self, file_path):
608        """Call the check_file() method of a test StyleChecker instance."""
609        # Confirm that the attributes are reset.
610        self.assert_attributes(None, None, None, "")
611
612        # Create a test StyleChecker instance.
613        #
614        # The verbosity attribute is the only ProcessorOptions
615        # attribute that needs to be checked in this test.
616        # This is because it is the only option is directly
617        # passed to the constructor of a style processor.
618        options = ProcessorOptions(verbosity=3)
619
620        style_checker = StyleChecker(options, self.mock_stderr_write)
621
622        style_checker.check_file(file_path,
623                                 self.mock_handle_style_error,
624                                 self.mock_process_file)
625
626    def test_check_file_on_skip_without_warning(self):
627        """Test check_file() for a skipped-without-warning file."""
628
629        file_path = "LayoutTests/foo.txt"
630
631        dispatcher = ProcessorDispatcher()
632        # Confirm that the input file is truly a skipped-without-warning file.
633        self.assertTrue(dispatcher.should_skip_without_warning(file_path))
634
635        # Check the outcome.
636        self.call_check_file(file_path)
637        self.assert_attributes(None, None, None, "")
638
639    def test_check_file_on_skip_with_warning(self):
640        """Test check_file() for a skipped-with-warning file."""
641
642        file_path = "gtk2drawing.c"
643
644        dispatcher = ProcessorDispatcher()
645        # Check that the input file is truly a skipped-with-warning file.
646        self.assertTrue(dispatcher.should_skip_with_warning(file_path))
647
648        # Check the outcome.
649        self.call_check_file(file_path)
650        self.assert_attributes(None, None, None,
651                               'Ignoring "gtk2drawing.c": this file is exempt from the style guide.\n')
652
653    def test_check_file_on_non_skipped(self):
654
655        # We use a C++ file since by using a CppProcessor, we can check
656        # that all of the possible information is getting passed to
657        # process_file (in particular, the verbosity).
658        file_base = "foo"
659        file_extension = "cpp"
660        file_path = file_base + "." + file_extension
661
662        dispatcher = ProcessorDispatcher()
663        # Check that the input file is truly a C++ file.
664        self.assertEquals(dispatcher._file_type(file_path), style.FileType.CPP)
665
666        # Check the outcome.
667        self.call_check_file(file_path)
668
669        expected_processor = CppProcessor(file_path, file_extension, self.mock_handle_style_error, 3)
670
671        self.assert_attributes(file_path,
672                               self.mock_handle_style_error,
673                               expected_processor,
674                               "")
675
676
677if __name__ == '__main__':
678    import sys
679
680    unittest.main()
681
682