Skip to content

Instantly share code, notes, and snippets.

@danbradham
Created January 24, 2018 01:50
Show Gist options
  • Save danbradham/aff1e027bcdec0e30d4110e6d7dd887c to your computer and use it in GitHub Desktop.
Save danbradham/aff1e027bcdec0e30d4110e6d7dd887c to your computer and use it in GitHub Desktop.
Test conditions under which st_mtime of a directory changes
# -*- 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