diff options
author | Serhiy Storchaka <storchaka@gmail.com> | 2021-08-08 08:49:44 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-08-08 08:49:44 +0300 |
commit | 0eec6276fdcdde5221370d92b50ea95851760c72 (patch) | |
tree | 35fa0e56f83f404eb2120ec1963c6b5e15813d34 /Lib/sqlite3/test/userfunctions.py | |
parent | ebecffdb6d5fffa4249f9a813f1fc1915926feb5 (diff) | |
download | cpython-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.py | 48 |
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) |