一种基于函数替换的故障注入测试方法及装置转让专利

申请号 : CN202311285981.4

文献号 : CN117009252B

文献日 :

基本信息:

PDF:

法律信息:

相似专利:

发明人 : 刘念罗实王永恒葛晓东周宇陈昱宇张宝龙

申请人 : 之江实验室

摘要 :

本说明书公开了一种基于函数替换的故障注入测试方法及装置,可以获取待测试代码,并基于所述待测试代码,确定函数调用链,根据该函数调用链,确定待替换函数,而后,对该待替换函数的函数代码进行修改,以将需要注入的故障代码添加到该待替换函数中,得到修改后函数,并生成修改后函数对应的动态链接库,进而,将动态链接库注入到待替换函数所在的进程,以将进程中的待替换函数替换为修改后函数,最后,响应于预设的触发规则,触发修改后函数以完成故障触发,根据故障触发后得到的系统相关信息,完成故障注入测试,从而达到了灵活、安全的进行故障注入。(56)对比文件史毅龙;薛长斌.基于“龙芯”的VxWorks系统函数在轨更新研究.电子设计工程.2015,(第21期),全文.

权利要求 :

1.一种基于函数替换的故障注入测试方法,其特征在于,包括:获取待测试代码,并基于所述待测试代码,确定函数调用链;

根据所述函数调用链,确定待替换函数;

对所述待替换函数的函数代码进行修改,以将需要注入的故障代码添加到所述待替换函数中,得到修改后函数,并生成所述修改后函数对应的动态链接库;

将所述动态链接库注入到所述待替换函数所在的进程,以将所述进程中的待替换函数替换为所述修改后函数;

响应于预设的触发规则,触发所述修改后函数以完成故障触发,根据故障触发后得到的系统相关信息,完成故障注入测试,所述系统相关信息至少包括系统日志以及响应信息。

2.如权利要求1所述的方法,其特征在于,基于所述待测试代码,确定函数调用链,具体包括:通过Callgraph工具生成所述待测试代码的静态函数调用链,作为得到的函数调用链。

3.如权利要求1所述的方法,其特征在于,根据所述函数调用链,确定待替换函数,具体包括:确定所述函数调用链中的各函数;

从所述各函数确定出满足预设条件的函数,作为候选函数,其中,所述预设条件包括:函数属于用户态函数、函数不属于多线程函数以及函数不属于静态函数和静态函数中包含的函数中的至少一种;

从所述候选函数中,确定出待替换函数。

4.如权利要求1所述的方法,其特征在于,将所述动态链接库注入到所述待替换函数所在的进程,具体包括:确定所述待替换函数所在的进程,作为目标进程;

加载所述动态链接库对应的进程,并为所述动态链接库对应的进程分配内存空间;

获取所述目标进程中待替换函数对应的地址,以及所述动态链接库对应的进程中所述修改后函数对应的地址;

将寄存器中所述待替换函数对应的地址替换为所述动态链接库对应的进程中所述修改后函数对应的地址;

保存所述寄存器的数据和状态,以完成注入。

5.如权利要求1所述的方法,其特征在于,所述触发规则包括:在所述待测试代码对应的业务系统中进行按钮点击、在命令行中输入预设指令以及在所述业务系统中进行消息发送中的至少一种。

6.如权利要求1所述的方法,其特征在于,根据故障触发后得到的系统相关信息,完成故障注入测试,具体包括:获取系统日志中的错误日志,包括内存泄漏日志、磁盘满日志;

获取所述待测试代码对应的业务系统对故障检测的告警信息;

获取所述业务系统在不同故障触发后的响应信息,所述响应信息对应的响应包括服务超时、卡顿现象,以及系统重启;

通过诊断工具进行现象分析,得到分析结果;

根据所述错误日志、所述告警信息、所述响应信息以及所述分析结果,完成故障注入测试。

7.如权利要求4所述的方法,其特征在于,所述方法还包括:将寄存器中所述待替换函数对应的地址还原,并将所述动态链接库删除,以恢复所述待测试代码对应的业务系统。

8.一种基于函数替换的故障注入测试装置,其特征在于,包括:获取模块,用于获取待测试代码,并基于所述待测试代码,确定函数调用链;

确定模块,用于根据所述函数调用链,确定待替换函数;

修改模块,用于对所述待替换函数的函数代码进行修改,以将需要注入的故障代码添加到所述待替换函数中,得到修改后函数,并生成所述修改后函数对应的动态链接库;

注入模块,用于将所述动态链接库注入到所述待替换函数所在的进程,以将所述进程中的待替换函数替换为所述修改后函数;

触发模块,用于响应于预设的触发规则,触发所述修改后函数以完成故障触发,根据故障触发后得到的系统相关信息,完成故障注入测试,所述系统相关信息至少包括系统日志以及响应信息。

9.一种计算机可读存储介质,其特征在于,所述存储介质存储有计算机程序,所述计算机程序被处理器执行时实现上述权利要求1 7任一项所述的方法。

~

10.一种电子设备,包括存储器、处理器及存储在存储器上并可在处理器上运行的计算机程序,其特征在于,所述处理器执行所述程序时实现上述权利要求1 7任一项所述的方~法。

说明书 :

一种基于函数替换的故障注入测试方法及装置

技术领域

[0001] 本说明书涉及软件测试技术领域,尤其涉及一种基于函数替换的故障注入测试方法及装置。

背景技术

[0002] 目前软件系统的故障注入测试手段主要有以下几种:
[0003] 1、在目标服务器部署故障注入系统,该系统独立于业务系统,通过调用操作系统命令来注入系统级异常,包括CPU高/内存泄漏/网络延迟/磁盘写满等。这种故障注入方法存在灵活性不足的问题:系统级故障太宽泛,不能模拟真实的应用系统异常,比如特定进程/组件内存泄漏、资源未释放(连结数过多、文件句柄占用)等。
[0004] 2、应用系统部署在服务器之前在业务源代码中添加故障用例库,并在业务运行时通过命令/消息来触发故障生效。这种故障注入方法存在的不足为:需要侵入业务系统,改造业务系统代码,埋下了很多未触发的异常,不够安全可靠。另外,该方法不够灵活,如果要修改故障用例库,需要重新部署业务系统。
[0005] 因此,如何提高故障注入的灵活性以及安全性,则是亟待解决的问题。

发明内容

[0006] 本说明书提供一种基于函数替换的故障注入测试方法及装置,以部分的解决现有技术存在的上述问题。
[0007] 本说明书采用下述技术方案:
[0008] 本说明书提供了一种导基于函数替换的故障注入测试方法,包括:
[0009] 获取待测试代码,并基于所述待测试代码,确定函数调用链;
[0010] 根据所述函数调用链,确定待替换函数;
[0011] 对所述待替换函数的函数代码进行修改,以将需要注入的故障代码添加到所述待替换函数中,得到修改后函数,并生成所述修改后函数对应的动态链接库;
[0012] 将所述动态链接库注入到所述待替换函数所在的进程,以将所述进程中的待替换函数替换为所述修改后函数;
[0013] 响应于预设的触发规则,触发所述修改后函数以完成故障触发,根据故障触发后得到的系统相关信息,完成故障注入测试,所述系统相关信息至少包括系统日志以及响应信息。
[0014] 可选地,基于所述待测试代码,确定函数调用链,具体包括:
[0015] 通过Callgraph工具生成所述待测试代码的静态函数调用链,作为得到的函数调用链。
[0016] 可选地,根据所述函数调用链,确定待替换函数,具体包括:
[0017] 确定所述函数调用链中的各函数;
[0018] 从所述各函数确定出满足预设条件的函数,作为候选函数,其中,所述预设条件包括:函数属于用户态函数、函数不属于多线程函数以及函数不属于静态函数和静态函数中包含的函数中的至少一种;
[0019] 从所述候选函数中,确定出待替换函数。
[0020] 可选地,将所述动态链接库注入到所述待替换函数所在的进程,具体包括:
[0021] 确定所述待替换函数所在的进程,作为目标进程;
[0022] 加载所述动态链接库对应的进程,并为所述动态链接库对应的进程分配内存空间;
[0023] 获取所述目标进程中待替换函数对应的地址,以及所述动态链接库对应的进程中所述修改后函数对应的地址;
[0024] 将寄存器中所述待替换函数对应的地址替换为所述动态链接库对应的进程中所述修改后函数对应的地址;
[0025] 保存所述寄存器的数据和状态,以完成注入。
[0026] 可选地,所述触发规则包括:在所述待测试代码对应的业务系统中进行按钮点击、在命令行中输入预设指令以及在所述业务系统中进行消息发送中的至少一种。
[0027] 可选地,根据故障触发后得到的系统相关信息,完成故障注入测试,具体包括:
[0028] 获取系统日志中的错误日志,包括内存泄漏日志、磁盘满日志;
[0029] 获取所述待测试代码对应的业务系统对故障检测的告警信息;
[0030] 获取所述业务系统在不同故障触发后的响应信息,所述响应信息对应的响应包括服务超时、卡顿现象,以及系统重启;
[0031] 通过诊断工具进行现象分析,得到分析结果;
[0032] 根据所述错误日志、所述告警信息、所述响应信息以及所述分析结果,完成故障注入测试。
[0033] 可选地,所述方法还包括:
[0034] 将寄存器中所述待替换函数对应的地址还原,并将所述动态链接库删除,以恢复所述待测试代码对应的业务系统。
[0035] 本说明书提供了一种基于函数替换的故障注入测试装置,包括:
[0036] 获取模块,用于获取待测试代码,并基于所述待测试代码,确定函数调用链;
[0037] 确定模块,用于根据所述函数调用链,确定待替换函数;
[0038] 修改模块,用于对所述待替换函数的函数代码进行修改,以将需要注入的故障代码添加到所述待替换函数中,得到修改后函数,并生成所述修改后函数对应的动态链接库;
[0039] 注入模块,用于将所述动态链接库注入到所述待替换函数所在的进程,以将所述进程中的待替换函数替换为所述修改后函数;
[0040] 触发模块,用于响应于预设的触发规则,触发所述修改后函数以完成故障触发,根据故障触发后得到的系统相关信息,完成故障注入测试,所述系统相关信息至少包括系统日志以及响应信息。
[0041] 本说明书提供了一种计算机可读存储介质,所述存储介质存储有计算机程序,所述计算机程序被处理器执行时实现上述基于函数替换的故障注入测试方法。
[0042] 本说明书提供了一种电子设备,包括存储器、处理器及存储在存储器上并可在处理器上运行的计算机程序,所述处理器执行所述程序时实现上述基于函数替换的故障注入测试方法。
[0043] 本说明书采用的上述至少一个技术方案能够达到以下有益效果:
[0044] 从上述基于函数替换的故障注入测试方法中可以看出,该方法可以获取待测试代码,并基于所述待测试代码,确定函数调用链,根据该函数调用链,确定待替换函数,而后,对该待替换函数的函数代码进行修改,以将需要注入的故障代码添加到该待替换函数中,得到修改后函数,并生成修改后函数对应的动态链接库,进而,将动态链接库注入到待替换函数所在的进程,以将进程中的待替换函数替换为修改后函数,最后,响应于预设的触发规则,触发修改后函数以完成故障触发,根据故障触发后得到的系统相关信息,完成故障注入测试,系统相关信息至少包括系统日志以及响应信息。
[0045] 从上述内容中可以看出,本方法可以确定出需要注入故障代码的函数、并添加故障代码,进而通过生成动态链接库并注入相应进程的方式,直接进行故障注入,相比于现有技术1,能够灵活地按照所需要的故障进行故障注入,相比于现有技术2,不需要直接对业务系统的业务代码进行改造,从而达到了灵活、安全的进行故障注入。

附图说明

[0046] 此处所说明的附图用来提供对本说明书的进一步理解,构成本说明书的一部分,本说明书的示意性实施例及其说明用于解释本说明书,并不构成对本说明书的不当限定。在附图中:
[0047] 图1为本说明书提供的一种基于函数替换的故障注入测试方法的流程示意图;
[0048] 图2为本说明书提供的一种挑选待替换函数的流程示意图;
[0049] 图3为本说明书提供的一种函数调用链的示意图;
[0050] 图4为本说明书提供的一种注入动态链接库的流程示意图;
[0051] 图5为本说明书提供的一种基于函数替换的故障注入测试装置示意图;
[0052] 图6为本说明书提供的对应于图1的电子设备示意图。

具体实施方式

[0053] 为使本说明书的目的、技术方案和优点更加清楚,下面将结合本说明书具体实施例及相应的附图对本说明书技术方案进行清楚、完整地描述。显然,所描述的实施例仅是本说明书一部分实施例,而不是全部的实施例。基于本说明书中的实施例,本领域普通技术人员在没有做出创造性劳动前提下所获得的所有其他实施例,都属于本说明书保护的范围。
[0054] 以下结合附图,详细说明本说明书各实施例提供的技术方案。
[0055] 图1为本说明书中提供的一种基于函数替换的故障注入测试方法的流程示意图,具体包括以下步骤:
[0056] S100:获取待测试代码,并基于所述待测试代码,确定函数调用链。
[0057] S102:根据所述函数调用链,确定待替换函数。
[0058] 本说明书中的基于函数替换的故障注入测试方法可以应用在故障注入测试的场景中。
[0059] 首先,服务器可以获取待测试代码,并基于该待测试代码,确定函数调用链。
[0060] 应用程序的每个业务和功能都是由很多函数调用链组成的,函数替换时如果能将调用链中的某个函数保留原代码,并插入故障代码(能够模拟运行时出现故障的代码),那程序实际运行时没有破坏原函数的功能,又能快速地模拟出业务异常现象,并以此来检验应用程序的故障处理能力。
[0061] 图2为本说明书提供的一种挑选待替换函数的流程示意图。
[0062] 因此,可以如图2所示,确定出函数调用链,并挑选需要替换的函数,包括以下步骤:
[0063] S201:生成某个模块的函数调用链。
[0064] S202:函数筛选。
[0065] S203:业务影响分析。
[0066] 其中,待测试代码可以是开发出的一套业务系统对应的代码,此时,可以先通过静态分析的方式,确定出待测试代码的函数调用链(可以是某个需要进行故障注入测试的模块的函数调用链),具体的,可以通过Callgraph工具生成该待测试代码的静态函数调用链,作为得到的函数调用链。
[0067] 该工具可以指定某个文件或者函数列表,并指定函数调用深度来筛选结果。一个函数调用另一个函数,很多个函数组合在一起就形成了函数调用链的展示,例如函数funcA调用函数funcB,展示就是funcA‑>funcB,函数funcB调用函数funcC,展示就是funcB‑>funcC,那么函数调用链就是funcA‑>funcB‑>funcC。
[0068] Callgraph工具对某个目录生成的静态函数调用链可以如图2所示。
[0069] 图3为本说明书提供的一种函数调用链的示意图。
[0070] 根据图3展示的函数调用图可以分析出不同的函数调用链,比如这两个调用链:1、A‑>B‑>C‑>D‑>E,2、A‑>B‑>G‑>D‑>E。
[0071] 而后,可以根据确定出的函数调用链,确定出待替换函数。其中,可以确定函数调用链中的各函数,并从各函数确定出满足预设条件的函数,作为候选函数,其中,预设条件包括:函数属于用户态函数、函数不属于多线程函数以及函数不属于静态函数和静态函数中包含的函数中的至少一种,而后,可以从候选函数中,确定出待替换函数。
[0072] 也就是说,函数筛选主要考虑这三个方面:
[0073] 一、用户态与内核态函数。
[0074] 每个函数调用链的函数包括这两类:应用程序函数(用户态函数)和系统函数(库函数),应用程序函数的调用在用户态,系统函数(库函数)的调用往往在内核态,应用程序函数和系统函数是两个不同形态,这两个都可以用函数替换的方式来进行故障注入,但方法有较大差异,本发明主要考虑用户态函数对业务程序的影响,因此对系统函数比如D、E、H、L、M不考虑函数替换。
[0075] 二、多线程影响。
[0076] 函数执行需要数据和代码,数据包括函数形参、局部变量、全局变量、静态局部变量等。有的数据是保存在线程的栈空间,比如形参、局部变量,在多线程条件下每个线程的栈空间是独立的,函数调用不受影响。而有的数据是保存在进程堆内存,比如全局变量,在多线程条件下会共同访问该全局变量的堆内存首地址,会有安全问题,虽然引入互斥锁时会解决该问题,但是如果替换多线程下的函数,容易导致加锁后替换后的函数执行发生异常引起锁等待、死锁。
[0077] 函数的代码保存在公共空间,对所有线程是共享的,当替换多线程下的函数时,一部分线程执行旧函数,一部分线程执行新函数,在不是原子操作的前提下,会引起局部变量的不一致引发不可预知的逻辑问题。
[0078] 综上,从数据和代码两方面来考虑都不能选择多线程执行下的函数进行替换,多线程的函数标志是通过pthread_create系统函数创建,创建时参数指定了调用的函数名,该函数就是多线程函数。
[0079] 三、静态函数及静态函数内部的函数。
[0080] 静态函数的作用域仅局限于声明它的文件中,它的内部函数地址是不可见的,不能被其他文件引用,因此函数替换不能考虑静态函数及其内部的函数。
[0081] S104:对所述待替换函数的函数代码进行修改,以将需要注入的故障代码添加到所述待替换函数中,得到修改后函数,并生成所述修改后函数对应的动态链接库。
[0082] 确定出待替换函数后,可以对待替换函数的函数代码进行修改,以将需要注入的故障代码添加到待替换函数中,得到修改后函数,并生成该修改后函数对应的动态链接库。
[0083] 其中,确定出待替换函数后,开发人员可以人为将待替换函数的函数代码进行修改(当然,也可以通过接收需要注入的故障代码来自动得到修改后函数),并将修改后函数保存在本地,而后,服务器可以生成修改后函数对应的动态链接库。
[0084] 这里提到的将待替换函数的函数代码进行修改,得到修改后函数,并不是指直接将原有的待替换函数修改,而是指得到待替换函数的函数代码,并在待替换函数的函数代码中添加故障代码,得到修改后函数,也就是说修改后函数是除待替换函数的另一函数,而原有的待替换函数依然存在,这样也方便后续将修改后函数对应的动态链接库删除,以将待测试代码对应的业务系统还原。
[0085] (1)编写用于替换待替换函数的修改后函数
[0086] 假定待替换函数名为original_func,修改后函数为replaced_func。
[0087] original_func代码示例如下:
[0088] int original_func(int a, const char *b){
[0089] //代码省略
[0090] ...
[0091] return 0;
[0092] }
[0093] 假定注入的故障为模拟业务内存泄漏,那修改后函数代码示例如下:
[0094] int replaced_func(int a, const char *b){
[0095] //原代码保持不变
[0096] ...
[0097] //下面添加内存泄漏的代码
[0098] char *temp = (char *)malloc(300* sizeof(char));
[0099] temp = b;
[0100] return 0;
[0101] }
[0102] 修改后函数replaced_func中申请了一块300字节的内存,并将内存地址传给指针temp,然后将指针temp又指向了b,直到函数结束。这导致300字节内存地址没有指针指向它,无法找回,不能释放内存地址,造成了内存泄漏。每调用一次该函数,就会造成300字节的内存泄漏,根据实际测试需要,可以更改这个数值。
[0103] (2)制作动态链接库
[0104] 动态链接库是一个*.so文件,它包含了修改后函数(包含触发故障代码),可以通过gcc(linux c语言编译器)编译生成动态链接库libload.so文件。
[0105] 假定函数original_func的文件名为func_rep.c,编译命令如下,即可生成libload.so动态链接库:
[0106] “gcc func_rep.c ‑shared ‑fPIC ‑o libload.so”
[0107] S106:将所述动态链接库注入到所述待替换函数所在的进程,以将所述进程中的待替换函数替换为所述修改后函数。
[0108] 而后,可以将得到的修改后函数对应的动态链接库注入到待替换函数所在的进程,以将该进程中的待替换函数替换为修改后函数。
[0109] 其中,可以确定出待替换函数所在的进程,作为目标进程,而后,可以加载动态链接库(包含有修改后函数)对应的进程,并为该动态链接库对应的进程分配内存空间,而后,获取目标进程中待替换函数对应的地址,以及动态链接库对应的进程中修改后函数对应的地址,最后,可以将寄存器中待替换函数对应的地址(即,超始地址)替换为动态链接库对应的进程中修改后函数对应的地址,并保存寄存器的数据和状态,以完成注入。
[0110] 图4为本说明书提供的一种注入动态链接库的流程示意图。
[0111] 注入动态链接库的流程可以如图4所示,步骤详细过程如下:
[0112] S401:确认目标函数original_func所在的进程,通过gdb(调试工具)命令:info original_func查看进程中该函数是否存在,记录进程号pid。
[0113] S402:通过系统接口ptrace来加载libload.so(即动态链接库文件)进程,并调用系统接口mmap进行分配内存空间,这样libload.so中的函数可以通过地址来访问。
[0114] S403:通过系统接口dlsym来获取这两个函数的地址:original_func和replaced_func。
[0115] S404:在寄存器中将original_func函数超始地址替换为replaced_func函数地址,修改机器指令为jmp。
[0116] S405:寄存器数据和状态保存,结束注入过程。
[0117] 在此附上各系统接口的作用,如表1所示。
[0118] 表1
[0119]
[0120] S108:响应于预设的触发规则触发所述修改后函数以完成故障触发,根据故障触发后得到的系统相关信息,完成故障注入测试,所述系统相关信息至少包括系统日志以及响应信息。
[0121] 完成注入后,服务器可以响应于预设的触发规则,触发上述修改后函数以完成故障触发,根据故障触发后得到的系统相关信息,可以完成故障注入测试,这里提到的系统相关信息至少包括系统日志以及响应信息。
[0122] 需要说明的是,上述触发规则可以包括:在该待测试代码对应的业务系统中进行按钮点击、在命令行中输入预设指令以及在业务系统中进行消息发送等,这里提到的待测试代码对应的业务系统可以部署在上述服务器中,在修改后函数对应的触发规则在服务器中产生后,服务器触发修改后函数,即可以触发修改后函数内部的故障代码。
[0123] 其中,根据函数调用链,可以找到能够触发修改后函数的函数调用的触发规则,比如按钮点击、命令行、消息等。
[0124] 需要说明的是,若是不通过本说明书提供的方式进行函数替换,那么在代码执行时,执行到original_func函数是按照原有的函数代码进行执行,而通过本方法进行了动态链接库的注入后,在执行到original_func函数时,将跳转到replaced_func函数进行执行。
[0125] 即,函数替换后,当调用original_func函数时,该函数首地址操作符已替换,直接跳转到replaced_func函数执行,这时将触发replaced_func中的故障代码,这时可以快速地对系统注入异常。在一些需要重复注入异常的场景比如内存泄漏、资源占用等,可以触发多次相应的触发规则,如多次点击按钮来触发异常。
[0126] 故障触发后,可以根据故障触发后得到的系统相关信息,完成故障注入测试,其中,系统相关信息至少包括系统日志以及响应信息。
[0127] 具体的,可以获取系统日志中的错误日志,包括内存泄漏日志、磁盘满日志等,获取待测试代码对应的业务系统对故障检测的告警信息,获取业务系统在不同故障触发后的响应信息,这里提到的响应信息对应的响应包括服务超时、卡顿现象,以及系统重启等,还可以通过诊断工具进行现象分析,得到分析结果,从而可以根据错误日志、告警信息、响应信息以及分析结果,完成故障注入测试。
[0128] 也就是说,可以在故障触发后,可以通过业务系统的错误日志、告警信息、响应信息、诊断工具得到的分析结果等,来确定故障注入是否成功,以及确定业务系统是否对注入的故障产生了正确的反应。
[0129] 即,故障触发后根据故障类型可以针对性地观察、分析和检测,可以包括以下四点:
[0130] (1)检查错误日志。例如,上述replaced_func函数执行一次就有内存泄漏,达到一定程 度 时会 产生 内 存溢 出,这 时系 统申 请 内存 就有 异 常错 误日 志 :java.lang.OutOfMemoryError。
[0131] (2)检查业务系统对故障的反应。如果业务系统对一些故障会有检测和告警,检查这些告警信息与故障现象是否一致,这些故障包括:磁盘空间、内存空间、cpu等。
[0132] 本实施例中出现内存泄漏,会有内存空间不足的告警和CPU高的告警。
[0133] (3)检查业务响应。检查业务在不同故障触发后的响应(比如服务响应慢、重启、扩容等),与预期响应结果是否一致。本例中出现内存泄漏,影响业务功能的响应时间,出现卡顿和超时现象。
[0134] (4)系统分析、诊断、记录。有些故障触发后现象不太容易直观看到,需要通过诊断工具或诊断程序来判断故障是否注入成功,比如网络丢包、数据库表锁超时等。
[0135] 需要说明的是,本方法可以在故障注入测试完成后,方便地将待测试代码对应的业务系统恢复原状,即恢复为故障注入测试前的状态,即,可以将寄存器中所述待替换函数对应的地址还原,还原寄存器的状态数据,以及直接将动态链接库删除,以恢复所述待测试代码对应的业务系统。
[0136] 动态链接库在加载时记录了原始函数信息,再用同样的方法将寄存器中记录指令的地址恢复到原始数据,进程将不再加载动态链接库。
[0137] 需要说明的是,为了便于描述,将执行本方法的执行主体作为服务器进行描述,执行主体可以是台式电脑、服务器、大型的服务平台等,在此不进行限定。
[0138] 相比于其他故障注入测试方法,本发明实施例具有如下优点:
[0139] 基于业务系统和场景来进行故障注入,作用于业务系统的进程和组件,可以精准地模拟真实的业务场景异常,这些异常相比其他故障注入的系统级异常更真实和精准;
[0140] 相比于应用系统部署在服务器之前在业务源代码中添加故障用例库,并在业务运行时通过命令/消息来触发故障生效,本发明具有不浸入、不重启业务系统的优点,在业务系统正常运行时动态地替换函数,完成故障代码的注入,并根据需要随时触发故障,另外故障的恢复非常方便,只需要将替换函数的地址重新写回原函数的地址即可,不影响业务的运行,这种故障注入方式具有安全灵活的特点;
[0141] 相比于动态替换字节码技术,动态字段码通过JVM接口重写进程class字节码文件,实现函数的动态替换,但该技术有许多限制,不允许有成员变量和方法,不允许改变类的属性,不允许创建对象,只能调用静态方法,本发明没有这些限制,可以更改变量值,调用其他方法,灵活地编写故障代码来触发异常。
[0142] 以上为本说明书的一个或多个实施例提供基于函数替换的故障注入测试方法,基于同样的思路,本说明书还提供了基于函数替换的故障注入测试装置,如图5所示。
[0143] 图5为本说明书提供的一种基于函数替换的故障注入测试装置示意图,包括;
[0144] 获取模块501,用于获取待测试代码,并基于所述待测试代码,确定函数调用链;
[0145] 确定模块502,用于根据所述函数调用链,确定待替换函数;
[0146] 修改模块503,用于对所述待替换函数的函数代码进行修改,以将需要注入的故障代码添加到所述待替换函数中,得到修改后函数,并生成所述修改后函数对应的动态链接库;
[0147] 注入模块504,用于将所述动态链接库注入到所述待替换函数所在的进程,以将所述进程中的待替换函数替换为所述修改后函数;
[0148] 触发模块505,用于响应于预设的触发规则,触发所述修改后函数以完成故障触发,根据故障触发后得到的系统相关信息,完成故障注入测试,所述系统相关信息至少包括系统日志以及响应信息。
[0149] 可选地,所述获取模块501具体用于,通过Callgraph工具生成所述待测试代码的静态函数调用链,作为得到的函数调用链。
[0150] 可选地,所述确定模块502具体用于,确定所述函数调用链中的各函数;从所述各函数确定出满足预设条件的函数,作为候选函数,其中,所述预设条件包括:函数属于用户态函数、函数不属于多线程函数以及函数不属于静态函数和静态函数中包含的函数中的至少一种;从所述候选函数中,确定出待替换函数。
[0151] 可选地,所述注入模块504具体用于,确定所述待替换函数所在的进程,作为目标进程;加载所述动态链接库对应的进程,并为所述动态链接库对应的进程分配内存空间;获取所述目标进程中待替换函数对应的地址,以及所述动态链接库对应的进程中所述修改后函数对应的地址;将寄存器中所述待替换函数对应的地址替换为所述动态链接库对应的进程中所述修改后函数对应的地址;保存所述寄存器的数据和状态,以完成注入。
[0152] 可选地,所述触发规则包括:在所述待测试代码对应的业务系统中进行按钮点击、在命令行中输入预设指令以及在所述业务系统中进行消息发送中的至少一种。
[0153] 可选地,所述触发模块505具体用于,获取系统日志中的错误日志,包括内存泄漏日志、磁盘满日志;获取所述待测试代码对应的业务系统对故障检测的告警信息;获取所述业务系统在不同故障触发后的响应信息,所述响应信息对应的响应包括服务超时、卡顿现象,以及系统重启;通过诊断工具进行现象分析,得到分析结果;根据所述错误日志、所述告警信息、所述响应信息以及所述分析结果,完成故障注入测试。
[0154] 可选地,所述装置还包括:
[0155] 还原模块506,用于将寄存器中所述待替换函数对应的地址还原,并将所述动态链接库删除,以恢复所述待测试代码对应的业务系统。
[0156] 本说明书还提供了一种计算机可读存储介质,该存储介质存储有计算机程序,计算机程序可用于执行上述基于函数替换的故障注入测试方法。
[0157] 本说明书还提供了图6所示的电子设备的示意结构图。如图6所述,在硬件层面,该电子设备包括处理器、内部总线、网络接口、内存以及非易失性存储器,当然还可能包括其他业务所需要的硬件。处理器从非易失性存储器中读取对应的计算机程序到内存中然后运行,以实现基于函数替换的故障注入测试方法。
[0158] 当然,除了软件实现方式之外,本说明书并不排除其他实现方式,比如逻辑器件抑或软硬件结合的方式等等,也就是说以下处理流程的执行主体并不限定于各个逻辑单元,也可以是硬件或逻辑器件。
[0159] 在20世纪90年代,对于一个技术的改进可以很明显地区分是硬件上的改进(例如,对二极管、晶体管、开关等电路结构的改进)还是软件上的改进(对于方法流程的改进)。然而,随着技术的发展,当今的很多方法流程的改进已经可以视为硬件电路结构的直接改进。设计人员几乎都通过将改进的方法流程编程到硬件电路中来得到相应的硬件电路结构。因此,不能说一个方法流程的改进就不能用硬件实体模块来实现。例如,可编程逻辑器件(Programmable Logic Device, PLD)(例如现场可编程门阵列(Field Programmable Gate Array,FPGA))就是这样一种集成电路,其逻辑功能由用户对器件编程来确定。由设计人员自行编程来把一个数字系统“集成”在一片PLD上,而不需要请芯片制造厂商来设计和制作专用的集成电路芯片。而且,如今,取代手工地制作集成电路芯片,这种编程也多半改用“逻辑编译器(logic compiler)”软件来实现,它与程序开发撰写时所用的软件编译器相类似,而要编译之前的原始代码也得用特定的编程语言来撰写,此称之为硬件描述语言(Hardware Description Language,HDL),而HDL也并非仅有一种,而是有许多种,如ABEL(Advanced Boolean Expression Language)、AHDL(Altera Hardware Description Language)、Confluence、CUPL(Cornell University Programming Language)、HDCal、JHDL(Java Hardware Description Language)、Lava、Lola、MyHDL、PALASM、RHDL(Ruby Hardware Description Language)等,目前最普遍使用的是VHDL(Very‑High‑Speed Integrated Circuit Hardware Description Language)与Verilog。本领域技术人员也应该清楚,只需要将方法流程用上述几种硬件描述语言稍作逻辑编程并编程到集成电路中,就可以很容易得到实现该逻辑方法流程的硬件电路。
[0160] 控制器可以按任何适当的方式实现,例如,控制器可以采取例如微处理器或处理器以及存储可由该(微)处理器执行的计算机可读程序代码(例如软件或固件)的计算机可读介质、逻辑门、开关、专用集成电路(Application Specific Integrated Circuit,ASIC)、可编程逻辑控制器和嵌入微控制器的形式,控制器的例子包括但不限于以下微控制器:ARC 625D、Atmel AT91SAM、Microchip PIC18F26K20 以及Silicone Labs C8051F320,存储器控制器还可以被实现为存储器的控制逻辑的一部分。本领域技术人员也知道,除了以纯计算机可读程序代码方式实现控制器以外,完全可以通过将方法步骤进行逻辑编程来使得控制器以逻辑门、开关、专用集成电路、可编程逻辑控制器和嵌入微控制器等的形式来实现相同功能。因此这种控制器可以被认为是一种硬件部件,而对其内包括的用于实现各种功能的装置也可以视为硬件部件内的结构。或者甚至,可以将用于实现各种功能的装置视为既可以是实现方法的软件模块又可以是硬件部件内的结构。
[0161] 上述实施例阐明的系统、装置、模块或单元,具体可以由计算机芯片或实体实现,或者由具有某种功能的产品来实现。一种典型的实现设备为计算机。具体的,计算机例如可以为个人计算机、膝上型计算机、蜂窝电话、相机电话、智能电话、个人数字助理、媒体播放器、导航设备、电子邮件设备、游戏控制台、平板计算机、可穿戴设备或者这些设备中的任何设备的组合。
[0162] 为了描述的方便,描述以上装置时以功能分为各种单元分别描述。当然,在实施本说明书时可以把各单元的功能在同一个或多个软件和/或硬件中实现。
[0163] 本领域内的技术人员应明白,本说明书的实施例可提供为方法、系统、或计算机程序产品。因此,本说明书可采用完全硬件实施例、完全软件实施例、或结合软件和硬件方面的实施例的形式。而且,本说明书可采用在一个或多个其中包含有计算机可用程序代码的计算机可用存储介质(包括但不限于磁盘存储器、CD‑ROM、光学存储器等)上实施的计算机程序产品的形式。
[0164] 本说明书是参照根据本说明书实施例的方法、设备(系统)、和计算机程序产品的流程图和/或方框图来描述的。应理解可由计算机程序指令实现流程图和/或方框图中的每一流程和/或方框、以及流程图和/或方框图中的流程和/或方框的结合。可提供这些计算机程序指令到通用计算机、专用计算机、嵌入式处理机或其他可编程数据处理设备的处理器以产生一个机器,使得通过计算机或其他可编程数据处理设备的处理器执行的指令产生用于实现在流程图一个流程或多个流程和/或方框图一个方框或多个方框中指定的功能的装置。
[0165] 这些计算机程序指令也可存储在能引导计算机或其他可编程数据处理设备以特定方式工作的计算机可读存储器中,使得存储在该计算机可读存储器中的指令产生包括指令装置的制造品,该指令装置实现在流程图一个流程或多个流程和/或方框图一个方框或多个方框中指定的功能。
[0166] 这些计算机程序指令也可装载到计算机或其他可编程数据处理设备上,使得在计算机或其他可编程设备上执行一系列操作步骤以产生计算机实现的处理,从而在计算机或其他可编程设备上执行的指令提供用于实现在流程图一个流程或多个流程和/或方框图一个方框或多个方框中指定的功能的步骤。
[0167] 在一个典型的配置中,计算设备包括一个或多个处理器(CPU)、输入/输出接口、网络接口和内存。
[0168] 内存可能包括计算机可读介质中的非永久性存储器,随机存取存储器(RAM)和/或非易失性内存等形式,如只读存储器(ROM)或闪存(flash RAM)。内存是计算机可读介质的示例。
[0169] 计算机可读介质包括永久性和非永久性、可移动和非可移动媒体可以由任何方法或技术来实现信息存储。信息可以是计算机可读指令、数据结构、程序的模块或其他数据。计算机的存储介质的例子包括,但不限于相变内存(PRAM)、静态随机存取存储器(SRAM)、动态随机存取存储器(DRAM)、其他类型的随机存取存储器(RAM)、只读存储器(ROM)、电可擦除可编程只读存储器(EEPROM)、快闪记忆体或其他内存技术、只读光盘只读存储器(CD‑ROM)、数字多功能光盘(DVD)或其他光学存储、磁盒式磁带,磁带磁磁盘存储或其他磁性存储设备或任何其他非传输介质,可用于存储可以被计算设备访问的信息。按照本文中的界定,计算机可读介质不包括暂存电脑可读媒体(transitory media),如调制的数据信号和载波。
[0170] 还需要说明的是,术语“包括”、“包含”或者其任何其他变体意在涵盖非排他性的包含,从而使得包括一系列要素的过程、方法、商品或者设备不仅包括那些要素,而且还包括没有明确列出的其他要素,或者是还包括为这种过程、方法、商品或者设备所固有的要素。在没有更多限制的情况下,由语句“包括一个……”限定的要素,并不排除在包括所述要素的过程、方法、商品或者设备中还存在另外的相同要素。
[0171] 本领域技术人员应明白,本说明书的实施例可提供为方法、系统或计算机程序产品。因此,本说明书可采用完全硬件实施例、完全软件实施例或结合软件和硬件方面的实施例的形式。而且,本说明书可采用在一个或多个其中包含有计算机可用程序代码的计算机可用存储介质(包括但不限于磁盘存储器、CD‑ROM、光学存储器等)上实施的计算机程序产品的形式。
[0172] 本说明书可以在由计算机执行的计算机可执行指令的一般上下文中描述,例如程序模块。一般地,程序模块包括执行特定任务或实现特定抽象数据类型的例程、程序、对象、组件、数据结构等等。也可以在分布式计算环境中实践本说明书,在这些分布式计算环境中,由通过通信网络而被连接的远程处理设备来执行任务。在分布式计算环境中,程序模块可以位于包括存储设备在内的本地和远程计算机存储介质中。
[0173] 本说明书中的各个实施例均采用递进的方式描述,各个实施例之间相同相似的部分互相参见即可,每个实施例重点说明的都是与其他实施例的不同之处。尤其,对于系统实施例而言,由于其基本相似于方法实施例,所以描述的比较简单,相关之处参见方法实施例的部分说明即可。
[0174] 以上所述仅为本说明书的实施例而已,并不用于限制本说明书。对于本领域技术人员来说,本说明书可以有各种更改和变化。凡在本说明书的精神和原理之内所作的任何修改、等同替换、改进等,均应包含在本说明书的权利要求范围之内。