Skip to content

Commit

Permalink
proxy http: reproduce issue with transactions in pool (neondatabase#5293
Browse files Browse the repository at this point in the history
)

xfail test reproducing issue neondatabase#4698
  • Loading branch information
bojanserafimov committed Sep 12, 2023
1 parent 3b6b847 commit 8556d94
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 16 deletions.
22 changes: 22 additions & 0 deletions test_runner/fixtures/neon_fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -2136,6 +2136,28 @@ def wait_for_exit(self, timeout=2):
def _wait_until_ready(self):
requests.get(f"http://{self.host}:{self.http_port}/v1/status")

def http_query(self, query, args, **kwargs):
# TODO maybe use default values if not provided
user = kwargs["user"]
password = kwargs["password"]
expected_code = kwargs.get("expected_code")

connstr = f"postgresql://{user}:{password}@{self.domain}:{self.proxy_port}/postgres"
response = requests.post(
f"https://{self.domain}:{self.external_http_port}/sql",
data=json.dumps({"query": query, "params": args}),
headers={
"Content-Type": "application/sql",
"Neon-Connection-String": connstr,
"Neon-Pool-Opt-In": "true",
},
verify=str(self.test_output_dir / "proxy.crt"),
)

if expected_code is not None:
assert response.status_code == kwargs["expected_code"], f"response: {response.json()}"
return response.json()

def get_metrics(self) -> str:
request_result = requests.get(f"http://{self.host}:{self.http_port}/metrics")
request_result.raise_for_status()
Expand Down
42 changes: 26 additions & 16 deletions test_runner/regress/test_proxy.py
Original file line number Diff line number Diff line change
Expand Up @@ -346,23 +346,13 @@ def test_sql_over_http_pool(static_proxy: NeonProxy):
static_proxy.safe_psql("create user http_auth with password 'http' superuser")

def get_pid(status: int, pw: str) -> Any:
connstr = (
f"postgresql://http_auth:{pw}@{static_proxy.domain}:{static_proxy.proxy_port}/postgres"
)
response = requests.post(
f"https://{static_proxy.domain}:{static_proxy.external_http_port}/sql",
data=json.dumps(
{"query": "SELECT pid FROM pg_stat_activity WHERE state = 'active'", "params": []}
),
headers={
"Content-Type": "application/sql",
"Neon-Connection-String": connstr,
"Neon-Pool-Opt-In": "true",
},
verify=str(static_proxy.test_output_dir / "proxy.crt"),
return static_proxy.http_query(
"SELECT pid FROM pg_stat_activity WHERE state = 'active'",
[],
user="http_auth",
password=pw,
expected_code=status,
)
assert response.status_code == status
return response.json()

pid1 = get_pid(200, "http")["rows"][0]["pid"]

Expand All @@ -387,3 +377,23 @@ def get_pid(status: int, pw: str) -> Any:
# old password should not work
res = get_pid(400, "http")
assert "password authentication failed for user" in res["message"]


# Beginning a transaction should not impact the next query,
# which might come from a completely different client.
@pytest.mark.xfail(reason="not implemented")
def test_http_pool_begin(static_proxy: NeonProxy):
static_proxy.safe_psql("create user http_auth with password 'http' superuser")

def query(status: int, query: str, *args) -> Any:
static_proxy.http_query(
query,
args,
user="http_auth",
password="http",
expected_code=status,
)

query(200, "BEGIN;")
query(400, "garbage-lol(&(&(&(&") # Intentional error to break the transaction
query(200, "SELECT 1;") # Query that should succeed regardless of the transaction

0 comments on commit 8556d94

Please sign in to comment.