1 /* Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved. 2 3 This program is free software; you can redistribute it and/or modify 4 it under the terms of the GNU General Public License as published by 5 the Free Software Foundation; version 2 of the License. 6 7 This program is distributed in the hope that it will be useful, 8 but WITHOUT ANY WARRANTY; without even the implied warranty of 9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 GNU General Public License for more details. 11 12 You should have received a copy of the GNU General Public License 13 along with this program; if not, write to the Free Software 14 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ 15 16 #include <my_global.h> 17 #include <my_sys.h> 18 #include <mysql.h> 19 #include <errmsg.h> 20 #include <my_compare.h> 21 #include <my_getopt.h> 22 #include <m_string.h> 23 #include <mysqld_error.h> 24 #include <mysql_version.h> 25 #include <sql_common.h> 26 #include <mysql/client_plugin.h> 27 28 /* 29 If non_blocking_api_enabled is true, we will re-define all the blocking 30 API functions as wrappers that call the corresponding non-blocking API 31 and use poll()/select() to wait for them to complete. This way we can get 32 a good coverage testing of the non-blocking API as well. 33 */ 34 #include <my_context.h> 35 static my_bool non_blocking_api_enabled= 0; 36 #if !defined(EMBEDDED_LIBRARY) && !defined(MY_CONTEXT_DISABLE) 37 #define WRAP_NONBLOCK_ENABLED non_blocking_api_enabled 38 #include "nonblock-wrappers.h" 39 #endif 40 41 #define VER "2.1" 42 #define MAX_TEST_QUERY_LENGTH 300 /* MAX QUERY BUFFER LENGTH */ 43 #define MAX_KEY MAX_INDEXES 44 #define MAX_SERVER_ARGS 64 45 46 /* set default options */ 47 static int opt_testcase __attribute__((unused)) = 0; 48 static char *opt_db= 0; 49 static char *opt_user= 0; 50 static char *opt_password= 0; 51 static char *opt_host= 0; 52 static char *opt_unix_socket= 0; 53 #ifdef HAVE_SMEM 54 static char *shared_memory_base_name= 0; 55 #endif 56 static unsigned int opt_port; 57 static my_bool tty_password= 0, opt_silent= 0; 58 59 static MYSQL *mysql= 0; 60 static char current_db[]= "client_test_db"; 61 static unsigned int test_count= 0; 62 static unsigned int opt_count= 0; 63 static unsigned int opt_count_read= 0; 64 static unsigned int iter_count= 0; 65 static my_bool have_innodb= FALSE; 66 static char *opt_plugin_dir= 0, *opt_default_auth= 0; 67 static unsigned int opt_drop_db= 1; 68 69 static const char *opt_basedir= "./"; 70 static const char *opt_vardir= "mysql-test/var"; 71 static char mysql_charsets_dir[FN_REFLEN+1]; 72 73 static longlong opt_getopt_ll_test= 0; 74 75 static char **defaults_argv; 76 static int original_argc; 77 static char **original_argv; 78 static int embedded_server_arg_count= 0; 79 static char *embedded_server_args[MAX_SERVER_ARGS]; 80 81 static const char *embedded_server_groups[]= { 82 "server", 83 "embedded", 84 "mysql_client_test_SERVER", 85 NullS 86 }; 87 88 static time_t start_time, end_time; 89 static double total_time; 90 91 const char *default_dbug_option= "d:t:o,/tmp/mysql_client_test.trace"; 92 93 struct my_tests_st 94 { 95 const char *name; 96 void (*function)(); 97 }; 98 99 #define myheader(str) \ 100 DBUG_PRINT("test", ("name: %s", str)); \ 101 if (opt_silent < 2) \ 102 { \ 103 fprintf(stdout, "\n\n#####################################\n"); \ 104 fprintf(stdout, "%u of (%u/%u): %s", test_count++, iter_count, \ 105 opt_count, str); \ 106 fprintf(stdout, " \n#####################################\n"); \ 107 } 108 109 #define myheader_r(str) \ 110 DBUG_PRINT("test", ("name: %s", str)); \ 111 if (!opt_silent) \ 112 { \ 113 fprintf(stdout, "\n\n#####################################\n"); \ 114 fprintf(stdout, "%s", str); \ 115 fprintf(stdout, " \n#####################################\n"); \ 116 } 117 118 static void print_error(const char *msg); 119 static void print_st_error(MYSQL_STMT *stmt, const char *msg); 120 static void client_disconnect(MYSQL* mysql); 121 static void get_options(int *argc, char ***argv); 122 123 124 /* 125 Abort unless given experssion is non-zero. 126 127 SYNOPSIS 128 DIE_UNLESS(expr) 129 130 DESCRIPTION 131 We can't use any kind of system assert as we need to 132 preserve tested invariants in release builds as well. 133 */ 134 135 #define DIE_UNLESS(expr) \ 136 ((void) ((expr) ? 0 : (die(__FILE__, __LINE__, #expr), 0))) 137 #define DIE_IF(expr) \ 138 ((void) ((expr) ? (die(__FILE__, __LINE__, #expr), 0) : 0)) 139 #define DIE(expr) \ 140 die(__FILE__, __LINE__, #expr) 141 142 static void die(const char *file, int line, const char *expr) 143 { 144 fflush(stdout); 145 fprintf(stderr, "%s:%d: check failed: '%s'\n", file, line, expr); 146 fprintf(stderr, "MySQL error %d: %s\n", mysql_errno(0), mysql_error(0)); 147 fflush(stderr); 148 exit(1); 149 } 150 151 152 #define myerror(msg) print_error(msg) 153 #define mysterror(stmt, msg) print_st_error(stmt, msg) 154 155 #define myquery(RES) \ 156 { \ 157 int r= (RES); \ 158 if (r) \ 159 myerror(NULL); \ 160 DIE_UNLESS(r == 0); \ 161 } 162 163 #define myquery_r(r) \ 164 { \ 165 if (r) \ 166 myerror(NULL); \ 167 DIE_UNLESS(r != 0); \ 168 } 169 170 #define check_execute(stmt, r) \ 171 { \ 172 if (r) \ 173 mysterror(stmt, NULL); \ 174 DIE_UNLESS(r == 0); \ 175 } 176 177 #define check_execute_r(stmt, r) \ 178 { \ 179 if (r) \ 180 mysterror(stmt, NULL); \ 181 DIE_UNLESS(r != 0); \ 182 } 183 184 #define check_stmt(stmt) \ 185 { \ 186 if ( stmt == 0) \ 187 myerror(NULL); \ 188 DIE_UNLESS(stmt != 0); \ 189 } 190 191 #define check_stmt_r(stmt) \ 192 { \ 193 if (stmt == 0) \ 194 myerror(NULL); \ 195 DIE_UNLESS(stmt == 0); \ 196 } 197 198 #define mytest(x) if (!(x)) {myerror(NULL);DIE_UNLESS(FALSE);} 199 #define mytest_r(x) if ((x)) {myerror(NULL);DIE_UNLESS(FALSE);} 200 201 202 /* A workaround for Sun Forte 5.6 on Solaris x86 */ 203 204 static int cmp_double(double *a, double *b) 205 { 206 return *a == *b; 207 } 208 209 210 /* Print the error message */ 211 212 static void print_error(const char *msg) 213 { 214 if (!opt_silent) 215 { 216 if (mysql && mysql_errno(mysql)) 217 { 218 if (mysql->server_version) 219 fprintf(stdout, "\n [MySQL-%s]", mysql->server_version); 220 else 221 fprintf(stdout, "\n [MySQL]"); 222 fprintf(stdout, "[%d] %s\n", mysql_errno(mysql), mysql_error(mysql)); 223 } 224 else if (msg) 225 fprintf(stderr, " [MySQL] %s\n", msg); 226 } 227 } 228 229 230 static void print_st_error(MYSQL_STMT *stmt, const char *msg) 231 { 232 if (!opt_silent) 233 { 234 if (stmt && mysql_stmt_errno(stmt)) 235 { 236 if (stmt->mysql && stmt->mysql->server_version) 237 fprintf(stdout, "\n [MySQL-%s]", stmt->mysql->server_version); 238 else 239 fprintf(stdout, "\n [MySQL]"); 240 241 fprintf(stdout, "[%d] %s\n", mysql_stmt_errno(stmt), 242 mysql_stmt_error(stmt)); 243 } 244 else if (msg) 245 fprintf(stderr, " [MySQL] %s\n", msg); 246 } 247 } 248 249 /* 250 Enhanced version of mysql_client_init(), which may also set shared memory 251 base on Windows. 252 */ 253 static MYSQL *mysql_client_init(MYSQL* con) 254 { 255 MYSQL* res = mysql_init(con); 256 #ifdef HAVE_SMEM 257 if (res && shared_memory_base_name) 258 mysql_options(res, MYSQL_SHARED_MEMORY_BASE_NAME, shared_memory_base_name); 259 #endif 260 if (res && non_blocking_api_enabled) 261 mysql_options(res, MYSQL_OPT_NONBLOCK, 0); 262 if (opt_plugin_dir && *opt_plugin_dir) 263 mysql_options(res, MYSQL_PLUGIN_DIR, opt_plugin_dir); 264 265 if (opt_default_auth && *opt_default_auth) 266 mysql_options(res, MYSQL_DEFAULT_AUTH, opt_default_auth); 267 return res; 268 } 269 270 /* 271 Disable direct calls of mysql_init, as it disregards shared memory base. 272 */ 273 #define mysql_init(A) Please use mysql_client_init instead of mysql_init 274 275 276 /* Check if the connection has InnoDB tables */ 277 278 static my_bool check_have_innodb(MYSQL *conn) 279 { 280 MYSQL_RES *res; 281 MYSQL_ROW row; 282 int rc; 283 my_bool result= FALSE; 284 285 rc= mysql_query(conn, 286 "SELECT (support = 'YES' or support = 'DEFAULT' or support = 'ENABLED') " 287 "AS `TRUE` FROM information_schema.engines WHERE engine = 'innodb'"); 288 myquery(rc); 289 res= mysql_use_result(conn); 290 DIE_UNLESS(res); 291 292 row= mysql_fetch_row(res); 293 DIE_UNLESS(row); 294 295 if (row[0] && row[1]) 296 result= strcmp(row[1], "1") == 0; 297 mysql_free_result(res); 298 return result; 299 } 300 301 302 /* 303 This is to be what mysql_query() is for mysql_real_query(), for 304 mysql_simple_prepare(): a variant without the 'length' parameter. 305 */ 306 307 static MYSQL_STMT *STDCALL 308 mysql_simple_prepare(MYSQL *mysql_arg, const char *query) 309 { 310 MYSQL_STMT *stmt= mysql_stmt_init(mysql_arg); 311 if (stmt && mysql_stmt_prepare(stmt, query, (uint) strlen(query))) 312 { 313 mysql_stmt_close(stmt); 314 return 0; 315 } 316 return stmt; 317 } 318 319 320 /** 321 Connect to the server with options given by arguments to this application, 322 stored in global variables opt_host, opt_user, opt_password, opt_db, 323 opt_port and opt_unix_socket. 324 325 @param flag[in] client_flag passed on to mysql_real_connect 326 @param protocol[in] MYSQL_PROTOCOL_* to use for this connection 327 @param auto_reconnect[in] set to 1 for auto reconnect 328 329 @return pointer to initialized and connected MYSQL object 330 */ 331 static MYSQL* client_connect(ulong flag, uint protocol, my_bool auto_reconnect) 332 { 333 MYSQL* mysql; 334 int rc; 335 static char query[MAX_TEST_QUERY_LENGTH]; 336 myheader_r("client_connect"); 337 338 if (!opt_silent) 339 fprintf(stdout, "\n Establishing a connection to '%s' ...", 340 opt_host ? opt_host : ""); 341 342 if (!(mysql= mysql_client_init(NULL))) 343 { 344 opt_silent= 0; 345 myerror("mysql_client_init() failed"); 346 exit(1); 347 } 348 /* enable local infile, in non-binary builds often disabled by default */ 349 mysql_options(mysql, MYSQL_OPT_LOCAL_INFILE, 0); 350 mysql_options(mysql, MYSQL_OPT_PROTOCOL, &protocol); 351 if (opt_plugin_dir && *opt_plugin_dir) 352 mysql_options(mysql, MYSQL_PLUGIN_DIR, opt_plugin_dir); 353 354 if (opt_default_auth && *opt_default_auth) 355 mysql_options(mysql, MYSQL_DEFAULT_AUTH, opt_default_auth); 356 357 if (!(mysql_real_connect(mysql, opt_host, opt_user, 358 opt_password, opt_db ? opt_db:"test", opt_port, 359 opt_unix_socket, flag))) 360 { 361 opt_silent= 0; 362 myerror("connection failed"); 363 mysql_close(mysql); 364 fprintf(stdout, "\n Check the connection options using --help or -?\n"); 365 exit(1); 366 } 367 mysql_options(mysql, MYSQL_OPT_RECONNECT, &auto_reconnect); 368 369 if (!opt_silent) 370 fprintf(stdout, "OK"); 371 372 /* set AUTOCOMMIT to ON*/ 373 mysql_autocommit(mysql, TRUE); 374 375 if (!opt_silent) 376 { 377 fprintf(stdout, "\nConnected to MySQL server version: %s (%lu)\n", 378 mysql_get_server_info(mysql), 379 (ulong) mysql_get_server_version(mysql)); 380 fprintf(stdout, "\n Creating a test database '%s' ...", current_db); 381 } 382 strxmov(query, "CREATE DATABASE IF NOT EXISTS ", current_db, NullS); 383 384 rc= mysql_query(mysql, query); 385 myquery(rc); 386 387 strxmov(query, "USE ", current_db, NullS); 388 rc= mysql_query(mysql, query); 389 myquery(rc); 390 have_innodb= check_have_innodb(mysql); 391 392 if (!opt_silent) 393 fprintf(stdout, "OK\n"); 394 395 return mysql; 396 } 397 398 399 /* Close the connection */ 400 401 static void client_disconnect(MYSQL* mysql) 402 { 403 static char query[MAX_TEST_QUERY_LENGTH]; 404 405 myheader_r("client_disconnect"); 406 407 if (mysql) 408 { 409 if (opt_drop_db) 410 { 411 if (!opt_silent) 412 fprintf(stdout, "\n dropping the test database '%s' ...", current_db); 413 strxmov(query, "DROP DATABASE IF EXISTS ", current_db, NullS); 414 415 mysql_query(mysql, query); 416 if (!opt_silent) 417 fprintf(stdout, "OK"); 418 } 419 420 if (!opt_silent) 421 fprintf(stdout, "\n closing the connection ..."); 422 mysql_close(mysql); 423 if (!opt_silent) 424 fprintf(stdout, "OK\n"); 425 } 426 } 427 428 429 /* Print dashes */ 430 431 static void my_print_dashes(MYSQL_RES *result) 432 { 433 MYSQL_FIELD *field; 434 unsigned int i, j; 435 436 mysql_field_seek(result, 0); 437 fputc('\t', stdout); 438 fputc('+', stdout); 439 440 for(i= 0; i< mysql_num_fields(result); i++) 441 { 442 field= mysql_fetch_field(result); 443 for(j= 0; j < field->max_length+2; j++) 444 fputc('-', stdout); 445 fputc('+', stdout); 446 } 447 fputc('\n', stdout); 448 } 449 450 451 /* Print resultset metadata information */ 452 453 static void my_print_result_metadata(MYSQL_RES *result) 454 { 455 MYSQL_FIELD *field; 456 unsigned int i, j; 457 unsigned int field_count; 458 459 mysql_field_seek(result, 0); 460 if (!opt_silent) 461 { 462 fputc('\n', stdout); 463 fputc('\n', stdout); 464 } 465 466 field_count= mysql_num_fields(result); 467 for(i= 0; i< field_count; i++) 468 { 469 field= mysql_fetch_field(result); 470 j= strlen(field->name); 471 if (j < field->max_length) 472 j= field->max_length; 473 if (j < 4 && !IS_NOT_NULL(field->flags)) 474 j= 4; 475 field->max_length= j; 476 } 477 if (!opt_silent) 478 { 479 my_print_dashes(result); 480 fputc('\t', stdout); 481 fputc('|', stdout); 482 } 483 484 mysql_field_seek(result, 0); 485 for(i= 0; i< field_count; i++) 486 { 487 field= mysql_fetch_field(result); 488 if (!opt_silent) 489 fprintf(stdout, " %-*s |", (int) field->max_length, field->name); 490 } 491 if (!opt_silent) 492 { 493 fputc('\n', stdout); 494 my_print_dashes(result); 495 } 496 } 497 498 499 /* Process the result set */ 500 501 static int my_process_result_set(MYSQL_RES *result) 502 { 503 MYSQL_ROW row; 504 MYSQL_FIELD *field; 505 unsigned int i; 506 unsigned int row_count= 0; 507 508 if (!result) 509 return 0; 510 511 my_print_result_metadata(result); 512 513 while ((row= mysql_fetch_row(result)) != NULL) 514 { 515 mysql_field_seek(result, 0); 516 if (!opt_silent) 517 { 518 fputc('\t', stdout); 519 fputc('|', stdout); 520 } 521 522 for(i= 0; i< mysql_num_fields(result); i++) 523 { 524 field= mysql_fetch_field(result); 525 if (!opt_silent) 526 { 527 if (row[i] == NULL) 528 fprintf(stdout, " %-*s |", (int) field->max_length, "NULL"); 529 else if (IS_NUM(field->type)) 530 fprintf(stdout, " %*s |", (int) field->max_length, row[i]); 531 else 532 fprintf(stdout, " %-*s |", (int) field->max_length, row[i]); 533 } 534 } 535 if (!opt_silent) 536 { 537 fputc('\t', stdout); 538 fputc('\n', stdout); 539 } 540 row_count++; 541 } 542 if (!opt_silent) 543 { 544 if (row_count) 545 my_print_dashes(result); 546 547 if (mysql_errno(mysql) != 0) 548 fprintf(stderr, "\n\tmysql_fetch_row() failed\n"); 549 else 550 fprintf(stdout, "\n\t%d %s returned\n", row_count, 551 row_count == 1 ? "row" : "rows"); 552 } 553 return row_count; 554 } 555 556 557 static int my_process_result(MYSQL *mysql_arg) 558 { 559 MYSQL_RES *result; 560 int row_count; 561 562 if (!(result= mysql_store_result(mysql_arg))) 563 return 0; 564 565 row_count= my_process_result_set(result); 566 567 mysql_free_result(result); 568 return row_count; 569 } 570 571 572 /* Process the statement result set */ 573 574 #define MAX_RES_FIELDS 50 575 #define MAX_FIELD_DATA_SIZE 255 576 577 static int my_process_stmt_result(MYSQL_STMT *stmt) 578 { 579 int field_count; 580 int row_count= 0; 581 MYSQL_BIND buffer[MAX_RES_FIELDS]; 582 MYSQL_FIELD *field; 583 MYSQL_RES *result; 584 char data[MAX_RES_FIELDS][MAX_FIELD_DATA_SIZE]; 585 ulong length[MAX_RES_FIELDS]; 586 my_bool is_null[MAX_RES_FIELDS]; 587 int rc, i; 588 589 if (!(result= mysql_stmt_result_metadata(stmt))) /* No meta info */ 590 { 591 while (!mysql_stmt_fetch(stmt)) 592 row_count++; 593 return row_count; 594 } 595 596 field_count= MY_MIN(mysql_num_fields(result), MAX_RES_FIELDS); 597 598 bzero((char*) buffer, sizeof(buffer)); 599 bzero((char*) length, sizeof(length)); 600 bzero((char*) is_null, sizeof(is_null)); 601 602 for(i= 0; i < field_count; i++) 603 { 604 buffer[i].buffer_type= MYSQL_TYPE_STRING; 605 buffer[i].buffer_length= MAX_FIELD_DATA_SIZE; 606 buffer[i].length= &length[i]; 607 buffer[i].buffer= (void *) data[i]; 608 buffer[i].is_null= &is_null[i]; 609 } 610 611 rc= mysql_stmt_bind_result(stmt, buffer); 612 check_execute(stmt, rc); 613 614 rc= 1; 615 mysql_stmt_attr_set(stmt, STMT_ATTR_UPDATE_MAX_LENGTH, (void*)&rc); 616 rc= mysql_stmt_store_result(stmt); 617 check_execute(stmt, rc); 618 my_print_result_metadata(result); 619 620 mysql_field_seek(result, 0); 621 while ((rc= mysql_stmt_fetch(stmt)) == 0) 622 { 623 if (!opt_silent) 624 { 625 fputc('\t', stdout); 626 fputc('|', stdout); 627 } 628 mysql_field_seek(result, 0); 629 for (i= 0; i < field_count; i++) 630 { 631 field= mysql_fetch_field(result); 632 if (!opt_silent) 633 { 634 if (is_null[i]) 635 fprintf(stdout, " %-*s |", (int) field->max_length, "NULL"); 636 else if (length[i] == 0) 637 { 638 data[i][0]= '\0'; /* unmodified buffer */ 639 fprintf(stdout, " %*s |", (int) field->max_length, data[i]); 640 } 641 else if (IS_NUM(field->type)) 642 fprintf(stdout, " %*s |", (int) field->max_length, data[i]); 643 else 644 fprintf(stdout, " %-*s |", (int) field->max_length, data[i]); 645 } 646 } 647 if (!opt_silent) 648 { 649 fputc('\t', stdout); 650 fputc('\n', stdout); 651 } 652 row_count++; 653 } 654 DIE_UNLESS(rc == MYSQL_NO_DATA); 655 if (!opt_silent) 656 { 657 if (row_count) 658 my_print_dashes(result); 659 fprintf(stdout, "\n\t%d %s returned\n", row_count, 660 row_count == 1 ? "row" : "rows"); 661 } 662 mysql_free_result(result); 663 return row_count; 664 } 665 666 667 /* Prepare statement, execute, and process result set for given query */ 668 669 int my_stmt_result(const char *buff) 670 { 671 MYSQL_STMT *stmt; 672 int row_count; 673 int rc; 674 675 if (!opt_silent) 676 fprintf(stdout, "\n\n %s", buff); 677 stmt= mysql_simple_prepare(mysql, buff); 678 check_stmt(stmt); 679 680 rc= mysql_stmt_execute(stmt); 681 check_execute(stmt, rc); 682 683 row_count= my_process_stmt_result(stmt); 684 mysql_stmt_close(stmt); 685 686 return row_count; 687 } 688 689 /* Print the total number of warnings and the warnings themselves. */ 690 691 void my_process_warnings(MYSQL *conn, unsigned expected_warning_count) 692 { 693 MYSQL_RES *result; 694 int rc; 695 696 if (!opt_silent) 697 fprintf(stdout, "\n total warnings: %u (expected: %u)\n", 698 mysql_warning_count(conn), expected_warning_count); 699 700 DIE_UNLESS(mysql_warning_count(mysql) == expected_warning_count); 701 702 rc= mysql_query(conn, "SHOW WARNINGS"); 703 DIE_UNLESS(rc == 0); 704 705 result= mysql_store_result(conn); 706 mytest(result); 707 708 rc= my_process_result_set(result); 709 mysql_free_result(result); 710 } 711 712 713 /* Utility function to verify a particular column data */ 714 715 static void verify_col_data(const char *table, const char *col, 716 const char *exp_data) 717 { 718 static char query[MAX_TEST_QUERY_LENGTH]; 719 MYSQL_RES *result; 720 MYSQL_ROW row; 721 int rc, field= 1; 722 723 if (table && col) 724 { 725 strxmov(query, "SELECT ", col, " FROM ", table, " LIMIT 1", NullS); 726 if (!opt_silent) 727 fprintf(stdout, "\n %s", query); 728 rc= mysql_query(mysql, query); 729 myquery(rc); 730 731 field= 0; 732 } 733 734 result= mysql_use_result(mysql); 735 mytest(result); 736 737 if (!(row= mysql_fetch_row(result)) || !row[field]) 738 { 739 fprintf(stdout, "\n *** ERROR: FAILED TO GET THE RESULT ***"); 740 exit(1); 741 } 742 if (strcmp(row[field], exp_data)) 743 { 744 fprintf(stdout, "\n obtained: `%s` (expected: `%s`)", 745 row[field], exp_data); 746 DIE_UNLESS(FALSE); 747 } 748 mysql_free_result(result); 749 } 750 751 752 /* Utility function to verify the field members */ 753 754 #define verify_prepare_field(result,no,name,org_name,type,table,\ 755 org_table,db,length,def) \ 756 do_verify_prepare_field((result),(no),(name),(org_name),(type), \ 757 (table),(org_table),(db),(length),(def), \ 758 __FILE__, __LINE__) 759 760 static void do_verify_prepare_field(MYSQL_RES *result, 761 unsigned int no, const char *name, 762 const char *org_name, 763 enum enum_field_types type, 764 const char *table, 765 const char *org_table, const char *db, 766 unsigned long length, const char *def, 767 const char *file, int line) 768 { 769 MYSQL_FIELD *field; 770 CHARSET_INFO *cs; 771 ulonglong expected_field_length= length; 772 773 if (!(field= mysql_fetch_field_direct(result, no))) 774 { 775 fprintf(stdout, "\n *** ERROR: FAILED TO GET THE RESULT ***"); 776 exit(1); 777 } 778 cs= get_charset(field->charsetnr, 0); 779 DIE_UNLESS(cs); 780 if ((expected_field_length*= cs->mbmaxlen) > UINT_MAX32) 781 expected_field_length= UINT_MAX32; 782 if (!opt_silent) 783 { 784 fprintf(stdout, "\n field[%d]:", no); 785 fprintf(stdout, "\n name :`%s`\t(expected: `%s`)", field->name, name); 786 fprintf(stdout, "\n org_name :`%s`\t(expected: `%s`)", 787 field->org_name, org_name); 788 fprintf(stdout, "\n type :`%d`\t(expected: `%d`)", field->type, type); 789 if (table) 790 fprintf(stdout, "\n table :`%s`\t(expected: `%s`)", 791 field->table, table); 792 if (org_table) 793 fprintf(stdout, "\n org_table:`%s`\t(expected: `%s`)", 794 field->org_table, org_table); 795 fprintf(stdout, "\n database :`%s`\t(expected: `%s`)", field->db, db); 796 fprintf(stdout, "\n length :`%lu`\t(expected: `%llu`)", 797 field->length, expected_field_length); 798 fprintf(stdout, "\n maxlength:`%ld`", field->max_length); 799 fprintf(stdout, "\n charsetnr:`%d`", field->charsetnr); 800 fprintf(stdout, "\n default :`%s`\t(expected: `%s`)", 801 field->def ? field->def : "(null)", def ? def: "(null)"); 802 fprintf(stdout, "\n"); 803 } 804 DIE_UNLESS(strcmp(field->name, name) == 0); 805 DIE_UNLESS(strcmp(field->org_name, org_name) == 0); 806 /* 807 XXX: silent column specification change works based on number of 808 bytes a column occupies. So CHAR -> VARCHAR upgrade is possible even 809 for CHAR(2) column if its character set is multibyte. 810 VARCHAR -> CHAR downgrade won't work for VARCHAR(3) as one would 811 expect. 812 */ 813 if (cs->mbmaxlen == 1) 814 { 815 if (field->type != type) 816 { 817 fprintf(stderr, 818 "Expected field type: %d, got type: %d in file %s, line %d\n", 819 (int) type, (int) field->type, file, line); 820 DIE_UNLESS(field->type == type); 821 } 822 } 823 if (table) 824 DIE_UNLESS(strcmp(field->table, table) == 0); 825 if (org_table) 826 DIE_UNLESS(strcmp(field->org_table, org_table) == 0); 827 DIE_UNLESS(strcmp(field->db, db) == 0); 828 /* 829 Character set should be taken into account for multibyte encodings, such 830 as utf8. Field length is calculated as number of characters * maximum 831 number of bytes a character can occupy. 832 */ 833 if (length && (field->length != expected_field_length)) 834 { 835 fflush(stdout); 836 fprintf(stderr, "Expected field length: %llu, got length: %lu\n", 837 expected_field_length, field->length); 838 fflush(stderr); 839 DIE_UNLESS(field->length == expected_field_length); 840 } 841 if (def) 842 DIE_UNLESS(strcmp(field->def, def) == 0); 843 } 844 845 846 /* Utility function to verify the parameter count */ 847 848 static void verify_param_count(MYSQL_STMT *stmt, long exp_count) 849 { 850 long param_count= mysql_stmt_param_count(stmt); 851 if (!opt_silent) 852 fprintf(stdout, "\n total parameters in stmt: `%ld` (expected: `%ld`)", 853 param_count, exp_count); 854 DIE_UNLESS(param_count == exp_count); 855 } 856 857 858 /* Utility function to verify the total affected rows */ 859 860 static void verify_st_affected_rows(MYSQL_STMT *stmt, ulonglong exp_count) 861 { 862 ulonglong affected_rows= mysql_stmt_affected_rows(stmt); 863 if (!opt_silent) 864 fprintf(stdout, "\n total affected rows: `%ld` (expected: `%ld`)", 865 (long) affected_rows, (long) exp_count); 866 DIE_UNLESS(affected_rows == exp_count); 867 } 868 869 870 /* Utility function to verify the total affected rows */ 871 872 static void verify_affected_rows(ulonglong exp_count) 873 { 874 ulonglong affected_rows= mysql_affected_rows(mysql); 875 if (!opt_silent) 876 fprintf(stdout, "\n total affected rows: `%ld` (expected: `%ld`)", 877 (long) affected_rows, (long) exp_count); 878 DIE_UNLESS(affected_rows == exp_count); 879 } 880 881 882 /* Utility function to verify the total fields count */ 883 884 static void verify_field_count(MYSQL_RES *result, uint exp_count) 885 { 886 uint field_count= mysql_num_fields(result); 887 if (!opt_silent) 888 fprintf(stdout, "\n total fields in the result set: `%d` (expected: `%d`)", 889 field_count, exp_count); 890 DIE_UNLESS(field_count == exp_count); 891 } 892 893 894 /* Utility function to execute a query using prepare-execute */ 895 896 #ifndef EMBEDDED_LIBRARY 897 static void execute_prepare_query(const char *query, ulonglong exp_count) 898 { 899 MYSQL_STMT *stmt; 900 ulonglong affected_rows; 901 int rc; 902 903 stmt= mysql_simple_prepare(mysql, query); 904 check_stmt(stmt); 905 906 rc= mysql_stmt_execute(stmt); 907 myquery(rc); 908 909 affected_rows= mysql_stmt_affected_rows(stmt); 910 if (!opt_silent) 911 fprintf(stdout, "\n total affected rows: `%ld` (expected: `%ld`)", 912 (long) affected_rows, (long) exp_count); 913 914 DIE_UNLESS(affected_rows == exp_count); 915 mysql_stmt_close(stmt); 916 } 917 #endif 918 919 /* 920 Accepts arbitrary number of queries and runs them against the database. 921 Used to fill tables for each test. 922 */ 923 924 void fill_tables(const char **query_list, unsigned query_count) 925 { 926 int rc; 927 const char **query; 928 DBUG_ENTER("fill_tables"); 929 for (query= query_list; query < query_list + query_count; 930 ++query) 931 { 932 rc= mysql_query(mysql, *query); 933 myquery(rc); 934 } 935 DBUG_VOID_RETURN; 936 } 937 938 /* 939 All state of fetch from one statement: statement handle, out buffers, 940 fetch position. 941 See fetch_n for for the only use case. 942 */ 943 944 enum { MAX_COLUMN_LENGTH= 255 }; 945 946 typedef struct st_stmt_fetch 947 { 948 const char *query; 949 unsigned stmt_no; 950 MYSQL_STMT *handle; 951 my_bool is_open; 952 MYSQL_BIND *bind_array; 953 char **out_data; 954 unsigned long *out_data_length; 955 unsigned column_count; 956 unsigned row_count; 957 } Stmt_fetch; 958 959 960 /* 961 Create statement handle, prepare it with statement, execute and allocate 962 fetch buffers. 963 */ 964 965 void stmt_fetch_init(Stmt_fetch *fetch, unsigned stmt_no_arg, 966 const char *query_arg) 967 { 968 unsigned long type= CURSOR_TYPE_READ_ONLY; 969 int rc; 970 unsigned i; 971 MYSQL_RES *metadata; 972 DBUG_ENTER("stmt_fetch_init"); 973 974 /* Save query and statement number for error messages */ 975 fetch->stmt_no= stmt_no_arg; 976 fetch->query= query_arg; 977 978 fetch->handle= mysql_stmt_init(mysql); 979 980 rc= mysql_stmt_prepare(fetch->handle, fetch->query, (ulong)strlen(fetch->query)); 981 check_execute(fetch->handle, rc); 982 983 /* 984 The attribute is sent to server on execute and asks to open read-only 985 for result set 986 */ 987 mysql_stmt_attr_set(fetch->handle, STMT_ATTR_CURSOR_TYPE, 988 (const void*) &type); 989 990 rc= mysql_stmt_execute(fetch->handle); 991 check_execute(fetch->handle, rc); 992 993 /* Find out total number of columns in result set */ 994 metadata= mysql_stmt_result_metadata(fetch->handle); 995 fetch->column_count= mysql_num_fields(metadata); 996 mysql_free_result(metadata); 997 998 /* 999 Now allocate bind handles and buffers for output data: 1000 calloc memory to reduce number of MYSQL_BIND members we need to 1001 set up. 1002 */ 1003 1004 fetch->bind_array= (MYSQL_BIND *) calloc(1, sizeof(MYSQL_BIND) * 1005 fetch->column_count); 1006 fetch->out_data= (char**) calloc(1, sizeof(char*) * fetch->column_count); 1007 fetch->out_data_length= (ulong*) calloc(1, sizeof(ulong) * 1008 fetch->column_count); 1009 for (i= 0; i < fetch->column_count; ++i) 1010 { 1011 fetch->out_data[i]= (char*) calloc(1, MAX_COLUMN_LENGTH); 1012 fetch->bind_array[i].buffer_type= MYSQL_TYPE_STRING; 1013 fetch->bind_array[i].buffer= fetch->out_data[i]; 1014 fetch->bind_array[i].buffer_length= MAX_COLUMN_LENGTH; 1015 fetch->bind_array[i].length= fetch->out_data_length + i; 1016 } 1017 1018 mysql_stmt_bind_result(fetch->handle, fetch->bind_array); 1019 1020 fetch->row_count= 0; 1021 fetch->is_open= TRUE; 1022 1023 /* Ready for reading rows */ 1024 DBUG_VOID_RETURN; 1025 } 1026 1027 1028 /* Fetch and print one row from cursor */ 1029 1030 int stmt_fetch_fetch_row(Stmt_fetch *fetch) 1031 { 1032 int rc; 1033 unsigned i; 1034 DBUG_ENTER("stmt_fetch_fetch_row"); 1035 1036 if ((rc= mysql_stmt_fetch(fetch->handle)) == 0) 1037 { 1038 ++fetch->row_count; 1039 if (!opt_silent) 1040 printf("Stmt %d fetched row %d:\n", fetch->stmt_no, fetch->row_count); 1041 for (i= 0; i < fetch->column_count; ++i) 1042 { 1043 fetch->out_data[i][fetch->out_data_length[i]]= '\0'; 1044 if (!opt_silent) 1045 printf("column %d: %s\n", i+1, fetch->out_data[i]); 1046 } 1047 } 1048 else 1049 fetch->is_open= FALSE; 1050 DBUG_RETURN(rc); 1051 } 1052 1053 1054 void stmt_fetch_close(Stmt_fetch *fetch) 1055 { 1056 unsigned i; 1057 DBUG_ENTER("stmt_fetch_close"); 1058 1059 for (i= 0; i < fetch->column_count; ++i) 1060 free(fetch->out_data[i]); 1061 free(fetch->out_data); 1062 free(fetch->out_data_length); 1063 free(fetch->bind_array); 1064 mysql_stmt_close(fetch->handle); 1065 DBUG_VOID_RETURN; 1066 } 1067 1068 /* 1069 For given array of queries, open query_count cursors and fetch 1070 from them in simultaneous manner. 1071 In case there was an error in one of the cursors, continue 1072 reading from the rest. 1073 */ 1074 1075 enum fetch_type { USE_ROW_BY_ROW_FETCH= 0, USE_STORE_RESULT= 1 }; 1076 1077 my_bool fetch_n(const char **query_list, unsigned query_count, 1078 enum fetch_type fetch_type) 1079 { 1080 unsigned open_statements= query_count; 1081 int rc, error_count= 0; 1082 Stmt_fetch *fetch_array= (Stmt_fetch*) calloc(1, sizeof(Stmt_fetch) * 1083 query_count); 1084 Stmt_fetch *fetch; 1085 DBUG_ENTER("fetch_n"); 1086 1087 for (fetch= fetch_array; fetch < fetch_array + query_count; ++fetch) 1088 { 1089 /* Init will exit(1) in case of error */ 1090 stmt_fetch_init(fetch, (uint)(fetch - fetch_array), 1091 query_list[fetch - fetch_array]); 1092 } 1093 1094 if (fetch_type == USE_STORE_RESULT) 1095 { 1096 for (fetch= fetch_array; fetch < fetch_array + query_count; ++fetch) 1097 { 1098 rc= mysql_stmt_store_result(fetch->handle); 1099 check_execute(fetch->handle, rc); 1100 } 1101 } 1102 1103 while (open_statements) 1104 { 1105 for (fetch= fetch_array; fetch < fetch_array + query_count; ++fetch) 1106 { 1107 if (fetch->is_open && (rc= stmt_fetch_fetch_row(fetch))) 1108 { 1109 open_statements--; 1110 /* 1111 We try to fetch from the rest of the statements in case of 1112 error 1113 */ 1114 if (rc != MYSQL_NO_DATA) 1115 { 1116 fprintf(stderr, 1117 "Got error reading rows from statement %d,\n" 1118 "query is: %s,\n" 1119 "error message: %s", (int) (fetch - fetch_array), 1120 fetch->query, 1121 mysql_stmt_error(fetch->handle)); 1122 error_count++; 1123 } 1124 } 1125 } 1126 } 1127 if (error_count) 1128 fprintf(stderr, "Fetch FAILED"); 1129 else 1130 { 1131 unsigned total_row_count= 0; 1132 for (fetch= fetch_array; fetch < fetch_array + query_count; ++fetch) 1133 total_row_count+= fetch->row_count; 1134 if (!opt_silent) 1135 printf("Success, total rows fetched: %d\n", total_row_count); 1136 } 1137 for (fetch= fetch_array; fetch < fetch_array + query_count; ++fetch) 1138 stmt_fetch_close(fetch); 1139 free(fetch_array); 1140 DBUG_RETURN(error_count != 0); 1141 } 1142 1143 /* Separate thread query to test some cases */ 1144 1145 static my_bool thread_query(const char *query) 1146 { 1147 MYSQL *l_mysql; 1148 my_bool error; 1149 my_bool reconnect= 1; 1150 error= 0; 1151 if (!opt_silent) 1152 fprintf(stdout, "\n in thread_query(%s)", query); 1153 if (!(l_mysql= mysql_client_init(NULL))) 1154 { 1155 myerror("mysql_client_init() failed"); 1156 return 1; 1157 } 1158 if (!(mysql_real_connect(l_mysql, opt_host, opt_user, 1159 opt_password, current_db, opt_port, 1160 opt_unix_socket, 0))) 1161 { 1162 myerror("connection failed"); 1163 error= 1; 1164 goto end; 1165 } 1166 mysql_options(l_mysql, MYSQL_OPT_RECONNECT, &reconnect); 1167 if (mysql_query(l_mysql, query)) 1168 { 1169 fprintf(stderr, "Query failed (%s)\n", mysql_error(l_mysql)); 1170 error= 1; 1171 goto end; 1172 } 1173 mysql_commit(l_mysql); 1174 end: 1175 mysql_close(l_mysql); 1176 return error; 1177 } 1178 1179 1180 static int mysql_query_or_error(MYSQL *mysql, const char *query) 1181 { 1182 int rc= mysql_query(mysql, query); 1183 if (rc) 1184 fprintf(stderr, "ERROR %d: %s", mysql_errno(mysql), mysql_error(mysql)); 1185 return rc; 1186 } 1187 1188 1189 /* 1190 Read and parse arguments and MySQL options from my.cnf 1191 */ 1192 1193 static const char *client_test_load_default_groups[]= 1194 { "client", "client-server", "client-mariadb", 0 }; 1195 static char **defaults_argv; 1196 1197 static struct my_option client_test_long_options[] = 1198 { 1199 {"basedir", 'b', "Basedir for tests.",(void *)&opt_basedir, 1200 (void *)&opt_basedir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, 1201 {"character-sets-dir", 'C', 1202 "Directory for character set files.", (void *)&charsets_dir, 1203 (void *)&charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, 1204 {"count", 't', "Number of times test to be executed", &opt_count_read, 1205 &opt_count_read, 0, GET_UINT, REQUIRED_ARG, 1, 0, 0, 0, 0, 0}, 1206 {"database", 'D', "Database to use", &opt_db, &opt_db, 1207 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, 1208 {"do-not-drop-database", 'd', "Do not drop database while disconnecting", 1209 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, 1210 {"debug", '#', "Output debug log", (void *)&default_dbug_option, 1211 (void *)&default_dbug_option, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, 1212 {"help", '?', "Display this help and exit", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 1213 0, 0, 0, 0, 0}, 1214 {"host", 'h', "Connect to host", &opt_host, &opt_host, 1215 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, 1216 {"password", 'p', 1217 "Password to use when connecting to server. If password is not given it's asked from the tty.", 1218 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, 1219 {"port", 'P', "Port number to use for connection or 0 for default to, in " 1220 "order of preference, my.cnf, $MYSQL_TCP_PORT, " 1221 #if MYSQL_PORT_DEFAULT == 0 1222 "/etc/services, " 1223 #endif 1224 "built-in default (" STRINGIFY_ARG(MYSQL_PORT) ").", 1225 &opt_port, &opt_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, 1226 {"server-arg", 'A', "Send embedded server this as a parameter.", 1227 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, 1228 {"show-tests", 'T', "Show all tests' names", 0, 0, 0, GET_NO_ARG, NO_ARG, 1229 0, 0, 0, 0, 0, 0}, 1230 {"silent", 's', "Be more silent", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 1231 0}, 1232 #ifdef HAVE_SMEM 1233 {"shared-memory-base-name", 'm', "Base name of shared memory.", 1234 &shared_memory_base_name, (uchar**)&shared_memory_base_name, 0, 1235 GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, 1236 #endif 1237 {"socket", 'S', "Socket file to use for connection", 1238 &opt_unix_socket, &opt_unix_socket, 0, GET_STR, 1239 REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, 1240 {"testcase", 'c', 1241 "May disable some code when runs as mysql-test-run testcase.", 1242 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, 1243 #ifndef DONT_ALLOW_USER_CHANGE 1244 {"user", 'u', "User for login if not current user", &opt_user, 1245 &opt_user, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, 1246 #endif 1247 {"vardir", 'v', "Data dir for tests.", (void *)&opt_vardir, 1248 (void *)&opt_vardir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, 1249 {"non-blocking-api", 'n', 1250 "Use the non-blocking client API for communication.", 1251 &non_blocking_api_enabled, &non_blocking_api_enabled, 0, 1252 GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, 1253 {"getopt-ll-test", 'g', "Option for testing bug in getopt library", 1254 &opt_getopt_ll_test, &opt_getopt_ll_test, 0, 1255 GET_LL, REQUIRED_ARG, 0, 0, LONGLONG_MAX, 0, 0, 0}, 1256 {"plugin_dir", 0, "Directory for client-side plugins.", 1257 &opt_plugin_dir, &opt_plugin_dir, 0, 1258 GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, 1259 {"default_auth", 0, "Default authentication client-side plugin to use.", 1260 &opt_default_auth, &opt_default_auth, 0, 1261 GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, 1262 { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} 1263 }; 1264 1265 1266 static void usage(void) 1267 { 1268 /* show the usage string when the user asks for this */ 1269 putc('\n', stdout); 1270 printf("%s Ver %s Distrib %s, for %s (%s)\n", 1271 my_progname, VER, MYSQL_SERVER_VERSION, SYSTEM_TYPE, MACHINE_TYPE); 1272 puts("By Monty, Venu, Kent and others\n"); 1273 printf("\ 1274 Copyright (C) 2002-2004 MySQL AB\n\ 1275 This software comes with ABSOLUTELY NO WARRANTY. This is free software,\n\ 1276 and you are welcome to modify and redistribute it under the GPL license\n"); 1277 printf("Usage: %s [OPTIONS] [TESTNAME1 TESTNAME2...]\n", my_progname); 1278 my_print_help(client_test_long_options); 1279 print_defaults("my", client_test_load_default_groups); 1280 my_print_variables(client_test_long_options); 1281 } 1282 1283 static struct my_tests_st *get_my_tests(); /* To be defined in main .c file */ 1284 1285 static struct my_tests_st *my_testlist= 0; 1286 1287 static my_bool 1288 get_one_option(int optid, const struct my_option *opt __attribute__((unused)), 1289 char *argument) 1290 { 1291 switch (optid) { 1292 case '#': 1293 DBUG_PUSH(argument ? argument : default_dbug_option); 1294 break; 1295 case 'c': 1296 opt_testcase = 1; 1297 break; 1298 case 'p': 1299 if (argument) 1300 { 1301 char *start=argument; 1302 my_free(opt_password); 1303 opt_password= my_strdup(argument, MYF(MY_FAE)); 1304 while (*argument) *argument++= 'x'; /* Destroy argument */ 1305 if (*start) 1306 start[1]=0; 1307 } 1308 else 1309 tty_password= 1; 1310 break; 1311 case 's': 1312 if (argument == disabled_my_option) 1313 opt_silent= 0; 1314 else 1315 opt_silent++; 1316 break; 1317 case 'd': 1318 opt_drop_db= 0; 1319 break; 1320 case 'A': 1321 /* 1322 When the embedded server is being tested, the test suite needs to be 1323 able to pass command-line arguments to the embedded server so it can 1324 locate the language files and data directory. The test suite 1325 (mysql-test-run) never uses config files, just command-line options. 1326 */ 1327 if (!embedded_server_arg_count) 1328 { 1329 embedded_server_arg_count= 1; 1330 embedded_server_args[0]= (char*) ""; 1331 } 1332 if (embedded_server_arg_count == MAX_SERVER_ARGS-1 || 1333 !(embedded_server_args[embedded_server_arg_count++]= 1334 my_strdup(argument, MYF(MY_FAE)))) 1335 { 1336 DIE("Can't use server argument"); 1337 } 1338 break; 1339 case 'T': 1340 { 1341 struct my_tests_st *fptr; 1342 1343 printf("All possible test names:\n\n"); 1344 for (fptr= my_testlist; fptr->name; fptr++) 1345 printf("%s\n", fptr->name); 1346 exit(0); 1347 break; 1348 } 1349 case 'C': 1350 strmake_buf(mysql_charsets_dir, argument); 1351 charsets_dir = mysql_charsets_dir; 1352 break; 1353 case '?': 1354 case 'I': /* Info */ 1355 usage(); 1356 exit(0); 1357 break; 1358 } 1359 return 0; 1360 } 1361 1362 static void get_options(int *argc, char ***argv) 1363 { 1364 int ho_error; 1365 /* Copy argv from load_defaults, so we can free it when done. */ 1366 defaults_argv= *argv; 1367 /* reset --silent option */ 1368 opt_silent= 0; 1369 1370 if ((ho_error= handle_options(argc, argv, client_test_long_options, 1371 get_one_option))) 1372 exit(ho_error); 1373 1374 if (tty_password) 1375 opt_password= get_tty_password(NullS); 1376 return; 1377 } 1378 1379 /* 1380 Print the test output on successful execution before exiting 1381 */ 1382 1383 static void print_test_output() 1384 { 1385 if (opt_silent < 3) 1386 { 1387 fprintf(stdout, "\n\n"); 1388 fprintf(stdout, "All '%d' tests were successful (in '%d' iterations)", 1389 test_count-1, opt_count); 1390 if (!opt_silent) 1391 { 1392 fprintf(stdout, "\n Total execution time: %g SECS", total_time); 1393 if (opt_count > 1) 1394 fprintf(stdout, " (Avg: %g SECS)", total_time/opt_count); 1395 } 1396 1397 fprintf(stdout, "\n\n!!! SUCCESS !!!\n"); 1398 } 1399 } 1400 1401 /*************************************************************************** 1402 main routine 1403 ***************************************************************************/ 1404 1405 1406 int main(int argc, char **argv) 1407 { 1408 int i; 1409 char **tests_to_run= NULL, **curr_test; 1410 struct my_tests_st *fptr; 1411 my_testlist= get_my_tests(); 1412 1413 MY_INIT(argv[0]); 1414 /* Copy the original arguments, so it can be reused for restarting. */ 1415 original_argc= argc; 1416 original_argv= malloc(argc * sizeof(char*)); 1417 if (argc && !original_argv) 1418 exit(1); 1419 for (i= 0; i < argc; i++) 1420 original_argv[i]= strdup(argv[i]); 1421 1422 load_defaults_or_exit("my", client_test_load_default_groups, &argc, &argv); 1423 1424 get_options(&argc, &argv); 1425 /* Set main opt_count. */ 1426 opt_count= opt_count_read; 1427 1428 /* If there are any arguments left (named tests), save them. */ 1429 if (argc) 1430 { 1431 tests_to_run= malloc((argc + 1) * sizeof(char*)); 1432 if (!tests_to_run) 1433 exit(1); 1434 for (i= 0; i < argc; i++) 1435 tests_to_run[i]= strdup(argv[i]); 1436 tests_to_run[i]= NULL; 1437 } 1438 1439 if (mysql_server_init(embedded_server_arg_count, 1440 embedded_server_args, 1441 (char**) embedded_server_groups)) 1442 DIE("Can't initialize MySQL server"); 1443 1444 /* connect to server with no flags, default protocol, auto reconnect true */ 1445 mysql= client_connect(0, MYSQL_PROTOCOL_DEFAULT, 1); 1446 1447 total_time= 0; 1448 for (iter_count= 1; iter_count <= opt_count; iter_count++) 1449 { 1450 /* Start of tests */ 1451 test_count= 1; 1452 start_time= time((time_t *)0); 1453 if (!tests_to_run) 1454 { 1455 for (fptr= my_testlist; fptr->name; fptr++) 1456 (*fptr->function)(); 1457 } 1458 else 1459 { 1460 for (curr_test= tests_to_run ; *curr_test ; curr_test++) 1461 { 1462 for (fptr= my_testlist; fptr->name; fptr++) 1463 { 1464 if (!strcmp(fptr->name, *curr_test)) 1465 { 1466 (*fptr->function)(); 1467 break; 1468 } 1469 } 1470 if (!fptr->name) 1471 { 1472 fprintf(stderr, "\n\nGiven test not found: '%s'\n", *argv); 1473 fprintf(stderr, "See legal test names with %s -T\n\nAborting!\n", 1474 my_progname); 1475 client_disconnect(mysql); 1476 free_defaults(defaults_argv); 1477 mysql_server_end(); 1478 exit(1); 1479 } 1480 } 1481 } 1482 1483 end_time= time((time_t *)0); 1484 total_time+= difftime(end_time, start_time); 1485 1486 /* End of tests */ 1487 } 1488 1489 client_disconnect(mysql); /* disconnect from server */ 1490 1491 free_defaults(defaults_argv); 1492 print_test_output(); 1493 1494 while (embedded_server_arg_count > 1) 1495 my_free(embedded_server_args[--embedded_server_arg_count]); 1496 1497 mysql_server_end(); 1498 1499 my_end(0); 1500 1501 for (i= 0; i < original_argc; i++) 1502 free(original_argv[i]); 1503 if (original_argc) 1504 free(original_argv); 1505 if (tests_to_run) 1506 { 1507 for (curr_test= tests_to_run ; *curr_test ; curr_test++) 1508 free(*curr_test); 1509 free(tests_to_run); 1510 } 1511 my_free(opt_password); 1512 my_free(opt_host); 1513 1514 exit(0); 1515 } 1516