python (3.11.7)

(root)/
lib/
python3.11/
test/
test_ntpath.py
       1  import ntpath
       2  import os
       3  import string
       4  import sys
       5  import unittest
       6  import warnings
       7  from test.support import os_helper
       8  from test.support import TestFailed, is_emscripten
       9  from test.support.os_helper import FakePath
      10  from test import test_genericpath
      11  from tempfile import TemporaryFile
      12  
      13  
      14  try:
      15      import nt
      16  except ImportError:
      17      # Most tests can complete without the nt module,
      18      # but for those that require it we import here.
      19      nt = None
      20  
      21  try:
      22      ntpath._getfinalpathname
      23  except AttributeError:
      24      HAVE_GETFINALPATHNAME = False
      25  else:
      26      HAVE_GETFINALPATHNAME = True
      27  
      28  try:
      29      import ctypes
      30  except ImportError:
      31      HAVE_GETSHORTPATHNAME = False
      32  else:
      33      HAVE_GETSHORTPATHNAME = True
      34      def _getshortpathname(path):
      35          GSPN = ctypes.WinDLL("kernel32", use_last_error=True).GetShortPathNameW
      36          GSPN.argtypes = [ctypes.c_wchar_p, ctypes.c_wchar_p, ctypes.c_uint32]
      37          GSPN.restype = ctypes.c_uint32
      38          result_len = GSPN(path, None, 0)
      39          if not result_len:
      40              raise OSError("failed to get short path name 0x{:08X}"
      41                            .format(ctypes.get_last_error()))
      42          result = ctypes.create_unicode_buffer(result_len)
      43          result_len = GSPN(path, result, result_len)
      44          return result[:result_len]
      45  
      46  def _norm(path):
      47      if isinstance(path, (bytes, str, os.PathLike)):
      48          return ntpath.normcase(os.fsdecode(path))
      49      elif hasattr(path, "__iter__"):
      50          return tuple(ntpath.normcase(os.fsdecode(p)) for p in path)
      51      return path
      52  
      53  
      54  def tester(fn, wantResult):
      55      fn = fn.replace("\\", "\\\\")
      56      gotResult = eval(fn)
      57      if wantResult != gotResult and _norm(wantResult) != _norm(gotResult):
      58          raise TestFailed("%s should return: %s but returned: %s" \
      59                %(str(fn), str(wantResult), str(gotResult)))
      60  
      61      # then with bytes
      62      fn = fn.replace("('", "(b'")
      63      fn = fn.replace('("', '(b"')
      64      fn = fn.replace("['", "[b'")
      65      fn = fn.replace('["', '[b"')
      66      fn = fn.replace(", '", ", b'")
      67      fn = fn.replace(', "', ', b"')
      68      fn = os.fsencode(fn).decode('latin1')
      69      fn = fn.encode('ascii', 'backslashreplace').decode('ascii')
      70      with warnings.catch_warnings():
      71          warnings.simplefilter("ignore", DeprecationWarning)
      72          gotResult = eval(fn)
      73      if _norm(wantResult) != _norm(gotResult):
      74          raise TestFailed("%s should return: %s but returned: %s" \
      75                %(str(fn), str(wantResult), repr(gotResult)))
      76  
      77  
      78  class ESC[4;38;5;81mNtpathTestCase(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
      79      def assertPathEqual(self, path1, path2):
      80          if path1 == path2 or _norm(path1) == _norm(path2):
      81              return
      82          self.assertEqual(path1, path2)
      83  
      84      def assertPathIn(self, path, pathset):
      85          self.assertIn(_norm(path), _norm(pathset))
      86  
      87  
      88  class ESC[4;38;5;81mTestNtpath(ESC[4;38;5;149mNtpathTestCase):
      89      def test_splitext(self):
      90          tester('ntpath.splitext("foo.ext")', ('foo', '.ext'))
      91          tester('ntpath.splitext("/foo/foo.ext")', ('/foo/foo', '.ext'))
      92          tester('ntpath.splitext(".ext")', ('.ext', ''))
      93          tester('ntpath.splitext("\\foo.ext\\foo")', ('\\foo.ext\\foo', ''))
      94          tester('ntpath.splitext("foo.ext\\")', ('foo.ext\\', ''))
      95          tester('ntpath.splitext("")', ('', ''))
      96          tester('ntpath.splitext("foo.bar.ext")', ('foo.bar', '.ext'))
      97          tester('ntpath.splitext("xx/foo.bar.ext")', ('xx/foo.bar', '.ext'))
      98          tester('ntpath.splitext("xx\\foo.bar.ext")', ('xx\\foo.bar', '.ext'))
      99          tester('ntpath.splitext("c:a/b\\c.d")', ('c:a/b\\c', '.d'))
     100  
     101      def test_splitdrive(self):
     102          tester('ntpath.splitdrive("c:\\foo\\bar")',
     103                 ('c:', '\\foo\\bar'))
     104          tester('ntpath.splitdrive("c:/foo/bar")',
     105                 ('c:', '/foo/bar'))
     106          tester('ntpath.splitdrive("\\\\conky\\mountpoint\\foo\\bar")',
     107                 ('\\\\conky\\mountpoint', '\\foo\\bar'))
     108          tester('ntpath.splitdrive("//conky/mountpoint/foo/bar")',
     109                 ('//conky/mountpoint', '/foo/bar'))
     110          tester('ntpath.splitdrive("\\\\\\conky\\mountpoint\\foo\\bar")',
     111              ('\\\\\\conky', '\\mountpoint\\foo\\bar'))
     112          tester('ntpath.splitdrive("///conky/mountpoint/foo/bar")',
     113              ('///conky', '/mountpoint/foo/bar'))
     114          tester('ntpath.splitdrive("\\\\conky\\\\mountpoint\\foo\\bar")',
     115                 ('\\\\conky\\', '\\mountpoint\\foo\\bar'))
     116          tester('ntpath.splitdrive("//conky//mountpoint/foo/bar")',
     117                 ('//conky/', '/mountpoint/foo/bar'))
     118          # Issue #19911: UNC part containing U+0130
     119          self.assertEqual(ntpath.splitdrive('//conky/MOUNTPOİNT/foo/bar'),
     120                           ('//conky/MOUNTPOİNT', '/foo/bar'))
     121  
     122          # gh-81790: support device namespace, including UNC drives.
     123          tester('ntpath.splitdrive("//?/c:")', ("//?/c:", ""))
     124          tester('ntpath.splitdrive("//?/c:/")', ("//?/c:", "/"))
     125          tester('ntpath.splitdrive("//?/c:/dir")', ("//?/c:", "/dir"))
     126          tester('ntpath.splitdrive("//?/UNC")', ("//?/UNC", ""))
     127          tester('ntpath.splitdrive("//?/UNC/")', ("//?/UNC/", ""))
     128          tester('ntpath.splitdrive("//?/UNC/server/")', ("//?/UNC/server/", ""))
     129          tester('ntpath.splitdrive("//?/UNC/server/share")', ("//?/UNC/server/share", ""))
     130          tester('ntpath.splitdrive("//?/UNC/server/share/dir")', ("//?/UNC/server/share", "/dir"))
     131          tester('ntpath.splitdrive("//?/VOLUME{00000000-0000-0000-0000-000000000000}/spam")',
     132                 ('//?/VOLUME{00000000-0000-0000-0000-000000000000}', '/spam'))
     133          tester('ntpath.splitdrive("//?/BootPartition/")', ("//?/BootPartition", "/"))
     134  
     135          tester('ntpath.splitdrive("\\\\?\\c:")', ("\\\\?\\c:", ""))
     136          tester('ntpath.splitdrive("\\\\?\\c:\\")', ("\\\\?\\c:", "\\"))
     137          tester('ntpath.splitdrive("\\\\?\\c:\\dir")', ("\\\\?\\c:", "\\dir"))
     138          tester('ntpath.splitdrive("\\\\?\\UNC")', ("\\\\?\\UNC", ""))
     139          tester('ntpath.splitdrive("\\\\?\\UNC\\")', ("\\\\?\\UNC\\", ""))
     140          tester('ntpath.splitdrive("\\\\?\\UNC\\server\\")', ("\\\\?\\UNC\\server\\", ""))
     141          tester('ntpath.splitdrive("\\\\?\\UNC\\server\\share")', ("\\\\?\\UNC\\server\\share", ""))
     142          tester('ntpath.splitdrive("\\\\?\\UNC\\server\\share\\dir")',
     143                 ("\\\\?\\UNC\\server\\share", "\\dir"))
     144          tester('ntpath.splitdrive("\\\\?\\VOLUME{00000000-0000-0000-0000-000000000000}\\spam")',
     145                 ('\\\\?\\VOLUME{00000000-0000-0000-0000-000000000000}', '\\spam'))
     146          tester('ntpath.splitdrive("\\\\?\\BootPartition\\")', ("\\\\?\\BootPartition", "\\"))
     147  
     148          # gh-96290: support partial/invalid UNC drives
     149          tester('ntpath.splitdrive("//")', ("//", ""))  # empty server & missing share
     150          tester('ntpath.splitdrive("///")', ("///", ""))  # empty server & empty share
     151          tester('ntpath.splitdrive("///y")', ("///y", ""))  # empty server & non-empty share
     152          tester('ntpath.splitdrive("//x")', ("//x", ""))  # non-empty server & missing share
     153          tester('ntpath.splitdrive("//x/")', ("//x/", ""))  # non-empty server & empty share
     154  
     155      def test_split(self):
     156          tester('ntpath.split("c:\\foo\\bar")', ('c:\\foo', 'bar'))
     157          tester('ntpath.split("\\\\conky\\mountpoint\\foo\\bar")',
     158                 ('\\\\conky\\mountpoint\\foo', 'bar'))
     159  
     160          tester('ntpath.split("c:\\")', ('c:\\', ''))
     161          tester('ntpath.split("\\\\conky\\mountpoint\\")',
     162                 ('\\\\conky\\mountpoint\\', ''))
     163  
     164          tester('ntpath.split("c:/")', ('c:/', ''))
     165          tester('ntpath.split("//conky/mountpoint/")', ('//conky/mountpoint/', ''))
     166  
     167      def test_isabs(self):
     168          tester('ntpath.isabs("c:\\")', 1)
     169          tester('ntpath.isabs("\\\\conky\\mountpoint\\")', 1)
     170          tester('ntpath.isabs("\\foo")', 1)
     171          tester('ntpath.isabs("\\foo\\bar")', 1)
     172  
     173          # gh-96290: normal UNC paths and device paths without trailing backslashes
     174          tester('ntpath.isabs("\\\\conky\\mountpoint")', 1)
     175          tester('ntpath.isabs("\\\\.\\C:")', 1)
     176  
     177      def test_commonprefix(self):
     178          tester('ntpath.commonprefix(["/home/swenson/spam", "/home/swen/spam"])',
     179                 "/home/swen")
     180          tester('ntpath.commonprefix(["\\home\\swen\\spam", "\\home\\swen\\eggs"])',
     181                 "\\home\\swen\\")
     182          tester('ntpath.commonprefix(["/home/swen/spam", "/home/swen/spam"])',
     183                 "/home/swen/spam")
     184  
     185      def test_join(self):
     186          tester('ntpath.join("")', '')
     187          tester('ntpath.join("", "", "")', '')
     188          tester('ntpath.join("a")', 'a')
     189          tester('ntpath.join("/a")', '/a')
     190          tester('ntpath.join("\\a")', '\\a')
     191          tester('ntpath.join("a:")', 'a:')
     192          tester('ntpath.join("a:", "\\b")', 'a:\\b')
     193          tester('ntpath.join("a", "\\b")', '\\b')
     194          tester('ntpath.join("a", "b", "c")', 'a\\b\\c')
     195          tester('ntpath.join("a\\", "b", "c")', 'a\\b\\c')
     196          tester('ntpath.join("a", "b\\", "c")', 'a\\b\\c')
     197          tester('ntpath.join("a", "b", "\\c")', '\\c')
     198          tester('ntpath.join("d:\\", "\\pleep")', 'd:\\pleep')
     199          tester('ntpath.join("d:\\", "a", "b")', 'd:\\a\\b')
     200  
     201          tester("ntpath.join('', 'a')", 'a')
     202          tester("ntpath.join('', '', '', '', 'a')", 'a')
     203          tester("ntpath.join('a', '')", 'a\\')
     204          tester("ntpath.join('a', '', '', '', '')", 'a\\')
     205          tester("ntpath.join('a\\', '')", 'a\\')
     206          tester("ntpath.join('a\\', '', '', '', '')", 'a\\')
     207          tester("ntpath.join('a/', '')", 'a/')
     208  
     209          tester("ntpath.join('a/b', 'x/y')", 'a/b\\x/y')
     210          tester("ntpath.join('/a/b', 'x/y')", '/a/b\\x/y')
     211          tester("ntpath.join('/a/b/', 'x/y')", '/a/b/x/y')
     212          tester("ntpath.join('c:', 'x/y')", 'c:x/y')
     213          tester("ntpath.join('c:a/b', 'x/y')", 'c:a/b\\x/y')
     214          tester("ntpath.join('c:a/b/', 'x/y')", 'c:a/b/x/y')
     215          tester("ntpath.join('c:/', 'x/y')", 'c:/x/y')
     216          tester("ntpath.join('c:/a/b', 'x/y')", 'c:/a/b\\x/y')
     217          tester("ntpath.join('c:/a/b/', 'x/y')", 'c:/a/b/x/y')
     218          tester("ntpath.join('//computer/share', 'x/y')", '//computer/share\\x/y')
     219          tester("ntpath.join('//computer/share/', 'x/y')", '//computer/share/x/y')
     220          tester("ntpath.join('//computer/share/a/b', 'x/y')", '//computer/share/a/b\\x/y')
     221  
     222          tester("ntpath.join('a/b', '/x/y')", '/x/y')
     223          tester("ntpath.join('/a/b', '/x/y')", '/x/y')
     224          tester("ntpath.join('c:', '/x/y')", 'c:/x/y')
     225          tester("ntpath.join('c:a/b', '/x/y')", 'c:/x/y')
     226          tester("ntpath.join('c:/', '/x/y')", 'c:/x/y')
     227          tester("ntpath.join('c:/a/b', '/x/y')", 'c:/x/y')
     228          tester("ntpath.join('//computer/share', '/x/y')", '//computer/share/x/y')
     229          tester("ntpath.join('//computer/share/', '/x/y')", '//computer/share/x/y')
     230          tester("ntpath.join('//computer/share/a', '/x/y')", '//computer/share/x/y')
     231  
     232          tester("ntpath.join('c:', 'C:x/y')", 'C:x/y')
     233          tester("ntpath.join('c:a/b', 'C:x/y')", 'C:a/b\\x/y')
     234          tester("ntpath.join('c:/', 'C:x/y')", 'C:/x/y')
     235          tester("ntpath.join('c:/a/b', 'C:x/y')", 'C:/a/b\\x/y')
     236  
     237          for x in ('', 'a/b', '/a/b', 'c:', 'c:a/b', 'c:/', 'c:/a/b',
     238                    '//computer/share', '//computer/share/', '//computer/share/a/b'):
     239              for y in ('d:', 'd:x/y', 'd:/', 'd:/x/y',
     240                        '//machine/common', '//machine/common/', '//machine/common/x/y'):
     241                  tester("ntpath.join(%r, %r)" % (x, y), y)
     242  
     243          tester("ntpath.join('\\\\computer\\share\\', 'a', 'b')", '\\\\computer\\share\\a\\b')
     244          tester("ntpath.join('\\\\computer\\share', 'a', 'b')", '\\\\computer\\share\\a\\b')
     245          tester("ntpath.join('\\\\computer\\share', 'a\\b')", '\\\\computer\\share\\a\\b')
     246          tester("ntpath.join('//computer/share/', 'a', 'b')", '//computer/share/a\\b')
     247          tester("ntpath.join('//computer/share', 'a', 'b')", '//computer/share\\a\\b')
     248          tester("ntpath.join('//computer/share', 'a/b')", '//computer/share\\a/b')
     249  
     250      def test_normpath(self):
     251          tester("ntpath.normpath('A//////././//.//B')", r'A\B')
     252          tester("ntpath.normpath('A/./B')", r'A\B')
     253          tester("ntpath.normpath('A/foo/../B')", r'A\B')
     254          tester("ntpath.normpath('C:A//B')", r'C:A\B')
     255          tester("ntpath.normpath('D:A/./B')", r'D:A\B')
     256          tester("ntpath.normpath('e:A/foo/../B')", r'e:A\B')
     257  
     258          tester("ntpath.normpath('C:///A//B')", r'C:\A\B')
     259          tester("ntpath.normpath('D:///A/./B')", r'D:\A\B')
     260          tester("ntpath.normpath('e:///A/foo/../B')", r'e:\A\B')
     261  
     262          tester("ntpath.normpath('..')", r'..')
     263          tester("ntpath.normpath('.')", r'.')
     264          tester("ntpath.normpath('')", r'.')
     265          tester("ntpath.normpath('/')", '\\')
     266          tester("ntpath.normpath('c:/')", 'c:\\')
     267          tester("ntpath.normpath('/../.././..')", '\\')
     268          tester("ntpath.normpath('c:/../../..')", 'c:\\')
     269          tester("ntpath.normpath('../.././..')", r'..\..\..')
     270          tester("ntpath.normpath('K:../.././..')", r'K:..\..\..')
     271          tester("ntpath.normpath('C:////a/b')", r'C:\a\b')
     272          tester("ntpath.normpath('//machine/share//a/b')", r'\\machine\share\a\b')
     273  
     274          tester("ntpath.normpath('\\\\.\\NUL')", r'\\.\NUL')
     275          tester("ntpath.normpath('\\\\?\\D:/XY\\Z')", r'\\?\D:/XY\Z')
     276          tester("ntpath.normpath('handbook/../../Tests/image.png')", r'..\Tests\image.png')
     277          tester("ntpath.normpath('handbook/../../../Tests/image.png')", r'..\..\Tests\image.png')
     278          tester("ntpath.normpath('handbook///../a/.././../b/c')", r'..\b\c')
     279          tester("ntpath.normpath('handbook/a/../..///../../b/c')", r'..\..\b\c')
     280  
     281          tester("ntpath.normpath('//server/share/..')" ,    '\\\\server\\share\\')
     282          tester("ntpath.normpath('//server/share/../')" ,   '\\\\server\\share\\')
     283          tester("ntpath.normpath('//server/share/../..')",  '\\\\server\\share\\')
     284          tester("ntpath.normpath('//server/share/../../')", '\\\\server\\share\\')
     285  
     286          # gh-96290: don't normalize partial/invalid UNC drives as rooted paths.
     287          tester("ntpath.normpath('\\\\foo\\\\')", '\\\\foo\\\\')
     288          tester("ntpath.normpath('\\\\foo\\')", '\\\\foo\\')
     289          tester("ntpath.normpath('\\\\foo')", '\\\\foo')
     290          tester("ntpath.normpath('\\\\')", '\\\\')
     291  
     292      def test_realpath_curdir(self):
     293          expected = ntpath.normpath(os.getcwd())
     294          tester("ntpath.realpath('.')", expected)
     295          tester("ntpath.realpath('./.')", expected)
     296          tester("ntpath.realpath('/'.join(['.'] * 100))", expected)
     297          tester("ntpath.realpath('.\\.')", expected)
     298          tester("ntpath.realpath('\\'.join(['.'] * 100))", expected)
     299  
     300      def test_realpath_pardir(self):
     301          expected = ntpath.normpath(os.getcwd())
     302          tester("ntpath.realpath('..')", ntpath.dirname(expected))
     303          tester("ntpath.realpath('../..')",
     304                 ntpath.dirname(ntpath.dirname(expected)))
     305          tester("ntpath.realpath('/'.join(['..'] * 50))",
     306                 ntpath.splitdrive(expected)[0] + '\\')
     307          tester("ntpath.realpath('..\\..')",
     308                 ntpath.dirname(ntpath.dirname(expected)))
     309          tester("ntpath.realpath('\\'.join(['..'] * 50))",
     310                 ntpath.splitdrive(expected)[0] + '\\')
     311  
     312      @os_helper.skip_unless_symlink
     313      @unittest.skipUnless(HAVE_GETFINALPATHNAME, 'need _getfinalpathname')
     314      def test_realpath_basic(self):
     315          ABSTFN = ntpath.abspath(os_helper.TESTFN)
     316          open(ABSTFN, "wb").close()
     317          self.addCleanup(os_helper.unlink, ABSTFN)
     318          self.addCleanup(os_helper.unlink, ABSTFN + "1")
     319  
     320          os.symlink(ABSTFN, ABSTFN + "1")
     321          self.assertPathEqual(ntpath.realpath(ABSTFN + "1"), ABSTFN)
     322          self.assertPathEqual(ntpath.realpath(os.fsencode(ABSTFN + "1")),
     323                           os.fsencode(ABSTFN))
     324  
     325          # gh-88013: call ntpath.realpath with binary drive name may raise a
     326          # TypeError. The drive should not exist to reproduce the bug.
     327          for c in string.ascii_uppercase:
     328              d = f"{c}:\\"
     329              if not ntpath.exists(d):
     330                  break
     331          else:
     332              raise OSError("No free drive letters available")
     333          self.assertEqual(ntpath.realpath(d), d)
     334  
     335          # gh-106242: Embedded nulls and non-strict fallback to abspath
     336          self.assertEqual(ABSTFN + "\0spam",
     337                           ntpath.realpath(os_helper.TESTFN + "\0spam", strict=False))
     338  
     339      @os_helper.skip_unless_symlink
     340      @unittest.skipUnless(HAVE_GETFINALPATHNAME, 'need _getfinalpathname')
     341      def test_realpath_strict(self):
     342          # Bug #43757: raise FileNotFoundError in strict mode if we encounter
     343          # a path that does not exist.
     344          ABSTFN = ntpath.abspath(os_helper.TESTFN)
     345          os.symlink(ABSTFN + "1", ABSTFN)
     346          self.addCleanup(os_helper.unlink, ABSTFN)
     347          self.assertRaises(FileNotFoundError, ntpath.realpath, ABSTFN, strict=True)
     348          self.assertRaises(FileNotFoundError, ntpath.realpath, ABSTFN + "2", strict=True)
     349          # gh-106242: Embedded nulls should raise OSError (not ValueError)
     350          self.assertRaises(OSError, ntpath.realpath, ABSTFN + "\0spam", strict=True)
     351  
     352      @os_helper.skip_unless_symlink
     353      @unittest.skipUnless(HAVE_GETFINALPATHNAME, 'need _getfinalpathname')
     354      def test_realpath_relative(self):
     355          ABSTFN = ntpath.abspath(os_helper.TESTFN)
     356          open(ABSTFN, "wb").close()
     357          self.addCleanup(os_helper.unlink, ABSTFN)
     358          self.addCleanup(os_helper.unlink, ABSTFN + "1")
     359  
     360          os.symlink(ABSTFN, ntpath.relpath(ABSTFN + "1"))
     361          self.assertPathEqual(ntpath.realpath(ABSTFN + "1"), ABSTFN)
     362  
     363      @os_helper.skip_unless_symlink
     364      @unittest.skipUnless(HAVE_GETFINALPATHNAME, 'need _getfinalpathname')
     365      def test_realpath_broken_symlinks(self):
     366          ABSTFN = ntpath.abspath(os_helper.TESTFN)
     367          os.mkdir(ABSTFN)
     368          self.addCleanup(os_helper.rmtree, ABSTFN)
     369  
     370          with os_helper.change_cwd(ABSTFN):
     371              os.mkdir("subdir")
     372              os.chdir("subdir")
     373              os.symlink(".", "recursive")
     374              os.symlink("..", "parent")
     375              os.chdir("..")
     376              os.symlink(".", "self")
     377              os.symlink("missing", "broken")
     378              os.symlink(r"broken\bar", "broken1")
     379              os.symlink(r"self\self\broken", "broken2")
     380              os.symlink(r"subdir\parent\subdir\parent\broken", "broken3")
     381              os.symlink(ABSTFN + r"\broken", "broken4")
     382              os.symlink(r"recursive\..\broken", "broken5")
     383  
     384              self.assertPathEqual(ntpath.realpath("broken"),
     385                                   ABSTFN + r"\missing")
     386              self.assertPathEqual(ntpath.realpath(r"broken\foo"),
     387                                   ABSTFN + r"\missing\foo")
     388              # bpo-38453: We no longer recursively resolve segments of relative
     389              # symlinks that the OS cannot resolve.
     390              self.assertPathEqual(ntpath.realpath(r"broken1"),
     391                                   ABSTFN + r"\broken\bar")
     392              self.assertPathEqual(ntpath.realpath(r"broken1\baz"),
     393                                   ABSTFN + r"\broken\bar\baz")
     394              self.assertPathEqual(ntpath.realpath("broken2"),
     395                                   ABSTFN + r"\self\self\missing")
     396              self.assertPathEqual(ntpath.realpath("broken3"),
     397                                   ABSTFN + r"\subdir\parent\subdir\parent\missing")
     398              self.assertPathEqual(ntpath.realpath("broken4"),
     399                                   ABSTFN + r"\missing")
     400              self.assertPathEqual(ntpath.realpath("broken5"),
     401                                   ABSTFN + r"\missing")
     402  
     403              self.assertPathEqual(ntpath.realpath(b"broken"),
     404                                   os.fsencode(ABSTFN + r"\missing"))
     405              self.assertPathEqual(ntpath.realpath(rb"broken\foo"),
     406                                   os.fsencode(ABSTFN + r"\missing\foo"))
     407              self.assertPathEqual(ntpath.realpath(rb"broken1"),
     408                                   os.fsencode(ABSTFN + r"\broken\bar"))
     409              self.assertPathEqual(ntpath.realpath(rb"broken1\baz"),
     410                                   os.fsencode(ABSTFN + r"\broken\bar\baz"))
     411              self.assertPathEqual(ntpath.realpath(b"broken2"),
     412                                   os.fsencode(ABSTFN + r"\self\self\missing"))
     413              self.assertPathEqual(ntpath.realpath(rb"broken3"),
     414                                   os.fsencode(ABSTFN + r"\subdir\parent\subdir\parent\missing"))
     415              self.assertPathEqual(ntpath.realpath(b"broken4"),
     416                                   os.fsencode(ABSTFN + r"\missing"))
     417              self.assertPathEqual(ntpath.realpath(b"broken5"),
     418                                   os.fsencode(ABSTFN + r"\missing"))
     419  
     420      @os_helper.skip_unless_symlink
     421      @unittest.skipUnless(HAVE_GETFINALPATHNAME, 'need _getfinalpathname')
     422      def test_realpath_symlink_loops(self):
     423          # Symlink loops in non-strict mode are non-deterministic as to which
     424          # path is returned, but it will always be the fully resolved path of
     425          # one member of the cycle
     426          ABSTFN = ntpath.abspath(os_helper.TESTFN)
     427          self.addCleanup(os_helper.unlink, ABSTFN)
     428          self.addCleanup(os_helper.unlink, ABSTFN + "1")
     429          self.addCleanup(os_helper.unlink, ABSTFN + "2")
     430          self.addCleanup(os_helper.unlink, ABSTFN + "y")
     431          self.addCleanup(os_helper.unlink, ABSTFN + "c")
     432          self.addCleanup(os_helper.unlink, ABSTFN + "a")
     433  
     434          os.symlink(ABSTFN, ABSTFN)
     435          self.assertPathEqual(ntpath.realpath(ABSTFN), ABSTFN)
     436  
     437          os.symlink(ABSTFN + "1", ABSTFN + "2")
     438          os.symlink(ABSTFN + "2", ABSTFN + "1")
     439          expected = (ABSTFN + "1", ABSTFN + "2")
     440          self.assertPathIn(ntpath.realpath(ABSTFN + "1"), expected)
     441          self.assertPathIn(ntpath.realpath(ABSTFN + "2"), expected)
     442  
     443          self.assertPathIn(ntpath.realpath(ABSTFN + "1\\x"),
     444                            (ntpath.join(r, "x") for r in expected))
     445          self.assertPathEqual(ntpath.realpath(ABSTFN + "1\\.."),
     446                               ntpath.dirname(ABSTFN))
     447          self.assertPathEqual(ntpath.realpath(ABSTFN + "1\\..\\x"),
     448                               ntpath.dirname(ABSTFN) + "\\x")
     449          os.symlink(ABSTFN + "x", ABSTFN + "y")
     450          self.assertPathEqual(ntpath.realpath(ABSTFN + "1\\..\\"
     451                                               + ntpath.basename(ABSTFN) + "y"),
     452                               ABSTFN + "x")
     453          self.assertPathIn(ntpath.realpath(ABSTFN + "1\\..\\"
     454                                            + ntpath.basename(ABSTFN) + "1"),
     455                            expected)
     456  
     457          os.symlink(ntpath.basename(ABSTFN) + "a\\b", ABSTFN + "a")
     458          self.assertPathEqual(ntpath.realpath(ABSTFN + "a"), ABSTFN + "a")
     459  
     460          os.symlink("..\\" + ntpath.basename(ntpath.dirname(ABSTFN))
     461                     + "\\" + ntpath.basename(ABSTFN) + "c", ABSTFN + "c")
     462          self.assertPathEqual(ntpath.realpath(ABSTFN + "c"), ABSTFN + "c")
     463  
     464          # Test using relative path as well.
     465          self.assertPathEqual(ntpath.realpath(ntpath.basename(ABSTFN)), ABSTFN)
     466  
     467      @os_helper.skip_unless_symlink
     468      @unittest.skipUnless(HAVE_GETFINALPATHNAME, 'need _getfinalpathname')
     469      def test_realpath_symlink_loops_strict(self):
     470          # Symlink loops raise OSError in strict mode
     471          ABSTFN = ntpath.abspath(os_helper.TESTFN)
     472          self.addCleanup(os_helper.unlink, ABSTFN)
     473          self.addCleanup(os_helper.unlink, ABSTFN + "1")
     474          self.addCleanup(os_helper.unlink, ABSTFN + "2")
     475          self.addCleanup(os_helper.unlink, ABSTFN + "y")
     476          self.addCleanup(os_helper.unlink, ABSTFN + "c")
     477          self.addCleanup(os_helper.unlink, ABSTFN + "a")
     478  
     479          os.symlink(ABSTFN, ABSTFN)
     480          self.assertRaises(OSError, ntpath.realpath, ABSTFN, strict=True)
     481  
     482          os.symlink(ABSTFN + "1", ABSTFN + "2")
     483          os.symlink(ABSTFN + "2", ABSTFN + "1")
     484          self.assertRaises(OSError, ntpath.realpath, ABSTFN + "1", strict=True)
     485          self.assertRaises(OSError, ntpath.realpath, ABSTFN + "2", strict=True)
     486          self.assertRaises(OSError, ntpath.realpath, ABSTFN + "1\\x", strict=True)
     487          # Windows eliminates '..' components before resolving links, so the
     488          # following call is not expected to raise.
     489          self.assertPathEqual(ntpath.realpath(ABSTFN + "1\\..", strict=True),
     490                               ntpath.dirname(ABSTFN))
     491          self.assertRaises(OSError, ntpath.realpath, ABSTFN + "1\\..\\x", strict=True)
     492          os.symlink(ABSTFN + "x", ABSTFN + "y")
     493          self.assertRaises(OSError, ntpath.realpath, ABSTFN + "1\\..\\"
     494                                               + ntpath.basename(ABSTFN) + "y",
     495                                               strict=True)
     496          self.assertRaises(OSError, ntpath.realpath,
     497                            ABSTFN + "1\\..\\" + ntpath.basename(ABSTFN) + "1",
     498                            strict=True)
     499  
     500          os.symlink(ntpath.basename(ABSTFN) + "a\\b", ABSTFN + "a")
     501          self.assertRaises(OSError, ntpath.realpath, ABSTFN + "a", strict=True)
     502  
     503          os.symlink("..\\" + ntpath.basename(ntpath.dirname(ABSTFN))
     504                     + "\\" + ntpath.basename(ABSTFN) + "c", ABSTFN + "c")
     505          self.assertRaises(OSError, ntpath.realpath, ABSTFN + "c", strict=True)
     506  
     507          # Test using relative path as well.
     508          self.assertRaises(OSError, ntpath.realpath, ntpath.basename(ABSTFN),
     509                            strict=True)
     510  
     511      @os_helper.skip_unless_symlink
     512      @unittest.skipUnless(HAVE_GETFINALPATHNAME, 'need _getfinalpathname')
     513      def test_realpath_symlink_prefix(self):
     514          ABSTFN = ntpath.abspath(os_helper.TESTFN)
     515          self.addCleanup(os_helper.unlink, ABSTFN + "3")
     516          self.addCleanup(os_helper.unlink, "\\\\?\\" + ABSTFN + "3.")
     517          self.addCleanup(os_helper.unlink, ABSTFN + "3link")
     518          self.addCleanup(os_helper.unlink, ABSTFN + "3.link")
     519  
     520          with open(ABSTFN + "3", "wb") as f:
     521              f.write(b'0')
     522          os.symlink(ABSTFN + "3", ABSTFN + "3link")
     523  
     524          with open("\\\\?\\" + ABSTFN + "3.", "wb") as f:
     525              f.write(b'1')
     526          os.symlink("\\\\?\\" + ABSTFN + "3.", ABSTFN + "3.link")
     527  
     528          self.assertPathEqual(ntpath.realpath(ABSTFN + "3link"),
     529                               ABSTFN + "3")
     530          self.assertPathEqual(ntpath.realpath(ABSTFN + "3.link"),
     531                               "\\\\?\\" + ABSTFN + "3.")
     532  
     533          # Resolved paths should be usable to open target files
     534          with open(ntpath.realpath(ABSTFN + "3link"), "rb") as f:
     535              self.assertEqual(f.read(), b'0')
     536          with open(ntpath.realpath(ABSTFN + "3.link"), "rb") as f:
     537              self.assertEqual(f.read(), b'1')
     538  
     539          # When the prefix is included, it is not stripped
     540          self.assertPathEqual(ntpath.realpath("\\\\?\\" + ABSTFN + "3link"),
     541                               "\\\\?\\" + ABSTFN + "3")
     542          self.assertPathEqual(ntpath.realpath("\\\\?\\" + ABSTFN + "3.link"),
     543                               "\\\\?\\" + ABSTFN + "3.")
     544  
     545      @unittest.skipUnless(HAVE_GETFINALPATHNAME, 'need _getfinalpathname')
     546      def test_realpath_nul(self):
     547          tester("ntpath.realpath('NUL')", r'\\.\NUL')
     548  
     549      @unittest.skipUnless(HAVE_GETFINALPATHNAME, 'need _getfinalpathname')
     550      @unittest.skipUnless(HAVE_GETSHORTPATHNAME, 'need _getshortpathname')
     551      def test_realpath_cwd(self):
     552          ABSTFN = ntpath.abspath(os_helper.TESTFN)
     553  
     554          os_helper.unlink(ABSTFN)
     555          os_helper.rmtree(ABSTFN)
     556          os.mkdir(ABSTFN)
     557          self.addCleanup(os_helper.rmtree, ABSTFN)
     558  
     559          test_dir_long = ntpath.join(ABSTFN, "MyVeryLongDirectoryName")
     560          os.mkdir(test_dir_long)
     561  
     562          test_dir_short = _getshortpathname(test_dir_long)
     563          test_file_long = ntpath.join(test_dir_long, "file.txt")
     564          test_file_short = ntpath.join(test_dir_short, "file.txt")
     565  
     566          with open(test_file_long, "wb") as f:
     567              f.write(b"content")
     568  
     569          self.assertPathEqual(test_file_long, ntpath.realpath(test_file_short))
     570  
     571          with os_helper.change_cwd(test_dir_long):
     572              self.assertPathEqual(test_file_long, ntpath.realpath("file.txt"))
     573          with os_helper.change_cwd(test_dir_long.lower()):
     574              self.assertPathEqual(test_file_long, ntpath.realpath("file.txt"))
     575          with os_helper.change_cwd(test_dir_short):
     576              self.assertPathEqual(test_file_long, ntpath.realpath("file.txt"))
     577  
     578      def test_expandvars(self):
     579          with os_helper.EnvironmentVarGuard() as env:
     580              env.clear()
     581              env["foo"] = "bar"
     582              env["{foo"] = "baz1"
     583              env["{foo}"] = "baz2"
     584              tester('ntpath.expandvars("foo")', "foo")
     585              tester('ntpath.expandvars("$foo bar")', "bar bar")
     586              tester('ntpath.expandvars("${foo}bar")', "barbar")
     587              tester('ntpath.expandvars("$[foo]bar")', "$[foo]bar")
     588              tester('ntpath.expandvars("$bar bar")', "$bar bar")
     589              tester('ntpath.expandvars("$?bar")', "$?bar")
     590              tester('ntpath.expandvars("$foo}bar")', "bar}bar")
     591              tester('ntpath.expandvars("${foo")', "${foo")
     592              tester('ntpath.expandvars("${{foo}}")', "baz1}")
     593              tester('ntpath.expandvars("$foo$foo")', "barbar")
     594              tester('ntpath.expandvars("$bar$bar")', "$bar$bar")
     595              tester('ntpath.expandvars("%foo% bar")', "bar bar")
     596              tester('ntpath.expandvars("%foo%bar")', "barbar")
     597              tester('ntpath.expandvars("%foo%%foo%")', "barbar")
     598              tester('ntpath.expandvars("%%foo%%foo%foo%")', "%foo%foobar")
     599              tester('ntpath.expandvars("%?bar%")', "%?bar%")
     600              tester('ntpath.expandvars("%foo%%bar")', "bar%bar")
     601              tester('ntpath.expandvars("\'%foo%\'%bar")', "\'%foo%\'%bar")
     602              tester('ntpath.expandvars("bar\'%foo%")', "bar\'%foo%")
     603  
     604      @unittest.skipUnless(os_helper.FS_NONASCII, 'need os_helper.FS_NONASCII')
     605      def test_expandvars_nonascii(self):
     606          def check(value, expected):
     607              tester('ntpath.expandvars(%r)' % value, expected)
     608          with os_helper.EnvironmentVarGuard() as env:
     609              env.clear()
     610              nonascii = os_helper.FS_NONASCII
     611              env['spam'] = nonascii
     612              env[nonascii] = 'ham' + nonascii
     613              check('$spam bar', '%s bar' % nonascii)
     614              check('$%s bar' % nonascii, '$%s bar' % nonascii)
     615              check('${spam}bar', '%sbar' % nonascii)
     616              check('${%s}bar' % nonascii, 'ham%sbar' % nonascii)
     617              check('$spam}bar', '%s}bar' % nonascii)
     618              check('$%s}bar' % nonascii, '$%s}bar' % nonascii)
     619              check('%spam% bar', '%s bar' % nonascii)
     620              check('%{}% bar'.format(nonascii), 'ham%s bar' % nonascii)
     621              check('%spam%bar', '%sbar' % nonascii)
     622              check('%{}%bar'.format(nonascii), 'ham%sbar' % nonascii)
     623  
     624      def test_expanduser(self):
     625          tester('ntpath.expanduser("test")', 'test')
     626  
     627          with os_helper.EnvironmentVarGuard() as env:
     628              env.clear()
     629              tester('ntpath.expanduser("~test")', '~test')
     630  
     631              env['HOMEDRIVE'] = 'C:\\'
     632              env['HOMEPATH'] = 'Users\\eric'
     633              env['USERNAME'] = 'eric'
     634              tester('ntpath.expanduser("~test")', 'C:\\Users\\test')
     635              tester('ntpath.expanduser("~")', 'C:\\Users\\eric')
     636  
     637              del env['HOMEDRIVE']
     638              tester('ntpath.expanduser("~test")', 'Users\\test')
     639              tester('ntpath.expanduser("~")', 'Users\\eric')
     640  
     641              env.clear()
     642              env['USERPROFILE'] = 'C:\\Users\\eric'
     643              env['USERNAME'] = 'eric'
     644              tester('ntpath.expanduser("~test")', 'C:\\Users\\test')
     645              tester('ntpath.expanduser("~")', 'C:\\Users\\eric')
     646              tester('ntpath.expanduser("~test\\foo\\bar")',
     647                     'C:\\Users\\test\\foo\\bar')
     648              tester('ntpath.expanduser("~test/foo/bar")',
     649                     'C:\\Users\\test/foo/bar')
     650              tester('ntpath.expanduser("~\\foo\\bar")',
     651                     'C:\\Users\\eric\\foo\\bar')
     652              tester('ntpath.expanduser("~/foo/bar")',
     653                     'C:\\Users\\eric/foo/bar')
     654  
     655              # bpo-36264: ignore `HOME` when set on windows
     656              env.clear()
     657              env['HOME'] = 'F:\\'
     658              env['USERPROFILE'] = 'C:\\Users\\eric'
     659              env['USERNAME'] = 'eric'
     660              tester('ntpath.expanduser("~test")', 'C:\\Users\\test')
     661              tester('ntpath.expanduser("~")', 'C:\\Users\\eric')
     662  
     663              # bpo-39899: don't guess another user's home directory if
     664              # `%USERNAME% != basename(%USERPROFILE%)`
     665              env.clear()
     666              env['USERPROFILE'] = 'C:\\Users\\eric'
     667              env['USERNAME'] = 'idle'
     668              tester('ntpath.expanduser("~test")', '~test')
     669              tester('ntpath.expanduser("~")', 'C:\\Users\\eric')
     670  
     671  
     672  
     673      @unittest.skipUnless(nt, "abspath requires 'nt' module")
     674      def test_abspath(self):
     675          tester('ntpath.abspath("C:\\")', "C:\\")
     676          tester('ntpath.abspath("\\\\?\\C:////spam////eggs. . .")', "\\\\?\\C:\\spam\\eggs")
     677          tester('ntpath.abspath("\\\\.\\C:////spam////eggs. . .")', "\\\\.\\C:\\spam\\eggs")
     678          tester('ntpath.abspath("//spam//eggs. . .")',     "\\\\spam\\eggs")
     679          tester('ntpath.abspath("\\\\spam\\\\eggs. . .")', "\\\\spam\\eggs")
     680          tester('ntpath.abspath("C:/spam. . .")',  "C:\\spam")
     681          tester('ntpath.abspath("C:\\spam. . .")', "C:\\spam")
     682          tester('ntpath.abspath("C:/nul")',  "\\\\.\\nul")
     683          tester('ntpath.abspath("C:\\nul")', "\\\\.\\nul")
     684          tester('ntpath.abspath("//..")',           "\\\\")
     685          tester('ntpath.abspath("//../")',          "\\\\..\\")
     686          tester('ntpath.abspath("//../..")',        "\\\\..\\")
     687          tester('ntpath.abspath("//../../")',       "\\\\..\\..\\")
     688          tester('ntpath.abspath("//../../../")',    "\\\\..\\..\\")
     689          tester('ntpath.abspath("//../../../..")',  "\\\\..\\..\\")
     690          tester('ntpath.abspath("//../../../../")', "\\\\..\\..\\")
     691          tester('ntpath.abspath("//server")',           "\\\\server")
     692          tester('ntpath.abspath("//server/")',          "\\\\server\\")
     693          tester('ntpath.abspath("//server/..")',        "\\\\server\\")
     694          tester('ntpath.abspath("//server/../")',       "\\\\server\\..\\")
     695          tester('ntpath.abspath("//server/../..")',     "\\\\server\\..\\")
     696          tester('ntpath.abspath("//server/../../")',    "\\\\server\\..\\")
     697          tester('ntpath.abspath("//server/../../..")',  "\\\\server\\..\\")
     698          tester('ntpath.abspath("//server/../../../")', "\\\\server\\..\\")
     699          tester('ntpath.abspath("//server/share")',        "\\\\server\\share")
     700          tester('ntpath.abspath("//server/share/")',       "\\\\server\\share\\")
     701          tester('ntpath.abspath("//server/share/..")',     "\\\\server\\share\\")
     702          tester('ntpath.abspath("//server/share/../")',    "\\\\server\\share\\")
     703          tester('ntpath.abspath("//server/share/../..")',  "\\\\server\\share\\")
     704          tester('ntpath.abspath("//server/share/../../")', "\\\\server\\share\\")
     705          tester('ntpath.abspath("C:\\nul. . .")', "\\\\.\\nul")
     706          tester('ntpath.abspath("//... . .")',  "\\\\")
     707          tester('ntpath.abspath("//.. . . .")', "\\\\")
     708          tester('ntpath.abspath("//../... . .")',  "\\\\..\\")
     709          tester('ntpath.abspath("//../.. . . .")', "\\\\..\\")
     710          with os_helper.temp_cwd(os_helper.TESTFN) as cwd_dir: # bpo-31047
     711              tester('ntpath.abspath("")', cwd_dir)
     712              tester('ntpath.abspath(" ")', cwd_dir + "\\ ")
     713              tester('ntpath.abspath("?")', cwd_dir + "\\?")
     714              drive, _ = ntpath.splitdrive(cwd_dir)
     715              tester('ntpath.abspath("/abc/")', drive + "\\abc")
     716  
     717      def test_relpath(self):
     718          tester('ntpath.relpath("a")', 'a')
     719          tester('ntpath.relpath(ntpath.abspath("a"))', 'a')
     720          tester('ntpath.relpath("a/b")', 'a\\b')
     721          tester('ntpath.relpath("../a/b")', '..\\a\\b')
     722          with os_helper.temp_cwd(os_helper.TESTFN) as cwd_dir:
     723              currentdir = ntpath.basename(cwd_dir)
     724              tester('ntpath.relpath("a", "../b")', '..\\'+currentdir+'\\a')
     725              tester('ntpath.relpath("a/b", "../c")', '..\\'+currentdir+'\\a\\b')
     726          tester('ntpath.relpath("a", "b/c")', '..\\..\\a')
     727          tester('ntpath.relpath("c:/foo/bar/bat", "c:/x/y")', '..\\..\\foo\\bar\\bat')
     728          tester('ntpath.relpath("//conky/mountpoint/a", "//conky/mountpoint/b/c")', '..\\..\\a')
     729          tester('ntpath.relpath("a", "a")', '.')
     730          tester('ntpath.relpath("/foo/bar/bat", "/x/y/z")', '..\\..\\..\\foo\\bar\\bat')
     731          tester('ntpath.relpath("/foo/bar/bat", "/foo/bar")', 'bat')
     732          tester('ntpath.relpath("/foo/bar/bat", "/")', 'foo\\bar\\bat')
     733          tester('ntpath.relpath("/", "/foo/bar/bat")', '..\\..\\..')
     734          tester('ntpath.relpath("/foo/bar/bat", "/x")', '..\\foo\\bar\\bat')
     735          tester('ntpath.relpath("/x", "/foo/bar/bat")', '..\\..\\..\\x')
     736          tester('ntpath.relpath("/", "/")', '.')
     737          tester('ntpath.relpath("/a", "/a")', '.')
     738          tester('ntpath.relpath("/a/b", "/a/b")', '.')
     739          tester('ntpath.relpath("c:/foo", "C:/FOO")', '.')
     740  
     741      def test_commonpath(self):
     742          def check(paths, expected):
     743              tester(('ntpath.commonpath(%r)' % paths).replace('\\\\', '\\'),
     744                     expected)
     745          def check_error(exc, paths):
     746              self.assertRaises(exc, ntpath.commonpath, paths)
     747              self.assertRaises(exc, ntpath.commonpath,
     748                                [os.fsencode(p) for p in paths])
     749  
     750          self.assertRaises(ValueError, ntpath.commonpath, [])
     751          check_error(ValueError, ['C:\\Program Files', 'Program Files'])
     752          check_error(ValueError, ['C:\\Program Files', 'C:Program Files'])
     753          check_error(ValueError, ['\\Program Files', 'Program Files'])
     754          check_error(ValueError, ['Program Files', 'C:\\Program Files'])
     755          check(['C:\\Program Files'], 'C:\\Program Files')
     756          check(['C:\\Program Files', 'C:\\Program Files'], 'C:\\Program Files')
     757          check(['C:\\Program Files\\', 'C:\\Program Files'],
     758                'C:\\Program Files')
     759          check(['C:\\Program Files\\', 'C:\\Program Files\\'],
     760                'C:\\Program Files')
     761          check(['C:\\\\Program Files', 'C:\\Program Files\\\\'],
     762                'C:\\Program Files')
     763          check(['C:\\.\\Program Files', 'C:\\Program Files\\.'],
     764                'C:\\Program Files')
     765          check(['C:\\', 'C:\\bin'], 'C:\\')
     766          check(['C:\\Program Files', 'C:\\bin'], 'C:\\')
     767          check(['C:\\Program Files', 'C:\\Program Files\\Bar'],
     768                'C:\\Program Files')
     769          check(['C:\\Program Files\\Foo', 'C:\\Program Files\\Bar'],
     770                'C:\\Program Files')
     771          check(['C:\\Program Files', 'C:\\Projects'], 'C:\\')
     772          check(['C:\\Program Files\\', 'C:\\Projects'], 'C:\\')
     773  
     774          check(['C:\\Program Files\\Foo', 'C:/Program Files/Bar'],
     775                'C:\\Program Files')
     776          check(['C:\\Program Files\\Foo', 'c:/program files/bar'],
     777                'C:\\Program Files')
     778          check(['c:/program files/bar', 'C:\\Program Files\\Foo'],
     779                'c:\\program files')
     780  
     781          check_error(ValueError, ['C:\\Program Files', 'D:\\Program Files'])
     782  
     783          check(['spam'], 'spam')
     784          check(['spam', 'spam'], 'spam')
     785          check(['spam', 'alot'], '')
     786          check(['and\\jam', 'and\\spam'], 'and')
     787          check(['and\\\\jam', 'and\\spam\\\\'], 'and')
     788          check(['and\\.\\jam', '.\\and\\spam'], 'and')
     789          check(['and\\jam', 'and\\spam', 'alot'], '')
     790          check(['and\\jam', 'and\\spam', 'and'], 'and')
     791          check(['C:and\\jam', 'C:and\\spam'], 'C:and')
     792  
     793          check([''], '')
     794          check(['', 'spam\\alot'], '')
     795          check_error(ValueError, ['', '\\spam\\alot'])
     796  
     797          self.assertRaises(TypeError, ntpath.commonpath,
     798                            [b'C:\\Program Files', 'C:\\Program Files\\Foo'])
     799          self.assertRaises(TypeError, ntpath.commonpath,
     800                            [b'C:\\Program Files', 'Program Files\\Foo'])
     801          self.assertRaises(TypeError, ntpath.commonpath,
     802                            [b'Program Files', 'C:\\Program Files\\Foo'])
     803          self.assertRaises(TypeError, ntpath.commonpath,
     804                            ['C:\\Program Files', b'C:\\Program Files\\Foo'])
     805          self.assertRaises(TypeError, ntpath.commonpath,
     806                            ['C:\\Program Files', b'Program Files\\Foo'])
     807          self.assertRaises(TypeError, ntpath.commonpath,
     808                            ['Program Files', b'C:\\Program Files\\Foo'])
     809  
     810      @unittest.skipIf(is_emscripten, "Emscripten cannot fstat unnamed files.")
     811      def test_sameopenfile(self):
     812          with TemporaryFile() as tf1, TemporaryFile() as tf2:
     813              # Make sure the same file is really the same
     814              self.assertTrue(ntpath.sameopenfile(tf1.fileno(), tf1.fileno()))
     815              # Make sure different files are really different
     816              self.assertFalse(ntpath.sameopenfile(tf1.fileno(), tf2.fileno()))
     817              # Make sure invalid values don't cause issues on win32
     818              if sys.platform == "win32":
     819                  with self.assertRaises(OSError):
     820                      # Invalid file descriptors shouldn't display assert
     821                      # dialogs (#4804)
     822                      ntpath.sameopenfile(-1, -1)
     823  
     824      def test_ismount(self):
     825          self.assertTrue(ntpath.ismount("c:\\"))
     826          self.assertTrue(ntpath.ismount("C:\\"))
     827          self.assertTrue(ntpath.ismount("c:/"))
     828          self.assertTrue(ntpath.ismount("C:/"))
     829          self.assertTrue(ntpath.ismount("\\\\.\\c:\\"))
     830          self.assertTrue(ntpath.ismount("\\\\.\\C:\\"))
     831  
     832          self.assertTrue(ntpath.ismount(b"c:\\"))
     833          self.assertTrue(ntpath.ismount(b"C:\\"))
     834          self.assertTrue(ntpath.ismount(b"c:/"))
     835          self.assertTrue(ntpath.ismount(b"C:/"))
     836          self.assertTrue(ntpath.ismount(b"\\\\.\\c:\\"))
     837          self.assertTrue(ntpath.ismount(b"\\\\.\\C:\\"))
     838  
     839          with os_helper.temp_dir() as d:
     840              self.assertFalse(ntpath.ismount(d))
     841  
     842          if sys.platform == "win32":
     843              #
     844              # Make sure the current folder isn't the root folder
     845              # (or any other volume root). The drive-relative
     846              # locations below cannot then refer to mount points
     847              #
     848              test_cwd = os.getenv("SystemRoot")
     849              drive, path = ntpath.splitdrive(test_cwd)
     850              with os_helper.change_cwd(test_cwd):
     851                  self.assertFalse(ntpath.ismount(drive.lower()))
     852                  self.assertFalse(ntpath.ismount(drive.upper()))
     853  
     854              self.assertTrue(ntpath.ismount("\\\\localhost\\c$"))
     855              self.assertTrue(ntpath.ismount("\\\\localhost\\c$\\"))
     856  
     857              self.assertTrue(ntpath.ismount(b"\\\\localhost\\c$"))
     858              self.assertTrue(ntpath.ismount(b"\\\\localhost\\c$\\"))
     859  
     860      def assertEqualCI(self, s1, s2):
     861          """Assert that two strings are equal ignoring case differences."""
     862          self.assertEqual(s1.lower(), s2.lower())
     863  
     864      @unittest.skipUnless(nt, "OS helpers require 'nt' module")
     865      def test_nt_helpers(self):
     866          # Trivial validation that the helpers do not break, and support both
     867          # unicode and bytes (UTF-8) paths
     868  
     869          executable = nt._getfinalpathname(sys.executable)
     870  
     871          for path in executable, os.fsencode(executable):
     872              volume_path = nt._getvolumepathname(path)
     873              path_drive = ntpath.splitdrive(path)[0]
     874              volume_path_drive = ntpath.splitdrive(volume_path)[0]
     875              self.assertEqualCI(path_drive, volume_path_drive)
     876  
     877          cap, free = nt._getdiskusage(sys.exec_prefix)
     878          self.assertGreater(cap, 0)
     879          self.assertGreater(free, 0)
     880          b_cap, b_free = nt._getdiskusage(sys.exec_prefix.encode())
     881          # Free space may change, so only test the capacity is equal
     882          self.assertEqual(b_cap, cap)
     883          self.assertGreater(b_free, 0)
     884  
     885          for path in [sys.prefix, sys.executable]:
     886              final_path = nt._getfinalpathname(path)
     887              self.assertIsInstance(final_path, str)
     888              self.assertGreater(len(final_path), 0)
     889  
     890              b_final_path = nt._getfinalpathname(path.encode())
     891              self.assertIsInstance(b_final_path, bytes)
     892              self.assertGreater(len(b_final_path), 0)
     893  
     894  class ESC[4;38;5;81mNtCommonTest(ESC[4;38;5;149mtest_genericpathESC[4;38;5;149m.ESC[4;38;5;149mCommonTest, ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
     895      pathmodule = ntpath
     896      attributes = ['relpath']
     897  
     898  
     899  class ESC[4;38;5;81mPathLikeTests(ESC[4;38;5;149mNtpathTestCase):
     900  
     901      path = ntpath
     902  
     903      def setUp(self):
     904          self.file_name = os_helper.TESTFN
     905          self.file_path = FakePath(os_helper.TESTFN)
     906          self.addCleanup(os_helper.unlink, self.file_name)
     907          with open(self.file_name, 'xb', 0) as file:
     908              file.write(b"test_ntpath.PathLikeTests")
     909  
     910      def _check_function(self, func):
     911          self.assertPathEqual(func(self.file_path), func(self.file_name))
     912  
     913      def test_path_normcase(self):
     914          self._check_function(self.path.normcase)
     915          if sys.platform == 'win32':
     916              self.assertEqual(ntpath.normcase('\u03a9\u2126'), 'ωΩ')
     917              self.assertEqual(ntpath.normcase('abc\x00def'), 'abc\x00def')
     918  
     919      def test_path_isabs(self):
     920          self._check_function(self.path.isabs)
     921  
     922      def test_path_join(self):
     923          self.assertEqual(self.path.join('a', FakePath('b'), 'c'),
     924                           self.path.join('a', 'b', 'c'))
     925  
     926      def test_path_split(self):
     927          self._check_function(self.path.split)
     928  
     929      def test_path_splitext(self):
     930          self._check_function(self.path.splitext)
     931  
     932      def test_path_splitdrive(self):
     933          self._check_function(self.path.splitdrive)
     934  
     935      def test_path_basename(self):
     936          self._check_function(self.path.basename)
     937  
     938      def test_path_dirname(self):
     939          self._check_function(self.path.dirname)
     940  
     941      def test_path_islink(self):
     942          self._check_function(self.path.islink)
     943  
     944      def test_path_lexists(self):
     945          self._check_function(self.path.lexists)
     946  
     947      def test_path_ismount(self):
     948          self._check_function(self.path.ismount)
     949  
     950      def test_path_expanduser(self):
     951          self._check_function(self.path.expanduser)
     952  
     953      def test_path_expandvars(self):
     954          self._check_function(self.path.expandvars)
     955  
     956      def test_path_normpath(self):
     957          self._check_function(self.path.normpath)
     958  
     959      def test_path_abspath(self):
     960          self._check_function(self.path.abspath)
     961  
     962      def test_path_realpath(self):
     963          self._check_function(self.path.realpath)
     964  
     965      def test_path_relpath(self):
     966          self._check_function(self.path.relpath)
     967  
     968      def test_path_commonpath(self):
     969          common_path = self.path.commonpath([self.file_path, self.file_name])
     970          self.assertPathEqual(common_path, self.file_name)
     971  
     972      def test_path_isdir(self):
     973          self._check_function(self.path.isdir)
     974  
     975  
     976  if __name__ == "__main__":
     977      unittest.main()