mirror of
https://github.com/MariaDB/server.git
synced 2025-01-16 03:52:35 +01:00
run.test mysql-test -> mysqltest
run-all-tests mysql-test -> mysqltest README mysql-test -> mysqltest Makefile.am Retargetted mysql-test to mysqltest. .del-mysql-test.c Delete: client/mysql-test.c mysql-test-run Added program definitions. mysqltest.c BitKeeper file /home/mwagner/work/bk/mysql/client/mysqltest.c
This commit is contained in:
parent
45adf2a8a7
commit
06641fd079
6 changed files with 887 additions and 57 deletions
|
@ -21,8 +21,8 @@ INCLUDES = -I$(srcdir)/../include \
|
|||
-I..
|
||||
LIBS = @CLIENT_LIBS@
|
||||
LDADD = @CLIENT_EXTRA_LDFLAGS@ ../libmysql/libmysqlclient.la
|
||||
bin_PROGRAMS = mysql mysqladmin mysqlshow mysqldump mysqlimport
|
||||
noinst_PROGRAMS = insert_test select_test thread_test mysql-test
|
||||
bin_PROGRAMS = mysql mysqladmin mysqlshow mysqldump mysqlimport mysqltest
|
||||
noinst_PROGRAMS = insert_test select_test thread_test
|
||||
noinst_HEADERS = sql_string.h completion_hash.h my_readline.h
|
||||
mysql_SOURCES = mysql.cc readline.cc sql_string.cc completion_hash.cc
|
||||
mysql_LDADD = @readline_link@ @TERMCAP_LIB@ $(LDADD) $(CXXLDFLAGS)
|
||||
|
@ -33,8 +33,8 @@ mysqldump_DEPENDENCIES= $(LIBRARIES) $(pkglib_LTLIBRARIES)
|
|||
mysqlimport_DEPENDENCIES= $(LIBRARIES) $(pkglib_LTLIBRARIES)
|
||||
insert_test_DEPENDENCIES= $(LIBRARIES) $(pkglib_LTLIBRARIES)
|
||||
select_test_DEPENDENCIES= $(LIBRARIES) $(pkglib_LTLIBRARIES)
|
||||
mysql_test_SOURCES= mysql-test.c
|
||||
mysql_test_DEPENDENCIES= $(LIBRARIES) $(pkglib_LTLIBRARIES)
|
||||
mysqltest_SOURCES= mysqltest.c
|
||||
mysqltest_DEPENDENCIES= $(LIBRARIES) $(pkglib_LTLIBRARIES)
|
||||
|
||||
# Fix for mit-threads
|
||||
DEFS = -DUNDEF_THREADS_HACK
|
||||
|
|
826
client/mysqltest.c
Normal file
826
client/mysqltest.c
Normal file
|
@ -0,0 +1,826 @@
|
|||
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
/* mysqltest test tool
|
||||
* See man page for more information.
|
||||
*
|
||||
* Written by:
|
||||
* Sasha Pachev <sasha@mysql.com>
|
||||
* Matt Wagner <matt@mysql.com>
|
||||
*
|
||||
**/
|
||||
|
||||
#define MTEST_VERSION "1.0"
|
||||
|
||||
#include "global.h"
|
||||
#include "my_sys.h"
|
||||
#include "m_string.h"
|
||||
#include "mysql.h"
|
||||
#include "mysql_version.h"
|
||||
#include "my_config.h"
|
||||
#include "mysqld_error.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <getopt.h>
|
||||
#include <stdarg.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
||||
#define MAX_QUERY 16384
|
||||
#define MAX_RECORD_FILE 128
|
||||
#define PAD_SIZE 128
|
||||
#define MAX_CONS 1024
|
||||
#define MAX_INCLUDE_DEPTH 16
|
||||
|
||||
|
||||
int record = 0, verbose = 0, silent = 0;
|
||||
const char* record_mode = "r";
|
||||
static char *db = 0, *pass=0;
|
||||
const char* user = 0, *host = 0, *unix_sock = 0;
|
||||
int port = 0;
|
||||
static const char *load_default_groups[]= { "mysqltest","client",0 };
|
||||
|
||||
FILE* file_stack[MAX_INCLUDE_DEPTH];
|
||||
FILE** cur_file;
|
||||
FILE** file_stack_end;
|
||||
|
||||
struct connection
|
||||
{
|
||||
MYSQL mysql;
|
||||
char *name;
|
||||
};
|
||||
|
||||
struct connection cons[MAX_CONS];
|
||||
struct connection* cur_con, *next_con, *cons_end;
|
||||
|
||||
struct query
|
||||
{
|
||||
char q[MAX_QUERY];
|
||||
int has_result_set;
|
||||
int first_word_len;
|
||||
int abort_on_error;
|
||||
char record_file[MAX_RECORD_FILE];
|
||||
};
|
||||
|
||||
static void die(const char* fmt, ...);
|
||||
|
||||
|
||||
int hex_val(int c)
|
||||
{
|
||||
if(isdigit(c))
|
||||
return c - '0';
|
||||
else if((c = tolower(c)) >= 'a' && c <= 'f')
|
||||
return c - 'a' + 10;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
int open_file(const char* name)
|
||||
{
|
||||
if(*cur_file && ++cur_file == file_stack_end)
|
||||
die("Source directives are nesting too deep");
|
||||
if(!(*cur_file = fopen(name, "r")))
|
||||
die("Could not read '%s'\n", name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int do_source(struct query* q)
|
||||
{
|
||||
char* p, *name;
|
||||
p = (char*)q->q + q->first_word_len;
|
||||
while(*p && isspace(*p)) p++;
|
||||
if(!*p)
|
||||
die("Missing file name in source\n");
|
||||
name = p;
|
||||
while(*p && !isspace(*p))
|
||||
p++;
|
||||
*p = 0;
|
||||
|
||||
return open_file(name);
|
||||
}
|
||||
|
||||
int do_sleep(struct query* q)
|
||||
{
|
||||
char* p, *arg;
|
||||
p = (char*)q->q + q->first_word_len;
|
||||
while(*p && isspace(*p)) p++;
|
||||
if(!*p)
|
||||
die("Missing agument in sleep\n");
|
||||
arg = p;
|
||||
while(*p && !isspace(*p))
|
||||
p++;
|
||||
*p = 0;
|
||||
|
||||
return sleep(atoi(arg));
|
||||
}
|
||||
|
||||
|
||||
int select_connection(struct query* q)
|
||||
{
|
||||
char* p, *name;
|
||||
struct connection *con;
|
||||
p = (char*)q->q + q->first_word_len;
|
||||
while(*p && isspace(*p)) p++;
|
||||
if(!*p)
|
||||
die("Missing connection name in connect\n");
|
||||
name = p;
|
||||
while(*p && !isspace(*p))
|
||||
p++;
|
||||
*p = 0;
|
||||
|
||||
for(con = cons; con < next_con; con++)
|
||||
if(!strcmp(con->name, name))
|
||||
{
|
||||
cur_con = con;
|
||||
return 0;
|
||||
}
|
||||
|
||||
die("connection '%s' not found in connection pool", name);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* this one now is a hack - we may want to improve in in the
|
||||
future to handle quotes. For now we assume that anything that is not
|
||||
a comma, a space or ) belongs to the argument. space is a chopper, comma or
|
||||
) are delimiters/terminators
|
||||
*/
|
||||
char* safe_get_param(char* str, char** arg, const char* msg)
|
||||
{
|
||||
while(*str && isspace(*str)) str++;
|
||||
*arg = str;
|
||||
while(*str && *str != ',' && *str != ')')
|
||||
{
|
||||
if(isspace(*str)) *str = 0;
|
||||
str++;
|
||||
}
|
||||
if(!*str)
|
||||
die(msg);
|
||||
|
||||
*str++ = 0;
|
||||
return str;
|
||||
}
|
||||
|
||||
int do_connect(struct query* q)
|
||||
{
|
||||
char* con_name, *con_user,*con_pass, *con_host, *con_port_str,
|
||||
*con_db, *con_sock;
|
||||
char* p;
|
||||
|
||||
p = q->q + q->first_word_len;
|
||||
|
||||
while(*p && isspace(*p)) p++;
|
||||
if(*p != '(')
|
||||
die("Syntax error in connect - expeected '(' found '%c'", *p);
|
||||
p++;
|
||||
p = safe_get_param(p, &con_name, "missing connection name");
|
||||
p = safe_get_param(p, &con_host, "missing connection host");
|
||||
p = safe_get_param(p, &con_user, "missing connection user");
|
||||
p = safe_get_param(p, &con_pass, "missing connection password");
|
||||
p = safe_get_param(p, &con_db, "missing connection db");
|
||||
p = safe_get_param(p, &con_port_str, "missing connection port");
|
||||
p = safe_get_param(p, &con_sock, "missing connection scoket");
|
||||
if(next_con == cons_end)
|
||||
die("Connection limit exhausted - incread MAX_CONS in mysqltest.c");
|
||||
|
||||
if(!mysql_init(&next_con->mysql))
|
||||
die("Failed on mysql_init()");
|
||||
if(!mysql_real_connect(&next_con->mysql, con_host, con_user, con_pass,
|
||||
con_db, atoi(con_port_str), con_sock, 0))
|
||||
die("Could not open connection '%s': %s", con_name,
|
||||
mysql_error(&next_con->mysql));
|
||||
|
||||
if(!(next_con->name = my_strdup(con_name, MYF(MY_WME))))
|
||||
die("Out of memory");
|
||||
cur_con = next_con++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void close_cons()
|
||||
{
|
||||
for(--next_con; next_con >= cons; --next_con)
|
||||
{
|
||||
mysql_close(&next_con->mysql);
|
||||
my_free(next_con->name, MYF(0));
|
||||
}
|
||||
}
|
||||
|
||||
int safe_copy_unescape(char* dest, char* src, int size)
|
||||
{
|
||||
register char* p_dest = dest, *p_src = src;
|
||||
register int c, val;
|
||||
enum { ST_NORMAL, ST_ESCAPED, ST_HEX2} state = ST_NORMAL ;
|
||||
|
||||
size--; /* just to make life easier */
|
||||
|
||||
for(; p_dest - size < dest && p_src - size < src
|
||||
&& (c = *p_src) != '\n' && c; ++p_src )
|
||||
{
|
||||
switch(state)
|
||||
{
|
||||
case ST_NORMAL:
|
||||
if(c == '\\')
|
||||
{
|
||||
state = ST_ESCAPED;
|
||||
}
|
||||
else
|
||||
*p_dest++ = c;
|
||||
break;
|
||||
case ST_ESCAPED:
|
||||
if((val = hex_val(c)) > 0)
|
||||
{
|
||||
*p_dest = val;
|
||||
state = ST_HEX2;
|
||||
}
|
||||
else
|
||||
{
|
||||
state = ST_NORMAL;
|
||||
*p_dest++ = c;
|
||||
}
|
||||
break;
|
||||
case ST_HEX2:
|
||||
if((val = hex_val(c)) > 0)
|
||||
{
|
||||
*p_dest = (*p_dest << 4) + val;
|
||||
p_dest++;
|
||||
}
|
||||
else
|
||||
*p_dest++ = c;
|
||||
|
||||
state = ST_NORMAL;
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
*p_dest = 0;
|
||||
return (p_dest - dest);
|
||||
}
|
||||
|
||||
int read_line(char* buf, int size)
|
||||
{
|
||||
int c;
|
||||
char* p = buf, *buf_end = buf + size;
|
||||
int no_save = 0;
|
||||
enum {R_NORMAL, R_Q1, R_ESC_Q_Q1, R_ESC_Q_Q2,
|
||||
R_ESC_SLASH_Q1, R_ESC_SLASH_Q2,
|
||||
R_Q2, R_COMMENT, R_LINE_START} state = R_LINE_START;
|
||||
|
||||
for(; p < buf_end ;)
|
||||
{
|
||||
no_save = 0;
|
||||
c = fgetc(*cur_file);
|
||||
if(feof(*cur_file))
|
||||
{
|
||||
fclose(*cur_file);
|
||||
|
||||
if(cur_file == file_stack)
|
||||
return 1;
|
||||
else
|
||||
{
|
||||
cur_file--;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
switch(state)
|
||||
{
|
||||
case R_NORMAL:
|
||||
if(c == ';')
|
||||
{
|
||||
*p = 0;
|
||||
return 0;
|
||||
}
|
||||
else if(c == '\'')
|
||||
state = R_Q1;
|
||||
else if(c == '"')
|
||||
state = R_Q2;
|
||||
else if(c == '\n')
|
||||
state = R_LINE_START;
|
||||
|
||||
break;
|
||||
case R_COMMENT:
|
||||
no_save = 1;
|
||||
if(c == '\n')
|
||||
state = R_LINE_START;
|
||||
break;
|
||||
|
||||
case R_LINE_START:
|
||||
if(c == '#')
|
||||
{
|
||||
state = R_COMMENT;
|
||||
no_save = 1;
|
||||
}
|
||||
else if(isspace(c))
|
||||
no_save = 1;
|
||||
else
|
||||
state = R_NORMAL;
|
||||
break;
|
||||
|
||||
case R_Q1:
|
||||
if(c == '\'')
|
||||
state = R_ESC_Q_Q1;
|
||||
else if(c == '\\')
|
||||
state = R_ESC_SLASH_Q1;
|
||||
break;
|
||||
case R_ESC_Q_Q1:
|
||||
if(c == ';')
|
||||
{
|
||||
*p = 0;
|
||||
return 0;
|
||||
}
|
||||
if(c != '\'')
|
||||
state = R_NORMAL;
|
||||
break;
|
||||
case R_ESC_SLASH_Q1:
|
||||
state = R_Q1;
|
||||
break;
|
||||
|
||||
case R_Q2:
|
||||
if(c == '"')
|
||||
state = R_ESC_Q_Q2;
|
||||
else if(c == '\\')
|
||||
state = R_ESC_SLASH_Q2;
|
||||
break;
|
||||
case R_ESC_Q_Q2:
|
||||
if(c == ';')
|
||||
{
|
||||
*p = 0;
|
||||
return 0;
|
||||
}
|
||||
if(c != '"')
|
||||
state = R_NORMAL;
|
||||
break;
|
||||
case R_ESC_SLASH_Q2:
|
||||
state = R_Q2;
|
||||
break;
|
||||
}
|
||||
|
||||
if(!no_save)
|
||||
*p++ = c;
|
||||
}
|
||||
return feof(*cur_file);
|
||||
}
|
||||
|
||||
int read_query(struct query* q)
|
||||
{
|
||||
char buf[MAX_QUERY];
|
||||
char* p = buf,* p1 ;
|
||||
int c;
|
||||
|
||||
q->record_file[0] = 0;
|
||||
q->abort_on_error = 1;
|
||||
q->has_result_set = 0;
|
||||
q->first_word_len = 0;
|
||||
|
||||
if(read_line(buf, sizeof(buf)))
|
||||
return 1;
|
||||
if(buf[0] == '!')
|
||||
{
|
||||
q->abort_on_error = 0;
|
||||
p++;
|
||||
}
|
||||
|
||||
while(*p && isspace(*p)) p++ ;
|
||||
if(*p == '@')
|
||||
{
|
||||
q->has_result_set = 1;
|
||||
p++;
|
||||
p1 = q->record_file;
|
||||
while(!isspace(c = *p) &&
|
||||
p1 < q->record_file + sizeof(q->record_file) - 1)
|
||||
*p1++ = *p++;
|
||||
*p1 = 0;
|
||||
|
||||
}
|
||||
|
||||
while(*p && isspace(*p)) p++;
|
||||
p1 = q->q;
|
||||
while(*p && !isspace(*p))
|
||||
*p1++ = *p++;
|
||||
|
||||
q->first_word_len = p1 - q->q;
|
||||
strcpy(p1, p);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct option long_options[] =
|
||||
{
|
||||
{"verbose", no_argument, 0, 'v'},
|
||||
{"version", no_argument, 0, 'V'},
|
||||
{"silent", no_argument, 0, 'q'},
|
||||
{"quiet", no_argument, 0, 'q'},
|
||||
{"record", no_argument, 0, 'r'},
|
||||
{"help", no_argument, 0, '?'},
|
||||
{"user", required_argument, 0, 'u'},
|
||||
{"password", optional_argument, 0, 'p'},
|
||||
{"host", required_argument, 0, 'h'},
|
||||
{"socket", required_argument, 0, 'S'},
|
||||
{"database", required_argument, 0, 'D'},
|
||||
{"port", required_argument, 0, 'P'},
|
||||
{0, 0,0,0}
|
||||
};
|
||||
|
||||
void die(const char* fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
fprintf(stderr, "%s: ", my_progname);
|
||||
vfprintf(stderr, fmt, args);
|
||||
fprintf(stderr, "\n");
|
||||
va_end(args);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void verbose_msg(const char* fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
if(!verbose) return;
|
||||
|
||||
va_start(args, fmt);
|
||||
|
||||
fprintf(stderr, "%s: ", my_progname);
|
||||
vfprintf(stderr, fmt, args);
|
||||
fprintf(stderr, "\n");
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
static void print_version(void)
|
||||
{
|
||||
printf("%s Ver %s Distrib %s, for %s (%s)\n",my_progname,MTEST_VERSION,
|
||||
MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE);
|
||||
}
|
||||
|
||||
void usage()
|
||||
{
|
||||
print_version();
|
||||
printf("MySQL AB, by Sasha & Matt\n");
|
||||
printf("This software comes with ABSOLUTELY NO WARRANTY\n\n");
|
||||
printf("Runs a test against the mysql server and compares output with a results file.\n\n");
|
||||
printf("Usage: %s [OPTIONS] [database] < test_file\n", my_progname);
|
||||
printf("\n\
|
||||
-?, --help Display this help and exit.\n\
|
||||
-h, --host=... Connect to host.\n\
|
||||
-u, --user=... User for login.\n\
|
||||
-p[password], --password[=...]\n\
|
||||
Password to use when connecting to server.\n\
|
||||
-D, --database=... Database to use.\n\
|
||||
-P, --port=... Port number to use for connection.\n\
|
||||
-S, --socket=... Socket file to use for connection.\n\
|
||||
-r, --record Record output of test_file into result file.\n\
|
||||
-v, --verbose Write more.\n\
|
||||
-q, --quiet, --silent Suppress all normal output.\n\
|
||||
-V, --version Output version information and exit.\n\n");
|
||||
}
|
||||
|
||||
int parse_args(int argc, char **argv)
|
||||
{
|
||||
int c, option_index = 0;
|
||||
my_bool tty_password=0;
|
||||
|
||||
load_defaults("my",load_default_groups,&argc,&argv);
|
||||
while((c = getopt_long(argc, argv, "h:p::u:P:D:S:?rvVq",
|
||||
long_options, &option_index)) != EOF)
|
||||
{
|
||||
switch(c)
|
||||
{
|
||||
case 'v':
|
||||
verbose = 1;
|
||||
break;
|
||||
case 'r':
|
||||
record = 1;
|
||||
record_mode = "w";
|
||||
break;
|
||||
case 'u':
|
||||
user = optarg;
|
||||
break;
|
||||
case 'p':
|
||||
if (optarg)
|
||||
{
|
||||
my_free(pass,MYF(MY_ALLOW_ZERO_PTR));
|
||||
pass=my_strdup(optarg,MYF(MY_FAE));
|
||||
while (*optarg) *optarg++= 'x'; /* Destroy argument */
|
||||
}
|
||||
else
|
||||
tty_password=1;
|
||||
break;
|
||||
case 'P':
|
||||
port = atoi(optarg);
|
||||
break;
|
||||
case 'S':
|
||||
unix_sock = optarg;
|
||||
break;
|
||||
case 'D':
|
||||
db = optarg;
|
||||
break;
|
||||
case 'h':
|
||||
host = optarg;
|
||||
break;
|
||||
case 'q':
|
||||
silent = 1;
|
||||
break;
|
||||
case 'V':
|
||||
print_version();
|
||||
exit(0);
|
||||
case '?':
|
||||
usage();
|
||||
exit(0);
|
||||
default:
|
||||
usage();
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
argc-=optind;
|
||||
argv+=optind;
|
||||
if (argc > 1)
|
||||
{
|
||||
usage();
|
||||
exit(1);
|
||||
}
|
||||
if (argc == 1)
|
||||
{
|
||||
my_free(db,MYF(MY_ALLOW_ZERO_PTR));
|
||||
db=my_strdup(*argv,MYF(MY_WME));
|
||||
}
|
||||
if (tty_password)
|
||||
pass=get_tty_password(NullS);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
char* safe_str_append(char* buf, char* str, int size)
|
||||
{
|
||||
int i,c ;
|
||||
for(i = 0; (c = *str++) && i < size - 1; i++)
|
||||
*buf++ = c;
|
||||
*buf = 0;
|
||||
return buf;
|
||||
}
|
||||
|
||||
void reject_dump(char* record_file, char* buf, int size)
|
||||
{
|
||||
char reject_file[MAX_RECORD_FILE+16];
|
||||
char* p;
|
||||
FILE* freject;
|
||||
|
||||
p = reject_file;
|
||||
p = safe_str_append(p, record_file, size);
|
||||
p = safe_str_append(p, (char*)".reject", reject_file + size - p);
|
||||
|
||||
if(!(freject = fopen(reject_file, "w")))
|
||||
die("Could not open reject file %s, error %d", reject_file, errno);
|
||||
fwrite(buf, size, 1, freject);
|
||||
fclose(freject);
|
||||
}
|
||||
|
||||
int run_query(MYSQL* mysql, struct query* q)
|
||||
{
|
||||
MYSQL_RES* res = 0;
|
||||
MYSQL_FIELD* fields;
|
||||
MYSQL_ROW row;
|
||||
int num_fields,i, error = 0;
|
||||
FILE* frecord = 0;
|
||||
char* res_buf = 0, *p_res_buf = 0, *res_buf_end = 0, *record_buf = 0;
|
||||
struct stat info;
|
||||
unsigned long* lengths;
|
||||
char* val;
|
||||
int len;
|
||||
|
||||
|
||||
if(q->record_file[0])
|
||||
{
|
||||
if(!(frecord = fopen(q->record_file, record_mode)))
|
||||
die("Error %d opening record file '%s'", errno, q->record_file);
|
||||
if(!record)
|
||||
{
|
||||
if(stat(q->record_file, &info))
|
||||
die("Error %d on stat of record file '%s'", errno, q->record_file);
|
||||
if(!(p_res_buf = res_buf =
|
||||
(char*)malloc(info.st_size + PAD_SIZE)))
|
||||
die("malloc() failed trying to allocate %d bytes", info.st_size);
|
||||
res_buf_end = res_buf + info.st_size + PAD_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
if(mysql_query(mysql, q->q))
|
||||
{
|
||||
if(q->abort_on_error)
|
||||
die("query '%s' failed: %s", q->q, mysql_error(mysql));
|
||||
else
|
||||
{
|
||||
verbose_msg("query '%s' failed: %s", q->q, mysql_error(mysql));
|
||||
/* if we do not abort on error, failure to run the query does
|
||||
not fail the whole test case
|
||||
*/
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
if(!q->has_result_set)
|
||||
goto end;
|
||||
|
||||
if(!(res = mysql_store_result(mysql)))
|
||||
{
|
||||
if(q->abort_on_error)
|
||||
die("failed in mysql_store_result for query '%s'", q->q);
|
||||
else
|
||||
{
|
||||
verbose_msg("failed in mysql_store_result for query '%s'", q->q);
|
||||
error = 1;
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
if(!frecord)
|
||||
goto end;
|
||||
|
||||
fields = mysql_fetch_fields(res);
|
||||
num_fields = mysql_num_fields(res);
|
||||
for( i = 0; i < num_fields; i++)
|
||||
{
|
||||
if(record)
|
||||
fprintf(frecord, "%s\t", fields[i].name);
|
||||
else
|
||||
{
|
||||
p_res_buf = safe_str_append(p_res_buf, fields[i].name,
|
||||
res_buf_end - p_res_buf - 1);
|
||||
*p_res_buf++ = '\t';
|
||||
}
|
||||
}
|
||||
|
||||
if(record)
|
||||
fputc('\n', frecord);
|
||||
else if(res_buf_end > p_res_buf)
|
||||
*p_res_buf++ = '\n';
|
||||
|
||||
while((row = mysql_fetch_row(res)))
|
||||
{
|
||||
lengths = mysql_fetch_lengths(res);
|
||||
for(i = 0; i < num_fields; i++)
|
||||
{
|
||||
val = (char*)row[i];
|
||||
len = lengths[i];
|
||||
|
||||
if(!val)
|
||||
{
|
||||
val = (char*)"NULL";
|
||||
len = 4;
|
||||
}
|
||||
if(record)
|
||||
{
|
||||
fwrite(val, len, 1, frecord);
|
||||
fputc('\t', frecord);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(p_res_buf + len + 1 < res_buf_end)
|
||||
{
|
||||
memcpy(p_res_buf, val, len);
|
||||
p_res_buf += len;
|
||||
*p_res_buf++ = '\t';
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if(record)
|
||||
fputc('\n', frecord);
|
||||
else if(res_buf_end > p_res_buf)
|
||||
*p_res_buf++ = '\n';
|
||||
|
||||
}
|
||||
|
||||
if(!record && frecord)
|
||||
{
|
||||
if( (len = p_res_buf - res_buf) != info.st_size)
|
||||
{
|
||||
verbose_msg("Result length mismatch: actual %d, expected = %d ", len,
|
||||
info.st_size);
|
||||
reject_dump(q->record_file, res_buf, len);
|
||||
error = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!(record_buf = (char*)malloc(info.st_size)))
|
||||
die("malloc() failed allocating %d bytes", info.st_size);
|
||||
fread(record_buf, info.st_size, 1, frecord);
|
||||
if(memcmp(record_buf, res_buf, len))
|
||||
{
|
||||
verbose_msg("Result not the same as the record");
|
||||
reject_dump(q->record_file, res_buf, len);
|
||||
error = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
end:
|
||||
if(res_buf) free(res_buf);
|
||||
if(record_buf) free(record_buf);
|
||||
if(res) mysql_free_result(res);
|
||||
if(frecord) fclose(frecord);
|
||||
return error;
|
||||
}
|
||||
|
||||
int check_first_word(struct query* q, const char* word, int len)
|
||||
{
|
||||
const char* p, *p1, *end;
|
||||
|
||||
if(len != q->first_word_len)
|
||||
return 0;
|
||||
|
||||
|
||||
p = word;
|
||||
end = p + len;
|
||||
p1 = q->q;
|
||||
|
||||
for(; p < end; p++, p1++)
|
||||
if(tolower(*p) != tolower(*p1))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
int error = 0;
|
||||
struct query q;
|
||||
|
||||
MY_INIT(argv[0]);
|
||||
memset(cons, 0, sizeof(cons));
|
||||
cons_end = cons + MAX_CONS;
|
||||
next_con = cons + 1;
|
||||
cur_con = cons;
|
||||
|
||||
memset(file_stack, 0, sizeof(file_stack));
|
||||
file_stack_end = file_stack + MAX_INCLUDE_DEPTH;
|
||||
cur_file = file_stack;
|
||||
|
||||
parse_args(argc, argv);
|
||||
if(!*cur_file)
|
||||
*cur_file = stdin;
|
||||
|
||||
|
||||
|
||||
if(!( mysql_init(&cur_con->mysql)))
|
||||
die("Failed in mysql_init()");
|
||||
|
||||
mysql_options(&cur_con->mysql, MYSQL_READ_DEFAULT_GROUP, "mysql");
|
||||
|
||||
if(!mysql_real_connect(&cur_con->mysql, host,
|
||||
user, pass, db, port, unix_sock,
|
||||
0))
|
||||
die("Failed in mysql_real_connect(): %s", mysql_error(&cur_con->mysql));
|
||||
cur_con->name = my_strdup("default", MYF(MY_WME));
|
||||
if(!cur_con->name)
|
||||
die("Out of memory");
|
||||
|
||||
while(!read_query(&q))
|
||||
{
|
||||
if(check_first_word(&q, "connect", 7))
|
||||
do_connect(&q);
|
||||
else if(check_first_word(&q, "connection", 10))
|
||||
select_connection(&q);
|
||||
else if(check_first_word(&q, "source", 6))
|
||||
do_source(&q);
|
||||
else if(check_first_word(&q, "sleep", 5))
|
||||
do_sleep(&q);
|
||||
else
|
||||
error |= run_query(&cur_con->mysql, &q);
|
||||
}
|
||||
|
||||
close_cons();
|
||||
|
||||
if (!silent) {
|
||||
if(error)
|
||||
printf("not ok\n");
|
||||
else
|
||||
printf("ok\n");
|
||||
}
|
||||
|
||||
exit(error);
|
||||
return error;
|
||||
}
|
|
@ -17,6 +17,7 @@ cd $CWD
|
|||
MYBIN="$CWD/mybin"
|
||||
TESTVER=3.23
|
||||
TESTDIR="$CWD/t/$TESTVER"
|
||||
TESTSUFFIX=test
|
||||
TOT_PASS=0
|
||||
TOT_FAIL=0
|
||||
TOT_TEST=0
|
||||
|
@ -46,9 +47,12 @@ MYERR="$CWD/var/log/mysqld.err"
|
|||
#++
|
||||
# Program Definitions
|
||||
#--
|
||||
ECHO=/bin/echo
|
||||
EXPR=/usr/bin/expr
|
||||
PRINTF=/usr/bin/printf
|
||||
TIME=/usr/bin/time
|
||||
MYSQLD="$BASEDIR/sql/mysqld"
|
||||
MYSQL_TEST="$BASEDIR/client/mysql-test"
|
||||
MYSQL_TEST="$BASEDIR/client/mysqltest"
|
||||
MYSQLADMIN="$BASEDIR/client/mysqladmin"
|
||||
MYSQL_TEST="$MYSQL_TEST --socket=$MYSOCK --database=$DB --user=$USER --password=$PASSWD --silent"
|
||||
INSTALL_DB="$MYBIN/mysql-test_install_db"
|
||||
|
@ -57,11 +61,11 @@ INSTALL_DB="$MYBIN/mysql-test_install_db"
|
|||
#++
|
||||
# Terminal Modifications
|
||||
#--
|
||||
MOVE_TO_COL="echo -en \\033[300C\\033[20D"
|
||||
SETCOLOR_SUCCESS="echo -en \\033[1;32m"
|
||||
SETCOLOR_FAILURE="echo -en \\033[1;31m"
|
||||
SETCOLOR_WARNING="echo -en \\033[1;33m"
|
||||
SETCOLOR_NORMAL="echo -en \\033[0;39m"
|
||||
MOVE_TO_COL="$ECHO -en \\033[300C\\033[20D"
|
||||
SETCOLOR_SUCCESS="$ECHO -en \\033[1;32m"
|
||||
SETCOLOR_FAILURE="$ECHO -en \\033[1;31m"
|
||||
SETCOLOR_WARNING="$ECHO -en \\033[1;33m"
|
||||
SETCOLOR_NORMAL="$ECHO -en \\033[0;39m"
|
||||
|
||||
|
||||
|
||||
|
@ -70,78 +74,78 @@ SETCOLOR_NORMAL="echo -en \\033[0;39m"
|
|||
#--
|
||||
echo_ok() {
|
||||
$MOVE_TO_COL && $SETCOLOR_NORMAL
|
||||
echo -n "[ "
|
||||
$ECHO -n "[ "
|
||||
$SETCOLOR_SUCCESS
|
||||
echo -n "ok"
|
||||
$ECHO -n "ok"
|
||||
$SETCOLOR_NORMAL
|
||||
echo " ]"
|
||||
$ECHO " ]"
|
||||
return 0
|
||||
}
|
||||
|
||||
echo_notok() {
|
||||
$MOVE_TO_COL && $SETCOLOR_NORMAL
|
||||
echo -n "[ "
|
||||
$ECHO -n "[ "
|
||||
$SETCOLOR_FAILURE
|
||||
echo -n "not ok"
|
||||
$ECHO -n "not ok"
|
||||
$SETCOLOR_NORMAL
|
||||
echo " ]"
|
||||
$ECHO " ]"
|
||||
return 0
|
||||
}
|
||||
|
||||
echo_pass () {
|
||||
$MOVE_TO_COL && $SETCOLOR_NORMAL
|
||||
echo -n "[ "
|
||||
$ECHO -n "[ "
|
||||
$SETCOLOR_SUCCESS
|
||||
echo -n "pass"
|
||||
$ECHO -n "pass"
|
||||
$SETCOLOR_NORMAL
|
||||
echo " ]"
|
||||
$ECHO " ]"
|
||||
return 0
|
||||
}
|
||||
|
||||
echo_fail () {
|
||||
$MOVE_TO_COL && $SETCOLOR_NORMAL
|
||||
echo -n "[ "
|
||||
$ECHO -n "[ "
|
||||
$SETCOLOR_FAILURE
|
||||
echo -n "fail"
|
||||
$ECHO -n "fail"
|
||||
$SETCOLOR_NORMAL
|
||||
echo " ]"
|
||||
$ECHO " ]"
|
||||
return 0
|
||||
}
|
||||
|
||||
error () {
|
||||
|
||||
$SETCOLOR_FAILURE
|
||||
echo -n "Error: " && $SETCOLOR_NORMAL && echo $1
|
||||
$ECHO -n "Error: " && $SETCOLOR_NORMAL && $ECHO $1
|
||||
$SETCOLOR_NORMAL
|
||||
exit 1
|
||||
}
|
||||
|
||||
pass_inc () {
|
||||
TOT_PASS=`expr $TOT_PASS + 1`
|
||||
TOT_PASS=`$EXPR $TOT_PASS + 1`
|
||||
}
|
||||
|
||||
fail_inc () {
|
||||
TOT_FAIL=`expr $TOT_FAIL + 1`
|
||||
TOT_FAIL=`$EXPR $TOT_FAIL + 1`
|
||||
}
|
||||
|
||||
total_inc () {
|
||||
TOT_TEST=`expr $TOT_TEST + 1`
|
||||
TOT_TEST=`$EXPR $TOT_TEST + 1`
|
||||
}
|
||||
|
||||
report_stats () {
|
||||
if [ $TOT_FAIL = 0 ]; then
|
||||
echo "All tests successful."
|
||||
$ECHO "All tests successful."
|
||||
else
|
||||
echo -n "Failed ${TOT_FAIL}/${TOT_TEST} tests, "
|
||||
$ECHO -n "Failed ${TOT_FAIL}/${TOT_TEST} tests, "
|
||||
|
||||
xten=`expr $TOT_PASS \* 10000` #
|
||||
raw=`expr $xten / $TOT_TEST` # My God
|
||||
raw=`printf %.4d $raw` # This is such a ...
|
||||
whole=`printf %.2s $raw` # Narttu!!
|
||||
xwhole=`expr $whole \* 100` # Hynda!!!
|
||||
deci=`expr $raw - $xwhole` #
|
||||
xten=`$EXPR $TOT_PASS \* 10000` #
|
||||
raw=`$EXPR $xten / $TOT_TEST` # My God
|
||||
raw=`$PRINTF %.4d $raw` # This is such a ...
|
||||
whole=`$PRINTF %.2s $raw` # Narttu!!
|
||||
xwhole=`$EXPR $whole \* 100` # Hynda!!!
|
||||
deci=`$EXPR $raw - $xwhole` #
|
||||
|
||||
echo "${whole}.${deci}% successful."
|
||||
$ECHO "${whole}.${deci}% successful."
|
||||
fi
|
||||
}
|
||||
|
||||
|
@ -197,27 +201,27 @@ mysql_loadstd () {
|
|||
|
||||
mysql_install_db
|
||||
|
||||
$SETCOLOR_NORMAL && echo -n "Starting mysqld for Testing"
|
||||
$SETCOLOR_NORMAL && $ECHO -n "Starting mysqld for Testing"
|
||||
mysql_start
|
||||
res=$?
|
||||
res=1
|
||||
[ $res != 1 ] && echo_notok && error "Starting mysqld"
|
||||
[ $res = 1 ] && echo_ok
|
||||
|
||||
$SETCOLOR_NORMAL && echo -n "Loading Standard Test Database"
|
||||
$SETCOLOR_NORMAL && $ECHO -n "Loading Standard Test Database"
|
||||
mysql_loadstd
|
||||
res=$?
|
||||
[ $res != 1 ] && echo_notok && error "Loading STD"
|
||||
[ $res = 1 ] && echo_ok
|
||||
|
||||
$SETCOLOR_NORMAL && echo -n "Starting Tests for MySQL $TESTVER Series"
|
||||
$SETCOLOR_NORMAL && $ECHO -n "Starting Tests for MySQL $TESTVER Series"
|
||||
$SETCOLOR_SUCCESS && echo_ok
|
||||
|
||||
echo
|
||||
echo -e " TEST\t\t\tUSER\tSYSTEM\tELAPSED\t%CPU\t RESULT"
|
||||
echo $DASH72
|
||||
$ECHO
|
||||
$ECHO -e " TEST\t\t\tUSER\tSYSTEM\tELAPSED\t%CPU\t RESULT"
|
||||
$ECHO $DASH72
|
||||
|
||||
for tf in $TESTDIR/*.test
|
||||
for tf in $TESTDIR/*.$TESTSUFFIX
|
||||
do
|
||||
if [ -f $tf ] ; then
|
||||
mytime=`$TIME -f $TIME_FORMAT $MYSQL_TEST < $tf 2>&1`
|
||||
|
@ -225,31 +229,31 @@ do
|
|||
|
||||
tf=`basename $tf`
|
||||
|
||||
[ $res = 1 ] && mytime=`echo -ne $mytime | cut -b 39-`
|
||||
$SETCOLOR_NORMAL && echo -ne "$tf\t$mytime"
|
||||
[ $res = 1 ] && mytime=`$ECHO -ne $mytime | cut -b 39-`
|
||||
$SETCOLOR_NORMAL && $ECHO -ne "$tf\t$mytime"
|
||||
[ $res = 1 ] && fail_inc && echo_fail
|
||||
[ $res != 1 ] && pass_inc && echo_pass
|
||||
|
||||
total_inc
|
||||
|
||||
if [ $res != 0 ]; then
|
||||
echo
|
||||
$SETCOLOR_NORMAL && echo -ne "Restarting mysqld\t$DASHBLANK"
|
||||
$ECHO
|
||||
$SETCOLOR_NORMAL && $ECHO -ne "Restarting mysqld\t$DASHBLANK"
|
||||
mysql_restart
|
||||
$SETCOLOR_SUCCESS && echo_ok
|
||||
$SETCOLOR_NORMAL && echo -ne "Resuming Tests\t\t$DASHBLANK"
|
||||
$SETCOLOR_NORMAL && $ECHO -ne "Resuming Tests\t\t$DASHBLANK"
|
||||
$SETCOLOR_SUCCESS && echo_ok
|
||||
echo
|
||||
$ECHO
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
echo $DASH72
|
||||
echo
|
||||
$SETCOLOR_NORMAL && echo -n "Ending Tests for MySQL $TESTVER Series"
|
||||
$ECHO $DASH72
|
||||
$ECHO
|
||||
$SETCOLOR_NORMAL && $ECHO -n "Ending Tests for MySQL $TESTVER Series"
|
||||
$SETCOLOR_SUCCESS && echo_ok
|
||||
|
||||
$SETCOLOR_NORMAL && echo -n "Shutdown mysqld"
|
||||
$SETCOLOR_NORMAL && $ECHO -n "Shutdown mysqld"
|
||||
mysql_stop
|
||||
res=$?
|
||||
res=1
|
||||
|
@ -258,8 +262,8 @@ res=1
|
|||
|
||||
$SETCOLOR_NORMAL
|
||||
|
||||
echo
|
||||
$ECHO
|
||||
report_stats
|
||||
echo
|
||||
$ECHO
|
||||
|
||||
exit 0
|
||||
|
|
|
@ -9,4 +9,4 @@ sh run-all-tests
|
|||
If you would like to add your own test case, create a directory
|
||||
test-your-test-case-name, write your own run.test following the examples
|
||||
in the other test cases. Note that you can create the files containing
|
||||
the expected output ( master files) by running mysql-test --record < run.test
|
||||
the expected output ( master files) by running mysqltest --record < run.test
|
|
@ -4,6 +4,6 @@ for d in test-*; do
|
|||
cd $d
|
||||
echo -n $d | sed -e s/test-//
|
||||
echo -n "...."
|
||||
../../client/mysql-test $@ < run.test
|
||||
../../client/mysqltest $@ < run.test
|
||||
cd ..
|
||||
done
|
|
@ -1,4 +1,4 @@
|
|||
#! ../client/mysql-test
|
||||
#! ../client/mysqltest
|
||||
# tests if the replicaion preserves timestamp properly
|
||||
|
||||
source ../include/master-slave.inc;
|
||||
|
|
Loading…
Reference in a new issue