From: Daniele Varrazzo Date: Wed, 25 May 2022 21:12:10 +0000 (+0100) Subject: test(crdb): adapt or skip more tests to CRDB X-Git-Tag: 3.1~49^2~41 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=fd50c958e16599497c657317fc3fc77100db05e7;p=thirdparty%2Fpsycopg.git test(crdb): adapt or skip more tests to CRDB --- diff --git a/tests/fix_crdb.py b/tests/fix_crdb.py index dfa98ad9c..b9e8373f1 100644 --- a/tests/fix_crdb.py +++ b/tests/fix_crdb.py @@ -96,7 +96,7 @@ _crdb_reasons = { "infinity date": 41564, "interval style": 35807, "large objects": 243, - "named cursor": 41412, + "server-side cursor": 41412, "negative interval": 81577, "nested array": 32552, "notify": 41522, diff --git a/tests/fix_psycopg.py b/tests/fix_psycopg.py index 8a4671a9c..0c3b2960a 100644 --- a/tests/fix_psycopg.py +++ b/tests/fix_psycopg.py @@ -24,6 +24,7 @@ def global_adapters(): @pytest.fixture +@pytest.mark.crdb("skip", reason="2-phase commit") def tpc(svcconn): tpc = Tpc(svcconn) tpc.check_tpc() @@ -41,6 +42,11 @@ class Tpc: self.conn = conn def check_tpc(self): + from .fix_crdb import is_crdb, crdb_skip_message + + if is_crdb(self.conn): + pytest.skip(crdb_skip_message("2-phase commit")) + val = int(self.conn.execute("show max_prepared_transactions").fetchone()[0]) if not val: pytest.skip("prepared transactions disabled in the database") diff --git a/tests/pq/test_pipeline.py b/tests/pq/test_pipeline.py index 855801b77..00cd54abe 100644 --- a/tests/pq/test_pipeline.py +++ b/tests/pq/test_pipeline.py @@ -31,9 +31,9 @@ def test_work_in_progress(pgconn): def test_multi_pipelines(pgconn): assert pgconn.pipeline_status == pq.PipelineStatus.OFF pgconn.enter_pipeline_mode() - pgconn.send_query_params(b"select $1", [b"1"]) + pgconn.send_query_params(b"select $1", [b"1"], param_types=[25]) pgconn.pipeline_sync() - pgconn.send_query_params(b"select $1", [b"2"]) + pgconn.send_query_params(b"select $1", [b"2"], param_types=[25]) pgconn.pipeline_sync() # result from first query @@ -77,7 +77,7 @@ def test_multi_pipelines(pgconn): def test_flush_request(pgconn): assert pgconn.pipeline_status == pq.PipelineStatus.OFF pgconn.enter_pipeline_mode() - pgconn.send_query_params(b"select $1", [b"1"]) + pgconn.send_query_params(b"select $1", [b"1"], param_types=[25]) pgconn.send_flush_request() r = pgconn.get_result() assert r.status == pq.ExecStatus.TUPLES_OK diff --git a/tests/test_generators.py b/tests/test_generators.py index c836b428c..b47c620a1 100644 --- a/tests/test_generators.py +++ b/tests/test_generators.py @@ -84,6 +84,8 @@ def pipeline_demo(pgconn): assert res.status == pq.ExecStatus.COMMAND_OK, res.error_message +# TODOCRDB: 1 doesn't get rolled back. Open a ticket? +@pytest.mark.crdb("skip", reason="pipeline aborted") def test_pipeline_communicate_abort(pgconn, pipeline_demo, pipeline, generators): insert_sql = b"insert into pg_pipeline(itemno) values ($1)" commands = deque( diff --git a/tests/test_rows.py b/tests/test_rows.py index a345a5b5b..872c0be5d 100644 --- a/tests/test_rows.py +++ b/tests/test_rows.py @@ -103,6 +103,7 @@ def test_no_result(factory, conn): cur.fetchone() +@pytest.mark.crdb("skip", reason="no col query") @pytest.mark.parametrize( "factory", "tuple_row dict_row namedtuple_row args_row".split() ) @@ -114,6 +115,7 @@ def test_no_column(factory, conn): assert not recs[0] +@pytest.mark.crdb("skip") def test_no_column_class_row(conn): class Empty: def __init__(self, x=10, y=20): diff --git a/tests/test_server_cursor.py b/tests/test_server_cursor.py index fd47b684d..ca8fd59b8 100644 --- a/tests/test_server_cursor.py +++ b/tests/test_server_cursor.py @@ -4,6 +4,8 @@ import psycopg from psycopg import rows, errors as e from psycopg.pq import Format +pytestmark = pytest.mark.crdb("skip", reason="server-side cursor") + def test_init_row_factory(conn): with psycopg.ServerCursor(conn, "foo") as cur: diff --git a/tests/test_server_cursor_async.py b/tests/test_server_cursor_async.py index 396e48149..e74c15a8b 100644 --- a/tests/test_server_cursor_async.py +++ b/tests/test_server_cursor_async.py @@ -4,7 +4,10 @@ import psycopg from psycopg import rows, errors as e from psycopg.pq import Format -pytestmark = pytest.mark.asyncio +pytestmark = [ + pytest.mark.asyncio, + pytest.mark.crdb("skip", reason="server-side cursor"), +] async def test_init_row_factory(aconn): diff --git a/tests/test_sql.py b/tests/test_sql.py index 43a58aa27..991e43500 100644 --- a/tests/test_sql.py +++ b/tests/test_sql.py @@ -14,6 +14,9 @@ from psycopg.types import TypeInfo from psycopg.types.string import StrDumper from .utils import eur +from .fix_crdb import crdb_encoding + +crdb_skip_scs = pytest.mark.crdb("skip", reason="standard_conforming_strings=off") @pytest.mark.parametrize( @@ -30,7 +33,7 @@ def test_quote(obj, quoted): assert sql.quote(obj) == quoted -@pytest.mark.parametrize("scs", ["on", "off"]) +@pytest.mark.parametrize("scs", ["on", pytest.param("off", marks=crdb_skip_scs)]) def test_quote_roundtrip(conn, scs): messages = [] conn.add_notice_handler(lambda msg: messages.append(msg.message_primary)) @@ -46,6 +49,7 @@ def test_quote_roundtrip(conn, scs): assert not messages, f"error with {want!r}" +@crdb_skip_scs def test_quote_stable_despite_deranged_libpq(conn): # Verify the libpq behaviour of PQescapeString using the last setting seen. # Check that we are not affected by it. @@ -207,6 +211,7 @@ class TestSqlFormat: cur.execute("select * from test_compose") assert cur.fetchall() == [(10, "a", "b", "c"), (20, "d", "e", "f")] + @pytest.mark.crdb("skip", reason="copy") def test_copy(self, conn): cur = conn.cursor() cur.execute( @@ -278,11 +283,11 @@ class TestIdentifier: @pytest.mark.parametrize( "args, want, enc", [ - (("foo",), '"foo"', "ascii"), - (("foo", "bar"), '"foo"."bar"', "ascii"), - (("fo'o", 'ba"r'), '"fo\'o"."ba""r"', "ascii"), + crdb_encoding(("foo",), '"foo"', "ascii"), + crdb_encoding(("foo", "bar"), '"foo"."bar"', "ascii"), + crdb_encoding(("fo'o", 'ba"r'), '"fo\'o"."ba""r"', "ascii"), (("foo", eur), f'"foo"."{eur}"', "utf8"), - (("foo", eur), f'"foo"."{eur}"', "latin9"), + crdb_encoding(("foo", eur), f'"foo"."{eur}"', "latin9"), ], ) def test_as_bytes(self, conn, args, want, enc): @@ -321,10 +326,10 @@ class TestLiteral: assert sql.Literal(42).as_bytes(conn) == b"42" assert sql.Literal(dt.date(2017, 1, 1)).as_bytes(conn) == b"'2017-01-01'::date" - conn.execute("set client_encoding to utf8") - assert sql.Literal(eur).as_bytes(conn) == f"'{eur}'".encode() - conn.execute("set client_encoding to latin9") - assert sql.Literal(eur).as_bytes(conn) == f"'{eur}'".encode("latin9") + @pytest.mark.parametrize("encoding", ["utf8", crdb_encoding("latin9")]) + def test_as_bytes_encoding(self, conn, encoding): + conn.execute(f"set client_encoding to {encoding}") + assert sql.Literal(eur).as_bytes(conn) == f"'{eur}'".encode(encoding) def test_eq(self): assert sql.Literal("foo") == sql.Literal("foo") @@ -360,6 +365,7 @@ class TestLiteral: conn.adapters.register_dumper(str, StrDumper) assert sql.Literal("foo").as_string(conn) == "'foo'" + @pytest.mark.crdb("skip", reason="composite") # create type, actually @pytest.mark.parametrize("name", ["a-b", f"{eur}", "order", "foo bar"]) def test_invalid_name(self, conn, name): conn.execute( @@ -454,14 +460,12 @@ class TestSQL: def test_as_string(self, conn): assert sql.SQL("foo").as_string(conn) == "foo" - def test_as_bytes(self, conn): - assert sql.SQL("foo").as_bytes(conn) == b"foo" - - conn.execute("set client_encoding to utf8") - assert sql.SQL(eur).as_bytes(conn) == eur.encode() + @pytest.mark.parametrize("encoding", ["utf8", crdb_encoding("latin9")]) + def test_as_bytes(self, conn, encoding): + if encoding: + conn.execute(f"set client_encoding to {encoding}") - conn.execute("set client_encoding to latin9") - assert sql.SQL(eur).as_bytes(conn) == eur.encode("latin9") + assert sql.SQL(eur).as_bytes(conn) == eur.encode(encoding) class TestComposed: @@ -527,13 +531,11 @@ class TestComposed: obj = sql.Composed([sql.SQL("foo"), sql.SQL("bar")]) assert obj.as_bytes(conn) == b"foobar" + @pytest.mark.parametrize("encoding", ["utf8", crdb_encoding("latin9")]) + def test_as_bytes_encoding(self, conn, encoding): obj = sql.Composed([sql.SQL("foo"), sql.SQL(eur)]) - - conn.execute("set client_encoding to utf8") - assert obj.as_bytes(conn) == ("foo" + eur).encode() - - conn.execute("set client_encoding to latin9") - assert obj.as_bytes(conn) == ("foo" + eur).encode("latin9") + conn.execute(f"set client_encoding to {encoding}") + assert obj.as_bytes(conn) == ("foo" + eur).encode(encoding) class TestPlaceholder: diff --git a/tests/test_transaction.py b/tests/test_transaction.py index 788b9270e..4879a86d4 100644 --- a/tests/test_transaction.py +++ b/tests/test_transaction.py @@ -141,6 +141,7 @@ def test_rollback_on_exception_exit(conn): assert not inserted(conn) +@pytest.mark.crdb("skip", reason="pg_terminate_backend") def test_context_inerror_rollback_no_clobber(conn, pipeline, dsn, caplog): if pipeline: # Only 'conn' is possibly in pipeline mode, but the transaction and @@ -164,6 +165,7 @@ def test_context_inerror_rollback_no_clobber(conn, pipeline, dsn, caplog): assert "in rollback" in rec.message +@pytest.mark.crdb("skip", reason="copy") def test_context_active_rollback_no_clobber(dsn, caplog): caplog.set_level(logging.WARNING, logger="psycopg") diff --git a/tests/test_typeinfo.py b/tests/test_typeinfo.py index d0316ad3a..544e49f98 100644 --- a/tests/test_typeinfo.py +++ b/tests/test_typeinfo.py @@ -72,6 +72,7 @@ async def test_fetch_not_found_async(aconn, name, status): assert info is None +@pytest.mark.crdb("skip", reason="composite") @pytest.mark.parametrize( "name", ["testschema.testtype", sql.Identifier("testschema", "testtype")] )