diff options
Diffstat (limited to 'tools/code_coverage/croc_scan_test.py')
-rw-r--r-- | tools/code_coverage/croc_scan_test.py | 219 |
1 files changed, 219 insertions, 0 deletions
diff --git a/tools/code_coverage/croc_scan_test.py b/tools/code_coverage/croc_scan_test.py new file mode 100644 index 0000000..17fc7fa --- /dev/null +++ b/tools/code_coverage/croc_scan_test.py @@ -0,0 +1,219 @@ +#!/usr/bin/python2.4 +# +# Copyright 2009, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT +# OWNER OR 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 croc_scan.py.""" + +#import os +import re +#import sys +#import StringIO +import unittest +import croc_scan + +#------------------------------------------------------------------------------ + + +class TestScanner(unittest.TestCase): + """Tests for croc_scan.Scanner.""" + + def testInit(self): + """Test __init()__.""" + s = croc_scan.Scanner() + + self.assertEqual(s.re_token.pattern, '#') + self.assertEqual(s.comment_to_eol, ['#']) + self.assertEqual(s.comment_start, None) + self.assertEqual(s.comment_end, None) + + def testScanLines(self): + """Test ScanLines().""" + s = croc_scan.Scanner() + # Set up imaginary language: + # ':' = comment to EOL + # '"' = string start/end + # '(' = comment start + # ')' = comment end + s.re_token = re.compile(r'([\:\"\(\)])') + s.comment_to_eol = [':'] + s.comment_start = '(' + s.comment_end = ')' + + # No input file = no output lines + self.assertEqual(s.ScanLines([]), []) + + # Empty lines and lines with only whitespace are ignored + self.assertEqual(s.ScanLines([ + '', # 1 + 'line', # 2 exe + ' \t ', # 3 + ]), [2]) + + # Comments to EOL are stripped, but not inside strings + self.assertEqual(s.ScanLines([ + 'test', # 1 exe + ' : A comment', # 2 + '"a : in a string"', # 3 exe + 'test2 : with comment to EOL', # 4 exe + 'foo = "a multiline string with an empty line', # 5 exe + '', # 6 exe + ': and a comment-to-EOL character"', # 7 exe + ': done', # 8 + ]), [1, 3, 4, 5, 6, 7]) + + # Test Comment start/stop detection + self.assertEqual(s.ScanLines([ + '( a comment on one line)', # 1 + 'text (with a comment)', # 2 exe + '( a comment with a : in the middle)', # 3 + '( a multi-line', # 4 + ' comment)', # 5 + 'a string "with a ( in it"', # 6 exe + 'not in a multi-line comment', # 7 exe + '(a comment with a " in it)', # 8 + ': not in a string, so this gets stripped', # 9 + 'more text "with an uninteresting string"', # 10 exe + ]), [2, 6, 7, 10]) + + # TODO: Test Scan(). Low priority, since it just wraps ScanLines(). + + +class TestPythonScanner(unittest.TestCase): + """Tests for croc_scan.PythonScanner.""" + + def testScanLines(self): + """Test ScanLines().""" + s = croc_scan.PythonScanner() + + # No input file = no output lines + self.assertEqual(s.ScanLines([]), []) + + self.assertEqual(s.ScanLines([ + '# a comment', # 1 + '', # 2 + '"""multi-line string', # 3 exe + '# not a comment', # 4 exe + 'end of multi-line string"""', # 5 exe + ' ', # 6 + '"single string with #comment"', # 7 exe + '', # 8 + '\'\'\'multi-line string, single-quote', # 9 exe + '# not a comment', # 10 exe + 'end of multi-line string\'\'\'', # 11 exe + '', # 12 + '"string with embedded \\" is handled"', # 13 exe + '# quoted "', # 14 + '"\\""', # 15 exe + '# quoted backslash', # 16 + '"\\\\"', # 17 exe + 'main()', # 18 exe + '# end', # 19 + ]), [3, 4, 5, 7, 9, 10, 11, 13, 15, 17, 18]) + + +class TestCppScanner(unittest.TestCase): + """Tests for croc_scan.CppScanner.""" + + def testScanLines(self): + """Test ScanLines().""" + s = croc_scan.CppScanner() + + # No input file = no output lines + self.assertEqual(s.ScanLines([]), []) + + self.assertEqual(s.ScanLines([ + '// a comment', # 1 + '# a preprocessor define', # 2 + '', # 3 + '\'#\', \'"\'', # 4 exe + '', # 5 + '/* a multi-line comment', # 6 + 'with a " in it', # 7 + '*/', # 8 + '', # 9 + '"a string with /* and \' in it"', # 10 exe + '', # 11 + '"a multi-line string\\', # 12 exe + '// not a comment\\', # 13 exe + 'ending here"', # 14 exe + '', # 15 + '"string with embedded \\" is handled"', # 16 exe + '', # 17 + 'main()', # 18 exe + '// end', # 19 + ]), [4, 10, 12, 13, 14, 16, 18]) + + +class TestScanFile(unittest.TestCase): + """Tests for croc_scan.ScanFile().""" + + class MockScanner(object): + """Mock scanner.""" + + def __init__(self, language): + """Constructor.""" + self.language = language + + def Scan(self, filename): + """Mock Scan() method.""" + return 'scan %s %s' % (self.language, filename) + + def MockPythonScanner(self): + return self.MockScanner('py') + + def MockCppScanner(self): + return self.MockScanner('cpp') + + def setUp(self): + """Per-test setup.""" + # Hook scanners + self.old_python_scanner = croc_scan.PythonScanner + self.old_cpp_scanner = croc_scan.CppScanner + croc_scan.PythonScanner = self.MockPythonScanner + croc_scan.CppScanner = self.MockCppScanner + + def tearDown(self): + """Per-test cleanup.""" + croc_scan.PythonScanner = self.old_python_scanner + croc_scan.CppScanner = self.old_cpp_scanner + + def testScanFile(self): + """Test ScanFile().""" + self.assertEqual(croc_scan.ScanFile('foo', 'python'), 'scan py foo') + self.assertEqual(croc_scan.ScanFile('bar1', 'C'), 'scan cpp bar1') + self.assertEqual(croc_scan.ScanFile('bar2', 'C++'), 'scan cpp bar2') + self.assertEqual(croc_scan.ScanFile('bar3', 'ObjC'), 'scan cpp bar3') + self.assertEqual(croc_scan.ScanFile('bar4', 'ObjC++'), 'scan cpp bar4') + self.assertEqual(croc_scan.ScanFile('bar', 'fortran'), []) + +#------------------------------------------------------------------------------ + +if __name__ == '__main__': + unittest.main() |