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