4542
static struct my_option my_long_options[] =
4544
{"help", '?', "Display this help and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG,
4546
{"basedir", 'b', "Basedir for tests.", (char**) &opt_basedir,
4547
(char**) &opt_basedir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
4548
{"character-sets-dir", OPT_CHARSETS_DIR,
4549
"Directory where character sets are.", (char**) &opt_charsets_dir,
4550
(char**) &opt_charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
4551
{"compress", 'C', "Use the compressed server/client protocol.",
4552
(char**) &opt_compress, (char**) &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0,
4554
{"database", 'D', "Database to use.", (char**) &opt_db, (char**) &opt_db, 0,
4555
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
4556
{"debug-check", OPT_DEBUG_CHECK, "Check memory and open file usage at exit.",
4557
(char**) &debug_check_flag, (char**) &debug_check_flag, 0,
4558
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
4559
{"debug-info", OPT_DEBUG_INFO, "Print some debug info at exit.",
4560
(char**) &debug_info_flag, (char**) &debug_info_flag,
4561
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
4562
{"host", 'h', "Connect to host.", (char**) &opt_host, (char**) &opt_host, 0,
4563
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
4564
{"include", 'i', "Include SQL before each test case.", (char**) &opt_include,
4565
(char**) &opt_include, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
4566
{"testdir", OPT_TESTDIR, "Path to use to search for test files",
4567
(char**) &opt_testdir,
4568
(char**) &opt_testdir, 0,GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
4569
{"logdir", OPT_LOG_DIR, "Directory for log files", (char**) &opt_logdir,
4570
(char**) &opt_logdir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
4571
{"mark-progress", OPT_MARK_PROGRESS,
4572
"Write linenumber and elapsed time to <testname>.progress ",
4573
(char**) &opt_mark_progress, (char**) &opt_mark_progress, 0,
4574
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
4575
{"max-connect-retries", OPT_MAX_CONNECT_RETRIES,
4576
"Max number of connection attempts when connecting to server",
4577
(char**) &opt_max_connect_retries, (char**) &opt_max_connect_retries, 0,
4578
GET_INT, REQUIRED_ARG, 500, 1, 10000, 0, 0, 0},
4579
{"password", 'P', "Password to use when connecting to server.",
4580
0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
4581
{"port", 'p', "Port number to use for connection or 0 for default to, in "
4582
"order of preference, drizzle.cnf, $DRIZZLE_TCP_PORT, "
4583
"built-in default (" STRINGIFY_ARG(DRIZZLE_PORT) ").",
4584
0, 0, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
4585
{"quiet", 's', "Suppress all normal output.", (char**) &silent,
4586
(char**) &silent, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
4587
{"record", 'r', "Record output of test_file into result file.",
4588
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
4589
{"result-file", 'R', "Read/Store result from/in this file.",
4590
(char**) &result_file_name, (char**) &result_file_name, 0,
4591
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
4592
{"server-arg", 'A', "Send option value to embedded server as a parameter.",
4593
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
4594
{"server-file", 'F', "Read embedded server arguments from file.",
4595
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
4596
{"silent", 's', "Suppress all normal output. Synonym for --quiet.",
4597
(char**) &silent, (char**) &silent, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
4598
{"sleep", 'T', "Sleep always this many seconds on sleep commands.",
4599
(char**) &opt_sleep, (char**) &opt_sleep, 0, GET_INT, REQUIRED_ARG, -1, -1, 0,
4601
{"tail-lines", OPT_TAIL_LINES,
4602
"Number of lines of the resul to include in a failure report",
4603
(char**) &opt_tail_lines, (char**) &opt_tail_lines, 0,
4604
GET_INT, REQUIRED_ARG, 0, 0, 10000, 0, 0, 0},
4605
{"test-file", 'x', "Read test from/in this file (default stdin).",
4606
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
4607
{"timer-file", 'm', "File where the timing in micro seconds is stored.",
4608
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
4609
{"tmpdir", 't', "Temporary directory where sockets are put.",
4610
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
4611
{"user", 'u', "User for login.", (char**) &opt_user, (char**) &opt_user, 0,
4612
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
4613
{"verbose", 'v', "Write more.", (char**) &verbose, (char**) &verbose, 0,
4614
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
4615
{"version", 'V', "Output version information and exit.",
4616
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
4617
{ 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
4621
static void print_version(void)
4623
printf("%s Ver %s Distrib %s, for %s-%s (%s)\n",my_progname,MTEST_VERSION,
4624
drizzle_version(),HOST_VENDOR,HOST_OS,HOST_CPU);
4627
static void usage(void)
4630
printf("MySQL AB, by Sasha, Matt, Monty & Jani\n");
4631
printf("This software comes with ABSOLUTELY NO WARRANTY\n\n");
4632
printf("Runs a test against the DRIZZLE server and compares output with a results file.\n\n");
4633
printf("Usage: %s [OPTIONS] [database] < test_file\n", my_progname);
4634
my_print_help(my_long_options);
4635
printf(" --no-defaults Don't read default options from any options file.\n");
4636
my_print_variables(my_long_options);
4640
Read arguments for embedded server and put them into
4641
embedded_server_args[]
4644
static void read_embedded_server_arguments(const char *name)
4646
char argument[1024],buff[FN_REFLEN], *str=0;
4649
if (!test_if_hard_path(name))
4651
sprintf(buff,"%s%s",opt_basedir,name);
4654
fn_format(buff, name, "", "", MY_UNPACK_FILENAME);
4656
if (!embedded_server_arg_count)
4658
embedded_server_arg_count=1;
4659
embedded_server_args[0]= (char*) ""; /* Progname */
4661
if (!(file= fopen(buff, "r")))
4662
die("Failed to open file '%s'", buff);
4664
while (embedded_server_arg_count < MAX_EMBEDDED_SERVER_ARGS &&
4665
(str=fgets(argument,sizeof(argument), file)))
4667
*(strchr(str, '\0')-1)=0; /* Remove end newline */
4668
if (!(embedded_server_args[embedded_server_arg_count]=
4669
(char*) strdup(str)))
4672
die("Out of memory");
4675
embedded_server_arg_count++;
4679
die("Too many arguments in option file: %s",name);
4685
bool get_one_option(int optid, const struct my_option *, char *argument)
4687
char *endchar= NULL;
4688
uint64_t temp_drizzle_port= 0;
4696
char buff[FN_REFLEN];
4697
if (!test_if_hard_path(argument))
4699
sprintf(buff,"%s%s",opt_basedir,argument);
4702
fn_format(buff, argument, "", "", MY_UNPACK_FILENAME);
4703
assert(cur_file == file_stack && cur_file->file == 0);
4704
if (!(cur_file->file= fopen(buff, "r")))
4705
die("Could not open '%s' for reading: errno = %d", buff, errno);
4706
if (!(cur_file->file_name= strdup(buff)))
4707
die("Out of memory");
4708
cur_file->lineno= 1;
4713
static char buff[FN_REFLEN];
4714
if (!test_if_hard_path(argument))
4716
sprintf(buff,"%s%s",opt_basedir,argument);
4719
fn_format(buff, argument, "", "", MY_UNPACK_FILENAME);
4721
unlink(timer_file); /* Ignore error, may not exist */
4725
temp_drizzle_port= (uint64_t) strtoul(argument, &endchar, 10);
4726
/* if there is an alpha character this is not a valid port */
4727
if (strlen(endchar) != 0)
4729
fprintf(stderr, _("Non-integer value supplied for port. If you are trying to enter a password please use --password instead.\n"));
4732
/* If the port number is > 65535 it is not a valid port
4733
This also helps with potential data loss casting unsigned long to a
4735
if ((temp_drizzle_port == 0) || (temp_drizzle_port > 65535))
4737
fprintf(stderr, _("Value supplied for port is not valid.\n"));
4742
opt_port= (uint32_t) temp_drizzle_port;
4750
opt_pass = strdup(argument);
4751
if (opt_pass == NULL)
4752
die("Out of memory");
4755
/* Overwriting password with 'x' */
4764
strncpy(TMPDIR, argument, sizeof(TMPDIR));
4767
if (!embedded_server_arg_count)
4769
embedded_server_arg_count=1;
4770
embedded_server_args[0]= (char*) "";
4772
if (embedded_server_arg_count == MAX_EMBEDDED_SERVER_ARGS-1 ||
4773
!(embedded_server_args[embedded_server_arg_count++]=
4776
die("Can't use server argument");
4780
read_embedded_server_arguments(argument);
4793
static int parse_args(int argc, char **argv)
4795
load_defaults("drizzle",load_default_groups,&argc,&argv);
4798
if ((handle_options(&argc, &argv, my_long_options, get_one_option)))
4809
opt_pass= client_get_tty_password(NULL); /* purify tested */
4810
if (debug_info_flag)
4811
my_end_arg= MY_CHECK_ERROR | MY_GIVE_INFO;
4812
if (debug_check_flag)
4813
my_end_arg= MY_CHECK_ERROR;
4624
4819
Write the content of str into file
5398
static void check_retries(uint32_t in_opt_max_connect_retries)
5400
if (in_opt_max_connect_retries > 10000 || opt_max_connect_retries<1)
5402
cout << N_("Error: Invalid Value for opt_max_connect_retries");
5405
opt_max_connect_retries= in_opt_max_connect_retries;
5408
static void check_tail_lines(uint32_t in_opt_tail_lines)
5410
if (in_opt_tail_lines > 10000)
5412
cout << N_("Error: Invalid Value for opt_tail_lines");
5415
opt_tail_lines= in_opt_tail_lines;
5418
static void check_sleep(int32_t in_opt_sleep)
5420
if (in_opt_sleep < -1)
5422
cout << N_("Error: Invalid Value for opt_sleep");
5425
opt_sleep= in_opt_sleep;
5428
5594
int main(int argc, char **argv)
5432
5596
struct st_command *command;
5433
5597
bool q_send_flag= 0, abort_flag= 0;
5434
5598
uint32_t command_executed= 0, last_command_executed= 0;
5435
string save_file("");
5599
char save_file[FN_REFLEN];
5436
5600
struct stat res_info;
5440
internal::my_init();
5442
po::options_description commandline_options("Options used only in command line");
5443
commandline_options.add_options()
5444
("help,?", "Display this help and exit.")
5445
("mark-progress", po::value<bool>(&opt_mark_progress)->default_value(false)->zero_tokens(),
5446
"Write linenumber and elapsed time to <testname>.progress ")
5447
("sleep,T", po::value<int32_t>(&opt_sleep)->default_value(-1)->notifier(&check_sleep),
5448
"Sleep always this many seconds on sleep commands.")
5449
("test-file,x", po::value<string>(),
5450
"Read test from/in this file (default stdin).")
5451
("timer-file,f", po::value<string>(),
5452
"File where the timing in micro seconds is stored.")
5453
("tmpdir,t", po::value<string>(),
5454
"Temporary directory where sockets are put.")
5455
("verbose,v", po::value<bool>(&verbose)->default_value(false),
5457
("version,V", "Output version information and exit.")
5458
("no-defaults", po::value<bool>()->default_value(false)->zero_tokens(),
5459
"Configuration file defaults are not used if no-defaults is set")
5462
po::options_description test_options("Options specific to the drizzleimport");
5463
test_options.add_options()
5464
("basedir,b", po::value<string>(&opt_basedir)->default_value(""),
5465
"Basedir for tests.")
5466
("character-sets-dir", po::value<string>(&opt_charsets_dir)->default_value(""),
5467
"Directory where character sets are.")
5468
("database,D", po::value<string>(&opt_db)->default_value(""),
5470
("include,i", po::value<string>(&opt_include)->default_value(""),
5471
"Include SQL before each test case.")
5472
("testdir", po::value<string>(&opt_testdir)->default_value(""),
5473
"Path to use to search for test files")
5474
("logdir", po::value<string>(&opt_logdir)->default_value(""),
5475
"Directory for log files")
5476
("max-connect-retries", po::value<uint32_t>(&opt_max_connect_retries)->default_value(500)->notifier(&check_retries),
5477
"Max number of connection attempts when connecting to server")
5478
("quiet,s", po::value<bool>(&silent)->default_value(false)->zero_tokens(),
5479
"Suppress all normal output.")
5480
("record,r", "Record output of test_file into result file.")
5481
("result-file,R", po::value<string>(&result_file_name)->default_value(""),
5482
"Read/Store result from/in this file.")
5483
("silent,s", po::value<bool>(&silent)->default_value(false)->zero_tokens(),
5484
"Suppress all normal output. Synonym for --quiet.")
5485
("tail-lines", po::value<uint32_t>(&opt_tail_lines)->default_value(0)->notifier(&check_tail_lines),
5486
"Number of lines of the resul to include in a failure report")
5489
po::options_description client_options("Options specific to the client");
5490
client_options.add_options()
5492
("host,h", po::value<string>(&opt_host)->default_value("localhost"),
5494
("password,P", po::value<string>(&password)->default_value("PASSWORD_SENTINEL"),
5495
"Password to use when connecting to server.")
5496
("port,p", po::value<uint32_t>(&opt_port)->default_value(0),
5497
"Port number to use for connection or 0 for default")
5498
("protocol", po::value<string>(&opt_protocol),
5499
"The protocol of connection (mysql or drizzle).")
5500
("user,u", po::value<string>(&opt_user)->default_value(""),
5504
po::positional_options_description p;
5505
p.add("database", 1);
5507
po::options_description long_options("Allowed Options");
5508
long_options.add(commandline_options).add(test_options).add(client_options);
5510
std::string system_config_dir_test(SYSCONFDIR);
5511
system_config_dir_test.append("/drizzle/drizzletest.cnf");
5513
std::string system_config_dir_client(SYSCONFDIR);
5514
system_config_dir_client.append("/drizzle/client.cnf");
5516
std::string user_config_dir((getenv("XDG_CONFIG_HOME")? getenv("XDG_CONFIG_HOME"):"~/.config"));
5518
if (user_config_dir.compare(0, 2, "~/") == 0)
5521
homedir= getenv("HOME");
5522
if (homedir != NULL)
5523
user_config_dir.replace(0, 1, homedir);
5526
po::variables_map vm;
5528
// Disable allow_guessing
5529
int style = po::command_line_style::default_style & ~po::command_line_style::allow_guessing;
5531
po::store(po::command_line_parser(argc, argv).options(long_options).
5532
style(style).positional(p).extra_parser(parse_password_arg).run(),
5535
if (! vm["no-defaults"].as<bool>())
5537
std::string user_config_dir_test(user_config_dir);
5538
user_config_dir_test.append("/drizzle/drizzletest.cnf");
5540
std::string user_config_dir_client(user_config_dir);
5541
user_config_dir_client.append("/drizzle/client.cnf");
5543
ifstream user_test_ifs(user_config_dir_test.c_str());
5544
po::store(parse_config_file(user_test_ifs, test_options), vm);
5546
ifstream user_client_ifs(user_config_dir_client.c_str());
5547
po::store(parse_config_file(user_client_ifs, client_options), vm);
5549
ifstream system_test_ifs(system_config_dir_test.c_str());
5550
store(parse_config_file(system_test_ifs, test_options), vm);
5552
ifstream system_client_ifs(system_config_dir_client.c_str());
5553
po::store(parse_config_file(system_client_ifs, client_options), vm);
5558
5606
/* Init expected errors */
5559
5607
memset(&saved_expected_errors, 0, sizeof(saved_expected_errors));
5591
5643
ds_progress.reserve(2048);
5592
5644
ds_warning_messages.reserve(2048);
5595
if (vm.count("record"))
5600
if (vm.count("test-file"))
5602
string tmp= vm["test-file"].as<string>();
5603
char buff[FN_REFLEN];
5604
if (!internal::test_if_hard_path(tmp.c_str()))
5606
snprintf(buff, sizeof(buff), "%s%s",opt_basedir.c_str(),tmp.c_str());
5609
internal::fn_format(buff, tmp.c_str(), "", "", MY_UNPACK_FILENAME);
5610
assert(cur_file == file_stack && cur_file->file == 0);
5611
if (!(cur_file->file= fopen(buff, "r")))
5613
fprintf(stderr, _("Could not open '%s' for reading: errno = %d"), buff, errno);
5614
return EXIT_ARGUMENT_INVALID;
5616
if (!(cur_file->file_name= strdup(buff)))
5618
fprintf(stderr, _("Out of memory"));
5619
return EXIT_OUT_OF_MEMORY;
5621
cur_file->lineno= 1;
5624
if (vm.count("timer-file"))
5626
string tmp= vm["timer-file"].as<string>().c_str();
5627
static char buff[FN_REFLEN];
5628
if (!internal::test_if_hard_path(tmp.c_str()))
5630
snprintf(buff, sizeof(buff), "%s%s",opt_basedir.c_str(),tmp.c_str());
5633
internal::fn_format(buff, tmp.c_str(), "", "", MY_UNPACK_FILENAME);
5635
unlink(timer_file); /* Ignore error, may not exist */
5638
if (vm.count("protocol"))
5640
std::transform(opt_protocol.begin(), opt_protocol.end(),
5641
opt_protocol.begin(), ::tolower);
5643
if (not opt_protocol.compare("mysql"))
5644
use_drizzle_protocol=false;
5645
else if (not opt_protocol.compare("drizzle"))
5646
use_drizzle_protocol=true;
5649
cout << _("Error: Unknown protocol") << " '" << opt_protocol << "'" << endl;
5654
if (vm.count("port"))
5656
/* If the port number is > 65535 it is not a valid port
5657
This also helps with potential data loss casting unsigned long to a
5659
if (opt_port > 65535)
5661
fprintf(stderr, _("Value supplied for port is not valid.\n"));
5662
exit(EXIT_ARGUMENT_INVALID);
5666
if( vm.count("password") )
5668
if (!opt_password.empty())
5669
opt_password.erase();
5670
if (password == PASSWORD_SENTINEL)
5676
opt_password= password;
5677
tty_password= false;
5685
if (vm.count("tmpdir"))
5687
strncpy(TMPDIR, vm["tmpdir"].as<string>().c_str(), sizeof(TMPDIR));
5690
if (vm.count("version"))
5692
printf("%s Ver %s Distrib %s, for %s-%s (%s)\n",internal::my_progname,MTEST_VERSION,
5693
drizzle_version(),HOST_VENDOR,HOST_OS,HOST_CPU);
5697
if (vm.count("help"))
5699
printf("%s Ver %s Distrib %s, for %s-%s (%s)\n",internal::my_progname,MTEST_VERSION,
5700
drizzle_version(),HOST_VENDOR,HOST_OS,HOST_CPU);
5701
printf("MySQL AB, by Sasha, Matt, Monty & Jani\n");
5702
printf("Drizzle version modified by Brian, Jay, Monty Taylor, PatG and Stewart\n");
5703
printf("This software comes with ABSOLUTELY NO WARRANTY\n\n");
5704
printf("Runs a test against the DRIZZLE server and compares output with a results file.\n\n");
5705
printf("Usage: %s [OPTIONS] [database] < test_file\n", internal::my_progname);
5711
opt_pass= client_get_tty_password(NULL); /* purify tested */
5646
parse_args(argc, argv);
5714
5648
server_initialized= 1;
5715
5649
if (cur_file == file_stack && cur_file->file == 0)
6644
6545
icase - flag, if set to 1 the match is case insensitive
6646
6547
int reg_replace(char** buf_p, int* buf_len_p, char *pattern,
6647
char *replace, char *in_string, int icase, int global)
6548
char *replace, char *in_string, int icase)
6550
string string_to_match(in_string);
6649
6551
const char *error= NULL;
6651
6553
int ovector[3];
6652
6554
pcre *re= pcre_compile(pattern,
6653
icase ? PCRE_CASELESS | PCRE_MULTILINE : PCRE_MULTILINE,
6555
icase ? PCRE_CASELESS : 0,
6654
6556
&error, &erroffset, NULL);
6655
6557
if (re == NULL)
6661
int rc= pcre_exec(re, NULL, in_string, (int)strlen(in_string),
6669
char *substring_to_replace= in_string + ovector[0];
6670
int substring_length= ovector[1] - ovector[0];
6671
*buf_len_p= strlen(in_string) - substring_length + strlen(replace);
6672
char * new_buf = (char *)malloc(*buf_len_p+1);
6673
if (new_buf == NULL)
6679
memset(new_buf, 0, *buf_len_p+1);
6680
strncpy(new_buf, in_string, substring_to_replace-in_string);
6681
strncpy(new_buf+(substring_to_replace-in_string), replace, strlen(replace));
6682
strncpy(new_buf+(substring_to_replace-in_string)+strlen(replace),
6683
substring_to_replace + substring_length,
6686
- (substring_to_replace-in_string));
6694
/* Repeatedly replace the string with the matched regex */
6695
string subject(in_string);
6696
size_t replace_length= strlen(replace);
6697
size_t length_of_replacement= strlen(replace);
6698
size_t current_position= 0;
6703
rc= pcre_exec(re, NULL, subject.c_str(), subject.length(),
6704
current_position, 0, ovector, 3);
6710
current_position= static_cast<size_t>(ovector[0]);
6711
replace_length= static_cast<size_t>(ovector[1] - ovector[0]);
6712
subject.replace(current_position, replace_length, replace, length_of_replacement);
6713
current_position= current_position + length_of_replacement;
6716
char *new_buf = (char *) malloc(subject.length() + 1);
6717
if (new_buf == NULL)
6722
memset(new_buf, 0, subject.length() + 1);
6723
strncpy(new_buf, subject.c_str(), subject.length());
6724
*buf_len_p= subject.length() + 1;
6560
int rc= pcre_exec(re, NULL, in_string, (int)strlen(in_string),
6568
char *substring_to_replace= in_string + ovector[0];
6569
int substring_length= ovector[1] - ovector[0];
6570
*buf_len_p= strlen(in_string) - substring_length + strlen(replace);
6571
char * new_buf = (char *)malloc(*buf_len_p+1);
6572
if (new_buf == NULL)
6578
memset(new_buf, 0, *buf_len_p+1);
6579
strncpy(new_buf, in_string, substring_to_replace-in_string);
6580
strncpy(new_buf+(substring_to_replace-in_string), replace, strlen(replace));
6581
strncpy(new_buf+(substring_to_replace-in_string)+strlen(replace),
6582
substring_to_replace + substring_length,
6585
- (substring_to_replace-in_string));