summaryrefslogtreecommitdiff
path: root/client
diff options
context:
space:
mode:
authorunknown <sasha@mysql.sashanet.com>2000-12-12 12:12:41 -0700
committerunknown <sasha@mysql.sashanet.com>2000-12-12 12:12:41 -0700
commit078c05d50a60871d49f754c0241bf47d4407327f (patch)
tree982acf7a74d794e3241181648d96450854156f76 /client
parent2ce474dc658a42ad1bf6e8f5842babb5a86dd333 (diff)
downloadmariadb-git-078c05d50a60871d49f754c0241bf47d4407327f.tar.gz
client/mysqltest.c
add --result-file option mysql-test/mysql-test-run do a really good job to kill mysqld if it is stuck client/mysqltest.c: add --result-file option mysql-test/mysql-test-run: do a really good job to kill mysqld if it is stuck
Diffstat (limited to 'client')
-rw-r--r--client/mysqltest.c261
1 files changed, 151 insertions, 110 deletions
diff --git a/client/mysqltest.c b/client/mysqltest.c
index 8e5848734ee..20b8c06d451 100644
--- a/client/mysqltest.c
+++ b/client/mysqltest.c
@@ -31,6 +31,7 @@
#include "mysql.h"
#include "mysql_version.h"
#include "my_config.h"
+#include "my_dir.h"
#include "mysqld_error.h"
#include <stdio.h>
#include <stdlib.h>
@@ -81,6 +82,8 @@ typedef
PARSER parser;
int block_ok = 1; /* set to 0 if the current block should not be executed */
int false_block_depth = 0;
+const char* result_file = 0; /* if set, all results are concated and
+ compared against this file*/
typedef struct
{
@@ -113,9 +116,26 @@ struct query
Q_UNKNOWN} type;
};
+#define DS_CHUNK 16384
+
+typedef struct dyn_string
+{
+ char* str;
+ int len,max_len;
+} DYN_STRING;
+
+DYN_STRING ds_res;
+
+void dyn_string_init(DYN_STRING* ds);
+void dyn_string_append(DYN_STRING* ds, const char* str, int len);
+int dyn_string_cmp(DYN_STRING* ds, const char* fname);
+void reject_dump(const char* record_file, char* buf, int size);
+
+
static void die(const char* fmt, ...);
int close_connection(struct query* q);
VAR* var_get(char* var_name, char* var_name_end, int raw);
+void verbose_msg(const char* fmt, ...);
void init_parser()
{
@@ -133,6 +153,83 @@ int hex_val(int c)
return -1;
}
+void dyn_string_init(DYN_STRING* ds)
+{
+ if(!(ds->str = (char*)my_malloc(DS_CHUNK, MYF(0))))
+ die("Out of memory");
+ ds->len = 0;
+ ds->max_len = DS_CHUNK;
+}
+void dyn_string_append(DYN_STRING* ds, const char* str, int len)
+{
+ int new_len;
+ if(!len)
+ len = strlen(str);
+ new_len = ds->len + len;
+ if(new_len > ds->max_len)
+ {
+ int new_alloc_len = (new_len & ~(DS_CHUNK-1)) + DS_CHUNK;
+ char* tmp = (char*) my_malloc(new_alloc_len, MYF(0));
+ if(!tmp)
+ die("Out of memory");
+ memcpy(tmp, ds->str, ds->len);
+ memcpy(tmp + ds->len, str, len);
+ my_free((gptr)ds->str, MYF(0));
+ ds->str = tmp;
+ ds->len = new_len;
+ ds->max_len = new_alloc_len;
+ }
+ else
+ {
+ memcpy(ds->str + ds->len, str, len);
+ ds->len += len;
+ }
+}
+int dyn_string_cmp(DYN_STRING* ds, const char* fname)
+{
+ MY_STAT stat_info;
+ char *tmp;
+ int res;
+ int fd;
+ if(!my_stat(fname, &stat_info, MYF(MY_WME)))
+ die("Could not stat %s: errno =%d", fname, errno);
+ if(stat_info.st_size != ds->len)
+ return 2;
+ if(!(tmp = (char*) my_malloc(ds->len, MYF(0))))
+ die("Out of memory");
+ if((fd = my_open(fname, O_RDONLY, MYF(MY_WME))) < 0)
+ die("Could not open %s: errno = %d", fname, errno);
+ if(my_read(fd, (byte*)tmp, stat_info.st_size, MYF(MY_WME|MY_NABP)))
+ die("read failed");
+ res = (memcmp(tmp, ds->str, stat_info.st_size)) ? 1 : 0;
+ my_free((gptr)tmp, MYF(0));
+ my_close(fd, MYF(0));
+ return res;
+}
+
+int check_result(DYN_STRING* ds, const char* fname)
+{
+ int error = 0;
+ switch(dyn_string_cmp(ds, fname))
+ {
+ case 0:
+ break; /* ok */
+ case 2:
+ verbose_msg("Result length mismatch");
+ error = 1;
+ break;
+ case 1:
+ verbose_msg("Result content mismatch");
+ error = 1;
+ break;
+ default: /* impossible */
+ die("Unknown error code from dyn_string_cmp()");
+ }
+ if(error)
+ reject_dump(fname, ds->str, ds->len);
+ return error;
+}
+
VAR* var_get(char* var_name, char* var_name_end, int raw)
{
int digit;
@@ -491,7 +588,7 @@ void close_cons()
for(--next_con; next_con >= cons; --next_con)
{
mysql_close(&next_con->mysql);
- my_free(next_con->name, MYF(0));
+ my_free(next_con->name, MYF(MY_ALLOW_ZERO_PTR));
}
}
@@ -734,6 +831,7 @@ struct option long_options[] =
{"silent", no_argument, 0, 'q'},
{"quiet", no_argument, 0, 'q'},
{"record", no_argument, 0, 'r'},
+ {"result-file", required_argument, 0, 'R'},
{"help", no_argument, 0, '?'},
{"user", required_argument, 0, 'u'},
{"password", optional_argument, 0, 'p'},
@@ -752,6 +850,7 @@ void die(const char* fmt, ...)
vfprintf(stderr, fmt, args);
fprintf(stderr, "\n");
va_end(args);
+ close_cons();
exit(1);
}
@@ -803,7 +902,7 @@ int parse_args(int argc, char **argv)
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",
+ while((c = getopt_long(argc, argv, "h:p::u:P:D:S:R:?rvVq",
long_options, &option_index)) != EOF)
{
switch(c)
@@ -818,6 +917,9 @@ int parse_args(int argc, char **argv)
case 'u':
user = optarg;
break;
+ case 'R':
+ result_file = optarg;
+ break;
case 'p':
if (optarg)
{
@@ -873,7 +975,7 @@ int parse_args(int argc, char **argv)
return 0;
}
-char* safe_str_append(char* buf, char* str, int size)
+char* safe_str_append(char* buf, const char* str, int size)
{
int i,c ;
for(i = 0; (c = *str++) && i < size - 1; i++)
@@ -882,7 +984,17 @@ char* safe_str_append(char* buf, char* str, int size)
return buf;
}
-void reject_dump(char* record_file, char* buf, int size)
+void str_to_file(const char* fname, char* str, int size)
+{
+ int fd;
+ if((fd = my_open(fname, O_WRONLY|O_CREAT, MYF(MY_WME))) < 0)
+ die("Could not open %s: errno = %d", fname, errno);
+ if(my_write(fd, (byte*)str, size, MYF(MY_WME|MY_NABP)))
+ die("write failed");
+ my_close(fd, MYF(0));
+}
+
+void reject_dump(const char* record_file, char* buf, int size)
{
char reject_file[MAX_RECORD_FILE+16];
char* p;
@@ -892,11 +1004,7 @@ void reject_dump(char* record_file, char* buf, int size)
p = safe_str_append(p, record_file, sizeof(reject_file));
p = safe_str_append(p, (char*)".reject", reject_file - p +
sizeof(reject_file));
-
- 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);
+ str_to_file(reject_file, buf, size);
}
int run_query(MYSQL* mysql, struct query* q)
@@ -905,46 +1013,14 @@ int run_query(MYSQL* mysql, struct query* q)
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;
- int guess_result_size;
- if(q->record_file[0])
+ if(!result_file && 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);
- /* let the developer be lazy and generate a .reject file
- * by touching the the result file and running the test
- * in that case, we need a buffer large enough to hold the
- * entire rejected result
- */
- guess_result_size = (info.st_size ? info.st_size :
- LAZY_GUESS_BUF_SIZE) + PAD_SIZE;
- /* if we guess wrong, the result will be truncated */
- /* if the master result file is 0 length, the developer */
- /* wants to generate reject file, edit it, and then move into
- * the master result location - in this case we should just
- * allocate a buffer that is large enough for the kind of result
- * that a human would want to examine - hope 8 K is enough
- * if this is a real test, the result should be exactly the length
- * of the master file if it is correct. If it is wrong and is
- * longer, we should be able to tell what is wrong by looking
- * at the first "correct" number of bytes
- */
- if(!(p_res_buf = res_buf =
- (char*)malloc(guess_result_size)))
- die("malloc() failed trying to allocate %d bytes",
- guess_result_size);
- res_buf_end = res_buf + guess_result_size;;
- }
+ ds_res.len = 0;
}
@@ -980,10 +1056,8 @@ int run_query(MYSQL* mysql, struct query* q)
goto end;
}
- if(!q->has_result_set)
- goto end;
- if(!(res = mysql_store_result(mysql)))
+ if(!(res = mysql_store_result(mysql)) && mysql_field_count(mysql))
{
if(q->abort_on_error)
die("failed in mysql_store_result for query '%s'", q->q);
@@ -994,28 +1068,19 @@ int run_query(MYSQL* mysql, struct query* q)
goto end;
}
}
-
- if(!frecord)
- goto end;
+
+ if(!res) 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';
- }
+ dyn_string_append(&ds_res, fields[i].name, 0);
+ dyn_string_append(&ds_res, "\t", 1);
}
- if(record)
- fputc('\n', frecord);
- else if(res_buf_end > p_res_buf)
- *p_res_buf++ = '\n';
+ dyn_string_append(&ds_res, "\n", 1);
+
while((row = mysql_fetch_row(res)))
{
@@ -1030,59 +1095,28 @@ int run_query(MYSQL* mysql, struct query* q)
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';
- }
-
- }
+
+ dyn_string_append(&ds_res, val, len);
+ dyn_string_append(&ds_res, "\t", 1);
}
-
- if(record)
- fputc('\n', frecord);
- else if(res_buf_end > p_res_buf)
- *p_res_buf++ = '\n';
-
+
+ dyn_string_append(&ds_res, "\n", 1);
}
- if(!record && frecord)
+ if(record)
{
- 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;
- }
- }
+ if(!q->record_file[0] && !result_file)
+ die("Missing result file");
+ if(!result_file)
+ str_to_file(q->record_file, ds_res.str, ds_res.len);
+ }
+ else if(!result_file && q->record_file[0])
+ {
+ error = check_result(&ds_res, q->record_file);
}
-
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;
}
@@ -1170,7 +1204,7 @@ int main(int argc, char** argv)
memset(block_stack, 0, sizeof(block_stack));
block_stack_end = block_stack + BLOCK_STACK_DEPTH;
cur_block = block_stack;
-
+ dyn_string_init(&ds_res);
parse_args(argc, argv);
if(!*cur_file)
*cur_file = stdin;
@@ -1182,13 +1216,14 @@ int main(int argc, char** argv)
mysql_options(&cur_con->mysql, MYSQL_READ_DEFAULT_GROUP, "mysql");
+ cur_con->name = my_strdup("default", MYF(MY_WME));
+ if(!cur_con->name)
+ die("Out of memory");
+
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");
for(;!read_query(&q);)
{
@@ -1229,6 +1264,12 @@ int main(int argc, char** argv)
}
close_cons();
+
+ if(result_file)
+ if(!record)
+ error |= check_result(&ds_res, result_file);
+ else
+ str_to_file(result_file, ds_res.str, ds_res.len);
if (!silent) {
if(error)