diff options
Diffstat (limited to 'ndb/test/run-test')
-rw-r--r-- | ndb/test/run-test/Makefile | 22 | ||||
-rw-r--r-- | ndb/test/run-test/README.ATRT | 34 | ||||
-rwxr-xr-x | ndb/test/run-test/atrt-analyze-result.sh | 12 | ||||
-rwxr-xr-x | ndb/test/run-test/atrt-clear-result.sh | 4 | ||||
-rwxr-xr-x | ndb/test/run-test/atrt-gather-result.sh | 16 | ||||
-rwxr-xr-x | ndb/test/run-test/atrt-setup.sh | 6 | ||||
-rw-r--r-- | ndb/test/run-test/main.cpp | 942 | ||||
-rwxr-xr-x | ndb/test/run-test/make-config.sh | 465 | ||||
-rwxr-xr-x | ndb/test/run-test/make-html-reports.sh | 437 | ||||
-rwxr-xr-x | ndb/test/run-test/make-index.sh | 242 | ||||
-rw-r--r-- | ndb/test/run-test/run-test.hpp | 92 |
11 files changed, 2272 insertions, 0 deletions
diff --git a/ndb/test/run-test/Makefile b/ndb/test/run-test/Makefile new file mode 100644 index 00000000000..6b4689b2dbb --- /dev/null +++ b/ndb/test/run-test/Makefile @@ -0,0 +1,22 @@ +include .defs.mk + +TYPE := util + +BIN_TARGET := atrt +BIN_TARGET_LIBS := mgmapi + +SOURCES = main.cpp +SCRIPTS = atrt-analyze-result.sh atrt-gather-result.sh atrt-setup.sh \ + atrt-clear-result.sh make-config.sh + +OBJECTS_LOC = $(call fixpath,$(NDB_TOP)/src/mgmclient/CpcClient.o) + +CFLAGS_main.cpp := -I$(call fixpath,$(NDB_TOP)/src/mgmclient) +CCFLAGS_LOC += -I$(call fixpath,$(NDB_TOP)/include/mgmapi) + +include $(NDB_TOP)/Epilogue.mk + +_bins:: + -rm -f $(SCRIPTS:%=$(NDB_TOP)/bin/%) + cp $(SCRIPTS) $(NDB_TOP)/bin + diff --git a/ndb/test/run-test/README.ATRT b/ndb/test/run-test/README.ATRT new file mode 100644 index 00000000000..7fe04ccdac4 --- /dev/null +++ b/ndb/test/run-test/README.ATRT @@ -0,0 +1,34 @@ + +!-- install ndb_cpcd +!-- many steps? future RPM + +!-- deploy binaries and libraries to hosts, rsync +% export DEPLOY_DST="mc05:/space/tomas/keso" +% ssh mc05 mkdir /space/tomas/keso +% export RSYNC_RSH=ssh +% make + +% mkdir -p /tmp/atrt-run-2-node +% cd /tmp/atrt-run-2-node +% cat > d.txt +baseport: 9321 +basedir: /space/tomas/keso +mgm: localhost +ndb: localhost localhost +api: localhost +% cat > default.txt +[DB DEFAULT] +NoOfReplicas: 2 +% bin/make-config.sh -m d.txt -t default.txt -d . + +% atrt -v -v +test_event -r 5 T1 + + +!-- check output +% tail -f /space/tomas/keso/run/4.ndb_api/log.out + + +!-- check processes +% export NDB_CPCC_HOSTS="mc05" +% ndb_cpcc diff --git a/ndb/test/run-test/atrt-analyze-result.sh b/ndb/test/run-test/atrt-analyze-result.sh new file mode 100755 index 00000000000..0fa46e918ef --- /dev/null +++ b/ndb/test/run-test/atrt-analyze-result.sh @@ -0,0 +1,12 @@ +#!/bin/sh + +f=`find result -name 'log.out' | xargs grep "NDBT_ProgramExit: " | grep -c "Failed"` +o=`find result -name 'log.out' | xargs grep "NDBT_ProgramExit: " | grep -c "OK"` + +if [ $o -gt 0 -a $f -eq 0 ] +then + exit 0 +fi + +exit 1 + diff --git a/ndb/test/run-test/atrt-clear-result.sh b/ndb/test/run-test/atrt-clear-result.sh new file mode 100755 index 00000000000..57d3d43d247 --- /dev/null +++ b/ndb/test/run-test/atrt-clear-result.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +set -e +rm -rf result diff --git a/ndb/test/run-test/atrt-gather-result.sh b/ndb/test/run-test/atrt-gather-result.sh new file mode 100755 index 00000000000..93d4ae428d0 --- /dev/null +++ b/ndb/test/run-test/atrt-gather-result.sh @@ -0,0 +1,16 @@ +#!/bin/sh + +set -e + +mkdir -p result +cd result +rm -rf * + +while [ $# -gt 0 ] +do + rsync -a "$1" . + shift +done + + + diff --git a/ndb/test/run-test/atrt-setup.sh b/ndb/test/run-test/atrt-setup.sh new file mode 100755 index 00000000000..aff5d4119dc --- /dev/null +++ b/ndb/test/run-test/atrt-setup.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +set -e + +ssh $1 mkdir -p $3 +rsync -a --delete --force --ignore-errors $2 $1:$3 diff --git a/ndb/test/run-test/main.cpp b/ndb/test/run-test/main.cpp new file mode 100644 index 00000000000..1ce9124431c --- /dev/null +++ b/ndb/test/run-test/main.cpp @@ -0,0 +1,942 @@ +/* Copyright (C) 2003 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + + +#include <stdio.h> +#include <getarg.h> +#include <BaseString.hpp> +#include <Parser.hpp> +#include <NdbOut.hpp> +#include <Properties.hpp> +#include <NdbAutoPtr.hpp> + +#include "run-test.hpp" +#include <SysLogHandler.hpp> +#include <FileLogHandler.hpp> + +#include <mgmapi.h> +#include "CpcClient.hpp" + +/** + psuedo code for run-test.bin + + define autotest_wrapper process at each host + start ndb-processes + + for each testcase + do + start mysqld processes + start replication processes + start test programs + + wait until test program finished or max time passed + + stop test program + stop replication processes + stop mysqld processes + + write report data-file + if test failed and ! last test + restart ndb processes + + drop all tables created by test + done + + stop ndb processes + undefined wrapper processes +*/ + +/** Global variables */ +static const char progname[] = "ndb_atrt"; +static const char * g_gather_progname = "atrt-gather-result.sh"; +static const char * g_analyze_progname = "atrt-analyze-result.sh"; +static const char * g_clear_progname = "atrt-clear-result.sh"; +static const char * g_setup_progname = "atrt-setup.sh"; + +static const char * g_setup_path = 0; +static const char * g_process_config_filename = "d.txt"; +static const char * g_log_filename = 0; +static const char * g_test_case_filename = 0; +static const char * g_report_filename = 0; + +static const char * g_default_user = 0; +static const char * g_default_base_dir = 0; +static int g_default_base_port = 0; + +static int g_report = 0; +static int g_verbosity = 0; +static FILE * g_report_file = 0; +static FILE * g_test_case_file = stdin; + +Logger g_logger; +atrt_config g_config; + +static int g_mode_bench = 0; +static int g_mode_regression = 0; +static int g_mode_interactive = 0; +static int g_mode = 0; + +static +struct getargs args[] = { + { "process-config", 0, arg_string, &g_process_config_filename, 0, 0 }, + { "setup-path", 0, arg_string, &g_setup_path, 0, 0 }, + { 0, 'v', arg_counter, &g_verbosity, 0, 0 }, + { "log-file", 0, arg_string, &g_log_filename, 0, 0 }, + { "testcase-file", 'f', arg_string, &g_test_case_filename, 0, 0 }, + { 0, 'R', arg_flag, &g_report, 0, 0 }, + { "report-file", 0, arg_string, &g_report_filename, 0, 0 }, + { "interactive", 'i', arg_flag, &g_mode_interactive, 0, 0 }, + { "regression", 'r', arg_flag, &g_mode_regression, 0, 0 }, + { "bench", 'b', arg_flag, &g_mode_bench, 0, 0 }, +}; + +const int arg_count = 10; + +int +main(int argc, const char ** argv){ + + bool restart = true; + int lineno = 1; + int test_no = 1; + + const int p_ndb = atrt_process::NDB_MGM | atrt_process::NDB_DB; + const int p_servers = atrt_process::MYSQL_SERVER | atrt_process::NDB_REP; + const int p_clients = atrt_process::MYSQL_CLIENT | atrt_process::NDB_API; + + g_logger.setCategory(progname); + g_logger.enable(Logger::LL_ALL); + g_logger.createConsoleHandler(); + + if(!parse_args(argc, argv)) + goto end; + + g_logger.info("Starting..."); + if(!setup_config(g_config)) + goto end; + + g_logger.info("Connecting to hosts"); + if(!connect_hosts(g_config)) + goto end; + + if(!setup_hosts(g_config)) + goto end; + + if(!start_processes(g_config, atrt_process::NDB_MGM)) + goto end; + + if(!connect_ndb_mgm(g_config)){ + goto end; + } + + /** + * Main loop + */ + while(!feof(g_test_case_file)){ + /** + * Do we need to restart ndb + */ + if(restart){ + g_logger.info("(Re)starting ndb processes"); + if(!stop_processes(g_config, atrt_process::NDB_DB)) + goto end; + + if(!wait_ndb(g_config, NDB_MGM_NODE_STATUS_NO_CONTACT)) + goto end; + + if(!start_processes(g_config, atrt_process::NDB_DB)) + goto end; + + if(!wait_ndb(g_config, NDB_MGM_NODE_STATUS_STARTED)) + goto end; + + g_logger.info("Ndb start completed"); + } + + const int start_line = lineno; + atrt_testcase test_case; + if(!read_test_case(g_test_case_file, test_case, lineno)) + goto end; + + g_logger.info("#%d - %s %s", + test_no, + test_case.m_command.c_str(), test_case.m_args.c_str()); + + // Assign processes to programs + if(!setup_test_case(g_config, test_case)) + goto end; + + if(!start_processes(g_config, p_servers)) + goto end; + + if(!start_processes(g_config, p_clients)) + goto end; + + int result = 0; + + const time_t start = time(0); + time_t now = start; + do { + if(!update_status(g_config, atrt_process::ALL)) + goto end; + + int count = 0; + + if((count = is_running(g_config, p_ndb)) != 2){ + result = ERR_NDB_FAILED; + break; + } + + if((count = is_running(g_config, p_servers)) != 2){ + result = ERR_SERVERS_FAILED; + break; + } + + if((count = is_running(g_config, p_clients)) == 0){ + break; + } + + now = time(0); + if(now > (start + test_case.m_max_time)){ + result = ERR_MAX_TIME_ELAPSED; + break; + } + sleep(1); + } while(true); + + const time_t elapsed = time(0) - start; + + if(!stop_processes(g_config, p_clients)) + goto end; + + if(!stop_processes(g_config, p_servers)) + goto end; + + if(!gather_result(g_config, &result)) + goto end; + + g_logger.info("#%d %s(%d)", + test_no, + (result == 0 ? "OK" : "FAILED"), result); + + if(g_report_file != 0){ + fprintf(g_report_file, "%s %s ; %d ; %d ; %d\n", + test_case.m_command.c_str(), + test_case.m_args.c_str(), + test_no, result, elapsed); + fflush(g_report_file); + } + + if(g_mode_bench || (g_mode_regression && result)){ + BaseString tmp; + tmp.assfmt("result.%d", test_no); + if(rename("result", tmp.c_str()) != 0){ + g_logger.critical("Failed to rename %s as %s", + "result", tmp.c_str()); + goto end; + } + } + + if(g_mode_interactive && result){ + g_logger.info + ("Encountered failed test in interactive mode - terminating"); + break; + } + + if(result != 0){ + restart = true; + } else { + restart = false; + } + test_no++; + } + + end: + if(g_report_file != 0){ + fclose(g_report_file); + g_report_file = 0; + } + + if(g_test_case_file != 0 && g_test_case_file != stdin){ + fclose(g_test_case_file); + g_test_case_file = 0; + } + + stop_processes(g_config, atrt_process::ALL); + return 0; +} + +bool +parse_args(int argc, const char** argv){ + int optind = 0; + if(getarg(args, arg_count, argc, argv, &optind)) { + arg_printusage(args, arg_count, progname, ""); + return false; + } + + if(g_log_filename != 0){ + g_logger.removeConsoleHandler(); + g_logger.addHandler(new FileLogHandler(g_log_filename)); + } + + { + int tmp = Logger::LL_WARNING - g_verbosity; + tmp = (tmp < Logger::LL_DEBUG ? Logger::LL_DEBUG : tmp); + g_logger.disable(Logger::LL_ALL); + g_logger.enable((Logger::LoggerLevel)tmp, Logger::LL_ALERT); + } + + + + if(!g_process_config_filename){ + g_logger.critical("Process config not specified!"); + return false; + } + + if(!g_setup_path){ + char buf[1024]; + if(getcwd(buf, sizeof(buf))){ + g_setup_path = strdup(buf); + g_logger.info("Setup path not specified, using %s", buf); + } else { + g_logger.critical("Setup path not specified!\n"); + return false; + } + } + + if(g_report & !g_report_filename){ + g_report_filename = "report.txt"; + } + + if(g_report_filename){ + g_report_file = fopen(g_report_filename, "w"); + if(g_report_file == 0){ + g_logger.critical("Unable to create report file: %s", g_report_filename); + return false; + } + } + + if(g_test_case_filename){ + g_test_case_file = fopen(g_test_case_filename, "r"); + if(g_test_case_file == 0){ + g_logger.critical("Unable to open file: %s", g_test_case_filename); + return false; + } + } + + int sum = g_mode_interactive + g_mode_regression + g_mode_bench; + if(sum == 0){ + g_mode_interactive = 1; + } + + if(sum > 1){ + g_logger.critical + ("Only one of bench/regression/interactive can be specified"); + return false; + } + + g_default_user = strdup(getenv("USER")); + + return true; +} + + +static +atrt_host * +find(const BaseString& host, Vector<atrt_host> & hosts){ + for(size_t i = 0; i<hosts.size(); i++){ + if(hosts[i].m_hostname == host){ + return &hosts[i]; + } + } + return 0; +} + +bool +setup_config(atrt_config& config){ + + FILE * f = fopen(g_process_config_filename, "r"); + if(!f){ + g_logger.critical("Failed to open process config file: %s", + g_process_config_filename); + return false; + } + bool result = true; + + int lineno = 0; + char buf[2048]; + while(fgets(buf, 2048, f)){ + lineno++; + + BaseString tmp(buf); + tmp.trim(" \t\n\r"); + + if(tmp.length() == 0 || tmp == "" || tmp.c_str()[0] == '#') + continue; + + Vector<BaseString> split1; + if(tmp.split(split1, ":", 2) != 2){ + g_logger.warning("Invalid line %d in %s - ignoring", + lineno, g_process_config_filename); + continue; + } + + if(split1[0].trim() == "basedir"){ + g_default_base_dir = strdup(split1[1].trim().c_str()); + continue; + } + + if(split1[0].trim() == "baseport"){ + g_default_base_port = atoi(split1[1].trim().c_str()); + continue; + } + + if(split1[0].trim() == "user"){ + g_default_user = strdup(split1[1].trim().c_str()); + continue; + } + + Vector<BaseString> hosts; + if(split1[1].trim().split(hosts) <= 0){ + g_logger.warning("Invalid line %d in %s - ignoring", + lineno, g_process_config_filename); + } + + // 1 - Check hosts + for(size_t i = 0; i<hosts.size(); i++){ + Vector<BaseString> tmp; + hosts[i].split(tmp, ":"); + BaseString hostname = tmp[0].trim(); + BaseString base_dir; + if(tmp.size() >= 2) + base_dir = tmp[1]; + else if(g_default_base_dir == 0){ + g_logger.critical("Basedir not specified..."); + return false; + } + + atrt_host * host_ptr; + if((host_ptr = find(hostname, config.m_hosts)) == 0){ + atrt_host host; + host.m_index = config.m_hosts.size(); + host.m_cpcd = new SimpleCpcClient(hostname.c_str(), 1234); + host.m_base_dir = (base_dir.empty() ? g_default_base_dir : base_dir); + host.m_user = g_default_user; + host.m_hostname = hostname.c_str(); + config.m_hosts.push_back(host); + } else { + if(!base_dir.empty() && (base_dir == host_ptr->m_base_dir)){ + g_logger.critical("Inconsistent base dir definition for host %s" + ", \"%s\" != \"%s\"", hostname.c_str(), + base_dir.c_str(), host_ptr->m_base_dir.c_str()); + return false; + } + } + } + + for(size_t i = 0; i<hosts.size(); i++){ + BaseString & tmp = hosts[i]; + atrt_host * host = find(tmp, config.m_hosts); + + const int index = config.m_processes.size() + 1; + atrt_process proc; + proc.m_index = index; + proc.m_host = host; + proc.m_proc.m_id = -1; + proc.m_proc.m_type = "temporary"; + proc.m_proc.m_owner = "atrt"; + proc.m_proc.m_group = "group"; + proc.m_proc.m_cwd.assign(host->m_base_dir).append("/run/"); + proc.m_proc.m_env.assign("LD_LIBRARY_PATH=").append(host->m_base_dir).append("/lib"); + proc.m_proc.m_stdout = "log.out"; + proc.m_proc.m_stderr = "2>&1"; + proc.m_proc.m_runas = proc.m_host->m_user; + proc.m_proc.m_ulimit = "c:unlimited"; + proc.m_hostname = proc.m_host->m_hostname; + proc.m_ndb_mgm_port = g_default_base_port; + if(split1[0] == "mgm"){ + proc.m_type = atrt_process::NDB_MGM; + proc.m_proc.m_name.assfmt("%d-%s", index, "ndb_mgm"); + proc.m_proc.m_path.assign(host->m_base_dir).append("/bin/mgmtsrvr"); + proc.m_proc.m_args = "-n -c initconfig.txt"; + proc.m_proc.m_cwd.appfmt("%d.ndb_mgm", index); + } else if(split1[0] == "ndb"){ + proc.m_type = atrt_process::NDB_DB; + proc.m_proc.m_name.assfmt("%d-%s", index, "ndb_db"); + proc.m_proc.m_path.assign(host->m_base_dir).append("/bin/ndb"); + proc.m_proc.m_args = "-i -n"; + proc.m_proc.m_cwd.appfmt("%d.ndb_db", index); + } else if(split1[0] == "api"){ + proc.m_type = atrt_process::NDB_API; + proc.m_proc.m_name.assfmt("%d-%s", index, "ndb_api"); + proc.m_proc.m_path = ""; + proc.m_proc.m_args = ""; + proc.m_proc.m_cwd.appfmt("%d.ndb_api", index); + } else { + g_logger.critical("%s:%d: Unhandled process type: %s", + g_process_config_filename, lineno, + split1[0].c_str()); + result = false; + goto end; + } + config.m_processes.push_back(proc); + } + } + + end: + fclose(f); + return result; +} + +bool +connect_hosts(atrt_config& config){ + for(size_t i = 0; i<config.m_hosts.size(); i++){ + if(config.m_hosts[i].m_cpcd->connect() != 0){ + g_logger.error("Unable to connect to cpc %s:%d", + config.m_hosts[i].m_cpcd->getHost(), + config.m_hosts[i].m_cpcd->getPort()); + return false; + } + g_logger.debug("Connected to %s:%d", + config.m_hosts[i].m_cpcd->getHost(), + config.m_hosts[i].m_cpcd->getPort()); + } + + return true; +} + +bool +connect_ndb_mgm(atrt_process & proc){ + NdbMgmHandle handle = ndb_mgm_create_handle(); + if(handle == 0){ + g_logger.critical("Unable to create mgm handle"); + return false; + } + BaseString tmp = proc.m_hostname; + tmp.appfmt(":%d", proc.m_ndb_mgm_port); + time_t start = time(0); + const time_t max_connect_time = 30; + do { + if(ndb_mgm_connect(handle, tmp.c_str()) != -1){ + proc.m_ndb_mgm_handle = handle; + return true; + } + sleep(1); + } while(time(0) < (start + max_connect_time)); + g_logger.critical("Unable to connect to ndb mgm %s", tmp.c_str()); + return false; +} + +bool +connect_ndb_mgm(atrt_config& config){ + for(size_t i = 0; i<config.m_processes.size(); i++){ + atrt_process & proc = config.m_processes[i]; + if((proc.m_type & atrt_process::NDB_MGM) != 0){ + if(!connect_ndb_mgm(proc)){ + return false; + } + } + } + + return true; +} + +static int remap(int i){ + if(i == NDB_MGM_NODE_STATUS_NO_CONTACT) return NDB_MGM_NODE_STATUS_UNKNOWN; + if(i == NDB_MGM_NODE_STATUS_UNKNOWN) return NDB_MGM_NODE_STATUS_NO_CONTACT; + return i; +} + +bool +wait_ndb(atrt_config& config, int goal){ + + goal = remap(goal); + + + /** + * Get mgm handle for cluster + */ + NdbMgmHandle handle = 0; + for(size_t i = 0; i<config.m_processes.size(); i++){ + atrt_process & proc = config.m_processes[i]; + if((proc.m_type & atrt_process::NDB_MGM) != 0){ + handle = proc.m_ndb_mgm_handle; + break; + } + } + if(handle == 0){ + g_logger.critical("Unable to find mgm handle"); + return false; + } + + if(goal == NDB_MGM_NODE_STATUS_STARTED){ + /** + * 1) wait NOT_STARTED + * 2) send start + * 3) wait STARTED + */ + if(!wait_ndb(config, NDB_MGM_NODE_STATUS_NOT_STARTED)) + return false; + + ndb_mgm_start(handle, 0, 0); + } + + struct ndb_mgm_cluster_state * state; + + time_t now = time(0); + time_t end = now + 360; + int min = remap(NDB_MGM_NODE_STATUS_NO_CONTACT); + int min2 = goal; + + while(now < end){ + /** + * 1) retreive current state + */ + state = ndb_mgm_get_status(handle); + if(state == 0){ + g_logger.critical("Unable to poll db state"); + return false; + } + NdbAutoPtr<void> tmp(state); + + min2 = goal; + for(int i = 0; i<state->no_of_nodes; i++){ + if(state->node_states[i].node_type == NDB_MGM_NODE_TYPE_NDB){ + const int s = remap(state->node_states[i].node_status); + min2 = (min2 < s ? min2 : s ); + + if(s < remap(NDB_MGM_NODE_STATUS_NO_CONTACT) || + s > NDB_MGM_NODE_STATUS_STARTED){ + g_logger.critical("Strange DB status during start: %d %d", i, min2); + return false; + } + } + } + + if(min2 < min){ + g_logger.critical("wait ndb failed %d %d %d", min, min2, goal); + return false; + } + + if(min2 == goal){ + return true; + break; + } + + min = min2; + now = time(0); + } + + g_logger.critical("wait ndb timed out %d %d %d", min, min2, goal); + + return false; +} + +bool +start_process(atrt_process & proc){ + if(proc.m_proc.m_id != -1){ + g_logger.critical("starting already started process: %d", proc.m_index); + return false; + } + + BaseString path = proc.m_proc.m_cwd.substr(proc.m_host->m_base_dir.length()+BaseString("/run").length()); + + BaseString tmp = g_setup_progname; + tmp.appfmt(" %s %s/%s/ %s", + proc.m_host->m_hostname.c_str(), + g_setup_path, + path.c_str(), + proc.m_proc.m_cwd.c_str()); + + const int r1 = system(tmp.c_str()); + if(r1 != 0){ + g_logger.critical("Failed to setup process"); + return false; + } + + { + Properties reply; + if(proc.m_host->m_cpcd->define_process(proc.m_proc, reply) != 0){ + BaseString msg; + reply.get("errormessage", msg); + g_logger.error("Unable to define process: %s", msg.c_str()); + return false; + } + } + { + Properties reply; + if(proc.m_host->m_cpcd->start_process(proc.m_proc.m_id, reply) != 0){ + BaseString msg; + reply.get("errormessage", msg); + g_logger.error("Unable to start process: %s", msg.c_str()); + return false; + } + } + return true; +} + +bool +start_processes(atrt_config& config, int types){ + for(size_t i = 0; i<config.m_processes.size(); i++){ + atrt_process & proc = config.m_processes[i]; + if((types & proc.m_type) != 0){ + if(!start_process(proc)){ + return false; + } + } + } + return true; +} + +bool +stop_process(atrt_process & proc){ + if(proc.m_proc.m_id == -1){ + return true; + } + + { + Properties reply; + if(proc.m_host->m_cpcd->stop_process(proc.m_proc.m_id, reply) != 0){ + Uint32 status; + reply.get("status", &status); + if(status != 4){ + BaseString msg; + reply.get("errormessage", msg); + g_logger.error("Unable to stop process: %s(%d)", msg.c_str(), status); + return false; + } + } + } + { + Properties reply; + if(proc.m_host->m_cpcd->undefine_process(proc.m_proc.m_id, reply) != 0){ + BaseString msg; + reply.get("errormessage", msg); + g_logger.error("Unable to undefine process: %s", msg.c_str()); + return false; + } + proc.m_proc.m_id = -1; + } + return true; +} + +bool +stop_processes(atrt_config& config, int types){ + for(size_t i = 0; i<config.m_processes.size(); i++){ + atrt_process & proc = config.m_processes[i]; + if((types & proc.m_type) != 0){ + if(!stop_process(proc)){ + return false; + } + } + } + return true; +} + +bool +update_status(atrt_config& config, int){ + + Vector<Vector<SimpleCpcClient::Process> > m_procs; + + Vector<SimpleCpcClient::Process> dummy; + m_procs.fill(config.m_hosts.size(), dummy); + for(size_t i = 0; i<config.m_hosts.size(); i++){ + Properties p; + config.m_hosts[i].m_cpcd->list_processes(m_procs[i], p); + } + + for(size_t i = 0; i<config.m_processes.size(); i++){ + atrt_process & proc = config.m_processes[i]; + Vector<SimpleCpcClient::Process> & h_procs = m_procs[proc.m_host->m_index]; + bool found = false; + for(size_t j = 0; j<h_procs.size(); j++){ + if(proc.m_proc.m_id == h_procs[j].m_id){ + found = true; + proc.m_proc.m_status = h_procs[j].m_status; + break; + } + } + if(!found){ + g_logger.error("update_status: not found"); + return false; + } + } + return true; +} + +int +is_running(atrt_config& config, int types){ + int found = 0, running = 0; + for(size_t i = 0; i<config.m_processes.size(); i++){ + atrt_process & proc = config.m_processes[i]; + if((types & proc.m_type) != 0){ + found++; + if(proc.m_proc.m_status == "running") + running++; + } + } + + if(found == running) + return 2; + if(running == 0) + return 0; + return 1; +} + + +int +insert(const char * pair, Properties & p){ + BaseString tmp(pair); + + tmp.trim(" \t\n\r"); + + Vector<BaseString> split; + tmp.split(split, ":=", 2); + + if(split.size() != 2) + return -1; + + p.put(split[0].trim().c_str(), split[1].trim().c_str()); + + return 0; +} + +bool +read_test_case(FILE * file, atrt_testcase& tc, int& line){ + + Properties p; + int elements = 0; + char buf[1024]; + while(!feof(file)){ + if(!fgets(buf, 1024, file)) + break; + + line++; + BaseString tmp = buf; + + if(tmp.length() > 0 && tmp.c_str()[0] == '#') + continue; + + if(insert(tmp.c_str(), p) != 0) + break; + + elements++; + } + + if(elements == 0){ + if(file == stdin){ + BaseString tmp(buf); + tmp.trim(" \t\n\r"); + Vector<BaseString> split; + tmp.split(split, " ", 2); + tc.m_command = split[0]; + if(split.size() == 2) + tc.m_args = split[1]; + else + tc.m_args = ""; + tc.m_max_time = 60000; + return true; + } + return false; + } + + if(!p.get("cmd", tc.m_command)){ + g_logger.critical("Invalid test file: cmd is missing near line: %d", line); + return false; + } + + if(!p.get("args", tc.m_args)) + tc.m_args = ""; + + const char * mt = 0; + if(!p.get("max-time", &mt)) + tc.m_max_time = 60000; + else + tc.m_max_time = atoi(mt); + + return true; +} + +bool +setup_test_case(atrt_config& config, const atrt_testcase& tc){ + const int r1 = system(g_clear_progname); + if(r1 != 0){ + g_logger.critical("Failed to clear result"); + return false; + } + + for(size_t i = 0; i<config.m_processes.size(); i++){ + atrt_process & proc = config.m_processes[i]; + if(proc.m_type == atrt_process::NDB_API){ + proc.m_proc.m_path.assign(proc.m_host->m_base_dir).append("/bin/").append(tc.m_command); + proc.m_proc.m_args.assign(tc.m_args); + return true; + } + } + + return false; +} + +bool +gather_result(atrt_config& config, int * result){ + BaseString tmp = g_gather_progname; + for(size_t i = 0; i<config.m_processes.size(); i++){ + atrt_process & proc = config.m_processes[i]; + tmp.appfmt(" %s:%s", + proc.m_hostname.c_str(), + proc.m_proc.m_cwd.c_str()); + } + + const int r1 = system(tmp.c_str()); + if(r1 != 0){ + g_logger.critical("Failed to gather result"); + return false; + } + + const int r2 = system(g_analyze_progname); + + if(r2 == -1 || r2 == (127 << 8)){ + g_logger.critical("Failed to analyze results"); + return false; + } + + * result = r2 ; + return true; +} + +bool +setup_hosts(atrt_config& config){ + const int r1 = system(g_clear_progname); + if(r1 != 0){ + g_logger.critical("Failed to clear result"); + return false; + } + + for(size_t i = 0; i<config.m_hosts.size(); i++){ + BaseString tmp = g_setup_progname; + tmp.appfmt(" %s %s/ %s/run", + config.m_hosts[i].m_hostname.c_str(), + g_setup_path, + config.m_hosts[i].m_base_dir.c_str()); + + const int r1 = system(tmp.c_str()); + if(r1 != 0){ + g_logger.critical("Failed to setup %s", + config.m_hosts[i].m_hostname.c_str()); + return false; + } + } + return true; +} diff --git a/ndb/test/run-test/make-config.sh b/ndb/test/run-test/make-config.sh new file mode 100755 index 00000000000..5394b0654d4 --- /dev/null +++ b/ndb/test/run-test/make-config.sh @@ -0,0 +1,465 @@ +#!/bin/sh +# NAME +# make-config.sh - Makes a config file for mgm server +# +# SYNOPSIS +# make-config.sh [ -t <template> ] [-s] [ -m <machine conf> [ -d <directory> ] +# +# DESCRIPTION +# +# OPTIONS +# +# EXAMPLES +# +# +# ENVIRONMENT +# NDB_PROJ_HOME Home dir for ndb +# +# FILES +# $NDB_PROJ_HOME/lib/funcs.sh general shell script functions +# +# +# SEE ALSO +# +# DIAGNOSTICTS +# +# VERSION +# 1.0 +# 1.1 021112 epesson: Adapted for new mgmt server in NDB 2.00 +# +# AUTHOR +# Jonas Oreland +# +# CHANGES +# also generate ndbnet config +# + +progname=`basename $0` +synopsis="make-config.sh [ -t template ] [ -m <machine conf> ] [ -d <dst directory> ][-s] [<mgm host>]" + +#: ${NDB_PROJ_HOME:?} # If undefined, exit with error message + +#: ${NDB_LOCAL_BUILD_OPTIONS:=--} # If undef, set to --. Keeps getopts happy. + # You may have to experiment a bit + # to get quoting right (if you need it). + + +#. $NDB_PROJ_HOME/lib/funcs.sh # Load some good stuff +trace() { + echo $* 1>&2 +} +syndie() { + trace $* + exit 1 +} + +# defaults for options related variables +# + +mgm_nodes=0 +ndb_nodes=0 +api_nodes=0 +uniq_id=$$.$$ +own_host=`hostname` +dst_dir="" +template=/dev/null +machines=/dev/null +verbose=yes + +# used if error when parsing the options environment variable +# +env_opterr="options environment variable: <<$options>>" + +# Option parsing, for the options variable as well as the command line. +# +# We want to be able to set options in an environment variable, +# as well as on the command line. In order not to have to repeat +# the same getopts information twice, we loop two times over the +# getopts while loop. The first time, we process options from +# the options environment variable, the second time we process +# options from the command line. +# +# The things to change are the actual options and what they do. +# +add_node(){ + no=$1; shift + type=$1; shift + echo $* | awk 'BEGIN{FS=":";}{h=$1; if(h=="localhost") h="'$own_host'"; + printf("%s_%d_host=%s\n", "'$type'", "'$no'", h); + if(NF>1 && $2!="") printf("%s_%d_port=%d\n", + "'$type'", "'$no'", $2); + if(NF>2 && $3!="") printf("%s_%d_dir=%s\n", + "'$type'", "'$no'", $3); + }' +} + + +add_mgm_node(){ + mgm_nodes=`cat /tmp/mgm_nodes.$uniq_id | grep "_host=" | wc -l` + mgm_nodes=`expr $mgm_nodes + 1` + while [ $# -gt 0 ] + do + add_node ${mgm_nodes} mgm_node $1 >> /tmp/mgm_nodes.$uniq_id + shift + mgm_nodes=`expr $mgm_nodes + 1` + done +} + +add_ndb_node(){ + ndb_nodes=`cat /tmp/ndb_nodes.$uniq_id | grep "_host=" | wc -l` + ndb_nodes=`expr $ndb_nodes + 1` + while [ $# -gt 0 ] + do + add_node ${ndb_nodes} ndb_node $1 >> /tmp/ndb_nodes.$uniq_id + shift + ndb_nodes=`expr $ndb_nodes + 1` + done +} + +add_api_node(){ + api_nodes=`cat /tmp/api_nodes.$uniq_id | grep "_host=" |wc -l` + api_nodes=`expr $api_nodes + 1` + while [ $# -gt 0 ] + do + add_node ${api_nodes} api_node $1 >> /tmp/api_nodes.$uniq_id + shift + api_nodes=`expr $api_nodes + 1` + done +} + +rm -rf /tmp/mgm_nodes.$uniq_id ; touch /tmp/mgm_nodes.$uniq_id +rm -rf /tmp/ndb_nodes.$uniq_id ; touch /tmp/ndb_nodes.$uniq_id +rm -rf /tmp/api_nodes.$uniq_id ; touch /tmp/api_nodes.$uniq_id + +for optstring in "$options" "" # 1. options variable 2. cmd line +do + + while getopts d:m:t:n:o:a:b:p:s i $optstring # optstring empty => no arg => cmd line + do + case $i in + + q) verbose="";; # echo important things + t) template=$OPTARG;; # Template + d) dst_dir=$OPTARG;; # Destination directory + m) machines=$OPTARG;; # Machine configuration + s) mgm_start=yes;; # Make mgm start script + \?) syndie $env_opterr;; # print synopsis and exit + + esac + done + + [ -n "$optstring" ] && OPTIND=1 # Reset for round 2, cmdline options + + env_opterr= # Round 2 should not use the value + +done +shift `expr $OPTIND - 1` + +if [ -z "$dst_dir" ] +then + verbose= +fi + +skip(){ + no=$1; shift + shift $no + echo $* +} + +# --- option parsing done --- +grep "^ndb: " $machines | while read node +do + node=`skip 1 $node` + add_ndb_node $node +done + +grep "^api: " $machines | while read node +do + node=`skip 1 $node` + add_api_node $node +done + +grep "^mgm: " $machines | while read node +do + node=`skip 1 $node` + add_mgm_node $node +done + +tmp=`grep "^baseport: " $machines | tail -1 | cut -d ":" -f 2` +if [ "$tmp" ] +then + baseport=`echo $tmp` +else + syndie "Unable to find baseport" +fi + +trim(){ + echo $* +} +tmp=`grep "^basedir: " $machines | tail -1 | cut -d ":" -f 2` +if [ "$tmp" ] +then + basedir=`trim $tmp` +fi + +# -- Load enviroment -- +ndb_nodes=`cat /tmp/ndb_nodes.$uniq_id | grep "_host=" | wc -l` +api_nodes=`cat /tmp/api_nodes.$uniq_id | grep "_host=" | wc -l` +mgm_nodes=`cat /tmp/mgm_nodes.$uniq_id | grep "_host=" | wc -l` +. /tmp/ndb_nodes.$uniq_id +. /tmp/api_nodes.$uniq_id +. /tmp/mgm_nodes.$uniq_id +rm -f /tmp/ndb_nodes.$uniq_id /tmp/api_nodes.$uniq_id /tmp/mgm_nodes.$uniq_id + +# -- Verify +trace "Verifying arguments" + +if [ ! -r $template ] +then + syndie "Unable to read template file: $template" +fi + +if [ $ndb_nodes -le 0 ] +then + syndie "No ndb nodes specified" +fi + +if [ $api_nodes -le 0 ] +then + syndie "No api nodes specified" +fi + +if [ $mgm_nodes -gt 1 ] +then + syndie "More than one mgm node specified" +fi + +if [ $mgm_nodes -eq 0 ] +then + trace "No managment server specified using `hostname`" + mgm_nodes=1 + mgm_node_1=`hostname` +fi + +if [ -n "$dst_dir" ] +then + mkdir -p $dst_dir + if [ ! -d $dst_dir ] + then + syndie "Unable to create dst dir: $dst_dir" + fi + DST=/tmp/$uniq_id +fi + +# --- option verifying done --- + +# Find uniq computers +i=1 +while [ $i -le $mgm_nodes ] +do + echo `eval echo "\$"mgm_node_${i}_host` >> /tmp/hosts.$uniq_id + i=`expr $i + 1` +done + +i=1 +while [ $i -le $ndb_nodes ] +do + echo `eval echo "\$"ndb_node_${i}_host` >> /tmp/hosts.$uniq_id + i=`expr $i + 1` +done + +i=1 +while [ $i -le $api_nodes ] +do + echo `eval echo "\$"api_node_${i}_host` >> /tmp/hosts.$uniq_id + i=`expr $i + 1` +done + +sort -u -o /tmp/hosts.$uniq_id /tmp/hosts.$uniq_id + +get_computer_id(){ + grep -w -n $1 /tmp/hosts.$uniq_id | cut -d ":" -f 1 +} + +get_mgm_computer_id(){ + a=`eval echo "\$"mgm_node_${1}_host` + get_computer_id $a +} + +get_ndb_computer_id(){ + a=`eval echo "\$"ndb_node_${1}_host` + get_computer_id $a +} + +get_api_computer_id(){ + a=`eval echo "\$"api_node_${1}_host` + get_computer_id $a +} + +# -- Write config files -- + +mgm_port=$baseport + +( + i=1 + #echo "COMPUTERS" + cat /tmp/hosts.$uniq_id | while read host + do + echo "[COMPUTER]" + echo "Id: $i" + echo "ByteOrder: Big" + echo "HostName: $host" + echo + i=`expr $i + 1` + done + + node_id=1 + echo + + # Mgm process + echo + echo "[MGM]" + echo "Id: $node_id" + echo "ExecuteOnComputer: `get_mgm_computer_id 1`" + echo "PortNumber: $mgm_port" + node_id=`expr $node_id + 1` + + # Ndb processes + i=1 + ndb_nodes=`trim $ndb_nodes` + while [ $i -le $ndb_nodes ] + do + echo + echo "[DB]" + echo "Id: $node_id" + echo "ExecuteOnComputer: `get_ndb_computer_id $i`" + echo "FileSystemPath: $basedir/run/node-${node_id}-fs" + i=`expr $i + 1` + node_id=`expr $node_id + 1` + done + + # API processes + i=1 + while [ $i -le $api_nodes ] + do + echo + echo "[API]" + echo "Id: $node_id" + echo "ExecuteOnComputer: `get_api_computer_id $i`" + i=`expr $i + 1` + node_id=`expr $node_id + 1` + done + + # Connections + current_port=`expr $mgm_port + 1` + echo + + # Connect Mgm with all ndb-nodes + i=1 + while [ $i -le $ndb_nodes ] + do + echo + echo "[TCP]" + echo "NodeId1: 1" + echo "NodeId2: `expr $i + 1`" + echo "PortNumber: $current_port" + i=`expr $i + 1` + current_port=`expr $current_port + 1` + done + + # Connect All ndb processes with all ndb processes + i=1 + while [ $i -le $ndb_nodes ] + do + j=`expr $i + 1` + while [ $j -le $ndb_nodes ] + do + echo + echo "[TCP]" + echo "NodeId1: `expr $i + 1`" + echo "NodeId2: `expr $j + 1`" + echo "PortNumber: $current_port" + j=`expr $j + 1` + current_port=`expr $current_port + 1` + done + i=`expr $i + 1` + done + + # Connect all ndb-nodes with all api nodes + i=1 + while [ $i -le $ndb_nodes ] + do + j=1 + while [ $j -le $api_nodes ] + do + echo + echo "[TCP]" + echo "NodeId1: `expr $i + 1`" + echo "NodeId2: `expr $j + $ndb_nodes + 1`" + echo "PortNumber: $current_port" + j=`expr $j + 1` + current_port=`expr $current_port + 1` + done + i=`expr $i + 1` + done + echo +) > $DST + +trace "Init config file done" + +if [ -z "$dst_dir" ] +then + cat $DST + rm -f $DST + rm -f /tmp/hosts.$uniq_id + exit 0 +fi + +### +# Create Ndb.cfg files + +# nodeid=2;host=localhost:2200 + +# Mgm node +mkcfg(){ + mkdir -p $dst_dir/${2}.ndb_${1} + ( + echo "OwnProcessId $2" + echo "host://${mgm_node_1_host}:${mgm_port}" + ) > $dst_dir/${2}.ndb_${1}/Ndb.cfg + if [ $1 = "db" ] + then + mkdir $dst_dir/node-${2}-fs + fi +} + +mkcfg mgm 1 +cat $DST > $dst_dir/1.ndb_mgm/initconfig.txt + +trace "Creating Ndb.cfg for ndb nodes" + +current_node=2 +i=1 +while [ $i -le $ndb_nodes ] +do + mkcfg db ${current_node} + i=`expr $i + 1` + current_node=`expr $current_node + 1` +done + +trace "Creating Ndb.cfg for api nodes" + +i=1 +while [ $i -le $api_nodes ] +do + mkcfg api ${current_node} + i=`expr $i + 1` + current_node=`expr $current_node + 1` +done + +rm -f $DST +rm -f /tmp/hosts.$uniq_id + + +exit 0 +# vim: set sw=4: diff --git a/ndb/test/run-test/make-html-reports.sh b/ndb/test/run-test/make-html-reports.sh new file mode 100755 index 00000000000..079650a729f --- /dev/null +++ b/ndb/test/run-test/make-html-reports.sh @@ -0,0 +1,437 @@ +#!/bin/sh +# NAME +# make-html-reports.sh +# +# SYNOPSIS +# make-html-reports.sh [-q] [ -R <YYYY-MM-DD> ] [ -s <src dir> ] [ -d <dst dir> ] [ -c <conf dir> ] +# +# DESCRIPTION +# +# OPTIONS +# +# EXAMPLES +# +# +# ENVIRONMENT +# NDB_PROJ_HOME Home dir for ndb +# +# FILES +# $NDB_PROJ_HOME/lib/funcs.sh general shell script functions +# +# +# SEE ALSO +# +# DIAGNOSTICTS +# +# VERSION +# 1.0 +# +# AUTHOR +# Jonas Oreland +# + +progname=`basename $0` +synopsis="make-html-reports.sh [ -R <YYYY-MM-DD> ] [ -s <src dir> ] [ -d <dst dir> ] [ -c <conf dir> ]" + +: ${NDB_PROJ_HOME:?} # If undefined, exit with error message + +: ${NDB_LOCAL_BUILD_OPTIONS:=--} # If undef, set to --. Keeps getopts happy. + # You may have to experiment a bit + # to get quoting right (if you need it). + + +. $NDB_PROJ_HOME/lib/funcs.sh # Load some good stuff + +# defaults for options related variables +# + + +src_dir=`pwd` +dst_dir=`pwd` +conf_dir=`pwd` +report_date=`date '+%Y-%m-%d'` +uniq_id=$$.$$ +verbose=yes + +# used if error when parsing the options environment variable +# +env_opterr="options environment variable: <<$options>>" + +# Option parsing, for the options variable as well as the command line. +# +# We want to be able to set options in an environment variable, +# as well as on the command line. In order not to have to repeat +# the same getopts information twice, we loop two times over the +# getopts while loop. The first time, we process options from +# the options environment variable, the second time we process +# options from the command line. +# +# The things to change are the actual options and what they do. +# +# + +for optstring in "$options" "" # 1. options variable 2. cmd line +do + + while getopts q:s:R:d:c: i $optstring # optstring empty => no arg => cmd line + do + case $i in + + q) verbose="";; # echo important things + d) dst_dir=$OPTARG;; # Destination directory + s) src_dir=$OPTARG;; # Destination directory + c) conf_dir=$OPTARG;; # + R) report_date=$OPTARG;; # + \?) syndie $env_opterr;; # print synopsis and exit + + esac + done + + [ -n "$optstring" ] && OPTIND=1 # Reset for round 2, cmdline options + + env_opterr= # Round 2 should not use the value + +done +shift `expr $OPTIND - 1` + +src_dir=`abspath $src_dir` +dst_dir=`abspath $dst_dir` +conf_dir=`abspath $conf_dir` + +### +# +# General html functions +header(){ + cat <<EOF +<html><head><title>$*</title></head> +<body> +EOF +} + +footer(){ + cat <<EOF +</body></html> +EOF +} + +heading(){ + h=$1; shift + cat <<EOF +<h$h>$*</h$h> +EOF +} + +table(){ + echo "<table $*>" +} + +end_table(){ + echo "</table>" +} + +row(){ + echo "<tr>" +} + +end_row(){ + echo "</tr>" +} + +c_column(){ + cat <<EOF +<td valign=center align=center>$*</td> +EOF +} + +bold(){ + cat <<EOF +<b>$*</b> +EOF +} +column(){ + cat <<EOF +<td valign=center align=left>$*</td> +EOF +} + +para(){ + cat <<EOF +<p></p> +EOF +} + +hr(){ + cat <<EOF +<hr> +EOF +} + +# --- option parsing done --- + +# -- Verify +trace "Verifying arguments" +summary_file=$src_dir/reports/summary.$report_date + +if [ ! -r $summary_file ] +then + syndie "Invalid src directory or report date: $summary_file not found" +fi + +if [ ! -d $conf_dir/configurations ] +then + syndie "Invalid src directory: $conf_dir/configurations not found" +fi + +if [ ! -d $conf_dir/testcases ] +then + syndie "Invalid src directory: $conf_dir/testcases not found" +fi + +if [ ! -d $dst_dir ] +then + syndie "Invalid dst dir..." +fi + +# --- option verifying done --- + +trace "src_dir: $src_dir" +trace "dst_dir: $dst_dir" +trace "conf_dir: $conf_dir" +trace "report date: $report_date" + +### +config_spec(){ + cat <<EOF +<a href=#$1>$1</a> +EOF +} + +config_spec_include(){ + # Print the $1 file to the file we are generating + cat <<EOF +<a name=$1><pre> +EOF + if [ -r $conf_dir/configurations/$1 ] + then + cat -E $conf_dir/configurations/$1 | sed 's/\$/<BR>/g' + else + cat <<EOF + Config spec $1 not found +EOF + fi +cat <<EOF +</pre></a> +EOF +} + +time_spec(){ + # $1 - secs + _ts_tmp=$1 + + _ts_s=`expr $_ts_tmp % 60` + _ts_tmp=`expr $_ts_tmp / 60` + + _ts_m=`expr $_ts_tmp % 60` + _ts_tmp=`expr $_ts_tmp / 60` + + _ts_h=$_ts_tmp + + if [ $_ts_h -gt 0 ] + then + ret="${_ts_h}h" + fi + + [ $_ts_m -gt 0 ] || [ $_ts_h -gt 0 ] && ret="$ret${_ts_m}m" + + ret="$ret${_ts_s}s" + echo $ret +} + +log_spec(){ + _ff_=$src_dir/log/$report_date/$1.$2/test.$3.out + if [ -r $_ff_ ] && [ -s $_ff_ ] + then + _f2_=$dst_dir/log.$report_date.$1.$2.$3.out.gz + if [ -r $_f2_ ] + then + rm $_f2_ + fi + cp $_ff_ $dst_dir/log.$report_date.$1.$2.$3.out + gzip $dst_dir/log.$report_date.$1.$2.$3.out + rm -f $dst_dir/log.$report_date.$1.$2.$3.out + echo "<a href=log.$report_date.$1.$2.$3.out.gz>Log file</a>" + else + echo "-" + fi +} + +err_spec(){ + _ff_=$src_dir/log/$report_date/$1.$2/test.$3.err.tar + if [ -r $_ff_ ] && [ -s $_ff_ ] + then + cp $_ff_ $dst_dir/err.$report_date.$1.$2.$3.err.tar + gzip $dst_dir/err.$report_date.$1.$2.$3.err.tar + rm -f $dst_dir/err.$report_date.$1.$2.$3.err.tar + echo "<a href=err.$report_date.$1.$2.$3.err.tar.gz>Error tarball</a>" + else + echo "-" + fi +} + +command_spec(){ + echo $* | sed 's/;/<BR>/g' +} + +### Main + +html_summary_file=$dst_dir/summary.$report_date.html + +trace "Creating summary" +( + eval `grep "TOTAL" $summary_file | awk -F";" '{ printf("test_file=\"%s\"; elapsed=\"%s\"; started=\"%s\"; stopped=\"%s\"", $2, $3, $4, $5); }'` + + header "Autotest summary $report_date" + heading 1 "Autotest summary $report_date" + table + row ; column `bold test file: `; column $test_file ; end_row + row ; column `bold Started:` ; column "$started "; end_row + row ; column `bold Stopped:` ; column "$stopped "; end_row + row ; column `bold Elapsed:` ; column "`time_spec $elapsed secs`" ; end_row + end_table + hr + + table "border=1" + row + c_column `bold Report` + c_column `bold Tag` + c_column `bold Version` + c_column `bold Distr-Config` + c_column `bold Db-Config` + c_column `bold Type` + c_column `bold Test file` + c_column `bold Make` + c_column `bold Config` + c_column `bold Test time` + c_column `bold Passed` + c_column `bold Failed` + end_row + + grep -v "^#" $summary_file | grep -v TOTAL | sed 's/;/ /g' | \ + while read tag version config template type test_file make_res make_time conf_res conf_time test_time passed failed + do + row + if [ -r $src_dir/reports/report.$tag.$version.$config.$template.$type.$test_file.$report_date ] + then + column "<a href=\"report.$tag.$version.$config.$template.$type.$test_file.$report_date.html\">report</a>" + else + column "-" + fi + + column $tag + column $version + column $config + column $template + column $type + column $test_file + column "$make_res(`time_spec $make_time`)" + column "$conf_res(`time_spec $conf_time`)" + c_column "`time_spec $test_time`" + c_column `bold $passed` + c_column `bold $failed` + end_row + done + end_table + + footer +) > $html_summary_file + +for i in $src_dir/reports/report.*.$report_date +do + f=`basename $i` + trace "Creating report: $f" + eval `echo $f | awk -F"." '{printf("tag=%s;version=%s;config=%s;template=%s;type=%s;test_file=%s", $2, $3, $4, $5, $6, $7);}'` + + ( + header "Autotest report $report_date" + heading 1 "Autotest report $report_date" + table #"border=1" + row ; column `bold Tag:`; column $tag ; end_row + row ; column `bold Version:` ; column $version ; end_row + row ; column `bold Configuration:` ; column `config_spec $config`; end_row + row ; column `bold Template:` ; column `config_spec $template`; end_row + row ; column `bold Type:` ; column $type ; end_row + row ; column `bold Test file:` ; column $test_file; end_row + end_table + hr + + table "border=1" + row + c_column `bold Test case` + c_column `bold Result` + c_column `bold Test time` + c_column `bold Logfile` + c_column `bold Error tarfile` + end_row + + grep -v "^#" $i | sed 's/;/ /g' | \ + while read test_no test_res test_time cmd + do + row + column "`command_spec $cmd`" + case "$test_res" in + 0) + column "PASSED";; + 1001) + column "API error";; + 1002) + column "Max time expired";; + 1003) + column "Mgm port busy";; + *) + column "Unknown: $test_res";; + esac + + column "`time_spec $test_time`" + + column "`log_spec $tag $version $test_no`" + column "`err_spec $tag $version $test_no`" + end_row + done + end_table + + # Last on page we include spec + # of used machines and template for config + # for future reference + hr + table "border=1" + row; column `bold Configuration:` $config; end_row + row; column `config_spec_include $config`; end_row + end_table + hr + table "border=1" + row; column `bold Template:` $template; end_row + row; column `config_spec_include $template`; end_row + end_table + + footer + + ) > $dst_dir/$f.html +done + +# Re creating index +trace "Recreating index" +( + header "Autotest super-duper index" + heading 1 "<center>Autotest super-duper index</center>" + hr + for i in `ls $dst_dir/summary.*.html | sort -r -n` + do + f=`basename $i` + cat <<EOF +<p><a href=$f>$f</a></p> +EOF + done + footer +) > $dst_dir/index.html + +exit 0 diff --git a/ndb/test/run-test/make-index.sh b/ndb/test/run-test/make-index.sh new file mode 100755 index 00000000000..944f0df790b --- /dev/null +++ b/ndb/test/run-test/make-index.sh @@ -0,0 +1,242 @@ +#!/bin/sh +# NAME +# make-index.sh +# +# SYNOPSIS +# make-index.sh [ -d <dir> ] +# +# DESCRIPTION +# +# OPTIONS +# +# EXAMPLES +# +# +# ENVIRONMENT +# NDB_PROJ_HOME Home dir for ndb +# +# FILES +# $NDB_PROJ_HOME/lib/funcs.sh general shell script functions +# +# +# SEE ALSO +# +# DIAGNOSTICTS +# +# VERSION +# 1.0 +# +# AUTHOR +# Jonas Oreland +# + +progname=`basename $0` +synopsis="make-index.sh [ -d <dir> ]" + +: ${NDB_PROJ_HOME:?} # If undefined, exit with error message + +: ${NDB_LOCAL_BUILD_OPTIONS:=--} # If undef, set to --. Keeps getopts happy. + # You may have to experiment a bit + # to get quoting right (if you need it). + + +. $NDB_PROJ_HOME/lib/funcs.sh # Load some good stuff + +# defaults for options related variables +# + +dst_dir=/home/autotest/html +report_date=`date '+%Y-%m-%d'` +uniq_id=$$.$$ +verbose=yes + +# used if error when parsing the options environment variable +# +env_opterr="options environment variable: <<$options>>" + +# Option parsing, for the options variable as well as the command line. +# +# We want to be able to set options in an environment variable, +# as well as on the command line. In order not to have to repeat +# the same getopts information twice, we loop two times over the +# getopts while loop. The first time, we process options from +# the options environment variable, the second time we process +# options from the command line. +# +# The things to change are the actual options and what they do. +# +# + +for optstring in "$options" "" # 1. options variable 2. cmd line +do + + while getopts q:s:R:d: i $optstring # optstring empty => no arg => cmd line + do + case $i in + + q) verbose="";; # echo important things + d) dst_dir=$OPTARG;; # Destination directory + \?) syndie $env_opterr;; # print synopsis and exit + + esac + done + + [ -n "$optstring" ] && OPTIND=1 # Reset for round 2, cmdline options + + env_opterr= # Round 2 should not use the value + +done +shift `expr $OPTIND - 1` + +dst_dir=`abspath $dst_dir` + +### +# +# General html functions +header(){ + cat <<EOF +<html><head><title>$*</title></head> +<body> +EOF +} + +footer(){ + cat <<EOF +</body></html> +EOF +} + +heading(){ + h=$1; shift + cat <<EOF +<h$h>$*</h$h> +EOF +} + +table(){ + echo "<table $*>" +} + +end_table(){ + echo "</table>" +} + +row(){ + echo "<tr>" +} + +end_row(){ + echo "</tr>" +} + +c_column(){ + cat <<EOF +<td valign=center align=center>$*</td> +EOF +} + +bold(){ + cat <<EOF +<b>$*</b> +EOF +} +column(){ + cat <<EOF +<td valign=center align=left>$*</td> +EOF +} + +para(){ + cat <<EOF +<p></p> +EOF +} + +hr(){ + cat <<EOF +<hr> +EOF +} + +inc_summary() { + grep -v 'html>' $2 | grep -v body | sed 's/href="/href="'$1'\//g' +} + +# --- option parsing done --- + + + +# -- Verify +trace "Verifying arguments" + +# --- option verifying done --- + +### Main + +# Re creating index +trace "Creating index" +( + header "Autotest super-duper index" + heading 1 "<center>Autotest super-duper index</center>" + cat -E README.autotest | sed 's/\$/<BR>/g' + echo "<br>" + echo "Current <a href="crontab.current">crontab</a> installed on mc01 running [" `uname -a` "]" + hr + + dirs=`find $dst_dir -name 'summary.*.html' -type f -maxdepth 2 -exec dirname {} \; | sort -u` + + dates=`find $dst_dir -name 'summary.*.html' -type f -maxdepth 2 -exec basename {} \; | sed 's/summary\.\(.*\)\.html/\1/g' | sort -u | sort -r` + + echo "<p align=center>" + +#inline 5 latest reports + r_count=5 + for d in $dates + do + for o in $dirs + do + o=`basename $o` + if [ -r $dst_dir/$o/summary.$d.html ] + then + inc_summary $o $dst_dir/$o/summary.$d.html + hr + + r_count=`expr $r_count - 1` + if [ $r_count -eq 0 ] + then + break 2 + fi + fi + done + done + + table "border=1" + row + for i in $dirs + do + i=`basename $i` + column `bold $i` + done + end_row + + + for d in $dates + do + row + for o in $dirs + do + o=`basename $o` + if [ -r $dst_dir/$o/summary.$d.html ] + then + column "<a href=$o/summary.$d.html>$d</a>" + else + column "" + fi + done + end_row + done + end_table + footer +) > $dst_dir/index.html + +exit 0 diff --git a/ndb/test/run-test/run-test.hpp b/ndb/test/run-test/run-test.hpp new file mode 100644 index 00000000000..8387f8638ed --- /dev/null +++ b/ndb/test/run-test/run-test.hpp @@ -0,0 +1,92 @@ +/* Copyright (C) 2003 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#ifndef atrt_config_hpp +#define atrt_config_hpp + +#include <getarg.h> +#include <Vector.hpp> +#include <BaseString.hpp> +#include <Logger.hpp> +#include <mgmapi.h> +#include <CpcClient.hpp> + +enum ErrorCodes { + ERR_OK = 0, + ERR_NDB_FAILED = 101, + ERR_SERVERS_FAILED = 102, + ERR_MAX_TIME_ELAPSED = 103 +}; + +struct atrt_host { + size_t m_index; + BaseString m_user; + BaseString m_base_dir; + BaseString m_hostname; + SimpleCpcClient * m_cpcd; +}; + +struct atrt_process { + size_t m_index; + BaseString m_hostname; + struct atrt_host * m_host; + + enum Type { + ALL = 255, + NDB_DB = 1, + NDB_API = 2, + NDB_MGM = 4, + NDB_REP = 8, + MYSQL_SERVER = 16, + MYSQL_CLIENT = 32 + } m_type; + + SimpleCpcClient::Process m_proc; + short m_ndb_mgm_port; + NdbMgmHandle m_ndb_mgm_handle; // if type == ndb_mgm +}; + +struct atrt_config { + BaseString m_key; + Vector<atrt_host> m_hosts; + Vector<atrt_process> m_processes; +}; + +struct atrt_testcase { + time_t m_max_time; + BaseString m_command; + BaseString m_args; +}; + +extern Logger g_logger; + +bool parse_args(int argc, const char** argv); +bool setup_config(atrt_config&); +bool connect_hosts(atrt_config&); +bool connect_ndb_mgm(atrt_config&); +bool wait_ndb(atrt_config&, int ndb_mgm_node_status); +bool start_processes(atrt_config&, int); +bool stop_processes(atrt_config&, int); +bool update_status(atrt_config&, int); +int is_running(atrt_config&, int); +bool gather_result(atrt_config&, int * result); + +bool read_test_case(FILE *, atrt_testcase&, int& line); +bool setup_test_case(atrt_config&, const atrt_testcase&); + +bool setup_hosts(atrt_config&); + +#endif |