diff -r 2b7b203e3909 Lib/distutils/tests/test_archive_util.py --- a/Lib/distutils/tests/test_archive_util.py Wed Jan 11 20:18:03 2017 +0200 +++ b/Lib/distutils/tests/test_archive_util.py Thu Jan 12 13:05:20 2017 +0100 @@ -162,7 +162,9 @@ # now create another tarball using `tar` tarball2 = os.path.join(tmpdir, 'archive2.tar.gz') tar_cmd = ['tar', '-cf', 'archive2.tar', 'dist'] - gzip_cmd = ['gzip', '-f9', 'archive2.tar'] + # Issue 29185: use separate command line options as gzip on Android + # API 24 understands '-f9' as the name of a file. + gzip_cmd = ['gzip', '-f', '-9', 'archive2.tar'] old_dir = os.getcwd() os.chdir(tmpdir) try: diff -r 2b7b203e3909 Lib/distutils/tests/test_file_util.py --- a/Lib/distutils/tests/test_file_util.py Wed Jan 11 20:18:03 2017 +0200 +++ b/Lib/distutils/tests/test_file_util.py Thu Jan 12 13:05:20 2017 +0100 @@ -8,7 +8,7 @@ from distutils import log from distutils.tests import support from distutils.errors import DistutilsFileError -from test.support import run_unittest +from test.support import run_unittest, skip_unless_hardlink class FileUtilTestCase(support.TempdirManager, unittest.TestCase): @@ -77,6 +77,7 @@ fobj.write('spam eggs') move_file(self.source, self.target, verbose=0) + @skip_unless_hardlink def test_copy_file_hard_link(self): with open(self.source, 'w') as f: f.write('some content') diff -r 2b7b203e3909 Lib/test/support/__init__.py --- a/Lib/test/support/__init__.py Wed Jan 11 20:18:03 2017 +0200 +++ b/Lib/test/support/__init__.py Thu Jan 12 13:05:20 2017 +0100 @@ -91,6 +91,7 @@ "requires_IEEE_754", "skip_unless_xattr", "requires_zlib", "anticipate_failure", "load_package_tests", "detect_api_mismatch", "check__all__", "requires_android_level", "requires_multiprocessing_queue", + "skip_unless_hardlink", # sys "is_jython", "is_android", "check_impl_detail", "unix_shell", "setswitchinterval", "android_not_root", @@ -2241,27 +2242,33 @@ return result -_can_symlink = None -def can_symlink(): - global _can_symlink - if _can_symlink is not None: - return _can_symlink - symlink_path = TESTFN + "can_symlink" +_can_link = { os.symlink: None, os.link: None } +def can_link(func): + if _can_link[func] is not None: + return _can_link[func] + link_path = TESTFN + "can_link" try: - os.symlink(TESTFN, symlink_path) + func(TESTFN, link_path) can = True except (OSError, NotImplementedError, AttributeError): can = False else: - os.remove(symlink_path) - _can_symlink = can + os.remove(link_path) + _can_link[func] = can return can +def _skip_unless_link(test, func, type): + ok = can_link(func) + msg = "Requires functional %slink implementation" % type + return test if ok else unittest.skip(msg)(test) + def skip_unless_symlink(test): """Skip decorator for tests that require functional symlink""" - ok = can_symlink() - msg = "Requires functional symlink implementation" - return test if ok else unittest.skip(msg)(test) + return _skip_unless_link(test, os.symlink, 'sym') + +def skip_unless_hardlink(test): + """Skip decorator for tests that require functional hard link""" + return _skip_unless_link(test, os.link, 'hard ') _can_xattr = None def can_xattr():