]> git.ipfire.org Git - thirdparty/psycopg.git/commitdiff
test(crdb): adapt or skip more tests to CRDB
authorDaniele Varrazzo <daniele.varrazzo@gmail.com>
Wed, 25 May 2022 21:12:10 +0000 (22:12 +0100)
committerDaniele Varrazzo <daniele.varrazzo@gmail.com>
Tue, 12 Jul 2022 11:58:34 +0000 (12:58 +0100)
tests/fix_crdb.py
tests/fix_psycopg.py
tests/pq/test_pipeline.py
tests/test_generators.py
tests/test_rows.py
tests/test_server_cursor.py
tests/test_server_cursor_async.py
tests/test_sql.py
tests/test_transaction.py
tests/test_typeinfo.py

index dfa98ad9c35148b2a7457a439a0960bdcba5bf23..b9e8373f11db1ddb47463a0372f425a8f7fc18fb 100644 (file)
@@ -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,
index 8a4671a9c973d152d84f3efc5aa1cb39956e13d9..0c3b2960ac9522197bcb5d48149970eddd0d9ff6 100644 (file)
@@ -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")
index 855801b770039e2d94bf4048c06e7c80951862f3..00cd54abef810d714becdcbc5e1e9c93d0d01b83 100644 (file)
@@ -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
index c836b428c3ef98c1d5d2ef3a10849e406eb12725..b47c620a11da149e07f2f757b98d3b61f090087f 100644 (file)
@@ -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(
index a345a5b5b4afc801081176616ce324b943874f51..872c0be5d4eecac9c0122bcc78eb81552f04ad44 100644 (file)
@@ -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):
index fd47b684d35a5bbd188c02aedcdb457067f955a9..ca8fd59b8b67c9c5dd4fb953007c0b1061311095 100644 (file)
@@ -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:
index 396e48149d75d4f8d4571173ddc390e991a19292..e74c15a8b63762ab7db64d64e58a730cd9e25dac 100644 (file)
@@ -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):
index 43a58aa27e83c2e581be10c3674ebc9df43cf913..991e435007355f86eec7eb0b97906ef62d32697a 100644 (file)
@@ -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:
index 788b9270eaa360d4f6bfa43081e3d74eaa0c5e89..4879a86d41eb04aafc7b248748af9b173992b518 100644 (file)
@@ -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")
 
index d0316ad3abb5690553ed936aacf8391ec9b89d0b..544e49f98bc1708ccd42b24e5620c40629f128b5 100644 (file)
@@ -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")]
 )