8000 bpo-25872: Add unit tests for linecache and threading by uniocto · Pull Request #25913 · python/cpython · GitHub
[go: up one dir, main page]

Skip to content

bpo-25872: Add unit tests for linecache and threading #25913

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 21 commits into from
May 18, 2021
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
bpo-25872: add test_oserror
  • Loading branch information
uniocto committed May 5, 2021
commit 5143e745931fdb4855eedb7110d733251a0573db
37 changes: 37 additions & 0 deletions Lib/test/test_linecache.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ def f():
return 3''' # No ending newline


SOURCE_4 = '''
raise OSError
'''

class TempFile:

def setUp(self):
Expand Down Expand Up @@ -181,6 +185,39 @@ def test_checkcache(self):
self.assertEqual(line, getline(source_name, index + 1))
source_list.append(line)

def test_checkcache_oserror(self):
linecache.clearcache()
_ = linecache.getlines(FILENAME)
self.assertTrue(_)
self.assertEqual(1, len(linecache.cache.keys()))
def raise_oserror(*args, **kwargs):
raise OSError
with support.swap_attr(os, 'stat', raise_oserror):
< 8000 div class="timeline-comment-actions flex-shrink-0 d-flex flex-items-center">
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fact that os.stat is used in checkcache is an implementation detail, not a part of that's function's external API, so I don't think the unit test should depend on that.

I would write this as a black-box test. And also test that the cache clearing is selective. Note that there are two cases in checkcache() where the cache is popped: OSError from stat, or size/timestamp don't match.

So, create three files f1, f2, f3 and load them into the cache. Then delete f1, modify f2 and call checkcache. Ensure that the cache entries for f1 and f2 were removed from the cache but the entries for f3 are still there.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for your feedback.
As you said, other tests are written in such a way that they do not depend on the internal implementation.
I will try to write them in a black box as you suggested, so I would appreciate it if you could take look again !!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I write a black box test, and would be happy if you could check it out.

def test_oserror(self):
    def _oserror_helper():
        linecache.clearcache()
        be_deleted_file = os_helper.TESTFN + '.1'
        be_modified_file = os_helper.TESTFN + '.2'
        unchange_file = os_helper.TESTFN + '.3'
        self.addCleanup(os_helper.unlink, be_deleted_file)
        self.addCleanup(os_helper.unlink, be_modified_file)
        self.addCleanup(os_helper.unlink, unchange_file)
        with open(be_deleted_file, 'w', encoding='utf-8') as source:
            source.write('print("will be deleted")')
        with open(be_modified_file, 'w', encoding='utf-8') as source:
            source.write('print("will be modified")')
        with open(unchange_file, 'w', encoding='utf-8') as source:
            source.write('print("unchange")')

        _ = linecache.getlines(be_deleted_file)
        _ = linecache.getlines(be_modified_file)
        _ = linecache.getlines(unchange_file)
        self.assertEqual(3, len(linecache.cache.keys()))

        os.remove(be_deleted_file)
        with open(be_modified_file, 'w', encoding='utf-8') as source:
            source.write('print("was modified")')
        return (be_deleted_file, be_modified_file, unchange_file)

    deleted_file, modified_file, unchange_file = _oserror_helper()
    _ = linecache.checkcache(deleted_file)
    self.assertEqual(2, len(linecache.cache.keys()))
    _ = linecache.checkcache(modified_file)
    self.assertEqual(1, len(linecache.cache.keys()))
    _ = linecache.checkcache(unchange_file)
    self.assertEqual(1, len(linecache.cache.keys()))

    deleted_file, modified_file, unchange_file = _oserror_helper()
    _ = linecache.updatecache(deleted_file)
    self.assertEqual(2, len(linecache.cache.keys()))
    _ = linecache.updatecache(modified_file)
    self.assertEqual(2, len(linecache.cache.keys()))
    _ = linecache.updatecache(unchange_file)
    self.assertEqual(2, len(linecache.cache.keys()))

# pop all cache
_ = linecache.checkcache()
self.assertEqual(0, len(linecache.cache.keys()))

def test_updatecache_oserror(self):
linecache.clearcache()
def raise_oserror(*args, **kwargs):
raise OSError
source_name = os_helper.TESTFN
self.addCleanup(os_helper.unlink, os_helper.TESTFN)
with open(source_name, 'w', encoding='utf-8') as source:
source.write(SOURCE_4)
_ = linecache.getlines(source_name)
self.assertEqual(1, len(linecache.cache.keys()))

with support.swap_attr(os, 'stat', raise_oserror):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As above - delete/modify the file instead of mocking os.stat.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As shown above, I write delete/modify test.

# Trace OSError with no pop cache
_ = linecache.updatecache('dummy')
self.assertEqual(1, len(linecache.cache.keys()))

with support.swap_attr(os, 'stat', raise_oserror):
# Trace OSError with pop cache
_ = linecache.updatecache(source_name)
self.assertEqual(0, len(linecache.cache.keys()))

def test_lazycache_no_globals(self):
lines = linecache.getlines(FILENAME)
linecache.clearcache()
Expand Down
0