Commit 27e85842 authored by Magnus Svensson's avatar Magnus Svensson

Bug #38181 Please print more debug info when tests fail

parent 106e64a6
...@@ -32,8 +32,8 @@ INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include ...@@ -32,8 +32,8 @@ INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include
ADD_EXECUTABLE(mysql completion_hash.cc mysql.cc readline.cc sql_string.cc ../mysys/my_conio.c) ADD_EXECUTABLE(mysql completion_hash.cc mysql.cc readline.cc sql_string.cc ../mysys/my_conio.c)
TARGET_LINK_LIBRARIES(mysql mysqlclient_notls wsock32) TARGET_LINK_LIBRARIES(mysql mysqlclient_notls wsock32)
ADD_EXECUTABLE(mysqltest mysqltest.c) ADD_EXECUTABLE(mysqltest mysqltest.cc)
SET_SOURCE_FILES_PROPERTIES(mysqltest.c PROPERTIES COMPILE_FLAGS "-DTHREADS") SET_SOURCE_FILES_PROPERTIES(mysqltest.cc PROPERTIES COMPILE_FLAGS "-DTHREADS")
TARGET_LINK_LIBRARIES(mysqltest mysqlclient mysys regex wsock32 dbug) TARGET_LINK_LIBRARIES(mysqltest mysqlclient mysys regex wsock32 dbug)
ADD_EXECUTABLE(mysqlcheck mysqlcheck.c) ADD_EXECUTABLE(mysqlcheck mysqlcheck.c)
......
...@@ -86,8 +86,8 @@ mysqlslap_LDADD = $(CXXLDFLAGS) $(CLIENT_THREAD_LIBS) \ ...@@ -86,8 +86,8 @@ mysqlslap_LDADD = $(CXXLDFLAGS) $(CLIENT_THREAD_LIBS) \
$(LIBMYSQLCLIENT_LA) \ $(LIBMYSQLCLIENT_LA) \
$(top_builddir)/mysys/libmysys.a $(top_builddir)/mysys/libmysys.a
mysqltest_SOURCES= mysqltest.c mysqltest_SOURCES= mysqltest.cc
mysqltest_CFLAGS= -DTHREAD -UUNDEF_THREADS_HACK mysqltest_CXXFLAGS= -DTHREAD -UUNDEF_THREADS_HACK
mysqltest_LDADD = $(CXXLDFLAGS) $(CLIENT_THREAD_LIBS) \ mysqltest_LDADD = $(CXXLDFLAGS) $(CLIENT_THREAD_LIBS) \
@CLIENT_EXTRA_LDFLAGS@ \ @CLIENT_EXTRA_LDFLAGS@ \
$(LIBMYSQLCLIENT_LA) \ $(LIBMYSQLCLIENT_LA) \
......
...@@ -169,7 +169,6 @@ static ulonglong timer_start; ...@@ -169,7 +169,6 @@ static ulonglong timer_start;
static void timer_output(void); static void timer_output(void);
static ulonglong timer_now(void); static ulonglong timer_now(void);
static ulonglong progress_start= 0;
/* Precompiled re's */ /* Precompiled re's */
static my_regex_t ps_re; /* the query can be run using PS protocol */ static my_regex_t ps_re; /* the query can be run using PS protocol */
...@@ -184,12 +183,12 @@ DYNAMIC_ARRAY q_lines; ...@@ -184,12 +183,12 @@ DYNAMIC_ARRAY q_lines;
#include "sslopt-vars.h" #include "sslopt-vars.h"
struct struct Parser
{ {
int read_lines,current_line; int read_lines,current_line;
} parser; } parser;
struct struct MasterPos
{ {
char file[FN_REFLEN]; char file[FN_REFLEN];
ulong pos; ulong pos;
...@@ -198,7 +197,7 @@ struct ...@@ -198,7 +197,7 @@ struct
/* if set, all results are concated and compared against this file */ /* if set, all results are concated and compared against this file */
const char *result_file_name= 0; const char *result_file_name= 0;
typedef struct st_var typedef struct
{ {
char *name; char *name;
int name_len; int name_len;
...@@ -420,7 +419,7 @@ struct st_command ...@@ -420,7 +419,7 @@ struct st_command
TYPELIB command_typelib= {array_elements(command_names),"", TYPELIB command_typelib= {array_elements(command_names),"",
command_names, 0}; command_names, 0};
DYNAMIC_STRING ds_res, ds_progress, ds_warning_messages; DYNAMIC_STRING ds_res;
char builtin_echo[FN_REFLEN]; char builtin_echo[FN_REFLEN];
...@@ -430,8 +429,6 @@ void abort_not_supported_test(const char *fmt, ...) ...@@ -430,8 +429,6 @@ void abort_not_supported_test(const char *fmt, ...)
ATTRIBUTE_FORMAT(printf, 1, 2); ATTRIBUTE_FORMAT(printf, 1, 2);
void verbose_msg(const char *fmt, ...) void verbose_msg(const char *fmt, ...)
ATTRIBUTE_FORMAT(printf, 1, 2); ATTRIBUTE_FORMAT(printf, 1, 2);
void warning_msg(const char *fmt, ...)
ATTRIBUTE_FORMAT(printf, 1, 2);
void log_msg(const char *fmt, ...) void log_msg(const char *fmt, ...)
ATTRIBUTE_FORMAT(printf, 1, 2); ATTRIBUTE_FORMAT(printf, 1, 2);
...@@ -444,9 +441,7 @@ VAR* var_get(const char *var_name, const char** var_name_end, ...@@ -444,9 +441,7 @@ VAR* var_get(const char *var_name, const char** var_name_end,
void eval_expr(VAR* v, const char *p, const char** p_end); void eval_expr(VAR* v, const char *p, const char** p_end);
my_bool match_delimiter(int c, const char *delim, uint length); my_bool match_delimiter(int c, const char *delim, uint length);
void dump_result_to_reject_file(char *buf, int size); void dump_result_to_reject_file(char *buf, int size);
void dump_result_to_log_file(char *buf, int size);
void dump_warning_messages(); void dump_warning_messages();
void dump_progress();
void do_eval(DYNAMIC_STRING *query_eval, const char *query, void do_eval(DYNAMIC_STRING *query_eval, const char *query,
const char *query_end, my_bool pass_through_escape_chars); const char *query_end, my_bool pass_through_escape_chars);
...@@ -483,6 +478,169 @@ void free_all_replace(){ ...@@ -483,6 +478,169 @@ void free_all_replace(){
} }
class LogFile {
FILE* m_file;
char m_file_name[FN_REFLEN];
uint m_bytes_written;
public:
LogFile() : m_file(NULL), m_bytes_written(0) {
bzero(m_file_name, sizeof(m_file_name));
}
~LogFile() {
close();
}
const char* file_name() const { return m_file_name; }
uint bytes_written() const { return m_bytes_written; }
void open(const char* dir, const char* name, const char* ext)
{
DBUG_ENTER("LogFile::open");
DBUG_PRINT("enter", ("dir: %s, name: %s",
name, dir));
if (!name)
{
m_file= stdout;
DBUG_VOID_RETURN;
}
fn_format(m_file_name, name, dir, ext,
*dir ? MY_REPLACE_DIR | MY_REPLACE_EXT :
MY_REPLACE_EXT);
DBUG_PRINT("info", ("file_name: %s", m_file_name));
if ((m_file= fopen(m_file_name, "w+")) == NULL)
die("Failed to open log file %s, errno: %d", m_file_name, errno);
DBUG_VOID_RETURN;
}
void close()
{
if (m_file && m_file != stdout)
fclose(m_file);
m_file= NULL;
}
void flush()
{
if (m_file && m_file != stdout)
fflush(m_file);
}
void write(DYNAMIC_STRING* ds)
{
DBUG_ENTER("LogFile::write");
DBUG_ASSERT(m_file);
if (ds->length == 0)
DBUG_VOID_RETURN;
DBUG_ASSERT(ds->str);
if (fwrite(ds->str, 1, ds->length, m_file) != ds->length)
die("Failed to write %d bytes to '%s', errno: %d",
ds->length, m_file_name, errno);
m_bytes_written+= ds->length;
DBUG_VOID_RETURN;
}
void show_tail(uint lines) {
DBUG_ENTER("LogFile::show_tail");
if (!m_file || m_file == stdout)
DBUG_VOID_RETURN;
if (lines == 0)
DBUG_VOID_RETURN;
lines++;
int show_offset= 0;
char buf[256];
size_t bytes;
bool found_bof= false;
/* Search backward in file until "lines" newline has been found */
while (lines && !found_bof)
{
show_offset-= sizeof(buf);
while(fseek(m_file, show_offset, SEEK_END) != 0 && show_offset < 0)
{
found_bof= true;
// Seeking before start of file
show_offset++;
}
if ((bytes= fread(buf, 1, sizeof(buf), m_file)) <= 0)
{
fprintf(stderr, "Failed to read from '%s', errno: %d\n",
m_file_name, errno);
DBUG_VOID_RETURN;
}
DBUG_PRINT("info", ("Read %d bytes from file, buf: %s", bytes, buf));
char* show_from= buf + bytes;
while(show_from > buf && lines > 0 )
{
show_from--;
if (*show_from == '\n')
lines--;
}
if (show_from != buf)
{
// The last new line was found in this buf, adjust offset
show_offset+= (show_from - buf) + 1;
DBUG_PRINT("info", ("adjusted offset to %d", show_offset));
}
DBUG_PRINT("info", ("show_offset: %d", show_offset));
}
fprintf(stderr, "\nThe result from queries just before the failure was:\n");
DBUG_PRINT("info", ("show_offset: %d", show_offset));
if (!lines)
{
fprintf(stderr, "< snip >\n");
if (fseek(m_file, show_offset, SEEK_END) != 0)
{
fprintf(stderr, "Failed to seek to position %d in '%s', errno: %d",
show_offset, m_file_name, errno);
DBUG_VOID_RETURN;
}
}
else {
DBUG_PRINT("info", ("Showing the whole file"));
if (fseek(m_file, 0L, SEEK_SET) != 0)
{
fprintf(stderr, "Failed to seek to pos 0 in '%s', errno: %d",
m_file_name, errno);
DBUG_VOID_RETURN;
}
}
while ((bytes= fread(buf, 1, sizeof(buf), m_file)) > 0)
fwrite(buf, 1, bytes, stderr);
if (!lines)
{
fprintf(stderr,
"\nMore results from queries before failure can be found in %s\n",
m_file_name);
}
fflush(stderr);
DBUG_VOID_RETURN;
}
};
LogFile log_file;
LogFile progress_file;
/* Disable functions that only exist in MySQL 4.0 */ /* Disable functions that only exist in MySQL 4.0 */
#if MYSQL_VERSION_ID < 40000 #if MYSQL_VERSION_ID < 40000
void mysql_enable_rpl_parse(MYSQL* mysql __attribute__((unused))) {} void mysql_enable_rpl_parse(MYSQL* mysql __attribute__((unused))) {}
...@@ -627,7 +785,7 @@ void do_eval(DYNAMIC_STRING *query_eval, const char *query, ...@@ -627,7 +785,7 @@ void do_eval(DYNAMIC_STRING *query_eval, const char *query,
/* /*
Run query and dump the result to stdout in vertical format Run query and dump the result to stderr in vertical format
NOTE! This function should be safe to call when an error NOTE! This function should be safe to call when an error
has occured and thus any further errors will be ignored(although logged) has occured and thus any further errors will be ignored(although logged)
...@@ -963,8 +1121,6 @@ void free_used_memory() ...@@ -963,8 +1121,6 @@ void free_used_memory()
my_free(embedded_server_args[--embedded_server_arg_count],MYF(0)); my_free(embedded_server_args[--embedded_server_arg_count],MYF(0));
delete_dynamic(&q_lines); delete_dynamic(&q_lines);
dynstr_free(&ds_res); dynstr_free(&ds_res);
dynstr_free(&ds_progress);
dynstr_free(&ds_warning_messages);
free_all_replace(); free_all_replace();
my_free(opt_pass,MYF(MY_ALLOW_ZERO_PTR)); my_free(opt_pass,MYF(MY_ALLOW_ZERO_PTR));
free_defaults(default_argv); free_defaults(default_argv);
...@@ -1042,31 +1198,7 @@ void die(const char *fmt, ...) ...@@ -1042,31 +1198,7 @@ void die(const char *fmt, ...)
fprintf(stderr, "\n"); fprintf(stderr, "\n");
fflush(stderr); fflush(stderr);
/* Show results from queries just before failure */ log_file.show_tail(opt_tail_lines);
if (ds_res.length && opt_tail_lines)
{
int tail_lines= opt_tail_lines;
char* show_from= ds_res.str + ds_res.length - 1;
while(show_from > ds_res.str && tail_lines > 0 )
{
show_from--;
if (*show_from == '\n')
tail_lines--;
}
fprintf(stderr, "\nThe result from queries just before the failure was:\n");
if (show_from > ds_res.str)
fprintf(stderr, "< snip >");
fprintf(stderr, "%s", show_from);
fflush(stderr);
}
/* Dump the result that has been accumulated so far to .log file */
if (result_file_name && ds_res.length)
dump_result_to_log_file(ds_res.str, ds_res.length);
/* Dump warning messages */
if (result_file_name && ds_warning_messages.length)
dump_warning_messages();
/* /*
Help debugging by displaying any warnings that might have Help debugging by displaying any warnings that might have
...@@ -1140,41 +1272,6 @@ void verbose_msg(const char *fmt, ...) ...@@ -1140,41 +1272,6 @@ void verbose_msg(const char *fmt, ...)
} }
void warning_msg(const char *fmt, ...)
{
va_list args;
char buff[512];
size_t len;
DBUG_ENTER("warning_msg");
va_start(args, fmt);
dynstr_append(&ds_warning_messages, "mysqltest: ");
if (start_lineno != 0)
{
dynstr_append(&ds_warning_messages, "Warning detected ");
if (cur_file && cur_file != file_stack)
{
len= my_snprintf(buff, sizeof(buff), "in included file %s ",
cur_file->file_name);
dynstr_append_mem(&ds_warning_messages,
buff, len);
}
len= my_snprintf(buff, sizeof(buff), "at line %d: ",
start_lineno);
dynstr_append_mem(&ds_warning_messages,
buff, len);
}
len= my_vsnprintf(buff, sizeof(buff), fmt, args);
dynstr_append_mem(&ds_warning_messages, buff, len);
dynstr_append(&ds_warning_messages, "\n");
va_end(args);
DBUG_VOID_RETURN;
}
void log_msg(const char *fmt, ...) void log_msg(const char *fmt, ...)
{ {
va_list args; va_list args;
...@@ -1583,18 +1680,17 @@ int dyn_string_cmp(DYNAMIC_STRING* ds, const char *fname) ...@@ -1583,18 +1680,17 @@ int dyn_string_cmp(DYNAMIC_STRING* ds, const char *fname)
/* /*
Check the content of ds against result file Check the content of log against result file
SYNOPSIS SYNOPSIS
check_result check_result
ds - content to be checked
RETURN VALUES RETURN VALUES
error - the function will not return error - the function will not return
*/ */
void check_result(DYNAMIC_STRING* ds) void check_result()
{ {
const char* mess= "Result content mismatch\n"; const char* mess= "Result content mismatch\n";
...@@ -1602,10 +1698,7 @@ void check_result(DYNAMIC_STRING* ds) ...@@ -1602,10 +1698,7 @@ void check_result(DYNAMIC_STRING* ds)
DBUG_ASSERT(result_file_name); DBUG_ASSERT(result_file_name);
DBUG_PRINT("enter", ("result_file_name: %s", result_file_name)); DBUG_PRINT("enter", ("result_file_name: %s", result_file_name));
if (access(result_file_name, F_OK) != 0) switch (compare_files(log_file.file_name(), result_file_name)) {
die("The specified result file does not exist: '%s'", result_file_name);
switch (dyn_string_cmp(ds, result_file_name)) {
case RESULT_OK: case RESULT_OK:
break; /* ok */ break; /* ok */
case RESULT_LENGTH_MISMATCH: case RESULT_LENGTH_MISMATCH:
...@@ -1633,9 +1726,10 @@ void check_result(DYNAMIC_STRING* ds) ...@@ -1633,9 +1726,10 @@ void check_result(DYNAMIC_STRING* ds)
fn_format(reject_file, result_file_name, opt_logdir, fn_format(reject_file, result_file_name, opt_logdir,
".reject", MY_REPLACE_DIR | MY_REPLACE_EXT); ".reject", MY_REPLACE_DIR | MY_REPLACE_EXT);
} }
str_to_file(reject_file, ds->str, ds->length);
dynstr_set(ds, NULL); /* Don't create a .log file */ if (my_copy(log_file.file_name(), reject_file, MYF(0)) != 0)
die("Failed to copy '%s' to '%s', errno: %d",
log_file.file_name(), reject_file, errno);
show_diff(NULL, result_file_name, reject_file); show_diff(NULL, result_file_name, reject_file);
die(mess); die(mess);
...@@ -1749,7 +1843,7 @@ VAR *var_init(VAR *v, const char *name, int name_len, const char *val, ...@@ -1749,7 +1843,7 @@ VAR *var_init(VAR *v, const char *name, int name_len, const char *val,
tmp_var->name = (name) ? (char*) tmp_var + sizeof(*tmp_var) : 0; tmp_var->name = (name) ? (char*) tmp_var + sizeof(*tmp_var) : 0;
tmp_var->alloced = (v == 0); tmp_var->alloced = (v == 0);
if (!(tmp_var->str_val = my_malloc(val_alloc_len+1, MYF(MY_WME)))) if (!(tmp_var->str_val = (char*)my_malloc(val_alloc_len+1, MYF(MY_WME))))
die("Out of memory"); die("Out of memory");
memcpy(tmp_var->name, name, name_len); memcpy(tmp_var->name, name, name_len);
...@@ -2162,8 +2256,8 @@ void var_copy(VAR *dest, VAR *src) ...@@ -2162,8 +2256,8 @@ void var_copy(VAR *dest, VAR *src)
/* Alloc/realloc data for str_val in dest */ /* Alloc/realloc data for str_val in dest */
if (dest->alloced_len < src->alloced_len && if (dest->alloced_len < src->alloced_len &&
!(dest->str_val= dest->str_val !(dest->str_val= dest->str_val
? my_realloc(dest->str_val, src->alloced_len, MYF(MY_WME)) ? (char*)my_realloc(dest->str_val, src->alloced_len, MYF(MY_WME))
: my_malloc(src->alloced_len, MYF(MY_WME)))) : (char*)my_malloc(src->alloced_len, MYF(MY_WME))))
die("Out of memory"); die("Out of memory");
else else
dest->alloced_len= src->alloced_len; dest->alloced_len= src->alloced_len;
...@@ -2221,9 +2315,9 @@ void eval_expr(VAR *v, const char *p, const char **p_end) ...@@ -2221,9 +2315,9 @@ void eval_expr(VAR *v, const char *p, const char **p_end)
v->alloced_len = (new_val_len < MIN_VAR_ALLOC - 1) ? v->alloced_len = (new_val_len < MIN_VAR_ALLOC - 1) ?
MIN_VAR_ALLOC : new_val_len + 1; MIN_VAR_ALLOC : new_val_len + 1;
if (!(v->str_val = if (!(v->str_val =
v->str_val ? my_realloc(v->str_val, v->alloced_len+1, v->str_val ?
MYF(MY_WME)) : (char*)my_realloc(v->str_val, v->alloced_len+1, MYF(MY_WME)) :
my_malloc(v->alloced_len+1, MYF(MY_WME)))) (char*)my_malloc(v->alloced_len+1, MYF(MY_WME))))
die("Out of memory"); die("Out of memory");
} }
v->str_val_len = new_val_len; v->str_val_len = new_val_len;
...@@ -2559,7 +2653,7 @@ enum enum_operator ...@@ -2559,7 +2653,7 @@ enum enum_operator
SYNOPSIS SYNOPSIS
do_modify_var() do_modify_var()
query called command query called command
operator operation to perform on the var op operation to perform on the var
DESCRIPTION DESCRIPTION
dec $var_name dec $var_name
...@@ -2568,7 +2662,7 @@ enum enum_operator ...@@ -2568,7 +2662,7 @@ enum enum_operator
*/ */
int do_modify_var(struct st_command *command, int do_modify_var(struct st_command *command,
enum enum_operator operator) enum enum_operator op)
{ {
const char *p= command->first_argument; const char *p= command->first_argument;
VAR* v; VAR* v;
...@@ -2578,7 +2672,7 @@ int do_modify_var(struct st_command *command, ...@@ -2578,7 +2672,7 @@ int do_modify_var(struct st_command *command,
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);
v= var_get(p, &p, 1, 0); v= var_get(p, &p, 1, 0);
switch (operator) { switch (op) {
case DO_DEC: case DO_DEC:
v->int_val--; v->int_val--;
break; break;
...@@ -3398,24 +3492,19 @@ void do_wait_for_slave_to_stop(struct st_command *c __attribute__((unused))) ...@@ -3398,24 +3492,19 @@ void do_wait_for_slave_to_stop(struct st_command *c __attribute__((unused)))
} }
void do_sync_with_master2(long offset) void do_sync_with_master2(struct st_command *command, long offset)
{ {
MYSQL_RES *res; MYSQL_RES *res;
MYSQL_ROW row; MYSQL_ROW row;
MYSQL *mysql= &cur_con->mysql; MYSQL *mysql= &cur_con->mysql;
char query_buf[FN_REFLEN+128]; char query_buf[FN_REFLEN+128];
int tries= 0; int timeout= 300; /* seconds */
int rpl_parse;
if (!master_pos.file[0]) if (!master_pos.file[0])
die("Calling 'sync_with_master' without calling 'save_master_pos'"); die("Calling 'sync_with_master' without calling 'save_master_pos'");
rpl_parse= mysql_rpl_parse_enabled(mysql);
mysql_disable_rpl_parse(mysql);
sprintf(query_buf, "select master_pos_wait('%s', %ld)", master_pos.file,
master_pos.pos + offset);
wait_for_position: sprintf(query_buf, "select master_pos_wait('%s', %ld, %d)",
master_pos.file, master_pos.pos + offset, timeout);
if (mysql_query(mysql, query_buf)) if (mysql_query(mysql, query_buf))
die("failed in '%s': %d: %s", query_buf, mysql_errno(mysql), die("failed in '%s': %d: %s", query_buf, mysql_errno(mysql),
...@@ -3428,30 +3517,48 @@ void do_sync_with_master2(long offset) ...@@ -3428,30 +3517,48 @@ void do_sync_with_master2(long offset)
mysql_free_result(res); mysql_free_result(res);
die("empty result in %s", query_buf); die("empty result in %s", query_buf);
} }
if (!row[0])
{ int result= -99;
/* const char* result_str= row[0];
It may be that the slave SQL thread has not started yet, though START if (result_str)
SLAVE has been issued ? result= atoi(result_str);
*/
mysql_free_result(res); mysql_free_result(res);
if (tries++ == 30)
if (!result_str || result < 0)
{ {
/* master_pos_wait returned NULL or < 0 */
show_query(mysql, "SHOW MASTER STATUS"); show_query(mysql, "SHOW MASTER STATUS");
show_query(mysql, "SHOW SLAVE STATUS"); show_query(mysql, "SHOW SLAVE STATUS");
die("could not sync with master ('%s' returned NULL)", query_buf); show_query(mysql, "SHOW PROCESSLIST");
fprintf(stderr, "analyze: sync_with_master\n");
if (!result_str)
{
/*
master_pos_wait returned NULL. This indicates that
slave SQL thread is not started, the slave's master
information is not initialized, the arguments are
incorrect, or an error has occured
*/
die("%.*s failed: '%s' returned NULL "\
"indicating slave SQL thread failure",
command->first_word_len, command->query, query_buf);
} }
sleep(1); /* So at most we will wait 30 seconds and make 31 tries */
goto wait_for_position; if (result == -1)
die("%.*s failed: '%s' returned -1 "\
"indicating timeout after %d seconds",
command->first_word_len, command->query, query_buf, timeout);
else
die("%.*s failed: '%s' returned unknown result :%d",
command->first_word_len, command->query, query_buf, result);
} }
mysql_free_result(res);
if (rpl_parse)
mysql_enable_rpl_parse(mysql);
return; return;
} }
void do_sync_with_master(struct st_command *command) void do_sync_with_master(struct st_command *command)
{ {
long offset= 0; long offset= 0;
...@@ -3466,7 +3573,7 @@ void do_sync_with_master(struct st_command *command) ...@@ -3466,7 +3573,7 @@ void do_sync_with_master(struct st_command *command)
die("Invalid integer argument \"%s\"", offset_start); die("Invalid integer argument \"%s\"", offset_start);
command->last_argument= p; command->last_argument= p;
} }
do_sync_with_master2(offset); do_sync_with_master2(command, offset);
return; return;
} }
...@@ -3943,7 +4050,7 @@ void do_shutdown_server(struct st_command *command) ...@@ -3943,7 +4050,7 @@ void do_shutdown_server(struct st_command *command)
break; break;
} }
DBUG_PRINT("info", ("Sleeping, timeout: %d", timeout)); DBUG_PRINT("info", ("Sleeping, timeout: %d", timeout));
my_sleep(1); my_sleep(1000000L);
} }
/* Kill the server */ /* Kill the server */
...@@ -5081,55 +5188,6 @@ void convert_to_format_v1(char* query) ...@@ -5081,55 +5188,6 @@ void convert_to_format_v1(char* query)
} }
/*
Check a command that is about to be sent (or should have been
sent if parsing was enabled) to mysql server for
suspicious things and generate warnings.
*/
void scan_command_for_warnings(struct st_command *command)
{
const char *ptr= command->query;
DBUG_ENTER("scan_command_for_warnings");
DBUG_PRINT("enter", ("query: %s", command->query));
while(*ptr)
{
/*
Look for query's that lines that start with a -- comment
and has a mysqltest command
*/
if (ptr[0] == '\n' &&
ptr[1] && ptr[1] == '-' &&
ptr[2] && ptr[2] == '-' &&
ptr[3])
{
uint type;
char save;
char *end, *start= (char*)ptr+3;
/* Skip leading spaces */
while (*start && my_isspace(charset_info, *start))
start++;
end= start;
/* Find end of command(next space) */
while (*end && !my_isspace(charset_info, *end))
end++;
save= *end;
*end= 0;
DBUG_PRINT("info", ("Checking '%s'", start));
type= find_type(start, &command_typelib, 1+2);
if (type)
warning_msg("Embedded mysqltest command '--%s' detected in "
"query '%s' was this intentional? ",
start, command->query);
*end= save;
}
ptr++;
}
DBUG_VOID_RETURN;
}
/* /*
Check for unexpected "junk" after the end of query Check for unexpected "junk" after the end of query
This is normally caused by missing delimiters or when This is normally caused by missing delimiters or when
...@@ -5187,6 +5245,19 @@ void check_eol_junk(const char *eol) ...@@ -5187,6 +5245,19 @@ void check_eol_junk(const char *eol)
} }
bool is_delimiter(const char* p)
{
uint match= 0;
char* delim= delimiter;
while (*p && *p == *delim++)
{
match++;
p++;
}
return (match == delimiter_length);
}
/* /*
Create a command from a set of lines Create a command from a set of lines
...@@ -5253,9 +5324,11 @@ int read_command(struct st_command** command_ptr) ...@@ -5253,9 +5324,11 @@ int read_command(struct st_command** command_ptr)
if (!(command->query_buf= command->query= my_strdup(p, MYF(MY_WME)))) if (!(command->query_buf= command->query= my_strdup(p, MYF(MY_WME))))
die("Out of memory"); die("Out of memory");
/* Calculate first word length(the command), terminated by space or ( */ /*
Calculate first word length(the command), terminated
by 'space' , '(' or 'delimiter' */
p= command->query; p= command->query;
while (*p && !my_isspace(charset_info, *p) && *p != '(') while (*p && !my_isspace(charset_info, *p) && *p != '(' && !is_delimiter(p))
p++; p++;
command->first_word_len= (uint) (p - command->query); command->first_word_len= (uint) (p - command->query);
DBUG_PRINT("info", ("first_word: %.*s", DBUG_PRINT("info", ("first_word: %.*s",
...@@ -5520,6 +5593,11 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), ...@@ -5520,6 +5593,11 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
die("Can't use server argument"); die("Can't use server argument");
} }
break; break;
case OPT_LOG_DIR:
/* Check that the file exists */
if (access(opt_logdir, F_OK) != 0)
die("The specified log directory does not exist: '%s'", opt_logdir);
break;
case 'F': case 'F':
read_embedded_server_arguments(argument); read_embedded_server_arguments(argument);
break; break;
...@@ -5561,6 +5639,14 @@ int parse_args(int argc, char **argv) ...@@ -5561,6 +5639,14 @@ int parse_args(int argc, char **argv)
if (debug_check_flag) if (debug_check_flag)
my_end_arg= MY_CHECK_ERROR; my_end_arg= MY_CHECK_ERROR;
if (!record)
{
/* Check that the result file exists */
if (result_file_name && access(result_file_name, F_OK) != 0)
die("The specified result file '%s' does not exist", result_file_name);
}
return 0; return 0;
} }
...@@ -5615,37 +5701,6 @@ void str_to_file(const char *fname, char *str, int size) ...@@ -5615,37 +5701,6 @@ void str_to_file(const char *fname, char *str, int size)
} }
void dump_result_to_log_file(char *buf, int size)
{
char log_file[FN_REFLEN];
str_to_file(fn_format(log_file, result_file_name, opt_logdir, ".log",
*opt_logdir ? MY_REPLACE_DIR | MY_REPLACE_EXT :
MY_REPLACE_EXT),
buf, size);
fprintf(stderr, "\nMore results from queries before failure can be found in %s\n",
log_file);
}
void dump_progress(void)
{
char progress_file[FN_REFLEN];
str_to_file(fn_format(progress_file, result_file_name,
opt_logdir, ".progress",
*opt_logdir ? MY_REPLACE_DIR | MY_REPLACE_EXT :
MY_REPLACE_EXT),
ds_progress.str, ds_progress.length);
}
void dump_warning_messages(void)
{
char warn_file[FN_REFLEN];
str_to_file(fn_format(warn_file, result_file_name, opt_logdir, ".warnings",
*opt_logdir ? MY_REPLACE_DIR | MY_REPLACE_EXT :
MY_REPLACE_EXT),
ds_warning_messages.str, ds_warning_messages.length);
}
void check_regerr(my_regex_t* r, int err) void check_regerr(my_regex_t* r, int err)
{ {
char err_buf[1024]; char err_buf[1024];
...@@ -5890,7 +5945,7 @@ void append_stmt_result(DYNAMIC_STRING *ds, MYSQL_STMT *stmt, ...@@ -5890,7 +5945,7 @@ void append_stmt_result(DYNAMIC_STRING *ds, MYSQL_STMT *stmt,
{ {
uint max_length= fields[i].max_length + 1; uint max_length= fields[i].max_length + 1;
my_bind[i].buffer_type= MYSQL_TYPE_STRING; my_bind[i].buffer_type= MYSQL_TYPE_STRING;
my_bind[i].buffer= (char *)my_malloc(max_length, MYF(MY_WME | MY_FAE)); my_bind[i].buffer= my_malloc(max_length, MYF(MY_WME | MY_FAE));
my_bind[i].buffer_length= max_length; my_bind[i].buffer_length= max_length;
my_bind[i].is_null= &is_null[i]; my_bind[i].is_null= &is_null[i];
my_bind[i].length= &length[i]; my_bind[i].length= &length[i];
...@@ -5906,7 +5961,7 @@ void append_stmt_result(DYNAMIC_STRING *ds, MYSQL_STMT *stmt, ...@@ -5906,7 +5961,7 @@ void append_stmt_result(DYNAMIC_STRING *ds, MYSQL_STMT *stmt,
while (mysql_stmt_fetch(stmt) == 0) while (mysql_stmt_fetch(stmt) == 0)
{ {
for (i= 0; i < num_fields; i++) for (i= 0; i < num_fields; i++)
append_field(ds, i, &fields[i], my_bind[i].buffer, append_field(ds, i, &fields[i], (char*)my_bind[i].buffer,
*my_bind[i].length, *my_bind[i].is_null); *my_bind[i].length, *my_bind[i].is_null);
if (!display_result_vertically) if (!display_result_vertically)
dynstr_append_mem(ds, "\n", 1); dynstr_append_mem(ds, "\n", 1);
...@@ -6614,9 +6669,6 @@ void run_query(struct st_connection *cn, struct st_command *command, int flags) ...@@ -6614,9 +6669,6 @@ void run_query(struct st_connection *cn, struct st_command *command, int flags)
init_dynamic_string(&ds_warnings, NULL, 0, 256); init_dynamic_string(&ds_warnings, NULL, 0, 256);
/* Scan for warning before sending to server */
scan_command_for_warnings(command);
/* /*
Evaluate query if this is an eval command Evaluate query if this is an eval command
*/ */
...@@ -6946,28 +6998,10 @@ void get_command_type(struct st_command* command) ...@@ -6946,28 +6998,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 */
command->type= Q_COMMENT; die("Found line beginning with -- that didn't contain "\
warning_msg("Suspicious command '--%s' detected, was this intentional? "\ "a valid mysqltest command, check your syntax or "\
"Use # instead of -- to avoid this warning", "use # if you intended to write a comment");
command->query);
if (command->first_word_len &&
strcmp(command->query + command->first_word_len - 1, delimiter) == 0)
{
/*
Detect comment with command using extra delimiter
Ex --disable_query_log;
^ Extra delimiter causing the command
to be skipped
*/
save= command->query[command->first_word_len-1];
command->query[command->first_word_len-1]= 0;
if (find_type(command->query, &command_typelib, 1+2) > 0)
die("Extra delimiter \";\" found");
command->query[command->first_word_len-1]= save;
}
} }
} }
...@@ -6986,22 +7020,25 @@ void get_command_type(struct st_command* command) ...@@ -6986,22 +7020,25 @@ void get_command_type(struct st_command* command)
/* /*
Record how many milliseconds it took to execute the test file Record how many milliseconds it took to execute the test file
up until the current line and save it in the dynamic string ds_progress. up until the current line and write it to .progress file
The ds_progress will be dumped to <test_name>.progress when
test run completes
*/ */
void mark_progress(struct st_command* command __attribute__((unused)), void mark_progress(struct st_command* command __attribute__((unused)),
int line) int line)
{ {
static ulonglong progress_start= 0; // < Beware
DYNAMIC_STRING ds_progress;
char buf[32], *end; char buf[32], *end;
ulonglong timer= timer_now(); ulonglong timer= timer_now();
if (!progress_start) if (!progress_start)
progress_start= timer; progress_start= timer;
timer-= progress_start; timer-= progress_start;
if (init_dynamic_string(&ds_progress, "", 256, 256))
die("Out of memory");
/* Milliseconds since start */ /* Milliseconds since start */
end= longlong2str(timer, buf, 10); end= longlong2str(timer, buf, 10);
dynstr_append_mem(&ds_progress, buf, (int)(end-buf)); dynstr_append_mem(&ds_progress, buf, (int)(end-buf));
...@@ -7023,6 +7060,10 @@ void mark_progress(struct st_command* command __attribute__((unused)), ...@@ -7023,6 +7060,10 @@ void mark_progress(struct st_command* command __attribute__((unused)),
dynstr_append_mem(&ds_progress, "\n", 1); dynstr_append_mem(&ds_progress, "\n", 1);
progress_file.write(&ds_progress);
dynstr_free(&ds_progress);
} }
#ifdef HAVE_STACKTRACE #ifdef HAVE_STACKTRACE
...@@ -7130,7 +7171,6 @@ int main(int argc, char **argv) ...@@ -7130,7 +7171,6 @@ int main(int argc, char **argv)
my_bool q_send_flag= 0, abort_flag= 0; my_bool q_send_flag= 0, abort_flag= 0;
uint command_executed= 0, last_command_executed= 0; uint command_executed= 0, last_command_executed= 0;
char save_file[FN_REFLEN]; char save_file[FN_REFLEN];
MY_STAT res_info;
MY_INIT(argv[0]); MY_INIT(argv[0]);
save_file[0]= 0; save_file[0]= 0;
...@@ -7189,11 +7229,14 @@ int main(int argc, char **argv) ...@@ -7189,11 +7229,14 @@ int main(int argc, char **argv)
init_win_path_patterns(); init_win_path_patterns();
#endif #endif
init_dynamic_string(&ds_res, "", 65536, 65536); init_dynamic_string(&ds_res, "", 2048, 2048);
init_dynamic_string(&ds_progress, "", 0, 2048);
init_dynamic_string(&ds_warning_messages, "", 0, 2048);
parse_args(argc, argv); parse_args(argc, argv);
log_file.open(opt_logdir, result_file_name, ".log");
if (opt_mark_progress)
progress_file.open(opt_logdir, result_file_name, ".progress");
var_set_int("$PS_PROTOCOL", ps_protocol); var_set_int("$PS_PROTOCOL", ps_protocol);
var_set_int("$SP_PROTOCOL", sp_protocol); var_set_int("$SP_PROTOCOL", sp_protocol);
var_set_int("$VIEW_PROTOCOL", view_protocol); var_set_int("$VIEW_PROTOCOL", view_protocol);
...@@ -7282,8 +7325,8 @@ int main(int argc, char **argv) ...@@ -7282,8 +7325,8 @@ int main(int argc, char **argv)
command->type != Q_ENABLE_PARSING && command->type != Q_ENABLE_PARSING &&
command->type != Q_DISABLE_PARSING) command->type != Q_DISABLE_PARSING)
{ {
/* Parsing is disabled, silently convert this line to a comment */
command->type= Q_COMMENT; command->type= Q_COMMENT;
scan_command_for_warnings(command);
} }
if (cur_block->ok) if (cur_block->ok)
...@@ -7447,7 +7490,7 @@ int main(int argc, char **argv) ...@@ -7447,7 +7490,7 @@ int main(int argc, char **argv)
select_connection(command); select_connection(command);
else else
select_connection_name("slave"); select_connection_name("slave");
do_sync_with_master2(0); do_sync_with_master2(command, 0);
break; break;
} }
case Q_COMMENT: /* Ignore row */ case Q_COMMENT: /* Ignore row */
...@@ -7572,8 +7615,14 @@ int main(int argc, char **argv) ...@@ -7572,8 +7615,14 @@ int main(int argc, char **argv)
parser.current_line += current_line_inc; parser.current_line += current_line_inc;
if ( opt_mark_progress ) if ( opt_mark_progress )
mark_progress(command, parser.current_line); mark_progress(command, parser.current_line);
/* Write result from command to log file */
log_file.write(&ds_res);
dynstr_set(&ds_res, 0);
} }
log_file.close();
start_lineno= 0; start_lineno= 0;
if (parsing_disabled) if (parsing_disabled)
...@@ -7582,9 +7631,9 @@ int main(int argc, char **argv) ...@@ -7582,9 +7631,9 @@ int main(int argc, char **argv)
/* /*
The whole test has been executed _sucessfully_. The whole test has been executed _sucessfully_.
Time to compare result or save it to record file. Time to compare result or save it to record file.
The entire output from test is now kept in ds_res. The entire output from test is in the log file
*/ */
if (ds_res.length) if (log_file.bytes_written())
{ {
if (result_file_name) if (result_file_name)
{ {
...@@ -7592,22 +7641,29 @@ int main(int argc, char **argv) ...@@ -7592,22 +7641,29 @@ int main(int argc, char **argv)
if (record) if (record)
{ {
/* Recording - dump the output from test to result file */ /* Recording */
str_to_file(result_file_name, ds_res.str, ds_res.length);
/* save a copy of the log to result file */
if (my_copy(log_file.file_name(), result_file_name, MYF(0)) != 0)
die("Failed to copy '%s' to '%s', errno: %d",
log_file.file_name(), result_file_name, errno);
} }
else else
{ {
/* Check that the output from test is equal to result file /* Check that the output from test is equal to result file */
- detect missing result file check_result();
- detect zero size result file
*/
check_result(&ds_res);
} }
} }
else else
{ {
/* No result_file_name specified to compare with, print to stdout */ /*
printf("%s", ds_res.str); No result_file_name specified, the result
has been printed to stdout, exit with error
unless script has called "exit" to indicate success
*/
if (abort_flag == 0)
die("Exit with failure! Call 'exit' in script to return with sucess");
} }
} }
else else
...@@ -7615,25 +7671,8 @@ int main(int argc, char **argv) ...@@ -7615,25 +7671,8 @@ int main(int argc, char **argv)
die("The test didn't produce any output"); die("The test didn't produce any output");
} }
if (!command_executed && if (!command_executed && result_file_name)
result_file_name && my_stat(result_file_name, &res_info, 0))
{
/*
my_stat() successful on result file. Check if we have not run a
single query, but we do have a result file that contains data.
Note that we don't care, if my_stat() fails. For example, for a
non-existing or non-readable file, we assume it's fine to have
no query output from the test file, e.g. regarded as no error.
*/
die("No queries executed but result file found!"); die("No queries executed but result file found!");
}
if ( opt_mark_progress && result_file_name )
dump_progress();
/* Dump warning messages */
if (result_file_name && ds_warning_messages.length)
dump_warning_messages();
timer_output(); timer_output();
/* Yes, if we got this far the test has suceeded! Sakila smiles */ /* Yes, if we got this far the test has suceeded! Sakila smiles */
...@@ -7702,12 +7741,11 @@ void do_get_replace_column(struct st_command *command) ...@@ -7702,12 +7741,11 @@ void do_get_replace_column(struct st_command *command)
die("Missing argument in %s", command->query); die("Missing argument in %s", command->query);
/* Allocate a buffer for results */ /* Allocate a buffer for results */
start= buff= my_malloc(strlen(from)+1,MYF(MY_WME | MY_FAE)); start= buff= (char*)my_malloc(strlen(from)+1,MYF(MY_WME | MY_FAE));
while (*from) while (*from)
{ {
char *to; char *to;
uint column_number; uint column_number;
to= get_string(&buff, &from, command); to= get_string(&buff, &from, 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);
...@@ -7785,7 +7823,7 @@ void do_get_replace(struct st_command *command) ...@@ -7785,7 +7823,7 @@ void do_get_replace(struct st_command *command)
bzero((char*) &from_array,sizeof(from_array)); bzero((char*) &from_array,sizeof(from_array));
if (!*from) if (!*from)
die("Missing argument in %s", command->query); die("Missing argument in %s", command->query);
start= buff= my_malloc(strlen(from)+1,MYF(MY_WME | MY_FAE)); start= buff= (char*)my_malloc(strlen(from)+1,MYF(MY_WME | MY_FAE));
while (*from) while (*from)
{ {
char *to= buff; char *to= buff;
......
...@@ -32,7 +32,7 @@ ADD_EXECUTABLE(mysql_embedded ../../client/completion_hash.cc ...@@ -32,7 +32,7 @@ ADD_EXECUTABLE(mysql_embedded ../../client/completion_hash.cc
TARGET_LINK_LIBRARIES(mysql_embedded mysys yassl taocrypt zlib debug dbug regex strings wsock32) TARGET_LINK_LIBRARIES(mysql_embedded mysys yassl taocrypt zlib debug dbug regex strings wsock32)
ADD_DEPENDENCIES(mysql_embedded libmysqld) ADD_DEPENDENCIES(mysql_embedded libmysqld)
ADD_EXECUTABLE(mysqltest_embedded ../../client/mysqltest.c) ADD_EXECUTABLE(mysqltest_embedded ../../client/mysqltest.cc
TARGET_LINK_LIBRARIES(mysqltest_embedded mysys yassl taocrypt zlib debug dbug regex strings wsock32) TARGET_LINK_LIBRARIES(mysqltest_embedded mysys yassl taocrypt zlib debug dbug regex strings wsock32)
ADD_DEPENDENCIES(mysqltest_embedded libmysqld) ADD_DEPENDENCIES(mysqltest_embedded libmysqld)
......
...@@ -41,7 +41,7 @@ LDADD = @CLIENT_EXTRA_LDFLAGS@ ../libmysqld.a @LIBDL@ $(CXXLDFLAGS) \ ...@@ -41,7 +41,7 @@ LDADD = @CLIENT_EXTRA_LDFLAGS@ ../libmysqld.a @LIBDL@ $(CXXLDFLAGS) \
@NDB_SCI_LIBS@ @NDB_SCI_LIBS@
mysqltest_embedded_LINK = $(CXXLINK) mysqltest_embedded_LINK = $(CXXLINK)
nodist_mysqltest_embedded_SOURCES = mysqltest.c nodist_mysqltest_embedded_SOURCES = mysqltest.cc
mysqltest_embedded_LDADD = $(LDADD) $(top_builddir)/regex/libregex.a mysqltest_embedded_LDADD = $(LDADD) $(top_builddir)/regex/libregex.a
nodist_mysql_SOURCES = mysql.cc readline.cc completion_hash.cc \ nodist_mysql_SOURCES = mysql.cc readline.cc completion_hash.cc \
......
SHOW PROCESSLIST;
let $binlog_name= query_get_value("SHOW MASTER STATUS", File, 1);
eval SHOW BINLOG EVENTS IN '$binlog_name';
exit;
\ No newline at end of file
# Connect to both master and slave
connect (master,127.0.0.1,root,,test,$MASTER_MYPORT,);
connect (slave,127.0.0.1,root,,test,$SLAVE_MYPORT,);
vertical_results;
echo == MASTER ===========================================================;
connection master;
show master status;
show slave status;
echo == SLAVE ===========================================================;
connection slave;
show master status;
show slave status;
echo Output from mysqltest-x.inc; echo Output from mysqltest-x.inc;
exit;
...@@ -677,11 +677,15 @@ sub collect_one_test_case { ...@@ -677,11 +677,15 @@ sub collect_one_test_case {
name => "$suitename.$tname", name => "$suitename.$tname",
path => "$testdir/$filename", path => "$testdir/$filename",
# TODO allow nonexistsing result file );
my $result_file= "$resdir/$tname.result";
if (-f $result_file) {
# Allow nonexistsing result file
# in that case .test must issue "exit" otherwise test # in that case .test must issue "exit" otherwise test
# should fail by default # should fail by default
result_file => "$resdir/$tname.result", $tinfo->{result_file}= $result_file;
); }
# ---------------------------------------------------------------------- # ----------------------------------------------------------------------
# Skip some tests but include in list, just mark them as skipped # Skip some tests but include in list, just mark them as skipped
......
...@@ -103,17 +103,24 @@ sub mtr_report_test ($) { ...@@ -103,17 +103,24 @@ sub mtr_report_test ($) {
my ($tinfo)= @_; my ($tinfo)= @_;
_mtr_report_test_name($tinfo); _mtr_report_test_name($tinfo);
if ($tinfo->{'result'} eq 'MTR_RES_FAILED'){ my $comment= $tinfo->{'comment'};
my $logfile= $tinfo->{'logfile'};
my $warnings= $tinfo->{'warnings'};
my $result= $tinfo->{'result'};
if ( defined $tinfo->{'warnings'} ) if ($result eq 'MTR_RES_FAILED'){
if ( $warnings )
{ {
mtr_report("[ fail ] Found warnings in server log file!"); mtr_report("[ fail ] Found warnings in server log file!");
mtr_report($tinfo->{'warnings'}); mtr_report($warnings);
return; return;
} }
if ( defined $tinfo->{'timeout'} ) my $timeout= $tinfo->{'timeout'};
if ( $timeout )
{ {
mtr_report("[ fail ] timeout"); mtr_report("[ fail ] timeout after $timeout minutes");
mtr_report("\n$tinfo->{'comment'}");
return; return;
} }
else else
...@@ -121,43 +128,42 @@ sub mtr_report_test ($) { ...@@ -121,43 +128,42 @@ sub mtr_report_test ($) {
mtr_report("[ fail ]"); mtr_report("[ fail ]");
} }
if ( $tinfo->{'comment'} ) if ( $logfile )
{
# Test failure was detected by test tool and its report
# about what failed has been saved to file. Display the report.
mtr_report("\n$logfile\n");
}
if ( $comment )
{ {
# The test failure has been detected by mysql-test-run.pl # The test failure has been detected by mysql-test-run.pl
# when starting the servers or due to other error, the reason for # when starting the servers or due to other error, the reason for
# failing the test is saved in "comment" # failing the test is saved in "comment"
mtr_report("\nERROR: $tinfo->{'comment'}"); mtr_report("\n$comment\n");
} }
elsif ( $tinfo->{logfile} )
{
# Test failure was detected by test tool and its report
# about what failed has been saved to file. Display the report.
mtr_report("\n");
mtr_report($tinfo->{logfile}, "\n");
} if ( !$logfile and !$comment )
else
{ {
# Neither this script or the test tool has recorded info # Neither this script or the test tool has recorded info
# about why the test has failed. Should be debugged. # about why the test has failed. Should be debugged.
mtr_report("\nUnexpected termination, probably when starting mysqld");; mtr_report("\nUnknown result, neither 'comment' or 'logfile' set");
} }
} }
elsif ($tinfo->{'result'} eq 'MTR_RES_SKIPPED') elsif ($result eq 'MTR_RES_SKIPPED')
{ {
if ( $tinfo->{'disable'} ) if ( $tinfo->{'disable'} )
{ {
mtr_report("[ disabled ] $tinfo->{'comment'}"); mtr_report("[ disabled ] $comment");
} }
elsif ( $tinfo->{'comment'} ) elsif ( $comment )
{ {
if ( $tinfo->{skip_detected_by_test} ) if ( $tinfo->{skip_detected_by_test} )
{ {
mtr_report("[ skip ]. $tinfo->{'comment'}"); mtr_report("[ skip ]. $comment");
} }
else else
{ {
mtr_report("[ skip ] $tinfo->{'comment'}"); mtr_report("[ skip ] $comment");
} }
} }
else else
...@@ -165,7 +171,7 @@ sub mtr_report_test ($) { ...@@ -165,7 +171,7 @@ sub mtr_report_test ($) {
mtr_report("[ skip ]"); mtr_report("[ skip ]");
} }
} }
elsif ($tinfo->{'result'} eq 'MTR_RES_PASSED') elsif ($result eq 'MTR_RES_PASSED')
{ {
my $timer_str= $tinfo->{timer} || ""; my $timer_str= $tinfo->{timer} || "";
$tot_real_time += ($timer_str/1000); $tot_real_time += ($timer_str/1000);
......
...@@ -164,7 +164,7 @@ my $opt_repeat= 1; ...@@ -164,7 +164,7 @@ my $opt_repeat= 1;
my $opt_retry= 3; my $opt_retry= 3;
my $opt_retry_failure= 2; my $opt_retry_failure= 2;
my $opt_parallel; my $opt_parallel= $ENV{MTR_PARALLEL};
my $opt_strace_client; my $opt_strace_client;
...@@ -291,8 +291,9 @@ sub main { ...@@ -291,8 +291,9 @@ sub main {
my $tinfo = My::Test->new my $tinfo = My::Test->new
( (
name => 'report_features', name => 'report_features',
result_file => undef, # Prints result # No result_file => Prints result
path => 'include/report-features.test'. path => 'include/report-features.test'.
template_path => "include/default_my.cnf",
master_opt => [], master_opt => [],
slave_opt => [], slave_opt => [],
); );
...@@ -615,6 +616,7 @@ sub run_worker ($) { ...@@ -615,6 +616,7 @@ sub run_worker ($) {
} }
setup_vardir(); setup_vardir();
check_running_as_root();
mysql_install_db($thread_num); mysql_install_db($thread_num);
if ( using_extern() ) { if ( using_extern() ) {
...@@ -2326,7 +2328,6 @@ sub initialize_servers { ...@@ -2326,7 +2328,6 @@ sub initialize_servers {
mysql_install_db(0); mysql_install_db(0);
} }
} }
check_running_as_root();
} }
...@@ -2685,6 +2686,120 @@ sub check_testcase($$) ...@@ -2685,6 +2686,120 @@ sub check_testcase($$)
} }
# Start run mysqltest on one server
#
# RETURN VALUE
# 0 OK
# 1 Check failed
#
sub start_run_one ($$) {
my ($mysqld, $run)= @_;
my $name= "$run-".$mysqld->name();
my $args;
mtr_init_args(\$args);
mtr_add_arg($args, "--defaults-file=%s", $path_config_file);
mtr_add_arg($args, "--defaults-group-suffix=%s", $mysqld->after('mysqld'));
mtr_add_arg($args, "--silent");
mtr_add_arg($args, "--skip-safemalloc");
mtr_add_arg($args, "--test-file=%s", "include/$run.test");
my $errfile= "$opt_vardir/tmp/$name.err";
my $proc= My::SafeProcess->new
(
name => $name,
path => $exe_mysqltest,
error => $errfile,
output => $errfile,
args => \$args,
user_data => $errfile,
);
mtr_verbose("Started $proc");
return $proc;
}
#
# Run script on all servers, collect results
#
# RETURN VALUE
# 0 ok
# 1 Failure
sub run_on_all($$)
{
my ($tinfo, $run)= @_;
my $tname= $tinfo->{name};
# Start the mysqltest processes in parallel to save time
# also makes it possible to wait for any process to exit during the check
# and to have a timeout process
my %started;
foreach my $mysqld ( mysqlds() )
{
if ( defined $mysqld->{'proc'} )
{
my $proc= start_run_one($mysqld, $run);
$started{$proc->pid()}= $proc;
}
}
# Return immediately if no check proceess was started
return 0 unless ( keys %started );
my $timeout_proc= My::SafeProcess->timer(60); # Seconds
while (1){
my $result;
my $proc= My::SafeProcess->wait_any();
mtr_report("Got $proc");
if ( delete $started{$proc->pid()} ) {
# One mysqltest process returned
my $err_file= $proc->user_data();
my $res= $proc->exit_status();
# Append the report from .err file
$tinfo->{comment}.= " == $err_file ==\n";
$tinfo->{comment}.= mtr_grab_file($err_file);
$tinfo->{comment}.= "\n";
# Remove the .err file
unlink($err_file);
if ( keys(%started) == 0){
# All completed
$timeout_proc->kill();
return 0;
}
# Wait for next process to exit
next;
}
elsif ( $proc eq $timeout_proc ) {
$tinfo->{comment}.= "Timeout $timeout_proc expired for running '$run'";
}
else {
# Unknown process returned, most likley a crash, abort everything
$tinfo->{comment}.=
"Unexpected process $proc returned during ".
"execution of '$run'";
}
# Kill any check processes still running
map($_->kill(), values(%started));
$timeout_proc->kill();
return 1;
}
}
sub mark_log { sub mark_log {
my ($log, $tinfo)= @_; my ($log, $tinfo)= @_;
my $log_msg= "CURRENT_TEST: $tinfo->{name}\n"; my $log_msg= "CURRENT_TEST: $tinfo->{name}\n";
...@@ -2722,6 +2837,26 @@ sub find_testcase_skipped_reason($) ...@@ -2722,6 +2837,26 @@ sub find_testcase_skipped_reason($)
} }
sub find_analyze_request
{
# Open the test log file
my $F= IO::File->new($path_current_testlog)
or return;
my $analyze;
while ( my $line= <$F> )
{
# Look for "reason: <reason for skipping test>"
if ( $line =~ /analyze: (.*)/ )
{
$analyze= $1;
}
}
return $analyze;
}
# Return timezone value of tinfo or default value # Return timezone value of tinfo or default value
sub timezone { sub timezone {
my ($tinfo)= @_; my ($tinfo)= @_;
...@@ -2925,6 +3060,13 @@ sub run_testcase ($) { ...@@ -2925,6 +3060,13 @@ sub run_testcase ($) {
} }
elsif ( $res == 1 ) elsif ( $res == 1 )
{ {
# Check if the test tool requests that
# an analyze script should be run
my $analyze= find_analyze_request();
if ($analyze){
run_on_all($tinfo, "analyze-$analyze");
}
# Test case failure reported by mysqltest # Test case failure reported by mysqltest
report_failure_and_restart($tinfo); report_failure_and_restart($tinfo);
} }
...@@ -2983,8 +3125,10 @@ sub run_testcase ($) { ...@@ -2983,8 +3125,10 @@ sub run_testcase ($) {
# ---------------------------------------------------- # ----------------------------------------------------
if ( $proc eq $test_timeout_proc ) if ( $proc eq $test_timeout_proc )
{ {
mtr_report("Test case timeout!"); $tinfo->{comment}=
$tinfo->{'timeout'}= 1; # Mark as timeout "Test case timeout after $opt_testcase_timeout minute(s)\n\n";
$tinfo->{'timeout'}= $opt_testcase_timeout; # Mark as timeout
run_on_all($tinfo, 'analyze-timeout');
report_failure_and_restart($tinfo); report_failure_and_restart($tinfo);
return 1; return 1;
} }
...@@ -3301,7 +3445,6 @@ sub report_failure_and_restart ($) { ...@@ -3301,7 +3445,6 @@ sub report_failure_and_restart ($) {
$tinfo->{'failures'}= $test_failures + 1; $tinfo->{'failures'}= $test_failures + 1;
my $logfile= $path_current_testlog;
if ( $tinfo->{comment} ) if ( $tinfo->{comment} )
{ {
# The test failure has been detected by mysql-test-run.pl # The test failure has been detected by mysql-test-run.pl
...@@ -3309,13 +3452,18 @@ sub report_failure_and_restart ($) { ...@@ -3309,13 +3452,18 @@ sub report_failure_and_restart ($) {
# failing the test is saved in "comment" # failing the test is saved in "comment"
; ;
} }
elsif ( defined $logfile and -f $logfile )
if ( !defined $tinfo->{logfile} )
{
my $logfile= $path_current_testlog;
if ( defined $logfile and -f $logfile )
{ {
# Test failure was detected by test tool and its report # Test failure was detected by test tool and its report
# about what failed has been saved to file. Save the report # about what failed has been saved to file. Save the report
# in tinfo # in tinfo
$tinfo->{logfile}= mtr_fromfile($logfile); $tinfo->{logfile}= mtr_fromfile($logfile);
} }
}
after_failure($tinfo); after_failure($tinfo);
...@@ -3892,6 +4040,16 @@ sub start_servers($) { ...@@ -3892,6 +4040,16 @@ sub start_servers($) {
$mysqld->{'proc'}) == 0) { $mysqld->{'proc'}) == 0) {
$tinfo->{comment}= $tinfo->{comment}=
"Failed to start ".$mysqld->name(); "Failed to start ".$mysqld->name();
my $logfile= $mysqld->value('log-error');
if ( defined $logfile and -f $logfile )
{
$tinfo->{logfile}= mtr_fromfile($logfile);
}
else
{
$tinfo->{logfile}= "Could not open server logfile: '$logfile'";
}
return 1; return 1;
} }
} }
...@@ -4012,8 +4170,6 @@ sub start_mysqltest ($) { ...@@ -4012,8 +4170,6 @@ sub start_mysqltest ($) {
mtr_add_arg($args, "--sleep=%d", $opt_sleep); mtr_add_arg($args, "--sleep=%d", $opt_sleep);
} }
client_debug_arg($args, "mysqltest");
if ( $opt_ssl ) if ( $opt_ssl )
{ {
# Turn on SSL for _all_ test cases if option --ssl was used # Turn on SSL for _all_ test cases if option --ssl was used
...@@ -4069,6 +4225,8 @@ sub start_mysqltest ($) { ...@@ -4069,6 +4225,8 @@ sub start_mysqltest ($) {
mtr_add_arg($args, "--result-file=%s", $tinfo->{'result_file'}); mtr_add_arg($args, "--result-file=%s", $tinfo->{'result_file'});
} }
client_debug_arg($args, "mysqltest");
if ( $opt_record ) if ( $opt_record )
{ {
mtr_add_arg($args, "--record"); mtr_add_arg($args, "--record");
......
...@@ -293,7 +293,7 @@ var5 from query that returns no row ...@@ -293,7 +293,7 @@ var5 from query that returns no row
failing query in let failing query in let
mysqltest: At line 1: Error running query 'failing query': 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'failing query' at line 1 mysqltest: At line 1: Error running query 'failing query': 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'failing query' at line 1
mysqltest: At line 1: Missing required argument 'filename' to command 'source' mysqltest: At line 1: Missing required argument 'filename' to command 'source'
mysqltest: At line 1: Could not open './non_existingFile' for reading mysqltest: At line 1: Could not open './non_existingFile' for reading, errno: 2
mysqltest: In included file "MYSQLTEST_VARDIR/tmp/recursive.sql": At line 1: Source directives are nesting too deep mysqltest: In included file "MYSQLTEST_VARDIR/tmp/recursive.sql": At line 1: Source directives are nesting too deep
mysqltest: In included file "MYSQLTEST_VARDIR/tmp/error.sql": At line 1: query 'garbage ' failed: 1064: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'garbage' at line 1 mysqltest: In included file "MYSQLTEST_VARDIR/tmp/error.sql": At line 1: query 'garbage ' failed: 1064: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'garbage' at line 1
...@@ -443,7 +443,7 @@ ERROR 3D000: No database selected ...@@ -443,7 +443,7 @@ ERROR 3D000: No database selected
Output from mysqltest-x.inc Output from mysqltest-x.inc
Output from mysqltest-x.inc Output from mysqltest-x.inc
Output from mysqltest-x.inc Output from mysqltest-x.inc
mysqltest: Could not open './non_existing_file.inc' for reading: errno = 2 mysqltest: Could not open './non_existing_file.inc' for reading, errno: 2
failing_statement; failing_statement;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'failing_statement' at line 1 ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'failing_statement' at line 1
failing_statement; failing_statement;
...@@ -486,8 +486,6 @@ mysqltest: At line 3: query 'create table t1 (a int primary key); ...@@ -486,8 +486,6 @@ mysqltest: At line 3: query 'create table t1 (a int primary key);
insert into t1 values (1); insert into t1 values (1);
select 'select-me'; select 'select-me';
insertz 'error query'' failed: 1064: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'insertz 'error query'' at line 1 insertz 'error query'' failed: 1064: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'insertz 'error query'' at line 1
More results from queries before failure can be found in MYSQLTEST_VARDIR/log/bug11731.log
drop table t1; drop table t1;
Multi statement using expected error Multi statement using expected error
create table t1 (a int primary key); create table t1 (a int primary key);
...@@ -728,4 +726,12 @@ mysqltest: At line 1: change user failed: Access denied for user 'root'@'localho ...@@ -728,4 +726,12 @@ mysqltest: At line 1: change user failed: Access denied for user 'root'@'localho
SELECT 'c:\\a.txt' AS col; SELECT 'c:\\a.txt' AS col;
col col
z z
select 1;
1
1
select 1;
1
1
-- a comment for the server;
mysqltest: At line 1: Found line beginning with -- that didn't contain a valid mysqltest command, check your syntax or use # if you intended to write a comment
End of tests End of tests
...@@ -51,7 +51,8 @@ echo; ...@@ -51,7 +51,8 @@ echo;
-- disable_query_log -- disable_query_log
# Run the mysql_fix_privilege_tables.sql using "mysql --force" # Run the mysql_fix_privilege_tables.sql using "mysql --force"
--exec $MYSQL --force mysql < $MYSQL_FIX_PRIVILEGE_TABLES > $MYSQLTEST_VARDIR/log/fix_priv_tables.log 2>&1 --exec $MYSQL --force mysql < $MYSQL_FIX_PRIVILEGE_TABLES > $MYSQLTEST_VARDIR/tmp/fix_priv_tables.log 2>&1
--remove_file $MYSQLTEST_VARDIR/tmp/fix_priv_tables.log
-- enable_query_log -- enable_query_log
-- enable_result_log -- enable_result_log
......
...@@ -1225,7 +1225,7 @@ select "a" as col1, "c" as col2; ...@@ -1225,7 +1225,7 @@ select "a" as col1, "c" as col2;
--exec echo "replace_result a;" | $MYSQL_TEST 2>&1 --exec echo "replace_result a;" | $MYSQL_TEST 2>&1
--error 1 --error 1
--exec echo "replace_result a ;" | $MYSQL_TEST 2>&1 --exec echo "replace_result a ;" | $MYSQL_TEST 2>&1
--exec echo "replace_result a b; echo OK;" | $MYSQL_TEST 2>&1 --exec echo "replace_result a b; echo OK; exit;" | $MYSQL_TEST 2>&1
--error 1 --error 1
--exec echo "--replace_result a b c" | $MYSQL_TEST 2>&1 --exec echo "--replace_result a b c" | $MYSQL_TEST 2>&1
--error 1 --error 1
...@@ -1289,7 +1289,7 @@ while ($i) ...@@ -1289,7 +1289,7 @@ while ($i)
dec $i; dec $i;
} }
EOF EOF
--exec echo "source $MYSQLTEST_VARDIR/tmp/mysqltest.sql; echo OK;" | $MYSQL_TEST 2>&1 --exec echo "source $MYSQLTEST_VARDIR/tmp/mysqltest.sql; echo OK; exit;" | $MYSQL_TEST 2>&1
remove_file $MYSQLTEST_VARDIR/tmp/mysqltest.sql; remove_file $MYSQLTEST_VARDIR/tmp/mysqltest.sql;
# Repeat connect/disconnect # Repeat connect/disconnect
...@@ -1496,6 +1496,7 @@ echo Multi statement using expected error; ...@@ -1496,6 +1496,7 @@ echo Multi statement using expected error;
--exec echo "select 'select-me';" >> $MYSQLTEST_VARDIR/tmp/bug11731.sql --exec echo "select 'select-me';" >> $MYSQLTEST_VARDIR/tmp/bug11731.sql
--exec echo "insertz "error query"||||" >> $MYSQLTEST_VARDIR/tmp/bug11731.sql --exec echo "insertz "error query"||||" >> $MYSQLTEST_VARDIR/tmp/bug11731.sql
--exec echo "delimiter ;||||" >> $MYSQLTEST_VARDIR/tmp/bug11731.sql --exec echo "delimiter ;||||" >> $MYSQLTEST_VARDIR/tmp/bug11731.sql
--exec echo "exit;" >> $MYSQLTEST_VARDIR/tmp/bug11731.sql
# These two should work since the error is expected # These two should work since the error is expected
--exec $MYSQL_TEST -x $MYSQLTEST_VARDIR/tmp/bug11731.sql 2>&1 --exec $MYSQL_TEST -x $MYSQLTEST_VARDIR/tmp/bug11731.sql 2>&1
...@@ -1688,6 +1689,7 @@ EOF ...@@ -1688,6 +1689,7 @@ EOF
--diff_files $MYSQLTEST_VARDIR/tmp/diff1.tmp $MYSQLTEST_VARDIR/tmp/diff4.tmp --diff_files $MYSQLTEST_VARDIR/tmp/diff1.tmp $MYSQLTEST_VARDIR/tmp/diff4.tmp
--error 1 --error 1
--diff_files $MYSQLTEST_VARDIR/tmp/diff4.tmp $MYSQLTEST_VARDIR/tmp/diff1.tmp --diff_files $MYSQLTEST_VARDIR/tmp/diff4.tmp $MYSQLTEST_VARDIR/tmp/diff1.tmp
exit;
EOF EOF
# Execute the above diffs, and send their output to /dev/null - only # Execute the above diffs, and send their output to /dev/null - only
...@@ -2131,5 +2133,19 @@ rmdir $MYSQLTEST_VARDIR/tmp/testdir; ...@@ -2131,5 +2133,19 @@ rmdir $MYSQLTEST_VARDIR/tmp/testdir;
--replace_result c:\\a.txt z --replace_result c:\\a.txt z
SELECT 'c:\\a.txt' AS col; SELECT 'c:\\a.txt' AS col;
# ----------------------------------------------------------------------------
# Test that -- is not allowed as comment, only as mysqltest builtin command
# ----------------------------------------------------------------------------
# valid
select 1;
--query select 1
--query -- a comment for the server
# Not valid, "select" is not a mysqltest command
--error 1
--exec echo "--select 1;" | $MYSQL_TEST 2>&1
--echo End of tests --echo End of tests
...@@ -101,7 +101,7 @@ drop table t1; ...@@ -101,7 +101,7 @@ drop table t1;
# - Apparently selecting a cipher doesn't work at all # - Apparently selecting a cipher doesn't work at all
# - Usa a cipher that both yaSSL and OpenSSL supports # - Usa a cipher that both yaSSL and OpenSSL supports
# #
--exec echo "SHOW STATUS LIKE 'Ssl_cipher';" > $MYSQLTEST_VARDIR/tmp/test.sql --exec echo "SHOW STATUS LIKE 'Ssl_cipher'; exit;" > $MYSQLTEST_VARDIR/tmp/test.sql
--exec $MYSQL_TEST --ssl-cipher=DHE-RSA-AES256-SHA < $MYSQLTEST_VARDIR/tmp/test.sql 2>&1 --exec $MYSQL_TEST --ssl-cipher=DHE-RSA-AES256-SHA < $MYSQLTEST_VARDIR/tmp/test.sql 2>&1
# #
...@@ -155,18 +155,18 @@ SET GLOBAL event_scheduler=0; ...@@ -155,18 +155,18 @@ SET GLOBAL event_scheduler=0;
# #
# Test to connect using a list of ciphers # Test to connect using a list of ciphers
# #
--exec echo "SHOW STATUS LIKE 'Ssl_cipher';" > $MYSQLTEST_VARDIR/tmp/test.sql --exec echo "SHOW STATUS LIKE 'Ssl_cipher'; exit;" > $MYSQLTEST_VARDIR/tmp/test.sql
--exec $MYSQL_TEST --ssl-cipher=UNKNOWN-CIPHER:AES128-SHA < $MYSQLTEST_VARDIR/tmp/test.sql 2>&1 --exec $MYSQL_TEST --ssl-cipher=UNKNOWN-CIPHER:AES128-SHA < $MYSQLTEST_VARDIR/tmp/test.sql 2>&1
# Test to connect using a specifi cipher # Test to connect using a specifi cipher
# #
--exec echo "SHOW STATUS LIKE 'Ssl_cipher';" > $MYSQLTEST_VARDIR/tmp/test.sql --exec echo "SHOW STATUS LIKE 'Ssl_cipher'; exit;" > $MYSQLTEST_VARDIR/tmp/test.sql
--exec $MYSQL_TEST --ssl-cipher=AES128-SHA < $MYSQLTEST_VARDIR/tmp/test.sql 2>&1 --exec $MYSQL_TEST --ssl-cipher=AES128-SHA < $MYSQLTEST_VARDIR/tmp/test.sql 2>&1
# Test to connect using an unknown cipher # Test to connect using an unknown cipher
# #
--exec echo "SHOW STATUS LIKE 'Ssl_cipher';" > $MYSQLTEST_VARDIR/tmp/test.sql --exec echo "SHOW STATUS LIKE 'Ssl_cipher'; exit" > $MYSQLTEST_VARDIR/tmp/test.sql
--error 1 --error 1
--exec $MYSQL_TEST --ssl-cipher=UNKNOWN-CIPHER < $MYSQLTEST_VARDIR/tmp/test.sql 2>&1 --exec $MYSQL_TEST --ssl-cipher=UNKNOWN-CIPHER < $MYSQLTEST_VARDIR/tmp/test.sql 2>&1
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment