From 038e52096011b42f1ea2e6004b4449187e95a1ee Mon Sep 17 00:00:00 2001 From: Vitaly Baranov Date: Sat, 29 Feb 2020 15:57:52 +0300 Subject: [PATCH] Add tests. --- dbms/tests/integration/helpers/client.py | 17 ++++++---- dbms/tests/integration/helpers/cluster.py | 22 +++++++------ .../test_allowed_client_hosts/test.py | 2 +- .../test_authentication/__init__.py | 0 .../integration/test_authentication/test.py | 32 +++++++++++++++++++ .../integration/test_mysql_protocol/test.py | 4 +-- 6 files changed, 57 insertions(+), 20 deletions(-) create mode 100644 dbms/tests/integration/test_authentication/__init__.py create mode 100644 dbms/tests/integration/test_authentication/test.py diff --git a/dbms/tests/integration/helpers/client.py b/dbms/tests/integration/helpers/client.py index e986a9ef7c8..10962cfb724 100644 --- a/dbms/tests/integration/helpers/client.py +++ b/dbms/tests/integration/helpers/client.py @@ -17,11 +17,11 @@ class Client: self.command += ['--host', self.host, '--port', str(self.port), '--stacktrace'] - def query(self, sql, stdin=None, timeout=None, settings=None, user=None, ignore_error=False): - return self.get_query_request(sql, stdin=stdin, timeout=timeout, settings=settings, user=user, ignore_error=ignore_error).get_answer() + def query(self, sql, stdin=None, timeout=None, settings=None, user=None, password=None, ignore_error=False): + return self.get_query_request(sql, stdin=stdin, timeout=timeout, settings=settings, user=user, password=password, ignore_error=ignore_error).get_answer() - def get_query_request(self, sql, stdin=None, timeout=None, settings=None, user=None, ignore_error=False): + def get_query_request(self, sql, stdin=None, timeout=None, settings=None, user=None, password=None, ignore_error=False): command = self.command[:] if stdin is None: @@ -37,15 +37,18 @@ class Client: if user is not None: command += ['--user', user] + if password is not None: + command += ['--password', password] + return CommandRequest(command, stdin, timeout, ignore_error) - def query_and_get_error(self, sql, stdin=None, timeout=None, settings=None, user=None): - return self.get_query_request(sql, stdin=stdin, timeout=timeout, settings=settings, user=user).get_error() + def query_and_get_error(self, sql, stdin=None, timeout=None, settings=None, user=None, password=None): + return self.get_query_request(sql, stdin=stdin, timeout=timeout, settings=settings, user=user, password=password).get_error() - def query_and_get_answer_with_error(self, sql, stdin=None, timeout=None, settings=None, user=None): - return self.get_query_request(sql, stdin=stdin, timeout=timeout, settings=settings, user=user).get_answer_and_error() + def query_and_get_answer_with_error(self, sql, stdin=None, timeout=None, settings=None, user=None, password=None): + return self.get_query_request(sql, stdin=stdin, timeout=timeout, settings=settings, user=user, password=password).get_answer_and_error() class QueryTimeoutExceedException(Exception): pass diff --git a/dbms/tests/integration/helpers/cluster.py b/dbms/tests/integration/helpers/cluster.py index 991a359967b..bc736ee9990 100644 --- a/dbms/tests/integration/helpers/cluster.py +++ b/dbms/tests/integration/helpers/cluster.py @@ -619,15 +619,15 @@ class ClickHouseInstance: self.with_installed_binary = with_installed_binary # Connects to the instance via clickhouse-client, sends a query (1st argument) and returns the answer - def query(self, sql, stdin=None, timeout=None, settings=None, user=None, ignore_error=False): - return self.client.query(sql, stdin, timeout, settings, user, ignore_error) + def query(self, sql, stdin=None, timeout=None, settings=None, user=None, password=None, ignore_error=False): + return self.client.query(sql, stdin, timeout, settings, user, password, ignore_error) - def query_with_retry(self, sql, stdin=None, timeout=None, settings=None, user=None, ignore_error=False, + def query_with_retry(self, sql, stdin=None, timeout=None, settings=None, user=None, password=None, ignore_error=False, retry_count=20, sleep_time=0.5, check_callback=lambda x: True): result = None for i in range(retry_count): try: - result = self.query(sql, stdin, timeout, settings, user, ignore_error) + result = self.query(sql, stdin, timeout, settings, user, password, ignore_error) if check_callback(result): return result time.sleep(sleep_time) @@ -644,15 +644,15 @@ class ClickHouseInstance: return self.client.get_query_request(*args, **kwargs) # Connects to the instance via clickhouse-client, sends a query (1st argument), expects an error and return its code - def query_and_get_error(self, sql, stdin=None, timeout=None, settings=None, user=None): - return self.client.query_and_get_error(sql, stdin, timeout, settings, user) + def query_and_get_error(self, sql, stdin=None, timeout=None, settings=None, user=None, password=None): + return self.client.query_and_get_error(sql, stdin, timeout, settings, user, password) # The same as query_and_get_error but ignores successful query. - def query_and_get_answer_with_error(self, sql, stdin=None, timeout=None, settings=None, user=None): - return self.client.query_and_get_answer_with_error(sql, stdin, timeout, settings, user) + def query_and_get_answer_with_error(self, sql, stdin=None, timeout=None, settings=None, user=None, password=None): + return self.client.query_and_get_answer_with_error(sql, stdin, timeout, settings, user, password) # Connects to the instance via HTTP interface, sends a query and returns the answer - def http_query(self, sql, data=None, params=None, user=None): + def http_query(self, sql, data=None, params=None, user=None, password=None): if params is None: params = {} else: @@ -661,7 +661,9 @@ class ClickHouseInstance: params["query"] = sql auth = "" - if user: + if user and password: + auth = "{}:{}@".format(user, password) + elif user: auth = "{}@".format(user) url = "http://" + auth + self.ip_address + ":8123/?" + urllib.urlencode(params) diff --git a/dbms/tests/integration/test_allowed_client_hosts/test.py b/dbms/tests/integration/test_allowed_client_hosts/test.py index fcdf408c88a..23f7f0a4abd 100644 --- a/dbms/tests/integration/test_allowed_client_hosts/test.py +++ b/dbms/tests/integration/test_allowed_client_hosts/test.py @@ -57,4 +57,4 @@ def test_allowed_host(): for client_node in expected_to_fail: with pytest.raises(Exception) as e: query_from_one_node_to_another(client_node, server, "SELECT * FROM test_table") - assert "User default is not allowed to connect from address" in str(e) + assert "default: Authentication failed" in str(e) diff --git a/dbms/tests/integration/test_authentication/__init__.py b/dbms/tests/integration/test_authentication/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/dbms/tests/integration/test_authentication/test.py b/dbms/tests/integration/test_authentication/test.py new file mode 100644 index 00000000000..11ca967fbee --- /dev/null +++ b/dbms/tests/integration/test_authentication/test.py @@ -0,0 +1,32 @@ +import pytest +from helpers.cluster import ClickHouseCluster + +cluster = ClickHouseCluster(__file__) +instance = cluster.add_instance('instance') + + +@pytest.fixture(scope="module", autouse=True) +def setup_nodes(): + try: + cluster.start() + + instance.query("CREATE USER sasha PROFILE 'default'") + instance.query("CREATE USER masha IDENTIFIED BY 'qwerty' PROFILE 'default'") + + yield cluster + + finally: + cluster.shutdown() + + +def test_authentication_pass(): + assert instance.query("SELECT currentUser()", user='sasha') == 'sasha\n' + assert instance.query("SELECT currentUser()", user='masha', password='qwerty') == 'masha\n' + + +def test_authentication_fail(): + # User doesn't exist. + assert "vasya: Authentication failed" in instance.query_and_get_error("SELECT currentUser()", user = 'vasya') + + # Wrong password. + assert "masha: Authentication failed" in instance.query_and_get_error("SELECT currentUser()", user = 'masha', password = '123') diff --git a/dbms/tests/integration/test_mysql_protocol/test.py b/dbms/tests/integration/test_mysql_protocol/test.py index 3f4f4e2a2f8..7987076c29a 100644 --- a/dbms/tests/integration/test_mysql_protocol/test.py +++ b/dbms/tests/integration/test_mysql_protocol/test.py @@ -101,7 +101,7 @@ def test_mysql_client(mysql_client, server_address): '''.format(host=server_address, port=server_port), demux=True) assert stderr == 'mysql: [Warning] Using a password on the command line interface can be insecure.\n' \ - 'ERROR 193 (00000): Wrong password for user default\n' + 'ERROR 516 (00000): default: Authentication failed: password is incorrect or there is no user with such name\n' code, (stdout, stderr) = mysql_client.exec_run(''' mysql --protocol tcp -h {host} -P {port} default -u default --password=123 @@ -179,7 +179,7 @@ def test_python_client(server_address): with pytest.raises(pymysql.InternalError) as exc_info: pymysql.connections.Connection(host=server_address, user='default', password='abacab', database='default', port=server_port) - assert exc_info.value.args == (193, 'Wrong password for user default') + assert exc_info.value.args == (516, 'default: Authentication failed: password is incorrect or there is no user with such name') client = pymysql.connections.Connection(host=server_address, user='default', password='123', database='default', port=server_port)