3.1.5 LTP(Linux Test Project)学习(五)-LTP代码学习

华为技术有限公司 Linux内核开发
2 人赞同了该文章

LTP代码学习方法主要介绍两个步骤,个人认为效果最好,见效也快。

方法1 查看官方介绍文档(如果你最开始接触ltp,那么步骤1一定要看)

1)用例Makefile配置介绍,见:linux-test-project/ltp

用例介绍,见:linux-test-project/ltp

上面两个网址,是LTP官方Guidelines,学习LTP时请仔细阅读,方能熟悉里面代码的写作格式。

2)LTP git仓库doc资料,主要包括:

CORE 2

doc/ltp-howto.txt

doc/style-guide.txt

doc/test-writing-guidelines.txt

doc/ltp-run-files.txt

等等(如果有时间最好全部大概浏览一遍)。

3)自己不太想多写什么介绍性文字,因为ltp的官方资料个人认为介绍非常全面,完全不需要别人再浪费口舌,但是还是写点注意(之前别人经常疑问的地方)。

a. ltp编译后目录,用例二进制全部放在testcases/bin,个人习惯单独cd进去执行,但是执行前请执行 PATH=$PATH:/home/ltp/testcases/bin 将其目录添加到环境变量,这是因为ltp本身有些框架性二进制文件,比如tst_brk等,用例执行会直接tst_brk调用,如果不添加到环境变量则报错命令无法找到,比如:

./wc01.sh

./wc01.sh: line 24: .: tst_test.sh: file not found

其实tst_test.sh就在 testcases/bin 下面。

(其实这条ltp已经提到,只是很少人去注意,然后大部分ltp的介绍性文档,都不会写的这么细,都仅仅告诉你怎么执行)

b. 每个用例均包括setup(void)和clean(void)函数进行环境初始化和清理,然后用例test01(void)、test02(void)等方式命名(test没太大规定,可以特性名称_test01均可)。

c. ltp内部包含了很多的封装脚本,基本满足用例执行的检查,报错打印等等,比如

需要root用户权限执行::

tst_require_root()

执行成功or失败,打印:

tst_res(TPASS, "getenv(" ENV1 ") = '"ENV_VAL "'");
tst_res(TFAIL, "getenv(" ENV1 ") = '%s', expected '"ENV_VAL "'", ret);

创建打开关闭:

SAFE_MKDIR(MNTPOINT, 0777);
SAFE_MKFS(tst_device->dev, tst_device->fs_type, NULL, NULL);
fd1 = SAFE_OPEN(cleanup, FILE1, O_CREAT | O_RDWR, 0666);
SAFE_CLOSE(fd1);

在看代码时候请认识到这点,不要看到这里就认为看不懂了。

Test-Writing-Guidelines说明:
Instead of writing: fd =
open(“/dev/null”, O_RDONLY); if (fd < 0) tst_brk(TBROK | TERRNO,
“opening /dev/null failed”); You write just: fd =
SAFE_OPEN(“/dev/null”, O_RDONLY);

其实就是对一般系统调用进行封装,减少调用后的返回值判断等,优化结构,让开发者更关注用例的功能逻辑,而不是返回值check等“琐事”。

d. LTP中有五种打印级别:

- TPASS Test has passed. 用例执行PASS

- TFAIL Test has failed. 用例执行FAIL

- TINFO General message. 用例执行过程中必要的提示信息(尽量不要太多)

- TBROK Something has failed in test preparation phase. 用例准备阶段broken,主要指Setup()时候测试环境不满足,或者执行过程突然发现不满足测试条件,系统异常 等而出现的broken性质退出

- TCONF Test is not appropriate for current configuration (syscall not implemented, unsupported arch, …) 用例不满足当前架构、平台、系统等。

e. LTP主要包括C代码和shell代码用例,所以在看Test-Writing-Guidelines时候注意区分,C代码主要调用框架中接口函数,shell代码主要调用框架中接口二进制(比如tst_res TPASS “xx”),其中tst_res是testcases/bin下面二进制。

方法2 学习前人提交的代码

个人推荐2个目录:

1)c语言代码学习,查看testcases/kernel/syscalls/,里面是系统调用用例,可以挑个自己喜欢的syscall,比如open,会看到open01.c open02.c …

一般来说目录中用例至少两个,一个包括正常功能验证,一个包括系统调用异常测试情况,其实就是man open的DESCRIPTION:功能说明,参数说明 和ERRORS:所有错误返回值和导致错误原因覆盖

(man不太了解可以看下我的 https://blog.csdn.net/cui841923894/article/details/81395591 man命令介绍)。

挑个简单的梳理下,open01.c

/*
* Copyright (c) International Business Machines Corp., 2001
* 07/2001 Ported by Wayne Boyer
* 06/2017 Modified by Guangwen Feng <fenggw-fnst@cn.fujitsu.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
* the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
这段是当你提交代码到开源社区时(ltp),必须声明,遵循GNU General Public License协议(不知道的可以搜一下)。主要规定代码是否可供别人使用,是否可允许修改,是否可商业使用等等。
*/ /*
* DESCRIPTION
* Open a file with oflag = O_CREAT set, does it set the sticky bit off?
* Open a dir with O_DIRECTORY, does it set the S_IFDIR bit on?
*
* ALGORITHM
* 1. open a new file with O_CREAT, fstat.st_mode should not have the
* 01000 bit on. In Linux, the save text bit is *NOT* cleared.
* 2. open a new dir with O_DIRECTORY, fstat.st_mode should have the
* 040000 bit on.
*/
用例描述性文字,如果自己提交,记得写清楚哈 #define _GNU_SOURCE /* for O_DIRECTORY */
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include "tst_test.h"
包含有文件,其中"tst_test.h"是调用框架接口,必须包含 #define TEST_FILE "testfile"
#define TEST_DIR "testdir" static int fd; static struct tcase {
char *filename;
int flag;
mode_t mode;
unsigned short tst_bit;
char *desc;
} tcases[] = {
{TEST_FILE, O_RDWR | O_CREAT, 01444, S_ISVTX, "Sticky bit"},
{TEST_DIR, O_DIRECTORY, 0, S_IFDIR, "Directory bit"}
};
变量和用例初始化,这里提一下,为了代码的可扩展性,系统调用参数尽量提取出来,使用结构体数组存储,方便新增或者删除用例。用例执行部分直接open(tcases[0]->filename,tcases[0]->flag…)。 static void verify_open(unsigned int n)
{
struct tcase *tc = &tcases[n];
struct stat buf; TEST(open(tc->filename, tc->flag, tc->mode));
fd = TEST_RETURN;
if (fd == -1) {
tst_res(TFAIL, "Cannot open a file");
return;
} SAFE_FSTAT(fd, &buf);
if (!(buf.st_mode & tc->tst_bit))
tst_res(TFAIL, "%s is cleared unexpectedly", tc->desc);
else
tst_res(TPASS, "%s is set as expected", tc->desc); SAFE_CLOSE(fd);
if (S_ISREG(buf.st_mode))
SAFE_UNLINK(tc->filename);
}
verify_open()用例主体 static void setup(void)
{
SAFE_MKDIR(TEST_DIR, 0755);
}
setup初始化 static void cleanup(void)
{
if (fd > 0)
SAFE_CLOSE(fd);
}
cleanup清理环境 static struct tst_test test = {
.tcnt = ARRAY_SIZE(tcases),
.needs_tmpdir = 1,
.setup = setup,
.cleanup = cleanup,
.test = verify_open,
};
架构声明,声明用例数组,函数等,框架会直接调用执行。

2)shell语言,查看testcases/commands,里面是shell写的内核基本命令测试用例

这里就不讲了,没什么意思,自己通过 sh –x 用例,去看下用例执行流程吧。

最后

之前很多使用ltp的人,遇到执行失败,比如broken,crash,或者TFAIL,想都不想都直接求助过来,我认为是非常不对的,有的人甚至问他代码是干什么的,执行到哪里失败了,有没有进行初步分析等都无法回答,我认为正常的流程应该包括:

1)顺序浏览一遍代码(自己作为执行者,代码至少看一遍吧~);

2)再次读代码,明白代码干什么的(这个是实现什么功能?测试什么接口?)

3)通过个别用户态调测工具进行初步定位,比如strace,gdb,sh -x等单步调式(strace对于用户态程序调试非常好用,https://blog.csdn.net/cui841923894/article/details/81395572,或者perror())

4)定位到代码后,看一下执行到哪里出错,为什么会出错,用例期望是什么,现在现象是什么,这个现象你认为正常吗?

到此为止,我认为是ok了,你认为正不正常,因为你能力有限,可能无法判断,但希望大胆说出自己的想法,就是不知道,也要说出来,但是前面三步请做一遍,尽管可能你也不知道为什么这么做。剩下还不了解,可以求助。

看问题请钻研一到两天,用尽办法去解决它(google问题,学习尝试新的调试方法等),这样才能进步。本人学习ltp,把所有syscall和command在ubuntu执行一编,花一周时间分析所有fail用例完毕,才养成良好的分析习惯。

发布于 2019-08-03
 

最新文章

  1. PAT (Advanced Level) Practise:1002. A+B for Polynomials
  2. js原型继承的几种方式
  3. 你会swap吗,按值传递还是按引用?
  4. hdu 1800 (map)
  5. dev combobox edit 怎么设置让选项清空
  6. 在WPF中自定义你的绘制(二)
  7. 关于写的Java书籍进展
  8. DataTable 用linq分组查询
  9. Roguelike元素对游戏设计的影响
  10. (java web后端方向)如何让你的简历为你争取到更多的面试机会,内容来自java web轻量级开发面试教程
  11. JsonIgnore注解不起作用的解决办法
  12. 英语演讲稿——Get Along with Fear
  13. ReactiveX 学习笔记(5)合并数据流
  14. python-bs4的使用
  15. &#39;sudo&#39;不是内部或外部命令,,,,的解决办法
  16. python直接赋值、浅拷贝和深拷贝
  17. poj_3261 后缀数组
  18. 201621123005《Java程序设计》第九次实验总结
  19. python开发_calendar
  20. Graph_Master(连通分量_D_Trajan缩点+dfs)

热门文章

  1. 【Papers】Robust Lane Detection via Expanded Self Attention 论文解读
  2. sql注入之超详细sqlmap使用攻略
  3. 史上最全jdk新特性总结,涵盖jdk8到jdk15!
  4. 【Java】7.0 进制转换
  5. MySQL数据库高级四:工具拾遗(视图)
  6. 「HTML+CSS」--自定义加载动画【016】
  7. 通过Fiddler 远程 对 安卓手机 iPhone 苹果手机 访问请求抓包 Android IOS14.4 fiddler代理 无法联网
  8. Go 类型转换与类型判断
  9. 代码安全丨第二期:URL重定向(跳转)漏洞
  10. 关于nacos在windows系统启动时闪退的问题