Commit 346e5659 authored by msvensson@pilot.(none)'s avatar msvensson@pilot.(none)

Merge bk-internal:/home/bk/mysql-5.1-maint

into  pilot.(none):/data/msvensson/mysql/mysql-5.1-new-maint
parents 76d173fa 2b8218d3
......@@ -468,6 +468,7 @@ static int run_query(const char *query, DYNAMIC_STRING *ds_res,
NULL);
my_close(fd, MYF(0));
my_delete(query_file_path, MYF(0));
DBUG_RETURN(ret);
}
......
......@@ -60,16 +60,10 @@
#define QUERY_SEND_FLAG 1
#define QUERY_REAP_FLAG 2
enum {
RESULT_OK= 0,
RESULT_CONTENT_MISMATCH= 1,
RESULT_LENGTH_MISMATCH= 2
};
enum {
OPT_SKIP_SAFEMALLOC=OPT_MAX_CLIENT_OPTION,
OPT_PS_PROTOCOL, OPT_SP_PROTOCOL, OPT_CURSOR_PROTOCOL, OPT_VIEW_PROTOCOL,
OPT_MAX_CONNECT_RETRIES, OPT_MARK_PROGRESS, OPT_LOG_DIR
OPT_MAX_CONNECT_RETRIES, OPT_MARK_PROGRESS, OPT_LOG_DIR, OPT_TAIL_LINES
};
static int record= 0, opt_sleep= -1;
......@@ -103,6 +97,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 my_end_arg= 0;
/* Number of lines of the result to include in failure report */
static uint opt_tail_lines= 0;
static char delimiter[MAX_DELIMITER_LENGTH]= ";";
static uint delimiter_length= 1;
......@@ -224,7 +221,7 @@ struct st_connection
#endif /*EMBEDDED_LIBRARY*/
};
struct st_connection connections[128];
struct st_connection* cur_con, *next_con, *connections_end;
struct st_connection* cur_con= NULL, *next_con, *connections_end;
/*
List of commands in mysqltest
......@@ -441,7 +438,6 @@ void free_tmp_sh_file();
void free_win_path_patterns();
#endif
static int eval_result = 0;
/* For replace_column */
static char *replace_column[MAX_COLUMNS];
......@@ -489,11 +485,11 @@ void handle_no_error(struct st_command*);
pthread_attr_t cn_thd_attrib;
/*
send_one_query executes query in separate thread what is
send_one_query executes query in separate thread, which is
necessary in embedded library to run 'send' in proper way.
This implementation doesn't handle errors returned
by mysql_send_query. It's technically possible, though
i don't see where it is needed.
I don't see where it is needed.
*/
pthread_handler_t send_one_query(void *arg)
{
......@@ -594,6 +590,77 @@ void do_eval(DYNAMIC_STRING *query_eval, const char *query,
}
/*
Show any warnings just before the error. Since the last error
is added to the warning stack, only print @@warning_count-1 warnings.
NOTE! This function should be safe to call when an error
has occured and this any further errors will be ignored(although logged)
SYNOPSIS
show_warnings_before_error
mysql - connection to use
*/
static void show_warnings_before_error(MYSQL* mysql)
{
MYSQL_RES* res;
const char* query= "SHOW WARNINGS";
DBUG_ENTER("show_warnings_before_error");
if (!mysql)
DBUG_VOID_RETURN;
if (mysql_query(mysql, query))
{
log_msg("Error running query '%s': %d %s",
query, mysql_errno(mysql), mysql_error(mysql));
DBUG_VOID_RETURN;
}
if ((res= mysql_store_result(mysql)) == NULL)
{
/* No result set returned */
DBUG_VOID_RETURN;
}
if (mysql_num_rows(res) <= 1)
{
/* Don't display the last row, it's "last error" */
}
else
{
MYSQL_ROW row;
unsigned int row_num= 0;
unsigned int num_fields= mysql_num_fields(res);
fprintf(stderr, "\nWarnings from just before the error:\n");
while ((row= mysql_fetch_row(res)))
{
unsigned int i;
unsigned long *lengths= mysql_fetch_lengths(res);
if (++row_num >= mysql_num_rows(res))
{
/* Don't display the last row, it's "last error" */
break;
}
for(i= 0; i < num_fields; i++)
{
fprintf(stderr, "%.*s ", (int)lengths[i],
row[i] ? row[i] : "NULL");
}
fprintf(stderr, "\n");
}
}
mysql_free_result(res);
DBUG_VOID_RETURN;
}
enum arg_type
{
ARG_STRING,
......@@ -672,6 +739,15 @@ void check_command_args(struct st_command *command,
command->first_word_len, command->query);
}
/* Check for too many arguments passed */
ptr= command->last_argument;
while(ptr <= command->end)
{
if (*ptr && *ptr != ' ')
die("Extra argument '%s' passed to '%.*s'",
ptr, command->first_word_len, command->query);
ptr++;
}
DBUG_VOID_RETURN;
}
......@@ -865,6 +941,24 @@ void die(const char *fmt, ...)
fprintf(stderr, "\n");
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 */
if (result_file_name && ds_res.length)
dump_result_to_log_file(ds_res.str, ds_res.length);
......@@ -873,6 +967,13 @@ void die(const char *fmt, ...)
if (result_file_name && ds_warning_messages.length)
dump_warning_messages();
/*
Help debugging by displaying any warnings that might have
been produced prior to the error
*/
if (cur_con)
show_warnings_before_error(&cur_con->mysql);
cleanup_and_exit(1);
}
......@@ -976,11 +1077,10 @@ void warning_msg(const char *fmt, ...)
void log_msg(const char *fmt, ...)
{
va_list args;
char buff[512];
char buff[1024];
size_t len;
DBUG_ENTER("log_msg");
memset(buff, 0, sizeof(buff));
va_start(args, fmt);
len= my_vsnprintf(buff, sizeof(buff)-1, fmt, args);
va_end(args);
......@@ -993,77 +1093,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;
DYNAMIC_STRING res_ds;
DBUG_ENTER("dyn_string_cmp");
uint len;
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, (uchar*)&buff,
sizeof(buff), MYF(0))) > 0)
{
char *p= buff, *start= buff;
while (p < buff+len)
{
strxmov(eval_file, opt_basedir, fname, NullS);
fn_format(eval_file, eval_file, "", "", MY_UNPACK_FILENAME);
/* 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
fn_format(eval_file, fname, "", "", MY_UNPACK_FILENAME);
p++;
}
/* Output any chars that migh be left */
dynstr_append_mem(ds, start, p-start);
}
my_close(fd, MYF(0));
}
if (!my_stat(eval_file, &stat_info, MYF(MY_WME)))
die(NullS);
if (!eval_result && (uint) stat_info.st_size != ds->length)
/*
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))
{
DBUG_PRINT("info", ("buf: %s", buf));
if(ds_res)
{
/* Save the output of this command in the supplied string */
dynstr_append(ds_res, buf);
}
else
{
DBUG_PRINT("info",("Size differs: result size: %u file size: %lu",
(uint) ds->length, (ulong) stat_info.st_size));
DBUG_PRINT("info",("result: '%s'", ds->str));
DBUG_RETURN(RESULT_LENGTH_MISMATCH);
/* Print it directly on screen */
fprintf(stdout, "%s", buf);
}
if (!(tmp = (char*) my_malloc(stat_info.st_size + 1, MYF(MY_WME))))
}
error= pclose(res_file);
return WEXITSTATUS(error);
}
/*
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");
if ((fd = my_open(eval_file, O_RDONLY, MYF(MY_WME))) < 0)
die("Failed to open file %s", eval_file);
if (my_read(fd, (uchar*)tmp, stat_info.st_size, MYF(MY_WME|MY_NABP)))
die("Failed to read from file %s, errno: %d", eval_file, errno);
tmp[stat_info.st_size] = 0;
init_dynamic_string(&res_ds, "", stat_info.st_size+256, 256);
if (eval_result)
dynstr_append_os_quoted(&ds_cmdline, tool_path, NullS);
dynstr_append(&ds_cmdline, " ");
va_start(args, ds_res);
while ((arg= va_arg(args, char *)))
{
do_eval(&res_ds, tmp, tmp + stat_info.st_size, FALSE);
res_ptr= res_ds.str;
res_len= res_ds.length;
if (res_len != ds->length)
/* Options should be os quoted */
if (strncmp(arg, "--", 2) == 0)
dynstr_append_os_quoted(&ds_cmdline, arg, NullS);
else
dynstr_append(&ds_cmdline, arg);
dynstr_append(&ds_cmdline, " ");
}
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");
/* First try with unified diff */
if (run_tool("diff",
&ds_tmp, /* Get output from diff in ds_tmp */
"-u",
filename1,
filename2,
"2>&1",
NULL) > 1) /* Most "diff" tools return >1 if error */
{
dynstr_set(&ds_tmp, "");
/* 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
{
res_ptr = tmp;
res_len = stat_info.st_size;
/* Print diff directly to stdout */
fprintf(stderr, "%s\n", ds_tmp.str);
}
res= (memcmp(res_ptr, ds->str, res_len)) ?
RESULT_CONTENT_MISMATCH : RESULT_OK;
dynstr_free(&ds_tmp);
err:
if (res && eval_result)
str_to_file(fn_format(eval_file, fname, "", ".eval",
MY_REPLACE_EXT),
res_ptr, res_len);
}
enum compare_files_result_enum {
RESULT_OK= 0,
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
dynstr_free(&res_ds);
my_free(tmp, MYF(0));
my_close(fd, MYF(MY_WME));
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];
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, (uchar*)&buff,
sizeof(buff), MYF(0))) > 0)
{
if ((len2= my_read(fd2, (uchar*)&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, (uchar*)&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;
DBUG_RETURN(res);
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 temp_file_path[FN_REFLEN];
DBUG_ENTER("dyn_string_cmp");
DBUG_PRINT("enter", ("fname: %s", fname));
if ((fd= create_temp_file(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(temp_file_path, MYF(0));
die("Failed to write file '%s'", temp_file_path);
}
error= compare_files2(fd, fname);
my_close(fd, MYF(0));
/* Remove the temporary file */
my_delete(temp_file_path, MYF(0));
DBUG_RETURN(error);
}
......@@ -1081,20 +1476,39 @@ int dyn_string_cmp(DYNAMIC_STRING* ds, const char *fname)
void check_result(DYNAMIC_STRING* ds)
{
const char* mess= "Result content mismatch\n";
DBUG_ENTER("check_result");
DBUG_ASSERT(result_file_name);
DBUG_PRINT("enter", ("result_file_name: %s", result_file_name));
if (access(result_file_name, F_OK) != 0)
die("The specified result file does not exist: '%s'", result_file_name);
switch (dyn_string_cmp(ds, result_file_name)) {
case RESULT_OK:
break; /* ok */
case RESULT_LENGTH_MISMATCH:
dump_result_to_reject_file(ds->str, ds->length);
die("Result length mismatch");
break;
mess= "Result length mismatch\n";
/* Fallthrough */
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];
str_to_file(fn_format(reject_file, result_file_name, opt_logdir, ".reject",
*opt_logdir ? MY_REPLACE_DIR | MY_REPLACE_EXT :
MY_REPLACE_EXT),
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;
}
default: /* impossible */
die("Unknown error code from dyn_string_cmp()");
}
......@@ -1109,7 +1523,7 @@ void check_result(DYNAMIC_STRING* ds)
indicating that test is not supported
SYNOPSIS
check_result
check_require
ds - content to be checked
fname - name of file to check against
......@@ -1439,40 +1853,22 @@ void var_query_set(VAR *var, const char *query, const char** query_end)
die("Query '%s' didn't return a result set", ds_query.str);
dynstr_free(&ds_query);
if ((row = mysql_fetch_row(res)) && row[0])
if ((row= mysql_fetch_row(res)) && row[0])
{
/*
Concatenate all row results with tab in between to allow us to work
with results from many columns (for example from SHOW VARIABLES)
Concatenate all fields in the first row with tab in between
and assign that string to the $variable
*/
DYNAMIC_STRING result;
uint i;
ulong *lengths;
#ifdef NOT_YET
MYSQL_FIELD *fields= mysql_fetch_fields(res);
#endif
init_dynamic_string(&result, "", 2048, 2048);
init_dynamic_string(&result, "", 512, 512);
lengths= mysql_fetch_lengths(res);
for (i=0; i < mysql_num_fields(res); i++)
for (i= 0; i < mysql_num_fields(res); i++)
{
if (row[0])
if (row[i])
{
#ifdef NOT_YET
/* Add to <var_name>_<col_name> */
uint j;
char var_col_name[MAX_VAR_NAME_LENGTH];
uint length= snprintf(var_col_name, MAX_VAR_NAME_LENGTH,
"$%s_%s", var->name, fields[i].name);
/* Convert characters not allowed in variable names to '_' */
for (j= 1; j < length; j++)
{
if (!my_isvar(charset_info,var_col_name[j]))
var_col_name[j]= '_';
}
var_set(var_col_name, var_col_name + length,
row[i], row[i] + lengths[i]);
#endif
/* Add column to tab separated string */
dynstr_append_mem(&result, row[i], lengths[i]);
}
......@@ -1514,7 +1910,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)
{
ulong row_no;
long row_no;
int col_no= -1;
MYSQL_RES* res;
MYSQL* mysql= &cur_con->mysql;
......@@ -1586,7 +1982,7 @@ void var_set_query_get_value(struct st_command *command, VAR *var)
{
/* Get the value */
MYSQL_ROW row;
ulong rows= 0;
long rows= 0;
const char* value= "No such row";
while ((row= mysql_fetch_row(res)))
......@@ -1715,7 +2111,7 @@ int open_file(const char *name)
if (!(cur_file->file = my_fopen(buff, O_RDONLY | FILE_BINARY, MYF(0))))
{
cur_file--;
die("Could not open file %s", buff);
die("Could not open file '%s'", buff);
}
cur_file->file_name= my_strdup(buff, MYF(MY_FAE));
cur_file->lineno=1;
......@@ -1953,7 +2349,7 @@ void do_exec(struct st_command *command)
if (command->abort_on_error)
{
log_msg("exec of '%s failed, error: %d, status: %d, errno: %d",
log_msg("exec of '%s' failed, error: %d, status: %d, errno: %d",
ds_cmd.str, error, status, errno);
dynstr_free(&ds_cmd);
die("command \"%s\" failed", command->first_argument);
......@@ -2196,8 +2592,8 @@ void do_copy_file(struct st_command *command)
command command handle
DESCRIPTION
chmod <octal> <file>
Change file permission of <file>
chmod_file <octal> <file_name>
Change file permission of <file_name>
*/
......@@ -2207,8 +2603,8 @@ void do_chmod_file(struct st_command *command)
static DYNAMIC_STRING ds_mode;
static DYNAMIC_STRING ds_file;
const struct command_arg chmod_file_args[] = {
{ "mode", ARG_STRING, TRUE, &ds_mode, "Mode of file" },
{ "file", ARG_STRING, TRUE, &ds_file, "Filename of file to modify" }
{ "mode", ARG_STRING, TRUE, &ds_mode, "Mode of file(octal) ex. 0660"},
{ "filename", ARG_STRING, TRUE, &ds_file, "Filename of file to modify" }
};
DBUG_ENTER("do_chmod_file");
......@@ -2303,8 +2699,22 @@ void read_until_delimiter(DYNAMIC_STRING *ds,
c= my_getc(cur_file->file);
if (c == '\n')
{
cur_file->lineno++;
/* Skip newline from the same line as the command */
if (start_lineno == (cur_file->lineno - 1))
continue;
}
else if (start_lineno == cur_file->lineno)
{
/*
No characters except \n are allowed on
the same line as the command
*/
die("Trailing characters found after command");
}
if (feof(cur_file->file))
die("End of file encountered before '%s' delimiter was found",
ds_delimiter->str);
......@@ -2342,6 +2752,12 @@ void do_write_file_command(struct st_command *command, my_bool append)
if (ds_delimiter.length == 0)
dynstr_set(&ds_delimiter, "EOF");
if (!append && access(ds_filename.str, F_OK) == 0)
{
/* The file should not be overwritten */
die("File already exist: '%s'", ds_filename.str);
}
init_dynamic_string(&ds_content, "", 1024, 1024);
read_until_delimiter(&ds_content, &ds_delimiter);
DBUG_PRINT("info", ("Writing to file: %s", ds_filename.str));
......@@ -2374,7 +2790,7 @@ void do_write_file_command(struct st_command *command, my_bool append)
Write everything between the "write_file" command and 'delimiter'
to "file_name"
NOTE! Overwrites existing file
NOTE! Will fail if <file_name> exists
Default <delimiter> is EOF
......@@ -2431,9 +2847,6 @@ void do_append_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;
const struct command_arg cat_file_args[] = {
{ "filename", ARG_STRING, TRUE, &ds_filename, "File to read from" }
......@@ -2448,37 +2861,13 @@ void do_cat_file(struct st_command *command)
DBUG_PRINT("info", ("Reading from, file: %s", ds_filename.str));
if ((fd= my_open(ds_filename.str, O_RDONLY, MYF(0))) < 0)
die("Failed to open file %s", ds_filename.str);
while((len= my_read(fd, (uchar*)&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));
cat_file(&ds_res, ds_filename.str);
dynstr_free(&ds_filename);
DBUG_VOID_RETURN;
}
/*
SYNOPSIS
do_diff_files
......@@ -2494,9 +2883,6 @@ void do_cat_file(struct st_command *command)
void do_diff_files(struct st_command *command)
{
int error= 0;
int fd, fd2;
uint len, len2;
char buff[512], buff2[512];
static DYNAMIC_STRING ds_filename;
static DYNAMIC_STRING ds_filename2;
const struct command_arg diff_file_args[] = {
......@@ -2511,39 +2897,14 @@ void do_diff_files(struct st_command *command)
sizeof(diff_file_args)/sizeof(struct command_arg),
' ');
if ((fd= my_open(ds_filename.str, O_RDONLY, MYF(0))) < 0)
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, (uchar*)&buff,
sizeof(buff), MYF(0))) > 0)
{
if ((len2= my_read(fd2, (uchar*)&buff2,
sizeof(buff2), MYF(0))) != len)
{
/* File 2 was smaller */
error= 1;
break;
}
if ((memcmp(buff, buff2, len)))
if ((error= compare_files(ds_filename.str, ds_filename2.str)))
{
/* Content of this part differed */
error= 1;
break;
}
}
if (my_read(fd2, (uchar*)&buff2,
sizeof(buff2), MYF(0)) > 0)
{
/* File 1 was smaller */
error= 1;
/* Compare of the two files failed, append them to output
so the failure can be analyzed
*/
show_diff(&ds_res, ds_filename.str, ds_filename2.str);
}
my_close(fd, MYF(0));
my_close(fd2, MYF(0));
dynstr_free(&ds_filename);
dynstr_free(&ds_filename2);
handle_command_error(command, error);
......@@ -2614,8 +2975,10 @@ void do_send_quit(struct st_command *command)
void do_perl(struct st_command *command)
{
int error;
char buf[FN_REFLEN];
File fd;
FILE *res_file;
char buf[FN_REFLEN];
char temp_file_path[FN_REFLEN];
static DYNAMIC_STRING ds_script;
static DYNAMIC_STRING ds_delimiter;
const struct command_arg perl_args[] = {
......@@ -2638,14 +3001,17 @@ void do_perl(struct st_command *command)
DBUG_PRINT("info", ("Executing perl: %s", ds_script.str));
/* Format a name for a tmp .pl file that is unique for this process */
my_snprintf(buf, sizeof(buf), "%s/tmp/tmp_%d.pl",
getenv("MYSQLTEST_VARDIR"), getpid());
str_to_file(buf, ds_script.str, ds_script.length);
/* Create temporary file name */
if ((fd= create_temp_file(temp_file_path, getenv("MYSQLTEST_VARDIR"),
"tmp", O_CREAT | O_SHARE | O_RDWR,
MYF(MY_WME))) < 0)
die("Failed to create temporary file for perl command");
my_close(fd, MYF(0));
str_to_file(temp_file_path, ds_script.str, ds_script.length);
/* Format the perl <filename> command */
my_snprintf(buf, sizeof(buf), "perl %s/tmp/tmp_%d.pl",
getenv("MYSQLTEST_VARDIR"), getpid());
/* Format the "perl <filename>" command */
my_snprintf(buf, sizeof(buf), "perl %s", temp_file_path);
if (!(res_file= popen(buf, "r")) && command->abort_on_error)
die("popen(\"%s\", \"r\") failed", buf);
......@@ -2663,6 +3029,10 @@ void do_perl(struct st_command *command)
}
}
error= pclose(res_file);
/* Remove the temporary file */
my_delete(temp_file_path, MYF(0));
handle_command_error(command, WEXITSTATUS(error));
dynstr_free(&ds_script);
dynstr_free(&ds_delimiter);
......@@ -3788,7 +4158,7 @@ void do_connect(struct st_command *command)
mysql_options(&con_slot->mysql, MYSQL_SET_CHARSET_NAME,
charset_info->csname);
if (opt_charsets_dir)
mysql_options(&cur_con->mysql, MYSQL_SET_CHARSET_DIR,
mysql_options(&con_slot->mysql, MYSQL_SET_CHARSET_DIR,
opt_charsets_dir);
#ifdef HAVE_OPENSSL
......@@ -4401,7 +4771,7 @@ void check_eol_junk(const char *eol)
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];
int read_command(struct st_command** command_ptr)
......@@ -4449,9 +4819,13 @@ int read_command(struct st_command** command_ptr)
if (!(command->query_buf= command->query= my_strdup(p, MYF(MY_WME))))
die("Out of memory");
/* Calculate first word and first argument */
for (p= command->query; *p && !my_isspace(charset_info, *p) ; p++) ;
/* Calculate first word length(the command), terminated by space or ( */
p= command->query;
while (*p && !my_isspace(charset_info, *p) && *p != '(')
p++;
command->first_word_len= (uint) (p - command->query);
DBUG_PRINT("info", ("first_word: %.*s",
command->first_word_len, command->query));
/* Skip spaces between command and first argument */
while (*p && my_isspace(charset_info, *p))
......@@ -4541,6 +4915,10 @@ static struct my_option my_long_options[] =
{"sp-protocol", OPT_SP_PROTOCOL, "Use stored procedures for select",
(uchar**) &sp_protocol, (uchar**) &sp_protocol, 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",
(uchar**) &opt_tail_lines, (uchar**) &opt_tail_lines, 0,
GET_INT, REQUIRED_ARG, 0, 0, 10000, 0, 0, 0},
#include "sslopt-longopts.h"
{"test-file", 'x', "Read test from/in this file (default stdin).",
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
......@@ -4607,7 +4985,7 @@ void read_embedded_server_arguments(const char *name)
embedded_server_args[0]= (char*) ""; /* Progname */
}
if (!(file=my_fopen(buff, O_RDONLY | FILE_BINARY, MYF(MY_WME))))
die("Failed to open file %s", buff);
die("Failed to open file '%s'", buff);
while (embedded_server_arg_count < MAX_EMBEDDED_SERVER_ARGS &&
(str=fgets(argument,sizeof(argument), file)))
......@@ -4797,14 +5175,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)
{
char log_file[FN_REFLEN];
......@@ -4812,6 +5182,8 @@ void dump_result_to_log_file(char *buf, int size)
*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)
......@@ -5793,7 +6165,7 @@ void run_query(struct st_connection *cn, struct st_command *command, int flags)
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);
/*
......@@ -6225,7 +6597,6 @@ int main(int argc, char **argv)
connections_end= connections +
(sizeof(connections)/sizeof(struct st_connection)) - 1;
next_con= connections + 1;
cur_con= connections;
#ifdef EMBEDDED_LIBRARY
/* set appropriate stack for the 'query' threads */
......@@ -6301,6 +6672,7 @@ int main(int argc, char **argv)
if (cursor_protocol_enabled)
ps_protocol_enabled= 1;
cur_con= connections;
if (!( mysql_init(&cur_con->mysql)))
die("Failed in mysql_init()");
if (opt_compress)
......@@ -6425,7 +6797,7 @@ int main(int argc, char **argv)
break;
case Q_LET: do_let(command); break;
case Q_EVAL_RESULT:
eval_result = 1; break;
die("'eval_result' command is deprecated");
case Q_EVAL:
case Q_QUERY_VERTICAL:
case Q_QUERY_HORIZONTAL:
......
......@@ -99,25 +99,26 @@ sub spawn_impl ($$$$$$$) {
if ( $::opt_script_debug )
{
print STDERR "\n";
print STDERR "#### ", "-" x 78, "\n";
print STDERR "#### ", "STDIN $input\n" if $input;
print STDERR "#### ", "STDOUT $output\n" if $output;
print STDERR "#### ", "STDERR $error\n" if $error;
print STDERR "#### ", "$mode : $path ", join(" ",@$arg_list_t), "\n";
print STDERR "#### ", "spawn options:\n";
mtr_report("");
mtr_debug("-" x 73);
mtr_debug("STDIN $input") if $input;
mtr_debug("STDOUT $output") if $output;
mtr_debug("STDERR $error") if $error;
mtr_debug("$mode: $path ", join(" ",@$arg_list_t));
mtr_debug("spawn options:");
if ($spawn_opts)
{
foreach my $key (sort keys %{$spawn_opts})
{
print STDERR "#### ", " - $key: $spawn_opts->{$key}\n";
mtr_debug(" - $key: $spawn_opts->{$key}");
}
}
else
{
print STDERR "#### ", " none\n";
mtr_debug(" none");
}
print STDERR "#### ", "-" x 78, "\n";
mtr_debug("-" x 73);
mtr_report("");
}
mtr_error("Can't spawn with empty \"path\"") unless defined $path;
......
......@@ -19,6 +19,7 @@
# same name.
use strict;
use warnings;
sub mtr_report_test_name($);
sub mtr_report_test_passed($);
......@@ -26,7 +27,6 @@ sub mtr_report_test_failed($);
sub mtr_report_test_skipped($);
sub mtr_report_test_not_skipped_though_disabled($);
sub mtr_show_failed_diff ($);
sub mtr_report_stats ($);
sub mtr_print_line ();
sub mtr_print_thick_line ();
......@@ -38,6 +38,9 @@ sub mtr_child_error (@);
sub mtr_debug (@);
sub mtr_verbose (@);
my $tot_real_time= 0;
##############################################################################
#
......@@ -45,43 +48,10 @@ sub mtr_verbose (@);
#
##############################################################################
# We can't use diff -u or diff -a as these are not portable
sub mtr_show_failed_diff ($) {
my $tinfo= shift;
# The reject and log files have been dumped to
# to filenames based on the result_file's name
my $base_file= mtr_match_extension($tinfo->{'result_file'},
"result"); # Trim extension
my $reject_file= "$base_file.reject";
my $result_file= "$base_file.result";
my $log_file= "$base_file.log";
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 ($) {
my $tinfo= shift;
_mtr_log("$tinfo->{name}");
printf "%-30s ", $tinfo->{'name'};
}
......@@ -91,15 +61,15 @@ sub mtr_report_test_skipped ($) {
$tinfo->{'result'}= 'MTR_RES_SKIPPED';
if ( $tinfo->{'disable'} )
{
print "[ disabled ] $tinfo->{'comment'}\n";
mtr_report("[ disabled ] $tinfo->{'comment'}");
}
elsif ( $tinfo->{'comment'} )
{
print "[ skipped ] $tinfo->{'comment'}\n";
mtr_report("[ skipped ] $tinfo->{'comment'}");
}
else
{
print "[ skipped ]\n";
mtr_report("[ skipped ]");
}
}
......@@ -127,11 +97,11 @@ sub mtr_report_test_passed ($) {
if ( $::opt_timer and -f "$::opt_vardir/log/timer" )
{
$timer= mtr_fromfile("$::opt_vardir/log/timer");
$::glob_tot_real_time += ($timer/1000);
$tot_real_time += ($timer/1000);
$timer= sprintf "%12s", $timer;
}
$tinfo->{'result'}= 'MTR_RES_PASSED';
print "[ pass ] $timer\n";
mtr_report("[ pass ] $timer");
}
sub mtr_report_test_failed ($) {
......@@ -140,27 +110,34 @@ sub mtr_report_test_failed ($) {
$tinfo->{'result'}= 'MTR_RES_FAILED';
if ( defined $tinfo->{'timeout'} )
{
print "[ fail ] timeout\n";
mtr_report("[ fail ] timeout");
return;
}
else
{
print "[ fail ]\n";
mtr_report("[ fail ]");
}
if ( $tinfo->{'comment'} )
{
print "\nERROR: $tinfo->{'comment'}\n";
# 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"
mtr_report("\nERROR: $tinfo->{'comment'}");
}
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 "\n(the last lines may be the most important ones)\n";
print "\n";
}
else
{
print "\nUnexpected termination, probably when starting mysqld\n";
# Neither this script or the test tool has recorded info
# about why the test has failed. Should be debugged.
mtr_report("\nUnexpected termination, probably when starting mysqld");;
}
}
......@@ -228,8 +205,10 @@ sub mtr_report_stats ($) {
if ( $::opt_timer )
{
print
"Spent $::glob_tot_real_time seconds actually executing testcases\n"
use English;
mtr_report("Spent", sprintf("%.3f", $tot_real_time),"of",
time - $BASETIME, "seconds executing testcases");
}
# ----------------------------------------------------------------------
......@@ -484,35 +463,66 @@ sub mtr_print_header () {
##############################################################################
#
# Misc
# Log and reporting functions
#
##############################################################################
use IO::File;
my $log_file_ref= undef;
sub mtr_log_init ($) {
my ($filename)= @_;
mtr_error("Log is already open") if defined $log_file_ref;
$log_file_ref= IO::File->new($filename, "a") or
mtr_warning("Could not create logfile $filename: $!");
}
sub _mtr_log (@) {
print $log_file_ref join(" ", @_),"\n"
if defined $log_file_ref;
}
sub mtr_report (@) {
# Print message to screen and log
_mtr_log(@_);
print join(" ", @_),"\n";
}
sub mtr_warning (@) {
# Print message to screen and log
_mtr_log("WARNING: ", @_);
print STDERR "mysql-test-run: WARNING: ",join(" ", @_),"\n";
}
sub mtr_error (@) {
# Print message to screen and log
_mtr_log("ERROR: ", @_);
print STDERR "mysql-test-run: *** ERROR: ",join(" ", @_),"\n";
mtr_exit(1);
}
sub mtr_child_error (@) {
# Print message to screen and log
_mtr_log("ERROR(child): ", @_);
print STDERR "mysql-test-run: *** ERROR(child): ",join(" ", @_),"\n";
exit(1);
}
sub mtr_debug (@) {
# Only print if --script-debug is used
if ( $::opt_script_debug )
{
_mtr_log("###: ", @_);
print STDERR "####: ",join(" ", @_),"\n";
}
}
sub mtr_verbose (@) {
# Always print to log, print to screen only when --verbose is used
_mtr_log("> ",@_);
if ( $::opt_verbose )
{
print STDERR "> ",join(" ", @_),"\n";
......
......@@ -52,12 +52,10 @@ sub mtr_init_timers () {
sub mtr_timer_start($$$) {
my ($timers,$name,$duration)= @_;
mtr_verbose("mtr_timer_start: $name, $duration");
if ( exists $timers->{'timers'}->{$name} )
{
# We have an old running timer, kill it
mtr_verbose("There is an old timer running");
mtr_warning("There is an old timer running");
mtr_timer_stop($timers,$name);
}
......@@ -75,22 +73,22 @@ sub mtr_timer_start($$$) {
}
else
{
mtr_error("can't fork");
mtr_error("can't fork timer, error: $!");
}
}
if ( $tpid )
{
# Parent, record the information
mtr_verbose("timer parent, record info($name, $tpid, $duration)");
mtr_verbose("Starting timer for '$name',",
"duration: $duration, pid: $tpid");
$timers->{'timers'}->{$name}->{'pid'}= $tpid;
$timers->{'timers'}->{$name}->{'duration'}= $duration;
$timers->{'pids'}->{$tpid}= $name;
}
else
{
# Child, redirect output and exec
# FIXME do we need to redirect streams?
# Child, install signal handlers and sleep for "duration"
# Don't do the ^C cleanup in the timeout child processes!
# There is actually a race here, if we get ^C after fork(), but before
......@@ -98,13 +96,13 @@ sub mtr_timer_start($$$) {
$SIG{INT}= 'DEFAULT';
$SIG{TERM}= sub {
mtr_verbose("timer woke up, exiting!");
mtr_verbose("timer $$ woke up, exiting!");
exit(0);
};
$0= "mtr_timer(timers,$name,$duration)";
sleep($duration);
mtr_verbose("timer expired after $duration seconds");
mtr_verbose("timer $$ expired after $duration seconds");
exit(0);
}
}
......@@ -114,12 +112,10 @@ sub mtr_timer_start($$$) {
sub mtr_timer_stop ($$) {
my ($timers,$name)= @_;
mtr_verbose("mtr_timer_stop: $name");
if ( exists $timers->{'timers'}->{$name} )
{
my $tpid= $timers->{'timers'}->{$name}->{'pid'};
mtr_verbose("Stopping timer with pid $tpid");
mtr_verbose("Stopping timer for '$name' with pid $tpid");
# FIXME as Cygwin reuses pids fast, maybe check that is
# the expected process somehow?!
......@@ -134,11 +130,8 @@ sub mtr_timer_stop ($$) {
return 1;
}
else
{
mtr_error("Asked to stop timer \"$name\" not started");
return 0;
}
mtr_error("Asked to stop timer '$name' not started");
}
......@@ -158,7 +151,8 @@ sub mtr_timer_timeout ($$) {
return "" unless exists $timers->{'pids'}->{$pid};
# We got a timeout, return the name ot the timer
# Got a timeout(the process with $pid is recorded as being a timer)
# return the name of the timer
return $timers->{'pids'}->{$pid};
}
......
......@@ -83,7 +83,6 @@ require "lib/mtr_io.pl";
require "lib/mtr_gcov.pl";
require "lib/mtr_gprof.pl";
require "lib/mtr_report.pl";
require "lib/mtr_diff.pl";
require "lib/mtr_match.pl";
require "lib/mtr_misc.pl";
require "lib/mtr_stress.pl";
......@@ -234,7 +233,6 @@ my $opt_report_features;
our $opt_check_testcases;
our $opt_mark_progress;
our $opt_skip;
our $opt_skip_rpl;
our $max_slave_num= 0;
our $max_master_num= 1;
......@@ -277,13 +275,8 @@ our $opt_stress_test_duration= 0;
our $opt_stress_init_file= "";
our $opt_stress_test_file= "";
our $opt_wait_for_master;
our $opt_wait_for_slave;
our $opt_warnings;
our $opt_udiff;
our $opt_skip_ndbcluster= 0;
our $opt_skip_ndbcluster_slave= 0;
our $opt_with_ndbcluster= 0;
......@@ -307,7 +300,6 @@ our @data_dir_lst;
our $used_binlog_format;
our $used_default_engine;
our $debug_compiled_binaries;
our $glob_tot_real_time= 0;
our %mysqld_variables;
......@@ -619,7 +611,6 @@ sub command_line_setup () {
'start-dirty' => \$opt_start_dirty,
'start-and-exit' => \$opt_start_and_exit,
'timer!' => \$opt_timer,
'unified-diff|udiff' => \$opt_udiff,
'user=s' => \$opt_user,
'testcase-timeout=i' => \$opt_testcase_timeout,
'suite-timeout=i' => \$opt_suite_timeout,
......@@ -2924,13 +2915,16 @@ sub initialize_servers () {
}
}
check_running_as_root();
mtr_log_init("$opt_vardir/log/mysql-test-run.log");
}
sub mysql_install_db () {
install_db('master', $master->[0]->{'path_myddir'});
if ($max_master_num)
if ($max_master_num > 1)
{
copy_install_db('master', $master->[1]->{'path_myddir'});
}
......@@ -3652,7 +3646,6 @@ sub report_failure_and_restart ($) {
my $tinfo= shift;
mtr_report_test_failed($tinfo);
mtr_show_failed_diff($tinfo);
print "\n";
if ( $opt_force )
{
......@@ -3661,13 +3654,13 @@ sub report_failure_and_restart ($) {
# Restore the snapshot of the installed test db
restore_installed_db($tinfo->{'name'});
print "Resuming Tests\n\n";
mtr_report("Resuming Tests\n");
return;
}
my $test_mode= join(" ", @::glob_test_mode) || "default";
print "Aborting: $tinfo->{'name'} failed in $test_mode mode. ";
print "To continue, re-run with '--force'.\n";
mtr_report("Aborting: $tinfo->{'name'} failed in $test_mode mode. ");
mtr_report("To continue, re-run with '--force'.");
if ( ! $glob_debugger and
! $opt_extern and
! $glob_use_embedded_server )
......@@ -4126,11 +4119,11 @@ sub mysqld_start ($$$) {
sub stop_all_servers () {
print "Stopping All Servers\n";
mtr_report("Stopping All Servers");
if ( ! $opt_skip_im )
{
print "Shutting-down Instance Manager\n";
mtr_report("Shutting-down Instance Manager");
unless (mtr_im_stop($instance_manager, "stop_all_servers"))
{
mtr_error("Failed to stop Instance Manager.")
......@@ -4840,6 +4833,9 @@ sub run_mysqltest ($) {
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'} ) {
mtr_add_arg($args, "--result-file=%s", $tinfo->{'result_file'});
}
......@@ -5253,7 +5249,6 @@ Misc options
fast Don't try to clean up from earlier runs
reorder Reorder tests to get fewer server restarts
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)
suite-timeout=MINUTES Max test suite run time (default $default_suite_timeout)
......
......@@ -280,8 +280,20 @@ let $B = changed value of B;
var2: content of variable 1
var3: content of variable 1 content of variable 1
length of var3 is longer than 0
var1
hi 1 hi there
var2
2
var2 again
2
var3 two columns with same name
1 2 3
var4 from query that returns NULL
var5 from query that returns no row
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: Missing required argument 'filename' to command 'source'
mysqltest: At line 1: Could not open file ./non_existingFile
mysqltest: At line 1: Could not open file './non_existingFile'
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
......@@ -340,6 +352,8 @@ here is the sourced script
In loop
here is the sourced script
here is the sourced script
"hello"
"hello"
mysqltest: At line 1: Missing argument to sleep
mysqltest: At line 1: Missing argument to real_sleep
mysqltest: At line 1: Invalid argument to sleep "abc"
......@@ -461,7 +475,6 @@ root@localhost
--------------------------------------------------------------------------------
this will be executed
this will be executed
mysqltest: Result length mismatch
mysqltest: The test didn't produce any output
Failing multi statement query
mysqltest: At line 3: query 'create table t1 (a int primary key);
......@@ -473,6 +486,8 @@ mysqltest: At line 3: query 'create table t1 (a int primary key);
insert into t1 values (1);
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
More results from queries before failure can be found in MYSQLTEST_VARDIR/log/bug11731.log
drop table t1;
Multi statement using expected error
create table t1 (a int primary key);
......@@ -520,17 +535,19 @@ drop table t1;
mysqltest: At line 1: Missing required argument 'filename' to command 'remove_file'
mysqltest: At line 1: Missing required argument 'filename' to command 'write_file'
mysqltest: At line 1: End of file encountered before 'EOF' delimiter was found
Content for test_file1
mysqltest: At line 1: File already exist: 'MYSQLTEST_VARDIR/tmp/test_file1.tmp'
Some data
for cat_file command
of mysqltest
mysqltest: At line 1: Failed to open file non_existing_file
mysqltest: At line 1: Failed to open file 'non_existing_file'
mysqltest: At line 1: Missing required argument 'filename' to command 'file_exists'
mysqltest: At line 1: Missing required argument 'from_file' to command 'copy_file'
mysqltest: At line 1: Missing required argument 'to_file' to command 'copy_file'
mysqltest: At line 1: Missing required argument 'mode' to command 'chmod'
mysqltest: At line 1: You must write a 4 digit octal number for mode
mysqltest: At line 1: You must write a 4 digit octal number for mode
mysqltest: At line 1: Missing required argument 'file' to command 'chmod'
mysqltest: At line 1: Missing required argument 'filename' to command 'chmod'
mysqltest: At line 1: You must write a 4 digit octal number for mode
mysqltest: At line 1: You must write a 4 digit octal number for mode
hello
......
......@@ -9,12 +9,13 @@ drop table if exists t1;
#
# Check that --bootstrap reads from stdin
#
--write_file $MYSQLTEST_VARDIR/tmp/bootstrap.sql
--write_file $MYSQLTEST_VARDIR/tmp/bootstrap_test.sql
use test;
CREATE TABLE t1(a int);
EOF
--exec $MYSQLD_BOOTSTRAP_CMD < $MYSQLTEST_VARDIR/tmp/bootstrap.sql >> $MYSQLTEST_VARDIR/tmp/bootstrap.log 2>&1
--exec $MYSQLD_BOOTSTRAP_CMD < $MYSQLTEST_VARDIR/tmp/bootstrap_test.sql >> $MYSQLTEST_VARDIR/tmp/bootstrap.log 2>&1
drop table t1;
remove_file $MYSQLTEST_VARDIR/tmp/bootstrap_test.sql;
#
# Check that --bootstrap of file with SQL error returns error
......@@ -28,6 +29,7 @@ EOF
# Table t1 should not exists
--error 1051
drop table t1;
remove_file $MYSQLTEST_VARDIR/tmp/bootstrap_error.sql;
#
# Bootstrap with a query larger than 2*thd->net.max_packet
......@@ -40,6 +42,7 @@ eval select * into outfile '$MYSQLTEST_VARDIR/tmp/long_query.sql' from t1;
--enable_query_log
--error 1
--exec $MYSQLD_BOOTSTRAP_CMD < $MYSQLTEST_VARDIR/tmp/long_query.sql >> $MYSQLTEST_VARDIR/tmp/bootstrap.log 2>&1
remove_file $MYSQLTEST_VARDIR/tmp/long_query.sql;
set global max_allowed_packet=@my_max_allowed_packet;
drop table t1;
......
......@@ -1424,6 +1424,7 @@ DROP TABLE test_repair_table2;
# Corrupt csv file and see if we can repair it
CREATE TABLE test_repair_table3 ( val integer ) ENGINE = CSV;
--remove_file $MYSQLTEST_VARDIR/master-data/test/test_repair_table3.CSV
--write_file $MYSQLTEST_VARDIR/master-data/test/test_repair_table3.CSV
"1"
"4"
......@@ -1476,6 +1477,7 @@ CREATE TABLE test_repair_table5 (
) ENGINE = CSV;
# Corrupt a table -- put a file with wrong # of columns
--remove_file $MYSQLTEST_VARDIR/master-data/test/test_repair_table5.CSV
--write_file $MYSQLTEST_VARDIR/master-data/test/test_repair_table5.CSV
"1","101","IBM"
EOF
......@@ -1629,6 +1631,7 @@ insert into bug22080_1 values(2,'string');
insert into bug22080_1 values(3,'string');
# Create first corrupt file as described in bug report
--remove_file $MYSQLTEST_VARDIR/master-data/test/bug22080_2.CSV
--write_file $MYSQLTEST_VARDIR/master-data/test/bug22080_2.CSV
1,"string"
2","string"
......@@ -1636,6 +1639,7 @@ insert into bug22080_1 values(3,'string');
EOF
# Create second corrupt file as described in bug report
--remove_file $MYSQLTEST_VARDIR/master-data/test/bug22080_3.CSV
--write_file $MYSQLTEST_VARDIR/master-data/test/bug22080_3.CSV
1,"string"
"2",string"
......@@ -1696,6 +1700,7 @@ check table t1;
drop table t1;
create table t1(a int, b int) engine=csv;
--remove_file $MYSQLTEST_VARDIR/master-data/test/t1.CSV
--write_file $MYSQLTEST_VARDIR/master-data/test/t1.CSV
1, 1E-2
-2E2, .9
......
......@@ -242,18 +242,21 @@ DELIMITER /
SELECT 1/
EOF
--exec $MYSQL < $MYSQLTEST_VARDIR/tmp/bug21412.sql 2>&1
remove_file $MYSQLTEST_VARDIR/tmp/bug21412.sql;
# This should give an error...
--write_file $MYSQLTEST_VARDIR/tmp/bug21412.sql
DELIMITER \
EOF
--exec $MYSQL < $MYSQLTEST_VARDIR/tmp/bug21412.sql 2>&1
remove_file $MYSQLTEST_VARDIR/tmp/bug21412.sql;
# As should this...
--write_file $MYSQLTEST_VARDIR/tmp/bug21412.sql
DELIMITER \\
EOF
--exec $MYSQL < $MYSQLTEST_VARDIR/tmp/bug21412.sql 2>&1
remove_file $MYSQLTEST_VARDIR/tmp/bug21412.sql;
#
# Some coverage of not normally used parts
......
......@@ -20,7 +20,7 @@ EOF
--replace_regex /.*mysqladmin.*: unknown/mysqladmin: unknown/
--error 7
--exec $MYSQLADMIN --defaults-file=$MYSQLTEST_VARDIR/tmp/bug10608.cnf -S $MASTER_MYSOCK -P $MASTER_MYPORT -u root --password= ping 2>&1
remove_file $MYSQLTEST_VARDIR/tmp/bug10608.cnf;
# When mysqladmin finds "loose-database" in .cnf file it shall print
# a warning and continue
......@@ -32,3 +32,4 @@ EOF
--replace_regex /Warning: .*mysqladmin.*: unknown/Warning: mysqladmin: unknown/
--exec $MYSQLADMIN --defaults-file=$MYSQLTEST_VARDIR/tmp/bug10608.cnf -S $MASTER_MYSOCK -P $MASTER_MYPORT -u root --password= ping 2>&1
remove_file $MYSQLTEST_VARDIR/tmp/bug10608.cnf;
......@@ -366,6 +366,7 @@ show status;
EOF
--error 1
--exec $MYSQL_TEST < $MYSQLTEST_VARDIR/tmp/mysqltest.sql 2>&1
remove_file $MYSQLTEST_VARDIR/tmp/mysqltest.sql;
#
# Missing delimiter until eof
......@@ -377,6 +378,7 @@ sleep 7
EOF
--error 1
--exec $MYSQL_TEST < $MYSQLTEST_VARDIR/tmp/mysqltest.sql 2>&1
remove_file $MYSQLTEST_VARDIR/tmp/mysqltest.sql;
#
# Missing delimiter until "disable_query_log"
......@@ -391,6 +393,7 @@ disable_query_log;
EOF
--error 1
--exec $MYSQL_TEST < $MYSQLTEST_VARDIR/tmp/mysqltest.sql 2>&1
remove_file $MYSQLTEST_VARDIR/tmp/mysqltest.sql;
#
# Missing delimiter until "disable_query_log"
......@@ -406,6 +409,7 @@ disable_query_log;
EOF
--error 1
--exec $MYSQL_TEST < $MYSQLTEST_VARDIR/tmp/mysqltest.sql 2>&1
remove_file $MYSQLTEST_VARDIR/tmp/mysqltest.sql;
#
# Missing delimiter until eof
......@@ -422,6 +426,7 @@ disconnect default
EOF
--error 1
--exec $MYSQL_TEST < $MYSQLTEST_VARDIR/tmp/mysqltest.sql 2>&1
remove_file $MYSQLTEST_VARDIR/tmp/mysqltest.sql;
#
# Missing delimiter until eof
......@@ -436,6 +441,8 @@ EOF
--error 1
--exec $MYSQL_TEST < $MYSQLTEST_VARDIR/tmp/mysqltest.sql 2>&1
remove_file $MYSQLTEST_VARDIR/tmp/mysqltest.sql;
#
# Extra delimiter
#
......@@ -734,38 +741,40 @@ if (`select length("$var3") > 0`)
# Test to assign let from query
# let $<var_name>=`<query>`;
# ----------------------------------------------------------------------------
--disable_parsing
echo var1;
let $var1= `select "hi" as "Col", 1 as "Column1", "hi there" as Col3`;
echo $var1;
echo $var1_Col;
echo $var1_Column1;
echo $var1_Col3;
echo var2;
let $var2= `select 2 as "Column num 2"`;
echo $var2;
echo $var2_Column num 2;
echo $var2_Column;
echo var2 again;
let $var2= `select 2 as "Column num 2"`;
echo $var2;
echo $var2_Column num 2;
echo $var2_Column_num_2;
echo $var2_Column;
echo var3 two columns with same name;
let $var3= `select 1 as "Col", 2 as "Col", 3 as "var3"`;
echo $var3;
echo $var3_Col;
echo $var3_Col;
echo $var3_var3;
#echo failing query in let;
#--error 1
#--exec echo "let $var2= `failing query;`" | $MYSQL_TEST 2>&1
--enable_parsing
echo var4 from query that returns NULL;
let $var4= `select NULL`;
echo var5 from query that returns no row;
let $var5= `SHOW VARIABLES LIKE "nonexisting_variable"`;
echo failing query in let;
--write_file $MYSQLTEST_VARDIR/tmp/let.sql
let $var2= `failing query`;
echo $var2;
EOF
--error 1
--exec $MYSQL_TEST < $MYSQLTEST_VARDIR/tmp/let.sql 2>&1
remove_file $MYSQLTEST_VARDIR/tmp/let.sql;
# ----------------------------------------------------------------------------
# Test source command
# ----------------------------------------------------------------------------
......@@ -786,6 +795,7 @@ echo $var3_var3;
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
--error 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
--exec echo "garbage ;" > $MYSQLTEST_VARDIR/tmp/error.sql
......@@ -793,6 +803,7 @@ echo $var3_var3;
--error 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
--write_file $MYSQLTEST_VARDIR/tmp/sourced.inc
......@@ -843,6 +854,19 @@ while ($num)
--remove_file $MYSQLTEST_VARDIR/tmp/sourced.inc
--write_file $MYSQLTEST_VARDIR/tmp/sourced.inc
echo "hello";
EOF
let $x= sourced;
source $MYSQLTEST_VARDIR/tmp/$x.inc;
let $x= $MYSQLTEST_VARDIR;
source $x/tmp/sourced.inc;
--remove_file $MYSQLTEST_VARDIR/tmp/sourced.inc
# ----------------------------------------------------------------------------
# Test sleep command
# ----------------------------------------------------------------------------
......@@ -963,7 +987,7 @@ if (!$counter)
echo Counter is not 0, (counter=10);
}
let $counter=0;
if ($counter)
if($counter)
{
echo Counter is greater than 0, (counter=0);
}
......@@ -1156,6 +1180,7 @@ echo hej;
EOF
--error 1
--exec $MYSQL_TEST < $MYSQLTEST_VARDIR/tmp/mysqltest.sql 2>&1
remove_file $MYSQLTEST_VARDIR/tmp/mysqltest.sql;
--write_file $MYSQLTEST_VARDIR/tmp/mysqltest.sql
while (0)
......@@ -1163,6 +1188,7 @@ while (0)
EOF
--error 1
--exec $MYSQL_TEST < $MYSQLTEST_VARDIR/tmp/mysqltest.sql 2>&1
remove_file $MYSQLTEST_VARDIR/tmp/mysqltest.sql;
--write_file $MYSQLTEST_VARDIR/tmp/mysqltest.sql
while (0){
......@@ -1171,6 +1197,8 @@ EOF
--error 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
# ----------------------------------------------------------------------------
......@@ -1262,6 +1290,7 @@ while ($i)
}
EOF
--exec echo "source $MYSQLTEST_VARDIR/tmp/mysqltest.sql; echo OK;" | $MYSQL_TEST 2>&1
remove_file $MYSQLTEST_VARDIR/tmp/mysqltest.sql;
# Repeat connect/disconnect
--write_file $MYSQLTEST_VARDIR/tmp/mysqltest.sql
......@@ -1276,6 +1305,7 @@ EOF
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
--error 1
--exec echo "source $MYSQLTEST_VARDIR/tmp/mysqltest.sql;" | $MYSQL_TEST 2>&1
remove_file $MYSQLTEST_VARDIR/tmp/mysqltest.sql;
# Select disconnected connection
--write_file $MYSQLTEST_VARDIR/tmp/mysqltest.sql
......@@ -1286,6 +1316,7 @@ EOF
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
--error 1
--exec echo "source $MYSQLTEST_VARDIR/tmp/mysqltest.sql;" | $MYSQL_TEST 2>&1
remove_file $MYSQLTEST_VARDIR/tmp/mysqltest.sql;
# Connection name already used
--write_file $MYSQLTEST_VARDIR/tmp/mysqltest.sql
......@@ -1296,6 +1327,8 @@ EOF
--error 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"
--replace_result $MASTER_MYSOCK MASTER_SOCKET $MASTER_MYPORT MASTER_PORT
--disable_abort_on_error
......@@ -1399,7 +1432,11 @@ select "this will be executed";
--exec touch $MYSQLTEST_VARDIR/tmp/zero_length_file.result
--exec echo "echo ok;" > $MYSQLTEST_VARDIR/tmp/query.sql
--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/log/zero_length_file.reject;
#
# Test that a test file that does not generate any output fails.
#
......@@ -1407,6 +1444,8 @@ select "this will be executed";
--error 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
# but a result file exists
......@@ -1436,6 +1475,7 @@ echo Failing multi statement query;
--exec $MYSQL_TEST -x $MYSQLTEST_VARDIR/tmp/bug11731.sql 2>&1
drop table t1;
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
--error 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
......@@ -1462,6 +1502,9 @@ drop table t1;
# The .out file should exist
--exec test -s $MYSQLTEST_VARDIR/tmp/bug11731.out
drop table t1;
remove_file $MYSQLTEST_VARDIR/tmp/bug11731.out;
remove_file $MYSQLTEST_VARDIR/log/bug11731.log;
remove_file $MYSQLTEST_VARDIR/tmp/bug11731.sql;
#
# Bug#19890 mysqltest: "query" command is broken
......@@ -1544,12 +1587,19 @@ write_file $MYSQLTEST_VARDIR/tmp/test_file1.tmp;
Content for test_file1
EOF
file_exists $MYSQLTEST_VARDIR/tmp/test_file1.tmp;
cat_file $MYSQLTEST_VARDIR/tmp/test_file1.tmp;
remove_file $MYSQLTEST_VARDIR/tmp/test_file1.tmp;
write_file $MYSQLTEST_VARDIR/tmp/test_file1.tmp END_DELIMITER;
Content for test_file1 contains EOF
END_DELIMITER
file_exists $MYSQLTEST_VARDIR/tmp/test_file1.tmp;
# write to already exisiting file
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
--error 1
--exec echo "write_file $MYSQLTEST_VARDIR/tmp/test_file1.tmp;" | $MYSQL_TEST 2>&1
remove_file $MYSQLTEST_VARDIR/tmp/test_file1.tmp;
# ----------------------------------------------------------------------------
......@@ -1571,6 +1621,8 @@ append_file $MYSQLTEST_VARDIR/tmp/test_file1.tmp;
Appended text on nonexisting file
EOF
remove_file $MYSQLTEST_VARDIR/tmp/test_file1.tmp;
# ----------------------------------------------------------------------------
# test for cat_file
# ----------------------------------------------------------------------------
......@@ -1581,6 +1633,7 @@ for cat_file command
of mysqltest
EOF
cat_file $MYSQLTEST_VARDIR/tmp/test_file1.tmp;
remove_file $MYSQLTEST_VARDIR/tmp/test_file1.tmp;
--error 1
--exec echo "cat_file non_existing_file;" | $MYSQL_TEST 2>&1
......@@ -1607,19 +1660,48 @@ for diff_file command
of mysqltest
EOF
--write_file $MYSQLTEST_VARDIR/tmp/diff4.tmp
Some data
for diff_file command
of musqltest
EOF
# Compare equal files
--diff_files $MYSQLTEST_VARDIR/tmp/diff1.tmp $MYSQLTEST_VARDIR/tmp/diff2.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
--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
--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...
--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
# ----------------------------------------------------------------------------
......@@ -1672,6 +1754,7 @@ chmod 0000 $MYSQLTEST_VARDIR/tmp/file1.tmp;
#EOF
chmod 0777 $MYSQLTEST_VARDIR/tmp/file1.tmp;
remove_file $MYSQLTEST_VARDIR/tmp/file1.tmp;
--write_file $MYSQLTEST_VARDIR/tmp/file1.tmp
test2
EOF
......
......@@ -50,6 +50,7 @@ insert into t1 values (0);
flush table mysql.proc;
# Thrashing the .frm file
--remove_file $MYSQLTEST_VARDIR/master-data/mysql/proc.frm
--write_file $MYSQLTEST_VARDIR/master-data/mysql/proc.frm
saljdfa
EOF
......
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