From: Daniele Varrazzo Date: Sat, 16 Jan 2021 02:35:20 +0000 (+0100) Subject: Added leak test for async cursor X-Git-Tag: 3.0.dev0~148 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a13f91d8c2ef07ebecb76d5dcf8aae4c663aa599;p=thirdparty%2Fpsycopg.git Added leak test for async cursor Leak and correctness tests separated. --- diff --git a/tests/test_adapt.py b/tests/test_adapt.py index 366a49b19..222538cda 100644 --- a/tests/test_adapt.py +++ b/tests/test_adapt.py @@ -291,6 +291,27 @@ def test_optimised_adapters(): assert not c_adapters +@pytest.mark.slow +@pytest.mark.parametrize("fmt", [Format.AUTO, Format.TEXT, Format.BINARY]) +def test_random(conn, faker, fmt): + if fmt != Format.BINARY: + pytest.xfail("faker to extend to all text dumpers") + + faker.format = fmt + faker.choose_schema(ncols=20) + faker.make_records(50) + + with conn.cursor(binary=Format.as_pq(fmt)) as cur: + cur.execute(faker.drop_stmt) + cur.execute(faker.create_stmt) + cur.executemany(faker.insert_stmt, faker.records) + cur.execute(faker.select_stmt) + recs = cur.fetchall() + + for got, want in zip(recs, faker.records): + faker.assert_record(got, want) + + class MyStr(str): pass diff --git a/tests/test_cursor.py b/tests/test_cursor.py index b731ef94c..11629afc4 100644 --- a/tests/test_cursor.py +++ b/tests/test_cursor.py @@ -423,29 +423,23 @@ def test_leak(dsn, faker, fmt, fetch): cur.executemany(faker.insert_stmt, faker.records) cur.execute(faker.select_stmt) - recs = [] if fetch == "one": while 1: tmp = cur.fetchone() if tmp is None: break - recs.append(tmp) elif fetch == "many": while 1: tmp = cur.fetchmany(3) if not tmp: break - recs.extend(tmp) elif fetch == "all": - recs.extend(cur.fetchall()) + cur.fetchall() elif fetch == "iter": for rec in cur: - recs.append(rec) + pass - for got, want in zip(recs, faker.records): - faker.assert_record(got, want) - - recs = tmp = None + tmp = None del cur, conn gc.collect() diff --git a/tests/test_cursor_async.py b/tests/test_cursor_async.py index c35e019e0..c9b7f1fee 100644 --- a/tests/test_cursor_async.py +++ b/tests/test_cursor_async.py @@ -314,3 +314,51 @@ async def test_str(aconn): await cur.close() assert "[closed]" in str(cur) assert "[INTRANS]" in str(cur) + + +@pytest.mark.slow +@pytest.mark.parametrize("fmt", [Format.AUTO, Format.TEXT, Format.BINARY]) +@pytest.mark.parametrize("fetch", ["one", "many", "all", "iter"]) +async def test_leak(dsn, faker, fmt, fetch): + if fmt != Format.BINARY: + pytest.xfail("faker to extend to all text dumpers") + + faker.format = fmt + faker.choose_schema(ncols=5) + faker.make_records(10) + + n = [] + for i in range(3): + async with await psycopg3.AsyncConnection.connect(dsn) as conn: + async with await conn.cursor(binary=Format.as_pq(fmt)) as cur: + await cur.execute(faker.drop_stmt) + await cur.execute(faker.create_stmt) + await cur.executemany(faker.insert_stmt, faker.records) + await cur.execute(faker.select_stmt) + + if fetch == "one": + while 1: + tmp = await cur.fetchone() + if tmp is None: + break + elif fetch == "many": + while 1: + tmp = await cur.fetchmany(3) + if not tmp: + break + elif fetch == "all": + await cur.fetchall() + elif fetch == "iter": + async for rec in cur: + pass + + tmp = None + + del cur, conn + gc.collect() + gc.collect() + n.append(len(gc.get_objects())) + + assert ( + n[0] == n[1] == n[2] + ), f"objects leaked: {n[1] - n[0]}, {n[2] - n[1]}"