操作数值超出系统的限制_嵌入式操作系统API的测试方法浅谈

*作者单位:中科院空间软件评测中心、北京航空航天大学、卡索(北京)科技有限公司。

嵌入式操作系统API(Application Programming Interface,API),是一些预先定义的函数,它是由操作系统实现并提供给用户的程序接口或应用编程接口。用户通过调用操作系统中的API,来实现预期功能。

为确保用户在调用操作系统API时,尽可能不出现问题,需要在操作系统的研制过程中,对API进行测试验证。

423f14db77cf781d83ed586af570d06b.png

目前嵌入式操作系统测试的主要难点

测试环境构建较为困难——

嵌入式操作系统与大家熟悉的桌面式操作系统有较大差异,它没有图形化显示界面供使用者操作。测试人员难以控制操作系统的输入,难以观察操作系统的输出。

对测试人员要求较高——

为构建嵌入式操作系统API测试场景,测试人员需熟练掌握嵌入式操作系统的组成、架构等基础知识。

423f14db77cf781d83ed586af570d06b.png

嵌入式操作系统API应该如何开展测试呢?

下面我们以嵌入式Linux操作系统为例,从以下几个角度探究嵌入式操作系统的API测试:

1、测试依据;

2、测试目标;

3、测试形式;

4、测试方法;

5、经验总结。

>>>> 1、测试依据

用户在调用操作系统的API时,首先需要查看API用户手册,了解API使用方法。用户手册中详细描述了函数原型、实现功能、返回值、可能出现的错误等,是API测试的依据。

在用户手册中,API函数主要有以下特点:

模块化:功能以函数形式封装;

独立性:函数独立进行调用,较少存在并发;

ERROR设计多:函数返回值为ERROR的设计较多;

等价类明确:详细描述函数参数的有效范围,正常、异常等价类明确。

下面我们以CentOS中的Linux Programmer’s Manual为例,简要说明从用户手册获取API测试依据的方法。

f37a83af8c0a59699cef74e69eeeb03d.png

这段内容描述了Inotify_init和Inotify_init1函数:

  • 函数功能为初始化Inotify的实例;

  • flags可能的取值宏为IN_NONBLOCK和IN_CLOEXEC;

  • 函数的返回值为文件描述符或-1;

  • 可能出现的错误有EINVAL、EMFILE和ENFILE等。

以上述内容作为依据进行API测试,当函数实际调用结果与用户手册不符时,就测出了函数Bug。

一般导致Bug出现原因有两类:

  • API函数实现错误(程序错误);

  • 用户手册描述错误(文档错误)。

>>>> 2、测试目标

小结一下,嵌入式操作系统API测试的目标:

  • 验证API函数能否满足用户手册要求;

  • API函数在异常条件下是否存在处理缺陷;

  • API函数的ERROR返回结果是否正确等。

>>>> 3、测试形式

API测试的对象是函数,在测试过程中,测试人员需要编写程序或软件,并在其中调用被测API函数,获取输出并记录系统的响应,来验证API实现是否正确。

有些人会疑惑,API测试和软件单元测试的对象都是函数,两者是否是类似的?

实际上,API测试与单元测试存在本质区别:单元测试为白盒测试,API测试为黑盒测试

API测试

API测试将函数当作黑盒看待,通过调用它并查看系统的响应和状态来完成测试;

API测试的输入输出形式多样;

API测试时,测试人员可以通过创建变量、通过文件系统或命令行操作查看等方式,设计测试的输入输出。

单元测试

单元测试从函数内部切入,需要在了解函数内部代码的前提下开展;

单元测试的输入输出形式固定;

单元测试时,输入输出的内容限定于函数的形参、内部变量、返回值等。

>>>> 4、测试方法

我们先来看看标准中是如何要求的,以GJB 7706-2012《嵌入式操作系统测评要求 》中文件系统测试的要求为例:

39e71e0ab286c7a3222986f4edbf477e.png

标准要求是概括性的,在实际测试中,可能一条标准要求由多项API函数共同完成,或者某个API函数的功能未在标准要求中完全体现,等等。

因此,构建API函数的使用场景是测试切入点,能够更好模拟API在真实环境下的运行状态,也更容易与标准要求挂钩。测试总体方法如下:

503f78f67e32367352b5ec4ad706c93b.png

使用场景构建:从用户使用角度出发,针对一个或多个API函数的运行情况,测试API函数完成用户任务的能力;

实参等价类划分:针对API函数的实参输入,考虑各类输入场景,测试API函数是否达到用户手册要求;

错误情况覆盖:重点测试API函数的ERROR场景,验证API函数的错误处理能力。

使用场景构建 (功能测试)

用户实际使用API的场景复杂,构建使用场景时,不仅需要考虑API函数输入(实参传递)的正确性和有效性,还需要尽可能多去考虑当前系统状态、系统设置等因素。

例如,在进行文件系统测试时,构建使用场景的考虑因素包含:

  • 文件所属的文件系统及其读写权限(ext4、vfat、xfs等);

  • 文件类型(普通文件,管道文件,套接字文件,目录文件、链接文件、字符\块设备文件等);

  • 文件的权限(777,755,644等);

  • 文件的扩展属性(EA);

  • 等等。

下面以symlink函数为例,介绍使用场景构建方法——

  • 函数原型为:int symlink(const char *target, const char *linkpath);

  • 实现功能:创建名为linkpath的符号链接,指向目标文件target。(在linux系统,符号链接类似于windows系统的快捷方式,但符号链接可对目标文件进行操作)

我们制定以下测试内容,验证symlink函数的正常功能:

1)可正确创建指向目标文件的符号链接linkpath,并生成新的inode信息;

2)目标文件为无效路径时linkpath也为无效符号链接;

3)打开符号链接可正确读取目标文件内容;

4)打开符号链接修改其中内容可达到修改目标文件的效果;

5)删除符号链接时,不会删除目标文件。

考虑到symlink函数的使用场景,上述测试内容并不充分。还需要考虑:

  • 使用符号链接时,目标文件与符号链接不在同一个文件系统中,此时需要开展跨文件系统创建符号链接的测试。在测试过程中发现,并非所有文件系统都支持符号链接创建,如vfat文件系统不直接支持符号链接创建;当linkpath所在文件系统为vfat时,目标文件为ext4时,函数会返回EPERM错误,即linkpath所在文件系统不支持符号链接创建;当linkpath所在文件系统为只读文件系统时,同样不支持创建符号链接,调用函数返回EROFS错误……

  • 当创建符号链接的目录权限存在不可写的情况时,函数会返回EACCES错误,即没有写权限。其他系统设置也可能影响函数的执行结果……

  • 除此之外,符号链接目标文件的类型可能为普通文件、管道文件、套接字文件、目录文件、链接文件、字符\块设备文件这七大类,测试时不能仅测试普通文件,还应充分考虑其它文件类型……

  • ……

尽可能构建API函数的使用场景,尤其是小概率、异常操作的使用场景,是测试发现问题的有效方法。

实参等价类划分 (功能测试)

构建使用场景之后,针对API函数的实参输入,进行等价类划分。按参数区间、数值、集合等划分的等价类大家都很熟悉了,除此之外,还需根据实参的实际内容进行等价类划分。

还以symlink函数为例,两个形参分别为const char *target和const char *linkpath,二者实际内容为路径:

按参数数值进行等价类划分:

可分为文件名最大长度超过/未超过255字符,文件路径最大长度超过/未超过4096字符,当路径、文件名超出最大长度时,函数返回ENAMETOOLONG错误。

按参数实际内容进行等价类划分:

可将target分为路径存在/路径不存在,当创建一个目标文件不存在的符号链接时,函数可以创建成功,但创建出的符号链接指向一个不存在的文件,符号链接并不可用;

也可将linkpath划分为链接文件已存在/链接文件不存在,当创建一个链接文件已存在的符号链接时,函数返回EEXIST错误。链接文件不存在的情况,还可细化为linkpath中的路径非目录、路径不存在,路径指针偏移等情况,也会使函数返回不同的ERROR;

甚至可以把路径划分为相对路径和和绝对路径,虽然这样划分对于函数功能的验证来说意义不大。

错误覆盖情况 (接口测试)

在进行使用场景构建、和实参等价类划分的测试工作中,已经对部分异常或非法参数进行了测试。在此基础上,需要对用户手册中的ERRORS测试查漏补缺,重点测试API函数的ERROR场景。

通过查看用户手册,还有以下内容未覆盖:

  • EIO输入输出错误;

  • EDQUOT超出磁盘配额;

  • ENOMEM内存不足等。

这些错误不直接与API功能相关,更多是因操作系统资源不足导致的错误,在API测试过程中也比较难设置。对于symlink函数来说,出现EIO错误可能由于磁盘本身的扇区故障,EDQUOT错误意味着磁盘没有存储空间了,ENOMEM错误是在系统内存不足的情况下创建符号链接。

这些错误往往伴随着复杂场景,需要尽可能去探究,例如,使用故障的磁盘进行测试、占满磁盘空间进行测试、封锁swap分区、限制进程的内存申请等。

至此,测试思路介绍告一段落。在开展操作系统测试前,需要对被测操作系统进行丰富的知识储备,尽可能多的构建使用场景,才能使测试更加充分,这对于测试人员是一个不小的挑战。

>>>> 5、经验总结

我们在实际进行嵌入式操作系统API测试的过程中,总结了几点经验,供大家参考:

测试优先级

对于某一组功能模块的函数,可能存在必须先对功能模块进行初始化后才能使用的情况,此时需要考虑测试优先级,避免多个函数互相进行测试验证。

例如Inotify_init函数,它负责返回一个Inotify实例,供后续Inotify_add_watch函数使用。测试过程中,需要先对Inotify_init的正确性进行验证,再测试其他使用它的函数。

并发及抢占

若函数对系统资源进行操作,需要考虑多个线程同时对系统资源操作的情况,可能需要同时使用多个终端进行测试。

自动化测试

测试过程中,为了提高测试效率,可以编写脚本开展自动测试,这里就先不展开了。

以上是嵌入式操作系统API测试的一些总结体会,如有错误希望指正,也希望能够帮助正在进行操作系统测试的各位,期待一同探讨。

7324b69bd2823d1e1c5bf4d68a84bf80.png

5848f19c320213f3a1c197aa5dfa8074.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值