query_test.py 5.0 KB
Newer Older
1 2 3 4
import pytest

import difflib
import os
5 6
import random
import string
7 8 9 10
import subprocess
import sys


I
Ivan 已提交
11
def check_result(result, error, return_code, reference, replace_map):
A
Azat Khuzhin 已提交
12
    for old, new in replace_map.items():
I
Ivan Lezhankin 已提交
13
        result = result.replace(old.encode('utf-8'), new.encode('utf-8'))
14

I
Ivan 已提交
15 16 17 18 19 20
    if return_code != 0:
        try:
            print(error.decode('utf-8'), file=sys.stderr)
        except UnicodeDecodeError:
            print(error.decode('latin1'), file=sys.stderr)  # encoding with 1 symbol per 1 byte, covering all values
        pytest.fail('Client died unexpectedly with code {code}'.format(code=return_code), pytrace=False)
21 22 23
    elif result != reference:
        pytest.fail("Query output doesn't match reference:{eol}{diff}".format(
                eol=os.linesep,
I
Ivan Lezhankin 已提交
24 25 26
                diff=os.linesep.join(l.strip() for l in difflib.unified_diff(reference.decode('utf-8').splitlines(),
                                                                             result.decode('utf-8').splitlines(),
                                                                             fromfile='expected', tofile='actual'))),
27 28 29
            pytrace=False)


I
Ivan 已提交
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
def run_client(bin_prefix, port, query, reference, replace_map={}):
    # We can't use `text=True` since some tests may return binary data
    client = subprocess.Popen([bin_prefix + '-client', '--port', str(port), '-m', '-n', '--testmode'],
                              stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    result, error = client.communicate(query.encode('utf-8'))
    assert client.returncode is not None, "Client should exit after processing all queries"

    check_result(result, error, client.returncode, reference, replace_map)


def run_shell(bin_prefix, tmp_dir, tcp_port, http_port, inter_port, database, path, reference, replace_map={}):
    env = {
        'CLICKHOUSE_BINARY': bin_prefix,
        'CLICKHOUSE_DATABASE': database,
        'CLICKHOUSE_PORT_TCP': str(tcp_port),
        'CLICKHOUSE_PORT_HTTP': str(http_port),
        'CLICKHOUSE_PORT_INTERSERVER': str(inter_port),
        'CLICKHOUSE_TMP': tmp_dir,
    }
    shell = subprocess.Popen([path], env=env, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    result, error = shell.communicate()
    assert shell.returncode is not None, "Script should exit after executing all commands"

    check_result(result, error, shell.returncode, reference, replace_map)


56 57 58 59 60
def random_str(length=10):
    alphabet = string.ascii_lowercase + string.digits
    return ''.join(random.choice(alphabet) for _ in range(length))


I
Ivan 已提交
61
def test_sql_query(bin_prefix, sql_query, standalone_server):
62 63 64 65 66 67 68 69 70 71
    tcp_port = standalone_server.tcp_port

    query_path = sql_query + ".sql"
    reference_path = sql_query + ".reference"

    if not os.path.exists(reference_path):
        pytest.skip('No .reference file found')

    with open(query_path, 'r') as file:
        query = file.read()
I
Ivan Lezhankin 已提交
72
    with open(reference_path, 'rb') as file:
73 74
        reference = file.read()

75
    random_name = 'test_{random}'.format(random=random_str())
76
    query = 'CREATE DATABASE {random}; USE {random}; {query}'.format(random=random_name, query=query)
77
    run_client(bin_prefix, tcp_port, query, reference, {random_name: 'default'})
78

79
    query = "SELECT 'SHOW ORPHANED TABLES'; SELECT name FROM system.tables WHERE database != 'system' ORDER BY (database, name);"
I
Ivan Lezhankin 已提交
80
    run_client(bin_prefix, tcp_port, query, b'SHOW ORPHANED TABLES\n')
81

I
Ivan 已提交
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
    query = 'DROP DATABASE {random};'.format(random=random_name)
    run_client(bin_prefix, tcp_port, query, b'')

    query = "SELECT 'SHOW ORPHANED DATABASES'; SHOW DATABASES;"
    run_client(bin_prefix, tcp_port, query, b'SHOW ORPHANED DATABASES\n_temporary_and_external_tables\ndefault\nsystem\n')


def test_shell_query(bin_prefix, shell_query, standalone_server):
    tcp_port = standalone_server.tcp_port
    http_port = standalone_server.http_port
    inter_port = standalone_server.inter_port
    tmp_path = standalone_server.tmp_dir

    shell_path = shell_query + ".sh"
    reference_path = shell_query + ".reference"

    if not os.path.exists(reference_path):
        pytest.skip('No .reference file found')

    with open(reference_path, 'rb') as file:
        reference = file.read()

    random_name = 'test_{random}'.format(random=random_str())
    query = 'CREATE DATABASE {random};'.format(random=random_name)
    run_client(bin_prefix, tcp_port, query, b'')

    run_shell(bin_prefix, tmp_path, tcp_port, http_port, inter_port, random_name, shell_path, reference, {random_name: 'default'})

    query = "SELECT 'SHOW ORPHANED TABLES'; SELECT name FROM system.tables WHERE database != 'system' ORDER BY (database, name);"
    run_client(bin_prefix, tcp_port, query, b'SHOW ORPHANED TABLES\n')

    query = 'DROP DATABASE {random};'.format(random=random_name)
    run_client(bin_prefix, tcp_port, query, b'')
115 116

    query = "SELECT 'SHOW ORPHANED DATABASES'; SHOW DATABASES;"
I
Ivan Lezhankin 已提交
117
    run_client(bin_prefix, tcp_port, query, b'SHOW ORPHANED DATABASES\n_temporary_and_external_tables\ndefault\nsystem\n')