Home | History | Annotate | Download | only in test
      1 import os
      2 import posixpath
      3 import unittest
      4 import warnings
      5 from posixpath import realpath, abspath, dirname, basename
      6 from test import support, test_genericpath
      7 
      8 try:
      9     import posix
     10 except ImportError:
     11     posix = None
     12 
     13 # An absolute path to a temporary filename for testing. We can't rely on TESTFN
     14 # being an absolute path, so we need this.
     15 
     16 ABSTFN = abspath(support.TESTFN)
     17 
     18 def skip_if_ABSTFN_contains_backslash(test):
     19     """
     20     On Windows, posixpath.abspath still returns paths with backslashes
     21     instead of posix forward slashes. If this is the case, several tests
     22     fail, so skip them.
     23     """
     24     found_backslash = '\\' in ABSTFN
     25     msg = "ABSTFN is not a posix path - tests fail"
     26     return [test, unittest.skip(msg)(test)][found_backslash]
     27 
     28 def safe_rmdir(dirname):
     29     try:
     30         os.rmdir(dirname)
     31     except OSError:
     32         pass
     33 
     34 class PosixPathTest(unittest.TestCase):
     35 
     36     def setUp(self):
     37         self.tearDown()
     38 
     39     def tearDown(self):
     40         for suffix in ["", "1", "2"]:
     41             support.unlink(support.TESTFN + suffix)
     42             safe_rmdir(support.TESTFN + suffix)
     43 
     44     def test_join(self):
     45         self.assertEqual(posixpath.join("/foo", "bar", "/bar", "baz"),
     46                          "/bar/baz")
     47         self.assertEqual(posixpath.join("/foo", "bar", "baz"), "/foo/bar/baz")
     48         self.assertEqual(posixpath.join("/foo/", "bar/", "baz/"),
     49                          "/foo/bar/baz/")
     50 
     51         self.assertEqual(posixpath.join(b"/foo", b"bar", b"/bar", b"baz"),
     52                          b"/bar/baz")
     53         self.assertEqual(posixpath.join(b"/foo", b"bar", b"baz"),
     54                          b"/foo/bar/baz")
     55         self.assertEqual(posixpath.join(b"/foo/", b"bar/", b"baz/"),
     56                          b"/foo/bar/baz/")
     57 
     58     def test_split(self):
     59         self.assertEqual(posixpath.split("/foo/bar"), ("/foo", "bar"))
     60         self.assertEqual(posixpath.split("/"), ("/", ""))
     61         self.assertEqual(posixpath.split("foo"), ("", "foo"))
     62         self.assertEqual(posixpath.split("////foo"), ("////", "foo"))
     63         self.assertEqual(posixpath.split("//foo//bar"), ("//foo", "bar"))
     64 
     65         self.assertEqual(posixpath.split(b"/foo/bar"), (b"/foo", b"bar"))
     66         self.assertEqual(posixpath.split(b"/"), (b"/", b""))
     67         self.assertEqual(posixpath.split(b"foo"), (b"", b"foo"))
     68         self.assertEqual(posixpath.split(b"////foo"), (b"////", b"foo"))
     69         self.assertEqual(posixpath.split(b"//foo//bar"), (b"//foo", b"bar"))
     70 
     71     def splitextTest(self, path, filename, ext):
     72         self.assertEqual(posixpath.splitext(path), (filename, ext))
     73         self.assertEqual(posixpath.splitext("/" + path), ("/" + filename, ext))
     74         self.assertEqual(posixpath.splitext("abc/" + path),
     75                          ("abc/" + filename, ext))
     76         self.assertEqual(posixpath.splitext("abc.def/" + path),
     77                          ("abc.def/" + filename, ext))
     78         self.assertEqual(posixpath.splitext("/abc.def/" + path),
     79                          ("/abc.def/" + filename, ext))
     80         self.assertEqual(posixpath.splitext(path + "/"),
     81                          (filename + ext + "/", ""))
     82 
     83         path = bytes(path, "ASCII")
     84         filename = bytes(filename, "ASCII")
     85         ext = bytes(ext, "ASCII")
     86 
     87         self.assertEqual(posixpath.splitext(path), (filename, ext))
     88         self.assertEqual(posixpath.splitext(b"/" + path),
     89                          (b"/" + filename, ext))
     90         self.assertEqual(posixpath.splitext(b"abc/" + path),
     91                          (b"abc/" + filename, ext))
     92         self.assertEqual(posixpath.splitext(b"abc.def/" + path),
     93                          (b"abc.def/" + filename, ext))
     94         self.assertEqual(posixpath.splitext(b"/abc.def/" + path),
     95                          (b"/abc.def/" + filename, ext))
     96         self.assertEqual(posixpath.splitext(path + b"/"),
     97                          (filename + ext + b"/", b""))
     98 
     99     def test_splitext(self):
    100         self.splitextTest("foo.bar", "foo", ".bar")
    101         self.splitextTest("foo.boo.bar", "foo.boo", ".bar")
    102         self.splitextTest("foo.boo.biff.bar", "foo.boo.biff", ".bar")
    103         self.splitextTest(".csh.rc", ".csh", ".rc")
    104         self.splitextTest("nodots", "nodots", "")
    105         self.splitextTest(".cshrc", ".cshrc", "")
    106         self.splitextTest("...manydots", "...manydots", "")
    107         self.splitextTest("...manydots.ext", "...manydots", ".ext")
    108         self.splitextTest(".", ".", "")
    109         self.splitextTest("..", "..", "")
    110         self.splitextTest("........", "........", "")
    111         self.splitextTest("", "", "")
    112 
    113     def test_isabs(self):
    114         self.assertIs(posixpath.isabs(""), False)
    115         self.assertIs(posixpath.isabs("/"), True)
    116         self.assertIs(posixpath.isabs("/foo"), True)
    117         self.assertIs(posixpath.isabs("/foo/bar"), True)
    118         self.assertIs(posixpath.isabs("foo/bar"), False)
    119 
    120         self.assertIs(posixpath.isabs(b""), False)
    121         self.assertIs(posixpath.isabs(b"/"), True)
    122         self.assertIs(posixpath.isabs(b"/foo"), True)
    123         self.assertIs(posixpath.isabs(b"/foo/bar"), True)
    124         self.assertIs(posixpath.isabs(b"foo/bar"), False)
    125 
    126     def test_basename(self):
    127         self.assertEqual(posixpath.basename("/foo/bar"), "bar")
    128         self.assertEqual(posixpath.basename("/"), "")
    129         self.assertEqual(posixpath.basename("foo"), "foo")
    130         self.assertEqual(posixpath.basename("////foo"), "foo")
    131         self.assertEqual(posixpath.basename("//foo//bar"), "bar")
    132 
    133         self.assertEqual(posixpath.basename(b"/foo/bar"), b"bar")
    134         self.assertEqual(posixpath.basename(b"/"), b"")
    135         self.assertEqual(posixpath.basename(b"foo"), b"foo")
    136         self.assertEqual(posixpath.basename(b"////foo"), b"foo")
    137         self.assertEqual(posixpath.basename(b"//foo//bar"), b"bar")
    138 
    139     def test_dirname(self):
    140         self.assertEqual(posixpath.dirname("/foo/bar"), "/foo")
    141         self.assertEqual(posixpath.dirname("/"), "/")
    142         self.assertEqual(posixpath.dirname("foo"), "")
    143         self.assertEqual(posixpath.dirname("////foo"), "////")
    144         self.assertEqual(posixpath.dirname("//foo//bar"), "//foo")
    145 
    146         self.assertEqual(posixpath.dirname(b"/foo/bar"), b"/foo")
    147         self.assertEqual(posixpath.dirname(b"/"), b"/")
    148         self.assertEqual(posixpath.dirname(b"foo"), b"")
    149         self.assertEqual(posixpath.dirname(b"////foo"), b"////")
    150         self.assertEqual(posixpath.dirname(b"//foo//bar"), b"//foo")
    151 
    152     def test_islink(self):
    153         self.assertIs(posixpath.islink(support.TESTFN + "1"), False)
    154         self.assertIs(posixpath.lexists(support.TESTFN + "2"), False)
    155         f = open(support.TESTFN + "1", "wb")
    156         try:
    157             f.write(b"foo")
    158             f.close()
    159             self.assertIs(posixpath.islink(support.TESTFN + "1"), False)
    160             if support.can_symlink():
    161                 os.symlink(support.TESTFN + "1", support.TESTFN + "2")
    162                 self.assertIs(posixpath.islink(support.TESTFN + "2"), True)
    163                 os.remove(support.TESTFN + "1")
    164                 self.assertIs(posixpath.islink(support.TESTFN + "2"), True)
    165                 self.assertIs(posixpath.exists(support.TESTFN + "2"), False)
    166                 self.assertIs(posixpath.lexists(support.TESTFN + "2"), True)
    167         finally:
    168             if not f.close():
    169                 f.close()
    170 
    171     def test_ismount(self):
    172         self.assertIs(posixpath.ismount("/"), True)
    173         with warnings.catch_warnings():
    174             warnings.simplefilter("ignore", DeprecationWarning)
    175             self.assertIs(posixpath.ismount(b"/"), True)
    176 
    177     def test_ismount_non_existent(self):
    178         # Non-existent mountpoint.
    179         self.assertIs(posixpath.ismount(ABSTFN), False)
    180         try:
    181             os.mkdir(ABSTFN)
    182             self.assertIs(posixpath.ismount(ABSTFN), False)
    183         finally:
    184             safe_rmdir(ABSTFN)
    185 
    186     @unittest.skipUnless(support.can_symlink(),
    187                          "Test requires symlink support")
    188     def test_ismount_symlinks(self):
    189         # Symlinks are never mountpoints.
    190         try:
    191             os.symlink("/", ABSTFN)
    192             self.assertIs(posixpath.ismount(ABSTFN), False)
    193         finally:
    194             os.unlink(ABSTFN)
    195 
    196     @unittest.skipIf(posix is None, "Test requires posix module")
    197     def test_ismount_different_device(self):
    198         # Simulate the path being on a different device from its parent by
    199         # mocking out st_dev.
    200         save_lstat = os.lstat
    201         def fake_lstat(path):
    202             st_ino = 0
    203             st_dev = 0
    204             if path == ABSTFN:
    205                 st_dev = 1
    206                 st_ino = 1
    207             return posix.stat_result((0, st_ino, st_dev, 0, 0, 0, 0, 0, 0, 0))
    208         try:
    209             os.lstat = fake_lstat
    210             self.assertIs(posixpath.ismount(ABSTFN), True)
    211         finally:
    212             os.lstat = save_lstat
    213 
    214     @unittest.skipIf(posix is None, "Test requires posix module")
    215     def test_ismount_directory_not_readable(self):
    216         # issue #2466: Simulate ismount run on a directory that is not
    217         # readable, which used to return False.
    218         save_lstat = os.lstat
    219         def fake_lstat(path):
    220             st_ino = 0
    221             st_dev = 0
    222             if path.startswith(ABSTFN) and path != ABSTFN:
    223                 # ismount tries to read something inside the ABSTFN directory;
    224                 # simulate this being forbidden (no read permission).
    225                 raise OSError("Fake [Errno 13] Permission denied")
    226             if path == ABSTFN:
    227                 st_dev = 1
    228                 st_ino = 1
    229             return posix.stat_result((0, st_ino, st_dev, 0, 0, 0, 0, 0, 0, 0))
    230         try:
    231             os.lstat = fake_lstat
    232             self.assertIs(posixpath.ismount(ABSTFN), True)
    233         finally:
    234             os.lstat = save_lstat
    235 
    236     def test_expanduser(self):
    237         self.assertEqual(posixpath.expanduser("foo"), "foo")
    238         self.assertEqual(posixpath.expanduser(b"foo"), b"foo")
    239         with support.EnvironmentVarGuard() as env:
    240             for home in '/', '', '//', '///':
    241                 with self.subTest(home=home):
    242                     env['HOME'] = home
    243                     self.assertEqual(posixpath.expanduser("~"), "/")
    244                     self.assertEqual(posixpath.expanduser("~/"), "/")
    245                     self.assertEqual(posixpath.expanduser("~/foo"), "/foo")
    246         try:
    247             import pwd
    248         except ImportError:
    249             pass
    250         else:
    251             self.assertIsInstance(posixpath.expanduser("~/"), str)
    252             self.assertIsInstance(posixpath.expanduser(b"~/"), bytes)
    253             # if home directory == root directory, this test makes no sense
    254             if posixpath.expanduser("~") != '/':
    255                 self.assertEqual(
    256                     posixpath.expanduser("~") + "/",
    257                     posixpath.expanduser("~/")
    258                 )
    259                 self.assertEqual(
    260                     posixpath.expanduser(b"~") + b"/",
    261                     posixpath.expanduser(b"~/")
    262                 )
    263             self.assertIsInstance(posixpath.expanduser("~root/"), str)
    264             self.assertIsInstance(posixpath.expanduser("~foo/"), str)
    265             self.assertIsInstance(posixpath.expanduser(b"~root/"), bytes)
    266             self.assertIsInstance(posixpath.expanduser(b"~foo/"), bytes)
    267 
    268             with support.EnvironmentVarGuard() as env:
    269                 # expanduser should fall back to using the password database
    270                 del env['HOME']
    271                 home = pwd.getpwuid(os.getuid()).pw_dir
    272                 # $HOME can end with a trailing /, so strip it (see #17809)
    273                 home = home.rstrip("/") or '/'
    274                 self.assertEqual(posixpath.expanduser("~"), home)
    275 
    276     def test_normpath(self):
    277         self.assertEqual(posixpath.normpath(""), ".")
    278         self.assertEqual(posixpath.normpath("/"), "/")
    279         self.assertEqual(posixpath.normpath("//"), "//")
    280         self.assertEqual(posixpath.normpath("///"), "/")
    281         self.assertEqual(posixpath.normpath("///foo/.//bar//"), "/foo/bar")
    282         self.assertEqual(posixpath.normpath("///foo/.//bar//.//..//.//baz"),
    283                          "/foo/baz")
    284         self.assertEqual(posixpath.normpath("///..//./foo/.//bar"), "/foo/bar")
    285 
    286         self.assertEqual(posixpath.normpath(b""), b".")
    287         self.assertEqual(posixpath.normpath(b"/"), b"/")
    288         self.assertEqual(posixpath.normpath(b"//"), b"//")
    289         self.assertEqual(posixpath.normpath(b"///"), b"/")
    290         self.assertEqual(posixpath.normpath(b"///foo/.//bar//"), b"/foo/bar")
    291         self.assertEqual(posixpath.normpath(b"///foo/.//bar//.//..//.//baz"),
    292                          b"/foo/baz")
    293         self.assertEqual(posixpath.normpath(b"///..//./foo/.//bar"),
    294                          b"/foo/bar")
    295 
    296     @skip_if_ABSTFN_contains_backslash
    297     def test_realpath_curdir(self):
    298         self.assertEqual(realpath('.'), os.getcwd())
    299         self.assertEqual(realpath('./.'), os.getcwd())
    300         self.assertEqual(realpath('/'.join(['.'] * 100)), os.getcwd())
    301 
    302         self.assertEqual(realpath(b'.'), os.getcwdb())
    303         self.assertEqual(realpath(b'./.'), os.getcwdb())
    304         self.assertEqual(realpath(b'/'.join([b'.'] * 100)), os.getcwdb())
    305 
    306     @skip_if_ABSTFN_contains_backslash
    307     def test_realpath_pardir(self):
    308         self.assertEqual(realpath('..'), dirname(os.getcwd()))
    309         self.assertEqual(realpath('../..'), dirname(dirname(os.getcwd())))
    310         self.assertEqual(realpath('/'.join(['..'] * 100)), '/')
    311 
    312         self.assertEqual(realpath(b'..'), dirname(os.getcwdb()))
    313         self.assertEqual(realpath(b'../..'), dirname(dirname(os.getcwdb())))
    314         self.assertEqual(realpath(b'/'.join([b'..'] * 100)), b'/')
    315 
    316     @unittest.skipUnless(hasattr(os, "symlink"),
    317                          "Missing symlink implementation")
    318     @skip_if_ABSTFN_contains_backslash
    319     def test_realpath_basic(self):
    320         # Basic operation.
    321         try:
    322             os.symlink(ABSTFN+"1", ABSTFN)
    323             self.assertEqual(realpath(ABSTFN), ABSTFN+"1")
    324         finally:
    325             support.unlink(ABSTFN)
    326 
    327     @unittest.skipUnless(hasattr(os, "symlink"),
    328                          "Missing symlink implementation")
    329     @skip_if_ABSTFN_contains_backslash
    330     def test_realpath_relative(self):
    331         try:
    332             os.symlink(posixpath.relpath(ABSTFN+"1"), ABSTFN)
    333             self.assertEqual(realpath(ABSTFN), ABSTFN+"1")
    334         finally:
    335             support.unlink(ABSTFN)
    336 
    337     @unittest.skipUnless(hasattr(os, "symlink"),
    338                          "Missing symlink implementation")
    339     @skip_if_ABSTFN_contains_backslash
    340     def test_realpath_symlink_loops(self):
    341         # Bug #930024, return the path unchanged if we get into an infinite
    342         # symlink loop.
    343         try:
    344             os.symlink(ABSTFN, ABSTFN)
    345             self.assertEqual(realpath(ABSTFN), ABSTFN)
    346 
    347             os.symlink(ABSTFN+"1", ABSTFN+"2")
    348             os.symlink(ABSTFN+"2", ABSTFN+"1")
    349             self.assertEqual(realpath(ABSTFN+"1"), ABSTFN+"1")
    350             self.assertEqual(realpath(ABSTFN+"2"), ABSTFN+"2")
    351 
    352             self.assertEqual(realpath(ABSTFN+"1/x"), ABSTFN+"1/x")
    353             self.assertEqual(realpath(ABSTFN+"1/.."), dirname(ABSTFN))
    354             self.assertEqual(realpath(ABSTFN+"1/../x"), dirname(ABSTFN) + "/x")
    355             os.symlink(ABSTFN+"x", ABSTFN+"y")
    356             self.assertEqual(realpath(ABSTFN+"1/../" + basename(ABSTFN) + "y"),
    357                              ABSTFN + "y")
    358             self.assertEqual(realpath(ABSTFN+"1/../" + basename(ABSTFN) + "1"),
    359                              ABSTFN + "1")
    360 
    361             os.symlink(basename(ABSTFN) + "a/b", ABSTFN+"a")
    362             self.assertEqual(realpath(ABSTFN+"a"), ABSTFN+"a/b")
    363 
    364             os.symlink("../" + basename(dirname(ABSTFN)) + "/" +
    365                        basename(ABSTFN) + "c", ABSTFN+"c")
    366             self.assertEqual(realpath(ABSTFN+"c"), ABSTFN+"c")
    367 
    368             # Test using relative path as well.
    369             with support.change_cwd(dirname(ABSTFN)):
    370                 self.assertEqual(realpath(basename(ABSTFN)), ABSTFN)
    371         finally:
    372             support.unlink(ABSTFN)
    373             support.unlink(ABSTFN+"1")
    374             support.unlink(ABSTFN+"2")
    375             support.unlink(ABSTFN+"y")
    376             support.unlink(ABSTFN+"c")
    377             support.unlink(ABSTFN+"a")
    378 
    379     @unittest.skipUnless(hasattr(os, "symlink"),
    380                          "Missing symlink implementation")
    381     @skip_if_ABSTFN_contains_backslash
    382     def test_realpath_repeated_indirect_symlinks(self):
    383         # Issue #6975.
    384         try:
    385             os.mkdir(ABSTFN)
    386             os.symlink('../' + basename(ABSTFN), ABSTFN + '/self')
    387             os.symlink('self/self/self', ABSTFN + '/link')
    388             self.assertEqual(realpath(ABSTFN + '/link'), ABSTFN)
    389         finally:
    390             support.unlink(ABSTFN + '/self')
    391             support.unlink(ABSTFN + '/link')
    392             safe_rmdir(ABSTFN)
    393 
    394     @unittest.skipUnless(hasattr(os, "symlink"),
    395                          "Missing symlink implementation")
    396     @skip_if_ABSTFN_contains_backslash
    397     def test_realpath_deep_recursion(self):
    398         depth = 10
    399         try:
    400             os.mkdir(ABSTFN)
    401             for i in range(depth):
    402                 os.symlink('/'.join(['%d' % i] * 10), ABSTFN + '/%d' % (i + 1))
    403             os.symlink('.', ABSTFN + '/0')
    404             self.assertEqual(realpath(ABSTFN + '/%d' % depth), ABSTFN)
    405 
    406             # Test using relative path as well.
    407             with support.change_cwd(ABSTFN):
    408                 self.assertEqual(realpath('%d' % depth), ABSTFN)
    409         finally:
    410             for i in range(depth + 1):
    411                 support.unlink(ABSTFN + '/%d' % i)
    412             safe_rmdir(ABSTFN)
    413 
    414     @unittest.skipUnless(hasattr(os, "symlink"),
    415                          "Missing symlink implementation")
    416     @skip_if_ABSTFN_contains_backslash
    417     def test_realpath_resolve_parents(self):
    418         # We also need to resolve any symlinks in the parents of a relative
    419         # path passed to realpath. E.g.: current working directory is
    420         # /usr/doc with 'doc' being a symlink to /usr/share/doc. We call
    421         # realpath("a"). This should return /usr/share/doc/a/.
    422         try:
    423             os.mkdir(ABSTFN)
    424             os.mkdir(ABSTFN + "/y")
    425             os.symlink(ABSTFN + "/y", ABSTFN + "/k")
    426 
    427             with support.change_cwd(ABSTFN + "/k"):
    428                 self.assertEqual(realpath("a"), ABSTFN + "/y/a")
    429         finally:
    430             support.unlink(ABSTFN + "/k")
    431             safe_rmdir(ABSTFN + "/y")
    432             safe_rmdir(ABSTFN)
    433 
    434     @unittest.skipUnless(hasattr(os, "symlink"),
    435                          "Missing symlink implementation")
    436     @skip_if_ABSTFN_contains_backslash
    437     def test_realpath_resolve_before_normalizing(self):
    438         # Bug #990669: Symbolic links should be resolved before we
    439         # normalize the path. E.g.: if we have directories 'a', 'k' and 'y'
    440         # in the following hierarchy:
    441         # a/k/y
    442         #
    443         # and a symbolic link 'link-y' pointing to 'y' in directory 'a',
    444         # then realpath("link-y/..") should return 'k', not 'a'.
    445         try:
    446             os.mkdir(ABSTFN)
    447             os.mkdir(ABSTFN + "/k")
    448             os.mkdir(ABSTFN + "/k/y")
    449             os.symlink(ABSTFN + "/k/y", ABSTFN + "/link-y")
    450 
    451             # Absolute path.
    452             self.assertEqual(realpath(ABSTFN + "/link-y/.."), ABSTFN + "/k")
    453             # Relative path.
    454             with support.change_cwd(dirname(ABSTFN)):
    455                 self.assertEqual(realpath(basename(ABSTFN) + "/link-y/.."),
    456                                  ABSTFN + "/k")
    457         finally:
    458             support.unlink(ABSTFN + "/link-y")
    459             safe_rmdir(ABSTFN + "/k/y")
    460             safe_rmdir(ABSTFN + "/k")
    461             safe_rmdir(ABSTFN)
    462 
    463     @unittest.skipUnless(hasattr(os, "symlink"),
    464                          "Missing symlink implementation")
    465     @skip_if_ABSTFN_contains_backslash
    466     def test_realpath_resolve_first(self):
    467         # Bug #1213894: The first component of the path, if not absolute,
    468         # must be resolved too.
    469 
    470         try:
    471             os.mkdir(ABSTFN)
    472             os.mkdir(ABSTFN + "/k")
    473             os.symlink(ABSTFN, ABSTFN + "link")
    474             with support.change_cwd(dirname(ABSTFN)):
    475                 base = basename(ABSTFN)
    476                 self.assertEqual(realpath(base + "link"), ABSTFN)
    477                 self.assertEqual(realpath(base + "link/k"), ABSTFN + "/k")
    478         finally:
    479             support.unlink(ABSTFN + "link")
    480             safe_rmdir(ABSTFN + "/k")
    481             safe_rmdir(ABSTFN)
    482 
    483     def test_relpath(self):
    484         (real_getcwd, os.getcwd) = (os.getcwd, lambda: r"/home/user/bar")
    485         try:
    486             curdir = os.path.split(os.getcwd())[-1]
    487             self.assertRaises(ValueError, posixpath.relpath, "")
    488             self.assertEqual(posixpath.relpath("a"), "a")
    489             self.assertEqual(posixpath.relpath(posixpath.abspath("a")), "a")
    490             self.assertEqual(posixpath.relpath("a/b"), "a/b")
    491             self.assertEqual(posixpath.relpath("../a/b"), "../a/b")
    492             self.assertEqual(posixpath.relpath("a", "../b"), "../"+curdir+"/a")
    493             self.assertEqual(posixpath.relpath("a/b", "../c"),
    494                              "../"+curdir+"/a/b")
    495             self.assertEqual(posixpath.relpath("a", "b/c"), "../../a")
    496             self.assertEqual(posixpath.relpath("a", "a"), ".")
    497             self.assertEqual(posixpath.relpath("/foo/bar/bat", "/x/y/z"), '../../../foo/bar/bat')
    498             self.assertEqual(posixpath.relpath("/foo/bar/bat", "/foo/bar"), 'bat')
    499             self.assertEqual(posixpath.relpath("/foo/bar/bat", "/"), 'foo/bar/bat')
    500             self.assertEqual(posixpath.relpath("/", "/foo/bar/bat"), '../../..')
    501             self.assertEqual(posixpath.relpath("/foo/bar/bat", "/x"), '../foo/bar/bat')
    502             self.assertEqual(posixpath.relpath("/x", "/foo/bar/bat"), '../../../x')
    503             self.assertEqual(posixpath.relpath("/", "/"), '.')
    504             self.assertEqual(posixpath.relpath("/a", "/a"), '.')
    505             self.assertEqual(posixpath.relpath("/a/b", "/a/b"), '.')
    506         finally:
    507             os.getcwd = real_getcwd
    508 
    509     def test_relpath_bytes(self):
    510         (real_getcwdb, os.getcwdb) = (os.getcwdb, lambda: br"/home/user/bar")
    511         try:
    512             curdir = os.path.split(os.getcwdb())[-1]
    513             self.assertRaises(ValueError, posixpath.relpath, b"")
    514             self.assertEqual(posixpath.relpath(b"a"), b"a")
    515             self.assertEqual(posixpath.relpath(posixpath.abspath(b"a")), b"a")
    516             self.assertEqual(posixpath.relpath(b"a/b"), b"a/b")
    517             self.assertEqual(posixpath.relpath(b"../a/b"), b"../a/b")
    518             self.assertEqual(posixpath.relpath(b"a", b"../b"),
    519                              b"../"+curdir+b"/a")
    520             self.assertEqual(posixpath.relpath(b"a/b", b"../c"),
    521                              b"../"+curdir+b"/a/b")
    522             self.assertEqual(posixpath.relpath(b"a", b"b/c"), b"../../a")
    523             self.assertEqual(posixpath.relpath(b"a", b"a"), b".")
    524             self.assertEqual(posixpath.relpath(b"/foo/bar/bat", b"/x/y/z"), b'../../../foo/bar/bat')
    525             self.assertEqual(posixpath.relpath(b"/foo/bar/bat", b"/foo/bar"), b'bat')
    526             self.assertEqual(posixpath.relpath(b"/foo/bar/bat", b"/"), b'foo/bar/bat')
    527             self.assertEqual(posixpath.relpath(b"/", b"/foo/bar/bat"), b'../../..')
    528             self.assertEqual(posixpath.relpath(b"/foo/bar/bat", b"/x"), b'../foo/bar/bat')
    529             self.assertEqual(posixpath.relpath(b"/x", b"/foo/bar/bat"), b'../../../x')
    530             self.assertEqual(posixpath.relpath(b"/", b"/"), b'.')
    531             self.assertEqual(posixpath.relpath(b"/a", b"/a"), b'.')
    532             self.assertEqual(posixpath.relpath(b"/a/b", b"/a/b"), b'.')
    533 
    534             self.assertRaises(TypeError, posixpath.relpath, b"bytes", "str")
    535             self.assertRaises(TypeError, posixpath.relpath, "str", b"bytes")
    536         finally:
    537             os.getcwdb = real_getcwdb
    538 
    539     def test_commonpath(self):
    540         def check(paths, expected):
    541             self.assertEqual(posixpath.commonpath(paths), expected)
    542             self.assertEqual(posixpath.commonpath([os.fsencode(p) for p in paths]),
    543                              os.fsencode(expected))
    544         def check_error(exc, paths):
    545             self.assertRaises(exc, posixpath.commonpath, paths)
    546             self.assertRaises(exc, posixpath.commonpath,
    547                               [os.fsencode(p) for p in paths])
    548 
    549         self.assertRaises(ValueError, posixpath.commonpath, [])
    550         check_error(ValueError, ['/usr', 'usr'])
    551         check_error(ValueError, ['usr', '/usr'])
    552 
    553         check(['/usr/local'], '/usr/local')
    554         check(['/usr/local', '/usr/local'], '/usr/local')
    555         check(['/usr/local/', '/usr/local'], '/usr/local')
    556         check(['/usr/local/', '/usr/local/'], '/usr/local')
    557         check(['/usr//local', '//usr/local'], '/usr/local')
    558         check(['/usr/./local', '/./usr/local'], '/usr/local')
    559         check(['/', '/dev'], '/')
    560         check(['/usr', '/dev'], '/')
    561         check(['/usr/lib/', '/usr/lib/python3'], '/usr/lib')
    562         check(['/usr/lib/', '/usr/lib64/'], '/usr')
    563 
    564         check(['/usr/lib', '/usr/lib64'], '/usr')
    565         check(['/usr/lib/', '/usr/lib64'], '/usr')
    566 
    567         check(['spam'], 'spam')
    568         check(['spam', 'spam'], 'spam')
    569         check(['spam', 'alot'], '')
    570         check(['and/jam', 'and/spam'], 'and')
    571         check(['and//jam', 'and/spam//'], 'and')
    572         check(['and/./jam', './and/spam'], 'and')
    573         check(['and/jam', 'and/spam', 'alot'], '')
    574         check(['and/jam', 'and/spam', 'and'], 'and')
    575 
    576         check([''], '')
    577         check(['', 'spam/alot'], '')
    578         check_error(ValueError, ['', '/spam/alot'])
    579 
    580         self.assertRaises(TypeError, posixpath.commonpath,
    581                           [b'/usr/lib/', '/usr/lib/python3'])
    582         self.assertRaises(TypeError, posixpath.commonpath,
    583                           [b'/usr/lib/', 'usr/lib/python3'])
    584         self.assertRaises(TypeError, posixpath.commonpath,
    585                           [b'usr/lib/', '/usr/lib/python3'])
    586         self.assertRaises(TypeError, posixpath.commonpath,
    587                           ['/usr/lib/', b'/usr/lib/python3'])
    588         self.assertRaises(TypeError, posixpath.commonpath,
    589                           ['/usr/lib/', b'usr/lib/python3'])
    590         self.assertRaises(TypeError, posixpath.commonpath,
    591                           ['usr/lib/', b'/usr/lib/python3'])
    592 
    593 
    594 class PosixCommonTest(test_genericpath.CommonTest, unittest.TestCase):
    595     pathmodule = posixpath
    596     attributes = ['relpath', 'samefile', 'sameopenfile', 'samestat']
    597 
    598 
    599 class PathLikeTests(unittest.TestCase):
    600 
    601     path = posixpath
    602 
    603     class PathLike:
    604         def __init__(self, path=''):
    605             self.path = path
    606         def __fspath__(self):
    607             if isinstance(self.path, BaseException):
    608                 raise self.path
    609             else:
    610                 return self.path
    611 
    612     def setUp(self):
    613         self.file_name = support.TESTFN.lower()
    614         self.file_path = self.PathLike(support.TESTFN)
    615         self.addCleanup(support.unlink, self.file_name)
    616         with open(self.file_name, 'xb', 0) as file:
    617             file.write(b"test_posixpath.PathLikeTests")
    618 
    619     def assertPathEqual(self, func):
    620         self.assertEqual(func(self.file_path), func(self.file_name))
    621 
    622     def test_path_normcase(self):
    623         self.assertPathEqual(self.path.normcase)
    624 
    625     def test_path_isabs(self):
    626         self.assertPathEqual(self.path.isabs)
    627 
    628     def test_path_join(self):
    629         self.assertEqual(self.path.join('a', self.PathLike('b'), 'c'),
    630                          self.path.join('a', 'b', 'c'))
    631 
    632     def test_path_split(self):
    633         self.assertPathEqual(self.path.split)
    634 
    635     def test_path_splitext(self):
    636         self.assertPathEqual(self.path.splitext)
    637 
    638     def test_path_splitdrive(self):
    639         self.assertPathEqual(self.path.splitdrive)
    640 
    641     def test_path_basename(self):
    642         self.assertPathEqual(self.path.basename)
    643 
    644     def test_path_dirname(self):
    645         self.assertPathEqual(self.path.dirname)
    646 
    647     def test_path_islink(self):
    648         self.assertPathEqual(self.path.islink)
    649 
    650     def test_path_lexists(self):
    651         self.assertPathEqual(self.path.lexists)
    652 
    653     def test_path_ismount(self):
    654         self.assertPathEqual(self.path.ismount)
    655 
    656     def test_path_expanduser(self):
    657         self.assertPathEqual(self.path.expanduser)
    658 
    659     def test_path_expandvars(self):
    660         self.assertPathEqual(self.path.expandvars)
    661 
    662     def test_path_normpath(self):
    663         self.assertPathEqual(self.path.normpath)
    664 
    665     def test_path_abspath(self):
    666         self.assertPathEqual(self.path.abspath)
    667 
    668     def test_path_realpath(self):
    669         self.assertPathEqual(self.path.realpath)
    670 
    671     def test_path_relpath(self):
    672         self.assertPathEqual(self.path.relpath)
    673 
    674     def test_path_commonpath(self):
    675         common_path = self.path.commonpath([self.file_path, self.file_name])
    676         self.assertEqual(common_path, self.file_name)
    677 
    678 
    679 if __name__=="__main__":
    680     unittest.main()
    681