summaryrefslogtreecommitdiffstats
path: root/Lib/test
diff options
context:
space:
mode:
authorBénédikt Tran <10796600+picnixz@users.noreply.github.com>2024-12-17 11:12:45 (GMT)
committerGitHub <noreply@github.com>2024-12-17 11:12:45 (GMT)
commit7303f06846b69016a075bca7ad7c6055f29ad024 (patch)
treefa3abb9f0a3b3b18bbd60590cbfb1c3c6a91d70f /Lib/test
parentb9a492b809d8765ee365a5dd3c6ba4e5130a80af (diff)
downloadcpython-7303f06846b69016a075bca7ad7c6055f29ad024.zip
cpython-7303f06846b69016a075bca7ad7c6055f29ad024.tar.gz
cpython-7303f06846b69016a075bca7ad7c6055f29ad024.tar.bz2
gh-126742: Add _PyErr_SetLocaleString, use it for gdbm & dlerror messages (GH-126746)
- Add a helper to set an error from locale-encoded `char*` - Use the helper for gdbm & dlerror messages Co-authored-by: Victor Stinner <vstinner@python.org>
Diffstat (limited to 'Lib/test')
-rw-r--r--Lib/test/test_ctypes/test_dlerror.py80
-rw-r--r--Lib/test/test_dbm_gnu.py21
2 files changed, 86 insertions, 15 deletions
diff --git a/Lib/test/test_ctypes/test_dlerror.py b/Lib/test/test_ctypes/test_dlerror.py
index 4441e30..c3c34d4 100644
--- a/Lib/test/test_ctypes/test_dlerror.py
+++ b/Lib/test/test_ctypes/test_dlerror.py
@@ -1,7 +1,12 @@
+import _ctypes
import os
+import platform
import sys
+import test.support
import unittest
-import platform
+from ctypes import CDLL, c_int
+from ctypes.util import find_library
+
FOO_C = r"""
#include <unistd.h>
@@ -26,7 +31,7 @@ void *foo(void)
@unittest.skipUnless(sys.platform.startswith('linux'),
- 'Test only valid for Linux')
+ 'test requires GNU IFUNC support')
class TestNullDlsym(unittest.TestCase):
"""GH-126554: Ensure that we catch NULL dlsym return values
@@ -53,14 +58,6 @@ class TestNullDlsym(unittest.TestCase):
import subprocess
import tempfile
- # To avoid ImportErrors on Windows, where _ctypes does not have
- # dlopen and dlsym,
- # import here, i.e., inside the test function.
- # The skipUnless('linux') decorator ensures that we're on linux
- # if we're executing these statements.
- from ctypes import CDLL, c_int
- from _ctypes import dlopen, dlsym
-
retcode = subprocess.call(["gcc", "--version"],
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL)
@@ -111,6 +108,8 @@ class TestNullDlsym(unittest.TestCase):
self.assertEqual(os.read(pipe_r, 2), b'OK')
# Case #3: Test 'py_dl_sym' from Modules/_ctypes/callproc.c
+ dlopen = test.support.get_attribute(_ctypes, 'dlopen')
+ dlsym = test.support.get_attribute(_ctypes, 'dlsym')
L = dlopen(dstname)
with self.assertRaisesRegex(OSError, "symbol 'foo' not found"):
dlsym(L, "foo")
@@ -119,5 +118,66 @@ class TestNullDlsym(unittest.TestCase):
self.assertEqual(os.read(pipe_r, 2), b'OK')
+@unittest.skipUnless(os.name != 'nt', 'test requires dlerror() calls')
+class TestLocalization(unittest.TestCase):
+
+ @staticmethod
+ def configure_locales(func):
+ return test.support.run_with_locale(
+ 'LC_ALL',
+ 'fr_FR.iso88591', 'ja_JP.sjis', 'zh_CN.gbk',
+ 'fr_FR.utf8', 'en_US.utf8',
+ '',
+ )(func)
+
+ @classmethod
+ def setUpClass(cls):
+ cls.libc_filename = find_library("c")
+
+ @configure_locales
+ def test_localized_error_from_dll(self):
+ dll = CDLL(self.libc_filename)
+ with self.assertRaises(AttributeError) as cm:
+ dll.this_name_does_not_exist
+ if sys.platform.startswith('linux'):
+ # On macOS, the filename is not reported by dlerror().
+ self.assertIn(self.libc_filename, str(cm.exception))
+
+ @configure_locales
+ def test_localized_error_in_dll(self):
+ dll = CDLL(self.libc_filename)
+ with self.assertRaises(ValueError) as cm:
+ c_int.in_dll(dll, 'this_name_does_not_exist')
+ if sys.platform.startswith('linux'):
+ # On macOS, the filename is not reported by dlerror().
+ self.assertIn(self.libc_filename, str(cm.exception))
+
+ @unittest.skipUnless(hasattr(_ctypes, 'dlopen'),
+ 'test requires _ctypes.dlopen()')
+ @configure_locales
+ def test_localized_error_dlopen(self):
+ missing_filename = b'missing\xff.so'
+ # Depending whether the locale, we may encode '\xff' differently
+ # but we are only interested in avoiding a UnicodeDecodeError
+ # when reporting the dlerror() error message which contains
+ # the localized filename.
+ filename_pattern = r'missing.*?\.so'
+ with self.assertRaisesRegex(OSError, filename_pattern):
+ _ctypes.dlopen(missing_filename, 2)
+
+ @unittest.skipUnless(hasattr(_ctypes, 'dlopen'),
+ 'test requires _ctypes.dlopen()')
+ @unittest.skipUnless(hasattr(_ctypes, 'dlsym'),
+ 'test requires _ctypes.dlsym()')
+ @configure_locales
+ def test_localized_error_dlsym(self):
+ dll = _ctypes.dlopen(self.libc_filename)
+ with self.assertRaises(OSError) as cm:
+ _ctypes.dlsym(dll, 'this_name_does_not_exist')
+ if sys.platform.startswith('linux'):
+ # On macOS, the filename is not reported by dlerror().
+ self.assertIn(self.libc_filename, str(cm.exception))
+
+
if __name__ == "__main__":
unittest.main()
diff --git a/Lib/test/test_dbm_gnu.py b/Lib/test/test_dbm_gnu.py
index e20addf..66268c4 100644
--- a/Lib/test/test_dbm_gnu.py
+++ b/Lib/test/test_dbm_gnu.py
@@ -1,10 +1,11 @@
-from test import support
-from test.support import import_helper, cpython_only
-gdbm = import_helper.import_module("dbm.gnu") #skip if not supported
-import unittest
import os
-from test.support.os_helper import TESTFN, TESTFN_NONASCII, unlink, FakePath
+import unittest
+from test import support
+from test.support import cpython_only, import_helper
+from test.support.os_helper import (TESTFN, TESTFN_NONASCII, FakePath,
+ create_empty_file, temp_dir, unlink)
+gdbm = import_helper.import_module("dbm.gnu") # skip if not supported
filename = TESTFN
@@ -205,6 +206,16 @@ class TestGdbm(unittest.TestCase):
self.assertNotIn(k, db)
self.assertEqual(len(db), 0)
+ @support.run_with_locale(
+ 'LC_ALL',
+ 'fr_FR.iso88591', 'ja_JP.sjis', 'zh_CN.gbk',
+ 'fr_FR.utf8', 'en_US.utf8',
+ '',
+ )
+ def test_localized_error(self):
+ with temp_dir() as d:
+ create_empty_file(os.path.join(d, 'test'))
+ self.assertRaises(gdbm.error, gdbm.open, filename, 'r')
if __name__ == '__main__':