40
39
#define MTEST_VERSION "3.3"
42
#include "client_priv.h"
52
#ifdef HAVE_SYS_WAIT_H
57
#include <sys/types.h>
59
#include <boost/program_options.hpp>
47
#include "client_priv.h"
48
#include <mysys/hash.h>
63
49
#include <stdarg.h>
64
#include <boost/unordered_map.hpp>
66
/* Added this for string translation. */
67
#include "drizzled/gettext.h"
68
#include "drizzled/drizzle_time.h"
69
#include "drizzled/charset.h"
70
#include <drizzled/configmake.h>
72
#ifndef DRIZZLE_RETURN_SERVER_GONE
73
#define DRIZZLE_RETURN_HANDSHAKE_FAILED DRIZZLE_RETURN_ERROR_CODE
75
namespace po= boost::program_options;
50
#include <vio/violite.h>
76
54
using namespace std;
77
using namespace drizzled;
80
unsigned char *get_var_key(const unsigned char* var, size_t *len, bool);
82
int get_one_option(int optid, const struct option *, char *argument);
84
56
#define MAX_VAR_NAME_LENGTH 256
85
57
#define MAX_COLUMNS 256
58
#define MAX_EMBEDDED_SERVER_ARGS 64
86
59
#define MAX_DELIMITER_LENGTH 16
87
61
/* Flags controlling send and reap */
88
62
#define QUERY_SEND_FLAG 1
89
63
#define QUERY_REAP_FLAG 2
91
typedef boost::unordered_map<std::string, uint32_t> ErrorCodes;
92
ErrorCodes global_error_names;
66
OPT_SKIP_SAFEMALLOC=OPT_MAX_CLIENT_OPTION,
95
67
OPT_PS_PROTOCOL, OPT_SP_PROTOCOL, OPT_CURSOR_PROTOCOL, OPT_VIEW_PROTOCOL,
96
OPT_MAX_CONNECT_RETRIES, OPT_MARK_PROGRESS, OPT_LOG_DIR, OPT_TAIL_LINES,
68
OPT_MAX_CONNECT_RETRIES, OPT_MARK_PROGRESS, OPT_LOG_DIR, OPT_TAIL_LINES
100
71
static int record= 0, opt_sleep= -1;
101
static char *opt_pass= NULL;
102
const char *unix_sock= NULL;
103
static uint32_t opt_port= 0;
104
static uint32_t opt_max_connect_retries;
105
static bool silent= false, verbose= false;
106
static bool opt_mark_progress= false;
107
static bool parsing_disabled= false;
72
static char *opt_db= 0, *opt_pass= 0;
73
const char *opt_user= 0, *opt_host= 0, *unix_sock= 0, *opt_basedir= "./";
74
const char *opt_logdir= "";
75
const char *opt_include= 0, *opt_charsets_dir;
76
static int opt_port= 0;
77
static int opt_max_connect_retries;
78
static bool opt_compress= 0, silent= 0, verbose= 0;
79
static bool debug_info_flag= 0, debug_check_flag= 0;
80
static bool tty_password= 0;
81
static bool opt_mark_progress= 0;
82
static bool parsing_disabled= 0;
108
83
static bool display_result_vertically= false,
109
84
display_metadata= false, display_result_sorted= false;
110
static bool disable_query_log= false, disable_result_log= false;
111
static bool disable_warnings= false;
112
static bool disable_info= true;
113
static bool abort_on_error= true;
114
static bool server_initialized= false;
115
static bool is_windows= false;
116
static bool use_drizzle_protocol= false;
85
static bool disable_query_log= 0, disable_result_log= 0;
86
static bool disable_warnings= 0;
87
static bool disable_info= 1;
88
static bool abort_on_error= 1;
89
static bool server_initialized= 0;
90
static bool is_windows= 0;
91
static char **default_argv;
92
static const char *load_default_groups[]= { "drizzletest", "client", 0 };
117
93
static char line_buffer[MAX_DELIMITER_LENGTH], *line_buffer_pos= line_buffer;
119
std::string opt_basedir,
132
static uint32_t start_lineno= 0; /* Start line of current command */
95
static uint start_lineno= 0; /* Start line of current command */
96
static uint my_end_arg= 0;
134
98
/* Number of lines of the result to include in failure report */
135
static uint32_t opt_tail_lines= 0;
99
static uint opt_tail_lines= 0;
137
101
static char delimiter[MAX_DELIMITER_LENGTH]= ";";
138
static uint32_t delimiter_length= 1;
102
static uint delimiter_length= 1;
140
104
static char TMPDIR[FN_REFLEN];
3383
3233
command->last_argument= p;
3384
charset_info= get_charset_by_csname(charset_name, MY_CS_PRIMARY);
3234
charset_info= get_charset_by_csname(charset_name,MY_CS_PRIMARY,MYF(MY_WME));
3385
3235
if (!charset_info)
3386
3236
abort_not_supported_test("Test requires charset '%s'", charset_name);
3389
static void fill_global_error_names()
3239
static uint get_errcode_from_name(char *error_name, char *error_end)
3391
drizzle_result_st res;
3392
drizzle_return_t ret;
3394
drizzle_con_st *con= &cur_con->con;
3396
global_error_names.clear();
3398
const std::string ds_query("select error_name, error_code "
3399
"from data_dictionary.errors");
3400
if (drizzle_query_str(con, &res, ds_query.c_str(), &ret) == NULL ||
3401
ret != DRIZZLE_RETURN_OK)
3403
if (ret == DRIZZLE_RETURN_ERROR_CODE)
3405
die("Error running query '%s': %d %s", ds_query.c_str(),
3406
drizzle_result_error_code(&res), drizzle_result_error(&res));
3407
drizzle_result_free(&res);
3411
die("Error running query '%s': %d %s", ds_query.c_str(), ret,
3412
drizzle_con_error(con));
3415
if (drizzle_result_column_count(&res) == 0 ||
3416
drizzle_result_buffer(&res) != DRIZZLE_RETURN_OK)
3418
drizzle_result_free(&res);
3419
die("Query '%s' didn't return a result set", ds_query.c_str());
3422
while ((row= drizzle_row_next(&res)) && row[0])
3241
/* SQL error as string */
3242
st_error *e= global_error_names;
3244
/* Loop through the array of known error names */
3245
for (; e->name; e++)
3425
Concatenate all fields in the first row with tab in between
3426
and assign that string to the $variable
3248
If we get a match, we need to check the length of the name we
3249
matched against in case it was longer than what we are checking
3250
(as in ER_WRONG_VALUE vs. ER_WRONG_VALUE_COUNT).
3428
size_t *lengths= drizzle_row_field_sizes(&res);
3429
const std::string error_name(row[0], lengths[0]);
3430
const std::string error_code(row[1], lengths[1]);
3434
global_error_names.insert(ErrorCodes::value_type(error_name,
3435
boost::lexical_cast<uint32_t>(error_code)));
3437
catch (boost::bad_lexical_cast &ex)
3439
drizzle_result_free(&res);
3440
die("Invalid error_code from Drizzle: %s", ex.what());
3445
drizzle_result_free(&res);
3448
static uint32_t get_errcode_from_name(char *error_name, char *error_end)
3450
size_t err_name_len= error_end - error_name;
3451
string error_name_s(error_name, err_name_len);
3453
ErrorCodes::iterator it= global_error_names.find(error_name_s);
3454
if (it != global_error_names.end())
3456
return (*it).second;
3459
die("Unknown SQL error name '%s'", error_name_s.c_str());
3252
if (!strncmp(error_name, e->name, (int) (error_end - error_name)) &&
3253
(uint) strlen(e->name) == (uint) (error_end - error_name))
3259
die("Unknown SQL error name '%s'", error_name);
3463
3263
static void do_get_errcodes(struct st_command *command)
3465
3265
struct st_match_err *to= saved_expected_errors.err;
3466
3266
char *p= command->first_argument;
4431
static struct my_option my_long_options[] =
4433
{"help", '?', "Display this help and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG,
4435
{"basedir", 'b', "Basedir for tests.", (char**) &opt_basedir,
4436
(char**) &opt_basedir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
4437
{"character-sets-dir", OPT_CHARSETS_DIR,
4438
"Directory where character sets are.", (char**) &opt_charsets_dir,
4439
(char**) &opt_charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
4440
{"compress", 'C', "Use the compressed server/client protocol.",
4441
(char**) &opt_compress, (char**) &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0,
4443
{"database", 'D', "Database to use.", (char**) &opt_db, (char**) &opt_db, 0,
4444
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
4445
{"debug-check", OPT_DEBUG_CHECK, "Check memory and open file usage at exit.",
4446
(char**) &debug_check_flag, (char**) &debug_check_flag, 0,
4447
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
4448
{"debug-info", OPT_DEBUG_INFO, "Print some debug info at exit.",
4449
(char**) &debug_info_flag, (char**) &debug_info_flag,
4450
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
4451
{"host", 'h', "Connect to host.", (char**) &opt_host, (char**) &opt_host, 0,
4452
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
4453
{"include", 'i', "Include SQL before each test case.", (char**) &opt_include,
4454
(char**) &opt_include, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
4455
{"logdir", OPT_LOG_DIR, "Directory for log files", (char**) &opt_logdir,
4456
(char**) &opt_logdir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
4457
{"mark-progress", OPT_MARK_PROGRESS,
4458
"Write linenumber and elapsed time to <testname>.progress ",
4459
(char**) &opt_mark_progress, (char**) &opt_mark_progress, 0,
4460
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
4461
{"max-connect-retries", OPT_MAX_CONNECT_RETRIES,
4462
"Max number of connection attempts when connecting to server",
4463
(char**) &opt_max_connect_retries, (char**) &opt_max_connect_retries, 0,
4464
GET_INT, REQUIRED_ARG, 500, 1, 10000, 0, 0, 0},
4465
{"password", 'p', "Password to use when connecting to server.",
4466
0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
4467
{"port", 'P', "Port number to use for connection or 0 for default to, in "
4468
"order of preference, my.cnf, $DRIZZLE_TCP_PORT, "
4469
"built-in default (" STRINGIFY_ARG(DRIZZLE_PORT) ").",
4471
(char**) &opt_port, 0, GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
4472
{"quiet", 's', "Suppress all normal output.", (char**) &silent,
4473
(char**) &silent, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
4474
{"record", 'r', "Record output of test_file into result file.",
4475
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
4476
{"result-file", 'R', "Read/Store result from/in this file.",
4477
(char**) &result_file_name, (char**) &result_file_name, 0,
4478
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
4479
{"server-arg", 'A', "Send option value to embedded server as a parameter.",
4480
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
4481
{"server-file", 'F', "Read embedded server arguments from file.",
4482
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
4483
{"silent", 's', "Suppress all normal output. Synonym for --quiet.",
4484
(char**) &silent, (char**) &silent, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
4485
{"sleep", 'T', "Sleep always this many seconds on sleep commands.",
4486
(char**) &opt_sleep, (char**) &opt_sleep, 0, GET_INT, REQUIRED_ARG, -1, -1, 0,
4488
{"tail-lines", OPT_TAIL_LINES,
4489
"Number of lines of the resul to include in a failure report",
4490
(char**) &opt_tail_lines, (char**) &opt_tail_lines, 0,
4491
GET_INT, REQUIRED_ARG, 0, 0, 10000, 0, 0, 0},
4492
{"test-file", 'x', "Read test from/in this file (default stdin).",
4493
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
4494
{"timer-file", 'm', "File where the timing in micro seconds is stored.",
4495
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
4496
{"tmpdir", 't', "Temporary directory where sockets are put.",
4497
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
4498
{"user", 'u', "User for login.", (char**) &opt_user, (char**) &opt_user, 0,
4499
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
4500
{"verbose", 'v', "Write more.", (char**) &verbose, (char**) &verbose, 0,
4501
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
4502
{"version", 'V', "Output version information and exit.",
4503
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
4504
{ 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
4508
static void print_version(void)
4510
printf("%s Ver %s Distrib %s, for %s (%s)\n",my_progname,MTEST_VERSION,
4511
drizzle_get_client_info(),SYSTEM_TYPE,MACHINE_TYPE);
4514
static void usage(void)
4517
printf("MySQL AB, by Sasha, Matt, Monty & Jani\n");
4518
printf("This software comes with ABSOLUTELY NO WARRANTY\n\n");
4519
printf("Runs a test against the DRIZZLE server and compares output with a results file.\n\n");
4520
printf("Usage: %s [OPTIONS] [database] < test_file\n", my_progname);
4521
my_print_help(my_long_options);
4522
printf(" --no-defaults Don't read default options from any options file.\n");
4523
my_print_variables(my_long_options);
4527
Read arguments for embedded server and put them into
4528
embedded_server_args[]
4531
static void read_embedded_server_arguments(const char *name)
4533
char argument[1024],buff[FN_REFLEN], *str=0;
4536
if (!test_if_hard_path(name))
4538
strxmov(buff, opt_basedir, name, NullS);
4541
fn_format(buff, name, "", "", MY_UNPACK_FILENAME);
4543
if (!embedded_server_arg_count)
4545
embedded_server_arg_count=1;
4546
embedded_server_args[0]= (char*) ""; /* Progname */
4548
if (!(file=my_fopen(buff, O_RDONLY | FILE_BINARY, MYF(MY_WME))))
4549
die("Failed to open file '%s'", buff);
4551
while (embedded_server_arg_count < MAX_EMBEDDED_SERVER_ARGS &&
4552
(str=fgets(argument,sizeof(argument), file)))
4554
*(strchr(str, '\0')-1)=0; /* Remove end newline */
4555
if (!(embedded_server_args[embedded_server_arg_count]=
4556
(char*) my_strdup(str,MYF(MY_WME))))
4558
my_fclose(file,MYF(0));
4559
die("Out of memory");
4562
embedded_server_arg_count++;
4564
my_fclose(file,MYF(0));
4566
die("Too many arguments in option file: %s",name);
4573
get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
4582
char buff[FN_REFLEN];
4583
if (!test_if_hard_path(argument))
4585
strxmov(buff, opt_basedir, argument, NullS);
4588
fn_format(buff, argument, "", "", MY_UNPACK_FILENAME);
4589
assert(cur_file == file_stack && cur_file->file == 0);
4590
if (!(cur_file->file=
4591
my_fopen(buff, O_RDONLY | FILE_BINARY, MYF(0))))
4592
die("Could not open '%s' for reading: errno = %d", buff, errno);
4593
cur_file->file_name= my_strdup(buff, MYF(MY_FAE));
4594
cur_file->lineno= 1;
4599
static char buff[FN_REFLEN];
4600
if (!test_if_hard_path(argument))
4602
strxmov(buff, opt_basedir, argument, NullS);
4605
fn_format(buff, argument, "", "", MY_UNPACK_FILENAME);
4607
unlink(timer_file); /* Ignore error, may not exist */
4613
my_free(opt_pass, MYF(MY_ALLOW_ZERO_PTR));
4614
opt_pass= my_strdup(argument, MYF(MY_FAE));
4615
while (*argument) *argument++= 'x'; /* Destroy argument */
4622
stpncpy(TMPDIR, argument, sizeof(TMPDIR));
4625
if (!embedded_server_arg_count)
4627
embedded_server_arg_count=1;
4628
embedded_server_args[0]= (char*) "";
4630
if (embedded_server_arg_count == MAX_EMBEDDED_SERVER_ARGS-1 ||
4631
!(embedded_server_args[embedded_server_arg_count++]=
4632
my_strdup(argument, MYF(MY_FAE))))
4634
die("Can't use server argument");
4638
read_embedded_server_arguments(argument);
4651
static int parse_args(int argc, char **argv)
4653
load_defaults("my",load_default_groups,&argc,&argv);
4656
if ((handle_options(&argc, &argv, my_long_options, get_one_option)))
4667
opt_pass= get_tty_password(NullS); /* purify tested */
4668
if (debug_info_flag)
4669
my_end_arg= MY_CHECK_ERROR | MY_GIVE_INFO;
4670
if (debug_check_flag)
4671
my_end_arg= MY_CHECK_ERROR;
4646
4677
Write the content of str into file
4932
4959
int flags, char *query, int query_len,
4933
4960
string *ds, string *ds_warnings)
4935
drizzle_result_st res;
4936
drizzle_return_t ret;
4937
drizzle_con_st *con= &cn->con;
4940
drizzle_con_add_options(con, DRIZZLE_CON_NO_RESULT_READ);
4962
DRIZZLE_RES *res= 0;
4963
DRIZZLE *drizzle= &cn->drizzle;
4964
int err= 0, counter= 0;
4942
4966
if (flags & QUERY_SEND_FLAG)
4945
4969
* Send the query
4948
(void) drizzle_query(con, &res, query, query_len, &ret);
4949
if (ret != DRIZZLE_RETURN_OK)
4971
if (do_send_query(cn, query, query_len, flags))
4951
if (ret == DRIZZLE_RETURN_ERROR_CODE ||
4952
ret == DRIZZLE_RETURN_HANDSHAKE_FAILED)
4954
err= drizzle_result_error_code(&res);
4955
handle_error(command, err, drizzle_result_error(&res),
4956
drizzle_result_sqlstate(&res), ds);
4957
if (ret == DRIZZLE_RETURN_ERROR_CODE)
4958
drizzle_result_free(&res);
4962
handle_error(command, ret, drizzle_con_error(con), "", ds);
4973
handle_error(command, drizzle_errno(drizzle), drizzle_error(drizzle),
4974
drizzle_sqlstate(drizzle), ds);
4968
4978
if (!(flags & QUERY_REAP_FLAG))
4973
* Read the result packet
4975
if (drizzle_result_read(con, &res, &ret) == NULL ||
4976
ret != DRIZZLE_RETURN_OK)
4984
When on first result set, call drizzle_read_query_result to retrieve
4985
answer to the query sent earlier
4987
if ((counter==0) && drizzle_read_query_result(drizzle))
4978
if (ret == DRIZZLE_RETURN_ERROR_CODE)
4980
handle_error(command, drizzle_result_error_code(&res),
4981
drizzle_result_error(&res), drizzle_result_sqlstate(&res),
4985
handle_error(command, ret, drizzle_con_error(con), "", ds);
4986
drizzle_result_free(&res);
4989
handle_error(command, drizzle_errno(drizzle), drizzle_error(drizzle),
4990
drizzle_sqlstate(drizzle), ds);
4992
4996
Store the result of the query if it will return any fields
4994
if (drizzle_result_column_count(&res) &&
4995
(ret= drizzle_result_buffer(&res)) != DRIZZLE_RETURN_OK)
4998
if (drizzle_field_count(drizzle) && ((res= drizzle_store_result(drizzle)) == 0))
4997
if (ret == DRIZZLE_RETURN_ERROR_CODE)
4999
handle_error(command, drizzle_result_error_code(&res),
5000
drizzle_result_error(&res), drizzle_result_sqlstate(&res),
5004
handle_error(command, ret, drizzle_con_error(con), "", ds);
5005
drizzle_result_free(&res);
5000
handle_error(command, drizzle_errno(drizzle), drizzle_error(drizzle),
5001
drizzle_sqlstate(drizzle), ds);
5396
static void mark_progress(struct st_command*, int line)
5406
static void mark_progress(struct st_command* command __attribute__((unused)),
5398
5410
uint64_t timer= timer_now();
5399
5411
if (!progress_start)
5400
5412
progress_start= timer;
5401
5413
timer-= progress_start;
5404
5415
/* Milliseconds since start */
5405
buf << timer << "\t";
5416
end= int64_t2str(timer, buf, 10);
5417
ds_progress.append(buf, (int)(end-buf));
5418
ds_progress.append("\t", 1);
5407
5420
/* Parser line number */
5408
buf << line << "\t";
5421
end= int10_to_str(line, buf, 10);
5422
ds_progress.append(buf, (int)(end-buf));
5423
ds_progress.append("\t", 1);
5411
buf << cur_file->file_name << ":";
5426
ds_progress.append(cur_file->file_name);
5427
ds_progress.append(":", 1);
5413
5429
/* Line in file */
5414
buf << cur_file->lineno << endl;
5416
ds_progress.append(buf.str());
5420
static void check_retries(uint32_t in_opt_max_connect_retries)
5422
if (in_opt_max_connect_retries > 10000 || opt_max_connect_retries<1)
5424
cout << N_("Error: Invalid Value for opt_max_connect_retries");
5427
opt_max_connect_retries= in_opt_max_connect_retries;
5430
static void check_tail_lines(uint32_t in_opt_tail_lines)
5432
if (in_opt_tail_lines > 10000)
5434
cout << N_("Error: Invalid Value for opt_tail_lines");
5437
opt_tail_lines= in_opt_tail_lines;
5440
static void check_sleep(int32_t in_opt_sleep)
5442
if (in_opt_sleep < -1)
5444
cout << N_("Error: Invalid Value for opt_sleep");
5447
opt_sleep= in_opt_sleep;
5430
end= int10_to_str(cur_file->lineno, buf, 10);
5431
ds_progress.append(buf, (int)(end-buf));
5434
ds_progress.append("\n", 1);
5450
5439
int main(int argc, char **argv)
5454
5441
struct st_command *command;
5455
5442
bool q_send_flag= 0, abort_flag= 0;
5456
uint32_t command_executed= 0, last_command_executed= 0;
5457
string save_file("");
5443
uint command_executed= 0, last_command_executed= 0;
5444
char save_file[FN_REFLEN];
5458
5445
struct stat res_info;
5462
internal::my_init();
5464
po::options_description commandline_options("Options used only in command line");
5465
commandline_options.add_options()
5466
("help,?", "Display this help and exit.")
5467
("mark-progress", po::value<bool>(&opt_mark_progress)->default_value(false)->zero_tokens(),
5468
"Write linenumber and elapsed time to <testname>.progress ")
5469
("sleep,T", po::value<int32_t>(&opt_sleep)->default_value(-1)->notifier(&check_sleep),
5470
"Sleep always this many seconds on sleep commands.")
5471
("test-file,x", po::value<string>(),
5472
"Read test from/in this file (default stdin).")
5473
("timer-file,f", po::value<string>(),
5474
"File where the timing in micro seconds is stored.")
5475
("tmpdir,t", po::value<string>(),
5476
"Temporary directory where sockets are put.")
5477
("verbose,v", po::value<bool>(&verbose)->default_value(false),
5479
("version,V", "Output version information and exit.")
5480
("no-defaults", po::value<bool>()->default_value(false)->zero_tokens(),
5481
"Configuration file defaults are not used if no-defaults is set")
5484
po::options_description test_options("Options specific to the drizzleimport");
5485
test_options.add_options()
5486
("basedir,b", po::value<string>(&opt_basedir)->default_value(""),
5487
"Basedir for tests.")
5488
("character-sets-dir", po::value<string>(&opt_charsets_dir)->default_value(""),
5489
"Directory where character sets are.")
5490
("database,D", po::value<string>(&opt_db)->default_value(""),
5492
("include,i", po::value<string>(&opt_include)->default_value(""),
5493
"Include SQL before each test case.")
5494
("testdir", po::value<string>(&opt_testdir)->default_value(""),
5495
"Path to use to search for test files")
5496
("logdir", po::value<string>(&opt_logdir)->default_value(""),
5497
"Directory for log files")
5498
("max-connect-retries", po::value<uint32_t>(&opt_max_connect_retries)->default_value(500)->notifier(&check_retries),
5499
"Max number of connection attempts when connecting to server")
5500
("quiet,s", po::value<bool>(&silent)->default_value(false)->zero_tokens(),
5501
"Suppress all normal output.")
5502
("record,r", "Record output of test_file into result file.")
5503
("result-file,R", po::value<string>(&result_file_name)->default_value(""),
5504
"Read/Store result from/in this file.")
5505
("silent,s", po::value<bool>(&silent)->default_value(false)->zero_tokens(),
5506
"Suppress all normal output. Synonym for --quiet.")
5507
("tail-lines", po::value<uint32_t>(&opt_tail_lines)->default_value(0)->notifier(&check_tail_lines),
5508
"Number of lines of the resul to include in a failure report")
5511
po::options_description client_options("Options specific to the client");
5512
client_options.add_options()
5514
("host,h", po::value<string>(&opt_host)->default_value("localhost"),
5516
("password,P", po::value<string>(&password)->default_value("PASSWORD_SENTINEL"),
5517
"Password to use when connecting to server.")
5518
("port,p", po::value<uint32_t>(&opt_port)->default_value(0),
5519
"Port number to use for connection or 0 for default")
5520
("protocol", po::value<string>(&opt_protocol),
5521
"The protocol of connection (mysql or drizzle).")
5522
("user,u", po::value<string>(&opt_user)->default_value(""),
5526
po::positional_options_description p;
5527
p.add("database", 1);
5529
po::options_description long_options("Allowed Options");
5530
long_options.add(commandline_options).add(test_options).add(client_options);
5532
std::string system_config_dir_test(SYSCONFDIR);
5533
system_config_dir_test.append("/drizzle/drizzletest.cnf");
5535
std::string system_config_dir_client(SYSCONFDIR);
5536
system_config_dir_client.append("/drizzle/client.cnf");
5538
std::string user_config_dir((getenv("XDG_CONFIG_HOME")? getenv("XDG_CONFIG_HOME"):"~/.config"));
5540
if (user_config_dir.compare(0, 2, "~/") == 0)
5543
homedir= getenv("HOME");
5544
if (homedir != NULL)
5545
user_config_dir.replace(0, 1, homedir);
5548
po::variables_map vm;
5550
// Disable allow_guessing
5551
int style = po::command_line_style::default_style & ~po::command_line_style::allow_guessing;
5553
po::store(po::command_line_parser(argc, argv).options(long_options).
5554
style(style).positional(p).extra_parser(parse_password_arg).run(),
5557
if (! vm["no-defaults"].as<bool>())
5559
std::string user_config_dir_test(user_config_dir);
5560
user_config_dir_test.append("/drizzle/drizzletest.cnf");
5562
std::string user_config_dir_client(user_config_dir);
5563
user_config_dir_client.append("/drizzle/client.cnf");
5565
ifstream user_test_ifs(user_config_dir_test.c_str());
5566
po::store(parse_config_file(user_test_ifs, test_options), vm);
5568
ifstream user_client_ifs(user_config_dir_client.c_str());
5569
po::store(parse_config_file(user_client_ifs, client_options), vm);
5571
ifstream system_test_ifs(system_config_dir_test.c_str());
5572
store(parse_config_file(system_test_ifs, test_options), vm);
5574
ifstream system_client_ifs(system_config_dir_client.c_str());
5575
po::store(parse_config_file(system_client_ifs, client_options), vm);
5580
5451
/* Init expected errors */
5581
5452
memset(&saved_expected_errors, 0, sizeof(saved_expected_errors));
5613
5488
ds_progress.reserve(2048);
5614
5489
ds_warning_messages.reserve(2048);
5617
if (vm.count("record"))
5622
if (vm.count("test-file"))
5624
string tmp= vm["test-file"].as<string>();
5625
char buff[FN_REFLEN];
5626
if (!internal::test_if_hard_path(tmp.c_str()))
5628
snprintf(buff, sizeof(buff), "%s%s",opt_basedir.c_str(),tmp.c_str());
5631
internal::fn_format(buff, tmp.c_str(), "", "", MY_UNPACK_FILENAME);
5632
assert(cur_file == file_stack && cur_file->file == 0);
5633
if (!(cur_file->file= fopen(buff, "r")))
5635
fprintf(stderr, _("Could not open '%s' for reading: errno = %d"), buff, errno);
5636
return EXIT_ARGUMENT_INVALID;
5638
if (!(cur_file->file_name= strdup(buff)))
5640
fprintf(stderr, _("Out of memory"));
5641
return EXIT_OUT_OF_MEMORY;
5643
cur_file->lineno= 1;
5646
if (vm.count("timer-file"))
5648
string tmp= vm["timer-file"].as<string>().c_str();
5649
static char buff[FN_REFLEN];
5650
if (!internal::test_if_hard_path(tmp.c_str()))
5652
snprintf(buff, sizeof(buff), "%s%s",opt_basedir.c_str(),tmp.c_str());
5655
internal::fn_format(buff, tmp.c_str(), "", "", MY_UNPACK_FILENAME);
5657
unlink(timer_file); /* Ignore error, may not exist */
5660
if (vm.count("protocol"))
5662
std::transform(opt_protocol.begin(), opt_protocol.end(),
5663
opt_protocol.begin(), ::tolower);
5665
if (not opt_protocol.compare("mysql"))
5666
use_drizzle_protocol=false;
5667
else if (not opt_protocol.compare("drizzle"))
5668
use_drizzle_protocol=true;
5671
cout << _("Error: Unknown protocol") << " '" << opt_protocol << "'" << endl;
5676
if (vm.count("port"))
5678
/* If the port number is > 65535 it is not a valid port
5679
This also helps with potential data loss casting unsigned long to a
5681
if (opt_port > 65535)
5683
fprintf(stderr, _("Value supplied for port is not valid.\n"));
5684
exit(EXIT_ARGUMENT_INVALID);
5688
if( vm.count("password") )
5690
if (!opt_password.empty())
5691
opt_password.erase();
5692
if (password == PASSWORD_SENTINEL)
5698
opt_password= password;
5699
tty_password= false;
5707
if (vm.count("tmpdir"))
5709
strncpy(TMPDIR, vm["tmpdir"].as<string>().c_str(), sizeof(TMPDIR));
5712
if (vm.count("version"))
5714
printf("%s Ver %s Distrib %s, for %s-%s (%s)\n",internal::my_progname,MTEST_VERSION,
5715
drizzle_version(),HOST_VENDOR,HOST_OS,HOST_CPU);
5719
if (vm.count("help"))
5721
printf("%s Ver %s Distrib %s, for %s-%s (%s)\n",internal::my_progname,MTEST_VERSION,
5722
drizzle_version(),HOST_VENDOR,HOST_OS,HOST_CPU);
5723
printf("MySQL AB, by Sasha, Matt, Monty & Jani\n");
5724
printf("Drizzle version modified by Brian, Jay, Monty Taylor, PatG and Stewart\n");
5725
printf("This software comes with ABSOLUTELY NO WARRANTY\n\n");
5726
printf("Runs a test against the DRIZZLE server and compares output with a results file.\n\n");
5727
printf("Usage: %s [OPTIONS] [database] < test_file\n", internal::my_progname);
5733
opt_pass= client_get_tty_password(NULL); /* purify tested */
5491
parse_args(argc, argv);
5736
5493
server_initialized= 1;
5737
5494
if (cur_file == file_stack && cur_file->file == 0)
5739
5496
cur_file->file= stdin;
5740
cur_file->file_name= strdup("<stdin>");
5741
if (cur_file->file_name == NULL)
5742
die("Out of memory");
5497
cur_file->file_name= my_strdup("<stdin>", MYF(MY_WME));
5743
5498
cur_file->lineno= 1;
5745
5500
cur_con= connections;
5746
if ((cur_con->drizzle= drizzle_create(NULL)) == NULL)
5501
if (!( drizzle_create(&cur_con->drizzle)))
5747
5502
die("Failed in drizzle_create()");
5748
if (!( drizzle_con_create(cur_con->drizzle, &cur_con->con)))
5749
die("Failed in drizzle_con_create()");
5750
drizzle_con_add_options(&cur_con->con, use_drizzle_protocol ? DRIZZLE_CON_EXPERIMENTAL : DRIZZLE_CON_MYSQL);
5504
drizzle_options(&cur_con->drizzle,DRIZZLE_OPT_COMPRESS,NullS);
5505
drizzle_options(&cur_con->drizzle, DRIZZLE_OPT_LOCAL_INFILE, 0);
5506
drizzle_options(&cur_con->drizzle, DRIZZLE_SET_CHARSET_NAME,
5507
charset_info->csname);
5508
int opt_protocol= DRIZZLE_PROTOCOL_TCP;
5509
drizzle_options(&cur_con->drizzle,DRIZZLE_OPT_PROTOCOL,(char*)&opt_protocol);
5510
if (opt_charsets_dir)
5511
drizzle_options(&cur_con->drizzle, DRIZZLE_SET_CHARSET_DIR,
5752
if (!(cur_con->name = strdup("default")))
5514
if (!(cur_con->name = my_strdup("default", MYF(MY_WME))))
5753
5515
die("Out of memory");
5754
safe_connect(&cur_con->con, cur_con->name, opt_host, opt_user, opt_pass,
5517
safe_connect(&cur_con->drizzle, cur_con->name, opt_host, opt_user, opt_pass,
5755
5518
opt_db, opt_port);
5757
fill_global_error_names();
5759
5520
/* Use all time until exit if no explicit 'start_timer' */
5760
5521
timer_start= timer_now();
5763
Initialize $drizzleclient_errno with -1, so we can
5524
Initialize $drizzle_errno with -1, so we can
5764
5525
- distinguish it from valid values ( >= 0 ) and
5765
5526
- detect if there was never a command sent to the server
5767
5528
var_set_errno(-1);
5769
/* Update $drizzleclient_get_server_version to that of current connection */
5770
var_set_drizzleclient_get_server_version(&cur_con->con);
5530
/* Update $drizzle_get_server_version to that of current connection */
5531
var_set_drizzle_get_server_version(&cur_con->drizzle);
5772
if (! opt_include.empty())
5774
open_file(opt_include.c_str());
5535
open_file(opt_include);
5777
5538
while (!read_command(&command) && !abort_flag)
6666
6400
icase - flag, if set to 1 the match is case insensitive
6668
6402
int reg_replace(char** buf_p, int* buf_len_p, char *pattern,
6669
char *replace, char *in_string, int icase, int global)
6403
char *replace, char *in_string, int icase)
6671
const char *error= NULL;
6674
pcre *re= pcre_compile(pattern,
6675
icase ? PCRE_CASELESS | PCRE_MULTILINE : PCRE_MULTILINE,
6676
&error, &erroffset, NULL);
6683
int rc= pcre_exec(re, NULL, in_string, (int)strlen(in_string),
6691
char *substring_to_replace= in_string + ovector[0];
6692
int substring_length= ovector[1] - ovector[0];
6693
*buf_len_p= strlen(in_string) - substring_length + strlen(replace);
6694
char * new_buf = (char *)malloc(*buf_len_p+1);
6695
if (new_buf == NULL)
6701
memset(new_buf, 0, *buf_len_p+1);
6702
strncpy(new_buf, in_string, substring_to_replace-in_string);
6703
strncpy(new_buf+(substring_to_replace-in_string), replace, strlen(replace));
6704
strncpy(new_buf+(substring_to_replace-in_string)+strlen(replace),
6705
substring_to_replace + substring_length,
6708
- (substring_to_replace-in_string));
6716
/* Repeatedly replace the string with the matched regex */
6717
string subject(in_string);
6718
size_t replace_length= strlen(replace);
6719
size_t length_of_replacement= strlen(replace);
6720
size_t current_position= 0;
6725
rc= pcre_exec(re, NULL, subject.c_str(), subject.length(),
6726
current_position, 0, ovector, 3);
6732
current_position= static_cast<size_t>(ovector[0]);
6733
replace_length= static_cast<size_t>(ovector[1] - ovector[0]);
6734
subject.replace(current_position, replace_length, replace, length_of_replacement);
6735
current_position= current_position + length_of_replacement;
6738
char *new_buf = (char *) malloc(subject.length() + 1);
6739
if (new_buf == NULL)
6744
memset(new_buf, 0, subject.length() + 1);
6745
strncpy(new_buf, subject.c_str(), subject.length());
6746
*buf_len_p= subject.length() + 1;
6405
string string_to_match(in_string);
6406
pcrecpp::RE_Options opt;
6409
opt.set_caseless(true);
6411
if (!pcrecpp::RE(pattern, opt).Replace(replace,&string_to_match)){
6415
const char * new_str= string_to_match.c_str();
6416
*buf_len_p= strlen(new_str);
6417
char * new_buf = (char *)malloc(*buf_len_p+1);
6418
if (new_buf == NULL)
6422
strcpy(new_buf, new_str);
6755
6429
#ifndef WORD_BIT
6756
#define WORD_BIT (8*sizeof(uint32_t))
6430
#define WORD_BIT (8*sizeof(uint))
6759
6433
#define SET_MALLOC_HUNC 64
6760
6434
#define LAST_CHAR_CODE 259
6762
6436
typedef struct st_rep_set {
6763
uint32_t *bits; /* Pointer to used sets */
6437
uint *bits; /* Pointer to used sets */
6764
6438
short next[LAST_CHAR_CODE]; /* Pointer to next sets */
6765
uint32_t found_len; /* Best match to date */
6439
uint found_len; /* Best match to date */
6766
6440
int found_offset;
6767
uint32_t table_offset;
6768
uint32_t size_of_bits; /* For convinience */
6442
uint size_of_bits; /* For convinience */
6771
6445
typedef struct st_rep_sets {
6772
uint32_t count; /* Number of sets */
6773
uint32_t extra; /* Extra sets in buffer */
6774
uint32_t invisible; /* Sets not chown */
6775
uint32_t size_of_bits;
6446
uint count; /* Number of sets */
6447
uint extra; /* Extra sets in buffer */
6448
uint invisible; /* Sets not chown */
6776
6450
REP_SET *set,*set_buffer;
6777
uint32_t *bit_buffer;
6780
6454
typedef struct st_found_set {
6781
uint32_t table_offset;
6782
6456
int found_offset;
6785
6459
typedef struct st_follow {
6787
uint32_t table_offset;
6792
int init_sets(REP_SETS *sets,uint32_t states);
6466
int init_sets(REP_SETS *sets,uint states);
6793
6467
REP_SET *make_new_set(REP_SETS *sets);
6794
6468
void make_sets_invisible(REP_SETS *sets);
6795
6469
void free_last_set(REP_SETS *sets);
6796
6470
void free_sets(REP_SETS *sets);
6797
void internal_set_bit(REP_SET *set, uint32_t bit);
6798
void internal_clear_bit(REP_SET *set, uint32_t bit);
6471
void internal_set_bit(REP_SET *set, uint bit);
6472
void internal_clear_bit(REP_SET *set, uint bit);
6799
6473
void or_bits(REP_SET *to,REP_SET *from);
6800
6474
void copy_bits(REP_SET *to,REP_SET *from);
6801
6475
int cmp_bits(REP_SET *set1,REP_SET *set2);
6802
int get_next_bit(REP_SET *set,uint32_t lastpos);
6476
int get_next_bit(REP_SET *set,uint lastpos);
6803
6477
int find_set(REP_SETS *sets,REP_SET *find);
6804
int find_found(FOUND_SET *found_set,uint32_t table_offset,
6478
int find_found(FOUND_SET *found_set,uint table_offset,
6805
6479
int found_offset);
6806
uint32_t start_at_word(char * pos);
6807
uint32_t end_of_word(char * pos);
6809
static uint32_t found_sets=0;
6812
static uint32_t replace_len(char * str)
6480
uint start_at_word(char * pos);
6481
uint end_of_word(char * pos);
6483
static uint found_sets=0;
6486
static uint replace_len(char * str)
6817
6491
if (str[0] == '\\' && str[1])