| 360 | |
| 361 | @pytest.mark.crdb_skip("backend pid") |
| 362 | def test_fail_rollback_close(dsn, caplog, monkeypatch): |
| 363 | caplog.set_level(logging.WARNING, logger="psycopg.pool") |
| 364 | pids = [] |
| 365 | |
| 366 | def worker(): |
| 367 | with p.connection() as conn: |
| 368 | pids.append(conn.info.backend_pid) |
| 369 | assert conn.info.transaction_status == TransactionStatus.IDLE |
| 370 | |
| 371 | with pool.NullConnectionPool(dsn, max_size=1) as p: |
| 372 | conn = p.getconn() |
| 373 | t = spawn(worker) |
| 374 | ensure_waiting(p) |
| 375 | |
| 376 | def bad_rollback(): |
| 377 | conn.pgconn.finish() |
| 378 | orig_rollback() |
| 379 | |
| 380 | # Make the rollback fail |
| 381 | orig_rollback = conn.rollback |
| 382 | monkeypatch.setattr(conn, "rollback", bad_rollback) |
| 383 | |
| 384 | pids.append(conn.info.backend_pid) |
| 385 | with pytest.raises(psycopg.ProgrammingError): |
| 386 | conn.execute("wat") |
| 387 | assert conn.info.transaction_status == TransactionStatus.INERROR |
| 388 | p.putconn(conn) |
| 389 | gather(t) |
| 390 | |
| 391 | assert pids[0] != pids[1] |
| 392 | assert len(caplog.records) == 3 |
| 393 | assert "INERROR" in caplog.records[0].message |
| 394 | assert "OperationalError" in caplog.records[1].message |
| 395 | assert "BAD" in caplog.records[2].message |
| 396 | |
| 397 | |
| 398 | def test_closed_putconn(dsn): |