本主题说明如何构建和使用 C/C++test 运行时库。
为了使用 C++test 在主机(安装 C++test 的环境)以外的平台上进行测试,必须使用交叉编译器构建。如果您计划仅在主机上运行测试,则不需要构建 C/C++test 运行时库(因为 C++test 附带了用于基于主机的测试的预构建库)。
作为测试可执行文件准备阶段的一部分,C/C++test 可以自动构建运行时库。除非您要准备 C++test 运行时库的自定义版本,否则不需要手动准备 C++test 运行时库。
各节内容包括:
辅助关键字
在本主题中,辅助关键字用于表示完整路径:
- <C/C++test_runtime_root> =
<CPPTEST_INSTALL_DIR>/engine/runtime
- <C/C++test_runtime_sources> =
<CPPTEST_INSTALL_DIR>/engine/runtime/src
- <C/C++test_includes> =
<CPPTEST_INSTALL_DIR>/engine/runtime/include
说明
C/C++test 运行时库以 C 源文件和头文件的形式随 C++test 安装一起分发。运行时库的源代码位于上述框中引用的目录中
在大多数情况下,您可以让 C/C++test 自动构建运行时库。如果需要,可以使用 make 实用程序和支持的平台的预配置 make 配置之一来构建运行时库。 (请参见 Building the C++test Runtime Library with 'make')。C++test 提供了特殊的项目文件,这些文件有助于为受用的 IDE 构建运行时库。
请注意,需要为每个目标构建离散版本的运行时库。因此,如果您的项目是为多个体系结构构建的,那么很可能需要构建多个 C/C++test 运行时库的版本(每个体系结构一个)。
运行时库源包括所有正式支持的嵌入式平台的配置宏以及基于功能的较低级别的配置。需要在 IDE 中为构建配置正确设置这些宏。
以下步骤描述了常用方法:
- 使用提供的 makefile 或位于
<C/C++test_runtime_root>/projects.
中的预配置 IDE 项目之一来构建运行时库。 - 将结果
.a
文件添加到 项目属性> C/C++test> 构建选项>链接选项使用绝对路径。
- 最好的选择是将库文件放置在某个固定位置,以便多个用户无需更改即可指向该文件。
- 还支持将常规环境变量用于运行时库。
有关运行时库的常规信息
C/C++test 的插桩引用了许多必须在链接测试对象期间解析的符号。这些符号在 C/C++test 运行时库中提供。
C/C++test 附带一个预构建的全功能运行时共享库。然而,这个运行时是为丰富主机平台设计的。考虑到可能在其上进行测试的众多嵌入式平台,以及它们的功能和局限性,通常需要在针对不同的嵌入式环境构建运行时间之前对其进行调整。这就是为什么还提供运行时库的纯 C 源代码的原因。
可以将库配置为支持目标平台上可用的功能,或阻止那些不可用的功能。默认配置是全功能的,但是您可能需要阻止麻烦的功能,尤其是在遇到编译时或运行时崩溃的情况下。嵌入式开发人员熟悉他们使用的平台的优缺点,并且应该能够构建适当配置的库并将其路径附加到链接器命令行。
运行时库的源可在 <C/C++test_runtime_sources> 获得。构建运行时库所需的头文件位于 <C/C++test_includes> 中。
了解运行时发行结构和内容
C/C++test 运行时发行版包含以下位于
<C/C++test_runtime_root> 目录中的子目录或文件:
- src/: 包含 C 源文件。
- listeners/: 包含一个套接字和串行接口监听器,作为可与给定通信通道一起使用的简单实用程序。
- target/: 包含一组目标配置
- tests/: 包含一项快速测试。
- 生成文件:用于构建运行时库的生成文件。
- projects/: 包含用于构建运行时库的预配置 IDE 项目
- channel/: 包含特定通信通道的 Makefile 配置
- include/: 包含 C 头文件
*.vcproj: 用于构建运行时库的 Microsoft Visual Studio 项目文件。
在目标目录中,有多种目标配置可用于各种平台、体系结构和编译器。目标配置定义生成文件用来编译运行时源文件(例如 CC、CFLAGS 等)的变量,以及 LIBTOOL、LIBTOOL_FLAGS 等变量,生成文件使用这些变量从已编译的源创建运行时库(请参见使用 'make’构建 C++test 运行时库)。
构建 C++test 运行时库
概述
C/C++test 可以在可执行测试的准备阶段中自动构建测试运行时。建议使用此方法。在大多数情况下,不需要手动准备 C++test 运行时库。
在某些情况下,您可能需要准备 C++test 运行时库的自定义版本。您可以使用 Makefile 构建 C/C++test 运行时库或项目 .vcproj 文件之一在 <C/C++test_runtime_root> 目录中。您还可以使用提供的预配置 IDE 项目之一来构建运行时库。这些可以在 <C/C++test_runtime_root>/projects
中找到。(可选)您可以自己创建一个 IDE 项目。
构建运行时库涉及选择通信通道,然后在包含 Makefile 的目录中运行 IDE 构建器或 Make。如果默认配置导致问题,或者您的编译器和目标平台没有默认配置,则可能还需要更改编译器和特定于平台的配置(请参见 Configuring the C++test Runtime Library)。
自动构建
以下测试执行步骤应用于自动构建 C/C++test 运行时:
<BuildRuntimeLibStep additionalFlags="<build options>" />
该执行步骤将使用被测试项目的环境(编译器可执行文件,构建选项)编译在 C++ test 运行时库源位置中找到的所有源文件。然后将已编译的对象链接到测试可执行文件中。additionalFlags
属性是可选的,可用于指定其他构建选项。
准备自定义版本
选择通信通道
手动构建运行时库的第一步是选择运行时将使用的通信通道实现之一。以下通信通道实现位于 C/C++test 运行时分发版中:
- 文件通讯:
- src/transport/CppTestTransportFille.c
- src/transport/CppTestTransportFileSplit.c
- src/transport/CppTestTransportFileBuffered.c
- TCP/IP 套接字:
- src/transport/CppTestTransportUnixSocket.c: 基于 Unix 套接字的通信通道
- src/transport/CppTestTransportWinSocket.c: 基于 Windows 套接字的通信通道
- Serial link (rs232):
- src/transport/CppTestTransportRS232Common.c
- src/transport/CppTestTransportRS232Common.h
- src/transport/CppTestTransportRS232Unix.c: 基于 Unix 串行接口 API 的通讯通道
- src/transport/CppTestTransportRS232Win32.c: 基于 Windows 串行接口 API 的通讯通道
- src/transport/CppTestTransportRS232STM32F103ZE.c: STM32F103 MCU UART 的通信通道
您可以通过在'make'命令行中添加适当的 CHANNEL_TYPE 参数来选择通信通道的实现:
- CHANNEL_TYPE=file: 选择基于文件的通信(默认)
- CHANNEL_TYPE=file-buffered: 通过缓冲的写操作选择基于文件的通信
- CHANNEL_TYPE=unix-socket: 选择基于 Unix 套接字的通信
- CHANNEL_TYPE=win-socket: 选择基于 Windows 套接字的通信
- CHANNEL_TYPE=win-rs232: 选择 Windows 串行接口通讯
- CHANNEL_TYPE=unix-rs232: 选择 Unix 串行接口通讯
- CHANNEL_TYPE=stm32f103ze-rs232: 选择 STM32F103 MCU uart 通信
或者,如果使用 IDE 而不是 make 工具,则可以将以下定义之一添加到编译器选项中
- CPPTEST_USE_FILE_COMMUNICATIONS
- CPPTEST_USE_FILE_BUFFERED_COMMUNICATION
- CPPTEST_USE_UNIX_SOCKET_COMMUNICATION
- CPPTEST_USE_WIN_SOCKET_COMMUNICATION
- CPPTEST_USE_RS232_WIN_COMMUNICATION
- CPPTEST_USE_RS232_UNIX_COMMUNICATION
- CPPTEST_USE_RS232_STM32F103ZE_COMMUNICATION
- CPPTEST_USE_CUSTOM_COMMUNICATION
使用 Make 构建 C/C++test 运行时库
在包含 Makefile 的目录中调用 make
命令,将使用 gcc 编译器编译运行时源,并使用 ar 库工具创建 C/C++test 运行时库。要更改编译器和库工具,您需要在 Make 命令行中指定目标配置。示例:
make TARGET_CFG=WR_DKM_gcc3_4_simlinux_VxWorks6_4.mk
C/C++test 运行时分发版(在 <C++test_runtime_sources>/target/目录中)提供以下配置:
- ARM_armcc1_2_ADS1_2.mk
- ARM_armcc3_0_RVDS3_0.mk
- ARM_armcc3_1_RVDS3_1.mk
- ARM_armcc3_1_uV3.mk
- ARM_armcc4_0_RVDS4_0.mk
- ARM_armcc5_0.mk
- ICCARM5_3.mk
- MSMobile.mk
- QNX_2_9.mk
- QNX_3_3.mk
- QNX_4_2.mk
- QNX_4_4.mk
- ST20_os20.mk
- ST40_os21.mk
- TIARM_4.9.mk
- TIARM_5.1.mk
- TIARM_5.1_eabi.mk
- TIARM_5.1_gcc.mk
- TIC2000_4.1.mk
- TIC2000_5.2.mk
- TIC6000_5.1.mk
- TIC6000_6.0.mk
- WR_DKM_dcc5_5_simlinux_VxWorks6_4.mk
- WR_DKM_dcc5_5_simnt_VxWorks6_4.mk
- WR_DKM_dcc5_5_simsparc_VxWorks6_4.mk
- WR_DKM_dcc5_6_simlinux_VxWorks6_6.mk
- WR_DKM_dcc5_6_simnt_VxWorks6_6.mk
- WR_DKM_dcc5_6_simsparc_VxWorks6_6.mk
- WR_DKM_gcc3_4_simlinux_VxWorks6_4.mk
- WR_DKM_gcc3_4_simnt_VxWorks6_4.mk
- WR_DKM_gcc3_4_simsparc_VxWorks6_4.mk
- WR_DKM_gcc4_1_simlinux_VxWorks6_6.mk
- WR_DKM_gcc4_1_simnt_VxWorks6_6.mk
- WR_DKM_gcc4_1_simsparc_VxWorks6_6.mk
- WR_RTP_dcc5_5_simpentium_VxWorks6_4.mk
- WR_RTP_dcc5_5_simsparc_VxWorks6_4.mk
- WR_RTP_dcc5_6_simpentium_VxWorks6_6.mk
- WR_RTP_gcc3_4_simpentium_VxWorks6_4.mk
- WR_RTP_gcc3_4_simsparc_VxWorks6_4.mk
- WR_RTP_gcc4_1_simpentium_VxWorks6_6.mk
- eVC4_0_arm.mk
- eVC4_0_mips.mk
- eVC4_0_sh.mk
- eVC4_0_x86.mk
- gcc-shared.mk
- gcc-static.mk
- msvc-shared.mk
- msvc-static.mk
目标配置为构建 C/C++test 运行时库时使用的以下变量提供定义:
名称 | 默认 | 说明 |
---|---|---|
CC | gcc | 用于编译 C/C++test 运行时源的编译器可执行文件。 |
CFLAGS | 编译期间使用的标志。 | |
CC_OUT_DIR_FLAG | 与用于存储编译产品的目录一起使用的标志: $(CC_OUT_DIR_FLAG)"<output-dir>" | |
CC_OUT_FLAG | -o | 与输出文件名一起使用的标志。 $(CC_OUT_FLAG)"<output-file-name>"被添加到编译器命令行。 |
OBJ_EXT | o | 创建输出文件名时使用的目标文件扩展名 |
LIBTOOL | ar | 可执行文件,可以从已编译的源创建库。 |
LIBTOOL_FLAGS | -ruv | 创建 C/C++test 运行时库时与 lib 工具一起使用的标志 |
LIBTOOL_OUT_FLAG | 与输出文件名一起使用的标志。将 $(LIBTOOL_OUT_FLAG)"<output-file-name>" 添加到 lib 工具命令行中。 | |
LIB_PREFIX | lib | 这些变量在创建 C++test 运行时库名称时使用: $(LIB_PREFIX)$(LIB_NAME).$(LIB_EXT) |
LIB_NAME | cpptestruntime | |
LIB_EXT | a |
LD、LDFLAGS、LD_OUT_FLAG 和 OUT_EXT 也由可用配置定义,但它们不是构建 C/C++test 运行时库所必需的。仅当调用 Makefile 中的 测试
目标时,它们才用于构建简单的测试可执行文件。
要创建自己的目标配置,请复制最能描述您目标的现有配置,然后根据需要进行修改。要使用新的目标配置构建 C/C++test 运行时库,请将 TARGET_DIR 参数添加到 'make’命令行:
make TARGET_DIR=<directory with my target configuration> TARGET_CFG=MyTargetConfig.mk
您还可以更改在其中创建运行时库的目录(默认情况下,它设置为 ./build 目录)。要更改此设置,请将 OUT_DIR 参数添加到 Make 命令行中。示例:
make OUT_DIR=<output directory for your C/C++test runtime library> ...
您可以在安装 C/C++test 的位置执行构建,也可以复制 C/C++test 运行时源文件并在不同位置构建它们。在这种情况下,请记住调整 C++test 包含的路径(存储在 <C/C++test_includes> 中)。为此,请将 make 文件中的 CPPTEST_INC_DIR 变量的值修改为绝对路径。示例:
CPPTEST_INC_DIR=/usr/local/<CPPTEST_INSTALL_DIR>/engine/runtime/include
配置 C/C++test 运行时库
由于不同的目标平台有不同的限制,C/C++test 运行时库被设计为易于配置以适应不同的环境。可以配置 C/C++test 运行时库——主要是借助可用的宏定义。如果您的目标有一些非标准的限制,则可能还需要对运行时源代码进行一些其他更改。
注释
用于构建运行时库的包含文件(位于 <C/C++test_includes> 中)也包含在生成的测试工具中(由 C/C++test 自动生成的测试源文件)。如果需要修改这些文件,请格外小心。即使是很小的错误也可能导致测试工具编译失败。通常使用预处理器条件指令(#ifdef...#endif)引入特定于目标的修改是安全的。
可用的编译器配置位于 <C/C++test_includes>/config/
目录中。C/C++test 包含目录中还有一个 cpptest_portinfo.h
头文件,该头文件确定在构建 C++test 运行时库时应使用哪种编译器配置。编译器配置头文件定义了一组宏,这些宏使运行时适合目标平台。它还可以定义禁用某些目标平台不支持的 C/C++test 功能的宏。可以禁用的功能的完整列表可在cpptest_features.h
头文件中找到。
在大多数情况下,如果您需要更改某些配置宏的值,则无需修改或创建新的配置文件。可以将适当的 -D 选项添加到目标配置文件中的 CFLAGS 变量中(如果使用 IDE 构建运行时,则添加到编译器选项中),这些选项将给定宏的值设置为所需值。
下表列出了可用的通用配置定义(请注意,指定的默认值取决于特定的编译器和目标环境):
名称 | 详情 |
---|---|
CPPTEST_EXPORT, CPPTEST_IMPORT | 在为 Windows 平台构建 DLL 时,它们会扩展为__declspec(dllexport) __declspec(dllimport)、Microsoft-specific 扩展,用于向 DLL 导入功能和从 DLL 导出功能。 |
CDECL_CALL | 使用 Microsoft 编译器进行构建时,它会扩展为 __cdecl Microsoft 特定的调用约定扩展。 |
CPPTEST_WCHAR_ENABLED | 如果定义为 1,则将在支持 wchar 类型的情况下构建运行时库。定义为 0 时,将构建不支持 wchar 类型的 C++test 运行时库。 |
CPPTEST_SETJMP_ENABLED | 如果定义为 1,则在执行测试用例期间抛出异常时,将使用信号处理例程进行恢复。在这种情况下,C++test 记录异常并尝试继续执行测试用例。 |
CPPTEST_USE_ANSI_SETJMP | 如果定义为 1,则以下功能用于信号处理:longjmp、setjmp。如果为 0,则使用 siglongjmp 和 sigsetjmp。并类似地使用数据类型:sigjmp_buf 与 jmp_buf。请注意,您需要将 CPPTEST_SETJMP_ENABLED 设置为 1,CPPTEST_USE_ANSI_SETJMP 才能生效。 |
CPPTEST_USE_UNCAUGHT_EXCEPTION_CHECKING | 如果定义为 1,则 uncaught_exception 函数用于未捕获的异常处理。 |
CPPTEST_USE_STD_NS | 当 C/C++test 不应该使用 std 命名空间或编译器不支持命名空间时,定义为 0。 |
CPPTEST_TIME_MODE | 该宏控制用于时间测量的功能。允许值的列表可在 cpptest_time.h 头文件中获取。 |
下表列出了可用的功能配置定义:
名称 | 详情 |
---|---|
CPPTEST_C_STREAMS_REDIRECT_ENABLED | 如果定义为 1,则启用 c 流 (stdin, stdout, stderr)重定向。 |
CPPTEST_CPP_STREAMS_REDIRECT_ENABLED | 如果定义为 1,则启用 cpp 流重定向 |
CPPTEST_USE_WSTREAMS | 如果定义为 1 ,则使用 wcin、wcout、wcerr、wclog 代替 cin、cout、cerr 和 clog。请注意,您需要将 CPPTEST_CPP_STREAMS_REDIRECT_ENABL ED 设置为 1,CPPTEST_USE_WSTREAMS 才能生效。 |
CPPTEST_EXCEPTIONS_ENABLED | 如果定义为 1,则启用异常处理。 |
CPPTEST_SPECIAL_STD_EXCEPTIONS_HANDLING_ENABLED | 如果定义为 1,则将 std::exception 与其他异常分开处理。请注意,您需要将 CPPTEST_EXCEPTIONS_ENABLED 设置为1, CPPTEST_SPECIAL_STD_EXCEPTIONS_HAN DLING_ENABLED 才能生效。 |
CPPTEST_DATA_SOURCES_ENABLED | 如果定义为 1,则启用数据源。 |
CPPTEST_CSV_DATA_SOURCE_ENABLED | 如果定义为 1,则启用 csv 数据源。 |
CPPTEST_USE_SETUP_FOR_C_SUITES | 如果定义为 1,则 c 套件允许使用 setUp 和 tearDown 函数。 |
CPPTEST_THREADS_ENABLED | 如果定义为 1,则启用对线程的支持。 |
通讯方式
本节内容包括:
文件通信通道
文件通信通道的实现
文件通信通道利用标准文件 I/O 操作来保存测试结果。有两种数据流:一种用于测试结果,另一种用于覆盖率结果。该实现包含三个变体:
- src/transport/CppTestTransportFile.c: 使用纯文件 I/O 写入。
- src/transport/CppTestTransportFileSplit.c: 通过普通文件 I/O 写入,可将数据拆分为具有可配置最大文件大小的一系列文件
- src/transport/CppTestTransportFileBuffered.c - 具有缓冲的写操作。
在第一种模式(CppTestTransportFile.c)中,测试过程中产生的每个数据包都会立即保存到文件中。在这种模式下,操作系统将决定何时执行实际的物理写入。
第二种模式(CppTestTransportFileSplit.c)与第一种模式相似,因为它也使用普通文件 I/O 写入。但是在 CppTestTransportFileSplit.c 模式下,数据包将保存到一系列文件中。通过使用 CPPTEST_MAX_ALLOWED_NUMBER_OF_BYTES_PER_FILE 宏设置一个值来配置每个文件的最大大小。默认值是 2000000000 字节(2 GB)。产生的文件是按顺序命名的,例如:'cpptest_results.clog', 'cpptest_results.clog.0001', 'cpptest_results.clog.0002'.有关将生成的结果文件加载到 C++test 中的信息,请参见 ReadDynamicCoverageStep 和 ReadTestLogStep 测试执行流步骤的描述。
在第三种模式(CppTestTransportFileBuffered.c)中,引入了中间存储器缓冲区以减少写入小数据包的频率。此模式应用于这样的环境,在该环境中,执行小数据块的多次写入要比写入合并的较大数据部分更为费劲。您可以使用 FILE_COMMUNICATION_BUFFER_SIZE 定义来确定中间缓冲区的大小。缓冲区大小越大,写操作将越不频繁。
套接字通信通道
套接字通信通道的实现
套接字通信通道利用 TCP/IP 套接字保存测试结果。打开了两个套接字:一个用于发送测试结果,另一个用于发送覆盖结果。有两种可用的实现:
- src/transport/CppTestTransportUnixSocket.c: 对于基于 Unix/Linux 的系统。
- src/transport/CppTestTransportWin32Socket.c: 对于基于 Windows 的系统。
套接字监听器
通过 TCP/IP 套接字从目标发出的数据应在套接字监听器的帮助下捕获。监听器是一个随 C/C++test 一起附带的简单实用程序。监听器位于 <C/C++test_runtime_root>/listeners/socket_listener,监听器接受以下参数:
名称 | 详情 |
---|---|
-cl, --channel port_number@log_file | 通信通道规范。有关用于监听结果的端口号和用于保存在此端口上捕获的数据的文件的信息。 |
-sf, --sync_file filename | 将用于同步的文件的路径。监听器将使用此路径来创建两个“同步文件”:
|
-to, --timeout timeout (几秒内) | 等待结果超时。如果超出此范围,程序将停止。 |
--help | 显示帮助信息。 |
RS232 通信通道
串行接口通信通道实现
串行接口通信模块设计用于处理仅串行通信可用的设备的测试结果传输。该通信的实现包括两个部分:
- 公用层:负责数据打包、制定框架和验证传输正确性。CppTestTransportRS232Common.c 和 CppTestTransportRS232Common.h 文件中提供了该实现。
- 指定目标部分:负责与物理 COM 端口进行交互。包含设置和发送功能的实现。C++test 为基于 Windows 的目标和基于 Unix 的目标提供了该层的示例实现; 它还为 STM32103ZE Cortex-M3 芯片(Keil uVision3)提供了一个简单的裸机实现。
原始和安全的通信模式
有两种可用的通信模式:
- 原始模式:在这种模式下,数据无需任何验证即可发送到主机。建议在稳定的环境中使用。
- 安全:在这种模式下,将为每个数据包计算校验和。如果校验和不正确,则停止传输。通过添加编译标志 - DCPPTEST_RS232_SAFE_MODE=1 激活此模式。
通过串行链路发送的数据被分成多个包。软件包如下所示。这是“原始”模式的框架示例:
这是“安全”模式的框架示例:
这是所用符号的描述:
符号 | 说明 |
---|---|
STX (0x02) | 文本开头 |
ETX (0x03) | 文本结束 |
EOT (0x04) | 传输结束 |
ENQ (0x05) | 查询 |
ACK (0x06) | 肯定应答 |
NAK (0x15) | 否定应答 |
在“安全”模式下,校验和使用异或运算。对于"原始"模式,不计算校验和,并发送所有帧的零值。
默认的最大数据量设置为 250 个字节。可以使用 MAX_PACKET_SIZE 宏来更改此值。
传输流程
在“安全模式”下,客户端发送 ENQ 来查询可用性。直到收到 ACK,它才能开始传输。客户端收到 ACK 后,它将发送另一个帧。主机通过 ACK 确认每个帧。最后,客户端发送 EOT。作为响应,主机发送一个 ACK 以完成传输。 校验和仅在安全模式下计算。在正常模式下,它始终为 0。
在“原始”模式下,传输仅是一种方式。目标平台无需等待任何数据发送阶段的 ACK 就可以发射数据。
添加新的特定于平台的串行接口通信实现
为了添加串行接口通信的另一种实现,需要完成以下步骤:
在 <C/C++test_runtime_root>/src/transport 目录中添加一个新文件,以实现自定义串行通信。请遵循以下模板:
#define CPPTEST_RUNTIME_IMPLEMENTATION #include "cpptest_portinfo.h" #ifdef CPPTEST_USE_RS232_MYPLATFORM_COMMUNICATION #include "CppTestTransportRS232Common.h" int localRsInitInternalSerial(CppTestStreamParameters *par) { return RS_OK; } int localRsUninitInternalSerial(CppTestStreamParameters *par) { return RS_OK; } int localRsSendInternalByte(CppTestStreamParameters *par, unsigned char byte, unsigned char *is_send) { return RS_OK; } int localRsSendInternalStr(CppTestStreamParameters *par, unsigned char *bytes, int *nBytes) { return RS_OK; } int localRsRecvInternalByte(CppTestStreamParameters *par, unsigned char *pByte, unsigned char *is_recv) { return RS_OK; } int localFlushInternalRS(CppTestStreamParameters *par) { return RS_OK; } void localSetStop(int *stop_bit, int result) { } void localSetParity(int *parity, char *result) { } void localRsSleep(unsigned int msec) { } #endif
- 提供以下功能的实现:
- int localFlushInternalRS(CppTestStreamParameters *par);
刷新内部串行端口缓冲区。CppTestStreamParameters 如下所述。 - int localRsInitInternalSerial(CppTestStreamParameters *par);
初始化串行端口。 - localRsSendInternalByte(CppTestStreamParameters *par, unsigned char byte, unsigned char *is_send);
发送一个字节。参数为 par(如下所述),要发送的字节和结果。 - int localRsSendInternalStr(CppTestStreamParameters *par, unsigned char bytes, int *nBytes);
发送 nBytes 个字节。参数为 par(如下所述),要发送的字节和已发送的 nByte。 - int localRsRecvInternalByte(CppTestStreamParameters *par, unsigned char *pByte, unsigned char *is_recv);
接收一个字节。参数为 par(如下所述),接收的字节结果。 - int localRsUninitInternalSerial(CppTestStreamParameters *par);
关闭串行接口。 - void localSetStop(int *stop_bit,int result);
设置停止位发送参数。 - void localSetParity(int *parity, char *result);
设置奇偶校验传输参数。 - char *localGetErrorText(void);
返回带有 ErrorText 的缓冲区(如果有)。 - void localRsSleep(unsigned int msec);
实现 Sleep 。
- int localFlushInternalRS(CppTestStreamParameters *par);
Struct CppTestStreamParameters: typedef struct { char serial_device[16]; Device name (COM1, /dev/ttyS0, cua0 etc). Depend on platform int baud_rate; Device speed int byte_size; Byte size int parity; Parity int stop_bit; Stop bit int timeout; Timeout between two operations. long max_timeout; If exceeded tranmision broken. } CppTestStreamParameters;
将新的实现与运行时库集成
要将新的实现与运行时库集成在一起:
- 在
通道
子目录中,插入一个名为myplatform-rs232.mk
的新文件。在此新文件中,添加以下行:"CHANNEL_CONFIG_MACRO=-DCPPTEST_USE_RS232_MYPLATFORM_COMMUNICATION"
在
include/cpptest_portinfo.h
文件中,替换为:#if !defined(CPPTEST_USE_FILE_COMMUNICATION) && \ !defined(CPPTEST_USE_FILE_BUFFERED_COMMUNICATION) && \ ... !defined(CPPTEST_USE_RS232_STM32F103ZE_COMMUNICATION) && \ ... !defined(USE_CUSTOM_COMMUNICATION_CHANNEL) # define CPPTEST_USE_FILE_COMMUNICATION #endif
用
#if !defined(CPPTEST_USE_FILE_COMMUNICATION) && \ !defined(CPPTEST_USE_FILE_BUFFERED_COMMUNICATION) && \ ... !defined(CPPTEST_USE_RS232_STM32F103ZE_COMMUNICATION) && \ !defined(CPPTEST_USE_RS232_MYPLATFORM_COMMUNICATION) && \ ... !defined(USE_CUSTOM_COMMUNICATION_CHANNEL) # define CPPTEST_USE_FILE_COMMUNICATION #endif
- 使用参数
CHANNEL_TYPE=myplatform-rs232.
构建库 - 如果使用“运行时库自动生成”步骤,请执行以下一项操作:
- 将
-DCPPTEST_USE_RS232_MYPLATFORM_COMMUNICATION
添加到 C++test 项目中的编译器标志中。 - 修改【运行时自动构建】步骤的测试执行 Flow,以包括标志
<BuildRuntimeLibStep
additionalFlags="-DCPPTEST_USE_RS232_MYPLATFORM_COMMUNICATION
" />
- 将
此 RS232 监听器
通过串行链接从目标发出的数据应在串行端口监听器的帮助下进行捕获。监听器是一个 C/c++test 一起附带的简单实用程序。监听器位于 <C/C++test_runtime_root>/listeners/rs232_listener,监听器接受以下参数:
参数 | 说明 |
---|---|
-d (--device) COM,SPEED,PARIT Y,STOP,BYTE_SIZE。 | 已用设备。例如 -d 1,19200,N,1,8 。我们使用 COM1 端口,速率为 19200,无奇偶校验,一个停止位和 8 字节大小。 |
-sf (--syncfile) <sync file> | 要同步的文件名 |
-cn (--channel) number<mode>@<fil e path> | 通信通道。C++test 使用两个通道的 -test 日志和覆盖率日志。该模式可以是二进制的 'b' 或文本的 't’(默认) |
-to (--timeout) <timeout in second> | 等待结果的时间。如果超出此范围,程序将停止。 |
-fi <file_name> | 文件模式。从二进制文件中读取结果。所有 RS232 设置将被忽略。 |
-rm (--rawmode) | 原始模式(无 ACK 和校验和)。如果在非安全模式下使用传输,则需要此选项。 |
-v (--verbose) | 详细模式。 |
根据运行模式(安全或原始),监听器可能会或可能不会计算传输校验和并发送 ACK。
初始化和完成
仅在正确初始化运行时库的情况下,才对在测试或应用程序执行期间传递给运行时库的所有数据进行处理,解释并传递给通信流。如果运行时库未初始化或尚未完成、则将忽略诸如覆盖率、单元测试消息,断言和运行时违规之类的数据。
在第一次调用 CppTest_InitializeRuntime() 函数期间会初始化运行时库,该函数将初始化运行时库模块并打开消息和覆盖率数据的通信通道。默认情况下,尽快调用 CppTest_InitializeRuntime()函数。在包含 C++ 代码的项目中,此调用是在调用全局对象的构造函数之前进行的。在 C 项目中,此函数在 main() 函数的开头调用。在第一次调用 CppTest_FinalizeRuntime() 函数期间,运行时库将完成,该函数将确定运行时库模块并关闭通信通道。在调用全局对象析构函数之后,将自动调用此函数。在 C 项目中,它在退出 main() 函数之前被调用。
您可以实现两个特殊功能,以将自定义初始化和完成代码贡献给测试工具执行:
void CppTest_Initialize(void)
该函数在 CppTest_InitializeRuntime 函数的开头调用,甚至在 C/C++test 运行时库模块初始化之前调用。
void CppTest_Finalize(void)
该函数在 CppTest_FinalizeRuntime 结束时在测试结果通信通道关闭后调用。
如果您的项目需要执行早期初始化代码,例如特定于硬件的初始化代码(例如禁用看门狗定时器)或任何其他类型的预计在执行序列中很早发生的初始化,通常会使用这些函数。类似地终结代码
CppTest_Initialize/Finalize 在单元测试和应用程序监视中的用法
运行单元测试时,原始项目中存在的初始化代码将在执行时被省略,因为原始应用程序入口点(通常是主函数)被 C/C++test 替换为自动生成的测试工具入口点。这就是为什么可能需要通过 CppTest_Initialize/Finalize函数钩住初始化/完成代码的原因。
相比之下,在应用程序内存监控模式下,通常不需要以 C/C++test 特定函数的形式提供硬件初始化代码。这是因为应该为此调用原始的初始化代码,因为 C/C++test 并没有替换应用程序监测模式下的应用程序入口点。但是,如果您确实需要在应用程序监控模式下执行特定于 C/C++test 的初始化/终结,则可以以相同的方式使用 CppTest_Initialize/Finalize 函数。
添加 CppTest_Initialize 和 CppTest_Finalize 函数
CppTest_Initialize 和 CppTest_Finalize 函数可以直接添加到您的项目中。您也可以将它们放置在不属于您的项目的源文件中。源文件必须放在一个专用目录中,该目录不是原始项目的一部分,并且与测试配置中指定的位置之一匹配:
- 打开测试配置。
- 选择 执行> 符号 选项卡。
- 在 使用以下位置的文件中的其他符号: 字段中,指定包含源文件的文件夹。
- 点击 应用。
当提供此函数的定义时,C/C++test 将在测试准备期间检测它并在测试可执行文件启动的早期生成对它的调用。
必须为经测试的源和其他源启用桩函数插桩:
创建 CppTest_Initialize 和 CppTest_Finalize 框架
C++test 附带一个专用向导,用于自动安装 CppTest_Initialize 和 CppTest_Finalize 函数框架。如果需要,用户仍然可以手动添加这些功能。
要访问“运行时-自定义初始化 & 终止化”向导:
- 选择文件 > 新建 > 其他。
- 选择 C++test > 运行时 - 自定义初始化 & 终止化 然后单击 下一步。
- 在提供的字段中指定源文件名和位置。向导应与首选测试配置设置中使用以下位置的文件提供的额外符号: (请参阅 添加 CppTest_Initialize 和 CppTest_Finalize 函数)。
- 从下拉菜单中选择文件类型(C 或 C++),然后单击 完成。
应用设置将在指定位置生成源文件。新文件将包含以下空定义:
- void CppTest_Initialize(void)
- void CppTest_Finalize(void)
然后,您可以使用自定义的初始化和终止化代码来扩展这些功能。
提示
- 如果运行时库初始化太早,从而导致应用程序监测问题,则可以使用高级选项 testrunner.earlyRuntimeInitialization(有关详细信息,请参阅 高级插桩配置选项)并在源代码适当位置调用 CppTest_InitializeRuntime() 来禁用自动运行时库初始化。我们建议使用 #ifdef PARASOFT_CPPTEST 保护调用。
- 要尽早确定运行时库,可以直接在源代码中调用 CppTest_FinalizeRuntime()。调用此函数后诸如覆盖率、单元测试消息、断言和运行时违规之类的数据将被忽略。
C/C++test 运行时库使用的符号
C/C++test 运行时库使用以下外部符号:
- close
- dup
- dup2
- exit
- fclose
- fflush
- fopen
- fprintf
- fputc
- free
- fwrite
- getenv
- malloc
- memcmp
- memcpy
- memset
- mkstemp
- open
- perror
- pthread_exit
- pthread_mutex_destroy
- pthread_mutex_init
- pthread_mutex_lock
- pthread_mutex_unlock
- pthread_self
- read
- siglongjmp
- signal
- sprint
- stdout
- strcmp
- strcpy
- strlen
- strncmp
- strstr
- tolower
- vprintf
- vsprintf
- write
注意
- 如果将 "CPPTEST_USE_ANSI_SETJMP”定义设置为 1,则将从系统库中引用以下符号:
- longjmp
- setjmp
- 如果将 "CPPTEST_USE_ANSI_SETJMP” 定义设置为 0,那么将使用下面列出的符号代替:
- siglongjmp
- sigsetjmp
- 如果将"CPPTEST_TIME_MODE”定义设置为 CPPTEST_TIME_ANSI,则将从系统库中引用以下符号:
- time
- 如果将 "CPPTEST_TIME_MODE”定义设置为 CPPTEST_TIME_GETTIMEOFDAY,则将从系统库中引用以下符号:
- gettimeofday
- 如果将 "CPPTEST_TIME_MODE” 定义设置为 CPPTEST_TIME_GETTIMEOFDAY,则将从系统库中引用以下符号:
- ftime
- 如果将 "CPPTEST_TIME_MODE” 定义设置为 CPPTEST_TIME_TICKLIB,则将从系统库中引用以下符号:
- tickGet
- sysClkRateGet
- 如果定义了''CPPTEST_USE_FILE_COMMUNICATION"或"CPPTEST_USE_FILE_SPLIT_COMMUNICATION",将从系统库中引用以下符号:
- fopen
- fclose
- fputc
- fwrite
- fflush
- 如果定义了''CPPTEST_USE_UNIX_SOCKET_COMMUNICATION",将从系统库中引用以下符号:
- socket
- gethostbyname
- htons
- inet_addr
- connect
- close
- send
- 如果定义了"CPPTEST_USE_WIN_SOCKET_COMMUNICATION",将从系统库中引用以下符号:
- WSAStartup
- socket
- gethostbyname
- htons
- inet_addr
- connect
- closesocket
- shutdown
- WSACleanup
- send
- 如果定义了"CPPTEST_C_STREAMS_REDIRECT_ENABLED"或"CPPTEST_CPP_STREAMS_REDIRECT_ENABLED",将从系统库中引用以下符号:
- dup
- dup2
- _get_osfhandle
- perror
- strstr
- unlink
- write
- open
- close
- GetTempFileName (_WIN32)
- GetTempPath (_WIN32)
- mkstemp (!_WIN32)