Home | History | Annotate | Download | only in test
      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