检验设备软件在各种条件下可实现持续运行状态,以及评估设备从故障中恢复正常服务所需要的时间和其他影响,是软件可靠性测试主要涉及的课题。

  设备为达到连续可运行目标,除了在硬件设计中考虑器件可连续无故障运行外,很重要的方面是软件在各种条件下可经受考验,持续工作。这需要在实现基本功能前提下,在软件中设计一系列容错性逻辑去保证。

  为全面评估软件容错性和故障恢复能力,测试需要制造或模拟一系列条件,包括内部硬件故障条件、外部恶意攻击条件、偶发过载条件、软件资源耗尽条件、周边环境故障条件以及长时间正常负荷持续运行模拟。为了在产品开发的不同阶段组织针对性测试,这些测试行为又被明确定义并归类。

  测试分类

  1、协议健壮性测试

  协议健壮性测试是为了找出特定协议的具体实现代码的弱点。是一种以破坏性手段去尝试运行软件的行为,通过用户接口的异常输入,使用异常协议消息交互引导软件进入未定义或未保护的状态。

  对软件系统而言,合法输入组合以外的输入往往超出正常输入的组合,软件运行中总会遇到一些预期之外的输入。因此,软件需要有严格的合法性检查才能避免进入未知状态。协议健壮行测试的目标是尽可能找出软件保护不周的问题。

  在软件测试的早期阶段进行的参数边界值测试属于健壮性测试的一部分。比如一个用户接口接受1-100的整数输入,那么1和100是合法边界,大于100和小于1的输入都是非法输入。其他非整数型的输入也属于非法值,包括故意破坏检查输入条件的代码的一些组合(如超长输入值,空输入,格式化字符等)。软件面对的接口除了终用户可见的部分之外,还有大量的软件组件之间的不可见部分,以及设备之间的通信协议接口。

  除了单一输入的简单合法性判断,软件在组合输入和特定状态下可接受输入的定义更为复杂。为确认软件在各种条件下的运行正常,测试需要尝试尽可能多的组合。复杂的通信协议除了定义有逻辑化结构的报文格式,还有一系列的内部状态,要测试人员完全手工方式遍历这些状态,并且构造所有可能的异常组合输入条件是无法想象的,因此需要专用的测试工具和仪器专门检测软件对各种协议变异报文的处理。目前,商用化的测试工具已经很多,比如IxDefend协议健壮性测试套件和MuDynamics的fuzzing测试套件是比较强大的。为了达成在特定状态下注入错误,测试套件需要先完成一些合法的交互过程,使被测目标达到预设状态,然后再注入异常。复杂的协议需要事先配置很多参数去达成这种交互,而变异输入的变化和组合数量非常庞大,一个复杂协议经常达到几十万甚至上百万的测试用例,尽管有自动化测试工具,这种测试运行也要耗费大量的时间。因此,对参数的调整是测试需要关注的一个重要方面。

  从系统测试的角度,观测协议健壮性的测试结果是比较困难的,一般是从系统外部观察整机是否存在异常,正在被测试的协议功能有没有停止响应,正常用户请求是否得到及时处理,设备的性能有没有下降。容易被观测到现象是系统死锁或重启,系统性能变化或主要功能异常也能被及时发现。而一些细微的功能异常或资源耗费,很容易被测试人员忽视,在这里,测试工具也无能为力。

  以IxDefend测试TLS-Server举例。

  1. 完成测试仪器与被测试设备的物理连接,并且将端口配置IP地址,开启TLS-Server服务。

  2. 通过测试仪器的GUI控制界面装入TLSServer测试套件,如图1所示。

图1 IxDefend选择测试套件

  3. 配置TLSServer测试所需要的参数,包括被测试设备IP、TLS服务端口、超时时间等,如图2所示。

图2 IxDefend配置TLS-Server套件运行参数

  4. 点击开始按钮启动测试运行。

  测试运行期间,仪器会发送事先定义好的各种异常组合,并检查设备对这些报文的响应。一旦被测试设备失去任何响应,记录为一次失败,并持续尝试下面的测试用例。如图3所示的是一个真实的运行记录,设备在某项测试运行后发生异常,该项目被标记为红色。测试人员可以根据该记录重现问题,并将设备异常信息一并提交给开发定位具体原因。

图3 IxDefend运行结果统计

  通常,判断软件行为是否正常的先决条件之一是其是否运行在正确的硬件环境之下,因为硬件故障对软件产生的影响往往是致命的和不可预测的。在实际情况中,越是造价昂贵且承担重要任务的硬件系统,其硬件的复杂度越高,故障率也更高。为了提高系统的可靠性,硬件在设计上会使用冗余器件的方式(比如多个电源、多个风扇、多个交换网板、多个主控板),但在很多情况下,硬件替换做不到对软件透明,需要依赖软件检测并采取一系列措施。此外,软件还需要设计足够的容错性去隔离硬件错误的影响范围。在非关键器件停止工作之前,软件需要尽可能保证系统其它功能不受影响。

  对测试人员而言,了解软件对硬件的依赖,通过制造或模拟硬件器件故障检验软件行为的合理性,是可靠性测试的一个重要环节。硬件故障测试的目标是观测和评估软件在硬件失效时的反映,找出预期与实际结果之间的差距。在测试有备份硬件系统的产品时,测试人员往往使用硬件拔出槽位,命令重启等方式验证备份机制的有效性。然而,这还远远不够。设备在实际运行条件下器件被拔出只是一种维护行为,很多情况下是在连续运行过程中,器件突然失效。测试人员需要验证这些情况,以确认软件设计的故障检测机制和容错机制的真实有效性。
$nwes_page$
  由于硬件系统的具体情况不同,每个器件的故障形式和直接影响不同,是否有规避方案需要具体分析。软件对硬件可用性的依存度往往很高,因此硬件故障测试的结果经常具有很大的争议性。对测试结果的分析和判断比测试设计和执行更为重要。

  现有的测试手段中,直接的方式是通过改动硬件线路或干预数字信号制造故障。此外,可以通过软件加入调试命令,对一些关键器件的状态进行修改,设置为非法的状态来模拟故障。

  2、压力测试

  任何设备或系统都是在一定的工作负荷下完成其功能。如果外部加入的工作负担超过其大能力,系统效能会下降甚至是停止工作。这是一种与可用性相背离的特性,却是任何系统的必然属性。很多重要系统是通过增加硬件成本,人为降低承诺指标来缓解这一问题,然而事实上都存在一个能力极限,除非输入子系统进行了硬性限制。

  为了提高设备的性价比,一般软件系统不会设定承载能力的硬性约束,因此,设备都会面对超负荷工作的场景。软件设计力争减少超负荷运行的负面效应,使系统在合理压力下能够正常运作是可靠性的一个重要考量。虽然用户不会要求设备能在超负荷的工作环境下连续稳定运行,但在真实网络中,负荷波动是无法避免的,短时间的超载运行不应该导致灾难性的后果。

  事实上,压力除了令系统的计算能力经受考验,也会使系统内的很多资源被软件进程占用;如果压力消除以后,这些资源不能被充分释放和回收,经受过压力的系统将无法完全恢复正常的工作能力。

  压力测试是通过制造设备的超载负荷,模拟设备在真实环境下可能遇到的场景。一台网络设备会有很多负载指标,验证各个指标的超载工作能力是一项繁杂的测试工作。除了观测压力下设备的反应,在负荷恢复到承诺指标范围内之后,系统完全达到正常工作状态的能力和恢复时间也是用户关心的指标。这些高负载的测试一般都要依赖专用的测试仪器来模拟。

  一般在设备规格会写明产品支持的IP路由表容量、大转发数据流量、ARP或MAC地址容量等指标。测试的工作是把被测试设备与测试仪器连接,通过仪器构造与规格指标相同或略低的一项负载,再制造一个10%左右的异常波动冲击被测设备,并观察被测设备在加载超载负荷前、负荷中和恢复到初始设定负荷之后的实际表现。。

  不受压力影响和能快速恢复的设备是可能被制造出来的,但是代价是必然提高硬件和软件成本。因此一个合理的可接受的压力反应和恢复时间,往往需要根据用户的使用场景和可承受成本综合考虑。

  3、内存耗尽测试

  与硬件发生故障类似,软件所要面对的另一种是情况是资源枯竭。因为软件要流畅地运行需要依赖很多外部资源,其中包括:内存、定时器、队列、文件句柄、Socket等等。这些资源中关键的是内存,因为很多资源不足可以等待,内存短缺会导致立即的操作失败。一个复杂的软件系统内存资源都是动态申请和释放的,在各个处理进程之间动态流转。在突发任务占用大量内存的情况下,其他任务可能面临资源枯竭。一个良好设计的软件系统需要设定内存门限,一旦内存消耗达到门限会强制一些不重要的任务退出运行而释放资源。而且所有申请内存的任务需要自身设计保护代码,避免没有申请成功时误入歧途。

  资源耗尽的情况下软件系统必然会产生一些功能受限的反应,只要这种情况能在资源充足后得到恢复不构成严重问题。确认系统在资源不足时没有异常反映,合理屏蔽了次要功能,同时确保高优先级进程得到应得的资源是软件测试所要做的工作。

  测试手段通常是启动一些重要的功能和构造动态的运行负荷,然后用调试命令占用内存或启动一些消耗型任务占用内存,以构造资源耗尽的条件,观察被测系统在内存枯竭后的反应,并继续进行操作。后再通过释放占用的内存来恢复正常条件,观察系统受影响的功能是否自动恢复。

  内存耗尽测试的原理非常简单,但是因为动态分配内存的指令无处不在,测试覆盖各种流程分支要设定各种组合条件,存在很大执行的难度。内存耗尽测试可能发现长期隐藏于软件中的严重问题,彻底解决这些问题,对软件的可靠性有很重要的意义。

  4、拷机测试

  由于软件固有的逻辑复杂性和系统测试手段的限制,有些问题只有在实际环境下经过足够长时间运行才会出现。拷机测试是在实验室模拟设备运行的真实工作场景,通过规定负荷及偶发性过载条件下连续运行,观测被测设备连续无故障运行时间,俘获异常错误的测试。

  测试所构造的工作场景能否还原真实应用,是能否提早发现问题的关键。由于用户的应用场景千差万别,需要用很多设备搭建组网来还原,而且必须等候足够长的时间,这是一种高成本的测试方式,却又不可替代。测试人员一般会采用频繁触发设备状态变化的手段加速问题出现,这对某些问题有效,却可能隐蔽另外一些问题。

  H3C的每个产品都要经过严格测试,其中必须进行的一项是长时间的拷机环境测试。设备被接入一个运行各种拓扑管理协议和有大量背景流量的模拟环境,以验证设备在典型应用环境下7*24小时的稳定运行。即使产品已经在市场正式投入使用,这套拷机环境还会持续运行,并且经常调整流量和业务规划,以期覆盖更多的用户应用环境。

  5、收敛指标测试

  对网络设备而言,保证网络通畅是其重要的功能之一。因此,网络设备除保障自身连续运行外,还专门设计了很多从环境故障中恢复网络连通性的协议。有些则是针对自身发生异常时实现冗余硬件切换,流量路径切换或快速故障恢复的协议。针对这些情况,有一个通用的度量指标,即网络收敛指标,是通过网络中断服务(或故障恢复)时间来考察设备或网络提供的可靠性。

  任何一种网络路由协议或拓扑管理协议都是为了在动态变化的网络中提供一个可行的流量路径而设计的,所以收敛是一个基本属性。从注入拓扑变化或故障发生的时间开始,网络服务和数据流量受到影响,在拓扑收敛后路径切换到备份网络上,恢复网络服务和流量所经历的时间是收敛时间。为加速收敛而提出的一些附加技术可以使收敛时间缩短到毫秒级甚至在设备主控发生重启等情况下提供不中断的转发服务。

图4 IGP路由收敛测试组网图

  IGP收敛的测试实例。

  如图4所示,被测试设备首先从B和C端口学习到大量的IGP路由信息,其中B端口的度量值优于C端口。测试仪器用稳定的流量由A端口发送,被测设备转发到B端口。测试仪器通过在B端口模拟拓扑变化,撤销一部分路由信息,受影响的流量开始丢失。被测试设备在完成路由计算后将这些流量重新路由到C端口上。测试仪器通过计算这个过程丢失的数据流量和发送速率折算收敛过程经历的时间。

  在收敛网络之外来评估收敛时间时,可以使用相同的原则,根据发送流量的速率和被丢失报文数量计算出收敛经历的时间。收敛测试的另一个方向是故障恢复主路径时,对于流量的保护。理想的情况可以做到网络无中断地回切到主路径。然而不同的拓扑管理协议和具体实现技术有一定差别,很多情况下回切过程的流量丢失不能完全避免。

  常见的收敛指标测试有二层网络STP收敛测试,RPR和RRPP环网收敛,三层路由协议RIP、OSPF、BGP收敛,以及双主控设备的主备倒换测试,VRRP设备倒换测试。为了减少拓扑管理协议在设备重启期间对周边网络的冲击,很多协议开发了GracefulRestart的功能,并通过控制与数据转发分离的Non-StopForwarding技术使流量转发近乎不中断。H3C的IRF2技术也可以将多个物理设备组成一个逻辑设备,以降低对STP、VRRP等慢收敛协议的依赖。所有这些技术的目标都是减少设备故障造成的网络影响,提高组网的可靠性,而评价这些技术的指标都是网络收敛时间。测试执行的步骤几乎是相同的,首先构建正常的网络拓扑,模拟故障发生,监测流量切换的过程和流量丢失的情况,计算切换需要的时间。

  结束语

  以上的几种测试类型基本覆盖了软件可靠性相关的测试。在具体的产品开发过程中,协议健壮性测试、硬件故障模拟测试、内存耗尽测试等适合在软件功能组件的开发过程中进行测试,而压力测试、收敛指标测试、拷机测试需要在系统整合并且功能稳定后才能实施,所以一般放在产品开发后期。经过全方位的可靠性测试并解决所有问题之后,软件系统可以应对各种内部外部的复杂情况,为用户提供更高可用性的健壮网络。