本主题说明如何构建和使用 C++test 运行时库。

为了使用 C++test 在主机(安装 C++test 的环境)以外的平台上进行测试,必须使用交叉编译器构建。如果计划仅在主机上运行测试,则不需要构建 C++test 运行时库(因为 C++test 附带了用于基于主机的测试的预构建库)。

C++test 可以在可执行测试的准备阶段中自动构建运行时库。除非您要准备 C++test 运行时库的自定义版本,否则不需要手动准备 C++test 运行时库。

内容包括:

辅助关键字

在整个主题中,辅助关键字用于表示完整路径。这些帮助辅助关键字的定义如下:
<C++test_runtime_root> = <C++test Install Dir>/engine

<C++test_runtime_sources> = <C++test Install Dir>/engine/runtime/src

<C++test_includes> = <C++test Install Dir>/engine/runtime/include

说明

C++test 运行时库以C源代码和头文件的形式随 C++test 安装一起分发。运行时库的源代码位于上述框中引用的目录中

在大多数情况下,您可以让 C++test 自动构建运行时库。如果需要,可以使用 make 实用程序和支持的平台的预配置 make 配置之一来构建运行时库。 (请参见 Building the C++test Runtime Library with 'make')。C++test 提供了特殊的项目文件,这些文件有助于为受用的 IDE 构建运行时库。

请注意,需要为每个目标构建离散版本的运行时库。因此,如果您的项目是为多个体系结构构建的,那么很可能需要构建一个多个版本的 C++test 运行时库(每个体系结构一个)。

运行时库源包括所有正式支持的嵌入式平台的配置宏以及基于功能的较低级别的配置。需要在 IDE 中为构建配置正确设置这些宏。

以下步骤描述了常用方法:

  1. 使用提供的 makefile 或位于其中的预配置 IDE 项目之一来构建运行时库。 <C++test_runtime_root>/runtime/projects.
  2. 将生成的 .a 文件添加到 Project Properties> C++test> Build Options> Linker Option
    • 使用绝对路径,或者如果运行时库在同一工作空间中,请使用 ${workspace_loc} 和 ${project_loc} 变量。

    • 最好的选择是将库文件放置在某个固定位置,以便多个用户无需更改即可指向该文件。
    • 还支持将常规环境变量用于运行时库。

有关运行时库的常规信息

C++test 的工具引用了许多在测试对象链接期间必须解析的符号。这些符号在 C++test 运行时库中提供。

C++test 附带一个预构建的全功能运行时共享库。然而,这个运行时是为富主机平台设计的。考虑到可能在其上进行测试的众多嵌入式平台,以及它们的功能和局限性,通常需要在针对不同的嵌入式环境构建运行时间之前对其进行调整。这就是为什么还提供运行时库的 pure-C 源代码的原因。

可以将库配置为支持目标平台上可用的功能,或阻止那些不可用的功能。默认配置是全功能的,但是您可能需要阻止麻烦的功能,尤其是在遇到编译时或运行时崩溃的情况下。嵌入式开发人员熟悉他们使用的平台的优缺点,并且应该能够构建适当配置的库并将其路径附加到链接器命令行。

运行时库的源可从 <C++test_runtime_sources> (<C++testInstallDir>/<C++test Install Dir>/engine/runtime/src)获取。构建运行时库所需的头文件位于 <C++test_includes> ( <C++test Install Dir>/engine/runtime/include )中。

例如,在 Windows C++test 7.3 发行版中,运行时源代码位于:

C:\Program Files\ParaSoft\C++test7.3\engine\runtime\src

相应的包含文件将位于:

C:\Program Files\ParaSoft\C++test7.3\engine\runtime\include

修改来源-最佳做法

切勿在 <C++test Install Dir>中修改文件。而是在修改源之前将源复制到其他目录中。然后,在 C++test 【项目选项】面板的【运行时库源】选项中指定此新路径(有关详细信息,请参阅 C++test 项目或文件选项面板中的指定选项)。自动化运行时库构建功能将使用此目录来构建库,如Building the C++test Runtime Library中所述。

了解运行时分发结构和内容

C++ test 运行时发行版由放置在
<C++test_runtime_sources> 目录中的以下子目录或文件组成:

  • src/: 包含 C 源文件。
  • 侦听器/: 包含一个套接字和串行接口侦听器,作为可与给定通信通道一起使用的简单实用程序。
  • 目标/:包含一组目标配置
  • 测试/:包含一项快速测试。
  • 生成文件:用于构建运行时库的生成文件。

C 源代码分为几个部分,由以下子目录或文件表示:

  • src/common/: 用于字符串操作等的通用实用程序功能。
  • src/transport/: 通信通道的实现。
  • src/presentation/CppTestMessagePlain.c: 纯文本层,用于结果报告。
  • src/: 测试用例执行工具。
  • src/CppTestCoverage.c: 用于处理覆盖率报告的实用程序功能。

在目标目录中,有多种目标配置可用于各种平台、体系结构和编译器。目标配置定义生成文件用来编译运行时源文件(例如 CC、CFLAGS 等)的变量,以及 LIBTOOL、LIBTOOL_FLAGS 等变量,生成文件使用这些变量从已编译的源创建运行时库(请参见 使用 使用 'make’ 构建 C++ test 运行时库)。

构建 C++ test 运行时库

总览

C++ test 可以在可执行测试的准备阶段中自动构建测试运行时。建议使用此方法。在大多数情况下,不需要手动准备 C++test 运行时库。

在某些情况下,您可能需要准备 C++test 运行时库的自定义版本。您可以使用 <C++test_runtime_sources> 目录中的生成文件构建 C++ test 运行时库。您还可以使用提供的预配置 IDE 项目之一来构建运行时库。 这些在 <C++test_runtime_root>/runtime/projects 中可用。(可选)您可以自己创建一个 IDE 项目

基本上,构建运行时库涉及选择通信通道,然后在包含生成文件的目录中运行 IDE 构建器或 'make’ 。如果默认配置导致问题,或者您的编译器和目标平台没有默认配置,则可能还需要更改编译器和特定于平台的配置(请参见 Configuring the C++test Runtime Library)。

自动构建

以下测试执行步骤应用于自动构建 C++ test 运行时:

<BuildRuntimeLibStep additionalFlags="<build options>" />

该执行步骤将使用被测试项目的环境(编译器可执行文件,构建选项)编译在 C++ test 运行时库源位置中找到的所有源文件。然后将已编译的对象链接到测试可执行文件中。 additionalFlags 属性是可选的,可用于指定其他构建选项。

重要说明-从构建设置中删除运行时库

在 C++ test 自动构建单元测试运行时之前(作为测试执行流的一部分),请确保从 Build Settings> Linker 选项中删除了 C++ test 运行时库。

准备自定义版本

选择通信通道

手动构建运行时库的第一步是选择运行时将使用的通信通道实现之一。以下通信通道实现在 C++ test 运行时发行版中:

  • 文件通讯:
    • src/transport/CppTestTransportFille.c
    • src/transport/CppTestTransportFileSplit.c
    • src/transport/CppTestTransportFileBuffered.c
  • TCP/IP sockets:
    • src/transport/CppTestTransportUnixSocket.c: 基于 Unix sockets 的通信通道
    • src/transport/CppTestTransportWinSocket.c: 基于 Windows sockets 的通信通道
  • 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=file-split: 选择基于文件的通信,将数据分成一系列可配置的最大大小的数据。
  • CHANNEL_TYPE=unix-socket: 选择基于 Unix 套接字的通信
  • CHANNEL_TYPE=win-socket: 选择基于 Windows 套接字的通信
  • CHANNEL_TYPE=win-rs232: 选择 Windows 串行接口通讯
  • CHANNEL_TYPE=unix-rs232: 选择 Unix 串行接口通讯
  • CHANNEL_TYPE=win-stm32f103ze-rs232: 选择 STM32F103 MCU uart 通信

或者,如果使用 IDE 而不是 make 工具,则可以将以下定义之一添加到编译器选项中

  • CPPTEST_USE_FILE_COMMUNICATIONS
  • CPPTEST_USE_FILE_SPLIT_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++ test 运行时库

在包含 Makefile 的目录中调用 'make’命令,将使用 gcc 编译器编译运行时源,并使用 ar 库工具创建 C++ test 运行时库。要更改编译器和库工具,您需要在 'make’命令行中指定目标配置。示例:

     make TARGET_CFG=WR_DKM_gcc3_4_simlinux_VxWorks6_4.mk

C++ test 运行时发行版中提供以下配置 (in <C++test_runtime_sources>/target/ directory):

  • 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++ test 运行时库时使用的以下变量的定义:

命名默认说明
CCgcc编译器可执行文件,用于编译 C++ test 运行时源。
CFLAGS 编译期间使用的标志。
CC_OUT_DIR_FLAG 与用于存储编译产品的目录一起使用的标志:
$(CC_OUT_DIR_FLAG)"<output-dir>"
CC_OUT_FLAG-o与输出文件名一起使用的标志。
$(CC_OUT_FLAG)"<output-file-name>"被添加到编译器命令行。
OBJ_EXTo创建输出文件名时使用的目标文件扩展名
LIBTOOLar可执行文件,可以从已编译的源创建库。
LIBTOOL_FLAGS-ruv创建 C++ test 运行时库时与 lib 工具一起使用的标志
LIBTOOL_OUT_FLAG 与输出文件名一起使用的标志。The
$(LIBTOOL_OUT_FLAG)"<output-file-name>" 添加到 lib 工具命令行中。
LIB_PREFIXlib这些变量在创建 C++ test 运行时库名称时使用:
$(LIB_PREFIX)$(LIB_NAME).$(LIB_EXT)
LIB_NAMEcpptestruntime
LIB_EXTa

LD、LDFLAGS、LD_OUT_FLAG 和 OUT_EXT 也由可用配置定义,但是构建 C++ test 运行时库不是必需的。仅当调用 make 文件中的 'test’目标时,它们才用于构建简单的测试可执行文件。

要创建自己的目标配置,请复制最能描述您目标的现有配置,然后根据需要进行修改。要使用新的目标配置构建 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 my C++test runtime library> ...

您可以在安装 C++ test 的位置执行构建,也可以复制 C++ test 运行时源文件并在其他位置进行构建。在这种情况下,请记住调整 C++ test 包含 (存储在 <C++test_includes>中)的路径。为此,请将 make 文件中的 CPPTEST_INC_DIR 变量的值修改为绝对路径。示例:

CPPTEST_INC_DIR=/usr/local/C++test/engine/runtime/include

多线程支持

要构建具有多线程支持的自定义运行时库,请在编译器命令行中添加 "-DCPPTEST_THREADS_ENABLED=1" 。

配置 C++ test 运行时库

由于不同的目标平台具有不同的限制,因此 C++ test 运行时库旨在易于配置以适合不同的环境。可以配置 C++ test 运行时库-主要是在可用的宏定义的帮助下。如果您的目标有一些非标准的限制,则可能还需要对运行时源代码进行一些其他更改。

注意

生成的测试工具(C++ test 自动生成的测试源文件)也包括用于构建运行时库的包含文件(位于<C++ test_includes>中)。如果需要修改这些文件,请格外小心。即使是很小的错误也可能导致测试工具编译失败。通常使用预处理器条件指令(#ifdef...#endif)引入特定于目标的修改是安全的。

可用的编译器配置位于 <C++test_includes>/config/ 目录中。C++ test 包含目录中还有一个 cpptest_portinfo.h 头文件,该头文件确定在构建 C++ test 运行时库时应使用哪种编译器配置。编译器配置头文件定义了一组宏,这些宏使运行时适合目标平台。它还可以定义宏,以禁用某些目标平台不支持的 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-specific 扩展名,以用于调用约定。
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++ test 不应该使用 std 命名空间或编译器不支持命名空间时,定义为 0。
CPPTEST_TIME_MODE该宏控制用于时间测量的功能。允许值的列表在 cpptest_time.h 头文件中可用。

下表列出了可用的功能配置定义:

命名详情
CPPTEST_C_STREAMS_REDIRECT_ENABLED如果定义为 1,则启用 c streams (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 定义来确定中间缓冲区的大小。缓冲区大小越大,写操作将越不频繁。

Socket 通信通道

Socket 通信通道的实现

Socket 通信通道利用 TCP/IP 套接字保存测试结果。打开了两个 Socket:一个用于发送测试结果,另一个用于发送覆盖结果。有两种可用的实现:

  • src/transport/CppTestTransportUnixSocket.c: 对于基于 Unix/Linux 的系统。
  • src/transport/CppTestTransportWin32Socket.c: 对于基于 Windows 的系统。

Socket 监听器

通过 TCP/IP Socket 从目标发出的数据应在 Socket 监听器的帮助下捕获。监听器是 C++ test 附带的简单实用程序。它位于 <C++test install dir>/ engine/runtime/listeners/socket_listener中,并接受以下参数:

命名详情
-cl, --channel port_number@log_file通信通道规范。有关用于监听结果的端口号和用于保存在此端口上捕获的数据的文件的信息。
-sf, --sync_file filename

将用于同步的文件的路径。监听器将使用此路径来创建两个“同步文件”:

  • 侦听器初始化完成时<Sync_file>.init。
  • 当关闭来自目标的连接时<sync_file>.final。
-to, --timeout timeout (几秒内)等待结果超时。如果超出此范围,程序将停止。
--帮助显示帮助信息。

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 就可以发射数据。

添加新的特定于平台的串行接口通信实现

为了添加串行接口通信的另一种实现,需要完成以下步骤:

  1. 通过自定义串行通信的实现,在<C++test Install dir>/engine/runtime/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
  2. 提供以下功能的实现:
    • 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 。
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;

将新的实现与运行时库集成

要将新的实现与运行时库集成在一起:

  1. 通道 子目录中,插入一个名为 myplatform-rs232.mk的新文件。在此新文件中,添加以下行:
    "CHANNEL_CONFIG_MACRO=-DCPPTEST_USE_RS232_MYPLATFORM_COMMUNICATION"
  2. 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
  3. 使用参数 CHANNEL_TYPE=myplatform-rs232.构建库
  4. 如果使用【运行时库自动生成】步骤,请执行以下一项操作:
    • -DCPPTEST_USE_RS232_MYPLATFORM_COMMUNICATION添加到 C++ test 项目中的编译器标志中。
    • 修改 Runtime Auto Build 步骤的测试执行流程,以包括标志
      <BuildRuntimeLibStep
          additionalFlags="-DCPPTEST_USE_RS232_MYPLATFORM_COMMUNICATION" />

此 RS232 监听器

通过串行链接从目标发出的数据应在串行端口监听器的帮助下进行捕获。监听器是 C++ test 附带的简单实用程序。它位于 <C++test install dir>/ engine/runtime/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)

即使在初始化 C++ test 运行时库模块之前,也要在 CppTest_InitializeRuntime 函数的开始 处调用此函数。

void CppTest_Finalize(void)

关闭测试结果通信通道后,在 CppTest_FinalizeRuntime 的末尾 调用此函数。 

如果您的项目需要早期执行初始化代码,例如特定于硬件的初始化代码(例如,禁用看门狗定时器)或预期在执行序列中很早发生的任何其他类型的初始化,则通常使用这些功能。类似地终结代码

CppTest_Initialize/Finalize 在单元测试和应用程序监视中的用法

在运行单元测试时,由于将原始应用程序入口点(通常是主函数)替换为具有自动生成的测试工具入口点的 C++ test,因此将省略执行原始项目中存在的初始化代码。这就是为什么可能需要通过 CppTest_Initialize/Finalize 函数 hook 初始化/完成代码的原因。

相反,在“应用程序内存监视”模式下,通常不需要以 C++ test 特定功能的形式提供硬件初始化代码。这是因为应为此目的调用原始初始化代码,因为 C++ test 不会替换【应用程序监视】模式下的应用程序入口点。但是,如果确实需要在【应用程序监视】模式下执行指定的 C++ test 的初始化/完成,则可以以相同的方式使用 CppTest_Initialize/Finalize 函数。

添加 CppTest_Initialize 和 CppTest_Finalize 函数

CppTest_Initialize 和 CppTest_Finalize 函数可以直接添加到您的项目中。您也可以将它们放置在不属于您的项目的源文件中。源文件必须放置在专用目录中,该目录不是原始项目的一部分,并且必须与测试配置中指定的位置之一匹配:

  1. 打开测试配置。
  2. 选择 执行> 符号 选项卡。
  3. 使用以下位置的文件中的其他符号: 字段中,指定包含源文件的文件夹。
  4. 点击 应用


提供此功能的定义后,C++ test 将在测试准备过程中检测到该功能,并在测试可执行程序启动的早期阶段对其进行调用。

必须为“经测试的源”和“其他源”启用存根检测:

创建 CppTest_Initialize 和 CppTest_Finalize 框架

C++ test 附带了一个专用向导,用于自动安装 CppTest_Initialize 和 CppTest_Finalize 功能框架。如果需要,用户仍然可以手动添加这些功能。

要访问“运行时-自定义初始化和完成”向导:

  1. 选择 File > New > Other
  2. 选择 C++test > Runtime - Custom initialization & finalization and click Next
  3. 在提供的字段中指定源文件名和位置。向导应与首选测试配置设置中使用以下位置的文件提供的额外符号: (请参阅 添加 CppTest_Initialize and CppTest_Finalize 函数)。
  4. 从下拉菜单中选择文件类型(C 或 C++),然后单击 完成

应用设置将在指定位置生成源文件。新文件将包含以下空定义:

  • void CppTest_Initialize(void)
  • void CppTest_Finalize(void)

然后,您可以使用自定义的初始化和完成代码来扩展这些功能。

提示

  • 如果运行时库初始化太早,从而导致应用程序监视问题,则可以使用高级选项 testrunner.earlyRuntimeInitialization(有关详细信息,请参阅 高级检测配置选项)并在源代码适当位置调用 CppTest_InitializeRuntime() 来禁用自动运行时库初始化。我们建议使用 #ifdef PARASOFT_CPPTEST 保护调用。
  • 要尽早确定运行时库,可以直接在源代码中调用 CppTest_FinalizeRuntime()。调用此函数后诸如覆盖率、单元测试消息、声明和运行时违规之类的数据将被忽略。

C++ test 运行时库使用的符号

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)
  • No labels