mysqltest的最新版本是V3.3。本文分析的代码来自mysql-5.5.27,
下载地址http://www.mysql.com/downloads/mirror.php?id=408971(记得跳过登录选择“No thanks,just start my download!”)
mysqltest是mysql自带的测试引擎,代码有10000多行,源码放在client目录(使用libmysql)下,它实现了一种小语言,用来描述测试过程,并将测试结果与预期对比。小语言按照语法大致分为三类:mysql command,sql,comment。sql和comment很容易理解,前者是mysql支持的sql,后者是注释,一般用来描述测试过程。而mysql command虽然没有高级语言(python,c)等强大,但也实现了测试控制最基本的语法,比如变量赋值、流程控制(if/while)、打印等等,以及mysql测试特有的一些指令(比如disable_query_log)。mysqltest的工作原理在测试领域很普遍,对于质量保证的同学,掌握它的实现非常有价值,可以顺利的移植到其他系统的测试。
开头便能看到以下的注释:
- /*
- mysqltest
- Tool used for executing a .test file
- See the "MySQL Test framework manual" for more information
- http://dev.mysql.com/doc/mysqltest/en/index.html
- Please keep the test framework tools identical in all versions!
- */
- #define MTEST_VERSION "3.3"
mysqltest解释的是以test为后缀名的文本文件,具体的用法可以参考mysql官方的介绍。
一. 主要数据结构
- enum match_err_type
- {
- ERR_EMPTY= 0,
- ERR_ERRNO,
- ERR_SQ
- struct st_match_err
- {
- enum match_err_type type;
- union
- {
- uint errnum;
- char sqlstate[SQLSTATE_LENGTH+1]; /* \0 terminated string */
- } code;
- };
- struct st_expected_errors
- {
- struct st_match_err err[10];
- uint count;
- };
- static struct st_expected_errors saved_expected_errors;
- #define ER_ERROR_FIRST 1000
- #define ER_HASHCHK 1000
- #define ER_NISAMCHK 1001
- #define ER_NO 1002
- ...
- #define ER_UNSUPPORTED_ENGINE 1726
- #define ER_BINLOG_UNSAFE_AUTOINC_NOT_FIRST 1727
- #define ER_ERROR_LAST 1727
- struct st_connection
- {
- MYSQL mysql;
- /* Used when creating views and sp, to avoid implicit commit */
- MYSQL* util_mysql;
- char *name;
- size_t name_len;
- MYSQL_STMT* stmt;
- /* Set after send to disallow other queries before reap */
- my_bool pending;
- #ifdef EMBEDDED_LIBRARY
- pthread_t tid;
- const char *cur_query;
- int cur_query_len;
- int command, result;
- pthread_mutex_t query_mutex;
- pthread_cond_t query_cond;
- pthread_mutex_t result_mutex;
- pthread_cond_t result_cond;
- int query_done;
- my_bool has_thread;
- #endif /*EMBEDDED_LIBRARY*/
- };
- struct st_connection *connections= NULL;
- struct st_connection* cur_con= NULL, *next_con, *connections_end;
- enum enum_commands {
- Q_CONNECTION=1, Q_QUERY,
- Q_CONNECT, Q_SLEEP, Q_REAL_SLEEP,
- Q_INC, Q_DEC,
- Q_SOURCE, Q_DISCONNECT,
- Q_LET, Q_ECHO,
- Q_WHILE, Q_END_BLOCK,
- Q_SYSTEM, Q_RESULT,
- Q_REQUIRE, Q_SAVE_MASTER_POS,
- Q_SYNC_WITH_MASTER,
- Q_SYNC_SLAVE_WITH_MASTER,
- Q_ERROR,
- Q_SEND, Q_REAP,
- Q_DIRTY_CLOSE, Q_REPLACE, Q_REPLACE_COLUMN,
- Q_PING, Q_EVAL,
- Q_EVAL_RESULT,
- Q_ENABLE_QUERY_LOG, Q_DISABLE_QUERY_LOG,
- Q_ENABLE_RESULT_LOG, Q_DISABLE_RESULT_LOG,
- Q_ENABLE_CONNECT_LOG, Q_DISABLE_CONNECT_LOG,
- Q_WAIT_FOR_SLAVE_TO_STOP,
- Q_ENABLE_WARNINGS, Q_DISABLE_WARNINGS,
- Q_ENABLE_INFO, Q_DISABLE_INFO,
- Q_ENABLE_METADATA, Q_DISABLE_METADATA,
- Q_EXEC, Q_DELIMITER,
- Q_DISABLE_ABORT_ON_ERROR, Q_ENABLE_ABORT_ON_ERROR,
- Q_DISPLAY_VERTICAL_RESULTS, Q_DISPLAY_HORIZONTAL_RESULTS,
- Q_QUERY_VERTICAL, Q_QUERY_HORIZONTAL, Q_SORTED_RESULT,
- Q_LOWERCASE,
- Q_START_TIMER, Q_END_TIMER,
- Q_CHARACTER_SET, Q_DISABLE_PS_PROTOCOL, Q_ENABLE_PS_PROTOCOL,
- Q_DISABLE_RECONNECT, Q_ENABLE_RECONNECT,
- Q_IF,
- Q_DISABLE_PARSING, Q_ENABLE_PARSING,
- Q_REPLACE_REGEX, Q_REMOVE_FILE, Q_FILE_EXIST,
- Q_WRITE_FILE, Q_COPY_FILE, Q_PERL, Q_DIE, Q_EXIT, Q_SKIP,
- Q_CHMOD_FILE, Q_APPEND_FILE, Q_CAT_FILE, Q_DIFF_FILES,
- Q_SEND_QUIT, Q_CHANGE_USER, Q_MKDIR, Q_RMDIR,
- Q_LIST_FILES, Q_LIST_FILES_WRITE_FILE, Q_LIST_FILES_APPEND_FILE,
- Q_SEND_SHUTDOWN, Q_SHUTDOWN_SERVER,
- Q_RESULT_FORMAT_VERSION,
- Q_MOVE_FILE, Q_REMOVE_FILES_WILDCARD, Q_SEND_EVAL,
- Q_UNKNOWN, /* Unknown command. */
- Q_COMMENT, /* Comments, ignored. */
- Q_COMMENT_WITH_COMMAND,
- Q_EMPTY_LINE
- };
- const char *command_names[]=
- {
- "connection",
- "query",
- "connect",
- "sleep",
- "real_sleep",
- "inc",
- "dec",
- "source",
- "disconnect",
- "let",
- "echo",
- "while",
- "end",
- "system",
- "result",
- "require",
- "save_master_pos",
- "sync_with_master",
- "sync_slave_with_master",
- "error",
- "send",
- "reap",
- "dirty_close",
- "replace_result",
- "replace_column",
- "ping",
- "eval",
- "eval_result",
- /* Enable/disable that the _query_ is logged to result file */
- "enable_query_log",
- "disable_query_log",
- /* Enable/disable that the _result_ from a query is logged to result file */
- "enable_result_log",
- "disable_result_log",
- "enable_connect_log",
- "disable_connect_log",
- "wait_for_slave_to_stop",
- "enable_warnings",
- "disable_warnings",
- "enable_info",
- "disable_info",
- "enable_metadata",
- "disable_metadata",
- "exec",
- "delimiter",
- "disable_abort_on_error",
- "enable_abort_on_error",
- "vertical_results",
- "horizontal_results",
- "query_vertical",
- "query_horizontal",
- "sorted_result",
- "lowercase_result",
- "start_timer",
- "end_timer",
- "character_set",
- "disable_ps_protocol",
- "enable_ps_protocol",
- "disable_reconnect",
- "enable_reconnect",
- "if",
- "disable_parsing",
- "enable_parsing",
- "replace_regex",
- "remove_file",
- "file_exists",
- "write_file",
- "copy_file",
- "perl",
- "die",
- /* Don't execute any more commands, compare result */
- "exit",
- "skip",
- "chmod",
- "append_file",
- "cat_file",
- "diff_files",
- "send_quit",
- "change_user",
- "mkdir",
- "rmdir",
- "list_files",
- "list_files_write_file",
- "list_files_append_file",
- "send_shutdown",
- "shutdown_server",
- "result_format",
- "move_file",
- "remove_files_wildcard",
- "send_eval",
- 0
- };
- struct st_command
- {
- char *query, *query_buf,*first_argument,*last_argument,*end;
- DYNAMIC_STRING content;
- int first_word_len, query_len;
- my_bool abort_on_error, used_replace;
- struct st_expected_errors expected_errors;
- char require_file[FN_REFLEN];
- enum enum_commands type;
- };
- struct st_command *curr_command= 0;
to do
二. 主要函数
to do