From c051788d0139b5d3c430cbccda302d8f8e12ca3e Mon Sep 17 00:00:00 2001 From: uniocto Date: Tue, 18 May 2021 17:56:52 +0900 Subject: [PATCH] bpo-25872: Add unit tests for linecache and threading (GH-25913) (cherry picked from commit 115dea9e2602b96b63390f00cc880e90c433efa2) --- Lib/test/test_linecache.py | 42 ++++++++++++++++++++++++++++++++++++++ Lib/test/test_threading.py | 19 ++++++++++++++++- 2 files changed, 60 insertions(+), 1 deletion(-) diff --git a/Lib/test/test_linecache.py b/Lib/test/test_linecache.py index 375d9c42137ba2..f5691163b8ec56 100644 --- a/Lib/test/test_linecache.py +++ b/Lib/test/test_linecache.py @@ -238,5 +238,47 @@ def raise_memoryerror(*args, **kwargs): self.assertEqual(linecache.getlines(FILENAME), lines) +class LineCacheInvalidationTests(unittest.TestCase): + def setUp(self): + super().setUp() + linecache.clearcache() + self.deleted_file = support.TESTFN + '.1' + self.modified_file = support.TESTFN + '.2' + self.unchanged_file = support.TESTFN + '.3' + + for fname in (self.deleted_file, + self.modified_file, + self.unchanged_file): + self.addCleanup(support.unlink, fname) + with open(fname, 'w', encoding='utf-8') as source: + source.write(f'print("I am {fname}")') + + self.assertNotIn(fname, linecache.cache) + linecache.getlines(fname) + self.assertIn(fname, linecache.cache) + + os.remove(self.deleted_file) + with open(self.modified_file, 'w', encoding='utf-8') as source: + source.write('print("was modified")') + + def test_checkcache_for_deleted_file(self): + linecache.checkcache(self.deleted_file) + self.assertNotIn(self.deleted_file, linecache.cache) + self.assertIn(self.modified_file, linecache.cache) + self.assertIn(self.unchanged_file, linecache.cache) + + def test_checkcache_for_modified_file(self): + linecache.checkcache(self.modified_file) + self.assertIn(self.deleted_file, linecache.cache) + self.assertNotIn(self.modified_file, linecache.cache) + self.assertIn(self.unchanged_file, linecache.cache) + + def test_checkcache_with_no_parameter(self): + linecache.checkcache() + self.assertNotIn(self.deleted_file, linecache.cache) + self.assertNotIn(self.modified_file, linecache.cache) + self.assertIn(self.unchanged_file, linecache.cache) + + if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_threading.py b/Lib/test/test_threading.py index 67e061e8aa63bc..a57085b75d58ad 100644 --- a/Lib/test/test_threading.py +++ b/Lib/test/test_threading.py @@ -3,7 +3,7 @@ """ import test.support -from test.support import verbose, import_module, cpython_only +from test.support import verbose, import_module, cpython_only, unlink from test.support.script_helper import assert_python_ok, assert_python_failure import random @@ -17,6 +17,7 @@ import subprocess import signal import textwrap +import traceback from test import lock_tests from test import support @@ -1243,6 +1244,22 @@ def run(self): # explicitly break the reference cycle to not leak a dangling thread thread.exc = None + def test_multithread_modify_file_noerror(self): + # See issue25872 + def modify_file(): + with open(test.support.TESTFN, 'w', encoding='utf-8') as fp: + fp.write(' ') + traceback.format_stack() + + self.addCleanup(unlink, test.support.TESTFN) + threads = [ + threading.Thread(target=modify_file) + for i in range(100) + ] + for t in threads: + t.start() + t.join() + class ThreadRunFail(threading.Thread): def run(self):