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