工程师必备:C/C++单元测试万能插桩工具
内容提要
腾讯安全平台部研发的动态插桩工具可优化研发效能,绕过编译器限制对C/C++代码进行插桩,实现单元测试的轻量化运行和提高代码覆盖率。支持插桩全局函数、成员函数、虚函数以及系统和第三方库函数。适用于X86_64平台上的Linux和MacOS系统。
延伸解读
动态插桩的底层原理与优势
该工具通过直接修改函数入口的机器指令,将控制流跳转到自定义桩函数,从而绕过编译器限制。与gmock等仅支持虚函数的工具相比,它能对非虚函数、系统API和第三方库函数进行插桩,且无需修改被测代码。这种底层方式几乎不受语法和编译器约束,为单元测试提供了更大的灵活性。
使用限制与平台注意事项
目前工具仅支持X86_64架构的Linux和MacOS,Windows及其他平台需等待后续支持。在MacOS下,需对可执行文件进行特定修改,且对内联函数无效,建议关闭内联和编译器优化。此外,可使用-fno-access-control编译选项关闭C++成员访问控制,便于测试私有成员。
桩函数的操作能力与测试隔离
桩函数不仅能模拟原函数返回值,还能访问真实参数、成员变量和全局变量,并可进行调用计数等操作。每个测试用例结束后需调用reset()恢复原函数行为,确保测试间互不干扰。这种设计使得单元测试更加轻量且可控,有助于提高代码覆盖率。
Q&A
这个动态插桩工具主要解决现有C/C++单元测试工具的哪些不足?
现有工具如gmock只能对虚函数插桩,对非虚函数需修改被测代码,且无法处理系统接口和C风格第三方库。该工具通过修改机器指令绕过编译器限制,可对任意函数进行插桩,实现轻量级单元测试并提高代码覆盖率。
动态插桩工具的实现原理是什么?
在函数B的入口处写入机器码,将函数C的地址存入寄存器并跳转,使所有对B的调用转为对C的调用。这样无需修改源代码或编译器,即可动态替换函数。
这个工具支持对哪些类型的函数进行插桩?
支持全局函数、普通成员函数、静态成员函数、虚函数,以及系统函数(如read、write)和第三方库函数。
使用该工具时有哪些平台限制和注意事项?
目前支持X86_64平台上的Linux和MacOS,Windows及其他平台短期内可支持。MacOS下需对可执行文件进行特定修改,且建议关闭内联和编译器优化。
如何对C++虚函数进行插桩?
桩函数需要this指针参数,mock时需额外传入一个任意对象(如&A::virtual_member, fake_virtual_member, &a_obj),调用reset()后恢复原行为。
这个工具的项目地址在哪里?
项目地址为https://github.com/wangyongfeng5/lmock。