1from PyObjCTools.TestSupport import *
2import os
3
4import objc._dyld as dyld
5
6try:
7    unicode
8except NameError:
9    unicode = str
10
11
12class TestDyld (TestCase):
13    def setUp(self):
14        self.orig_environ = os.environ
15        os.environ = os.environ.copy()
16
17    def tearDown(self):
18        os.environ = self.orig_environ
19
20    def test_inject_suffixes(self):
21        if 'DYLD_IMAGE_SUFFIX' in os.environ:
22            del os.environ['DYLD_IMAGE_SUFFIX']
23
24
25        # No suffix
26        paths = [ '/usr/lib/libSystem.dylib',
27                '/lib/libfoo.3.dylib',
28                '/System/Library/Frameworks/CorePython.framework/Versions/B/CorePython',
29                '/System/Library/Frameworks/CorePython.framework/CorePython',
30        ]
31        self.assertEqual(list(dyld.inject_suffixes(iter(paths))), paths)
32        self.assertIs(dyld.inject_suffixes(paths), paths)
33
34        os.environ['DYLD_IMAGE_SUFFIX'] = '_DEBUG'
35        self.maxDiff = None
36        self.assertEqual(list(dyld.inject_suffixes(iter(paths))), [
37                '/usr/lib/libSystem_DEBUG.dylib',
38                '/usr/lib/libSystem.dylib',
39                '/lib/libfoo.3_DEBUG.dylib',
40                '/lib/libfoo.3.dylib',
41                '/System/Library/Frameworks/CorePython.framework/Versions/B/CorePython_DEBUG',
42                '/System/Library/Frameworks/CorePython.framework/Versions/B/CorePython',
43                '/System/Library/Frameworks/CorePython.framework/CorePython_DEBUG',
44                '/System/Library/Frameworks/CorePython.framework/CorePython',
45        ])
46
47
48    def test_ensure_unicode(self):
49        v = dyld.ensure_unicode("foo")
50        self.assertIsInstance(v, unicode)
51        self.assertEqual(v, b"foo".decode("utf-8"))
52
53        v = dyld.ensure_unicode(b"foo")
54        self.assertIsInstance(v, unicode)
55        self.assertEqual(v, b"foo".decode("utf-8"))
56
57        v = dyld.ensure_unicode(b"foo".decode("utf-8"))
58        self.assertIsInstance(v, unicode)
59        self.assertEqual(v, b"foo".decode("utf-8"))
60
61        self.assertRaises(UnicodeError, dyld.ensure_unicode, b"\xff\xff")
62
63    def test_dyld_library(self):
64        for k in ('DYLD_LIBRARY_PATH', 'DYLD_FALLBACK_LIBRARY_PATH', 'DYLD_IMAGE_SUFFIX'):
65            if k in os.environ:
66                del os.environ[k]
67
68        orig = os.path.exists
69        try:
70            os.path.exists = lambda fn: l.append(fn)
71
72            l = []
73            self.assertRaises(ValueError, dyld.dyld_library, '/usr/lib/libSystem.dylib', 'libXSystem.dylib')
74            self.assertEqual(l, [
75                '/usr/lib/libSystem.dylib',
76                os.path.expanduser('~/lib/libXSystem.dylib'),
77                '/usr/local/lib/libXSystem.dylib',
78                '/lib/libXSystem.dylib',
79                '/usr/lib/libXSystem.dylib',
80            ])
81
82            os.environ['DYLD_IMAGE_SUFFIX'] = '_debug'
83            l = []
84            self.assertRaises(ValueError, dyld.dyld_library, '/usr/lib/libSystem.dylib', 'libXSystem.dylib')
85            self.assertEqual(l, [
86                '/usr/lib/libSystem_debug.dylib',
87                '/usr/lib/libSystem.dylib',
88                os.path.expanduser('~/lib/libXSystem_debug.dylib'),
89                os.path.expanduser('~/lib/libXSystem.dylib'),
90                '/usr/local/lib/libXSystem_debug.dylib',
91                '/usr/local/lib/libXSystem.dylib',
92                '/lib/libXSystem_debug.dylib',
93                '/lib/libXSystem.dylib',
94                '/usr/lib/libXSystem_debug.dylib',
95                '/usr/lib/libXSystem.dylib',
96            ])
97
98            del os.environ['DYLD_IMAGE_SUFFIX']
99
100            os.environ['DYLD_LIBRARY_PATH'] = '/slib:/usr/slib'
101            l = []
102            self.assertRaises(ValueError, dyld.dyld_library, '/usr/lib/libSystem.dylib', 'libXSystem.dylib')
103            self.assertEqual(l, [
104                '/slib/libXSystem.dylib',
105                '/usr/slib/libXSystem.dylib',
106                '/usr/lib/libSystem.dylib',
107                os.path.expanduser('~/lib/libXSystem.dylib'),
108                '/usr/local/lib/libXSystem.dylib',
109                '/lib/libXSystem.dylib',
110                '/usr/lib/libXSystem.dylib',
111            ])
112            del os.environ['DYLD_LIBRARY_PATH']
113
114            os.environ['DYLD_FALLBACK_LIBRARY_PATH'] = '/slib:/usr/slib'
115            l = []
116            self.assertRaises(ValueError, dyld.dyld_library, '/usr/lib/libSystem.dylib', 'libXSystem.dylib')
117            self.assertEqual(l, [
118                '/usr/lib/libSystem.dylib',
119                '/slib/libXSystem.dylib',
120                '/usr/slib/libXSystem.dylib',
121            ])
122            del os.environ['DYLD_FALLBACK_LIBRARY_PATH']
123
124            os.environ['DYLD_LIBRARY_PATH'] = "/lib2:/lib3"
125            os.environ['DYLD_FALLBACK_LIBRARY_PATH'] = "/lib4:/lib5"
126            os.environ['DYLD_IMAGE_SUFFIX'] = "_profile"
127
128            l = []
129            self.assertRaises(ValueError, dyld.dyld_library, '/usr/lib/libSystem.dylib', 'libXSystem.dylib')
130            self.assertEqual(l, [
131                '/lib2/libXSystem_profile.dylib',
132                '/lib2/libXSystem.dylib',
133                '/lib3/libXSystem_profile.dylib',
134                '/lib3/libXSystem.dylib',
135                '/usr/lib/libSystem_profile.dylib',
136                '/usr/lib/libSystem.dylib',
137                '/lib4/libXSystem_profile.dylib',
138                '/lib4/libXSystem.dylib',
139                '/lib5/libXSystem_profile.dylib',
140                '/lib5/libXSystem.dylib',
141            ])
142            del os.environ['DYLD_LIBRARY_PATH']
143            del os.environ['DYLD_FALLBACK_LIBRARY_PATH']
144            del os.environ['DYLD_IMAGE_SUFFIX']
145
146        finally:
147            os.path.exists = orig
148
149
150        self.assertEqual(dyld.dyld_library('/usr/lib/libSystem.dylib', 'libXSystem.dylib'), '/usr/lib/libSystem.dylib')
151
152        os.environ['DYLD_IMAGE_SUFFIX'] = "_debug"
153        self.assertEqual(dyld.dyld_library('/usr/lib/libSystem.dylib', 'libSystem.dylib'), '/usr/lib/libSystem_debug.dylib')
154
155    def test_dyld_framework(self):
156        for k in ('DYLD_FRAMEWORK_PATH', 'DYLD_FALLBACK_FRAMEWORK_PATH', 'DYLD_IMAGE_SUFFIX'):
157            if k in os.environ:
158                del os.environ[k]
159
160        orig = os.path.exists
161        try:
162            os.path.exists = lambda fn: l.append(fn)
163
164            self.maxDiff = None
165
166            l = []
167            self.assertRaises(ImportError, dyld.dyld_framework, "/System/Library/Cocoa.framework/Cocoa", "XCocoa")
168            self.assertEqual(l, [
169                "/System/Library/Cocoa.framework/Cocoa",
170                os.path.expanduser("~/Library/Frameworks/XCocoa.framework/XCocoa"),
171                "/Library/Frameworks/XCocoa.framework/XCocoa",
172                "/Network/Library/Frameworks/XCocoa.framework/XCocoa",
173                "/System/Library/Frameworks/XCocoa.framework/XCocoa",
174            ])
175
176            os.environ["DYLD_IMAGE_SUFFIX"] = "_profile"
177            l = []
178            self.assertRaises(ImportError, dyld.dyld_framework, "/System/Library/Cocoa.framework/Cocoa", "XCocoa")
179            self.assertEqual(l, [
180                "/System/Library/Cocoa.framework/Cocoa_profile",
181                "/System/Library/Cocoa.framework/Cocoa",
182                os.path.expanduser("~/Library/Frameworks/XCocoa.framework/XCocoa_profile"),
183                os.path.expanduser("~/Library/Frameworks/XCocoa.framework/XCocoa"),
184                "/Library/Frameworks/XCocoa.framework/XCocoa_profile",
185                "/Library/Frameworks/XCocoa.framework/XCocoa",
186                "/Network/Library/Frameworks/XCocoa.framework/XCocoa_profile",
187                "/Network/Library/Frameworks/XCocoa.framework/XCocoa",
188                "/System/Library/Frameworks/XCocoa.framework/XCocoa_profile",
189                "/System/Library/Frameworks/XCocoa.framework/XCocoa",
190            ])
191            del os.environ["DYLD_IMAGE_SUFFIX"]
192
193            os.environ["DYLD_FRAMEWORK_PATH"] = "/Projects/Frameworks:/Company"
194            l = []
195            self.assertRaises(ImportError, dyld.dyld_framework, "/System/Library/Cocoa.framework/Cocoa", "XCocoa")
196            self.assertEqual(l, [
197                "/Projects/Frameworks/XCocoa.framework/XCocoa",
198                "/Company/XCocoa.framework/XCocoa",
199                "/System/Library/Cocoa.framework/Cocoa",
200                os.path.expanduser("~/Library/Frameworks/XCocoa.framework/XCocoa"),
201                "/Library/Frameworks/XCocoa.framework/XCocoa",
202                "/Network/Library/Frameworks/XCocoa.framework/XCocoa",
203                "/System/Library/Frameworks/XCocoa.framework/XCocoa",
204            ])
205            del os.environ["DYLD_FRAMEWORK_PATH"]
206
207            os.environ["DYLD_FALLBACK_FRAMEWORK_PATH"] = "/Projects/Frameworks:/Company"
208            l = []
209            self.assertRaises(ImportError, dyld.dyld_framework, "/System/Library/Cocoa.framework/Cocoa", "XCocoa")
210            self.assertEqual(l, [
211                "/System/Library/Cocoa.framework/Cocoa",
212                "/Projects/Frameworks/XCocoa.framework/XCocoa",
213                "/Company/XCocoa.framework/XCocoa",
214            ])
215            del os.environ["DYLD_FALLBACK_FRAMEWORK_PATH"]
216
217            os.environ["DYLD_FRAMEWORK_PATH"] = "/Prefix1:/Prefix2"
218            os.environ["DYLD_FALLBACK_FRAMEWORK_PATH"] = "/Suffix1:/Suffix2"
219            os.environ["DYLD_IMAGE_SUFFIX"] = "_debug"
220
221            l = []
222            self.assertRaises(ImportError, dyld.dyld_framework, "/System/Library/Cocoa.framework/Cocoa", "XCocoa", "B")
223            self.assertEqual(l, [
224                "/Prefix1/XCocoa.framework/Versions/B/XCocoa_debug",
225                "/Prefix1/XCocoa.framework/Versions/B/XCocoa",
226                "/Prefix2/XCocoa.framework/Versions/B/XCocoa_debug",
227                "/Prefix2/XCocoa.framework/Versions/B/XCocoa",
228                "/System/Library/Cocoa.framework/Cocoa_debug",
229                "/System/Library/Cocoa.framework/Cocoa",
230                "/Suffix1/XCocoa.framework/Versions/B/XCocoa_debug",
231                "/Suffix1/XCocoa.framework/Versions/B/XCocoa",
232                "/Suffix2/XCocoa.framework/Versions/B/XCocoa_debug",
233                "/Suffix2/XCocoa.framework/Versions/B/XCocoa",
234            ])
235            del os.environ["DYLD_FRAMEWORK_PATH"]
236            del os.environ["DYLD_FALLBACK_FRAMEWORK_PATH"]
237            del os.environ["DYLD_IMAGE_SUFFIX"]
238
239
240        finally:
241            os.path.exists = orig
242
243        self.assertEqual(dyld.dyld_framework("/System/Library/Cocoa.framework/Cocoa", "Cocoa"), "/System/Library/Frameworks/Cocoa.framework/Cocoa")
244        self.assertEqual(dyld.dyld_framework("/System/Library/Cocoa.framework/Cocoa", "Cocoa", "A"), "/System/Library/Frameworks/Cocoa.framework/Versions/A/Cocoa")
245
246    def test_readlink(self):
247        # Some python versions had a readlink version that doesn't work with unicode
248        # input, ensure that we're not one one of those
249        self.assertEqual(os.path.realpath("/usr/lib/libSystem.dylib"), "/usr/lib/libSystem.B.dylib")
250        self.assertEqual(os.path.realpath(b"/usr/lib/libSystem.dylib"), b"/usr/lib/libSystem.B.dylib")
251        self.assertEqual(os.path.realpath(b"/usr/lib/libSystem.dylib".decode('utf-8')), b"/usr/lib/libSystem.B.dylib".decode('utf-8'))
252
253    def test_dyld_find(self):
254        self.assertEqual(dyld.dyld_find('Cocoa.framework'), '/System/Library/Frameworks/Cocoa.framework/Cocoa')
255        self.assertEqual(dyld.dyld_find('libSystem.dylib'), '/usr/lib/libSystem.dylib')
256
257    def test_pathForFramework(self):
258        self.assertEqual(dyld.pathForFramework('Cocoa.framework'), '/System/Library/Frameworks/Cocoa.framework')
259        self.assertRaises(ImportError, dyld.pathForFramework, 'Foo.framework')
260
261if __name__ == "__main__":
262    main()
263