0%

周谈(18)-测试框架的学习小结

前言

平常每周都会有一些心得感悟,这些在大家工作中可能会有许多共性。我觉得花一些时间整理一下,跟粉丝读者们分享一下日常学习工作的想法和所得,这是一个很好的互动和文章分享的痛点。

这是第十八篇。

DPDK测试框架

这一周看了DPDK的测试框架,主要是在app/test*这些目录下实现的application。

DPDK的测试框架的模型是基于XUnit模型实现的, 跟其他大多数的测试框架一样,分为测试套(test suite)和测试用例(test case)两个层级的概念。测试套下面可以包含多个测试套和多个测试用例,典型的树状结构,跟文件系统的目录结构是一样的。

测试套的执行流程是 suite->setup … unit_test_suite_runner … suite->teardown。setup和teardown分别是suite对应的资源的申请初始化和释放。unit_test_suite_runner就是嵌套的执行其下的测试套和测试用例。

测试用例的执行流程 case->setup … case->testcase/case->testwithdata … case->teardown。setup和teardown分别是case对应的资源的申请初始化和释放。testcase、testwithdata分别对应没有数据和有传入数据的用例执行。具体的就是业务函数的执行,然后对比输出结果和期望结果。返回值有三种, TEST_SKIP, TEST_SUCCESS, TEST_FAIL,分别表示不支持该测试功能,支持并且执行成功,支持但是执行失败。

最后,会输出用例的执行情况。

dpdk-test这个application 还支持命令行,通过绑定命令行和一个测试功能集的入口函数,可以很方便的执行指定的功能集测试用例。效果如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75

root@keep-VirtualBox:~/dpdk/build# dpdk-test -c 7 --vdev crypto_openssl --log-level 7 cryptodev_openssl_asym_autotest
EAL: Detected CPU lcores: 12
EAL: Detected NUMA nodes: 1
EAL: Detected static linkage of DPDK
EAL: Multi-process socket /var/run/dpdk/rte/mp_socket
EAL: Selected IOVA mode 'PA'
EAL: VFIO support initialized
CRYPTODEV: Creating cryptodev crypto_openssl

CRYPTODEV: Initialisation parameters - name: crypto_openssl,socket id: 0, max queue pairs: 8
TELEMETRY: No legacy callbacks, legacy socket not created
APP: HPET is not enabled, using TSC as default timer
RTE>>cryptodev_openssl_asym_autotest
+ ------------------------------------------------------- +
+ Test Suite : Crypto Device OPENSSL ASYM Unit Test Suite
+ ------------------------------------------------------- +

xform type: rsa
===================
operation supported - encrypt decrypt sign verify modlen: min 30 max 0 increment 1

xform type: modexp
===================
operation supported - modlen: min 0 max 0 increment 1

xform type: modinv
===================
operation supported - modlen: min 0 max 0 increment 1

xform type: dh
===================
operation supported - priv_key_generate pub_key_generate sharedsecret_compute modlen: min 0 max 0 increment 1

xform type: dsa
===================
operation supported - sign verify modlen: min 0 max 0 increment 1
+ TestCase [ 0] : test_capability succeeded
+ TestCase [ 1] : test_dsa succeeded
USER1: Test Public and Private key pair generation
USER1: Test Public Key Generation using pre-defined priv key
USER1: Test Private Key Generation only
USER1: Test shared secret compute
+ TestCase [ 2] : test_dh_keygenration succeeded
+ TestCase [ 3] : test_rsa_enc_dec succeeded
+ TestCase [ 4] : test_rsa_sign_verify succeeded
+ TestCase [ 5] : test_rsa_enc_dec_crt succeeded
+ TestCase [ 6] : test_rsa_sign_verify_crt succeeded
+ TestCase [ 7] : test_mod_inv succeeded
+ TestCase [ 8] : test_mod_exp succeeded
0) TestCase Modular Exponentiation (mod=128, base=20, exp=3, res=128) PASS
1) TestCase Modular Exponentiation (mod=60, base=50, exp=40, res=60) PASS
2) TestCase Modular Exponentiation (mod=8, base=65, exp=17, res=8) PASS
3) TestCase Modular Exponentiation (mod=100, base=150, exp=192, res=100) PASS
4) TestCase Modular Exponentiation (mod=255, base=20, exp=10, res=255) PASS
5) TestCase Modular Exponentiation (mod=112, base=257, exp=43, res=112) PASS
6) TestCase Modular Exponentiation (mod=299, base=240, exp=321, res=299) PASS
7) TestCase Modular Exponentiation (mod=448, base=50, exp=40, res=448) PASS
8) TestCase Modular Exponentiation (mod=19, base=500, exp=35, res=19) PASS
9) TestCase Modular Inverse (mod=128, base=20, exp=3, inv=128) PASS
10) TestCase RSA Encryption Decryption (n=128, pt=20, e=3) EXP, QT PASS
+ TestCase [ 9] : test_one_by_one succeeded
+ ------------------------------------------------------- +
+ Test Suite Summary : Crypto Device OPENSSL ASYM Unit Test Suite
+ ------------------------------------------------------- +
+ Tests Total : 10
+ Tests Skipped : 0
+ Tests Executed : 10
+ Tests Unsupported: 0
+ Tests Passed : 10
+ Tests Failed : 0
+ ------------------------------------------------------- +
Test OK


DPDK的测试用例里面的数据都是在代码中写死了的,数据比较单一,场景有可能覆盖不全。

libkcapi测试框架

libkcapi是对内核加密框架的封装,提供给用户态程序调用的库。这个库的测试用例采用了对比测试的方式。通过从/dev/urandom设备读取随机数据,然后分别使用libkcapi的程序和openssl程序对数据进行加密、解密,对比两个程序输出的结果是否一致来判断libkcapi的用例是否成功。

libkcapi的测试逻辑使用的shell脚本编写的,可以很方便进行调试。执行用例的时候,生成随机数据保存到临时文件中,然后通过命令行参数传递到程序中执行,输出结果到另一个临时文件,最后通过计算临时文件的sha1sum值来对比内容是否相同。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# 生成随机数据到指定的文件
gen_orig()
{
local size=$1
touch $ORIGPT
dd if=/dev/urandom of=$ORIGPT bs=$size count=1 2>/dev/null
}

# 对比文件的sha256sum摘要值
diff_file()
{
local orighash=$(sha256sum $1 | cut -d " " -f1)
local genhash=$(sha256sum $2 | cut -d " " -f1)
shift
shift

if [ x"$orighash" = x"$genhash" ]
then
echo_pass_local "$@"
else
echo_fail_local "$@: original file ($orighash) and generated file ($genhash)"
fi
}

...

# 临时文件的清理 用到了trap命令
init_setup()
{
trap "rm -f $TSTPREFIX*; exit" 0 1 2 3 15

# CR is also character
# Hex key string: 3031323334353637383961626364650a
echo -n "0123456789abcdef" > $KEYFILE_128
OPENSSLKEY128="0123456789abcdef"
# Hex key string: 303132333435363738396162636465663031323334353637383961626364650a
echo -n "0123456789abcdef0123456789abcdef" > $KEYFILE_256
OPENSSLKEY256="0123456789abcdef0123456789abcdef"
}

相比DPDK的测试框架, libkcapi采用随机数据,然后跟openssl的运算结果对比,相对比较灵活,覆盖场景比较全。不过,需要增加对openssl这个额外的库的学习成本,也是一种成长吧。

感受一下libkcapi的测试效果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
root@keep-VirtualBox:~/code/libkcapi/test# ./hasher-test.sh
[PASSED: 64-bit - 5.17.1] Failure on empty checker file for md5sum
[PASSED: 64-bit - 5.17.1] Failure on empty line checker file for md5sum
[PASSED: 64-bit - 5.17.1] Parsing checker file with asterisk with md5sum
[PASSED: 64-bit - 5.17.1] Checker file '-' interpretation with md5sum
[PASSED: 64-bit - 5.17.1] Input file '-' interpretation with md5sum
[PASSED: 64-bit - 5.17.1] Failure on empty checker file for sha1sum
[PASSED: 64-bit - 5.17.1] Failure on empty line checker file for sha1sum
[PASSED: 64-bit - 5.17.1] Parsing checker file with asterisk with sha1sum
[PASSED: 64-bit - 5.17.1] Checker file '-' interpretation with sha1sum
[PASSED: 64-bit - 5.17.1] Input file '-' interpretation with sha1sum
[PASSED: 64-bit - 5.17.1] Failure on empty checker file for sha256sum
...

这个就是简单的输出每个用例的执行结果,没有统计功能。不过看起来还比较清晰明了。

这两个框架每次都是批量的执行用例,没办法单独执行特定的用例。感觉用shell脚本的话,还是比较方便的。

更多

开源库基本上都是有对应的测试用例。通过剖析其实现的原理,我们也可以借鉴来为自研的代码库搞一个测试用例。实现测试驱动开发的目的,还可以在更改代码后,进行回归测试,裨益多多。

各种语言也有各自流行的测试框架,基本上也都是基于XUnit模型。 基于setup, test_case_fn,teardown的执行流程。


行动,才不会被动!

欢迎关注个人公众号 微信 -> 搜索 -> fishmwei,沟通交流。

博客地址: https://fishmwei.github.io

掘金主页: https://juejin.cn/user/2084329776486919