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() |