OLD | NEW |
(Empty) | |
| 1 #!/usr/bin/python2.4 |
| 2 # |
| 3 # Copyright 2009, Google Inc. |
| 4 # All rights reserved. |
| 5 # |
| 6 # Redistribution and use in source and binary forms, with or without |
| 7 # modification, are permitted provided that the following conditions are |
| 8 # met: |
| 9 # |
| 10 # * Redistributions of source code must retain the above copyright |
| 11 # notice, this list of conditions and the following disclaimer. |
| 12 # * Redistributions in binary form must reproduce the above |
| 13 # copyright notice, this list of conditions and the following disclaimer |
| 14 # in the documentation and/or other materials provided with the |
| 15 # distribution. |
| 16 # * Neither the name of Google Inc. nor the names of its |
| 17 # contributors may be used to endorse or promote products derived from |
| 18 # this software without specific prior written permission. |
| 19 # |
| 20 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 21 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| 22 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| 23 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| 24 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 25 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 26 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 27 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 28 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 29 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 30 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 31 |
| 32 """Unit tests for croc_scan.py.""" |
| 33 |
| 34 #import os |
| 35 import re |
| 36 #import sys |
| 37 #import StringIO |
| 38 import unittest |
| 39 import croc_scan |
| 40 |
| 41 #------------------------------------------------------------------------------ |
| 42 |
| 43 |
| 44 class TestScanner(unittest.TestCase): |
| 45 """Tests for croc_scan.Scanner.""" |
| 46 |
| 47 def testInit(self): |
| 48 """Test __init()__.""" |
| 49 s = croc_scan.Scanner() |
| 50 |
| 51 self.assertEqual(s.re_token.pattern, '#') |
| 52 self.assertEqual(s.comment_to_eol, ['#']) |
| 53 self.assertEqual(s.comment_start, None) |
| 54 self.assertEqual(s.comment_end, None) |
| 55 |
| 56 def testScanLines(self): |
| 57 """Test ScanLines().""" |
| 58 s = croc_scan.Scanner() |
| 59 # Set up imaginary language: |
| 60 # ':' = comment to EOL |
| 61 # '"' = string start/end |
| 62 # '(' = comment start |
| 63 # ')' = comment end |
| 64 s.re_token = re.compile(r'([\:\"\(\)])') |
| 65 s.comment_to_eol = [':'] |
| 66 s.comment_start = '(' |
| 67 s.comment_end = ')' |
| 68 |
| 69 # No input file = no output lines |
| 70 self.assertEqual(s.ScanLines([]), []) |
| 71 |
| 72 # Empty lines and lines with only whitespace are ignored |
| 73 self.assertEqual(s.ScanLines([ |
| 74 '', # 1 |
| 75 'line', # 2 exe |
| 76 ' \t ', # 3 |
| 77 ]), [2]) |
| 78 |
| 79 # Comments to EOL are stripped, but not inside strings |
| 80 self.assertEqual(s.ScanLines([ |
| 81 'test', # 1 exe |
| 82 ' : A comment', # 2 |
| 83 '"a : in a string"', # 3 exe |
| 84 'test2 : with comment to EOL', # 4 exe |
| 85 'foo = "a multiline string with an empty line', # 5 exe |
| 86 '', # 6 exe |
| 87 ': and a comment-to-EOL character"', # 7 exe |
| 88 ': done', # 8 |
| 89 ]), [1, 3, 4, 5, 6, 7]) |
| 90 |
| 91 # Test Comment start/stop detection |
| 92 self.assertEqual(s.ScanLines([ |
| 93 '( a comment on one line)', # 1 |
| 94 'text (with a comment)', # 2 exe |
| 95 '( a comment with a : in the middle)', # 3 |
| 96 '( a multi-line', # 4 |
| 97 ' comment)', # 5 |
| 98 'a string "with a ( in it"', # 6 exe |
| 99 'not in a multi-line comment', # 7 exe |
| 100 '(a comment with a " in it)', # 8 |
| 101 ': not in a string, so this gets stripped', # 9 |
| 102 'more text "with an uninteresting string"', # 10 exe |
| 103 ]), [2, 6, 7, 10]) |
| 104 |
| 105 # TODO: Test Scan(). Low priority, since it just wraps ScanLines(). |
| 106 |
| 107 |
| 108 class TestPythonScanner(unittest.TestCase): |
| 109 """Tests for croc_scan.PythonScanner.""" |
| 110 |
| 111 def testScanLines(self): |
| 112 """Test ScanLines().""" |
| 113 s = croc_scan.PythonScanner() |
| 114 |
| 115 # No input file = no output lines |
| 116 self.assertEqual(s.ScanLines([]), []) |
| 117 |
| 118 self.assertEqual(s.ScanLines([ |
| 119 '# a comment', # 1 |
| 120 '', # 2 |
| 121 '"""multi-line string', # 3 exe |
| 122 '# not a comment', # 4 exe |
| 123 'end of multi-line string"""', # 5 exe |
| 124 ' ', # 6 |
| 125 '"single string with #comment"', # 7 exe |
| 126 '', # 8 |
| 127 '\'\'\'multi-line string, single-quote', # 9 exe |
| 128 '# not a comment', # 10 exe |
| 129 'end of multi-line string\'\'\'', # 11 exe |
| 130 '', # 12 |
| 131 '"string with embedded \\" is handled"', # 13 exe |
| 132 '# quoted "', # 14 |
| 133 '"\\""', # 15 exe |
| 134 '# quoted backslash', # 16 |
| 135 '"\\\\"', # 17 exe |
| 136 'main()', # 18 exe |
| 137 '# end', # 19 |
| 138 ]), [3, 4, 5, 7, 9, 10, 11, 13, 15, 17, 18]) |
| 139 |
| 140 |
| 141 class TestCppScanner(unittest.TestCase): |
| 142 """Tests for croc_scan.CppScanner.""" |
| 143 |
| 144 def testScanLines(self): |
| 145 """Test ScanLines().""" |
| 146 s = croc_scan.CppScanner() |
| 147 |
| 148 # No input file = no output lines |
| 149 self.assertEqual(s.ScanLines([]), []) |
| 150 |
| 151 self.assertEqual(s.ScanLines([ |
| 152 '// a comment', # 1 |
| 153 '# a preprocessor define', # 2 |
| 154 '', # 3 |
| 155 '\'#\', \'"\'', # 4 exe |
| 156 '', # 5 |
| 157 '/* a multi-line comment', # 6 |
| 158 'with a " in it', # 7 |
| 159 '*/', # 8 |
| 160 '', # 9 |
| 161 '"a string with /* and \' in it"', # 10 exe |
| 162 '', # 11 |
| 163 '"a multi-line string\\', # 12 exe |
| 164 '// not a comment\\', # 13 exe |
| 165 'ending here"', # 14 exe |
| 166 '', # 15 |
| 167 '"string with embedded \\" is handled"', # 16 exe |
| 168 '', # 17 |
| 169 'main()', # 18 exe |
| 170 '// end', # 19 |
| 171 ]), [4, 10, 12, 13, 14, 16, 18]) |
| 172 |
| 173 |
| 174 class TestScanFile(unittest.TestCase): |
| 175 """Tests for croc_scan.ScanFile().""" |
| 176 |
| 177 class MockScanner(object): |
| 178 """Mock scanner.""" |
| 179 |
| 180 def __init__(self, language): |
| 181 """Constructor.""" |
| 182 self.language = language |
| 183 |
| 184 def Scan(self, filename): |
| 185 """Mock Scan() method.""" |
| 186 return 'scan %s %s' % (self.language, filename) |
| 187 |
| 188 def MockPythonScanner(self): |
| 189 return self.MockScanner('py') |
| 190 |
| 191 def MockCppScanner(self): |
| 192 return self.MockScanner('cpp') |
| 193 |
| 194 def setUp(self): |
| 195 """Per-test setup.""" |
| 196 # Hook scanners |
| 197 self.old_python_scanner = croc_scan.PythonScanner |
| 198 self.old_cpp_scanner = croc_scan.CppScanner |
| 199 croc_scan.PythonScanner = self.MockPythonScanner |
| 200 croc_scan.CppScanner = self.MockCppScanner |
| 201 |
| 202 def tearDown(self): |
| 203 """Per-test cleanup.""" |
| 204 croc_scan.PythonScanner = self.old_python_scanner |
| 205 croc_scan.CppScanner = self.old_cpp_scanner |
| 206 |
| 207 def testScanFile(self): |
| 208 """Test ScanFile().""" |
| 209 self.assertEqual(croc_scan.ScanFile('foo', 'python'), 'scan py foo') |
| 210 self.assertEqual(croc_scan.ScanFile('bar1', 'C'), 'scan cpp bar1') |
| 211 self.assertEqual(croc_scan.ScanFile('bar2', 'C++'), 'scan cpp bar2') |
| 212 self.assertEqual(croc_scan.ScanFile('bar3', 'ObjC'), 'scan cpp bar3') |
| 213 self.assertEqual(croc_scan.ScanFile('bar4', 'ObjC++'), 'scan cpp bar4') |
| 214 self.assertEqual(croc_scan.ScanFile('bar', 'fortran'), []) |
| 215 |
| 216 #------------------------------------------------------------------------------ |
| 217 |
| 218 if __name__ == '__main__': |
| 219 unittest.main() |
OLD | NEW |