aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/Lib/sqlite3/test/userfunctions.py
diff options
context:
space:
mode:
authorSerhiy Storchaka <storchaka@gmail.com>2021-08-08 08:49:44 +0300
committerGitHub <noreply@github.com>2021-08-08 08:49:44 +0300
commit0eec6276fdcdde5221370d92b50ea95851760c72 (patch)
tree35fa0e56f83f404eb2120ec1963c6b5e15813d34 /Lib/sqlite3/test/userfunctions.py
parentebecffdb6d5fffa4249f9a813f1fc1915926feb5 (diff)
downloadcpython-0eec6276fdcdde5221370d92b50ea95851760c72.tar.gz
cpython-0eec6276fdcdde5221370d92b50ea95851760c72.zip
bpo-44859: Improve error handling in sqlite3 and and raise more accurate exceptions. (GH-27654)
* MemoryError is now raised instead of sqlite3.Warning when memory is not enough for encoding a statement to UTF-8 in Connection.__call__() and Cursor.execute(). * UnicodEncodeError is now raised instead of sqlite3.Warning when the statement contains surrogate characters in Connection.__call__() and Cursor.execute(). * TypeError is now raised instead of ValueError for non-string script argument in Cursor.executescript(). * ValueError is now raised for script containing the null character instead of truncating it in Cursor.executescript(). * Correctly handle exceptions raised when getting boolean value of the result of the progress handler. * Add many tests covering different corner cases. Co-authored-by: Erlend Egeberg Aasland <erlend.aasland@innova.no>
Diffstat (limited to 'Lib/sqlite3/test/userfunctions.py')
-rw-r--r--Lib/sqlite3/test/userfunctions.py48
1 files changed, 37 insertions, 11 deletions
diff --git a/Lib/sqlite3/test/userfunctions.py b/Lib/sqlite3/test/userfunctions.py
index 9681dbdde2b..b4d5181777e 100644
--- a/Lib/sqlite3/test/userfunctions.py
+++ b/Lib/sqlite3/test/userfunctions.py
@@ -33,28 +33,37 @@ import sqlite3 as sqlite
from test.support import bigmemtest
-def with_tracebacks(strings):
+def with_tracebacks(strings, traceback=True):
"""Convenience decorator for testing callback tracebacks."""
- strings.append('Traceback')
+ if traceback:
+ strings.append('Traceback')
def decorator(func):
@functools.wraps(func)
def wrapper(self, *args, **kwargs):
# First, run the test with traceback enabled.
- sqlite.enable_callback_tracebacks(True)
- buf = io.StringIO()
- with contextlib.redirect_stderr(buf):
+ with check_tracebacks(self, strings):
func(self, *args, **kwargs)
- tb = buf.getvalue()
- for s in strings:
- self.assertIn(s, tb)
# Then run the test with traceback disabled.
- sqlite.enable_callback_tracebacks(False)
func(self, *args, **kwargs)
return wrapper
return decorator
+@contextlib.contextmanager
+def check_tracebacks(self, strings):
+ """Convenience context manager for testing callback tracebacks."""
+ sqlite.enable_callback_tracebacks(True)
+ try:
+ buf = io.StringIO()
+ with contextlib.redirect_stderr(buf):
+ yield
+ tb = buf.getvalue()
+ for s in strings:
+ self.assertIn(s, tb)
+ finally:
+ sqlite.enable_callback_tracebacks(False)
+
def func_returntext():
return "foo"
def func_returntextwithnull():
@@ -408,9 +417,26 @@ class FunctionTests(unittest.TestCase):
del x,y
gc.collect()
+ def test_func_return_too_large_int(self):
+ cur = self.con.cursor()
+ for value in 2**63, -2**63-1, 2**64:
+ self.con.create_function("largeint", 0, lambda value=value: value)
+ with check_tracebacks(self, ['OverflowError']):
+ with self.assertRaises(sqlite.DataError):
+ cur.execute("select largeint()")
+
+ def test_func_return_text_with_surrogates(self):
+ cur = self.con.cursor()
+ self.con.create_function("pychr", 1, chr)
+ for value in 0xd8ff, 0xdcff:
+ with check_tracebacks(self,
+ ['UnicodeEncodeError', 'surrogates not allowed']):
+ with self.assertRaises(sqlite.OperationalError):
+ cur.execute("select pychr(?)", (value,))
+
@unittest.skipUnless(sys.maxsize > 2**32, 'requires 64bit platform')
@bigmemtest(size=2**31, memuse=3, dry_run=False)
- def test_large_text(self, size):
+ def test_func_return_too_large_text(self, size):
cur = self.con.cursor()
for size in 2**31-1, 2**31:
self.con.create_function("largetext", 0, lambda size=size: "b" * size)
@@ -419,7 +445,7 @@ class FunctionTests(unittest.TestCase):
@unittest.skipUnless(sys.maxsize > 2**32, 'requires 64bit platform')
@bigmemtest(size=2**31, memuse=2, dry_run=False)
- def test_large_blob(self, size):
+ def test_func_return_too_large_blob(self, size):
cur = self.con.cursor()
for size in 2**31-1, 2**31:
self.con.create_function("largeblob", 0, lambda size=size: b"b" * size)