| Index: tools/code_coverage/croc_scan_test.py
|
| ===================================================================
|
| --- tools/code_coverage/croc_scan_test.py (revision 0)
|
| +++ tools/code_coverage/croc_scan_test.py (revision 0)
|
| @@ -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()
|
|
|