1 综述
MTR框架分为两部分:perl脚本(mysql-test-run.pl)和c++二进制(mysqltest)。perl脚本负责控制流程,包括启停、识别执行哪些用例、创建文件夹、收集结果等等,mysqltest负责执行测试用例,包括读文件,解析特定语法,执行用例。用例的特殊语法(比如,--source,--replace_column等)都在command_names和enum_commands两个枚举结构体中。
MTR框架时序图如下所示:
2 Perl脚本控制框架
如上图所示,mysql-test-run.pl框架运行流程如下:
1、初始化(Initialization)。确定用例执行范围(collect_test_cases),包括运行哪些suite,skip哪些用例,在本阶段根据disabled.def文件--skipXXX命令(比如skip-rpl)等确定执行用例。将所有用例组织到一个大的内存结构中,包括用例启动参数,用例
同时,初始化数据库(initialize_servers()->mysql_install_db()),后面运行用例启动数据库时,不需要每次初始化,只需从这里的目录中拷贝启动
2、运行用例(run test)。主线程根据参数--parallel,默认是1)启动一个或者多个用例执行线程(run_worker()),各线程有自己独立的client port,data dir等。启动的run_worker与主线程之间是server-client模式,主线程是server,run_worker()是client。主线程与run_worker是一问一答模式,主线程向run_worker发送运行用例的文件路径、配置文件参数等各种参数信息,run_worker向主线程返回运行结果,直到所有在collection中的用例都运行完毕,主线程close各run_worker,进行收尾工作
主线程先读取各run_worker返回值,对上一个用例进行收尾工作。之后,读取collection中的用例,通过本地socket发送到run_worker线程,run_worker线程接收到主线程命令,运行进去本次用例执行函数(run_testcase()),run_worker()的run_testcase()主要负责3件事:启动mysqld、启动并监控mysqltest,处理执行结果
启动mysqld:run_testcase根据参数启动一个或者多个mysqld(start_servers()),在start_servers大多数情况下会拷贝主线程初始化后的目录到run_worker的目录,作为新实例的启动目录,用shell命令启动数据库。
启动并监控mysqltest:用例在mysqltest中执行,run_worker线程会监控mysqltest的运行状态,监测其是否运行超时或者运行结束。
处理执行结果:mysqltest执行结束会留下执行日志,框架根据执行日志判断执行是否通过,如果没通过是否需要重试等
3 C++执行框架
执行框架都集中在mysqltest.cc中,mysqltest读取用例文件(*.test),根据预定义的命令(比如--source,--replace_column, shutdown_server等)执行相应的操作。mysql根据run_worker传入的运行参数(args)获得用例文件路径等信息,然后读取文件逐行执行语句,语句分为两种,一种是可以直接执行的SQL语句,一种是控制语句,控制语句用来控制mysqlclient的特殊行为,比如shutdown mysqld等,这些命令预定义在command_names中