blob: 59e00da242ad63c896be21d22cd58fb058ca0e3d [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
Hai Shia089d212020-07-06 17:15:08 +08009from test.support import os_helper
Georg Brandl991f9202009-05-05 08:31:54 +000010
11
12FILENAME = linecache.__file__
Robert Collins6bc2c1e2015-03-05 12:07:57 +130013NONEXISTENT_FILENAME = FILENAME + '.missing'
Georg Brandl991f9202009-05-05 08:31:54 +000014INVALID_NAME = '!@$)(!@#_1'
15EMPTY = ''
Nick Coghlanfb15aa12013-07-28 20:56:19 +100016TEST_PATH = os.path.dirname(__file__)
Benjamin Petersonbed7d042009-07-19 21:01:52 +000017MODULES = "linecache abc".split()
Georg Brandl991f9202009-05-05 08:31:54 +000018MODULE_PATH = os.path.dirname(FILENAME)
19
20SOURCE_1 = '''
21" Docstring "
22
23def function():
24 return result
25
26'''
27
28SOURCE_2 = '''
29def f():
30 return 1 + 1
31
32a = f()
33
34'''
35
Benjamin Petersonaada7b82010-05-21 21:45:06 +000036SOURCE_3 = '''
37def f():
38 return 3''' # No ending newline
39
40
Robert Collins631a35c2015-08-19 12:20:37 +120041class TempFile:
42
43 def setUp(self):
44 super().setUp()
45 with tempfile.NamedTemporaryFile(delete=False) as fp:
46 self.file_name = fp.name
47 fp.write(self.file_byte_string)
Hai Shia089d212020-07-06 17:15:08 +080048 self.addCleanup(os_helper.unlink, self.file_name)
Robert Collins631a35c2015-08-19 12:20:37 +120049
50
51class GetLineTestsGoodData(TempFile):
52 # file_list = ['list\n', 'of\n', 'good\n', 'strings\n']
53
54 def setUp(self):
55 self.file_byte_string = ''.join(self.file_list).encode('utf-8')
56 super().setUp()
57
58 def test_getline(self):
Robert Collinse4d35dc2015-08-20 10:48:46 +120059 with tokenize.open(self.file_name) as fp:
Robert Collins631a35c2015-08-19 12:20:37 +120060 for index, line in enumerate(fp):
61 if not line.endswith('\n'):
62 line += '\n'
63
64 cached_line = linecache.getline(self.file_name, index + 1)
65 self.assertEqual(line, cached_line)
66
67 def test_getlines(self):
68 lines = linecache.getlines(self.file_name)
69 self.assertEqual(lines, self.file_list)
70
71
72class GetLineTestsBadData(TempFile):
73 # file_byte_string = b'Bad data goes here'
74
75 def test_getline(self):
76 self.assertRaises((SyntaxError, UnicodeDecodeError),
77 linecache.getline, self.file_name, 1)
78
79 def test_getlines(self):
80 self.assertRaises((SyntaxError, UnicodeDecodeError),
81 linecache.getlines, self.file_name)
82
83
84class EmptyFile(GetLineTestsGoodData, unittest.TestCase):
85 file_list = []
86
87
88class SingleEmptyLine(GetLineTestsGoodData, unittest.TestCase):
89 file_list = ['\n']
90
91
92class GoodUnicode(GetLineTestsGoodData, unittest.TestCase):
93 file_list = ['á\n', 'b\n', 'abcdef\n', 'ááááá\n']
94
95
96class BadUnicode(GetLineTestsBadData, unittest.TestCase):
97 file_byte_string = b'\x80abc'
98
99
Georg Brandl991f9202009-05-05 08:31:54 +0000100class LineCacheTests(unittest.TestCase):
101
102 def test_getline(self):
103 getline = linecache.getline
104
105 # Bad values for line number should return an empty string
Ezio Melottib3aedd42010-11-20 19:04:17 +0000106 self.assertEqual(getline(FILENAME, 2**15), EMPTY)
107 self.assertEqual(getline(FILENAME, -1), EMPTY)
Georg Brandl991f9202009-05-05 08:31:54 +0000108
109 # Float values currently raise TypeError, should it?
110 self.assertRaises(TypeError, getline, FILENAME, 1.1)
111
112 # Bad filenames should return an empty string
Ezio Melottib3aedd42010-11-20 19:04:17 +0000113 self.assertEqual(getline(EMPTY, 1), EMPTY)
114 self.assertEqual(getline(INVALID_NAME, 1), EMPTY)
Georg Brandl991f9202009-05-05 08:31:54 +0000115
Georg Brandl991f9202009-05-05 08:31:54 +0000116 # Check module loading
117 for entry in MODULES:
118 filename = os.path.join(MODULE_PATH, entry) + '.py'
Inada Naokifb786922021-04-06 11:18:41 +0900119 with open(filename, encoding='utf-8') as file:
Brett Cannon01743682010-10-29 23:55:51 +0000120 for index, line in enumerate(file):
Ezio Melottib3aedd42010-11-20 19:04:17 +0000121 self.assertEqual(line, getline(filename, index + 1))
Georg Brandl991f9202009-05-05 08:31:54 +0000122
123 # Check that bogus data isn't returned (issue #1309567)
124 empty = linecache.getlines('a/b/c/__init__.py')
Ezio Melottib3aedd42010-11-20 19:04:17 +0000125 self.assertEqual(empty, [])
Georg Brandl991f9202009-05-05 08:31:54 +0000126
Benjamin Petersonaada7b82010-05-21 21:45:06 +0000127 def test_no_ending_newline(self):
Hai Shia089d212020-07-06 17:15:08 +0800128 self.addCleanup(os_helper.unlink, os_helper.TESTFN)
Inada Naokifb786922021-04-06 11:18:41 +0900129 with open(os_helper.TESTFN, "w", encoding='utf-8') as fp:
Benjamin Petersonaada7b82010-05-21 21:45:06 +0000130 fp.write(SOURCE_3)
Hai Shia089d212020-07-06 17:15:08 +0800131 lines = linecache.getlines(os_helper.TESTFN)
Benjamin Petersonaada7b82010-05-21 21:45:06 +0000132 self.assertEqual(lines, ["\n", "def f():\n", " return 3\n"])
133
Georg Brandl991f9202009-05-05 08:31:54 +0000134 def test_clearcache(self):
135 cached = []
Robert Collins631a35c2015-08-19 12:20:37 +1200136 for entry in MODULES:
137 filename = os.path.join(MODULE_PATH, entry) + '.py'
Georg Brandl991f9202009-05-05 08:31:54 +0000138 cached.append(filename)
139 linecache.getline(filename, 1)
140
141 # Are all files cached?
Robert Collins631a35c2015-08-19 12:20:37 +1200142 self.assertNotEqual(cached, [])
Georg Brandl991f9202009-05-05 08:31:54 +0000143 cached_empty = [fn for fn in cached if fn not in linecache.cache]
Ezio Melottib3aedd42010-11-20 19:04:17 +0000144 self.assertEqual(cached_empty, [])
Georg Brandl991f9202009-05-05 08:31:54 +0000145
146 # Can we clear the cache?
147 linecache.clearcache()
148 cached_empty = [fn for fn in cached if fn in linecache.cache]
Ezio Melottib3aedd42010-11-20 19:04:17 +0000149 self.assertEqual(cached_empty, [])
Georg Brandl991f9202009-05-05 08:31:54 +0000150
151 def test_checkcache(self):
152 getline = linecache.getline
Benjamin Petersonaada7b82010-05-21 21:45:06 +0000153 # Create a source file and cache its contents
Hai Shia089d212020-07-06 17:15:08 +0800154 source_name = os_helper.TESTFN + '.py'
155 self.addCleanup(os_helper.unlink, source_name)
Inada Naokifb786922021-04-06 11:18:41 +0900156 with open(source_name, 'w', encoding='utf-8') as source:
Benjamin Petersonaada7b82010-05-21 21:45:06 +0000157 source.write(SOURCE_1)
158 getline(source_name, 1)
Georg Brandl991f9202009-05-05 08:31:54 +0000159
Benjamin Petersonaada7b82010-05-21 21:45:06 +0000160 # Keep a copy of the old contents
161 source_list = []
Inada Naokifb786922021-04-06 11:18:41 +0900162 with open(source_name, encoding='utf-8') as source:
Benjamin Petersonaada7b82010-05-21 21:45:06 +0000163 for index, line in enumerate(source):
Ezio Melottib3aedd42010-11-20 19:04:17 +0000164 self.assertEqual(line, getline(source_name, index + 1))
Benjamin Petersonaada7b82010-05-21 21:45:06 +0000165 source_list.append(line)
Georg Brandl991f9202009-05-05 08:31:54 +0000166
Inada Naokifb786922021-04-06 11:18:41 +0900167 with open(source_name, 'w', encoding='utf-8') as source:
Benjamin Petersonaada7b82010-05-21 21:45:06 +0000168 source.write(SOURCE_2)
Georg Brandl991f9202009-05-05 08:31:54 +0000169
Benjamin Petersonaada7b82010-05-21 21:45:06 +0000170 # Try to update a bogus cache entry
171 linecache.checkcache('dummy')
172
173 # Check that the cache matches the old contents
174 for index, line in enumerate(source_list):
Ezio Melottib3aedd42010-11-20 19:04:17 +0000175 self.assertEqual(line, getline(source_name, index + 1))
Benjamin Petersonaada7b82010-05-21 21:45:06 +0000176
177 # Update the cache and check whether it matches the new source file
178 linecache.checkcache(source_name)
Inada Naokifb786922021-04-06 11:18:41 +0900179 with open(source_name, encoding='utf-8') as source:
Benjamin Petersonaada7b82010-05-21 21:45:06 +0000180 for index, line in enumerate(source):
Ezio Melottib3aedd42010-11-20 19:04:17 +0000181 self.assertEqual(line, getline(source_name, index + 1))
Benjamin Petersonaada7b82010-05-21 21:45:06 +0000182 source_list.append(line)
Georg Brandl991f9202009-05-05 08:31:54 +0000183
Robert Collins6bc2c1e2015-03-05 12:07:57 +1300184 def test_lazycache_no_globals(self):
185 lines = linecache.getlines(FILENAME)
186 linecache.clearcache()
187 self.assertEqual(False, linecache.lazycache(FILENAME, None))
188 self.assertEqual(lines, linecache.getlines(FILENAME))
189
190 def test_lazycache_smoke(self):
191 lines = linecache.getlines(NONEXISTENT_FILENAME, globals())
192 linecache.clearcache()
193 self.assertEqual(
194 True, linecache.lazycache(NONEXISTENT_FILENAME, globals()))
195 self.assertEqual(1, len(linecache.cache[NONEXISTENT_FILENAME]))
Martin Panter46f50722016-05-26 05:35:26 +0000196 # Note here that we're looking up a nonexistent filename with no
Robert Collins6bc2c1e2015-03-05 12:07:57 +1300197 # globals: this would error if the lazy value wasn't resolved.
198 self.assertEqual(lines, linecache.getlines(NONEXISTENT_FILENAME))
199
200 def test_lazycache_provide_after_failed_lookup(self):
201 linecache.clearcache()
202 lines = linecache.getlines(NONEXISTENT_FILENAME, globals())
203 linecache.clearcache()
204 linecache.getlines(NONEXISTENT_FILENAME)
205 linecache.lazycache(NONEXISTENT_FILENAME, globals())
206 self.assertEqual(lines, linecache.updatecache(NONEXISTENT_FILENAME))
207
208 def test_lazycache_check(self):
209 linecache.clearcache()
210 linecache.lazycache(NONEXISTENT_FILENAME, globals())
211 linecache.checkcache()
212
213 def test_lazycache_bad_filename(self):
214 linecache.clearcache()
215 self.assertEqual(False, linecache.lazycache('', globals()))
216 self.assertEqual(False, linecache.lazycache('<foo>', globals()))
217
218 def test_lazycache_already_cached(self):
219 linecache.clearcache()
220 lines = linecache.getlines(NONEXISTENT_FILENAME, globals())
221 self.assertEqual(
222 False,
223 linecache.lazycache(NONEXISTENT_FILENAME, globals()))
224 self.assertEqual(4, len(linecache.cache[NONEXISTENT_FILENAME]))
225
Serhiy Storchakac512adc2015-04-01 16:54:05 +0300226 def test_memoryerror(self):
227 lines = linecache.getlines(FILENAME)
228 self.assertTrue(lines)
229 def raise_memoryerror(*args, **kwargs):
230 raise MemoryError
231 with support.swap_attr(linecache, 'updatecache', raise_memoryerror):
232 lines2 = linecache.getlines(FILENAME)
233 self.assertEqual(lines2, lines)
Robert Collins6bc2c1e2015-03-05 12:07:57 +1300234
Serhiy Storchakac512adc2015-04-01 16:54:05 +0300235 linecache.clearcache()
236 with support.swap_attr(linecache, 'updatecache', raise_memoryerror):
237 lines3 = linecache.getlines(FILENAME)
238 self.assertEqual(lines3, [])
239 self.assertEqual(linecache.getlines(FILENAME), lines)
240
Georg Brandl991f9202009-05-05 08:31:54 +0000241
242if __name__ == "__main__":
Serhiy Storchakac512adc2015-04-01 16:54:05 +0300243 unittest.main()