Created
January 24, 2018 01:50
-
-
Save danbradham/aff1e027bcdec0e30d4110e6d7dd887c to your computer and use it in GitHub Desktop.
Test conditions under which st_mtime of a directory changes
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- coding: utf-8 -*- | |
''' | |
This module tests the circumstances under which a directory's st_mtime changes. | |
Precision is determined by the current file system. On Windows with NTFS the | |
tests will pass when the time between changes is as low as 0.01 seconds. If | |
you set the INTERVAL to 0 you'll discover how inconsistent the tests become. | |
On Unix based systems with other file systems the time between changes must | |
increase in order for the tests to pass, in the worst case up to 2 seconds. | |
Runs with a default SLEEP_INTERVAL of 0.1 seconds. You can pass a different | |
SLEEP_INTERVAL like so: | |
python -m dir_mtime 2.0 | |
''' | |
from __future__ import absolute_import, division, print_function | |
import os | |
import shutil | |
import time | |
import unittest | |
from datetime import datetime | |
from contextlib import contextmanager | |
SLEEP_INTERVAL = 0.1 | |
def time_since_modified(path): | |
return ( | |
datetime.now() | |
- datetime.fromtimestamp(os.path.getmtime(path)) | |
).total_seconds() | |
def mtime(*paths): | |
return os.path.getmtime(os.path.join(*paths)) | |
def link_dir(*paths): | |
try: | |
os.makedirs(os.path.join(*paths)) | |
except: | |
pass | |
def link(*paths): | |
file = os.path.join(*paths) | |
dir = os.path.dirname(file) | |
if not os.path.exists(dir): | |
make_dir(dir) | |
touch(file) | |
def unlink(*paths): | |
path = os.path.join(*paths) | |
if os.path.isdir(path): | |
shutil.rmtree(path) | |
else: | |
os.remove(path) | |
def touch(*paths): | |
file = os.path.join(*paths) | |
with open(file, 'a'): | |
os.utime(file, None) | |
@contextmanager | |
def assert_mtime_changed(path, value, sleep_interval): | |
mt = mtime(path) | |
if value: | |
msg = path + ' mtime has not changed' | |
else: | |
msg = path + ' mtime changed' | |
try: | |
if sleep_interval: | |
time.sleep(sleep_interval) | |
yield | |
finally: | |
assert (mt != mtime(path)) == value, msg | |
class TestMTime(unittest.TestCase): | |
def test_subdir_created(self): | |
'''mtime changes when subdir created''' | |
link_dir('tmp') | |
with assert_mtime_changed('tmp', True, SLEEP_INTERVAL): | |
link_dir('tmp', 'subdir') | |
unlink('tmp') | |
def test_subdir_deleted(self): | |
'''mtime changes when subdir deleted''' | |
link_dir('tmp') | |
link_dir('tmp', 'subdir') | |
with assert_mtime_changed('tmp', True, SLEEP_INTERVAL): | |
unlink('tmp', 'subdir') | |
unlink('tmp') | |
def test_subfile_created(self): | |
'''mtime changes when subfile created''' | |
link_dir('tmp') | |
with assert_mtime_changed('tmp', True, SLEEP_INTERVAL): | |
link('tmp', 'file') | |
unlink('tmp') | |
def test_subfile_changed(self): | |
'''mtime changes when subfile changed''' | |
link_dir('tmp') | |
link('tmp', 'file') | |
with assert_mtime_changed('tmp', False, SLEEP_INTERVAL): | |
touch('tmp', 'file') | |
unlink('tmp') | |
def test_subfile_deleted(self): | |
'''mtime changes when subfile deleted''' | |
link_dir('tmp') | |
link('tmp', 'file') | |
with assert_mtime_changed('tmp', True, SLEEP_INTERVAL): | |
unlink('tmp', 'file') | |
unlink('tmp') | |
if __name__ == '__main__': | |
import sys | |
args = sys.argv[1:] | |
if len(args) == 1: | |
SLEEP_INTERVAL = float(args[0]) | |
print('Running tests with SLEEP_INTERVAL:', SLEEP_INTERVAL, 'seconds') | |
loader = unittest.TestLoader() | |
suite = loader.loadTestsFromTestCase(TestMTime) | |
unittest.TextTestRunner(verbosity=2).run(suite) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment