2020-05-30 17:04:02 +00:00
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
|
|
|
|
import datetime
|
|
|
|
import decimal
|
|
|
|
import os
|
2020-09-16 04:26:10 +00:00
|
|
|
import sys
|
2020-05-30 17:04:02 +00:00
|
|
|
import time
|
|
|
|
import uuid
|
|
|
|
|
2020-09-16 04:26:10 +00:00
|
|
|
import docker
|
|
|
|
import psycopg2 as py_psql
|
|
|
|
import psycopg2.extras
|
|
|
|
import pytest
|
2021-01-22 14:27:23 +00:00
|
|
|
from helpers.cluster import ClickHouseCluster, get_docker_compose_path, run_and_check
|
2020-05-30 17:04:02 +00:00
|
|
|
|
|
|
|
psycopg2.extras.register_uuid()
|
|
|
|
|
|
|
|
SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__))
|
2020-08-07 08:42:04 +00:00
|
|
|
DOCKER_COMPOSE_PATH = get_docker_compose_path()
|
2020-05-30 17:04:02 +00:00
|
|
|
|
|
|
|
cluster = ClickHouseCluster(__file__)
|
2022-03-22 16:39:58 +00:00
|
|
|
node = cluster.add_instance(
|
|
|
|
"node",
|
|
|
|
main_configs=[
|
|
|
|
"configs/postresql.xml",
|
|
|
|
"configs/log.xml",
|
|
|
|
"configs/ssl_conf.xml",
|
|
|
|
"configs/dhparam.pem",
|
|
|
|
"configs/server.crt",
|
|
|
|
"configs/server.key",
|
|
|
|
],
|
|
|
|
user_configs=["configs/default_passwd.xml"],
|
|
|
|
env_variables={"UBSAN_OPTIONS": "print_stacktrace=1"},
|
|
|
|
)
|
2020-05-30 17:04:02 +00:00
|
|
|
|
|
|
|
server_port = 5433
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture(scope="module")
|
|
|
|
def server_address():
|
|
|
|
cluster.start()
|
|
|
|
try:
|
2022-03-22 16:39:58 +00:00
|
|
|
yield cluster.get_instance_ip("node")
|
2020-05-30 17:04:02 +00:00
|
|
|
finally:
|
|
|
|
cluster.shutdown()
|
|
|
|
|
|
|
|
|
2022-03-22 16:39:58 +00:00
|
|
|
@pytest.fixture(scope="module")
|
2020-05-30 17:04:02 +00:00
|
|
|
def psql_client():
|
2022-03-22 16:39:58 +00:00
|
|
|
docker_compose = os.path.join(DOCKER_COMPOSE_PATH, "docker_compose_postgresql.yml")
|
2021-01-22 14:27:23 +00:00
|
|
|
run_and_check(
|
2022-03-22 16:39:58 +00:00
|
|
|
[
|
|
|
|
"docker-compose",
|
|
|
|
"-p",
|
|
|
|
cluster.project_name,
|
|
|
|
"-f",
|
|
|
|
docker_compose,
|
|
|
|
"up",
|
2022-03-31 13:56:07 +00:00
|
|
|
"--force-recreate",
|
2022-03-22 16:39:58 +00:00
|
|
|
"-d",
|
|
|
|
"--build",
|
|
|
|
]
|
|
|
|
)
|
|
|
|
yield docker.DockerClient(
|
|
|
|
base_url="unix:///var/run/docker.sock",
|
|
|
|
version=cluster.docker_api_version,
|
|
|
|
timeout=600,
|
|
|
|
).containers.get(cluster.project_name + "_psql_1")
|
2020-05-30 17:04:02 +00:00
|
|
|
|
|
|
|
|
2022-03-22 16:39:58 +00:00
|
|
|
@pytest.fixture(scope="module")
|
2020-05-30 17:04:02 +00:00
|
|
|
def psql_server(psql_client):
|
|
|
|
"""Return PostgreSQL container when it is healthy."""
|
|
|
|
retries = 30
|
|
|
|
for i in range(retries):
|
|
|
|
info = psql_client.client.api.inspect_container(psql_client.name)
|
2022-03-22 16:39:58 +00:00
|
|
|
if info["State"]["Health"]["Status"] == "healthy":
|
2020-05-30 17:04:02 +00:00
|
|
|
break
|
|
|
|
time.sleep(1)
|
|
|
|
else:
|
2022-03-22 16:39:58 +00:00
|
|
|
print(info["State"])
|
|
|
|
raise Exception(
|
|
|
|
"PostgreSQL server has not started after {} retries.".format(retries)
|
|
|
|
)
|
2020-05-30 17:04:02 +00:00
|
|
|
|
|
|
|
return psql_client
|
|
|
|
|
|
|
|
|
2022-03-22 16:39:58 +00:00
|
|
|
@pytest.fixture(scope="module")
|
2020-05-30 17:04:02 +00:00
|
|
|
def java_container():
|
2022-03-22 16:39:58 +00:00
|
|
|
docker_compose = os.path.join(
|
|
|
|
DOCKER_COMPOSE_PATH, "docker_compose_postgresql_java_client.yml"
|
|
|
|
)
|
2021-01-22 14:27:23 +00:00
|
|
|
run_and_check(
|
2022-03-22 16:39:58 +00:00
|
|
|
[
|
|
|
|
"docker-compose",
|
|
|
|
"-p",
|
|
|
|
cluster.project_name,
|
|
|
|
"-f",
|
|
|
|
docker_compose,
|
|
|
|
"up",
|
2022-03-31 13:56:07 +00:00
|
|
|
"--force-recreate",
|
2022-03-22 16:39:58 +00:00
|
|
|
"-d",
|
|
|
|
"--build",
|
|
|
|
]
|
|
|
|
)
|
|
|
|
yield docker.DockerClient(
|
|
|
|
base_url="unix:///var/run/docker.sock",
|
|
|
|
version=cluster.docker_api_version,
|
|
|
|
timeout=600,
|
|
|
|
).containers.get(cluster.project_name + "_java_1")
|
2020-05-30 17:04:02 +00:00
|
|
|
|
|
|
|
|
|
|
|
def test_psql_is_ready(psql_server):
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
def test_psql_client(psql_client, server_address):
|
2022-03-22 16:39:58 +00:00
|
|
|
cmd_prefix = 'psql "sslmode=require host={server_address} port={server_port} user=default dbname=default password=123" '.format(
|
|
|
|
server_address=server_address, server_port=server_port
|
|
|
|
)
|
2020-05-30 17:04:02 +00:00
|
|
|
cmd_prefix += "--no-align --field-separator=' ' "
|
|
|
|
|
2022-03-22 16:39:58 +00:00
|
|
|
code, (stdout, stderr) = psql_client.exec_run(
|
|
|
|
cmd_prefix + '-c "SELECT 1 as a"', demux=True
|
|
|
|
)
|
|
|
|
assert stdout.decode() == "\n".join(["a", "1", "(1 row)", ""])
|
2020-05-30 17:04:02 +00:00
|
|
|
|
2022-03-22 16:39:58 +00:00
|
|
|
code, (stdout, stderr) = psql_client.exec_run(
|
|
|
|
cmd_prefix + '''-c "SELECT 'колонка' as a"''', demux=True
|
|
|
|
)
|
|
|
|
assert stdout.decode() == "\n".join(["a", "колонка", "(1 row)", ""])
|
2020-05-30 17:04:02 +00:00
|
|
|
|
|
|
|
code, (stdout, stderr) = psql_client.exec_run(
|
2022-03-22 16:39:58 +00:00
|
|
|
cmd_prefix
|
|
|
|
+ "-c "
|
|
|
|
+ """
|
2020-05-30 17:04:02 +00:00
|
|
|
"CREATE DATABASE x;
|
|
|
|
USE x;
|
|
|
|
CREATE TABLE table1 (column UInt32) ENGINE = Memory;
|
|
|
|
INSERT INTO table1 VALUES (0), (1), (5);
|
|
|
|
INSERT INTO table1 VALUES (0), (1), (5);
|
|
|
|
SELECT * FROM table1 ORDER BY column;"
|
2022-03-22 16:39:58 +00:00
|
|
|
""",
|
|
|
|
demux=True,
|
|
|
|
)
|
|
|
|
assert stdout.decode() == "\n".join(
|
|
|
|
["column", "0", "0", "1", "1", "5", "5", "(6 rows)", ""]
|
2020-05-30 17:04:02 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
code, (stdout, stderr) = psql_client.exec_run(
|
2022-03-22 16:39:58 +00:00
|
|
|
cmd_prefix
|
|
|
|
+ "-c "
|
|
|
|
+ """
|
2020-05-30 17:04:02 +00:00
|
|
|
"DROP DATABASE x;
|
|
|
|
CREATE TEMPORARY TABLE tmp (tmp_column UInt32);
|
|
|
|
INSERT INTO tmp VALUES (0), (1);
|
|
|
|
SELECT * FROM tmp ORDER BY tmp_column;"
|
2022-03-22 16:39:58 +00:00
|
|
|
""",
|
|
|
|
demux=True,
|
2020-05-30 17:04:02 +00:00
|
|
|
)
|
2022-03-22 16:39:58 +00:00
|
|
|
assert stdout.decode() == "\n".join(["tmp_column", "0", "1", "(2 rows)", ""])
|
2020-05-30 17:04:02 +00:00
|
|
|
|
|
|
|
|
|
|
|
def test_python_client(server_address):
|
|
|
|
with pytest.raises(py_psql.InternalError) as exc_info:
|
2022-03-22 16:39:58 +00:00
|
|
|
ch = py_psql.connect(
|
|
|
|
host=server_address,
|
|
|
|
port=server_port,
|
|
|
|
user="default",
|
|
|
|
password="123",
|
|
|
|
database="",
|
|
|
|
)
|
2020-05-30 17:04:02 +00:00
|
|
|
cur = ch.cursor()
|
2022-03-22 16:39:58 +00:00
|
|
|
cur.execute("select name from tables;")
|
2020-05-30 17:04:02 +00:00
|
|
|
|
2020-09-16 04:26:10 +00:00
|
|
|
assert exc_info.value.args == (
|
2022-03-22 16:39:58 +00:00
|
|
|
"Query execution failed.\nDB::Exception: Table default.tables doesn't exist\nSSL connection has been closed unexpectedly\n",
|
|
|
|
)
|
2020-05-30 17:04:02 +00:00
|
|
|
|
2022-03-22 16:39:58 +00:00
|
|
|
ch = py_psql.connect(
|
|
|
|
host=server_address,
|
|
|
|
port=server_port,
|
|
|
|
user="default",
|
|
|
|
password="123",
|
|
|
|
database="",
|
|
|
|
)
|
2020-05-30 17:04:02 +00:00
|
|
|
cur = ch.cursor()
|
|
|
|
|
2022-03-22 16:39:58 +00:00
|
|
|
cur.execute("select 1 as a, 2 as b")
|
|
|
|
assert (cur.description[0].name, cur.description[1].name) == ("a", "b")
|
2020-05-30 17:04:02 +00:00
|
|
|
assert cur.fetchall() == [(1, 2)]
|
|
|
|
|
2022-03-22 16:39:58 +00:00
|
|
|
cur.execute("CREATE DATABASE x")
|
|
|
|
cur.execute("USE x")
|
2020-09-16 04:26:10 +00:00
|
|
|
cur.execute(
|
2022-03-22 16:39:58 +00:00
|
|
|
"CREATE TEMPORARY TABLE tmp2 (ch Int8, i64 Int64, f64 Float64, str String, date Date, dec Decimal(19, 10), uuid UUID) ENGINE = Memory"
|
|
|
|
)
|
2020-09-16 04:26:10 +00:00
|
|
|
cur.execute(
|
2022-03-22 16:39:58 +00:00
|
|
|
"insert into tmp2 (ch, i64, f64, str, date, dec, uuid) values (44, 534324234, 0.32423423, 'hello', '2019-01-23', 0.333333, '61f0c404-5cb3-11e7-907b-a6006ad3dba0')"
|
|
|
|
)
|
|
|
|
cur.execute("select * from tmp2")
|
2020-09-16 04:26:10 +00:00
|
|
|
assert cur.fetchall()[0] == (
|
2022-03-22 16:39:58 +00:00
|
|
|
"44",
|
|
|
|
534324234,
|
|
|
|
0.32423423,
|
|
|
|
"hello",
|
|
|
|
datetime.date(2019, 1, 23),
|
|
|
|
decimal.Decimal("0.3333330000"),
|
|
|
|
uuid.UUID("61f0c404-5cb3-11e7-907b-a6006ad3dba0"),
|
|
|
|
)
|
2020-05-30 17:04:02 +00:00
|
|
|
|
|
|
|
|
|
|
|
def test_java_client(server_address, java_container):
|
2022-03-22 16:39:58 +00:00
|
|
|
with open(os.path.join(SCRIPT_DIR, "java.reference")) as fp:
|
2020-05-30 17:04:02 +00:00
|
|
|
reference = fp.read()
|
|
|
|
|
|
|
|
# database not exists exception.
|
2020-09-16 04:26:10 +00:00
|
|
|
code, (stdout, stderr) = java_container.exec_run(
|
2022-03-22 16:39:58 +00:00
|
|
|
"java JavaConnectorTest --host {host} --port {port} --user default --database "
|
|
|
|
"abc".format(host=server_address, port=server_port),
|
|
|
|
demux=True,
|
|
|
|
)
|
2020-05-30 17:04:02 +00:00
|
|
|
assert code == 1
|
|
|
|
|
|
|
|
# non-empty password passed.
|
2020-09-16 04:26:10 +00:00
|
|
|
code, (stdout, stderr) = java_container.exec_run(
|
2022-03-22 16:39:58 +00:00
|
|
|
"java JavaConnectorTest --host {host} --port {port} --user default --password 123 --database "
|
|
|
|
"default".format(host=server_address, port=server_port),
|
|
|
|
demux=True,
|
|
|
|
)
|
2020-05-30 17:04:02 +00:00
|
|
|
print(stdout, stderr, file=sys.stderr)
|
|
|
|
assert code == 0
|
2020-10-02 16:54:07 +00:00
|
|
|
assert stdout.decode() == reference
|