blob: 375d9c42137ba238376d8cd95255019dff97f5d0 [file] [log] [blame]
Georg Brandl991f9202009-05-05 08:31:54 +00001""" Tests for the linecache module """
2
3import linecache
4import unittest
5import os.path
Robert Collins631a35c2015-08-19 12:20:37 +12006import tempfile
Robert Collinse4d35dc2015-08-20 10:48:46 +12007import tokenize
Georg Brandl991f9202009-05-05 08:31:54 +00008from test import support
9
10
11FILENAME = linecache.__file__
Robert Collins6bc2c1e2015-03-05 12:07:57 +130012NONEXISTENT_FILENAME = FILENAME + '.missing'
Georg Brandl991f9202009-05-05 08:31:54 +000013INVALID_NAME = '!@$)(!@#_1'
14EMPTY = ''
Nick Coghlanfb15aa12013-07-28 20:56:19 +100015TEST_PATH = os.path.dirname(__file__)
Benjamin Petersonbed7d042009-07-19 21:01:52 +000016MODULES = "linecache abc".split()
Georg Brandl991f9202009-05-05 08:31:54 +000017MODULE_PATH = os.path.dirname(FILENAME)
18
19SOURCE_1 = '''
20" Docstring "
21
22def function():
23 return result
24
25'''
26
27SOURCE_2 = '''
28def f():
29 return 1 + 1
30
31a = f()
32
33'''
34
Benjamin Petersonaada7b82010-05-21 21:45:06 +000035SOURCE_3 = '''
36def f():
37 return 3''' # No ending newline
38
39
Robert Collins631a35c2015-08-19 12:20:37 +120040class TempFile:
41
42 def setUp(self):
43 super().setUp()
44 with tempfile.NamedTemporaryFile(delete=False) as fp:
45 self.file_name = fp.name
46 fp.write(self.file_byte_string)
47 self.addCleanup(support.unlink, self.file_name)
48
49
50class GetLineTestsGoodData(TempFile):
51 # file_list = ['list\n', 'of\n', 'good\n', 'strings\n']
52
53 def setUp(self):
54 self.file_byte_string = ''.join(self.file_list).encode('utf-8')
55 super().setUp()
56
57 def test_getline(self):
Robert Collinse4d35dc2015-08-20 10:48:46 +120058 with tokenize.open(self.file_name) as fp:
Robert Collins631a35c2015-08-19 12:20:37 +120059 for index, line in enumerate(fp):
60 if not line.endswith('\n'):
61 line += '\n'
62
63 cached_line = linecache.getline(self.file_name, index + 1)
64 self.assertEqual(line, cached_line)
65
66 def test_getlines(self):
67 lines = linecache.getlines(self.file_name)
68 self.assertEqual(lines, self.file_list)
69
70
71class GetLineTestsBadData(TempFile):
72 # file_byte_string = b'Bad data goes here'
73
74 def test_getline(self):
75 self.assertRaises((SyntaxError, UnicodeDecodeError),
76 linecache.getline, self.file_name, 1)
77
78 def test_getlines(self):
79 self.assertRaises((SyntaxError, UnicodeDecodeError),
80 linecache.getlines, self.file_name)
81
82
83class EmptyFile(GetLineTestsGoodData, unittest.TestCase):
84 file_list = []
85
86
87class SingleEmptyLine(GetLineTestsGoodData, unittest.TestCase):
88 file_list = ['\n']
89
90
91class GoodUnicode(GetLineTestsGoodData, unittest.TestCase):
92 file_list = ['á\n', 'b\n', 'abcdef\n', 'ááááá\n']
93
94
95class BadUnicode(GetLineTestsBadData, unittest.TestCase):
96 file_byte_string = b'\x80abc'
97
98
Georg Brandl991f9202009-05-05 08:31:54 +000099class LineCacheTests(unittest.TestCase):
100
101 def test_getline(self):
102 getline = linecache.getline
103
104 # Bad values for line number should return an empty string
Ezio Melottib3aedd42010-11-20 19:04:17 +0000105 self.assertEqual(getline(FILENAME, 2**15), EMPTY)
106 self.assertEqual(getline(FILENAME, -1), EMPTY)
Georg Brandl991f9202009-05-05 08:31:54 +0000107
108 # Float values currently raise TypeError, should it?
109 self.assertRaises(TypeError, getline, FILENAME, 1.1)
110
111 # Bad filenames should return an empty string
Ezio Melottib3aedd42010-11-20 19:04:17 +0000112 self.assertEqual(getline(EMPTY, 1), EMPTY)
113 self.assertEqual(getline(INVALID_NAME, 1), EMPTY)
Georg Brandl991f9202009-05-05 08:31:54 +0000114
Georg Brandl991f9202009-05-05 08:31:54 +0000115 # Check module loading
116 for entry in MODULES:
117 filename = os.path.join(MODULE_PATH, entry) + '.py'
Brett Cannon01743682010-10-29 23:55:51 +0000118 with open(filename) as file:
119 for index, line in enumerate(file):
Ezio Melottib3aedd42010-11-20 19:04:17 +0000120 self.assertEqual(line, getline(filename, index + 1))
Georg Brandl991f9202009-05-05 08:31:54 +0000121
122 # Check that bogus data isn't returned (issue #1309567)
123 empty = linecache.getlines('a/b/c/__init__.py')
Ezio Melottib3aedd42010-11-20 19:04:17 +0000124 self.assertEqual(empty, [])
Georg Brandl991f9202009-05-05 08:31:54 +0000125
Benjamin Petersonaada7b82010-05-21 21:45:06 +0000126 def test_no_ending_newline(self):
127 self.addCleanup(support.unlink, support.TESTFN)
128 with open(support.TESTFN, "w") as fp:
129 fp.write(SOURCE_3)
130 lines = linecache.getlines(support.TESTFN)
131 self.assertEqual(lines, ["\n", "def f():\n", " return 3\n"])
132
Georg Brandl991f9202009-05-05 08:31:54 +0000133 def test_clearcache(self):
134 cached = []
Robert Collins631a35c2015-08-19 12:20:37 +1200135 for entry in MODULES:
136 filename = os.path.join(MODULE_PATH, entry) + '.py'
Georg Brandl991f9202009-05-05 08:31:54 +0000137 cached.append(filename)
138 linecache.getline(filename, 1)
139
140 # Are all files cached?
Robert Collins631a35c2015-08-19 12:20:37 +1200141 self.assertNotEqual(cached, [])
Georg Brandl991f9202009-05-05 08:31:54 +0000142 cached_empty = [fn for fn in cached if fn not in linecache.cache]
Ezio Melottib3aedd42010-11-20 19:04:17 +0000143 self.assertEqual(cached_empty, [])
Georg Brandl991f9202009-05-05 08:31:54 +0000144
145 # Can we clear the cache?
146 linecache.clearcache()
147 cached_empty = [fn for fn in cached if fn in linecache.cache]
Ezio Melottib3aedd42010-11-20 19:04:17 +0000148 self.assertEqual(cached_empty, [])
Georg Brandl991f9202009-05-05 08:31:54 +0000149
150 def test_checkcache(self):
151 getline = linecache.getline
Benjamin Petersonaada7b82010-05-21 21:45:06 +0000152 # Create a source file and cache its contents
153 source_name = support.TESTFN + '.py'
154 self.addCleanup(support.unlink, source_name)
155 with open(source_name, 'w') as source:
156 source.write(SOURCE_1)
157 getline(source_name, 1)
Georg Brandl991f9202009-05-05 08:31:54 +0000158
Benjamin Petersonaada7b82010-05-21 21:45:06 +0000159 # Keep a copy of the old contents
160 source_list = []
161 with open(source_name) as source:
162 for index, line in enumerate(source):
Ezio Melottib3aedd42010-11-20 19:04:17 +0000163 self.assertEqual(line, getline(source_name, index + 1))
Benjamin Petersonaada7b82010-05-21 21:45:06 +0000164 source_list.append(line)
Georg Brandl991f9202009-05-05 08:31:54 +0000165
Benjamin Petersonaada7b82010-05-21 21:45:06 +0000166 with open(source_name, 'w') as source:
167 source.write(SOURCE_2)
Georg Brandl991f9202009-05-05 08:31:54 +0000168
Benjamin Petersonaada7b82010-05-21 21:45:06 +0000169 # Try to update a bogus cache entry
170 linecache.checkcache('dummy')
171
172 # Check that the cache matches the old contents
173 for index, line in enumerate(source_list):
Ezio Melottib3aedd42010-11-20 19:04:17 +0000174 self.assertEqual(line, getline(source_name, index + 1))
Benjamin Petersonaada7b82010-05-21 21:45:06 +0000175
176 # Update the cache and check whether it matches the new source file
177 linecache.checkcache(source_name)
178 with open(source_name) as source:
179 for index, line in enumerate(source):
Ezio Melottib3aedd42010-11-20 19:04:17 +0000180 self.assertEqual(line, getline(source_name, index + 1))
Benjamin Petersonaada7b82010-05-21 21:45:06 +0000181 source_list.append(line)
Georg Brandl991f9202009-05-05 08:31:54 +0000182
Robert Collins6bc2c1e2015-03-05 12:07:57 +1300183 def test_lazycache_no_globals(self):
184 lines = linecache.getlines(FILENAME)
185 linecache.clearcache()
186 self.assertEqual(False, linecache.lazycache(FILENAME, None))
187 self.assertEqual(lines, linecache.getlines(FILENAME))
188
189 def test_lazycache_smoke(self):
190 lines = linecache.getlines(NONEXISTENT_FILENAME, globals())
191 linecache.clearcache()
192 self.assertEqual(
193 True, linecache.lazycache(NONEXISTENT_FILENAME, globals()))
194 self.assertEqual(1, len(linecache.cache[NONEXISTENT_FILENAME]))
Martin Panter46f50722016-05-26 05:35:26 +0000195 # Note here that we're looking up a nonexistent filename with no
Robert Collins6bc2c1e2015-03-05 12:07:57 +1300196 # globals: this would error if the lazy value wasn't resolved.
197 self.assertEqual(lines, linecache.getlines(NONEXISTENT_FILENAME))
198
199 def test_lazycache_provide_after_failed_lookup(self):
200 linecache.clearcache()
201 lines = linecache.getlines(NONEXISTENT_FILENAME, globals())
202 linecache.clearcache()
203 linecache.getlines(NONEXISTENT_FILENAME)
204 linecache.lazycache(NONEXISTENT_FILENAME, globals())
205 self.assertEqual(lines, linecache.updatecache(NONEXISTENT_FILENAME))
206
207 def test_lazycache_check(self):
208 linecache.clearcache()
209 linecache.lazycache(NONEXISTENT_FILENAME, globals())
210 linecache.checkcache()
211
212 def test_lazycache_bad_filename(self):
213 linecache.clearcache()
214 self.assertEqual(False, linecache.lazycache('', globals()))
215 self.assertEqual(False, linecache.lazycache('<foo>', globals()))
216
217 def test_lazycache_already_cached(self):
218 linecache.clearcache()
219 lines = linecache.getlines(NONEXISTENT_FILENAME, globals())
220 self.assertEqual(
221 False,
222 linecache.lazycache(NONEXISTENT_FILENAME, globals()))
223 self.assertEqual(4, len(linecache.cache[NONEXISTENT_FILENAME]))
224
Serhiy Storchakac512adc2015-04-01 16:54:05 +0300225 def test_memoryerror(self):
226 lines = linecache.getlines(FILENAME)
227 self.assertTrue(lines)
228 def raise_memoryerror(*args, **kwargs):
229 raise MemoryError
230 with support.swap_attr(linecache, 'updatecache', raise_memoryerror):
231 lines2 = linecache.getlines(FILENAME)
232 self.assertEqual(lines2, lines)
Robert Collins6bc2c1e2015-03-05 12:07:57 +1300233
Serhiy Storchakac512adc2015-04-01 16:54:05 +0300234 linecache.clearcache()
235 with support.swap_attr(linecache, 'updatecache', raise_memoryerror):
236 lines3 = linecache.getlines(FILENAME)
237 self.assertEqual(lines3, [])
238 self.assertEqual(linecache.getlines(FILENAME), lines)
239
Georg Brandl991f9202009-05-05 08:31:54 +0000240
241if __name__ == "__main__":
Serhiy Storchakac512adc2015-04-01 16:54:05 +0300242 unittest.main()