Commit 2cedc54d authored by unknown's avatar unknown

WL#3935 Improve mysqltest report and exitcode for diff

 - Move the code to generate test report to the test tool(in this
   case mysqltest) where the best control of what failed is
- Simplify the code in mysql-test-run.pl
- mysqltest will now find what diff to use in a best effort attempt
  using "diff -u", "diff -c" and finally dumping the two files verbatim
  in the report.


client/mysqltest.c:
  - Add new option --tail-lines indicating how many lines of the result to output
    when generating report for a failure
  - Remove eval_result, noone knows what it should do and it's not used.
  - Add support for best effort execution of systems builtin "diff",
    try with "diff -u" and "diff -c" and if that fails dump the whole content
     of teh two files to report
  - Use one common function when comapring two files, used when test 
    has completed and the result should be compared to the .result file
    as well as using it from myqltest's builtin diff_files command.
  - Output the last lines og the result so far  in the report that mysqltest
    generates in case of a test failure.
mysql-test/lib/mtr_report.pl:
  - Remove code for generating diff between .reject and .result file,
    that is handled by mysqltest(or the test tool) from now on.
  - Add better comments
mysql-test/mysql-test-run.pl:
  - Remove the --udiff flag to mysql-test-run.pl, if the systems diff supports
    unified diff it will be used automatically
  - Remove the code for "mtr_show_failed_diff", the report from mysqltest
    will know include the diff so if mysqltest(or another test tool)
    fails, just display it's report what went wrong
  - Pass --tail-lines=20 to mysqltest to it will shos the last 20 lines 
    from the result in the report in case of failure.	
mysql-test/r/mysqltest.result:
  Update result file now when the output from mysqltest has been sent to /dev/null
mysql-test/t/mysqltest.test:
  - Improve tests for --diff_files
  - Remove temporary files in var/tmp generated in the fly
  - Send output from test for --diff_files to /deb/null since only the error
    code it returns are of interest and tyhe outpu may vary depending
    on what builtin diff is being used.
parent 8b265ffc
...@@ -74,18 +74,12 @@ ...@@ -74,18 +74,12 @@
#define QUERY_SEND_FLAG 1 #define QUERY_SEND_FLAG 1
#define QUERY_REAP_FLAG 2 #define QUERY_REAP_FLAG 2
enum {
RESULT_OK= 0,
RESULT_CONTENT_MISMATCH= 1,
RESULT_LENGTH_MISMATCH= 2
};
enum { enum {
OPT_SKIP_SAFEMALLOC=256, OPT_SSL_SSL, OPT_SSL_KEY, OPT_SSL_CERT, OPT_SKIP_SAFEMALLOC=256, OPT_SSL_SSL, OPT_SSL_KEY, OPT_SSL_CERT,
OPT_SSL_CA, OPT_SSL_CAPATH, OPT_SSL_CIPHER, OPT_PS_PROTOCOL, OPT_SSL_CA, OPT_SSL_CAPATH, OPT_SSL_CIPHER, OPT_PS_PROTOCOL,
OPT_SP_PROTOCOL, OPT_CURSOR_PROTOCOL, OPT_VIEW_PROTOCOL, OPT_SP_PROTOCOL, OPT_CURSOR_PROTOCOL, OPT_VIEW_PROTOCOL,
OPT_SSL_VERIFY_SERVER_CERT, OPT_MAX_CONNECT_RETRIES, OPT_SSL_VERIFY_SERVER_CERT, OPT_MAX_CONNECT_RETRIES,
OPT_MARK_PROGRESS, OPT_CHARSETS_DIR, OPT_LOG_DIR OPT_MARK_PROGRESS, OPT_CHARSETS_DIR, OPT_LOG_DIR, OPT_TAIL_LINES
}; };
static int record= 0, opt_sleep= -1; static int record= 0, opt_sleep= -1;
...@@ -117,6 +111,9 @@ static char line_buffer[MAX_DELIMITER_LENGTH], *line_buffer_pos= line_buffer; ...@@ -117,6 +111,9 @@ static char line_buffer[MAX_DELIMITER_LENGTH], *line_buffer_pos= line_buffer;
static uint start_lineno= 0; /* Start line of current command */ static uint start_lineno= 0; /* Start line of current command */
/* Number of lines of the result to include in failure report */
static uint opt_tail_lines= 0;
static char delimiter[MAX_DELIMITER_LENGTH]= ";"; static char delimiter[MAX_DELIMITER_LENGTH]= ";";
static uint delimiter_length= 1; static uint delimiter_length= 1;
...@@ -455,7 +452,6 @@ void free_tmp_sh_file(); ...@@ -455,7 +452,6 @@ void free_tmp_sh_file();
void free_win_path_patterns(); void free_win_path_patterns();
#endif #endif
static int eval_result = 0;
/* For replace_column */ /* For replace_column */
static char *replace_column[MAX_COLUMNS]; static char *replace_column[MAX_COLUMNS];
...@@ -881,6 +877,24 @@ void die(const char *fmt, ...) ...@@ -881,6 +877,24 @@ void die(const char *fmt, ...)
fprintf(stderr, "\n"); fprintf(stderr, "\n");
fflush(stderr); fflush(stderr);
/* Show results from queries just before failure */
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 */ /* Dump the result that has been accumulated so far to .log file */
if (result_file_name && ds_res.length) if (result_file_name && ds_res.length)
dump_result_to_log_file(ds_res.str, ds_res.length); dump_result_to_log_file(ds_res.str, ds_res.length);
...@@ -1009,77 +1023,372 @@ void log_msg(const char *fmt, ...) ...@@ -1009,77 +1023,372 @@ void log_msg(const char *fmt, ...)
/* /*
Compare content of the string ds to content of file fname Read a file and append it to ds
SYNOPSIS
cat_file
ds - pointer to dynamic string where to add the files content
filename - name of the file to read
*/ */
int dyn_string_cmp(DYNAMIC_STRING* ds, const char *fname) void cat_file(DYNAMIC_STRING* ds, const char* filename)
{ {
MY_STAT stat_info;
char *tmp, *res_ptr;
char eval_file[FN_REFLEN];
int res;
uint res_len;
int fd; int fd;
DYNAMIC_STRING res_ds; uint len;
DBUG_ENTER("dyn_string_cmp"); char buff[512];
if (!test_if_hard_path(fname)) if ((fd= my_open(filename, O_RDONLY, MYF(0))) < 0)
die("Failed to open file %s", filename);
while((len= my_read(fd, (byte*)&buff,
sizeof(buff), MYF(0))) > 0)
{
char *p= buff, *start= buff;
while (p < buff+len)
{
/* Convert cr/lf to lf */
if (*p == '\r' && *(p+1) && *(p+1)== '\n')
{
/* Add fake newline instead of cr and output the line */
*p= '\n';
p++; /* Step past the "fake" newline */
dynstr_append_mem(ds, start, p-start);
p++; /* Step past the "fake" newline */
start= p;
}
else
p++;
}
/* Output any chars that migh be left */
dynstr_append_mem(ds, start, p-start);
}
my_close(fd, MYF(0));
}
/*
Run the specified command with popen
SYNOPSIS
run_command
cmd - command to execute(should be properly quoted
ds_res- pointer to dynamic string where to store the result
*/
static int run_command(char* cmd,
DYNAMIC_STRING *ds_res)
{
char buf[512]= {0};
FILE *res_file;
int error;
if (!(res_file= popen(cmd, "r")))
die("popen(\"%s\", \"r\") failed", cmd);
while (fgets(buf, sizeof(buf), res_file))
{ {
strxmov(eval_file, opt_basedir, fname, NullS); DBUG_PRINT("info", ("buf: %s", buf));
fn_format(eval_file, eval_file, "", "", MY_UNPACK_FILENAME); if(ds_res)
{
/* Save the output of this command in the supplied string */
dynstr_append(ds_res, buf);
}
else
{
/* Print it directly on screen */
fprintf(stdout, "%s", buf);
}
} }
else
fn_format(eval_file, fname, "", "", MY_UNPACK_FILENAME);
if (!my_stat(eval_file, &stat_info, MYF(MY_WME))) error= pclose(res_file);
die(NullS); return WEXITSTATUS(error);
if (!eval_result && (uint) stat_info.st_size != ds->length) }
/*
Run the specified tool with variable number of arguments
SYNOPSIS
run_tool
tool_path - the name of the tool to run
ds_res - pointer to dynamic string where to store the result
... - variable number of arguments that will be properly
quoted and appended after the tool's name
*/
static int run_tool(const char *tool_path, DYNAMIC_STRING *ds_res, ...)
{
int ret;
const char* arg;
va_list args;
DYNAMIC_STRING ds_cmdline;
DBUG_ENTER("run_tool");
DBUG_PRINT("enter", ("tool_path: %s", tool_path));
if (init_dynamic_string(&ds_cmdline, IF_WIN("\"", ""), FN_REFLEN, FN_REFLEN))
die("Out of memory");
dynstr_append_os_quoted(&ds_cmdline, tool_path, NullS);
dynstr_append(&ds_cmdline, " ");
va_start(args, ds_res);
while ((arg= va_arg(args, char *)))
{ {
DBUG_PRINT("info",("Size differs: result size: %u file size: %lu", /* Options should be os quoted */
ds->length, (ulong) stat_info.st_size)); if (strncmp(arg, "--", 2) == 0)
DBUG_PRINT("info",("result: '%s'", ds->str)); dynstr_append_os_quoted(&ds_cmdline, arg, NullS);
DBUG_RETURN(RESULT_LENGTH_MISMATCH); else
dynstr_append(&ds_cmdline, arg);
dynstr_append(&ds_cmdline, " ");
} }
if (!(tmp = (char*) my_malloc(stat_info.st_size + 1, MYF(MY_WME))))
va_end(args);
#ifdef __WIN__
dynstr_append(&ds_cmdline, "\"");
#endif
DBUG_PRINT("info", ("Running: %s", ds_cmdline.str));
ret= run_command(ds_cmdline.str, ds_res);
DBUG_PRINT("exit", ("ret: %d", ret));
dynstr_free(&ds_cmdline);
DBUG_RETURN(ret);
}
/*
Show the diff of two files using the systems builtin diff
command. If no such diff command exist, just dump the content
of the two files and inform about how to get "diff"
SYNOPSIS
show_diff
ds - pointer to dynamic string where to add the diff(may be NULL)
filename1 - name of first file
filename2 - name of second file
*/
void show_diff(DYNAMIC_STRING* ds,
const char* filename1, const char* filename2)
{
DYNAMIC_STRING ds_tmp;
if (init_dynamic_string(&ds_tmp, "", 256, 256))
die("Out of memory"); die("Out of memory");
if ((fd = my_open(eval_file, O_RDONLY, MYF(MY_WME))) < 0) /* First try with unified diff */
die("Failed to open file %s", eval_file); if (run_tool("diff",
if (my_read(fd, (byte*)tmp, stat_info.st_size, MYF(MY_WME|MY_NABP))) &ds_tmp, /* Get output from diff in ds_tmp */
die("Failed to read from file %s, errno: %d", eval_file, errno); "-u",
tmp[stat_info.st_size] = 0; filename1,
init_dynamic_string(&res_ds, "", stat_info.st_size+256, 256); filename2,
if (eval_result) "2>&1",
{ NULL) > 1) /* Most "diff" tools return >1 if error */
do_eval(&res_ds, tmp, tmp + stat_info.st_size, FALSE); {
res_ptr= res_ds.str; dynstr_set(&ds_tmp, "");
res_len= res_ds.length;
if (res_len != ds->length) /* Fallback to context diff with "diff -c" */
if (run_tool("diff",
&ds_tmp, /* Get output from diff in ds_tmp */
"-c",
filename1,
filename2,
"2>&1",
NULL) > 1) /* Most "diff" tools return >1 if error */
{ {
res= RESULT_LENGTH_MISMATCH; /*
goto err; Fallback to dump both files to result file and inform
about installing "diff"
*/
dynstr_set(&ds_tmp, "");
dynstr_append(&ds_tmp,
"\n"
"The two files differ but it was not possible to execute 'diff' in\n"
"order to show only the difference, tried both 'diff -u' or 'diff -c'.\n"
"Instead the whole content of the two files was shown for you to diff manually. ;)\n\n"
"To get a better report you should install 'diff' on your system, which you\n"
"for example can get from http://www.gnu.org/software/diffutils/diffutils.html\n"
#ifdef __WIN__
"or http://gnuwin32.sourceforge.net/packages/diffutils.htm\n"
#endif
"\n");
dynstr_append(&ds_tmp, " --- ");
dynstr_append(&ds_tmp, filename1);
dynstr_append(&ds_tmp, " >>>\n");
cat_file(&ds_tmp, filename1);
dynstr_append(&ds_tmp, "<<<\n --- ");
dynstr_append(&ds_tmp, filename1);
dynstr_append(&ds_tmp, " >>>\n");
cat_file(&ds_tmp, filename2);
dynstr_append(&ds_tmp, "<<<<\n");
} }
} }
if (ds)
{
/* Add the diff to output */
dynstr_append_mem(ds, ds_tmp.str, ds_tmp.length);
}
else else
{ {
res_ptr = tmp; /* Print diff directly to stdout */
res_len = stat_info.st_size; fprintf(stderr, "%s", ds_tmp.str);
} }
dynstr_free(&ds_tmp);
res= (memcmp(res_ptr, ds->str, res_len)) ? }
RESULT_CONTENT_MISMATCH : RESULT_OK;
err:
if (res && eval_result)
str_to_file(fn_format(eval_file, fname, "", ".eval",
MY_REPLACE_EXT),
res_ptr, res_len);
dynstr_free(&res_ds); enum compare_files_result_enum {
my_free((gptr) tmp, MYF(0)); RESULT_OK= 0,
my_close(fd, MYF(MY_WME)); RESULT_CONTENT_MISMATCH= 1,
RESULT_LENGTH_MISMATCH= 2
};
/*
Compare two files, given a fd to the first file and
name of the second file
SYNOPSIS
compare_files2
fd - Open file descriptor of the first file
filename2 - Name of second file
RETURN VALUES
According to the values in "compare_files_result_enum"
*/
int compare_files2(File fd, const char* filename2)
{
int error= RESULT_OK;
File fd2;
uint len, len2;
char buff[512], buff2[512];
DBUG_RETURN(res); if ((fd2= my_open(filename2, O_RDONLY, MYF(0))) < 0)
{
my_close(fd, MYF(0));
die("Failed to open second file: %s", filename2);
}
while((len= my_read(fd, (byte*)&buff,
sizeof(buff), MYF(0))) > 0)
{
if ((len2= my_read(fd2, (byte*)&buff2,
sizeof(buff2), MYF(0))) < len)
{
/* File 2 was smaller */
error= RESULT_LENGTH_MISMATCH;
break;
}
if (len2 > len)
{
/* File 1 was smaller */
error= RESULT_LENGTH_MISMATCH;
break;
}
if ((memcmp(buff, buff2, len)))
{
/* Content of this part differed */
error= RESULT_CONTENT_MISMATCH;
break;
}
}
if (!error && my_read(fd2, (byte*)&buff2,
sizeof(buff2), MYF(0)) > 0)
{
/* File 1 was smaller */
error= RESULT_LENGTH_MISMATCH;
}
my_close(fd2, MYF(0));
return error;
}
/*
Compare two files, given their filenames
SYNOPSIS
compare_files
filename1 - Name of first file
filename2 - Name of second file
RETURN VALUES
See 'compare_files2'
*/
int compare_files(const char* filename1, const char* filename2)
{
File fd;
int error;
if ((fd= my_open(filename1, O_RDONLY, MYF(0))) < 0)
die("Failed to open first file: %s", filename1);
error= compare_files2(fd, filename2);
my_close(fd, MYF(0));
return error;
}
/*
Compare content of the string in ds to content of file fname
SYNOPSIS
dyn_string_cmp
ds - Dynamic string containing the string o be compared
fname - Name of file to compare with
RETURN VALUES
See 'compare_files2'
*/
int dyn_string_cmp(DYNAMIC_STRING* ds, const char *fname)
{
int error;
File fd;
char ds_temp_file_path[FN_REFLEN];
DBUG_ENTER("dyn_string_cmp");
DBUG_PRINT("enter", ("fname: %s", fname));
if ((fd= create_temp_file(ds_temp_file_path, NULL,
"tmp", O_CREAT | O_SHARE | O_RDWR,
MYF(MY_WME))) < 0)
die("Failed to create temporary file for ds");
/* Write ds to temporary file and set file pos to beginning*/
if (my_write(fd, ds->str, ds->length,
MYF(MY_FNABP | MY_WME)) ||
my_seek(fd, 0, SEEK_SET, MYF(0)) == MY_FILEPOS_ERROR)
{
my_close(fd, MYF(0));
/* Remove the temporary file */
my_delete(ds_temp_file_path, MYF(0));
die("Failed to write to '%s'", ds_temp_file_path);
}
error= compare_files2(fd, fname);
my_close(fd, MYF(0));
/* Remove the temporary file */
my_delete(ds_temp_file_path, MYF(0));
DBUG_RETURN(error);
} }
...@@ -1097,21 +1406,34 @@ err: ...@@ -1097,21 +1406,34 @@ err:
void check_result(DYNAMIC_STRING* ds) void check_result(DYNAMIC_STRING* ds)
{ {
const char* mess= "Result content mismatch\n";
DBUG_ENTER("check_result"); DBUG_ENTER("check_result");
DBUG_ASSERT(result_file_name); DBUG_ASSERT(result_file_name);
DBUG_PRINT("enter", ("result_file_name: %s", result_file_name));
switch (dyn_string_cmp(ds, 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:
dump_result_to_reject_file(ds->str, ds->length); mess= "Result length mismatch\n";
die("Result length mismatch"); /* Fallthrough */
break;
case RESULT_CONTENT_MISMATCH: case RESULT_CONTENT_MISMATCH:
dump_result_to_reject_file(ds->str, ds->length); {
die("Result content mismatch"); /* Result mismatched, dump results to .reject file and then show the diff */
char reject_file[FN_REFLEN];
fn_format(reject_file, result_file_name, "", ".reject",
MY_REPLACE_EXT);
DBUG_PRINT("enter", ("reject_file_name: %s", reject_file));
str_to_file(reject_file, ds->str, ds->length);
dynstr_set(ds, NULL); /* Don't create a .log file */
show_diff(NULL, result_file_name, reject_file);
die(mess);
break; break;
}
default: /* impossible */ default: /* impossible */
die("Unknown error code from dyn_string_cmp()"); die("Unknown error code from dyn_string_cmp()");
} }
...@@ -1126,7 +1448,7 @@ void check_result(DYNAMIC_STRING* ds) ...@@ -1126,7 +1448,7 @@ void check_result(DYNAMIC_STRING* ds)
indicating that test is not supported indicating that test is not supported
SYNOPSIS SYNOPSIS
check_result check_require
ds - content to be checked ds - content to be checked
fname - name of file to check against fname - name of file to check against
...@@ -1530,7 +1852,7 @@ void var_query_set(VAR *var, const char *query, const char** query_end) ...@@ -1530,7 +1852,7 @@ void var_query_set(VAR *var, const char *query, const char** query_end)
void var_set_query_get_value(struct st_command *command, VAR *var) void var_set_query_get_value(struct st_command *command, VAR *var)
{ {
ulong row_no; long row_no;
int col_no= -1; int col_no= -1;
MYSQL_RES* res; MYSQL_RES* res;
MYSQL* mysql= &cur_con->mysql; MYSQL* mysql= &cur_con->mysql;
...@@ -1602,7 +1924,7 @@ void var_set_query_get_value(struct st_command *command, VAR *var) ...@@ -1602,7 +1924,7 @@ void var_set_query_get_value(struct st_command *command, VAR *var)
{ {
/* Get the value */ /* Get the value */
MYSQL_ROW row; MYSQL_ROW row;
ulong rows= 0; long rows= 0;
const char* value= "No such row"; const char* value= "No such row";
while ((row= mysql_fetch_row(res))) while ((row= mysql_fetch_row(res)))
...@@ -2438,9 +2760,6 @@ void do_append_file(struct st_command *command) ...@@ -2438,9 +2760,6 @@ void do_append_file(struct st_command *command)
void do_cat_file(struct st_command *command) void do_cat_file(struct st_command *command)
{ {
int fd;
uint len;
char buff[512];
static DYNAMIC_STRING ds_filename; static DYNAMIC_STRING ds_filename;
const struct command_arg cat_file_args[] = { const struct command_arg cat_file_args[] = {
"filename", ARG_STRING, TRUE, &ds_filename, "File to read from" "filename", ARG_STRING, TRUE, &ds_filename, "File to read from"
...@@ -2455,37 +2774,13 @@ void do_cat_file(struct st_command *command) ...@@ -2455,37 +2774,13 @@ void do_cat_file(struct st_command *command)
DBUG_PRINT("info", ("Reading from, file: %s", ds_filename.str)); DBUG_PRINT("info", ("Reading from, file: %s", ds_filename.str));
if ((fd= my_open(ds_filename.str, O_RDONLY, MYF(0))) < 0) cat_file(&ds_res, ds_filename.str);
die("Failed to open file %s", ds_filename.str);
while((len= my_read(fd, (byte*)&buff,
sizeof(buff), MYF(0))) > 0)
{
char *p= buff, *start= buff;
while (p < buff+len)
{
/* Convert cr/lf to lf */
if (*p == '\r' && *(p+1) && *(p+1)== '\n')
{
/* Add fake newline instead of cr and output the line */
*p= '\n';
p++; /* Step past the "fake" newline */
dynstr_append_mem(&ds_res, start, p-start);
p++; /* Step past the "fake" newline */
start= p;
}
else
p++;
}
/* Output any chars that migh be left */
dynstr_append_mem(&ds_res, start, p-start);
}
my_close(fd, MYF(0));
dynstr_free(&ds_filename); dynstr_free(&ds_filename);
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
/* /*
SYNOPSIS SYNOPSIS
do_diff_files do_diff_files
...@@ -2501,9 +2796,6 @@ void do_cat_file(struct st_command *command) ...@@ -2501,9 +2796,6 @@ void do_cat_file(struct st_command *command)
void do_diff_files(struct st_command *command) void do_diff_files(struct st_command *command)
{ {
int error= 0; int error= 0;
int fd, fd2;
uint len, len2;
char buff[512], buff2[512];
static DYNAMIC_STRING ds_filename; static DYNAMIC_STRING ds_filename;
static DYNAMIC_STRING ds_filename2; static DYNAMIC_STRING ds_filename2;
const struct command_arg diff_file_args[] = { const struct command_arg diff_file_args[] = {
...@@ -2518,39 +2810,14 @@ void do_diff_files(struct st_command *command) ...@@ -2518,39 +2810,14 @@ void do_diff_files(struct st_command *command)
sizeof(diff_file_args)/sizeof(struct command_arg), sizeof(diff_file_args)/sizeof(struct command_arg),
' '); ' ');
if ((fd= my_open(ds_filename.str, O_RDONLY, MYF(0))) < 0) if ((error= compare_files(ds_filename.str, ds_filename2.str)))
die("Failed to open first file %s", ds_filename.str);
if ((fd2= my_open(ds_filename2.str, O_RDONLY, MYF(0))) < 0)
{
my_close(fd, MYF(0));
die("Failed to open second file %s", ds_filename2.str);
}
while((len= my_read(fd, (byte*)&buff,
sizeof(buff), MYF(0))) > 0)
{ {
if ((len2= my_read(fd2, (byte*)&buff2, /* Compare of the two files failed, append them to output
sizeof(buff2), MYF(0))) != len) so the failure can be analyzed
{ */
/* File 2 was smaller */ show_diff(&ds_res, ds_filename.str, ds_filename2.str);
error= 1;
break;
}
if ((memcmp(buff, buff2, len)))
{
/* Content of this part differed */
error= 1;
break;
}
}
if (my_read(fd2, (byte*)&buff2,
sizeof(buff2), MYF(0)) > 0)
{
/* File 1 was smaller */
error= 1;
} }
my_close(fd, MYF(0));
my_close(fd2, MYF(0));
dynstr_free(&ds_filename); dynstr_free(&ds_filename);
dynstr_free(&ds_filename2); dynstr_free(&ds_filename2);
handle_command_error(command, error); handle_command_error(command, error);
...@@ -4408,7 +4675,7 @@ void check_eol_junk(const char *eol) ...@@ -4408,7 +4675,7 @@ void check_eol_junk(const char *eol)
terminated by new line '\n' regardless how many "delimiter" it contain. terminated by new line '\n' regardless how many "delimiter" it contain.
*/ */
#define MAX_QUERY (256*1024) /* 256K -- a test in sp-big is >128K */ #define MAX_QUERY (256*1024*2) /* 256K -- a test in sp-big is >128K */
static char read_command_buf[MAX_QUERY]; static char read_command_buf[MAX_QUERY];
int read_command(struct st_command** command_ptr) int read_command(struct st_command** command_ptr)
...@@ -4542,6 +4809,10 @@ static struct my_option my_long_options[] = ...@@ -4542,6 +4809,10 @@ static struct my_option my_long_options[] =
{"sp-protocol", OPT_SP_PROTOCOL, "Use stored procedures for select", {"sp-protocol", OPT_SP_PROTOCOL, "Use stored procedures for select",
(gptr*) &sp_protocol, (gptr*) &sp_protocol, 0, (gptr*) &sp_protocol, (gptr*) &sp_protocol, 0,
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"tail-lines", OPT_TAIL_LINES,
"Number of lines of the resul to include in a failure report",
(gptr*) &opt_tail_lines, (gptr*) &opt_tail_lines, 0,
GET_INT, REQUIRED_ARG, 0, 0, 10000, 0, 0, 0},
#include "sslopt-longopts.h" #include "sslopt-longopts.h"
{"test-file", 'x', "Read test from/in this file (default stdin).", {"test-file", 'x', "Read test from/in this file (default stdin).",
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
...@@ -4793,14 +5064,6 @@ void str_to_file(const char *fname, char *str, int size) ...@@ -4793,14 +5064,6 @@ void str_to_file(const char *fname, char *str, int size)
} }
void dump_result_to_reject_file(char *buf, int size)
{
char reject_file[FN_REFLEN];
str_to_file(fn_format(reject_file, result_file_name, "", ".reject",
MY_REPLACE_EXT),
buf, size);
}
void dump_result_to_log_file(char *buf, int size) void dump_result_to_log_file(char *buf, int size)
{ {
char log_file[FN_REFLEN]; char log_file[FN_REFLEN];
...@@ -4808,6 +5071,8 @@ void dump_result_to_log_file(char *buf, int size) ...@@ -4808,6 +5071,8 @@ void dump_result_to_log_file(char *buf, int size)
*opt_logdir ? MY_REPLACE_DIR | MY_REPLACE_EXT : *opt_logdir ? MY_REPLACE_DIR | MY_REPLACE_EXT :
MY_REPLACE_EXT), MY_REPLACE_EXT),
buf, size); buf, size);
fprintf(stderr, "\nMore results from queries before failure can be found in %s\n",
log_file);
} }
void dump_progress(void) void dump_progress(void)
...@@ -5792,7 +6057,7 @@ void run_query(struct st_connection *cn, struct st_command *command, int flags) ...@@ -5792,7 +6057,7 @@ 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 sendign to server */ /* Scan for warning before sending to server */
scan_command_for_warnings(command); scan_command_for_warnings(command);
/* /*
...@@ -6424,7 +6689,7 @@ int main(int argc, char **argv) ...@@ -6424,7 +6689,7 @@ int main(int argc, char **argv)
break; break;
case Q_LET: do_let(command); break; case Q_LET: do_let(command); break;
case Q_EVAL_RESULT: case Q_EVAL_RESULT:
eval_result = 1; break; die("'eval_result' command is deprecated");
case Q_EVAL: case Q_EVAL:
case Q_QUERY_VERTICAL: case Q_QUERY_VERTICAL:
case Q_QUERY_HORIZONTAL: case Q_QUERY_HORIZONTAL:
......
...@@ -26,7 +26,6 @@ sub mtr_report_test_failed($); ...@@ -26,7 +26,6 @@ sub mtr_report_test_failed($);
sub mtr_report_test_skipped($); sub mtr_report_test_skipped($);
sub mtr_report_test_not_skipped_though_disabled($); sub mtr_report_test_not_skipped_though_disabled($);
sub mtr_show_failed_diff ($);
sub mtr_report_stats ($); sub mtr_report_stats ($);
sub mtr_print_line (); sub mtr_print_line ();
sub mtr_print_thick_line (); sub mtr_print_thick_line ();
...@@ -45,55 +44,6 @@ sub mtr_verbose (@); ...@@ -45,55 +44,6 @@ sub mtr_verbose (@);
# #
############################################################################## ##############################################################################
# We can't use diff -u or diff -a as these are not portable
sub mtr_show_failed_diff ($) {
my $result_file_name= shift;
# The reject and log files have been dumped to
# to filenames based on the result_file's name
my $tname= basename($result_file_name);
$tname=~ s/\..*$//;
my $reject_file= "r/$tname.reject";
my $result_file= "r/$tname.result";
my $log_file= "r/$tname.log";
my $eval_file= "r/$tname.eval";
if ( $::opt_suite ne "main" )
{
$reject_file= "$::glob_mysql_test_dir/suite/$::opt_suite/$reject_file";
$result_file= "$::glob_mysql_test_dir/suite/$::opt_suite/$result_file";
$eval_file= "$::glob_mysql_test_dir/suite/$::opt_suite/$eval_file";
$log_file= "$::glob_mysql_test_dir/suite/$::opt_suite/$log_file";
}
if ( -f $eval_file )
{
$result_file= $eval_file;
}
my $diffopts= $::opt_udiff ? "-u" : "-c";
if ( -f $reject_file )
{
print "Below are the diffs between actual and expected results:\n";
print "-------------------------------------------------------\n";
# FIXME check result code?!
mtr_run("diff",[$diffopts,$result_file,$reject_file], "", "", "", "");
print "-------------------------------------------------------\n";
print "Please follow the instructions outlined at\n";
print "http://www.mysql.com/doc/en/Reporting_mysqltest_bugs.html\n";
print "to find the reason to this problem and how to report this.\n\n";
}
if ( -f $log_file )
{
print "Result from queries before failure can be found in $log_file\n";
# FIXME Maybe a tail -f -n 10 $log_file here
}
}
sub mtr_report_test_name ($) { sub mtr_report_test_name ($) {
my $tinfo= shift; my $tinfo= shift;
...@@ -165,16 +115,23 @@ sub mtr_report_test_failed ($) { ...@@ -165,16 +115,23 @@ sub mtr_report_test_failed ($) {
if ( $tinfo->{'comment'} ) if ( $tinfo->{'comment'} )
{ {
# The test failure has been detected by mysql-test-run.pl
# when starting the servers or due to other error, the reason for
# failing the test is saved in "comment"
print "\nERROR: $tinfo->{'comment'}\n"; print "\nERROR: $tinfo->{'comment'}\n";
} }
elsif ( -f $::path_timefile ) elsif ( -f $::path_timefile )
{ {
print "\nErrors are (from $::path_timefile) :\n"; # Test failure was detected by test tool and it's report
# about what failed has been saved to file. Display the report.
print "\n";
print mtr_fromfile($::path_timefile); # FIXME print_file() instead print mtr_fromfile($::path_timefile); # FIXME print_file() instead
print "\n(the last lines may be the most important ones)\n"; print "\n";
} }
else else
{ {
# Neither this script or the test tool has recorded info
# about why the test has failed. Should be debugged.
print "\nUnexpected termination, probably when starting mysqld\n"; print "\nUnexpected termination, probably when starting mysqld\n";
} }
} }
......
...@@ -83,7 +83,6 @@ require "lib/mtr_io.pl"; ...@@ -83,7 +83,6 @@ require "lib/mtr_io.pl";
require "lib/mtr_gcov.pl"; require "lib/mtr_gcov.pl";
require "lib/mtr_gprof.pl"; require "lib/mtr_gprof.pl";
require "lib/mtr_report.pl"; require "lib/mtr_report.pl";
require "lib/mtr_diff.pl";
require "lib/mtr_match.pl"; require "lib/mtr_match.pl";
require "lib/mtr_misc.pl"; require "lib/mtr_misc.pl";
require "lib/mtr_stress.pl"; require "lib/mtr_stress.pl";
...@@ -281,8 +280,6 @@ our $opt_wait_for_slave; ...@@ -281,8 +280,6 @@ our $opt_wait_for_slave;
our $opt_warnings; our $opt_warnings;
our $opt_udiff;
our $opt_skip_ndbcluster= 0; our $opt_skip_ndbcluster= 0;
our $opt_skip_ndbcluster_slave= 0; our $opt_skip_ndbcluster_slave= 0;
our $opt_with_ndbcluster= 0; our $opt_with_ndbcluster= 0;
...@@ -619,7 +616,6 @@ sub command_line_setup () { ...@@ -619,7 +616,6 @@ sub command_line_setup () {
'start-dirty' => \$opt_start_dirty, 'start-dirty' => \$opt_start_dirty,
'start-and-exit' => \$opt_start_and_exit, 'start-and-exit' => \$opt_start_and_exit,
'timer!' => \$opt_timer, 'timer!' => \$opt_timer,
'unified-diff|udiff' => \$opt_udiff,
'user=s' => \$opt_user, 'user=s' => \$opt_user,
'testcase-timeout=i' => \$opt_testcase_timeout, 'testcase-timeout=i' => \$opt_testcase_timeout,
'suite-timeout=i' => \$opt_suite_timeout, 'suite-timeout=i' => \$opt_suite_timeout,
...@@ -3603,7 +3599,6 @@ sub report_failure_and_restart ($) { ...@@ -3603,7 +3599,6 @@ sub report_failure_and_restart ($) {
my $tinfo= shift; my $tinfo= shift;
mtr_report_test_failed($tinfo); mtr_report_test_failed($tinfo);
mtr_show_failed_diff($tinfo->{'result_file'});
print "\n"; print "\n";
if ( $opt_force ) if ( $opt_force )
{ {
...@@ -4788,6 +4783,9 @@ sub run_mysqltest ($) { ...@@ -4788,6 +4783,9 @@ sub run_mysqltest ($) {
mtr_add_arg($args, "--test-file=%s", $tinfo->{'path'}); mtr_add_arg($args, "--test-file=%s", $tinfo->{'path'});
# Number of lines of resut to include in failure report
mtr_add_arg($args, "--tail-lines=20");
if ( defined $tinfo->{'result_file'} ) { if ( defined $tinfo->{'result_file'} ) {
mtr_add_arg($args, "--result-file=%s", $tinfo->{'result_file'}); mtr_add_arg($args, "--result-file=%s", $tinfo->{'result_file'});
} }
...@@ -5199,7 +5197,6 @@ Misc options ...@@ -5199,7 +5197,6 @@ Misc options
fast Don't try to clean up from earlier runs fast Don't try to clean up from earlier runs
reorder Reorder tests to get fewer server restarts reorder Reorder tests to get fewer server restarts
help Get this help text help Get this help text
unified-diff | udiff When presenting differences, use unified diff
testcase-timeout=MINUTES Max test case run time (default $default_testcase_timeout) testcase-timeout=MINUTES Max test case run time (default $default_testcase_timeout)
suite-timeout=MINUTES Max test suite run time (default $default_suite_timeout) suite-timeout=MINUTES Max test suite run time (default $default_suite_timeout)
......
...@@ -461,7 +461,6 @@ root@localhost ...@@ -461,7 +461,6 @@ root@localhost
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
this will be executed this will be executed
this will be executed this will be executed
mysqltest: Result length mismatch
mysqltest: The test didn't produce any output mysqltest: The test didn't produce any output
Failing multi statement query Failing multi statement query
mysqltest: At line 3: query 'create table t1 (a int primary key); mysqltest: At line 3: query 'create table t1 (a int primary key);
...@@ -473,6 +472,8 @@ mysqltest: At line 3: query 'create table t1 (a int primary key); ...@@ -473,6 +472,8 @@ 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/tmp/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);
......
...@@ -436,6 +436,8 @@ EOF ...@@ -436,6 +436,8 @@ EOF
--error 1 --error 1
--exec $MYSQL_TEST < $MYSQLTEST_VARDIR/tmp/mysqltest.sql 2>&1 --exec $MYSQL_TEST < $MYSQLTEST_VARDIR/tmp/mysqltest.sql 2>&1
remove_file $MYSQLTEST_VARDIR/tmp/mysqltest.sql;
# #
# Extra delimiter # Extra delimiter
# #
...@@ -786,6 +788,7 @@ echo $var3_var3; ...@@ -786,6 +788,7 @@ echo $var3_var3;
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR --replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
--error 1 --error 1
--exec echo "source $MYSQLTEST_VARDIR/tmp/recursive.sql;" | $MYSQL_TEST 2>&1 --exec echo "source $MYSQLTEST_VARDIR/tmp/recursive.sql;" | $MYSQL_TEST 2>&1
remove_file $MYSQLTEST_VARDIR/tmp/recursive.sql;
# Source a file with error # Source a file with error
--exec echo "garbage ;" > $MYSQLTEST_VARDIR/tmp/error.sql --exec echo "garbage ;" > $MYSQLTEST_VARDIR/tmp/error.sql
...@@ -793,6 +796,7 @@ echo $var3_var3; ...@@ -793,6 +796,7 @@ echo $var3_var3;
--error 1 --error 1
--exec echo "source $MYSQLTEST_VARDIR/tmp/error.sql;" | $MYSQL_TEST 2>&1 --exec echo "source $MYSQLTEST_VARDIR/tmp/error.sql;" | $MYSQL_TEST 2>&1
remove_file $MYSQLTEST_VARDIR/tmp/error.sql;
# Test execution of source in a while loop # Test execution of source in a while loop
--write_file $MYSQLTEST_VARDIR/tmp/sourced.inc --write_file $MYSQLTEST_VARDIR/tmp/sourced.inc
...@@ -1171,6 +1175,8 @@ EOF ...@@ -1171,6 +1175,8 @@ EOF
--error 1 --error 1
--exec $MYSQL_TEST < $MYSQLTEST_VARDIR/tmp/mysqltest.sql 2>&1 --exec $MYSQL_TEST < $MYSQLTEST_VARDIR/tmp/mysqltest.sql 2>&1
remove_file $MYSQLTEST_VARDIR/tmp/mysqltest.sql;
# ---------------------------------------------------------------------------- # ----------------------------------------------------------------------------
# Test error messages returned from comments starting with a command # Test error messages returned from comments starting with a command
# ---------------------------------------------------------------------------- # ----------------------------------------------------------------------------
...@@ -1296,6 +1302,8 @@ EOF ...@@ -1296,6 +1302,8 @@ EOF
--error 1 --error 1
--exec echo "source $MYSQLTEST_VARDIR/tmp/mysqltest.sql;" | $MYSQL_TEST 2>&1 --exec echo "source $MYSQLTEST_VARDIR/tmp/mysqltest.sql;" | $MYSQL_TEST 2>&1
remove_file $MYSQLTEST_VARDIR/tmp/mysqltest.sql;
# connect when "disable_abort_on_error" caused "connection not found" # connect when "disable_abort_on_error" caused "connection not found"
--replace_result $MASTER_MYSOCK MASTER_SOCKET $MASTER_MYPORT MASTER_PORT --replace_result $MASTER_MYSOCK MASTER_SOCKET $MASTER_MYPORT MASTER_PORT
--disable_abort_on_error --disable_abort_on_error
...@@ -1399,7 +1407,11 @@ select "this will be executed"; ...@@ -1399,7 +1407,11 @@ select "this will be executed";
--exec touch $MYSQLTEST_VARDIR/tmp/zero_length_file.result --exec touch $MYSQLTEST_VARDIR/tmp/zero_length_file.result
--exec echo "echo ok;" > $MYSQLTEST_VARDIR/tmp/query.sql --exec echo "echo ok;" > $MYSQLTEST_VARDIR/tmp/query.sql
--error 1 --error 1
--exec $MYSQL_TEST -x $MYSQLTEST_VARDIR/tmp/query.sql -R $MYSQLTEST_VARDIR/tmp/zero_length_file.result 2>&1 --exec $MYSQL_TEST -x $MYSQLTEST_VARDIR/tmp/query.sql -R $MYSQLTEST_VARDIR/tmp/zero_length_file.result > /dev/null 2>&1
remove_file $MYSQLTEST_VARDIR/tmp/zero_length_file.result;
remove_file $MYSQLTEST_VARDIR/tmp/zero_length_file.reject;
# #
# Test that a test file that does not generate any output fails. # Test that a test file that does not generate any output fails.
# #
...@@ -1407,6 +1419,8 @@ select "this will be executed"; ...@@ -1407,6 +1419,8 @@ select "this will be executed";
--error 1 --error 1
--exec $MYSQL_TEST -x $MYSQLTEST_VARDIR/tmp/query.sql 2>&1 --exec $MYSQL_TEST -x $MYSQLTEST_VARDIR/tmp/query.sql 2>&1
remove_file $MYSQLTEST_VARDIR/tmp/query.sql;
# #
# Test that mysqltest fails when there are no queries executed # Test that mysqltest fails when there are no queries executed
# but a result file exists # but a result file exists
...@@ -1436,6 +1450,7 @@ echo Failing multi statement query; ...@@ -1436,6 +1450,7 @@ echo Failing multi statement query;
--exec $MYSQL_TEST -x $MYSQLTEST_VARDIR/tmp/bug11731.sql 2>&1 --exec $MYSQL_TEST -x $MYSQLTEST_VARDIR/tmp/bug11731.sql 2>&1
drop table t1; drop table t1;
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
--error 1 --error 1
--exec $MYSQL_TEST --record -x $MYSQLTEST_VARDIR/tmp/bug11731.sql -R $MYSQLTEST_VARDIR/tmp/bug11731.out 2>&1 --exec $MYSQL_TEST --record -x $MYSQLTEST_VARDIR/tmp/bug11731.sql -R $MYSQLTEST_VARDIR/tmp/bug11731.out 2>&1
# The .out file should be non existent # The .out file should be non existent
...@@ -1462,6 +1477,9 @@ drop table t1; ...@@ -1462,6 +1477,9 @@ drop table t1;
# The .out file should exist # The .out file should exist
--exec test -s $MYSQLTEST_VARDIR/tmp/bug11731.out --exec test -s $MYSQLTEST_VARDIR/tmp/bug11731.out
drop table t1; drop table t1;
remove_file $MYSQLTEST_VARDIR/tmp/bug11731.out;
remove_file $MYSQLTEST_VARDIR/tmp/bug11731.log;
remove_file $MYSQLTEST_VARDIR/tmp/bug11731.sql;
# #
# Bug#19890 mysqltest: "query" command is broken # Bug#19890 mysqltest: "query" command is broken
...@@ -1607,19 +1625,48 @@ for diff_file command ...@@ -1607,19 +1625,48 @@ for diff_file command
of mysqltest of mysqltest
EOF EOF
--write_file $MYSQLTEST_VARDIR/tmp/diff4.tmp
Some data
for diff_file command
of musqltest
EOF
# Compare equal files # Compare equal files
--diff_files $MYSQLTEST_VARDIR/tmp/diff1.tmp $MYSQLTEST_VARDIR/tmp/diff2.tmp --diff_files $MYSQLTEST_VARDIR/tmp/diff1.tmp $MYSQLTEST_VARDIR/tmp/diff2.tmp
--diff_files $MYSQLTEST_VARDIR/tmp/diff2.tmp $MYSQLTEST_VARDIR/tmp/diff1.tmp --diff_files $MYSQLTEST_VARDIR/tmp/diff2.tmp $MYSQLTEST_VARDIR/tmp/diff1.tmp
# Compare files that differ # Write the below commands to a intermediary file and execute them with
# mysqltest in --exec, since the output will vary depending on what "diff"
# is available it is sent to /dev/null
--write_file $MYSQLTEST_VARDIR/tmp/diff.test
# Compare files that differ in size
--error 2
--diff_files $MYSQLTEST_VARDIR/tmp/diff1.tmp $MYSQLTEST_VARDIR/tmp/diff3.tmp
--error 2
--diff_files $MYSQLTEST_VARDIR/tmp/diff3.tmp $MYSQLTEST_VARDIR/tmp/diff1.tmp
# Compare files that differ only in content
--error 1 --error 1
--diff_files $MYSQLTEST_VARDIR/tmp/diff3.tmp $MYSQLTEST_VARDIR/tmp/diff2.tmp --diff_files $MYSQLTEST_VARDIR/tmp/diff1.tmp $MYSQLTEST_VARDIR/tmp/diff4.tmp
--error 1 --error 1
--diff_files $MYSQLTEST_VARDIR/tmp/diff1.tmp $MYSQLTEST_VARDIR/tmp/diff3.tmp --diff_files $MYSQLTEST_VARDIR/tmp/diff4.tmp $MYSQLTEST_VARDIR/tmp/diff1.tmp
EOF
# Execute the above diffs, and send their output to /dev/null - only
# interesting to see that it returns correct error codes
--exec $MYSQL_TEST < $MYSQLTEST_VARDIR/tmp/diff.test > /dev/null 2>&1
# Compare equal files, again... # Compare equal files, again...
--diff_files $MYSQLTEST_VARDIR/tmp/diff1.tmp $MYSQLTEST_VARDIR/tmp/diff2.tmp --diff_files $MYSQLTEST_VARDIR/tmp/diff1.tmp $MYSQLTEST_VARDIR/tmp/diff2.tmp
--remove_file $MYSQLTEST_VARDIR/tmp/diff1.tmp
--remove_file $MYSQLTEST_VARDIR/tmp/diff2.tmp
--remove_file $MYSQLTEST_VARDIR/tmp/diff3.tmp
--remove_file $MYSQLTEST_VARDIR/tmp/diff4.tmp
--remove_file $MYSQLTEST_VARDIR/tmp/diff.test
# ---------------------------------------------------------------------------- # ----------------------------------------------------------------------------
# test for file_exist # test for file_exist
# ---------------------------------------------------------------------------- # ----------------------------------------------------------------------------
......
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