什么是POSIX
在开始POSIX依从性测试技术介绍以前,我们必须了解什么是POSIX,POSIX是Portable Operating System Interface ofUnix的缩写。由IEEE(Institute ofElectrical and Electronic Engineering)开发,由ANSI和ISO标准化。POSIX 表示可移植操作系统接口,简单的说它的出现就是为了应对UNIX操作系统不断分支化所造成的应用程序无法兼容和共享使用问题,目的是提高在不同UNIX环境之间应用程序的可移植性,换句话说,为一个POSIX兼容的操作系统编写的程序,应该可以在任何其它的POSIX操作系统(即使是来自另一个厂商)上编译执行。而随着Windows、Linux操作系统的兴起、普适计算、云计算技术导致的终端运算设备小型化趋势使得UNIX操作系统的市场地位不断萎缩,就三大UNIX操作系统(AIX、Solaris、HP-UX)目前生存现状来看,在SUN倒下、HP安腾服务器推广不利的大环境下,SPARC和IA64架构小型机基本处于退出历史舞台的边缘。以上的一切都导致POSIX依从性测试认证的活跃程度慢慢的开始转向LSB(Linux Standards Base)依从性测试认证上来,就从POSIX标准和测试工具集的维护进度上我们也可以看出这一点。
POSIX标准簇本身来说是非常庞大的,在这些标准里面我们主要关注的是POSIX.1标准,其被广泛地接受,是用于源代码级别的可移植性标准。1003.1 提供一个操作系统的 C 语言应用编程接口(API)。最新的版本是 IEEE Std 1003.1, 2013 Edition The core of theSingle UNIX Specification(核心服务),就中国国家标准是《GB/T 14246.1-1993 信息技术 可移植操作系统界面 第一部分系统应用程序界面(POSIX.1)》,比较起来有一个较大的时间跨度。IEEE的标准可以从http://pubs.opengroup.org/onlinepubs/9699919799/toc.htm直接获取电子版本。另外,值得一提的是根据依从性测试的要求,对应的中国国家标准是《GB/T17548-1998信息技术 POSIX依从性的测试方法》,标准中规范了我们即将介绍的POSIX依从性测试技术的内容。
POSIX依从性测试
下面我们参照OSDL提供的Open POSIX Test Suite测试集来介绍一下POSIX依从性测试的主要方法和内容,Wiki站点是https://wiki.linuxfoundation.org/en/OpenPosixTest,项目源码可以在https://sourceforge.net/projects/posixtest/获得。,当然如果想要进行完整的POSIX认证请参考http://get.posixcertified.ieee.org/docs/testsuites.html提供的信息开展相关工作,其目前已经融入到了LSB认证中。
测试内容
Open POSIX Test Suite测试集所提供的针对POSIX依从性测试的主要内容包括基本定义(definitions)测试、接口功能实现(interfaces)测试和接口行为实现(behavior)测试。另外,它还包括了一个对于接口调用的功能测试(functional)和压力测试(stress),我们会在下文结合测试框架和源码着重介绍一下依从性相关的测试内容,对于接口级别的压力测试由于存在着LTP(Linux Test Project)这样一个更加优秀的工具(其实,它已经包含了Open POSIX Test Suite的stress集),我们就不过多介绍了。
测试范围
基本定义(definitions)测试测试范围包括:
aio.h - asynchronousinput and output (REALTIME)
errno.h - system errornumbers
sched.h - executionscheduling (REALTIME)
sys/mman.h - memorymanagement declarations
sys/shm.h - XSI sharedmemory facility
mqueue.h - messagequeues (REALTIME)
pthread.h - threads
signal.h - signals
time.h - time types
unistd.h - standardsymbolic constants and types
接口功能实现(interfaces)测试测试范围包括:
异步输入输出(aio_XXXXX)
消息队列(mq_XXXXX)
信号(sigXXXXX)
计时器(timer_XXXXX;clock_XXXXX)
系统线程(pthread_XXXXX)
执行时序安排(sched_XXXXX)
信号量(sem_XXXXX)
内存管理(mXXXXX)等接口。
说明:XXXXX代表在测试集目录下的一些子特性对应名称的目录名
接口行为实现(behavior)测试测试范围包括:
timers和WIFEXITED两类行为。
术语
单元:功能接口或名字空间的分配。
断言:对一个POSIX单元的功能或行为的一项陈述,它是由将被测试的POSIX标准得出的,对于符合POSIX的实现为真。
基本断言:需要对所要求的特征和已实现的条件特征进行测试的一个断言。
条件特征:在POSIX标准中涉及到、并非所有的实现都必须具有某个特征或行为。
工具框架和使用
测试用例的组织形式
首先,为了进一步了解Open POSIX Test Suite或接口依从性测试一种普遍技术方法,我们先来看一下测试用例的组织形式。
下图,从工具的目录结构方面可以看到测试用例集是按照测试内容进行组织构建的,另外,每一组测试用例集目录下,均包含了assertions.xml和coverage.txt两个文件,分别说明了这组测试用例集对应的标准断言和覆盖率情况:
我们以timer为例子,分别看一下definitions、interfaces和behavior的测试用例的具体内容:
(1)definitions测试:
definitions/time_h/1-1.c(头文件、是否提供接口):
#include <time.h>
definitions/time_h/1-2.c(结构体tm及成员定义):
#include <time.h>
struct tm this_type_should_exist, t;
int dummyfcn(void)
{
int week, year, dst;
t.tm_sec = 0;
t.tm_min = 10;
t.tm_hour = 17;
t.tm_mday = 1;
t.tm_mon = 11;
t.tm_year = 102;
week = t.tm_wday;
year = t.tm_yday;
dst = t.tm_isdst;
return 0;
}
可以看到,关于接口定义测试的测试用例就是测试操作系统是否提供了符合POSIX标准的对于头文件、结构体、宏、类型定义。
(2)interfaces测试
interfaces/time/1-1.c(time函数)
#include <stdio.h>
#include <stdint.h>
#include <time.h>
#include "posixtest.h"
int main(void)
{
time_t current_time;
current_time = time(NULL);
printf("%ju secs since the Epoch\n",(uintmax_t) current_time);
if (current_time != -1) {
puts("Test PASSED");
return PTS_PASS;
} else {
puts("Test FAILED: not value for time.");
return PTS_FAIL;
}
}
可以看到,关于接口功能测试的测试用例就是测试操作系统是否提供了符合POSIX标准的对于函数的定义和功能。
(3)behavior测试:
behavior/timers/1-1.c(最大timer创建支持)
#include <time.h>
#include <stdio.h>
#include <limits.h>
#include <unistd.h>
#include "posixtest.h"
int main(int argc, char *argv[])
{
timer_t tid;
int i;
long scTIMER_MAX=0;
scTIMER_MAX=sysconf(_SC_TIMER_MAX);
for (i=0; i<scTIMER_MAX;i++) {
if (timer_create(CLOCK_REALTIME, NULL, &tid) != 0) {
perror("timer_create() did not return success\n");
return PTS_FAIL;
}
}
printf("Test PASSED\n");
return PTS_PASS;
}
可以看到,通过sysconf(_SC_TIMER_MAX)获取系统允许的timer最大值,并循环创建,检查接口支持这种边界值的行为。
测试框架概貌
Open POSIX Test Suite测试框架利用穷举编译的方法执行基本定义(definitions)测试,对被测操作系统的POSIX接口定义的存在性进行测试,使用编译、链接、运行的方式执行接口功能实现(interfaces)测试和接口行为实现(behavior)测试,对被测对象的POSIX接口的功能和行为实现进行测试。
(1)run_tests脚本主要的核心内容阐释了上述的依从性测试方法:
runtests方法遍历传入测试目录(经$1传入),对POSIX_TARGET(用例)执行make build-tests和make run-tests测试:
runtests()
{
for test in `ls -d $1`; do
POSIX_TARGET=$test make build-tests
POSIX_TARGET=$test make run-tests
done
}
通过指定如AIO,限定测试目录执行专项测试:
AIO) echo "Executing asynchronous I/O tests"
runtests "$BASEDIR/aio_*"
runtests "$BASEDIR/lio_listio"
(2)从run_tests脚本的内容可以看出所有的测试执行均依赖Makefile文件,下面的源代码阐释了Makefile对于接口定义和接口功能测试的主要逻辑方法:
接口定义测试:
%.test: %.o
@COMPLOG=$(LOGFILE).$$$$; \
[ -f $< ] || exit 0; \
{ nm -g $< | grep -q " T main"; } || \
{ echo "$(@:.test=): link: SKIP" | tee -a $(LOGFILE) && exit 0; }; \
if $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS) > $$COMPLOG 2>&1; \
then \
echo "$(@:.test=): link: PASS" | tee -a $(LOGFILE); \
else \
( \
echo "$(@:.test=): link: FAILED. Linker output: "; \
cat $$COMPLOG; \
) >> $(LOGFILE); \
echo "$(@:.test=): link: FAILED "; \
fi; \
接口功能测试:
%.run-test: %.test $(top_builddir)/t0 $(top_builddir)/t0.val
@COMPLOG=$(LOGFILE).$$$$; \
[ -f $< ] || exit 0; \
$(TIMEOUT) $< > $$COMPLOG 2>&1; \
RESULT=$$?; \
if [ $$RESULT -eq 1 ]; \
then \
MSG="FAILED"; \
fi; \
if [ $$RESULT -eq 2 ]; \
then \
MSG="UNRESOLVED"; \
fi; \
if [ $$RESULT -eq 4 ]; \
then \
MSG="UNSUPPORTED"; \
fi; \
if [ $$RESULT -eq 5 ]; \
then \
MSG="UNTESTED"; \
fi; \
if [ $$RESULT -eq $(TIMEOUT_RET) ]; \
then \
MSG="HUNG"; \
fi; \
if [ $$RESULT -gt 5 -a $$RESULT -ne $(TIMEOUT_RET) ]; \
then \
MSG="INTERRUPTED"; \
fi; \
if [ $$RESULT -eq 0 ]; \
then \
echo "$(@:.run-test=): execution: PASS" | tee -a $(LOGFILE); \
else \
( \
echo "$(@:.run-test=): execution: $$MSG: Output: "; \
cat $$COMPLOG; \
) >> $(LOGFILE); \
echo "$(@:.run-test=): execution: $$MSG "; \
fi; \
使用方法
Documentation目录下提供了各类帮助文档,帮助文档可以帮助你了解如何运行测试、结果判断方法、断言方法、覆盖率情况等,主要文档包括:
HOWTO_RunTests、HOWTO_ResultCodes、HOWTO_Assertions、HOWTO_Coverage、HOWTO_DefinitionsTest、HOWTO_ConformanceTest
你可以通过阅读以上文档,利用Open POSIX Test Suite完成POSIX依从性测试。
(1)首先,需要针对你要测试的操作系统本身情况来定义LDFLAGS
如修改LDFLAGS文件:
D_XOPEN_SOURCE=600 -lpthread -lrt -lm
(2)执行依从性测试,直接参考HOWTO_RunTests文档内容,在posixtestsuite/主目录下直接执行以下命令:
# make
就可以完成全部依从性测试内容。
当然,你也可以利用上文介绍的run_tests脚本来完成专项接口的测试:
# ./run_tests [SIG|SEM|THR|TMR|MSG]
结果解读
在include/posixtest.h中定义了主要的测试结果Flag:
#define PTS_PASS 0
#define PTS_FAIL 1
#define PTS_UNRESOLVED 2
#define PTS_UNSUPPORTED 4
#define PTS_UNTESTED 5
测试结果定义如下:
PASS 测试完全执行并通过
FAIL 测试完全执行但失败
UNRESOLVED 测试未完全执行,无法判断通过或失败
UNSUPPORTED 测试中由于一个有条件的特征无法执行
UNTESTED 无法进行测试
另外,根据测试中所产生的意外情况,定义了以下未能得到测试结果的测试结束状态:
HUNG 执行测试超时被挂起
INTERRUPTED 由于某些原因测试中断