Commit 6d89bcbc authored by unknown's avatar unknown

Bug #20010 mysql-test-run.pl: --record and --require conflict (test fails)

- When --record is passed to mysqltest the whole testcase should be executed
as it normally is while the output form the test is acumulating
in ds_res. When test has finished ds_res should simply be written to the
specified result file(if any) instead of comapring it against the result file.
Simplify handling of --require and also the cecking of result files by splitting
check_result function into one  function 'check_require' that is specialised in
checking require's and leave 'check_result' to do just that.
- "mysqltest --record" has been considered unsafe, but with this really simple
logic, it should be safe to use.


client/mysqltest.c:
  When --record is passed to mysqltest the whole testcase should be executed
  as it normally is while the output form the test is acumulating
  in ds_res. When test has finished ds_res should simply be written to the
  specified result file(if any) instead of comapring it against the result file.
  Simplify handling of --require and also the cecking of result files by splitting
  check_result function into one  function 'check_require' that is specialised in
  checking require's and leave 'check_result' to do just that.
parent 068641aa
...@@ -192,7 +192,7 @@ struct ...@@ -192,7 +192,7 @@ struct
} master_pos; } master_pos;
/* if set, all results are concated and compared against this file */ /* if set, all results are concated and compared against this file */
const char *result_file= 0; const char *result_file_name= 0;
typedef struct st_var typedef struct st_var
{ {
...@@ -382,9 +382,9 @@ struct st_command ...@@ -382,9 +382,9 @@ struct st_command
{ {
char *query, *query_buf,*first_argument,*last_argument,*end; char *query, *query_buf,*first_argument,*last_argument,*end;
int first_word_len, query_len; int first_word_len, query_len;
my_bool abort_on_error, require_file; my_bool abort_on_error;
struct st_expected_errors expected_errors; struct st_expected_errors expected_errors;
char record_file[FN_REFLEN]; char require_file[FN_REFLEN];
enum enum_commands type; enum enum_commands type;
}; };
...@@ -410,9 +410,10 @@ VAR* var_get(const char *var_name, const char** var_name_end, ...@@ -410,9 +410,10 @@ VAR* var_get(const char *var_name, const char** var_name_end,
my_bool raw, my_bool ignore_not_existing); my_bool raw, my_bool ignore_not_existing);
void eval_expr(VAR* v, const char *p, const char** p_end); void eval_expr(VAR* v, const char *p, const char** p_end);
my_bool match_delimiter(int c, const char *delim, uint length); my_bool match_delimiter(int c, const char *delim, uint length);
void dump_result_to_reject_file(const char *record_file, char *buf, int size); void dump_result_to_reject_file(char *buf, int size);
void dump_result_to_log_file(const char *record_file, char *buf, int size); void dump_result_to_log_file(char *buf, int size);
void dump_warning_messages(const char *record_file); void dump_warning_messages();
void dump_progress();
void do_eval(DYNAMIC_STRING *query_eval, const char *query, void do_eval(DYNAMIC_STRING *query_eval, const char *query,
const char *query_end, my_bool pass_through_escape_chars); const char *query_end, my_bool pass_through_escape_chars);
...@@ -742,12 +743,12 @@ void die(const char *fmt, ...) ...@@ -742,12 +743,12 @@ void die(const char *fmt, ...)
va_end(args); va_end(args);
/* 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 && ds_res.length) if (result_file_name && ds_res.length)
dump_result_to_log_file(result_file, ds_res.str, ds_res.length); dump_result_to_log_file(ds_res.str, ds_res.length);
/* Dump warning messages */ /* Dump warning messages */
if (result_file && ds_warning_messages.length) if (result_file_name && ds_warning_messages.length)
dump_warning_messages(result_file); dump_warning_messages();
/* Clean up and exit */ /* Clean up and exit */
free_used_memory(); free_used_memory();
...@@ -926,41 +927,32 @@ int dyn_string_cmp(DYNAMIC_STRING* ds, const char *fname) ...@@ -926,41 +927,32 @@ int dyn_string_cmp(DYNAMIC_STRING* ds, const char *fname)
/* /*
Check the content of ds against content of file fname Check the content of ds against result file
SYNOPSIS SYNOPSIS
check_result check_result
ds - content to be checked ds - content to be checked
fname - name of file to check against
require_option - if set and check fails, the test will be aborted
with the special exit code "not supported test"
RETURN VALUES RETURN VALUES
error - the function will not return error - the function will not return
*/ */
void check_result(DYNAMIC_STRING* ds, const char *fname, void check_result(DYNAMIC_STRING* ds)
my_bool require_option)
{ {
int res= dyn_string_cmp(ds, fname); DBUG_ASSERT(result_file_name);
DBUG_ENTER("check_result"); DBUG_ENTER("check_result");
if (res && require_option) switch (dyn_string_cmp(ds, result_file_name))
{ {
char reason[FN_REFLEN];
fn_format(reason, fname, "", "", MY_REPLACE_EXT | MY_REPLACE_DIR);
abort_not_supported_test("Test requires: '%s'", reason);
}
switch (res) {
case RESULT_OK: case RESULT_OK:
break; /* ok */ break; /* ok */
case RESULT_LENGTH_MISMATCH: case RESULT_LENGTH_MISMATCH:
dump_result_to_reject_file(fname, ds->str, ds->length); dump_result_to_reject_file(ds->str, ds->length);
die("Result length mismatch"); die("Result length mismatch");
break; break;
case RESULT_CONTENT_MISMATCH: case RESULT_CONTENT_MISMATCH:
dump_result_to_reject_file(fname, ds->str, ds->length); dump_result_to_reject_file(ds->str, ds->length);
die("Result content mismatch"); die("Result content mismatch");
break; break;
default: /* impossible */ default: /* impossible */
...@@ -971,6 +963,35 @@ void check_result(DYNAMIC_STRING* ds, const char *fname, ...@@ -971,6 +963,35 @@ void check_result(DYNAMIC_STRING* ds, const char *fname,
} }
/*
Check the content of ds against a require file
If match fails, abort the test with special error code
indicating that test is not supported
SYNOPSIS
check_result
ds - content to be checked
fname - name of file to check against
RETURN VALUES
error - the function will not return
*/
void check_require(DYNAMIC_STRING* ds, const char *fname)
{
DBUG_ENTER("check_require");
if (dyn_string_cmp(ds, fname))
{
char reason[FN_REFLEN];
fn_format(reason, fname, "", "", MY_REPLACE_EXT | MY_REPLACE_DIR);
abort_not_supported_test("Test requires: '%s'", reason);
}
DBUG_VOID_RETURN;
}
static byte *get_var_key(const byte* var, uint* len, static byte *get_var_key(const byte* var, uint* len,
my_bool __attribute__((unused)) t) my_bool __attribute__((unused)) t)
{ {
...@@ -2389,7 +2410,8 @@ int do_sleep(struct st_command *command, my_bool real_sleep) ...@@ -2389,7 +2410,8 @@ int do_sleep(struct st_command *command, my_bool real_sleep)
} }
void do_get_file_name(char *filename, struct st_command *command) void do_get_file_name(struct st_command *command,
char* dest, uint dest_max_len)
{ {
char *p= command->first_argument, *name; char *p= command->first_argument, *name;
if (!*p) if (!*p)
...@@ -2400,7 +2422,7 @@ void do_get_file_name(char *filename, struct st_command *command) ...@@ -2400,7 +2422,7 @@ void do_get_file_name(char *filename, struct st_command *command)
if (*p) if (*p)
*p++= 0; *p++= 0;
command->last_argument= p; command->last_argument= p;
strmake(filename, name, FN_REFLEN); strmake(dest, name, dest_max_len);
} }
...@@ -3672,8 +3694,7 @@ int read_command(struct st_command** command_ptr) ...@@ -3672,8 +3694,7 @@ int read_command(struct st_command** command_ptr)
insert_dynamic(&q_lines, (gptr) &command)) insert_dynamic(&q_lines, (gptr) &command))
die(NullS); die(NullS);
command->record_file[0]= 0; command->require_file[0]= 0;
command->require_file= 0;
command->first_word_len= 0; command->first_word_len= 0;
command->query_len= 0; command->query_len= 0;
...@@ -3767,8 +3788,8 @@ static struct my_option my_long_options[] = ...@@ -3767,8 +3788,8 @@ static struct my_option my_long_options[] =
{"record", 'r', "Record output of test_file into result file.", {"record", 'r', "Record output of test_file into result file.",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
{"result-file", 'R', "Read/Store result from/in this file.", {"result-file", 'R', "Read/Store result from/in this file.",
(gptr*) &result_file, (gptr*) &result_file, 0, GET_STR, REQUIRED_ARG, (gptr*) &result_file_name, (gptr*) &result_file_name, 0,
0, 0, 0, 0, 0, 0}, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"server-arg", 'A', "Send option value to embedded server as a parameter.", {"server-arg", 'A', "Send option value to embedded server as a parameter.",
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},
{"server-file", 'F', "Read embedded server arguments from file.", {"server-file", 'F', "Read embedded server arguments from file.",
...@@ -4018,35 +4039,35 @@ void str_to_file(const char *fname, char *str, int size) ...@@ -4018,35 +4039,35 @@ void str_to_file(const char *fname, char *str, int size)
} }
void dump_result_to_reject_file(const char *record_file, char *buf, int size) void dump_result_to_reject_file(char *buf, int size)
{ {
char reject_file[FN_REFLEN]; char reject_file[FN_REFLEN];
str_to_file(fn_format(reject_file, record_file, "", ".reject", str_to_file(fn_format(reject_file, result_file_name, "", ".reject",
MY_REPLACE_EXT), MY_REPLACE_EXT),
buf, size); buf, size);
} }
void dump_result_to_log_file(const char *record_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];
str_to_file(fn_format(log_file, record_file, "", ".log", str_to_file(fn_format(log_file, result_file_name, "", ".log",
MY_REPLACE_EXT), MY_REPLACE_EXT),
buf, size); buf, size);
} }
void dump_progress(const char *record_file) void dump_progress(void)
{ {
char log_file[FN_REFLEN]; char log_file[FN_REFLEN];
str_to_file(fn_format(log_file, record_file, "", ".progress", str_to_file(fn_format(log_file, result_file_name, "", ".progress",
MY_REPLACE_EXT), MY_REPLACE_EXT),
ds_progress.str, ds_progress.length); ds_progress.str, ds_progress.length);
} }
void dump_warning_messages(const char *record_file) void dump_warning_messages(void)
{ {
char warn_file[FN_REFLEN]; char warn_file[FN_REFLEN];
str_to_file(fn_format(warn_file, record_file, "", ".warnings", str_to_file(fn_format(warn_file, result_file_name, "", ".warnings",
MY_REPLACE_EXT), MY_REPLACE_EXT),
ds_warning_messages.str, ds_warning_messages.length); ds_warning_messages.str, ds_warning_messages.length);
} }
...@@ -4608,7 +4629,7 @@ void handle_error(struct st_command *command, ...@@ -4608,7 +4629,7 @@ void handle_error(struct st_command *command,
DBUG_ENTER("handle_error"); DBUG_ENTER("handle_error");
if (command->require_file) if (command->require_file[0])
{ {
/* /*
The query after a "--require" failed. This is fine as long the server The query after a "--require" failed. This is fine as long the server
...@@ -5004,12 +5025,12 @@ void run_query(MYSQL *mysql, struct st_command *command, int flags) ...@@ -5004,12 +5025,12 @@ void run_query(MYSQL *mysql, struct st_command *command, int flags)
} }
/* /*
When command->record_file is set the output of _this_ query When command->require_file is set the output of _this_ query
should be compared with an already existing file should be compared with an already existing file
Create a temporary dynamic string to contain the output from Create a temporary dynamic string to contain the output from
this query. this query.
*/ */
if (command->record_file[0]) if (command->require_file[0])
{ {
init_dynamic_string(&ds_result, "", 1024, 1024); init_dynamic_string(&ds_result, "", 1024, 1024);
ds= &ds_result; ds= &ds_result;
...@@ -5144,26 +5165,14 @@ void run_query(MYSQL *mysql, struct st_command *command, int flags) ...@@ -5144,26 +5165,14 @@ void run_query(MYSQL *mysql, struct st_command *command, int flags)
mysql_errno(mysql), mysql_error(mysql)); mysql_errno(mysql), mysql_error(mysql));
} }
if (command->record_file[0]) if (command->require_file[0])
{ {
/* A result file was specified for _this_ query */ /* A result file was specified for _this_ query
if (record) and the output should be checked against an already
{ existing file which has been specified using --require or --result
/* */
Recording in progress check_require(ds, command->require_file);
Dump the output from _this_ query to the specified record_file
*/
str_to_file(command->record_file, ds->str, ds->length);
} else {
/*
The output from _this_ query should be checked against an already
existing file which has been specified using --require or --result
*/
check_result(ds, command->record_file, command->require_file);
}
} }
dynstr_free(&ds_warnings); dynstr_free(&ds_warnings);
...@@ -5391,7 +5400,7 @@ void mark_progress(struct st_command* command __attribute__((unused)), ...@@ -5391,7 +5400,7 @@ void mark_progress(struct st_command* command __attribute__((unused)),
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
struct st_command *command; struct st_command *command;
my_bool require_file= 0, q_send_flag= 0; my_bool q_send_flag= 0;
uint command_executed= 0, last_command_executed= 0; uint command_executed= 0, last_command_executed= 0;
char save_file[FN_REFLEN]; char save_file[FN_REFLEN];
MY_STAT res_info; MY_STAT res_info;
...@@ -5442,7 +5451,8 @@ int main(int argc, char **argv) ...@@ -5442,7 +5451,8 @@ int main(int argc, char **argv)
init_dynamic_string(&ds_warning_messages, "", 0, 2048); init_dynamic_string(&ds_warning_messages, "", 0, 2048);
parse_args(argc, argv); parse_args(argc, argv);
DBUG_PRINT("info",("result_file: '%s'", result_file ? result_file : "")); DBUG_PRINT("info",("result_file: '%s'",
result_file_name ? result_file_name : ""));
if (mysql_server_init(embedded_server_arg_count, if (mysql_server_init(embedded_server_arg_count,
embedded_server_args, embedded_server_args,
(char**) embedded_server_groups)) (char**) embedded_server_groups))
...@@ -5594,9 +5604,8 @@ int main(int argc, char **argv) ...@@ -5594,9 +5604,8 @@ int main(int argc, char **argv)
display_result_vertically= (command->type == Q_QUERY_VERTICAL); display_result_vertically= (command->type == Q_QUERY_VERTICAL);
if (save_file[0]) if (save_file[0])
{ {
strmov(command->record_file,save_file); strmake(command->require_file, save_file, sizeof(save_file));
command->require_file=require_file; save_file[0]= 0;
save_file[0]=0;
} }
run_query(&cur_con->mysql, command, QUERY_REAP_FLAG|QUERY_SEND_FLAG); run_query(&cur_con->mysql, command, QUERY_REAP_FLAG|QUERY_SEND_FLAG);
display_result_vertically= old_display_result_vertically; display_result_vertically= old_display_result_vertically;
...@@ -5626,9 +5635,8 @@ int main(int argc, char **argv) ...@@ -5626,9 +5635,8 @@ int main(int argc, char **argv)
if (save_file[0]) if (save_file[0])
{ {
strmov(command->record_file,save_file); strmake(command->require_file, save_file, sizeof(save_file));
command->require_file=require_file; save_file[0]= 0;
save_file[0]=0;
} }
run_query(&cur_con->mysql, command, flags); run_query(&cur_con->mysql, command, flags);
command_executed++; command_executed++;
...@@ -5660,17 +5668,12 @@ int main(int argc, char **argv) ...@@ -5660,17 +5668,12 @@ int main(int argc, char **argv)
command_executed++; command_executed++;
command->last_argument= command->end; command->last_argument= command->end;
break; break;
case Q_RESULT: case Q_REQUIRE:
do_get_file_name(save_file, command); do_get_file_name(command, save_file, sizeof(save_file));
require_file=0;
break; break;
case Q_ERROR: case Q_ERROR:
do_get_errcodes(command); do_get_errcodes(command);
break; break;
case Q_REQUIRE:
do_get_file_name(save_file, command);
require_file=1;
break;
case Q_REPLACE: case Q_REPLACE:
do_get_replace(command); do_get_replace(command);
break; break;
...@@ -5741,11 +5744,14 @@ int main(int argc, char **argv) ...@@ -5741,11 +5744,14 @@ int main(int argc, char **argv)
else else
die("Parsing is already enabled"); die("Parsing is already enabled");
break; break;
case Q_DIE: case Q_DIE:
die("%s", command->first_argument); die("%s", command->first_argument);
break; break;
case Q_RESULT:
die("result, deprecated command");
break;
default: default:
processed= 0; processed= 0;
break; break;
...@@ -5802,12 +5808,14 @@ int main(int argc, char **argv) ...@@ -5802,12 +5808,14 @@ int main(int argc, char **argv)
*/ */
if (ds_res.length) if (ds_res.length)
{ {
if (result_file) if (result_file_name)
{ {
/* A result file has been specified */
if (record) if (record)
{ {
/* Dump the output from test to result file */ /* Recording - dump the output from test to result file */
str_to_file(result_file, ds_res.str, ds_res.length); str_to_file(result_file_name, ds_res.str, ds_res.length);
} }
else else
{ {
...@@ -5815,12 +5823,12 @@ int main(int argc, char **argv) ...@@ -5815,12 +5823,12 @@ int main(int argc, char **argv)
- detect missing result file - detect missing result file
- detect zero size result file - detect zero size result file
*/ */
check_result(&ds_res, result_file, 0); check_result(&ds_res);
} }
} }
else else
{ {
/* No result_file specified to compare with, print to stdout */ /* No result_file_name specified to compare with, print to stdout */
printf("%s", ds_res.str); printf("%s", ds_res.str);
} }
} }
...@@ -5829,7 +5837,8 @@ int main(int argc, char **argv) ...@@ -5829,7 +5837,8 @@ int main(int argc, char **argv)
die("The test didn't produce any output"); die("The test didn't produce any output");
} }
if (!command_executed && result_file && my_stat(result_file, &res_info, 0)) if (!command_executed &&
result_file_name && my_stat(result_file_name, &res_info, 0))
{ {
/* /*
my_stat() successful on result file. Check if we have not run a my_stat() successful on result file. Check if we have not run a
...@@ -5841,12 +5850,12 @@ int main(int argc, char **argv) ...@@ -5841,12 +5850,12 @@ int main(int argc, char **argv)
die("No queries executed but result file found!"); die("No queries executed but result file found!");
} }
if ( opt_mark_progress && result_file ) if ( opt_mark_progress && result_file_name )
dump_progress(result_file); dump_progress();
/* Dump warning messages */ /* Dump warning messages */
if (result_file && ds_warning_messages.length) if (result_file_name && ds_warning_messages.length)
dump_warning_messages(result_file); dump_warning_messages();
dynstr_free(&ds_res); dynstr_free(&ds_res);
......
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