1#!/pxrpythonsubst
2#
3# Copyright 2016 Pixar
4#
5# Licensed under the Apache License, Version 2.0 (the "Apache License")
6# with the following modification; you may not use this file except in
7# compliance with the Apache License and the following modification to it:
8# Section 6. Trademarks. is deleted and replaced with:
9#
10# 6. Trademarks. This License does not grant permission to use the trade
11#    names, trademarks, service marks, or product names of the Licensor
12#    and its affiliates, except as required to comply with Section 4(c) of
13#    the License and to reproduce the content of the NOTICE file.
14#
15# You may obtain a copy of the Apache License at
16#
17#     http://www.apache.org/licenses/LICENSE-2.0
18#
19# Unless required by applicable law or agreed to in writing, software
20# distributed under the Apache License with the above modification is
21# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
22# KIND, either express or implied. See the Apache License for the specific
23# language governing permissions and limitations under the Apache License.
24#
25
26import logging
27import os
28from pxr import Tf
29import unittest
30import platform
31
32class TestPathUtils(unittest.TestCase):
33
34    def setUp(self):
35        self.log = logging.getLogger()
36
37    def test_TfRealPath(self):
38        if not os.path.isdir('subdir/e'):
39            os.makedirs('subdir/e')
40        self.log.info('no symlinks')
41        self.assertEqual(os.path.abspath('subdir'), Tf.RealPath('subdir', True))
42
43        if hasattr(os, 'symlink'):
44            try:
45                if not os.path.islink('b'):
46                    os.symlink('subdir', 'b')
47                if not os.path.islink('c'):
48                    os.symlink('b', 'c')
49                if not os.path.islink('d'):
50                    os.symlink('c', 'd')
51                if not os.path.islink('e'):
52                    os.symlink('missing', 'e')
53                if not os.path.islink('f'):
54                    os.symlink('e', 'f')
55                if not os.path.islink('g'):
56                    os.symlink('f', 'g')
57
58                # XXX:
59                # On Windows, TfRealPath explicitly lower-cases drive letters
60                # if the given path contains symlinks, otherwise it returns
61                # the same as os.path.abspath. This is inconsistent but
62                # fixing it is a bit riskier. So for now, we just test the
63                # the current behavior.
64                def _TestSymlink(expected, got):
65                    if platform.system() == 'Windows':
66                        drive, tail = os.path.splitdrive(expected)
67                        expected = drive.lower() + tail
68                    self.assertEqual(expected, got)
69
70                self.log.info('leaf dir is symlink')
71                _TestSymlink(os.path.abspath('subdir'),
72                             Tf.RealPath('d', True))
73                self.log.info('symlinks through to dir')
74                _TestSymlink(os.path.abspath('subdir/e'),
75                             Tf.RealPath('d/e', True))
76                self.log.info('symlinks through to nonexistent dirs')
77                _TestSymlink(os.path.abspath('subdir/e/f/g/h'),
78                             Tf.RealPath('d/e/f/g/h', True))
79                self.log.info('symlinks through to broken link')
80                _TestSymlink('', Tf.RealPath('g', True))
81
82                self.log.info('symlinks through to broken link, '
83                              'raiseOnError=True')
84                with self.assertRaises(RuntimeError):
85                    Tf.RealPath('g', True, raiseOnError=True)
86
87                if platform.system() == 'Windows':
88                    try:
89                        # Test repro from USD-6557
90                        if not os.path.isdir(r'C:/symlink-test'):
91                            os.makedirs(r'C:/symlink-test')
92
93                        if not os.path.islink(r'C:/symlink-test-link'):
94                            os.symlink(r'C:/symlink-test', 'C:/symlink-test-link')
95                            cwd = os.getcwd()
96                            try:
97                                os.chdir(r'C:/symlink-test-link')
98                                _TestSymlink(os.path.abspath('C:/symlink-test'),
99                                             Tf.RealPath(r'C:/symlink-test-link'))
100                            finally:
101                                # Restore cwd before trying to remove the test
102                                # dirs, otherwise Windows will disallow it.
103                                os.chdir(cwd)
104                    finally:
105                        if os.path.isdir(r'C:/symlink-test-link'):
106                            os.rmdir(r'C:/symlink-test-link')
107                        if os.path.isdir(r'C:/symlink-test'):
108                            os.rmdir(r'C:/symlink-test')
109
110            except OSError:
111                # On windows this is expected if run by a non-administrator
112                if platform.system() == 'Windows':
113                    pass
114                else:
115                    raise
116
117if __name__ == '__main__':
118    unittest.main()
119