clickhouse-test 24.7 KB
Newer Older
1
#!/usr/bin/env python
2
from __future__ import print_function
3 4 5 6 7 8 9 10
import sys
import os
import os.path
import re

from argparse import ArgumentParser
from argparse import FileType
from pprint import pprint
11
import shlex
12
import subprocess
13 14 15 16
from subprocess import check_call
from subprocess import Popen
from subprocess import PIPE
from subprocess import CalledProcessError
17 18 19
from datetime import datetime
from time import sleep
from errno import ESRCH
20 21 22 23
try:
    import termcolor
except ImportError:
    termcolor = None
24
from random import random
P
proller 已提交
25
import commands
P
proller 已提交
26
import multiprocessing
P
proller 已提交
27
from contextlib import closing
28

29

A
alesapin 已提交
30
MESSAGES_TO_RETRY = [
31
    "DB::Exception: ZooKeeper session has been expired",
A
alesapin 已提交
32 33 34
    "Coordination::Exception: Connection loss",
]

35

36 37 38 39 40 41 42 43
def remove_control_characters(s):
    """
    https://github.com/html5lib/html5lib-python/issues/96#issuecomment-43438438
    """
    def str_to_int(s, default, base=10):
        if int(s, base) < 0x10000:
            return unichr(int(s, base))
        return default
44 45 46
    s = re.sub(r"&#(\d+);?", lambda c: str_to_int(c.group(1), c.group(0)), s)
    s = re.sub(r"&#[xX]([0-9a-fA-F]+);?", lambda c: str_to_int(c.group(1), c.group(0), base=16), s)
    s = re.sub(r"[\x00-\x08\x0b\x0e-\x1f\x7f]", "", s)
47 48
    return s

49 50 51

def run_single_test(args, ext, server_logs_level, client_options, case_file, stdout_file, stderr_file):

52 53
    # print(client_options)

54 55 56 57 58 59 60 61 62
    params = {
        'client': args.client_with_database,
        'logs_level': server_logs_level,
        'options': client_options,
        'test': case_file,
        'stdout': stdout_file,
        'stderr': stderr_file,
    }

63 64
    pattern = '{test} > {stdout} 2> {stderr}'

A
alesapin 已提交
65
    if ext == '.sql':
66 67 68 69
        pattern = "{client} --send_logs_level={logs_level} --testmode --multiquery {options} < " + pattern

    command = pattern.format(**params)
    #print(command)
A
alesapin 已提交
70

71
    proc = Popen(command, shell=True, env=os.environ)
A
alesapin 已提交
72 73 74 75
    start_time = datetime.now()
    while (datetime.now() - start_time).total_seconds() < args.timeout and proc.poll() is None:
        sleep(0.01)

76 77
    total_time = (datetime.now() - start_time).total_seconds()

A
alexey-milovidov 已提交
78
    # Normalize randomized database names in stdout, stderr files.
P
proller 已提交
79 80
    os.system("sed -i -e 's/{test_db}/default/g' {file}".format(test_db=args.database, file=stdout_file))
    os.system("sed -i -e 's/{test_db}/default/g' {file}".format(test_db=args.database, file=stderr_file))
81

A
alesapin 已提交
82 83 84 85 86
    stdout = open(stdout_file, 'r').read() if os.path.exists(stdout_file) else ''
    stdout = unicode(stdout, errors='replace', encoding='utf-8')
    stderr = open(stderr_file, 'r').read() if os.path.exists(stderr_file) else ''
    stderr = unicode(stderr, errors='replace', encoding='utf-8')

87
    return proc, stdout, stderr, total_time
A
alesapin 已提交
88

89

A
alesapin 已提交
90 91 92
def need_retry(stderr):
    return any(msg in stderr for msg in MESSAGES_TO_RETRY)

93

94 95 96 97 98 99
def get_processlist(client_cmd):
    try:
        return subprocess.check_output("{} --query 'SHOW PROCESSLIST FORMAT Vertical'".format(client_cmd), shell=True)
    except:
        return "" #  server seems dead

100

101 102 103 104 105 106 107
def get_stacktraces(server_pid):
    cmd = "gdb -q -ex 'set pagination off' -ex 'backtrace' -ex 'thread apply all backtrace' -ex 'detach' -ex 'quit' --pid {} 2>/dev/null".format(server_pid)
    try:
        return subprocess.check_output(cmd, shell=True)
    except Exception as ex:
        return "Error occured while receiving stack traces {}".format(str(ex))

108

109 110 111 112 113 114 115 116 117 118 119 120
def get_server_pid(server_tcp_port):
    cmd = "lsof -i tcp:{port} | grep '*:{port}'".format(port=server_tcp_port)
    try:
        output = subprocess.check_output(cmd, shell=True)
        if output:
            columns = output.strip().split(' ')
            return int(columns[1])
        else:
            return None # server dead
    except Exception as ex:
        return None

121

P
proller 已提交
122
def colored(text, args, color=None, on_color=None, attrs=None):
123
       if termcolor and (sys.stdout.isatty() or args.force_color):
P
proller 已提交
124 125 126 127
           return termcolor.colored(text, color, on_color, attrs)
       else:
           return text

128

P
proller 已提交
129 130 131
SERVER_DIED = False
exit_code = 0

132

133
# def run_tests_array(all_tests, suite, suite_dir, suite_tmp_dir, run_total):
P
proller 已提交
134 135
def run_tests_array(all_tests_with_params):
    all_tests, suite, suite_dir, suite_tmp_dir, run_total = all_tests_with_params
P
proller 已提交
136
    global exit_code
P
proller 已提交
137
    global SERVER_DIED
138

P
proller 已提交
139 140 141 142 143 144 145 146 147 148 149 150 151
    OP_SQUARE_BRACKET = colored("[", args, attrs=['bold'])
    CL_SQUARE_BRACKET = colored("]", args, attrs=['bold'])

    MSG_FAIL = OP_SQUARE_BRACKET + colored(" FAIL ", args, "red", attrs=['bold']) + CL_SQUARE_BRACKET
    MSG_UNKNOWN = OP_SQUARE_BRACKET + colored(" UNKNOWN ", args, "yellow", attrs=['bold']) + CL_SQUARE_BRACKET
    MSG_OK = OP_SQUARE_BRACKET + colored(" OK ", args, "green", attrs=['bold']) + CL_SQUARE_BRACKET
    MSG_SKIPPED = OP_SQUARE_BRACKET + colored(" SKIPPED ", args, "cyan", attrs=['bold']) + CL_SQUARE_BRACKET

    passed_total = 0
    skipped_total = 0
    failures_total = 0
    failures = 0
    failures_chain = 0
152

153 154
    client_options = get_additional_client_options(args)

155 156 157 158
    def print_test_time(test_time):
        if args.print_time:
            print(" {0:.2f} sec.".format(test_time), end='')

P
proller 已提交
159 160
    if len(all_tests):
        print("\nRunning {} {} tests.".format(len(all_tests), suite) + "\n")
A
alesapin 已提交
161

P
proller 已提交
162 163 164
    for case in all_tests:
        if SERVER_DIED:
            break
A
alesapin 已提交
165

P
proller 已提交
166 167 168 169 170 171 172 173 174 175 176 177 178 179
        case_file = os.path.join(suite_dir, case)
        (name, ext) = os.path.splitext(case)

        try:
            sys.stdout.write("{0:72}".format(name + ": "))
            if run_total == 1:
                sys.stdout.flush()

            if args.skip and any(s in name for s in args.skip):
                print(MSG_SKIPPED + " - skip")
                skipped_total += 1
            elif not args.zookeeper and 'zookeeper' in name:
                print(MSG_SKIPPED + " - no zookeeper")
                skipped_total += 1
A
akuzm 已提交
180 181 182
            elif not args.shard and ('shard' in name
                    or 'distributed' in name
                    or 'global' in name):
P
proller 已提交
183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203
                print(MSG_SKIPPED + " - no shard")
                skipped_total += 1
            elif not args.no_long and 'long' in name:
                print(MSG_SKIPPED + " - no long")
                skipped_total += 1
            else:
                disabled_file = os.path.join(suite_dir, name) + '.disabled'

                if os.path.exists(disabled_file) and not args.disabled:
                    message = open(disabled_file, 'r').read()
                    print(MSG_SKIPPED + " - " + message)
                else:

                    if args.testname:
                        clickhouse_proc = Popen(shlex.split(args.client_with_database), stdin=PIPE, stdout=PIPE, stderr=PIPE)
                        clickhouse_proc.communicate("SELECT 'Running test {suite}/{case} from pid={pid}';".format(pid = os.getpid(), case = case, suite = suite))

                    reference_file = os.path.join(suite_dir, name) + '.reference'
                    stdout_file = os.path.join(suite_tmp_dir, name) + '.stdout'
                    stderr_file = os.path.join(suite_tmp_dir, name) + '.stderr'

204
                    proc, stdout, stderr, total_time = run_single_test(args, ext, server_logs_level, client_options, case_file, stdout_file, stderr_file)
P
proller 已提交
205 206 207 208 209 210 211 212
                    if proc.returncode is None:
                        try:
                            proc.kill()
                        except OSError as e:
                            if e.errno != ESRCH:
                                raise

                        failures += 1
213 214 215
                        print(MSG_FAIL, end='')
                        print_test_time(total_time)
                        print(" - Timeout!")
P
proller 已提交
216 217 218
                    else:
                        counter = 1
                        while proc.returncode != 0 and need_retry(stderr):
219
                            proc, stdout, stderr, total_time = run_single_test(args, ext, server_logs_level, client_options, case_file, stdout_file, stderr_file)
P
proller 已提交
220 221 222 223 224 225 226 227
                            sleep(2**counter)
                            counter += 1
                            if counter > 6:
                                break

                        if proc.returncode != 0:
                            failures += 1
                            failures_chain += 1
228 229 230
                            print(MSG_FAIL, end='')
                            print_test_time(total_time)
                            print(" - return code {}".format(proc.returncode))
P
proller 已提交
231 232

                            if stderr:
233
                                print(stderr.encode('utf-8'))
P
proller 已提交
234 235 236 237 238 239 240

                            if args.stop and ('Connection refused' in stderr or 'Attempt to read after eof' in stderr) and not 'Received exception from server' in stderr:
                                SERVER_DIED = True

                        elif stderr:
                            failures += 1
                            failures_chain += 1
241 242 243
                            print(MSG_FAIL, end='')
                            print_test_time(total_time)
                            print(" - having stderror:\n{}".format(stderr.encode('utf-8')))
P
proller 已提交
244 245 246
                        elif 'Exception' in stdout:
                            failures += 1
                            failures_chain += 1
247 248 249
                            print(MSG_FAIL, end='')
                            print_test_time(total_time)
                            print(" - having exception:\n{}".format(stdout.encode('utf-8')))
P
proller 已提交
250
                        elif not os.path.isfile(reference_file):
251 252 253
                            print(MSG_UNKNOWN, end='')
                            print_test_time(total_time)
                            print(" - no reference file")
P
proller 已提交
254 255 256 257
                        else:
                            result_is_different = subprocess.call(['diff', '-q', reference_file, stdout_file], stdout = PIPE)

                            if result_is_different:
258
                                diff = Popen(['diff', '-U', str(args.unified), reference_file, stdout_file], stdout = PIPE).communicate()[0]
P
proller 已提交
259
                                failures += 1
260 261 262
                                print(MSG_FAIL, end='')
                                print_test_time(total_time)
                                print(" - result differs with reference:\n{}".format(diff))
P
proller 已提交
263 264 265
                            else:
                                passed_total += 1
                                failures_chain = 0
266 267 268
                                print(MSG_OK, end='')
                                print_test_time(total_time)
                                print()
P
proller 已提交
269 270 271 272 273 274 275 276 277 278 279
                                if os.path.exists(stdout_file):
                                    os.remove(stdout_file)
                                if os.path.exists(stderr_file):
                                    os.remove(stderr_file)
        except KeyboardInterrupt as e:
            print(colored("Break tests execution", args, "red"))
            raise e
        except:
            import traceback
            exc_type, exc_value, tb = sys.exc_info()
            failures += 1
280
            print("{0} - Test internal error: {1}\n{2}\n{3}".format(MSG_FAIL, exc_type.__name__, exc_value, "\n".join(traceback.format_tb(tb, 10))))
P
proller 已提交
281 282 283 284 285 286 287

        if failures_chain >= 20:
            break

    failures_total = failures_total + failures

    if failures_total > 0:
288
        print(colored("\nHaving {failures_total} errors! {passed_total} tests passed. {skipped_total} tests skipped.".format(passed_total = passed_total, skipped_total = skipped_total, failures_total = failures_total), args, "red", attrs=["bold"]))
P
proller 已提交
289 290 291
        exit_code = 1
    else:
        print(colored("\n{passed_total} tests passed. {skipped_total} tests skipped.".format(passed_total = passed_total, skipped_total = skipped_total), args, "green", attrs=["bold"]))
A
alesapin 已提交
292

293

P
proller 已提交
294 295
server_logs_level = "warning"

296

P
proller 已提交
297 298 299 300
def main(args):
    global SERVER_DIED
    global exit_code
    global server_logs_level
A
alesapin 已提交
301

302
    def is_data_present():
P
proller 已提交
303 304
        clickhouse_proc = Popen(shlex.split(args.client), stdin=PIPE, stdout=PIPE, stderr=PIPE)
        (stdout, stderr) = clickhouse_proc.communicate("EXISTS TABLE test.hits")
P
proller 已提交
305
        if clickhouse_proc.returncode != 0:
P
proller 已提交
306
            raise CalledProcessError(clickhouse_proc.returncode, args.client, stderr)
307 308 309

        return stdout.startswith('1')

P
proller 已提交
310 311 312
    base_dir = os.path.abspath(args.queries)
    tmp_dir = os.path.abspath(args.tmp)

313
    # Keep same default values as in queries/shell_config.sh
P
proller 已提交
314
    os.environ.setdefault("CLICKHOUSE_BINARY", args.binary)
P
proller 已提交
315
    #os.environ.setdefault("CLICKHOUSE_CLIENT", args.client)
316
    os.environ.setdefault("CLICKHOUSE_CONFIG", args.configserver)
P
proller 已提交
317 318
    if args.configclient:
        os.environ.setdefault("CLICKHOUSE_CONFIG_CLIENT", args.configclient)
P
proller 已提交
319
    os.environ.setdefault("CLICKHOUSE_TMP", tmp_dir)
320
    os.environ.setdefault("CLICKHOUSE_DATABASE", args.database)
321

322
    # Force to print server warnings in stderr
323
    # Shell scripts could change logging level
324 325
    os.environ.setdefault("CLICKHOUSE_CLIENT_SERVER_LOGS_LEVEL", server_logs_level)

326
    if args.zookeeper is None:
P
proller 已提交
327
        code, out = commands.getstatusoutput(args.extract_from_config +" --try --config " + args.configserver + ' --key zookeeper | grep . | wc -l')
328 329 330 331 332 333
        try:
            if int(out) > 0:
                args.zookeeper = True
            else:
                args.zookeeper = False
        except ValueError:
334 335 336
            args.zookeeper = False

    if args.shard is None:
P
proller 已提交
337
        code, out = commands.getstatusoutput(args.extract_from_config + " --try --config " + args.configserver + ' --key listen_host | grep -E "127.0.0.2|::"')
P
proller 已提交
338
        if out:
P
proller 已提交
339
            args.shard = True
P
proller 已提交
340 341
        else:
            args.shard = False
342

P
proller 已提交
343
    clickhouse_proc_create = Popen(shlex.split(args.client), stdin=PIPE, stdout=PIPE, stderr=PIPE)
344
    clickhouse_proc_create.communicate("CREATE DATABASE IF NOT EXISTS " + args.database)
345 346 347
    if args.database != "test":
        clickhouse_proc_create = Popen(shlex.split(args.client), stdin=PIPE, stdout=PIPE, stderr=PIPE)
        clickhouse_proc_create.communicate("CREATE DATABASE IF NOT EXISTS test")
348 349 350 351 352

    def is_test_from_dir(suite_dir, case):
        case_file = os.path.join(suite_dir, case)
        (name, ext) = os.path.splitext(case)
        return os.path.isfile(case_file) and (ext == '.sql' or ext == '.sh' or ext == '.py')
P
proller 已提交
353

354 355 356 357 358 359 360 361 362 363 364 365 366 367
    def sute_key_func(item):
       if args.order == 'random':
             return random()

       if -1 == item.find('_'):
           return 99998

       prefix, suffix = item.split('_', 1)

       try:
           return int(prefix), suffix
       except ValueError:
           return 99997

368
    total_tests_run = 0
369
    for suite in sorted(os.listdir(base_dir), key=sute_key_func):
370 371 372 373 374 375 376
        if SERVER_DIED:
            break

        suite_dir = os.path.join(base_dir, suite)
        suite_re_obj = re.search('^[0-9]+_(.*)$', suite)
        if not suite_re_obj: #skip .gitignore and so on
            continue
377 378 379 380 381

        suite_tmp_dir = os.path.join(tmp_dir, suite)
        if not os.path.exists(suite_tmp_dir):
            os.makedirs(suite_tmp_dir)

382 383 384
        suite = suite_re_obj.group(1)
        if os.path.isdir(suite_dir):

P
proller 已提交
385
            if 'stateful' in suite and not args.no_stateful and not is_data_present():
386
                print("Won't run stateful tests because test data wasn't loaded.")
387
                continue
388 389 390
            if 'stateless' in suite and args.no_stateless:
                print("Won't run stateless tests because they were manually disabled.")
                continue
391 392 393
            if 'stateful' in suite and args.no_stateful:
                print("Won't run stateful tests because they were manually disabled.")
                continue
394

P
proller 已提交
395 396 397
            # Reverse sort order: we want run newest test first.
            # And not reverse subtests
            def key_func(item):
398
                if args.order == 'random':
399
                    return random()
400 401 402 403 404 405

                reverse = 1 if args.order == 'asc' else -1

                if -1 == item.find('_'):
                    return 99998

P
proller 已提交
406
                prefix, suffix = item.split('_', 1)
407 408 409 410 411 412

                try:
                    return reverse * int(prefix), suffix
                except ValueError:
                    return 99997

413 414
            all_tests = os.listdir(suite_dir)
            all_tests = filter(lambda case: is_test_from_dir(suite_dir, case), all_tests)
415 416
            if args.test:
                all_tests = [t for t in all_tests if any([re.search(r, t) for r in args.test])]
417
            all_tests.sort(key=key_func)
418

P
proller 已提交
419 420 421 422 423 424 425 426
            run_n, run_total = args.parallel.split('/')
            run_n = float(run_n)
            run_total = float(run_total)
            tests_n = len(all_tests)
            if run_total > tests_n:
                run_total = tests_n
            if run_n > run_total:
                continue
427

P
proller 已提交
428
            jobs = args.jobs
P
proller 已提交
429 430
            if jobs > tests_n:
                jobs = tests_n
P
proller 已提交
431 432
            if jobs > run_total:
                run_total = jobs
P
proller 已提交
433

P
proller 已提交
434 435 436 437 438
            all_tests_array = []
            for n in range(1, 1 + int(run_total)):
                start = int(tests_n / run_total * (n - 1))
                end = int(tests_n / run_total * n)
                all_tests_array.append([all_tests[start : end], suite, suite_dir, suite_tmp_dir, run_total])
P
proller 已提交
439

P
proller 已提交
440
            if jobs > 1:
P
proller 已提交
441
                with closing(multiprocessing.Pool(processes=jobs)) as pool:
P
proller 已提交
442 443 444 445
                    pool.map(run_tests_array, all_tests_array)
                    pool.terminate()
            else:
                run_tests_array(all_tests_array[int(run_n)-1])
446

447 448
            total_tests_run += tests_n

449
    if args.hung_check:
450
        processlist = get_processlist(args.client_with_database)
451 452
        if processlist:
            server_pid = get_server_pid(os.getenv("CLICKHOUSE_PORT_TCP", '9000'))
453 454
            print(colored("\nFound hung queries in processlist:", args, "red", attrs=["bold"]))
            print(processlist)
455
            if server_pid:
456 457
                print("\nStacktraces of all threads:")
                print(get_stacktraces(server_pid))
458
            exit_code = 1
459
        else:
P
proller 已提交
460
            print(colored("\nNo queries hung.", args, "green", attrs=["bold"]))
461

462 463 464 465
    if total_tests_run == 0:
        print("No tests were run.")
        sys.exit(1)

466 467
    sys.exit(exit_code)

468

A
alesapin 已提交
469
def find_binary(name):
470 471
    if os.path.exists(name) and os.access(name, os.X_OK):
        return True
A
alesapin 已提交
472 473 474 475 476 477
    paths = os.environ.get("PATH").split(':')
    for path in paths:
        if os.access(os.path.join(path, name), os.X_OK):
            return True

    # maybe it wasn't in PATH
P
proller 已提交
478 479 480 481 482 483
    if os.access(os.path.join('/usr/local/bin', name), os.X_OK):
        return True
    if os.access(os.path.join('/usr/bin', name), os.X_OK):
        return True
    return False

484

485
def get_additional_client_options(args):
486 487 488 489 490 491 492 493 494 495 496
    if args.client_option:
        return ' '.join('--' + option for option in args.client_option)

    return ''


def get_additional_client_options_url(args):
    if args.client_option:
        return '&'.join(args.client_option)

    return ''
497 498


499
if __name__ == '__main__':
500 501 502
    parser=ArgumentParser(description='ClickHouse functional tests')
    parser.add_argument('-q', '--queries', help='Path to queries dir')
    parser.add_argument('--tmp', help='Path to tmp dir')
503
    parser.add_argument('-b', '--binary', default='clickhouse', help='Path to clickhouse binary or name of binary in PATH')
504 505 506 507 508 509
    parser.add_argument('-c', '--client', help='Client program')
    parser.add_argument('--extract_from_config', help='extract-from-config program')
    parser.add_argument('--configclient', help='Client config (if you use not default ports)')
    parser.add_argument('--configserver', default= '/etc/clickhouse-server/config.xml', help='Preprocessed server config')
    parser.add_argument('-o', '--output', help='Output xUnit compliant test report directory')
    parser.add_argument('-t', '--timeout', type=int, default=600, help='Timeout for each test case in seconds')
510
    parser.add_argument('test', nargs='*', help='Optional test case name regex')
511 512 513 514 515
    parser.add_argument('-d', '--disabled', action='store_true', default=False, help='Also run disabled tests')
    parser.add_argument('--stop', action='store_true', default=None, dest='stop', help='Stop on network errors')
    parser.add_argument('--order', default='desc', help='Run order (asc, desc, random)')
    parser.add_argument('--testname', action='store_true', default=None, dest='testname', help='Make query with test name before test run')
    parser.add_argument('--hung-check', action='store_true', default=False)
A
alesapin 已提交
516
    parser.add_argument('--force-color', action='store_true', default=False)
517
    parser.add_argument('--database', help='Database for tests (random name test_XXXXXX by default)')
P
proller 已提交
518
    parser.add_argument('--parallel', default='1/1', help='One parallel test run number/total')
P
proller 已提交
519
    parser.add_argument('-j', '--jobs', default=1, nargs='?', type=int, help='Run all tests in parallel')
520
    parser.add_argument('-U', '--unified', default=3, type=int, help='output NUM lines of unified context')
521 522

    parser.add_argument('--no-stateless', action='store_true', help='Disable all stateless tests')
523
    parser.add_argument('--no-stateful', action='store_true', help='Disable all stateful tests')
524 525
    parser.add_argument('--skip', nargs='+', help="Skip these tests")
    parser.add_argument('--no-long', action='store_false', dest='no_long', help='Do not run long tests')
526
    parser.add_argument('--client-option', nargs='+', help='Specify additional client argument')
527
    parser.add_argument('--print-time', action='store_true', dest='print_time', help='Print test time')
528 529 530 531 532 533
    group=parser.add_mutually_exclusive_group(required=False)
    group.add_argument('--zookeeper', action='store_true', default=None, dest='zookeeper', help='Run zookeeper related tests')
    group.add_argument('--no-zookeeper', action='store_false', default=None, dest='zookeeper', help='Do not run zookeeper related tests')
    group=parser.add_mutually_exclusive_group(required=False)
    group.add_argument('--shard', action='store_true', default=None, dest='shard', help='Run sharding related tests (required to clickhouse-server listen 127.0.0.2 127.0.0.3)')
    group.add_argument('--no-shard', action='store_false', default=None, dest='shard', help='Do not run shard related tests')
534 535

    args = parser.parse_args()
536 537 538

    if args.queries is None and os.path.isdir('queries'):
        args.queries = 'queries'
P
proller 已提交
539
    elif args.queries is None:
P
proller 已提交
540 541 542 543
        if (os.path.isdir('/usr/local/share/clickhouse-test/queries')):
            args.queries = '/usr/local/share/clickhouse-test/queries'
        if (args.queries is None and os.path.isdir('/usr/share/clickhouse-test/queries')):
            args.queries = '/usr/share/clickhouse-test/queries'
544 545
        if args.tmp is None:
            args.tmp = '/tmp/clickhouse-test'
A
akuzm 已提交
546 547 548
    if args.queries is None:
        print_err("Failed to detect path to the queries directory. Please specify it with '--queries' option.")
        exit(1)
P
proller 已提交
549 550
    if args.tmp is None:
        args.tmp = args.queries
551
    if args.client is None:
A
alesapin 已提交
552
        if find_binary(args.binary + '-client'):
P
proller 已提交
553
            args.client = args.binary + '-client'
A
alesapin 已提交
554
        elif find_binary(args.binary):
P
proller 已提交
555
            args.client = args.binary + ' client'
556
        else:
A
alesapin 已提交
557 558 559 560
            print("No 'clickhouse' binary found in PATH")
            parser.print_help()
            exit(1)

P
proller 已提交
561
        if args.configclient:
562 563 564 565 566
            args.client += ' --config-file=' + args.configclient
        if os.getenv("CLICKHOUSE_HOST"):
            args.client += ' --host=' + os.getenv("CLICKHOUSE_HOST")
        if os.getenv("CLICKHOUSE_PORT_TCP"):
            args.client += ' --port=' + os.getenv("CLICKHOUSE_PORT_TCP")
567 568 569
        if os.getenv("CLICKHOUSE_DATABASE"):
            args.client += ' --database=' + os.getenv("CLICKHOUSE_DATABASE")

570
    if args.client_option:
571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586
        # Set options for client
        if 'CLICKHOUSE_CLIENT_OPT' in os.environ:
           os.environ['CLICKHOUSE_CLIENT_OPT'] += ' '
        else:
           os.environ['CLICKHOUSE_CLIENT_OPT'] = ''

        os.environ['CLICKHOUSE_CLIENT_OPT'] += get_additional_client_options(args)

        # Set options for curl
        if 'CLICKHOUSE_URL_PARAMS' in os.environ:
           os.environ['CLICKHOUSE_URL_PARAMS'] += '&'
        else:
           os.environ['CLICKHOUSE_URL_PARAMS'] = ''

        os.environ['CLICKHOUSE_URL_PARAMS'] += get_additional_client_options_url(args)

587

588
    args.client_with_database = args.client
589 590 591 592 593 594 595 596
    if not args.database:
        def random_str(length=6):
            import random
            import string
            alphabet = string.ascii_lowercase + string.digits
            return ''.join(random.choice(alphabet) for _ in range(length))
        args.database = 'test_{suffix}'.format(suffix=random_str())
    args.client_with_database += ' --database=' + args.database
597

P
proller 已提交
598 599 600 601 602 603
    if args.extract_from_config is None:
        if os.access(args.binary + '-extract-from-config', os.X_OK):
            args.extract_from_config = args.binary + '-extract-from-config'
        else:
            args.extract_from_config = args.binary + ' extract-from-config'

P
proller 已提交
604
    if args.jobs is None:
605
        args.jobs = multiprocessing.cpu_count()
P
proller 已提交
606

607
    main(args)