1 import unittest 2 import os.path 3 import sys 4 import test.support 5 from ctypes import * 6 from ctypes.util import find_library 7 8 # On some systems, loading the OpenGL libraries needs the RTLD_GLOBAL mode. 9 class Test_OpenGL_libs(unittest.TestCase): 10 @classmethod 11 def setUpClass(cls): 12 lib_gl = lib_glu = lib_gle = None 13 if sys.platform == "win32": 14 lib_gl = find_library("OpenGL32") 15 lib_glu = find_library("Glu32") 16 elif sys.platform == "darwin": 17 lib_gl = lib_glu = find_library("OpenGL") 18 else: 19 lib_gl = find_library("GL") 20 lib_glu = find_library("GLU") 21 lib_gle = find_library("gle") 22 23 ## print, for debugging 24 if test.support.verbose: 25 print("OpenGL libraries:") 26 for item in (("GL", lib_gl), 27 ("GLU", lib_glu), 28 ("gle", lib_gle)): 29 print("\t", item) 30 31 cls.gl = cls.glu = cls.gle = None 32 if lib_gl: 33 try: 34 cls.gl = CDLL(lib_gl, mode=RTLD_GLOBAL) 35 except OSError: 36 pass 37 if lib_glu: 38 try: 39 cls.glu = CDLL(lib_glu, RTLD_GLOBAL) 40 except OSError: 41 pass 42 if lib_gle: 43 try: 44 cls.gle = CDLL(lib_gle) 45 except OSError: 46 pass 47 48 @classmethod 49 def tearDownClass(cls): 50 cls.gl = cls.glu = cls.gle = None 51 52 def test_gl(self): 53 if self.gl is None: 54 self.skipTest('lib_gl not available') 55 self.gl.glClearIndex 56 57 def test_glu(self): 58 if self.glu is None: 59 self.skipTest('lib_glu not available') 60 self.glu.gluBeginCurve 61 62 def test_gle(self): 63 if self.gle is None: 64 self.skipTest('lib_gle not available') 65 self.gle.gleGetJoinStyle 66 67 def test_shell_injection(self): 68 result = find_library('; echo Hello shell > ' + test.support.TESTFN) 69 self.assertFalse(os.path.lexists(test.support.TESTFN)) 70 self.assertIsNone(result) 71 72 73 @unittest.skipUnless(sys.platform.startswith('linux'), 74 'Test only valid for Linux') 75 class LibPathFindTest(unittest.TestCase): 76 def test_find_on_libpath(self): 77 import subprocess 78 import tempfile 79 80 try: 81 p = subprocess.Popen(['gcc', '--version'], stdout=subprocess.PIPE, 82 stderr=subprocess.DEVNULL) 83 out, _ = p.communicate() 84 except OSError: 85 raise unittest.SkipTest('gcc, needed for test, not available') 86 with tempfile.TemporaryDirectory() as d: 87 # create an empty temporary file 88 srcname = os.path.join(d, 'dummy.c') 89 libname = 'py_ctypes_test_dummy' 90 dstname = os.path.join(d, 'lib%s.so' % libname) 91 with open(srcname, 'w') as f: 92 pass 93 self.assertTrue(os.path.exists(srcname)) 94 # compile the file to a shared library 95 cmd = ['gcc', '-o', dstname, '--shared', 96 '-Wl,-soname,lib%s.so' % libname, srcname] 97 out = subprocess.check_output(cmd) 98 self.assertTrue(os.path.exists(dstname)) 99 # now check that the .so can't be found (since not in 100 # LD_LIBRARY_PATH) 101 self.assertIsNone(find_library(libname)) 102 # now add the location to LD_LIBRARY_PATH 103 with test.support.EnvironmentVarGuard() as env: 104 KEY = 'LD_LIBRARY_PATH' 105 if KEY not in env: 106 v = d 107 else: 108 v = '%s:%s' % (env[KEY], d) 109 env.set(KEY, v) 110 # now check that the .so can be found (since in 111 # LD_LIBRARY_PATH) 112 self.assertEqual(find_library(libname), 'lib%s.so' % libname) 113 114 115 if __name__ == "__main__": 116 unittest.main() 117