diff -r 3156dd82df2d Lib/test/test_os.py --- a/Lib/test/test_os.py Wed Jun 10 15:44:18 2015 -0700 +++ b/Lib/test/test_os.py Fri Jun 12 02:39:20 2015 +0200 @@ -70,16 +70,6 @@ root_in_posix = False if hasattr(os, 'geteuid'): root_in_posix = (os.geteuid() == 0) -with warnings.catch_warnings(): - warnings.simplefilter("ignore", DeprecationWarning) - os.stat_float_times(True) -st = os.stat(__file__) -stat_supports_subsecond = ( - # check if float and int timestamps are different - (st.st_atime != st[7]) - or (st.st_mtime != st[8]) - or (st.st_ctime != st[9])) - # Detect whether we're on a Linux system that uses the (now outdated # and unmaintained) linuxthreads threading library. There's an issue # when combining linuxthreads with a failed execv call: see @@ -223,15 +213,10 @@ class FileTests(unittest.TestCase): # Test attributes on return values from os.*stat* family. class StatAttributeTests(unittest.TestCase): def setUp(self): - os.mkdir(support.TESTFN) - self.fname = os.path.join(support.TESTFN, "f1") - f = open(self.fname, 'wb') - f.write(b"ABC") - f.close() - - def tearDown(self): - os.unlink(self.fname) - os.rmdir(support.TESTFN) + self.fname = support.TESTFN + self.addCleanup(support.unlink, self.fname) + with open(self.fname, 'wb') as fp: + fp.write(b"ABC") @unittest.skipUnless(hasattr(os, 'stat'), 'test needs os.stat()') def check_stat_attributes(self, fname): @@ -383,179 +368,6 @@ class StatAttributeTests(unittest.TestCa unpickled = pickle.loads(p) self.assertEqual(result, unpickled) - def test_utime_dir(self): - delta = 1000000 - st = os.stat(support.TESTFN) - # round to int, because some systems may support sub-second - # time stamps in stat, but not in utime. - os.utime(support.TESTFN, (st.st_atime, int(st.st_mtime-delta))) - st2 = os.stat(support.TESTFN) - self.assertEqual(st2.st_mtime, int(st.st_mtime-delta)) - - def _test_utime(self, filename, attr, utime, delta): - # Issue #13327 removed the requirement to pass None as the - # second argument. Check that the previous methods of passing - # a time tuple or None work in addition to no argument. - st0 = os.stat(filename) - # Doesn't set anything new, but sets the time tuple way - utime(filename, (attr(st0, "st_atime"), attr(st0, "st_mtime"))) - # Setting the time to the time you just read, then reading again, - # should always return exactly the same times. - st1 = os.stat(filename) - self.assertEqual(attr(st0, "st_mtime"), attr(st1, "st_mtime")) - self.assertEqual(attr(st0, "st_atime"), attr(st1, "st_atime")) - # Set to the current time in the old explicit way. - os.utime(filename, None) - st2 = os.stat(support.TESTFN) - # Set to the current time in the new way - os.utime(filename) - st3 = os.stat(filename) - self.assertAlmostEqual(attr(st2, "st_mtime"), attr(st3, "st_mtime"), delta=delta) - - def test_utime(self): - def utime(file, times): - return os.utime(file, times) - self._test_utime(self.fname, getattr, utime, 10) - self._test_utime(support.TESTFN, getattr, utime, 10) - - - def _test_utime_ns(self, set_times_ns, test_dir=True): - def getattr_ns(o, attr): - return getattr(o, attr + "_ns") - ten_s = 10 * 1000 * 1000 * 1000 - self._test_utime(self.fname, getattr_ns, set_times_ns, ten_s) - if test_dir: - self._test_utime(support.TESTFN, getattr_ns, set_times_ns, ten_s) - - def test_utime_ns(self): - def utime_ns(file, times): - return os.utime(file, ns=times) - self._test_utime_ns(utime_ns) - - requires_utime_dir_fd = unittest.skipUnless( - os.utime in os.supports_dir_fd, - "dir_fd support for utime required for this test.") - requires_utime_fd = unittest.skipUnless( - os.utime in os.supports_fd, - "fd support for utime required for this test.") - requires_utime_nofollow_symlinks = unittest.skipUnless( - os.utime in os.supports_follow_symlinks, - "follow_symlinks support for utime required for this test.") - - @requires_utime_nofollow_symlinks - def test_lutimes_ns(self): - def lutimes_ns(file, times): - return os.utime(file, ns=times, follow_symlinks=False) - self._test_utime_ns(lutimes_ns) - - @requires_utime_fd - def test_futimes_ns(self): - def futimes_ns(file, times): - with open(file, "wb") as f: - os.utime(f.fileno(), ns=times) - self._test_utime_ns(futimes_ns, test_dir=False) - - def _utime_invalid_arguments(self, name, arg): - with self.assertRaises(ValueError): - getattr(os, name)(arg, (5, 5), ns=(5, 5)) - - def test_utime_invalid_arguments(self): - self._utime_invalid_arguments('utime', self.fname) - - - @unittest.skipUnless(stat_supports_subsecond, - "os.stat() doesn't has a subsecond resolution") - def _test_utime_subsecond(self, set_time_func): - asec, amsec = 1, 901 - atime = asec + amsec * 1e-3 - msec, mmsec = 2, 901 - mtime = msec + mmsec * 1e-3 - filename = self.fname - os.utime(filename, (0, 0)) - set_time_func(filename, atime, mtime) - with warnings.catch_warnings(): - warnings.simplefilter("ignore", DeprecationWarning) - os.stat_float_times(True) - st = os.stat(filename) - self.assertAlmostEqual(st.st_atime, atime, places=3) - self.assertAlmostEqual(st.st_mtime, mtime, places=3) - - def test_utime_subsecond(self): - def set_time(filename, atime, mtime): - os.utime(filename, (atime, mtime)) - self._test_utime_subsecond(set_time) - - @requires_utime_fd - def test_futimes_subsecond(self): - def set_time(filename, atime, mtime): - with open(filename, "wb") as f: - os.utime(f.fileno(), times=(atime, mtime)) - self._test_utime_subsecond(set_time) - - @requires_utime_fd - def test_futimens_subsecond(self): - def set_time(filename, atime, mtime): - with open(filename, "wb") as f: - os.utime(f.fileno(), times=(atime, mtime)) - self._test_utime_subsecond(set_time) - - @requires_utime_dir_fd - def test_futimesat_subsecond(self): - def set_time(filename, atime, mtime): - dirname = os.path.dirname(filename) - dirfd = os.open(dirname, os.O_RDONLY) - try: - os.utime(os.path.basename(filename), dir_fd=dirfd, - times=(atime, mtime)) - finally: - os.close(dirfd) - self._test_utime_subsecond(set_time) - - @requires_utime_nofollow_symlinks - def test_lutimes_subsecond(self): - def set_time(filename, atime, mtime): - os.utime(filename, (atime, mtime), follow_symlinks=False) - self._test_utime_subsecond(set_time) - - @requires_utime_dir_fd - def test_utimensat_subsecond(self): - def set_time(filename, atime, mtime): - dirname = os.path.dirname(filename) - dirfd = os.open(dirname, os.O_RDONLY) - try: - os.utime(os.path.basename(filename), dir_fd=dirfd, - times=(atime, mtime)) - finally: - os.close(dirfd) - self._test_utime_subsecond(set_time) - - # Restrict tests to Win32, since there is no guarantee other - # systems support centiseconds - def get_file_system(path): - if sys.platform == 'win32': - root = os.path.splitdrive(os.path.abspath(path))[0] + '\\' - import ctypes - kernel32 = ctypes.windll.kernel32 - buf = ctypes.create_unicode_buffer("", 100) - if kernel32.GetVolumeInformationW(root, None, 0, None, None, None, buf, len(buf)): - return buf.value - - @unittest.skipUnless(sys.platform == "win32", "Win32 specific tests") - @unittest.skipUnless(get_file_system(support.TESTFN) == "NTFS", - "requires NTFS") - def test_1565150(self): - t1 = 1159195039.25 - os.utime(self.fname, (t1, t1)) - self.assertEqual(os.stat(self.fname).st_mtime, t1) - - @unittest.skipUnless(sys.platform == "win32", "Win32 specific tests") - @unittest.skipUnless(get_file_system(support.TESTFN) == "NTFS", - "requires NTFS") - def test_large_time(self): - t1 = 5000000000 # some day in 2128 - os.utime(self.fname, (t1, t1)) - self.assertEqual(os.stat(self.fname).st_mtime, t1) - @unittest.skipUnless(sys.platform == "win32", "Win32 specific tests") def test_1686475(self): # Verify that an open file can be stat'ed @@ -596,12 +408,200 @@ class StatAttributeTests(unittest.TestCa 0) # test directory st_file_attributes (FILE_ATTRIBUTE_DIRECTORY set) - result = os.stat(support.TESTFN) + dirname = support.TESTFN + "dir" + os.mkdir(dirname) + self.addCleanup(os.rmdir, dirname) + + result = os.stat(dirname) self.check_file_attributes(result) self.assertEqual( result.st_file_attributes & stat.FILE_ATTRIBUTE_DIRECTORY, stat.FILE_ATTRIBUTE_DIRECTORY) + +class UtimeTests(unittest.TestCase): + requires_utime_dir_fd = unittest.skipUnless( + os.utime in os.supports_dir_fd, + "dir_fd support for utime required for this test.") + requires_utime_fd = unittest.skipUnless( + os.utime in os.supports_fd, + "fd support for utime required for this test.") + requires_utime_nofollow_symlinks = unittest.skipUnless( + os.utime in os.supports_follow_symlinks, + "follow_symlinks support for utime required for this test.") + + + def setUp(self): + self.dirname = support.TESTFN + self.fname = os.path.join(self.dirname, "f1") + + self.addCleanup(support.rmtree, self.dirname) + os.mkdir(self.dirname) + with open(self.fname, 'wb') as fp: + fp.write(b"ABC") + + # ensure that st_atime and st_mtime are float + with warnings.catch_warnings(): + warnings.simplefilter("ignore", DeprecationWarning) + + old_state = os.stat_float_times(-1) + self.addCleanup(os.stat_float_times, old_state) + + os.stat_float_times(True) + + def support_subsecond(self): + # Heuristic to check if the filesystem supports timestamp with + # subsecond resolution: check if float and int timestamps are different + st = os.stat(self.fname) + return ((st.st_atime != st[7]) + or (st.st_mtime != st[8]) + or (st.st_ctime != st[9])) + + def _test_utime(self, set_time, filename=None): + if not filename: + filename = self.fname + + support_subsecond = self.support_subsecond() + if support_subsecond: + # Timestamp with a resolution of 1 us (10^-6). + # + # The resolution of the C internal function used by os.utime() + # depends on the platform: 1 sec, 1 us, 1 ns. Writing a portable + # test with a resolution of 1 ns requires more work: + # see the issue #15745. + atime_ns = 1002003000 # 1.002003 seconds + mtime_ns = 4005006000 # 4.005006 seconds + else: + # use a resolution of 1 second + atime_ns = 5 * 10**9 + mtime_ns = 8 * 10**9 + + set_time(filename, (atime_ns, mtime_ns)) + st = os.stat(filename) + + if support_subsecond: + self.assertAlmostEqual(st.st_atime, atime_ns * 1e-9, delta=1e-6) + self.assertAlmostEqual(st.st_mtime, mtime_ns * 1e-9, delta=1e-6) + else: + self.assertEqual(st.st_atime, atime_ns * 1e-9) + self.assertEqual(st.st_mtime, mtime_ns * 1e-9) + self.assertEqual(st.st_atime_ns, atime_ns) + self.assertEqual(st.st_mtime_ns, mtime_ns) + + def test_utime(self): + def set_time(filename, ns): + # test the ns keyword parameter + os.utime(filename, ns=ns) + self._test_utime(set_time) + + @staticmethod + def ns_to_sec(ns): + # Convert a number of nanosecond (int) to a number of seconds (float). + # Round towards infinity by adding 0.5 nanosecond to avoid rounding + # issue, os.utime() rounds towards minus infinity. + return (ns * 1e-9) + 0.5e-9 + + def test_utime_by_indexed(self): + # pass times as floating point seconds as the second indexed parameter + def set_time(filename, ns): + atime_ns, mtime_ns = ns + atime = self.ns_to_sec(atime_ns) + mtime = self.ns_to_sec(mtime_ns) + # test utimensat(timespec), utimes(timeval), utime(utimbuf) + # or utime(time_t) + os.utime(filename, (atime, mtime)) + self._test_utime(set_time) + + def test_utime_by_times(self): + def set_time(filename, ns): + atime_ns, mtime_ns = ns + atime = self.ns_to_sec(atime_ns) + mtime = self.ns_to_sec(mtime_ns) + # test the times keyword parameter + os.utime(filename, times=(atime, mtime)) + self._test_utime(set_time) + + @requires_utime_nofollow_symlinks + def test_utime_nofollow_symlinks(self): + def set_time(filename, ns): + # use follow_symlinks=False to test utimensat(timespec) + # or lutimes(timeval) + os.utime(filename, ns=ns, follow_symlinks=False) + self._test_utime(set_time) + + @requires_utime_fd + def test_utime_fd(self): + def set_time(filename, ns): + with open(filename, 'wb') as fp: + # use a file descriptor to test futimens(timespec) + # or futimes(timeval) + os.utime(fp.fileno(), ns=ns) + self._test_utime(set_time) + + @requires_utime_dir_fd + def test_utime_dir_fd(self): + def set_time(filename, ns): + dirname = os.path.dirname(filename) + dirfd = os.open(dirname, os.O_RDONLY) + try: + # pass dir_fd to test utimensat(timespec) or futimesat(timeval) + os.utime(os.path.basename(filename), dir_fd=dirfd, + ns=ns) + finally: + os.close(dirfd) + self._test_utime(set_time) + + def test_utime_directory(self): + def set_time(filename, ns): + os.utime(filename, ns=ns) + self._test_utime(set_time, filename=self.dirname) + + def _test_utime_current(self, utime): + current = time.time() + utime(self.fname) + + st = os.stat(self.fname) + # check with a resolution of 10 ms + self.assertAlmostEqual(st.st_mtime, current, delta=0.010) + + def test_utime_current(self): + def set_time(filename): + # Set to the current time in the new way + os.utime(self.fname) + self._test_utime_current(set_time) + + def test_utime_current_old(self): + def set_time(filename): + # Set to the current time in the old explicit way. + os.utime(self.fname, None) + self._test_utime_current(set_time) + + def get_file_system(self, path): + if sys.platform == 'win32': + root = os.path.splitdrive(os.path.abspath(path))[0] + '\\' + import ctypes + kernel32 = ctypes.windll.kernel32 + buf = ctypes.create_unicode_buffer("", 100) + if kernel32.GetVolumeInformationW(root, None, 0, None, None, None, buf, len(buf)): + return buf.value + # return None if the filesystem is unknown + + def test_large_time(self): + # Many filesystems are limited to the year 2038. At least, the test + # pass with NTFS filesystem. + if self.get_file_system(self.dirname) != "NTFS": + self.skipTest("requires NTFS") + + large = 5000000000 # some day in 2128 + os.utime(self.fname, (large, large)) + self.assertEqual(os.stat(self.fname).st_mtime, large) + + def test_utime_invalid_arguments(self): + # seconds and nanoseconds are mutually exclusive + with self.assertRaises(ValueError): + os.utime(self.fname, (5, 5), ns=(5, 5)) + + from test import mapping_tests class EnvironTests(mapping_tests.BasicTestMappingProtocol):