Added --continue-on-error to mysqltest and mysql-test-run
This will contune the test case even if there was an error and makes it easier to run a test that contains many sub tests against one engine. (originally by Monty)
This commit is contained in:
parent
ddd3e261b2
commit
c17bace4f0
@ -33,7 +33,7 @@
|
|||||||
And many others
|
And many others
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define MTEST_VERSION "3.3"
|
#define MTEST_VERSION "3.4"
|
||||||
|
|
||||||
#include "client_priv.h"
|
#include "client_priv.h"
|
||||||
#include <mysql_version.h>
|
#include <mysql_version.h>
|
||||||
@ -78,6 +78,8 @@ static my_bool non_blocking_api_enabled= 0;
|
|||||||
#define MAX_DELIMITER_LENGTH 16
|
#define MAX_DELIMITER_LENGTH 16
|
||||||
#define DEFAULT_MAX_CONN 64
|
#define DEFAULT_MAX_CONN 64
|
||||||
|
|
||||||
|
#define DIE_BUFF_SIZE 8192
|
||||||
|
|
||||||
/* Flags controlling send and reap */
|
/* Flags controlling send and reap */
|
||||||
#define QUERY_SEND_FLAG 1
|
#define QUERY_SEND_FLAG 1
|
||||||
#define QUERY_REAP_FLAG 2
|
#define QUERY_REAP_FLAG 2
|
||||||
@ -106,6 +108,7 @@ static int opt_port= 0;
|
|||||||
static int opt_max_connect_retries;
|
static int opt_max_connect_retries;
|
||||||
static int opt_result_format_version;
|
static int opt_result_format_version;
|
||||||
static int opt_max_connections= DEFAULT_MAX_CONN;
|
static int opt_max_connections= DEFAULT_MAX_CONN;
|
||||||
|
static int error_count= 0;
|
||||||
static my_bool opt_compress= 0, silent= 0, verbose= 0;
|
static my_bool opt_compress= 0, silent= 0, verbose= 0;
|
||||||
static my_bool debug_info_flag= 0, debug_check_flag= 0;
|
static my_bool debug_info_flag= 0, debug_check_flag= 0;
|
||||||
static my_bool tty_password= 0;
|
static my_bool tty_password= 0;
|
||||||
@ -122,7 +125,7 @@ static my_bool disable_connect_log= 1;
|
|||||||
static my_bool disable_warnings= 0, disable_column_names= 0;
|
static my_bool disable_warnings= 0, disable_column_names= 0;
|
||||||
static my_bool prepare_warnings_enabled= 0;
|
static my_bool prepare_warnings_enabled= 0;
|
||||||
static my_bool disable_info= 1;
|
static my_bool disable_info= 1;
|
||||||
static my_bool abort_on_error= 1;
|
static my_bool abort_on_error= 1, opt_continue_on_error= 0;
|
||||||
static my_bool server_initialized= 0;
|
static my_bool server_initialized= 0;
|
||||||
static my_bool is_windows= 0;
|
static my_bool is_windows= 0;
|
||||||
static char **default_argv;
|
static char **default_argv;
|
||||||
@ -559,14 +562,15 @@ const char *from, int len);
|
|||||||
|
|
||||||
static void cleanup_and_exit(int exit_code) __attribute__((noreturn));
|
static void cleanup_and_exit(int exit_code) __attribute__((noreturn));
|
||||||
|
|
||||||
void die(const char *fmt, ...)
|
void really_die(const char *msg) __attribute__((noreturn));
|
||||||
ATTRIBUTE_FORMAT(printf, 1, 2) __attribute__((noreturn));
|
void report_or_die(const char *fmt, ...) ATTRIBUTE_FORMAT(printf, 1, 2);
|
||||||
void abort_not_supported_test(const char *fmt, ...)
|
void die(const char *fmt, ...) ATTRIBUTE_FORMAT(printf, 1, 2)
|
||||||
ATTRIBUTE_FORMAT(printf, 1, 2) __attribute__((noreturn));
|
__attribute__((noreturn));
|
||||||
void verbose_msg(const char *fmt, ...)
|
static void make_error_message(char *buf, size_t len, const char *fmt, va_list args);
|
||||||
ATTRIBUTE_FORMAT(printf, 1, 2);
|
void abort_not_supported_test(const char *fmt, ...) ATTRIBUTE_FORMAT(printf, 1, 2)
|
||||||
void log_msg(const char *fmt, ...)
|
__attribute__((noreturn));
|
||||||
ATTRIBUTE_FORMAT(printf, 1, 2);
|
void verbose_msg(const char *fmt, ...) ATTRIBUTE_FORMAT(printf, 1, 2);
|
||||||
|
void log_msg(const char *fmt, ...) ATTRIBUTE_FORMAT(printf, 1, 2);
|
||||||
|
|
||||||
VAR* var_from_env(const char *, const char *);
|
VAR* var_from_env(const char *, const char *);
|
||||||
VAR* var_init(VAR* v, const char *name, int name_len, const char *val,
|
VAR* var_init(VAR* v, const char *name, int name_len, const char *val,
|
||||||
@ -983,7 +987,10 @@ void do_eval(DYNAMIC_STRING *query_eval, const char *query,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!(v= var_get(p, &p, 0, 0)))
|
if (!(v= var_get(p, &p, 0, 0)))
|
||||||
die("Bad variable in eval");
|
{
|
||||||
|
report_or_die( "Bad variable in eval");
|
||||||
|
return;
|
||||||
|
}
|
||||||
dynstr_append_mem(query_eval, v->str_val, v->str_val_len);
|
dynstr_append_mem(query_eval, v->str_val, v->str_val_len);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -1270,9 +1277,13 @@ void handle_command_error(struct st_command *command, uint error,
|
|||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (command->abort_on_error)
|
if (command->abort_on_error)
|
||||||
die("command \"%.*s\" failed with error: %u my_errno: %d errno: %d",
|
{
|
||||||
|
report_or_die("command \"%.*s\" failed with error: %u my_errno: %d "
|
||||||
|
"errno: %d",
|
||||||
command->first_word_len, command->query, error, my_errno,
|
command->first_word_len, command->query, error, my_errno,
|
||||||
sys_errno);
|
sys_errno);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
i= match_expected_error(command, error, NULL);
|
i= match_expected_error(command, error, NULL);
|
||||||
|
|
||||||
@ -1285,14 +1296,17 @@ void handle_command_error(struct st_command *command, uint error,
|
|||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
if (command->expected_errors.count > 0)
|
if (command->expected_errors.count > 0)
|
||||||
die("command \"%.*s\" failed with wrong error: %u my_errno: %d errno: %d",
|
report_or_die("command \"%.*s\" failed with wrong error: %u "
|
||||||
command->first_word_len, command->query, error, my_errno, sys_errno);
|
"my_errno: %d errno: %d",
|
||||||
|
command->first_word_len, command->query, error, my_errno,
|
||||||
|
sys_errno);
|
||||||
}
|
}
|
||||||
else if (command->expected_errors.err[0].type == ERR_ERRNO &&
|
else if (command->expected_errors.err[0].type == ERR_ERRNO &&
|
||||||
command->expected_errors.err[0].code.errnum != 0)
|
command->expected_errors.err[0].code.errnum != 0)
|
||||||
{
|
{
|
||||||
/* Error code we wanted was != 0, i.e. not an expected success */
|
/* Error code we wanted was != 0, i.e. not an expected success */
|
||||||
die("command \"%.*s\" succeeded - should have failed with errno %d...",
|
report_or_die("command \"%.*s\" succeeded - should have failed with "
|
||||||
|
"errno %d...",
|
||||||
command->first_word_len, command->query,
|
command->first_word_len, command->query,
|
||||||
command->expected_errors.err[0].code.errnum);
|
command->expected_errors.err[0].code.errnum);
|
||||||
}
|
}
|
||||||
@ -1437,50 +1451,59 @@ static void cleanup_and_exit(int exit_code)
|
|||||||
exit(exit_code);
|
exit(exit_code);
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_file_stack()
|
size_t print_file_stack(char *s, const char *end)
|
||||||
{
|
{
|
||||||
|
char *start= s;
|
||||||
struct st_test_file* err_file= cur_file;
|
struct st_test_file* err_file= cur_file;
|
||||||
if (err_file == file_stack)
|
if (err_file == file_stack)
|
||||||
return;
|
return 0;
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
err_file--;
|
err_file--;
|
||||||
fprintf(stderr, "included from %s at line %d:\n",
|
s+= my_snprintf(s, end - s, "included from %s at line %d:\n",
|
||||||
err_file->file_name, err_file->lineno);
|
err_file->file_name, err_file->lineno);
|
||||||
if (err_file == file_stack)
|
if (err_file == file_stack)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
return s - start;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void make_error_message(char *buf, size_t len, const char *fmt, va_list args)
|
||||||
|
{
|
||||||
|
char *s= buf, *end= buf + len;
|
||||||
|
s+= my_snprintf(s, end - s, "mysqltest: ");
|
||||||
|
if (cur_file && cur_file != file_stack)
|
||||||
|
{
|
||||||
|
s+= my_snprintf(s, end - s, "In included file \"%s\": \n",
|
||||||
|
cur_file->file_name);
|
||||||
|
s+= print_file_stack(s, end);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (start_lineno > 0)
|
||||||
|
s+= my_snprintf(s, end -s, "At line %u: ", start_lineno);
|
||||||
|
if (!fmt)
|
||||||
|
fmt= "unknown error";
|
||||||
|
|
||||||
|
s+= my_vsnprintf(s, end - s, fmt, args);
|
||||||
|
s+= my_snprintf(s, end -s, "\n", start_lineno);
|
||||||
}
|
}
|
||||||
|
|
||||||
void die(const char *fmt, ...)
|
void die(const char *fmt, ...)
|
||||||
{
|
{
|
||||||
static int dying= 0;
|
char buff[DIE_BUFF_SIZE];
|
||||||
va_list args;
|
va_list args;
|
||||||
DBUG_ENTER("die");
|
|
||||||
DBUG_PRINT("enter", ("start_lineno: %d", start_lineno));
|
|
||||||
|
|
||||||
fflush(stdout);
|
|
||||||
/* Print the error message */
|
|
||||||
fprintf(stderr, "mysqltest: ");
|
|
||||||
if (cur_file && cur_file != file_stack)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "In included file \"%s\": \n",
|
|
||||||
cur_file->file_name);
|
|
||||||
print_file_stack();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (start_lineno > 0)
|
|
||||||
fprintf(stderr, "At line %u: ", start_lineno);
|
|
||||||
if (fmt)
|
|
||||||
{
|
|
||||||
va_start(args, fmt);
|
va_start(args, fmt);
|
||||||
vfprintf(stderr, fmt, args);
|
make_error_message(buff, sizeof(buff), fmt, args);
|
||||||
va_end(args);
|
really_die(buff);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
fprintf(stderr, "unknown error");
|
void really_die(const char *msg)
|
||||||
fprintf(stderr, "\n");
|
{
|
||||||
|
static int dying= 0;
|
||||||
|
fflush(stdout);
|
||||||
|
fprintf(stderr, "%s", msg);
|
||||||
fflush(stderr);
|
fflush(stderr);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1504,6 +1527,28 @@ void die(const char *fmt, ...)
|
|||||||
cleanup_and_exit(1);
|
cleanup_and_exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void report_or_die(const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
DBUG_ENTER("report_or_die");
|
||||||
|
|
||||||
|
char buff[DIE_BUFF_SIZE];
|
||||||
|
|
||||||
|
va_start(args, fmt);
|
||||||
|
make_error_message(buff, sizeof(buff), fmt, args);
|
||||||
|
va_end(args);
|
||||||
|
|
||||||
|
if (opt_continue_on_error)
|
||||||
|
{
|
||||||
|
/* Just log the error and continue */
|
||||||
|
replace_dynstr_append(&ds_res, buff);
|
||||||
|
error_count++;
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
|
}
|
||||||
|
|
||||||
|
really_die(buff);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void abort_not_supported_test(const char *fmt, ...)
|
void abort_not_supported_test(const char *fmt, ...)
|
||||||
{
|
{
|
||||||
@ -1516,7 +1561,10 @@ void abort_not_supported_test(const char *fmt, ...)
|
|||||||
file_stack->file_name);
|
file_stack->file_name);
|
||||||
fprintf(stderr, "Detected in file %s at line %d\n",
|
fprintf(stderr, "Detected in file %s at line %d\n",
|
||||||
cur_file->file_name, cur_file->lineno);
|
cur_file->file_name, cur_file->lineno);
|
||||||
print_file_stack();
|
|
||||||
|
char buff[DIE_BUFF_SIZE];
|
||||||
|
print_file_stack(buff, buff + sizeof(buff));
|
||||||
|
fprintf(stderr, "%s", buff);
|
||||||
|
|
||||||
/* Print error message */
|
/* Print error message */
|
||||||
va_start(args, fmt);
|
va_start(args, fmt);
|
||||||
@ -1648,7 +1696,10 @@ static int run_command(char* cmd,
|
|||||||
DBUG_PRINT("enter", ("cmd: %s", cmd));
|
DBUG_PRINT("enter", ("cmd: %s", cmd));
|
||||||
|
|
||||||
if (!(res_file= popen(cmd, "r")))
|
if (!(res_file= popen(cmd, "r")))
|
||||||
die("popen(\"%s\", \"r\") failed", cmd);
|
{
|
||||||
|
report_or_die("popen(\"%s\", \"r\") failed", cmd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
while (fgets(buf, sizeof(buf), res_file))
|
while (fgets(buf, sizeof(buf), res_file))
|
||||||
{
|
{
|
||||||
@ -1748,7 +1799,10 @@ static int diff_check(const char *diff_name)
|
|||||||
if (!(res_file= popen(buf, "r")))
|
if (!(res_file= popen(buf, "r")))
|
||||||
die("popen(\"%s\", \"r\") failed", buf);
|
die("popen(\"%s\", \"r\") failed", buf);
|
||||||
|
|
||||||
/* if diff is not present, nothing will be in stdout to increment have_diff */
|
/*
|
||||||
|
if diff is not present, nothing will be in stdout to increment
|
||||||
|
have_diff
|
||||||
|
*/
|
||||||
if (fgets(buf, sizeof(buf), res_file))
|
if (fgets(buf, sizeof(buf), res_file))
|
||||||
have_diff= 1;
|
have_diff= 1;
|
||||||
|
|
||||||
@ -2061,7 +2115,7 @@ int dyn_string_cmp(DYNAMIC_STRING* ds, const char *fname)
|
|||||||
|
|
||||||
void check_result()
|
void check_result()
|
||||||
{
|
{
|
||||||
const char* mess= "Result content mismatch\n";
|
const char *mess= 0;
|
||||||
|
|
||||||
DBUG_ENTER("check_result");
|
DBUG_ENTER("check_result");
|
||||||
DBUG_ASSERT(result_file_name);
|
DBUG_ASSERT(result_file_name);
|
||||||
@ -2069,8 +2123,12 @@ void check_result()
|
|||||||
|
|
||||||
switch (compare_files(log_file.file_name(), result_file_name)) {
|
switch (compare_files(log_file.file_name(), result_file_name)) {
|
||||||
case RESULT_OK:
|
case RESULT_OK:
|
||||||
|
if (!error_count)
|
||||||
break; /* ok */
|
break; /* ok */
|
||||||
|
mess= "Got errors while running test";
|
||||||
|
/* Fallthrough */
|
||||||
case RESULT_LENGTH_MISMATCH:
|
case RESULT_LENGTH_MISMATCH:
|
||||||
|
if (!mess)
|
||||||
mess= "Result length mismatch\n";
|
mess= "Result length mismatch\n";
|
||||||
/* Fallthrough */
|
/* Fallthrough */
|
||||||
case RESULT_CONTENT_MISMATCH:
|
case RESULT_CONTENT_MISMATCH:
|
||||||
@ -2081,6 +2139,10 @@ void check_result()
|
|||||||
*/
|
*/
|
||||||
char reject_file[FN_REFLEN];
|
char reject_file[FN_REFLEN];
|
||||||
size_t reject_length;
|
size_t reject_length;
|
||||||
|
|
||||||
|
if (!mess)
|
||||||
|
mess= "Result content mismatch\n";
|
||||||
|
|
||||||
dirname_part(reject_file, result_file_name, &reject_length);
|
dirname_part(reject_file, result_file_name, &reject_length);
|
||||||
|
|
||||||
if (access(reject_file, W_OK) == 0)
|
if (access(reject_file, W_OK) == 0)
|
||||||
@ -2527,7 +2589,12 @@ void var_query_set(VAR *var, const char *query, const char** query_end)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!(res= mysql_store_result(mysql)))
|
if (!(res= mysql_store_result(mysql)))
|
||||||
die("Query '%s' didn't return a result set", ds_query.str);
|
{
|
||||||
|
report_or_die("Query '%s' didn't return a result set", ds_query.str);
|
||||||
|
dynstr_free(&ds_query);
|
||||||
|
eval_expr(var, "", 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
dynstr_free(&ds_query);
|
dynstr_free(&ds_query);
|
||||||
|
|
||||||
if ((row= mysql_fetch_row(res)) && row[0])
|
if ((row= mysql_fetch_row(res)) && row[0])
|
||||||
@ -2700,12 +2767,19 @@ void var_set_query_get_value(struct st_command *command, VAR *var)
|
|||||||
mysql_sqlstate(mysql), &ds_res);
|
mysql_sqlstate(mysql), &ds_res);
|
||||||
/* If error was acceptable, return empty string */
|
/* If error was acceptable, return empty string */
|
||||||
dynstr_free(&ds_query);
|
dynstr_free(&ds_query);
|
||||||
|
dynstr_free(&ds_col);
|
||||||
eval_expr(var, "", 0);
|
eval_expr(var, "", 0);
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(res= mysql_store_result(mysql)))
|
if (!(res= mysql_store_result(mysql)))
|
||||||
die("Query '%s' didn't return a result set", ds_query.str);
|
{
|
||||||
|
report_or_die("Query '%s' didn't return a result set", ds_query.str);
|
||||||
|
dynstr_free(&ds_query);
|
||||||
|
dynstr_free(&ds_col);
|
||||||
|
eval_expr(var, "", 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
/* Find column number from the given column name */
|
/* Find column number from the given column name */
|
||||||
@ -2725,8 +2799,11 @@ void var_set_query_get_value(struct st_command *command, VAR *var)
|
|||||||
if (col_no == -1)
|
if (col_no == -1)
|
||||||
{
|
{
|
||||||
mysql_free_result(res);
|
mysql_free_result(res);
|
||||||
die("Could not find column '%s' in the result of '%s'",
|
report_or_die("Could not find column '%s' in the result of '%s'",
|
||||||
ds_col.str, ds_query.str);
|
ds_col.str, ds_query.str);
|
||||||
|
dynstr_free(&ds_query);
|
||||||
|
dynstr_free(&ds_col);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
DBUG_PRINT("info", ("Found column %d with name '%s'",
|
DBUG_PRINT("info", ("Found column %d with name '%s'",
|
||||||
i, fields[i].name));
|
i, fields[i].name));
|
||||||
@ -3165,7 +3242,10 @@ void do_exec(struct st_command *command)
|
|||||||
while (*cmd && my_isspace(charset_info, *cmd))
|
while (*cmd && my_isspace(charset_info, *cmd))
|
||||||
cmd++;
|
cmd++;
|
||||||
if (!*cmd)
|
if (!*cmd)
|
||||||
die("Missing argument in exec");
|
{
|
||||||
|
report_or_die("Missing argument in exec");
|
||||||
|
return;
|
||||||
|
}
|
||||||
command->last_argument= command->end;
|
command->last_argument= command->end;
|
||||||
|
|
||||||
init_dynamic_string(&ds_cmd, 0, command->query_len+256, 256);
|
init_dynamic_string(&ds_cmd, 0, command->query_len+256, 256);
|
||||||
@ -3197,10 +3277,12 @@ void do_exec(struct st_command *command)
|
|||||||
DBUG_PRINT("info", ("Executing '%s' as '%s'",
|
DBUG_PRINT("info", ("Executing '%s' as '%s'",
|
||||||
command->first_argument, ds_cmd.str));
|
command->first_argument, ds_cmd.str));
|
||||||
|
|
||||||
if (!(res_file= my_popen(&ds_cmd, "r")) && command->abort_on_error)
|
if (!(res_file= my_popen(&ds_cmd, "r")))
|
||||||
{
|
{
|
||||||
dynstr_free(&ds_cmd);
|
dynstr_free(&ds_cmd);
|
||||||
die("popen(\"%s\", \"r\") failed", command->first_argument);
|
if (command->abort_on_error)
|
||||||
|
report_or_die("popen(\"%s\", \"r\") failed", command->first_argument);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ds_result= &ds_res;
|
ds_result= &ds_res;
|
||||||
@ -3237,11 +3319,12 @@ void do_exec(struct st_command *command)
|
|||||||
|
|
||||||
if (command->abort_on_error)
|
if (command->abort_on_error)
|
||||||
{
|
{
|
||||||
log_msg("exec of '%s' failed, error: %d, status: %d, errno: %d",
|
report_or_die("exec of '%s' failed, error: %d, status: %d, errno: %d\n"
|
||||||
ds_cmd.str, error, status, errno);
|
"Output from before failure:\n%s\n",
|
||||||
|
ds_cmd.str, error, status, errno,
|
||||||
|
ds_res.str);
|
||||||
dynstr_free(&ds_cmd);
|
dynstr_free(&ds_cmd);
|
||||||
die("command \"%s\" failed\n\nOutput from before failure:\n%s\n",
|
return;
|
||||||
command->first_argument, ds_res.str);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DBUG_PRINT("info",
|
DBUG_PRINT("info",
|
||||||
@ -3256,7 +3339,7 @@ void do_exec(struct st_command *command)
|
|||||||
{
|
{
|
||||||
dynstr_free(&ds_cmd);
|
dynstr_free(&ds_cmd);
|
||||||
if (command->expected_errors.count > 0)
|
if (command->expected_errors.count > 0)
|
||||||
die("command \"%s\" failed with wrong error: %d",
|
report_or_die("command \"%s\" failed with wrong error: %d",
|
||||||
command->first_argument, status);
|
command->first_argument, status);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3267,8 +3350,10 @@ void do_exec(struct st_command *command)
|
|||||||
log_msg("exec of '%s failed, error: %d, errno: %d",
|
log_msg("exec of '%s failed, error: %d, errno: %d",
|
||||||
ds_cmd.str, error, errno);
|
ds_cmd.str, error, errno);
|
||||||
dynstr_free(&ds_cmd);
|
dynstr_free(&ds_cmd);
|
||||||
die("command \"%s\" succeeded - should have failed with errno %d...",
|
report_or_die("command \"%s\" succeeded - should have failed with "
|
||||||
command->first_argument, command->expected_errors.err[0].code.errnum);
|
"errno %d...",
|
||||||
|
command->first_argument,
|
||||||
|
command->expected_errors.err[0].code.errnum);
|
||||||
}
|
}
|
||||||
|
|
||||||
dynstr_free(&ds_cmd);
|
dynstr_free(&ds_cmd);
|
||||||
@ -3302,7 +3387,8 @@ int do_modify_var(struct st_command *command,
|
|||||||
const char *p= command->first_argument;
|
const char *p= command->first_argument;
|
||||||
VAR* v;
|
VAR* v;
|
||||||
if (!*p)
|
if (!*p)
|
||||||
die("Missing argument to %.*s", command->first_word_len, command->query);
|
die("Missing argument to %.*s", command->first_word_len,
|
||||||
|
command->query);
|
||||||
if (*p != '$')
|
if (*p != '$')
|
||||||
die("The argument to %.*s must be a variable (start with $)",
|
die("The argument to %.*s must be a variable (start with $)",
|
||||||
command->first_word_len, command->query);
|
command->first_word_len, command->query);
|
||||||
@ -3368,7 +3454,10 @@ void do_system(struct st_command *command)
|
|||||||
DBUG_ENTER("do_system");
|
DBUG_ENTER("do_system");
|
||||||
|
|
||||||
if (strlen(command->first_argument) == 0)
|
if (strlen(command->first_argument) == 0)
|
||||||
die("Missing arguments to system, nothing to do!");
|
{
|
||||||
|
report_or_die("Missing arguments to system, nothing to do!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
init_dynamic_string(&ds_cmd, 0, command->query_len + 64, 256);
|
init_dynamic_string(&ds_cmd, 0, command->query_len + 64, 256);
|
||||||
|
|
||||||
@ -3389,13 +3478,15 @@ void do_system(struct st_command *command)
|
|||||||
if (my_system(&ds_cmd))
|
if (my_system(&ds_cmd))
|
||||||
{
|
{
|
||||||
if (command->abort_on_error)
|
if (command->abort_on_error)
|
||||||
die("system command '%s' failed", command->first_argument);
|
report_or_die("system command '%s' failed", command->first_argument);
|
||||||
|
else
|
||||||
|
{
|
||||||
/* If ! abort_on_error, log message and continue */
|
/* If ! abort_on_error, log message and continue */
|
||||||
dynstr_append(&ds_res, "system command '");
|
dynstr_append(&ds_res, "system command '");
|
||||||
replace_dynstr_append(&ds_res, command->first_argument);
|
replace_dynstr_append(&ds_res, command->first_argument);
|
||||||
dynstr_append(&ds_res, "' failed\n");
|
dynstr_append(&ds_res, "' failed\n");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
command->last_argument= command->end;
|
command->last_argument= command->end;
|
||||||
dynstr_free(&ds_cmd);
|
dynstr_free(&ds_cmd);
|
||||||
@ -3941,11 +4032,11 @@ void read_until_delimiter(DYNAMIC_STRING *ds,
|
|||||||
No characters except \n are allowed on
|
No characters except \n are allowed on
|
||||||
the same line as the command
|
the same line as the command
|
||||||
*/
|
*/
|
||||||
die("Trailing characters found after command");
|
report_or_die("Trailing characters found after command");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (feof(cur_file->file))
|
if (feof(cur_file->file))
|
||||||
die("End of file encountered before '%s' delimiter was found",
|
report_or_die("End of file encountered before '%s' delimiter was found",
|
||||||
ds_delimiter->str);
|
ds_delimiter->str);
|
||||||
|
|
||||||
if (match_delimiter(c, ds_delimiter->str, ds_delimiter->length))
|
if (match_delimiter(c, ds_delimiter->str, ds_delimiter->length))
|
||||||
@ -4350,8 +4441,13 @@ void do_perl(struct st_command *command)
|
|||||||
/* Format the "perl <filename>" command */
|
/* Format the "perl <filename>" command */
|
||||||
my_snprintf(buf, sizeof(buf), "perl %s", temp_file_path);
|
my_snprintf(buf, sizeof(buf), "perl %s", temp_file_path);
|
||||||
|
|
||||||
if (!(res_file= popen(buf, "r")) && command->abort_on_error)
|
if (!(res_file= popen(buf, "r")))
|
||||||
|
{
|
||||||
|
if (command->abort_on_error)
|
||||||
die("popen(\"%s\", \"r\") failed", buf);
|
die("popen(\"%s\", \"r\") failed", buf);
|
||||||
|
dynstr_free(&ds_delimiter);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
while (fgets(buf, sizeof(buf), res_file))
|
while (fgets(buf, sizeof(buf), res_file))
|
||||||
{
|
{
|
||||||
@ -4808,7 +4904,8 @@ int do_sleep(struct st_command *command, my_bool real_sleep)
|
|||||||
while (my_isspace(charset_info, *p))
|
while (my_isspace(charset_info, *p))
|
||||||
p++;
|
p++;
|
||||||
if (!*p)
|
if (!*p)
|
||||||
die("Missing argument to %.*s", command->first_word_len, command->query);
|
die("Missing argument to %.*s", command->first_word_len,
|
||||||
|
command->query);
|
||||||
sleep_start= p;
|
sleep_start= p;
|
||||||
/* Check that arg starts with a digit, not handled by my_strtod */
|
/* Check that arg starts with a digit, not handled by my_strtod */
|
||||||
if (!my_isdigit(charset_info, *sleep_start))
|
if (!my_isdigit(charset_info, *sleep_start))
|
||||||
@ -4880,16 +4977,21 @@ int query_get_string(MYSQL* mysql, const char* query,
|
|||||||
MYSQL_ROW row;
|
MYSQL_ROW row;
|
||||||
|
|
||||||
if (mysql_query(mysql, query))
|
if (mysql_query(mysql, query))
|
||||||
die("'%s' failed: %d %s", query,
|
{
|
||||||
|
report_or_die("'%s' failed: %d %s", query,
|
||||||
mysql_errno(mysql), mysql_error(mysql));
|
mysql_errno(mysql), mysql_error(mysql));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
if ((res= mysql_store_result(mysql)) == NULL)
|
if ((res= mysql_store_result(mysql)) == NULL)
|
||||||
die("Failed to store result: %d %s",
|
{
|
||||||
|
report_or_die("Failed to store result: %d %s",
|
||||||
mysql_errno(mysql), mysql_error(mysql));
|
mysql_errno(mysql), mysql_error(mysql));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
if ((row= mysql_fetch_row(res)) == NULL)
|
if ((row= mysql_fetch_row(res)) == NULL)
|
||||||
{
|
{
|
||||||
mysql_free_result(res);
|
mysql_free_result(res);
|
||||||
ds= 0;
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
init_dynamic_string(ds, (row[column] ? row[column] : "NULL"), ~0, 32);
|
init_dynamic_string(ds, (row[column] ? row[column] : "NULL"), ~0, 32);
|
||||||
@ -6675,6 +6777,12 @@ static struct my_option my_long_options[] =
|
|||||||
{"compress", 'C', "Use the compressed server/client protocol.",
|
{"compress", 'C', "Use the compressed server/client protocol.",
|
||||||
&opt_compress, &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0,
|
&opt_compress, &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0,
|
||||||
0, 0, 0},
|
0, 0, 0},
|
||||||
|
{"continue-on-error", 0,
|
||||||
|
"Continue test even if we got an error. "
|
||||||
|
"This is mostly useful when testing a storage engine to see what from a test file it can execute, "
|
||||||
|
"or to find all syntax errors in a newly created big test file",
|
||||||
|
&opt_continue_on_error, &opt_continue_on_error, 0,
|
||||||
|
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
|
||||||
{"cursor-protocol", 0, "Use cursors for prepared statements.",
|
{"cursor-protocol", 0, "Use cursors for prepared statements.",
|
||||||
&cursor_protocol, &cursor_protocol, 0,
|
&cursor_protocol, &cursor_protocol, 0,
|
||||||
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
|
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
|
||||||
@ -7006,7 +7114,8 @@ int parse_args(int argc, char **argv)
|
|||||||
{
|
{
|
||||||
/* Check that the result file exists */
|
/* Check that the result file exists */
|
||||||
if (result_file_name && access(result_file_name, F_OK) != 0)
|
if (result_file_name && access(result_file_name, F_OK) != 0)
|
||||||
die("The specified result file '%s' does not exist", result_file_name);
|
die("The specified result file '%s' does not exist",
|
||||||
|
result_file_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -7333,8 +7442,8 @@ void append_stmt_result(DYNAMIC_STRING *ds, MYSQL_STMT *stmt,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (error != MYSQL_NO_DATA)
|
if (error != MYSQL_NO_DATA)
|
||||||
die("mysql_fetch didn't end with MYSQL_NO_DATA from statement: error: %d",
|
die("mysql_fetch didn't end with MYSQL_NO_DATA from statement: "
|
||||||
error);
|
"error: %d", error);
|
||||||
if (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA)
|
if (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA)
|
||||||
die("mysql_fetch didn't end with MYSQL_NO_DATA from statement: %d %s",
|
die("mysql_fetch didn't end with MYSQL_NO_DATA from statement: %d %s",
|
||||||
mysql_stmt_errno(stmt), mysql_stmt_error(stmt));
|
mysql_stmt_errno(stmt), mysql_stmt_error(stmt));
|
||||||
@ -7666,7 +7775,8 @@ static int match_expected_error(struct st_command *command,
|
|||||||
NULL is quite likely, but not in conjunction with a SQL-state expect!
|
NULL is quite likely, but not in conjunction with a SQL-state expect!
|
||||||
*/
|
*/
|
||||||
if (unlikely(err_sqlstate == NULL))
|
if (unlikely(err_sqlstate == NULL))
|
||||||
die("expecting a SQL-state (%s) from query '%s' which cannot produce one...",
|
die("expecting a SQL-state (%s) from query '%s' which cannot "
|
||||||
|
"produce one...",
|
||||||
command->expected_errors.err[i].code.sqlstate, command->query);
|
command->expected_errors.err[i].code.sqlstate, command->query);
|
||||||
|
|
||||||
if (strncmp(command->expected_errors.err[i].code.sqlstate,
|
if (strncmp(command->expected_errors.err[i].code.sqlstate,
|
||||||
@ -7720,7 +7830,11 @@ void handle_error(struct st_command *command,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (command->abort_on_error)
|
if (command->abort_on_error)
|
||||||
die("query '%s' failed: %d: %s", command->query, err_errno, err_error);
|
{
|
||||||
|
report_or_die("query '%s' failed: %d: %s", command->query, err_errno,
|
||||||
|
err_error);
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
|
}
|
||||||
|
|
||||||
DBUG_PRINT("info", ("expected_errors.count: %d",
|
DBUG_PRINT("info", ("expected_errors.count: %d",
|
||||||
command->expected_errors.count));
|
command->expected_errors.count));
|
||||||
@ -7766,11 +7880,13 @@ void handle_error(struct st_command *command,
|
|||||||
if (command->expected_errors.count > 0)
|
if (command->expected_errors.count > 0)
|
||||||
{
|
{
|
||||||
if (command->expected_errors.err[0].type == ERR_ERRNO)
|
if (command->expected_errors.err[0].type == ERR_ERRNO)
|
||||||
die("query '%s' failed with wrong errno %d: '%s', instead of %d...",
|
report_or_die("query '%s' failed with wrong errno %d: '%s', instead of "
|
||||||
|
"%d...",
|
||||||
command->query, err_errno, err_error,
|
command->query, err_errno, err_error,
|
||||||
command->expected_errors.err[0].code.errnum);
|
command->expected_errors.err[0].code.errnum);
|
||||||
else
|
else
|
||||||
die("query '%s' failed with wrong sqlstate %s: '%s', instead of %s...",
|
report_or_die("query '%s' failed with wrong sqlstate %s: '%s', "
|
||||||
|
"instead of %s...",
|
||||||
command->query, err_sqlstate, err_error,
|
command->query, err_sqlstate, err_error,
|
||||||
command->expected_errors.err[0].code.sqlstate);
|
command->expected_errors.err[0].code.sqlstate);
|
||||||
}
|
}
|
||||||
@ -7799,15 +7915,17 @@ void handle_no_error(struct st_command *command)
|
|||||||
command->expected_errors.err[0].code.errnum != 0)
|
command->expected_errors.err[0].code.errnum != 0)
|
||||||
{
|
{
|
||||||
/* Error code we wanted was != 0, i.e. not an expected success */
|
/* Error code we wanted was != 0, i.e. not an expected success */
|
||||||
die("query '%s' succeeded - should have failed with errno %d...",
|
report_or_die("query '%s' succeeded - should have failed with errno %d...",
|
||||||
command->query, command->expected_errors.err[0].code.errnum);
|
command->query, command->expected_errors.err[0].code.errnum);
|
||||||
}
|
}
|
||||||
else if (command->expected_errors.err[0].type == ERR_SQLSTATE &&
|
else if (command->expected_errors.err[0].type == ERR_SQLSTATE &&
|
||||||
strcmp(command->expected_errors.err[0].code.sqlstate,"00000") != 0)
|
strcmp(command->expected_errors.err[0].code.sqlstate,"00000") != 0)
|
||||||
{
|
{
|
||||||
/* SQLSTATE we wanted was != "00000", i.e. not an expected success */
|
/* SQLSTATE we wanted was != "00000", i.e. not an expected success */
|
||||||
die("query '%s' succeeded - should have failed with sqlstate %s...",
|
report_or_die("query '%s' succeeded - should have failed with "
|
||||||
command->query, command->expected_errors.err[0].code.sqlstate);
|
"sqlstate %s...",
|
||||||
|
command->query,
|
||||||
|
command->expected_errors.err[0].code.sqlstate);
|
||||||
}
|
}
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
@ -8293,13 +8411,14 @@ void run_query(struct st_connection *cn, struct st_command *command, int flags)
|
|||||||
if (sp_created)
|
if (sp_created)
|
||||||
{
|
{
|
||||||
if (util_query(mysql, "DROP PROCEDURE mysqltest_tmp_sp "))
|
if (util_query(mysql, "DROP PROCEDURE mysqltest_tmp_sp "))
|
||||||
die("Failed to drop sp: %d: %s", mysql_errno(mysql), mysql_error(mysql));
|
report_or_die("Failed to drop sp: %d: %s", mysql_errno(mysql),
|
||||||
|
mysql_error(mysql));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (view_created)
|
if (view_created)
|
||||||
{
|
{
|
||||||
if (util_query(mysql, "DROP VIEW mysqltest_tmp_v "))
|
if (util_query(mysql, "DROP VIEW mysqltest_tmp_v "))
|
||||||
die("Failed to drop view: %d: %s",
|
report_or_die("Failed to drop view: %d: %s",
|
||||||
mysql_errno(mysql), mysql_error(mysql));
|
mysql_errno(mysql), mysql_error(mysql));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -8463,9 +8582,10 @@ void get_command_type(struct st_command* command)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* -- "comment" that didn't contain a mysqltest command */
|
/* -- "comment" that didn't contain a mysqltest command */
|
||||||
die("Found line beginning with -- that didn't contain "\
|
report_or_die("Found line beginning with -- that didn't contain " \
|
||||||
"a valid mysqltest command, check your syntax or " \
|
"a valid mysqltest command, check your syntax or " \
|
||||||
"use # if you intended to write a comment");
|
"use # if you intended to write a comment");
|
||||||
|
command->type= Q_COMMENT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -9190,7 +9310,7 @@ int main(int argc, char **argv)
|
|||||||
if (parsing_disabled == 0)
|
if (parsing_disabled == 0)
|
||||||
parsing_disabled= 1;
|
parsing_disabled= 1;
|
||||||
else
|
else
|
||||||
die("Parsing is already disabled");
|
report_or_die("Parsing is already disabled");
|
||||||
break;
|
break;
|
||||||
case Q_ENABLE_PARSING:
|
case Q_ENABLE_PARSING:
|
||||||
/*
|
/*
|
||||||
@ -9200,7 +9320,7 @@ int main(int argc, char **argv)
|
|||||||
if (parsing_disabled == 1)
|
if (parsing_disabled == 1)
|
||||||
parsing_disabled= 0;
|
parsing_disabled= 0;
|
||||||
else
|
else
|
||||||
die("Parsing is already enabled");
|
report_or_die("Parsing is already enabled");
|
||||||
break;
|
break;
|
||||||
case Q_DIE:
|
case Q_DIE:
|
||||||
/* Abort test with error code and error message */
|
/* Abort test with error code and error message */
|
||||||
@ -9404,7 +9524,8 @@ void do_get_replace_column(struct st_command *command)
|
|||||||
if (!(column_number= atoi(to)) || column_number > MAX_COLUMNS)
|
if (!(column_number= atoi(to)) || column_number > MAX_COLUMNS)
|
||||||
die("Wrong column number to replace_column in '%s'", command->query);
|
die("Wrong column number to replace_column in '%s'", command->query);
|
||||||
if (!*from)
|
if (!*from)
|
||||||
die("Wrong number of arguments to replace_column in '%s'", command->query);
|
die("Wrong number of arguments to replace_column in '%s'",
|
||||||
|
command->query);
|
||||||
to= get_string(&buff, &from, command);
|
to= get_string(&buff, &from, command);
|
||||||
my_free(replace_column[column_number-1]);
|
my_free(replace_column[column_number-1]);
|
||||||
replace_column[column_number-1]= my_strdup(to, MYF(MY_WME | MY_FAE));
|
replace_column[column_number-1]= my_strdup(to, MYF(MY_WME | MY_FAE));
|
||||||
|
@ -230,7 +230,7 @@ my %opts_extern;
|
|||||||
sub using_extern { return (keys %opts_extern > 0);};
|
sub using_extern { return (keys %opts_extern > 0);};
|
||||||
|
|
||||||
our $opt_fast= 0;
|
our $opt_fast= 0;
|
||||||
our $opt_force;
|
our $opt_force= 0;
|
||||||
our $opt_mem= $ENV{'MTR_MEM'};
|
our $opt_mem= $ENV{'MTR_MEM'};
|
||||||
our $opt_clean_vardir= $ENV{'MTR_CLEAN_VARDIR'};
|
our $opt_clean_vardir= $ENV{'MTR_CLEAN_VARDIR'};
|
||||||
|
|
||||||
@ -1136,7 +1136,7 @@ sub command_line_setup {
|
|||||||
'defaults-extra-file=s' => \&collect_option,
|
'defaults-extra-file=s' => \&collect_option,
|
||||||
|
|
||||||
# Control what test suites or cases to run
|
# Control what test suites or cases to run
|
||||||
'force' => \$opt_force,
|
'force+' => \$opt_force,
|
||||||
'with-ndbcluster-only' => \&collect_option,
|
'with-ndbcluster-only' => \&collect_option,
|
||||||
'include-ndbcluster' => \$opt_include_ndbcluster,
|
'include-ndbcluster' => \$opt_include_ndbcluster,
|
||||||
'skip-ndbcluster|skip-ndb' => \$opt_skip_ndbcluster,
|
'skip-ndbcluster|skip-ndb' => \$opt_skip_ndbcluster,
|
||||||
@ -5856,6 +5856,11 @@ sub start_mysqltest ($) {
|
|||||||
mtr_add_arg($args, "%s", $_) for @args_saved;
|
mtr_add_arg($args, "%s", $_) for @args_saved;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($opt_force > 1)
|
||||||
|
{
|
||||||
|
mtr_add_arg($args, "--continue-on-error");
|
||||||
|
}
|
||||||
|
|
||||||
my $suite = $tinfo->{suite};
|
my $suite = $tinfo->{suite};
|
||||||
if ($suite->{parent}) {
|
if ($suite->{parent}) {
|
||||||
mtr_add_arg($args, "--overlay-dir=%s/", $suite->{dir});
|
mtr_add_arg($args, "--overlay-dir=%s/", $suite->{dir});
|
||||||
@ -6285,7 +6290,11 @@ Options to control directories to use
|
|||||||
|
|
||||||
Options to control what test suites or cases to run
|
Options to control what test suites or cases to run
|
||||||
|
|
||||||
force Continue to run the suite after failure
|
force Continue after a failure. When specified once, a
|
||||||
|
failure in a test file will abort this test file, and
|
||||||
|
the execution will continue from the next test file.
|
||||||
|
When specified twice, execution will continue executing
|
||||||
|
the failed test file from the next command.
|
||||||
with-ndbcluster-only Run only tests that include "ndb" in the filename
|
with-ndbcluster-only Run only tests that include "ndb" in the filename
|
||||||
skip-ndb[cluster] Skip all tests that need cluster. Default.
|
skip-ndb[cluster] Skip all tests that need cluster. Default.
|
||||||
include-ndb[cluster] Enable all tests that need cluster
|
include-ndb[cluster] Enable all tests that need cluster
|
||||||
|
7
mysql-test/r/mysqltest_cont_on_error.result
Normal file
7
mysql-test/r/mysqltest_cont_on_error.result
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
select error;
|
||||||
|
mysqltest: At line 1: query 'select error' failed: 1054: Unknown column 'error' in 'field list'
|
||||||
|
SELECT ERROR;
|
||||||
|
mysqltest: At line 1: query 'SELECT ERROR' failed: 1054: Unknown column 'ERROR' in 'field list'
|
||||||
|
SELECT 2;
|
||||||
|
2
|
||||||
|
2
|
16
mysql-test/t/mysqltest_cont_on_error.test
Normal file
16
mysql-test/t/mysqltest_cont_on_error.test
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#
|
||||||
|
# mysqltest --continue-on-error
|
||||||
|
#
|
||||||
|
|
||||||
|
-- source include/not_embedded.inc
|
||||||
|
|
||||||
|
#
|
||||||
|
# with or without --continue-on-error the failing test should return an error
|
||||||
|
# but with --continue-on-error, the failing line does not abort the test
|
||||||
|
#
|
||||||
|
|
||||||
|
--error 1
|
||||||
|
--exec echo "select error; select 1;" | $MYSQL_TEST 2>&1
|
||||||
|
|
||||||
|
--exec echo "SELECT ERROR; SELECT 2;" | $MYSQL_TEST --continue-on-error 2>&1
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user