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的工作原理在测试领域很普遍,对于质量保证的同学,掌握它的实现非常有价值,可以顺利的移植到其他系统的测试。

开头便能看到以下的注释:

 
  
  1. /* 
  2.   mysqltest 
  3.  
  4.   Tool used for executing a .test file 
  5.  
  6.   See the "MySQL Test framework manual" for more information 
  7.   http://dev.mysql.com/doc/mysqltest/en/index.html 
  8.  
  9.   Please keep the test framework tools identical in all versions! 
  10. */ 
  11.  
  12. #define MTEST_VERSION "3.3" 

mysqltest解释的是以test为后缀名的文本文件,具体的用法可以参考mysql官方的介绍。

一. 主要数据结构

1. 错误信息

--error指定的错误码保存在一个元素类型为st_match_err的数组里面,每一个元素都记录了error number或者sqlstate字符串。当有元素的matcho_err_type值为ERR_EMPTY,表示结束。sql语句的执行结果会与它比较。
 
 
 
   
  1. enum match_err_type 
  2.   ERR_EMPTY= 0, 
  3.   ERR_ERRNO, 
  4.   ERR_SQ 
  5.  
  6. struct st_match_err 
  7.   enum match_err_type type; 
  8.   union 
  9.   { 
  10.     uint errnum; 
  11.     char sqlstate[SQLSTATE_LENGTH+1];  /* \0 terminated string */ 
  12.   } code; 
  13. }; 
  14. struct st_expected_errors 
  15.   struct st_match_err err[10]; 
  16.   uint count; 
  17. }; 
  18. static struct st_expected_errors saved_expected_errors; 

sql语句执行失败后会有错误码,错误码是个非负整数(uint errnum),会对应一种错误类型,可以查看mysqld_error.h, 在该版本中最小值为1000,最大值为1727:
 
   
  1. #define ER_ERROR_FIRST 1000 
  2. #define ER_HASHCHK 1000 
  3. #define ER_NISAMCHK 1001 
  4. #define ER_NO 1002 
  5. ... 
  6. #define ER_UNSUPPORTED_ENGINE 1726 
  7. #define ER_BINLOG_UNSAFE_AUTOINC_NOT_FIRST 1727 
  8. #define ER_ERROR_LAST 1727 

从数据结构看出,错误码errnum也可以用sqlstate字符串替换,编写预期错误的时候二者选其一即可,用type区分。type有3个值:  ERR_EMPTY= 0, ERR_ERRNO, ERR_SQLSTATE,分别对应未指定错误码,error number,sqlstate。 sqlstate是sql标准规定的状态码,5个字节,表示不同的错误类型,所有的数据库系统都要遵循这个标准,error number与sqlstate的对应关系由数据库决定,mysql在sql_state.h 中有定义,关于sqlstate详细可查看http://developer.mimer.com/documentation/html_92/Mimer_SQL_Mobile_DocSet/App_Return_Codes2.html。编写CASE的时候mysqltest为了区分这两种类型,sqlstate前面需要加上S作为开头。

2  连接管理

EMBEDDED_LIBRARY暂时不关注。

向mysqld server发送query需要先建立连接,st_connection封装了MYSQL(libmysql)数据结构。
 
 
 
   
  1. struct st_connection 
  2.   MYSQL mysql; 
  3.   /* Used when creating views and sp, to avoid implicit commit */ 
  4.   MYSQL* util_mysql; 
  5.   char *name; 
  6.   size_t name_len; 
  7.   MYSQL_STMT* stmt; 
  8.   /* Set after send to disallow other queries before reap */ 
  9.   my_bool pending; 
  10.  
  11. #ifdef EMBEDDED_LIBRARY  
  12.   pthread_t tid; 
  13.   const char *cur_query; 
  14.   int cur_query_len; 
  15.   int command, result; 
  16.   pthread_mutex_t query_mutex; 
  17.   pthread_cond_t query_cond; 
  18.   pthread_mutex_t result_mutex; 
  19.   pthread_cond_t result_cond; 
  20.   int query_done; 
  21.   my_bool has_thread; 
  22. #endif /*EMBEDDED_LIBRARY*/ 
  23. }; 
  24.  
  25. struct st_connection *connections= NULL; 
  26. struct st_connection* cur_con= NULL, *next_con, *connections_end; 

3.  mysqltest command

enum_command与commad_name数组必须一一对应起来,新的命令也必须加到QUNKNOWN前面。
 
 
   
  1. enum enum_commands { 
  2.   Q_CONNECTION=1,     Q_QUERY, 
  3.   Q_CONNECT,         Q_SLEEP, Q_REAL_SLEEP, 
  4.   Q_INC,              Q_DEC, 
  5.   Q_SOURCE,         Q_DISCONNECT, 
  6.   Q_LET,              Q_ECHO, 
  7.   Q_WHILE,         Q_END_BLOCK, 
  8.   Q_SYSTEM,         Q_RESULT, 
  9.   Q_REQUIRE,         Q_SAVE_MASTER_POS, 
  10.   Q_SYNC_WITH_MASTER, 
  11.   Q_SYNC_SLAVE_WITH_MASTER, 
  12.   Q_ERROR, 
  13.   Q_SEND,              Q_REAP, 
  14.   Q_DIRTY_CLOSE,         Q_REPLACE, Q_REPLACE_COLUMN, 
  15.   Q_PING,              Q_EVAL, 
  16.   Q_EVAL_RESULT, 
  17.   Q_ENABLE_QUERY_LOG, Q_DISABLE_QUERY_LOG, 
  18.   Q_ENABLE_RESULT_LOG, Q_DISABLE_RESULT_LOG, 
  19.   Q_ENABLE_CONNECT_LOG, Q_DISABLE_CONNECT_LOG, 
  20.   Q_WAIT_FOR_SLAVE_TO_STOP, 
  21.   Q_ENABLE_WARNINGS, Q_DISABLE_WARNINGS, 
  22.   Q_ENABLE_INFO, Q_DISABLE_INFO, 
  23.   Q_ENABLE_METADATA, Q_DISABLE_METADATA, 
  24.   Q_EXEC, Q_DELIMITER, 
  25.   Q_DISABLE_ABORT_ON_ERROR, Q_ENABLE_ABORT_ON_ERROR, 
  26.   Q_DISPLAY_VERTICAL_RESULTS, Q_DISPLAY_HORIZONTAL_RESULTS, 
  27.   Q_QUERY_VERTICAL, Q_QUERY_HORIZONTAL, Q_SORTED_RESULT, 
  28.   Q_LOWERCASE, 
  29.   Q_START_TIMER, Q_END_TIMER, 
  30.   Q_CHARACTER_SET, Q_DISABLE_PS_PROTOCOL, Q_ENABLE_PS_PROTOCOL, 
  31.   Q_DISABLE_RECONNECT, Q_ENABLE_RECONNECT, 
  32.   Q_IF, 
  33.   Q_DISABLE_PARSING, Q_ENABLE_PARSING, 
  34.   Q_REPLACE_REGEX, Q_REMOVE_FILE, Q_FILE_EXIST, 
  35.   Q_WRITE_FILE, Q_COPY_FILE, Q_PERL, Q_DIE, Q_EXIT, Q_SKIP, 
  36.   Q_CHMOD_FILE, Q_APPEND_FILE, Q_CAT_FILE, Q_DIFF_FILES, 
  37.   Q_SEND_QUIT, Q_CHANGE_USER, Q_MKDIR, Q_RMDIR, 
  38.   Q_LIST_FILES, Q_LIST_FILES_WRITE_FILE, Q_LIST_FILES_APPEND_FILE, 
  39.   Q_SEND_SHUTDOWN, Q_SHUTDOWN_SERVER, 
  40.   Q_RESULT_FORMAT_VERSION, 
  41.   Q_MOVE_FILE, Q_REMOVE_FILES_WILDCARD, Q_SEND_EVAL, 
  42.   Q_UNKNOWN,                      /* Unknown command.   */ 
  43.   Q_COMMENT,                      /* Comments, ignored. */ 
  44.   Q_COMMENT_WITH_COMMAND, 
  45.   Q_EMPTY_LINE 
  46. }; 
  47.  
  48.  
  49. const char *command_names[]= 
  50.   "connection"
  51.   "query"
  52.   "connect"
  53.   "sleep"
  54.   "real_sleep"
  55.   "inc"
  56.   "dec"
  57.   "source"
  58.   "disconnect"
  59.   "let"
  60.   "echo"
  61.   "while"
  62.   "end"
  63.   "system"
  64.   "result"
  65.   "require"
  66.   "save_master_pos"
  67.   "sync_with_master"
  68.   "sync_slave_with_master"
  69.   "error"
  70.   "send"
  71.   "reap"
  72.   "dirty_close"
  73.   "replace_result"
  74.   "replace_column"
  75.   "ping"
  76.   "eval"
  77.   "eval_result"
  78.   /* Enable/disable that the _query_ is logged to result file */ 
  79.   "enable_query_log"
  80.   "disable_query_log"
  81.   /* Enable/disable that the _result_ from a query is logged to result file */ 
  82.   "enable_result_log"
  83.   "disable_result_log"
  84.   "enable_connect_log"
  85.   "disable_connect_log"
  86.   "wait_for_slave_to_stop"
  87.   "enable_warnings"
  88.   "disable_warnings"
  89.   "enable_info"
  90.   "disable_info"
  91.   "enable_metadata"
  92.   "disable_metadata"
  93.   "exec"
  94.   "delimiter"
  95.   "disable_abort_on_error"
  96.   "enable_abort_on_error"
  97.   "vertical_results"
  98.   "horizontal_results"
  99.   "query_vertical"
  100.   "query_horizontal"
  101.   "sorted_result"
  102.   "lowercase_result"
  103.   "start_timer"
  104.   "end_timer"
  105.   "character_set"
  106.   "disable_ps_protocol"
  107.   "enable_ps_protocol"
  108.   "disable_reconnect"
  109.   "enable_reconnect"
  110.   "if"
  111.   "disable_parsing"
  112.   "enable_parsing"
  113.   "replace_regex"
  114.   "remove_file"
  115.   "file_exists"
  116.   "write_file"
  117.   "copy_file"
  118.   "perl"
  119.   "die"
  120.                 
  121.   /* Don't execute any more commands, compare result */ 
  122.   "exit"
  123.   "skip"
  124.   "chmod"
  125.   "append_file"
  126.   "cat_file"
  127.   "diff_files"
  128.   "send_quit"
  129.   "change_user"
  130.   "mkdir"
  131.   "rmdir"
  132.   "list_files"
  133.   "list_files_write_file"
  134.   "list_files_append_file"
  135.   "send_shutdown"
  136.   "shutdown_server"
  137.   "result_format"
  138.   "move_file"
  139.   "remove_files_wildcard"
  140.   "send_eval"
  141.  
  142.   0 
  143. }; 

 

注释也作为一种特殊的command保存在这个地方。
 
  
  1. struct st_command 
  2.   char *query, *query_buf,*first_argument,*last_argument,*end; 
  3.   DYNAMIC_STRING content; 
  4.   int first_word_len, query_len; 
  5.   my_bool abort_on_error, used_replace; 
  6.   struct st_expected_errors expected_errors; 
  7.   char require_file[FN_REFLEN]; 
  8.   enum enum_commands type; 
  9. }; 
  10. struct st_command *curr_command= 0; 

对test文件中的command的描述全部保存在st_command结构体。

 

to do

二. 主要函数 

to do