diff options
author | Kim van der Riet <kpvdr@apache.org> | 2014-02-05 19:31:16 +0000 |
---|---|---|
committer | Kim van der Riet <kpvdr@apache.org> | 2014-02-05 19:31:16 +0000 |
commit | 6830623d40df0e0cf266da9cc4d8e20ef5f701ff (patch) | |
tree | c61d66a96bc5dbdccb292e97dc82250e838c0c9f | |
parent | 3ad602825cf4954a09372822fc168f5b03d916e9 (diff) | |
download | qpid-python-6830623d40df0e0cf266da9cc4d8e20ef5f701ff.tar.gz |
QPID-5361: Added a bash script which allows for transactional soak testing.
git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk@1564893 13f79535-47bb-0310-9956-ffa450edef68
-rwxr-xr-x | qpid/cpp/src/tests/linearstore/tx-test-soak.sh | 234 |
1 files changed, 234 insertions, 0 deletions
diff --git a/qpid/cpp/src/tests/linearstore/tx-test-soak.sh b/qpid/cpp/src/tests/linearstore/tx-test-soak.sh new file mode 100755 index 0000000000..072b606ecb --- /dev/null +++ b/qpid/cpp/src/tests/linearstore/tx-test-soak.sh @@ -0,0 +1,234 @@ +#! /bin/bash + +# tx-test-soak +# +# Basic test methodology: +# 1. Start broker +# 2. Run qpid-txtest against broker using randomly generated parameters +# 3. After some time, kill the broker using SIGKILL +# 4. Restart broker, recover messages +# 5. Run qpid-txtest against broker in check mode, which checks that all expected messages are present. +# 6. Wash, rinse, repeat... The number of runs is determined by ${NUM_RUNS} + +NUM_RUNS=1000 +BASE_DIR=${HOME}/RedHat +CMAKE_BUILD_DIR=${BASE_DIR}/q.cm + +# Infrequently adjusted +RESULT_BASE_DIR_PREFIX=${BASE_DIR}/results.tx-test-soak +RECOVER_TIME_PER_QUEUE=1 +STORE_MODULE="linearstore.so" +BROKER_LOG_LEVEL="info+" +BROKER_MANAGEMENT="no" # "no" or "yes" +TRUNCATE_INTERVAL=10 +MAX_DISK_PERC_USED=90 + +# Consts (don't adjust these...) +export BASE_DIR +RELATIVE_BASE_DIR=`python -c "import os,os.path; print os.path.relpath(os.environ['BASE_DIR'], os.environ['PWD'])"` +LOG_FILE_NAME=log.txt +QPIDD_FN=qpidd +QPIDD=${CMAKE_BUILD_DIR}/src/${QPIDD_FN} +TXTEST=${CMAKE_BUILD_DIR}/src/tests/qpid-txtest +QPIDD_BASE_ARGS="--load-module ${STORE_MODULE} -m ${BROKER_MANAGEMENT} --auth no --default-flow-stop-threshold 0 --default-flow-resume-threshold 0 --default-queue-limit 0 --store-dir ${BASE_DIR} --log-enable ${BROKER_LOG_LEVEL} --log-to-stderr no --log-to-stdout no" +TXTEST_INIT_STR="--init yes --transfer no --check no" +TXTEST_RUN_STR="--init no --transfer yes --check no" +TXTEST_CHK_STR="--init no --transfer no --check yes" +SUCCESS_MSG="All expected messages were retrieved." +TIMESTAMP_FORMAT="+%Y-%m-%d_%H:%M:%S" +ANSI_RED="\e[1;31m" +ANSI_NONE="\e[0m" +DEFAULT_EFP_DIR=2048k +DEFAULT_EFP_SIZE=2101248 +SIG_KILL=-9 +SIG_TERM=-15 + +# Creates a random number into the variable named in string $1 in the range [$2..$3] (both inclusive). +# $1: variable name as string to which random value is assigned +# $2: minimum inclusive range of random number +# $3: maximum inclusive range of random number +get_random() { + eval $1=`python -S -c "import random; print random.randint($2,$3)"` +} + +# Uses anon-uniform distribution to set a random message size. +# Most messages must be small (0 - 1k), but we need a few medium (10k) and large (100k) ones also. +# Sets message size into var ${MSG_SIZE} +set_message_size() { + local key=0 + get_random "key" 1 10 + if (( "${key}" == "10" )); then # 1 out of 10 - very large + get_random "MSG_SIZE" 100000 1000000 + FILE_SIZE_MULTIPLIER=3 + elif (( "${key}" >= "8" )); then # 2 out of 10 - large + get_random "MSG_SIZE" 10000 100000 + FILE_SIZE_MULTIPLIER=2 + elif (( "${key}" >= "6" )); then # 2 out of 10 - medium + get_random "MSG_SIZE" 1000 10000 + FILE_SIZE_MULTIPLIER=1 + else # 5 out of 10 - small + get_random "MSG_SIZE" 10 1000 + FILE_SIZE_MULTIPLIER=1 + fi +} + +# Start or restart broker +# $1: Log suffix: either "A" or "B". If "A", broker is started with truncation, otherwise broker is restarted with recovery. +# $2: Truncate flag - only used if Log suffix is "A": if true, then truncate store +# The PID of the broker is returned in ${QPIDD_PID} +start_broker() { + local truncate_val + local truncate_str + if [[ "$1" == "A" ]]; then + if [[ $2 == true ]]; then + truncate_val="yes" + truncate_str="(Store truncated)" + if [[ -e ${BASE_DIR}/qls/p001/efp/${DEFAULT_EFP_DIR} ]]; then + for f in ${BASE_DIR}/qls/p001/efp/${DEFAULT_EFP_DIR}/*; do + local filesize=`stat -c%s "${f}"` + if (( ${filesize} != ${DEFAULT_EFP_SIZE} )); then + rm ${f} + fi + done + fi + else + truncate_val="no" + fi + else + truncate_val="no" + fi + echo "${QPIDD} ${QPIDD_BASE_ARGS} --truncate ${truncate_val} --log-to-file ${RESULT_DIR}/qpidd.$1.log &" > ${RESULT_DIR}/qpidd.$1.cmd + ${QPIDD} ${QPIDD_BASE_ARGS} --truncate ${truncate_val} --log-to-file ${RESULT_DIR}/qpidd.$1.log & + QPIDD_PID=$! + echo "Broker PID=${QPIDD_PID} ${truncate_str}" | tee -a ${LOG_FILE} +} + +# Start or evaluate results of transaction test client +# $1: Log suffix flag: either "A" or "B". If "A", client is started in test mode, otherwise client evaluates recovery. +start_tx_test() { + local tx_test_params="--messages-per-tx ${MSGS_PER_TX} --tx-count 1000000 --total-messages ${TOT_MSGS} --size ${MSG_SIZE} --queues ${NUM_QUEUES}" + if [[ "$1" == "A" ]]; then + # Run in background + echo "${TXTEST##*/} parameters: ${tx_test_params}" | tee -a ${LOG_FILE} + echo "${TXTEST} ${tx_test_params} ${TXTEST_INIT_STR} &> ${RESULT_DIR}/txtest.$1.log" > ${RESULT_DIR}/txtest.$1.cmd + ${TXTEST} ${tx_test_params} ${TXTEST_INIT_STR} &> ${RESULT_DIR}/txtest.$1.log + echo "${TXTEST} ${tx_test_params} ${TXTEST_RUN_STR} &> ${RESULT_DIR}/txtest.$1.log &" >> ${RESULT_DIR}/txtest.$1.cmd + ${TXTEST} ${tx_test_params} ${TXTEST_RUN_STR} &> ${RESULT_DIR}/txtest.$1.log & + else + # Run in foreground + #echo "${TXTEST##*/} ${tx_test_params} ${TXTEST_CHK_STR}" | tee -a ${LOG_FILE} + echo "${TXTEST} ${tx_test_params} ${TXTEST_CHK_STR} &> ${RESULT_DIR}/txtest.$1.log" > ${RESULT_DIR}/txtest.$1.cmd + ${TXTEST} ${tx_test_params} ${TXTEST_CHK_STR} &> ${RESULT_DIR}/txtest.$1.log + fi +} + +# Search for the presence of core.* files, move them into the current result directory and run gdb against them. +# No params +process_core_files() { + ls core.* &> /dev/null + if (( "$?" == "0" )); then + for cf in core.*; do + gdb --batch --quiet -ex "thread apply all bt" -ex "quit" ${QPIDD} ${cf} &> ${RESULT_DIR}/${cf##*/}.gdb.txt + gdb --batch --quiet -ex "thread apply all bt full" -ex "quit" ${QPIDD} ${cf} &> ${RESULT_DIR}/${cf##*/}.gdb-full.txt + cat ${RESULT_DIR}/${cf##*/}.gdb.txt + mv ${cf} ${RESULT_DIR}/ + echo "Core file ${cf##*/} found and recovered" + done + fi +} + +# Kill a process quietly +# $1: Signal +# $2: PID +kill_process() { + kill ${1} ${2} &>> ${LOG_FILE} + wait ${2} &>> ${LOG_FILE} +} + +# Check that test can run: No other copy of qpidd running, enough disk space +check_ready_to_run() { + # Check no copy of qpidd is running + PID=`pgrep ${QPIDD_FN}` + if [[ "$?" == "0" ]]; then + echo "ERROR: qpidd running as pid ${PID}" + exit 1 + fi + # Check disk is < 90% full + local perc_full=`df -h ${HOME} | tail -1 | awk '{print substr($5,0, length($5)-1)}'` + if (( ${perc_full} >= ${MAX_DISK_PERC_USED} )); then + echo "ERROR: Disk is too close to full (${perc_full}%)" + exit 2 + fi +} + +ulimit -c unlimited # Allow core files to be created + +RESULT_BASE_DIR_SUFFIX=`date "${TIMESTAMP_FORMAT}"` +RESULT_BASE_DIR="${RESULT_BASE_DIR_PREFIX}.${RESULT_BASE_DIR_SUFFIX}" +LOG_FILE=${RESULT_BASE_DIR}/${LOG_FILE_NAME} +if [[ -n "${RESULT_BASE_DIR}" ]]; then + rm -rf ${RESULT_BASE_DIR} +fi + +mkdir -p ${RESULT_BASE_DIR} +for rn in `seq ${NUM_RUNS}`; do + # === Prepare result dir, check ready to run test, set run vars === + RESULT_DIR=${RESULT_BASE_DIR}/run_${rn} + mkdir -p ${RESULT_DIR} + check_ready_to_run + if (( (${rn} - 1) % ${TRUNCATE_INTERVAL} == 0 )) || [[ -n ${ERROR_FLAG} ]]; then + TRUNCATE_FLAG=true + else + TRUNCATE_FLAG=false + fi + set_message_size + get_random "MSGS_PER_TX" 1 20 + get_random "TOT_MSGS" 100 1000 + get_random "NUM_QUEUES" 2 15 + MIN_RUNTIME=$(( 20 * ${FILE_SIZE_MULTIPLIER} )) + MAX_RUNTIME=$(( 120 * ${FILE_SIZE_MULTIPLIER} )) + get_random "RUN_TIME" ${MIN_RUNTIME} ${MAX_RUNTIME} + RECOVER_TIME=$(( ${NUM_QUEUES} * ${RECOVER_TIME_PER_QUEUE} * ${FILE_SIZE_MULTIPLIER} )) + echo "Run ${rn} of ${NUM_RUNS} ==============" | tee -a ${LOG_FILE} + + # === PART A: Initial run of qpid-txtest === + start_broker "A" ${TRUNCATE_FLAG} + sleep ${RECOVER_TIME} # Need a way to test if broker has started here + start_tx_test "A" + echo "Running for ${RUN_TIME} secs..." | tee -a ${LOG_FILE} + sleep ${RUN_TIME} + kill_process ${SIG_KILL} ${QPIDD_PID} + sleep 2 + tar -czf ${RESULT_DIR}/qls_B.tar.gz ${RELATIVE_BASE_DIR}/qls + + # === PART B: Recovery and check === + start_broker "B" + echo "Recover time=${RECOVER_TIME} secs..." | tee -a ${LOG_FILE} + sleep ${RECOVER_TIME} # Need a way to test if broker has started here + start_tx_test "B" + sleep 1 + kill_process ${SIG_TERM} ${QPIDD_PID} + sleep 2 + PID=`pgrep ${QPIDD_FN}` + if [[ "$?" == "0" ]]; then + kill_process ${SIG_KILL} ${PID} + sleep 2 + fi + tar -czf ${RESULT_DIR}/qls_C.tar.gz ${RELATIVE_BASE_DIR}/qls + + # === Check for errors, cores and exceptions in logs === + grep -Hn "jexception" ${RESULT_DIR}/qpidd.A.log | tee -a ${LOG_FILE} + grep -Hn "jexception" ${RESULT_DIR}/qpidd.B.log | tee -a ${LOG_FILE} + grep "${SUCCESS_MSG}" ${RESULT_DIR}/txtest.B.log &> /dev/null + if [[ "$?" != "0" ]]; then + echo "ERROR in run ${rn}" >> ${LOG_FILE} + echo -e "${ANSI_RED}ERROR${ANSI_NONE} in run ${rn}" + ERROR_FLAG=true + else + unset ERROR_FLAG + fi + sleep 2 + process_core_files + echo | tee -a ${LOG_FILE} +done + |