| #!/bin/env python |
| # -*- coding: utf-8 -*- |
| # Licensed to the Apache Software Foundation (ASF) under one |
| # or more contributor license agreements. See the NOTICE file |
| # distributed with this work for additional information |
| # regarding copyright ownership. The ASF licenses this file |
| # to you under the Apache License, Version 2.0 (the |
| # "License"); you may not use this file except in compliance |
| # with the License. You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, |
| # software distributed under the License is distributed on an |
| # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| # KIND, either express or implied. See the License for the |
| # specific language governing permissions and limitations |
| # under the License. |
| |
| """ |
| for palo query test |
| Date: 2018-07-24 16:16:33 |
| """ |
| import sys |
| import time |
| import optparse |
| import subprocess as commands |
| import json |
| import functools |
| sys.path.append("../..") |
| |
| from lib import palo_client |
| from lib import palo_config |
| from lib import palo_logger |
| |
| |
| LOG = palo_logger.Logger.getLogger() |
| L = palo_logger.StructedLogMessage |
| config = palo_config.config |
| |
| |
| def run_check(test_file, result_file): |
| """ |
| base test |
| """ |
| print("\t---------------------------------------------------------\t") |
| print("input file:%s, result file:%s" % (test_file, result_file)) |
| LOG.info(L('input file: %s, result file: %s' % (test_file, result_file))) |
| actual = _execute(test_file) |
| if not actual: |
| return False |
| f_result = open(result_file, "r") |
| lines = f_result.readlines() |
| k = 0 |
| j = 0 |
| ret = True |
| total_line = len(lines) |
| for res in lines: |
| res = res.strip() |
| j += 1 |
| if actual[k].upper().endswith("#IGNORE CHECK"): |
| if k >= total_line - 1: |
| break |
| k += 1 |
| continue |
| if res.upper().endswith("#IGNORE CHECK") or res.startswith("--"): |
| continue |
| if actual[k] != res: |
| if actual[k].startswith("False") and res.startswith("False"): |
| print('-----------------diff info--------------------------------') |
| print("different false info in result %d line" % j) |
| print('expected: %s\nactual: %s' % (res, actual[k])) |
| LOG.warning(L("different false info in result %d line" % j)) |
| LOG.warning(L('expected: %s\nactual: %s' % (res, actual[k]))) |
| else: |
| ret = False |
| print('****************diff result*******************************') |
| print("different in result %d line" % j) |
| LOG.error(L("different in result %d line" % j)) |
| if k > 0: |
| print(actual[k - 1]) |
| LOG.error(L('this is wrong sql', sql=actual[k - 1])) |
| print("expected: %s\nactual: %s" % (res, actual[k])) |
| LOG.error(L("expected: %s but actual: %s" % (res, actual[k]))) |
| |
| k += 1 |
| LOG.info(L('test %s result is %s' % (test_file, ret))) |
| return ret |
| |
| |
| def gen_result(test_file, result_file): |
| """ |
| gen result |
| """ |
| result = _execute(test_file) |
| f_result = open(result_file, "w") |
| for r in result: |
| f_result.write(r + "\n") |
| |
| f_result.close() |
| return True |
| |
| |
| def compare(a, b): |
| """compare data to None""" |
| assert isinstance(a, (tuple, list)) |
| assert isinstance(b, (tuple, list)) |
| for i in range(0, len(a)): |
| if a[i] is not None and b[i] is not None: |
| if a[i] > b[i]: |
| return 1 |
| elif a[i] < b[i]: |
| return -1 |
| else: |
| continue |
| elif a[i] is None and b[i] is None: |
| continue |
| elif a[i] is None: |
| return -1 |
| else: |
| return 1 |
| return 0 |
| |
| |
| def _execute(test_file): |
| client = palo_client.get_client(config.fe_host, config.fe_query_port, |
| user=config.fe_user, |
| password=config.fe_password) |
| f_sql = open(test_file, "r") |
| result = list() |
| for sql in f_sql: |
| IGNORE_CHECK = False |
| sql = sql.strip() |
| # 注释,忽略 |
| if not sql or sql.startswith("--"): |
| continue |
| |
| # ignore this sql's result |
| # select * from a#IGNORE CHECK ==> select * from a |
| # () ==> ()#IGNORE CHECK |
| if sql.upper().endswith("#IGNORE CHECK"): |
| sql = sql[:len(sql) - 13].strip() |
| IGNORE_CHECK = True |
| print(sql) |
| LOG.info(L('execute', sql=sql)) |
| result.append(sql) |
| |
| # 对于use和导入语句,只记录SQL,不记录结果 |
| if sql.upper().startswith("USE"): |
| selected_db = sql[4:].strip() |
| client.use(selected_db) |
| continue |
| # 异步导入 |
| if sql.upper().startswith("LOAD") or sql.upper().startswith("INSERT"): |
| try: |
| client.execute(sql) |
| client.wait_table_load_job() |
| except Exception as e: |
| print(str(e)) |
| continue |
| # curl multi load & stream load |
| if sql.upper().startswith("CURL"): |
| try: |
| sql = sql.format(FE_HOST=config.fe_host, HTTP_PORT=config.fe_http_port, FE_PASSWORD=config.fe_password) |
| print(sql) |
| ret = commands.getoutput(sql) |
| print(ret) |
| client.wait_table_load_job() |
| except Exception as e: |
| print(str(e)) |
| break |
| continue |
| |
| # 不支持异常操作,execute的SQL应该是支持的 |
| r = client.execute(sql) |
| # 排序 |
| if r: |
| r = list(r) |
| try: |
| r.sort() |
| except Exception as e: |
| if isinstance(e, TypeError): |
| r.sort(key=functools.cmp_to_key(compare)) |
| # 字符串格式化 |
| r = str_format(r) |
| actual = ("%s" % r).strip() |
| |
| if IGNORE_CHECK: |
| actual += "#IGNORE CHECK" |
| print(actual) |
| result.append(actual) |
| f_sql.close() |
| return result |
| |
| |
| def str_format(result): |
| """fromat result and return str""" |
| ret = list() |
| for line in result: |
| record = list() |
| for col in line: |
| record.append(str(col)) |
| ret.append(record) |
| return str(tuple(ret)) |
| |
| |
| def check_cluster(): |
| """check be if enough""" |
| client = palo_client.get_client(config.fe_host, config.fe_query_port, |
| user=config.fe_user, |
| password=config.fe_password) |
| alive_be = client.get_alive_backend_list() |
| if len(alive_be) >= 3: |
| return True |
| else: |
| return False |
| |
| |
| def main(): |
| """ |
| main |
| """ |
| usage = "Usage: python implement.py test_file result_file" |
| parser = optparse.OptionParser(usage) |
| parser.add_option("-g", "--gen", dest="gen", default=False, action='store_true', |
| help="generate result and write into file") |
| options, args = parser.parse_args() |
| if len(args) != 2: |
| parser.print_help() |
| return |
| #s = run_check("atomic.sql", "atomic.result") |
| if options.gen: |
| s = gen_result(args[0], args[1]) |
| return |
| s = run_check(args[0], args[1]) |
| print("--------------------------------------------------------------------------------------") |
| print("Check Result: %s" % s) |
| |
| |
| if __name__ == "__main__": |
| main() |
| |