Model-driven code coverage test, device, computer equipment and storage medium

CN122985641APending Publication Date: 2026-10-27SHENZHEN SHIGUAN DIGITAL INTELLIGENCE TECH CO LTD
View PDF 0 Cites 0 Cited by

Patent Information

Application Number
CN202611370047.6
Authority / Receiving Office
CN · China
Patent Type
Applications(China)
Current Assignee / Owner
Filing Date
2026-09-04
Publication Date
2026-10-27

AI Technical Summary

Benefits of technology

[0045]上述技术方案中的一个技术方案至少具有如下优点或有益效果之一:探针初始化聚合至与目标模型对应的模型入口函数,插桩引入的体积与执行开销得到压缩,覆盖率测试能够适配资源受限的嵌入式环境;覆盖率数据凭借按模型结构分配的索引回溯至具体模型元素,测试结果与模型结构一一对应;平台库函数被排除在插桩范围之外,覆盖率指标精准聚焦于模型逻辑。整个方案使覆盖率测试从面向代码文本转变为面向模型结构,形成模型生成代码、代码承载探针、探针产出数据、数据回归模型的完整闭环。

✦ Generated by Eureka AI based on patent content.

Smart Images

  • Figure CN122985641A_ABST
    Figure CN122985641A_ABST
Patent Text Reader

Abstract

The application discloses a model-driven code generation-oriented code coverage test method and device, computer equipment and a storage medium. Model semantic information carried by code generated by a model-driven development platform is used to organize a coverage probe. The probe is initialized and aggregated to a model entry function corresponding to a target model. The probe is indexed according to a model structure of the target model. Platform library functions are excluded from a probe range based on model semantics. Coverage data collected can be mapped back to the model structure along the index, thereby solving the problems of mismatching of probe overhead and entry structure, mixed coverage data and inability to trace back to a model caused by the fact that a general coverage tool does not understand model semantics.
Need to check novelty before this filing date? Find Prior Art

Description

Technical Field

[0001] This application relates to the field of computer technology, specifically to a code coverage testing method, apparatus, computer device, and storage medium for model-driven code generation. Background Technology

[0002] Model-driven development (MDD) refers to a software development approach centered around graphical models: developers build graphical models within a MDD platform, and the platform automatically generates product code based on these models. Code coverage refers to the percentage of code that is actually executed during testing; it's a commonly used metric for measuring test adequacy. A common method for statistically analyzing code coverage is instrumentation, which involves inserting probes into the code to record execution status. After code execution, data from each probe is collected to obtain the coverage statistics.

[0003] In the field of embedded software, model-driven development (MDT) is increasingly widely used. Automated generation of product code through MDT platforms can improve development efficiency and maintain consistency between the code and the model. In functional safety-related fields such as aerospace and automotive, industry standards have clear requirements for code coverage, and automatically generated code also needs to undergo coverage testing.

[0004] In related technologies, general-purpose coverage tools instrument the source code uniformly during the compilation phase. These tools treat source files as plain text and insert probes evenly at statements, branches, conditions, and other locations in the code according to the syntax structure. The probe initialization code is distributed throughout the code or provided by the runtime library. After program execution, these tools collect probe data and generate a coverage report.

[0005] Automatically generated code differs significantly from manually written code. Automatically generated code is produced in batches by the model-driven development platform based on graphical models. It includes both model code corresponding to the graphical model and library function code provided by the platform. Furthermore, the automatically generated code has an entry point structure defined by the platform, such as a main step entry function that is called periodically.

[0006] Because general-purpose coverage tools do not understand the correspondence between generated code and graphical models, the following problems arise when uniformly instrumenting the generated code: First, probes are indiscriminately inserted into platform library functions and other code unrelated to the graphical model, introducing a large amount of instrumentation noise irrelevant to model verification. Second, the collected coverage data is organized according to code location, making it impossible to map back to the model structure of the graphical model. Testers find it difficult to identify which model elements have been verified and which have not at the model level. Third, the probe initialization code is scattered throughout the code, mismatched with the entry structure of the generated code, increasing the workload of integrating and maintaining instrumentation code in the embedded target environment. These problems affect the efficiency and usability of code coverage testing under the model-driven development model. Summary of the Invention

[0007] This application provides a code coverage testing method, apparatus, computer device, and storage medium for model-driven code generation. It enables coverage data organization to fit the model structure, probe initialization to match the entry structure of the generated code, and coverage statistics to focus on model logic, achieving low-overhead, traceable, and accurate coverage testing results. The technical solution provided by this application is as follows.

[0008] Firstly, a code coverage testing method oriented towards model-driven code generation is provided. This method uses a coverage testing system as the execution entity, which includes an instrumentation engine and analysis tools deployed on the development host, and an embedded target platform connected to the development host. The method includes the following steps.

[0009] The coverage testing system acquires the target code. The target code is automatically generated by the model-driven development platform based on the target model. The target model is built by the developer within the model-driven development platform, and the platform's code generator converts the target model into target code according to the model-to-code mapping rules.

[0010] The coverage testing system identifies the model entry function in the target code and aggregates the coverage probe's initialization code into the model entry function. The model entry function is the entry function corresponding to the target model in the target code generated by the model-driven development platform. The coverage probe is used to collect coverage data during the execution of the target code; the storage area recording the probe's state needs to be reset before use. Aggregation refers to concentrating the initialization code, originally scattered across various functions, into the model entry function for execution.

[0011] The coverage testing system assigns an index to each coverage probe according to the model structure of the target model. The index is the mapping key between the coverage probe and the model structure. Using the index of a coverage probe, the coverage data collected by that probe can be located to the corresponding model element in the target model, and the organization order of the coverage data is consistent with the organization method of the model.

[0012] The coverage testing system identifies platform library functions in the target code and inserts coverage probes into the parts of the target code other than these platform library functions. Platform library functions are those provided by the model-driven development platform. The coverage of platform library functions does not reflect the user-built model logic; therefore, coverage probes are not inserted within platform library functions.

[0013] The coverage testing system executes the target code after inserting coverage probes, and collects coverage data based on the index of each coverage probe. The instrumented target code is compiled and run on the embedded target platform. Each time a coverage probe is executed, the probe status is written to the corresponding storage location according to its own index.

[0014] The coverage testing system maps coverage data to the target model's structure according to the index of each coverage probe, and then outputs the coverage test results. Since the indexes are already associated with the model structure during allocation, the mapping process does not require re-parsing the source code, and the output coverage test results are available for developers to view the coverage of each model element.

[0015] This method aggregates initialization code into the entry function corresponding to the target model, merging the initialization operations that were originally scattered across each function into a single operation at the entry point. This reduces the total amount of initialization code and runtime initialization overhead, thus compressing the size and execution cost of the target code after instrumentation. This allows coverage testing to adapt to resource-constrained embedded environments. Since the index is allocated according to the target model's structure, each coverage data point can be traced back to a specific model element using the index. Therefore, the coverage test results correspond one-to-one with the model structure, allowing developers to directly locate uncovered code areas from a model perspective without manual comparison between files and line numbers. Because platform library functions are excluded from instrumentation, the coverage data no longer contains execution information from platform library functions. The statistical focus is on the user-built model logic, resulting in more accurate coverage metrics. Developers no longer need to manually filter out coverage data for platform library functions from the report. The three model semantic features work together to transform coverage testing from being text-oriented to being structure-oriented, forming a complete closed loop: model generates code, code carries probes, probes produce data, and data regresses to the model.

[0016] In one possible implementation, acquiring the target code is done in two phases. In the first phase, the coverage testing system acquires product code generated by the model-driven development platform based on the target model. This product code is clean code without any test logic and is intended for product delivery. In the second phase, the coverage testing system triggers instrumentation on a copy of the product code to obtain the target code used for coverage testing. The product code enters the product build chain, while the target code enters the coverage testing chain; they share the same origin but are used differently.

[0017] In this implementation, since instrumentation only applies to a copy of the product code, the code generator is unaware of the coverage tests. The product code contains no test code, ensuring that the code delivered to the customer is consistent with the original, uninstrumented generated code, thus guaranteeing the purity of the product code and preventing testing activities from contaminating the deliverables. Furthermore, the instrumentation engine exists as an independent component; enabling, disabling, and upgrading coverage testing capabilities do not involve modifications to the code generator. Therefore, the code generator and instrumentation engine can evolve independently, improving system maintainability and eliminating the workload and error risks associated with manually inserting probes.

[0018] In some implementations, the specific method for collecting coverage data based on the index of each coverage probe is as follows: the probe state of each coverage probe is stored in a bitmap array, where each coverage probe occupies 1 bit of storage space. The probe state of each coverage probe is written into the bitmap array according to the index of the coverage probe, so that the bits in the bitmap array correspond to the model structure through the index.

[0019] With this implementation, since the probe status of each coverage probe occupies only 1 bit, taking 1000 coverage probes as an example, the storage requirement is reduced from 4 to 8 kilobytes (KB) in a general-purpose tool counter scheme to approximately 125 bytes, saving about 97% to 98% of memory. Therefore, the memory usage of coverage data storage on the target platform is significantly reduced, allowing even microcontrollers with random access memory (RAM) capacities in KB to handle complete coverage testing. Limited memory resources no longer pose a barrier to coverage testing. Furthermore, since the probe status is written to the corresponding bit according to the index, and the index is allocated according to the model structure, the arrangement order of the bits in the bitmap array is consistent with the model structure. Therefore, the bitmap array itself is a digital mirror of the model structure, allowing the analysis end to trace back the data to the model without reordering the original data.

[0020] In one possible implementation, based on the bitmap array scheme described above, the probe states of each coverage probe are written to the bitmap array via predefined bit manipulation macros. These bit manipulation macros are expanded at compile time and are independent of the operating system's application programming interface (API) and the file system.

[0021] In this implementation, because bit manipulation macros are expanded into several bitwise operation instructions at compile time, the instrumented target code does not call any external runtime services at runtime, nor does it depend on operating system APIs or the file system. Therefore, the target code can be directly compiled and run in the bare-metal environment of microcontrollers and digital signal processors without a file system. This eliminates the dependence of coverage testing on the external runtime environment, achieving bare-metal compatibility. Compared to schemes that rely on file system persistence for coverage data, the zero-dependency scheme does not require configuring configuration systems or porting runtime libraries on the target platform, thus significantly reducing the cost of porting coverage testing to various embedded target platforms.

[0022] In some implementations, the initialization code of coverage probes is aggregated into the model entry function as follows: the coverage testing system counts the total number of coverage probes in the target code, and based on this total, inserts the definition code for a storage array and the clearing code for a one-time clearing of the storage array at the entry point of the model entry function. The storage array is used to store the probe state of each coverage probe. Each time the model entry function is executed, the probe state of all coverage probes is uniformly reset at the entry point, and no further initialization code appears within any sub-functions.

[0023] With this implementation, since the initialization operation is reduced from once per function to once at the entry point of each execution cycle, the redundant initialization code scattered in each function is eliminated as a whole. Therefore, the size of the target code and the runtime initialization overhead are further compressed after instrumentation. Thus, when combined with bit-compressed storage, the additional overhead introduced by instrumentation is controlled within the range that the embedded platform can bear.

[0024] In one possible implementation, the model entry function is the main step function generated by the code generator of the model-driven development platform. The main step function is scheduled to be executed to complete the single-step calculation corresponding to the target model. In model-driven development, both the simulation of the model and the execution of the generated code follow a step-by-step rhythm. Each step cycle completes a full process from input sampling, model calculation to output update, and the main step function is the carrier of this process in the code.

[0025] In this implementation, because the main step function is scheduled deterministically in each step cycle, the zeroing operation aggregated in the main step function is strictly synchronized with the model's execution rhythm. Therefore, coverage acquisition in each step cycle starts from a defined all-zero state, resulting in a one-to-one correspondence between the coverage data acquired frame by frame and the model's step cycle, ensuring the temporal consistency and reproducibility of the coverage data. Simultaneously, the main step function has a fixed name or explicit code generation marker, eliminating the need for manual specification during the identification process, thus automatically and accurately determining the trigger position for aggregation initialization.

[0026] In some implementations, the specific method for assigning indices to each coverage probe according to the model structure of the target model is as follows: Based on the topological sorting of each model element in the target model, the indices of the coverage probes are assigned sequentially to the code portions in the target code corresponding to each model element, so that the index order of the coverage probes is consistent with the execution order of the target model. Topological sorting refers to sorting model elements according to the signal dependencies between them, with upstream model elements preceding downstream model elements.

[0027] In this implementation, because the indexing order matches the execution order of the target model, the physical arrangement of coverage data in storage reflects the direction of the model execution flow. Therefore, the distribution of probes in the coverage report presents a spatial layout consistent with the model structure, allowing developers to intuitively locate uncovered code regions by reading the report along the signal flow. Compared to linear indexing based on file order, topological sorting naturally aligns the organization of coverage data with the model, eliminating the need for developers to manually compare the linear probe distribution with the model structure.

[0028] In one possible implementation, the platform library functions in the target code are identified as follows: the coverage testing system identifies platform library functions generated by the model-driven development platform in the target code based on at least one of the function's file path, naming conventions, or code generation tags. These three identification criteria can be used individually or in combination.

[0029] This implementation method ensures robustness against platform library functions by eliminating their inclusion in coverage data, as the three criteria are independent yet mutually corroborative. The identification process does not rely on a single clue, maintaining stability even with adjustments to the project directory structure or changes in function naming styles. Accurate identification prevents the inclusion of platform library function execution information in coverage data, strictly limiting the statistical objects to code generated by user-built models. This ensures that coverage metrics accurately reflect the adequacy of model logic testing, eliminating the need for developers to manually screen reports.

[0030] In some implementations, before inserting coverage probes into the target code (excluding platform library functions), the coverage testing system expands the chained conditional branching structure in the target code into a nested conditional branching structure, and inserts corresponding coverage probes into the expanded nested conditional branching structure. This ensures that the execution of each level of conditional branch is independently captured by the corresponding coverage probe. The chained conditional branching structure is essentially an else if chain. After expansion, each of the original else if branches occupies an independent conditional branching structure, and each independent conditional branching structure is a clearly defined statement-level branch point.

[0031] In this implementation, because the expanded nested conditional branch structure explicitly expresses each branch level at the syntactic level, any compiler generates jump instructions according to the explicit nested structure. Differences in compiler optimization strategies no longer affect the number and position of branch points. Therefore, coverage statistics remain consistent across different compilation environments, making coverage data for the same model comparable across compilers and platforms. Furthermore, since each else if branch has its own independent conditional branch structure and is instrumented independently, the execution of each condition in the conditional chain is recorded separately. Therefore, the statistical granularity of branch coverage is refined to each condition level, thus avoiding coverage blind spots where some branches are executed but the statistical results are indistinguishable in a chained structure.

[0032] In one possible implementation, before inserting coverage probes into the target code (excluding platform library functions), the coverage testing system recursively expands the ternary operator expressions in the target code into conditional branch structures, and inserts corresponding coverage probes for the function calls in the conditional, truth, and false parts of the ternary operator expressions. Recursive expansion means that each time a ternary operator expression is encountered, it is converted into an equivalent conditional branch code block. If the truth or false part still contains nested ternary operators, the expansion continues until no more ternary operators exist.

[0033] In this implementation, recursive expansion elevates the branches hidden within the expression to statement-level conditional branching structures. Function calls in the conditional, truth, and false parts each acquire independent coverage probes. Therefore, the statistical precision of function call coverage is refined to each component of the ternary operator expression, eliminating the coverage blind spots caused by the ternary operator. Even function calls nested deep within the expression can be accurately measured. Simultaneously, the expanded statement-level structure is also free from the influence of compiler optimization strategy differences. Therefore, the coverage statistics of code containing ternary operators are equally certain under different compilation environments, thus forming a complete deterministic logic refactoring scheme together with the expansion of chained conditional branching structures.

[0034] In some implementations, the method further includes: the coverage testing system decomposing the composite condition in the target code to obtain the atomic conditions contained in the composite condition; and generating a minimal test case set to verify the independent influence of each atomic condition on the decision result of the composite condition according to the modified condition / decision coverage (MC / DC) criterion. The minimal test case set is used to drive the execution of the target code after the insertion of the coverage probe. When the number of atomic conditions contained in the composite condition is N, the minimal test case set includes N+1 sets of test cases, where N is a positive integer.

[0035] This implementation method automatically generates N+1 sets of minimum test cases according to the modified condition decision coverage criterion. This reduces the number of test cases required to verify the independent influence of N atomic conditions from 2^N exhaustive test cases to N+1 sets. The number of test cases increases linearly with the number of atomic conditions rather than exponentially. Therefore, the execution cost of modified condition decision coverage verification is significantly reduced, making modified condition decision coverage testing practically feasible in engineering practice without compromising coverage standards. Since the decomposition of composite conditions and the generation of test case sets are completed automatically during the instrumentation phase, eliminating the need for testers to manually design test cases, the coverage capabilities required by high safety standards are natively integrated into the testing process. This allows the solution to directly support the modified condition decision coverage requirements of standards such as the Airborne Software Airworthiness Standard (DO-178C) and the Road Vehicle Functional Safety Standard (ISO 26262).

[0036] In one possible implementation, the method further includes: the coverage testing system generating a probe description file, which records the index of each coverage probe, the position of the coverage probe in the target code, and the type of the coverage probe. Correspondingly, the specific way to map the coverage data to the model structure of the target model according to the index of each coverage probe is as follows: the coverage data is mapped to the model structure of the target model according to the probe description file.

[0037] In this implementation, because the probe's metadata, such as index, location, and type, is transmitted between the instrumentation and analysis ends in the form of independent description files, the analysis end does not need to re-parse the source code to interpret the meaning of each bit in the collected data. Therefore, the instrumentation and coverage calculation stages are decoupled into two independently runnable phases, allowing the instrumentation and analysis ends to be upgraded and deployed independently. Simultaneously, the probe description file links the instrumentation metadata and coverage calculation into a complete closed loop from instrumentation to coverage calculation, with a one-to-one correspondence between collected data and metadata, thus forming an integrated, automatically flowing test workflow.

[0038] In some implementations, the coverage test results are output as follows: the coverage test results are displayed according to the hierarchical structure of the target model, and the coverage test results are associated with the model elements in the target model's model file. Developers first see the overall coverage of the top-level model, and then expand layer by layer to see the coverage of each subsystem and each model element. The coverage entries in the report are associated with the model elements in the model file. When a developer selects a model element in the report, the corresponding module is located and displayed in the model canvas.

[0039] This implementation method, by organizing the report according to the hierarchical structure of the target model and displaying it in association with model elements in the model file, means that developers no longer face abstract files and line numbers, but rather the model structure they have built themselves. Uncovered areas can be directly located to specific model modules. Therefore, the feedback path from coverage results to model modifications is significantly shortened, thereby improving the efficiency of test iterations. The hierarchical display also allows managers to grasp the overall test adequacy at the subsystem level, making test progress assessment and task allocation more intuitive.

[0040] Secondly, a code coverage testing apparatus for model-driven code generation is provided. This apparatus has the functionality to implement the first aspect or any optional method thereof. The apparatus includes at least one unit for implementing the method provided by the first aspect or any optional method thereof.

[0041] In some embodiments, the units in the device are implemented in software, and the units in the device are program modules. In other embodiments, the units in the device are implemented in hardware or firmware. Specific details of the device provided in the second aspect can be found in the first aspect or any alternative to the first aspect described above, and will not be repeated here.

[0042] Thirdly, a computer device is provided. The computer device includes a processor and a memory, the processor being coupled to the memory. The memory stores at least one computer program instruction, which is loaded and executed by the processor to cause the computer device to implement the method provided by the first aspect or any alternative embodiment of the first aspect. Specific details of the computer device provided in the third aspect can be found in the first aspect or any alternative embodiment of the first aspect, and will not be repeated here.

[0043] Fourthly, a computer-readable storage medium is provided. This storage medium stores at least one instruction that, when executed on a computer, causes the computer to perform the method provided in the first aspect or any alternative method of the first aspect.

[0044] Fifthly, a computer program product is provided. This computer program product includes one or more computer program instructions that, when loaded and executed by a computer, cause the computer to perform the method provided in the first aspect or any alternative method of the first aspect.

[0045] One of the above technical solutions has at least one of the following advantages or beneficial effects: probe initialization is aggregated to the model entry function corresponding to the target model, the volume and execution overhead introduced by instrumentation are compressed, and coverage testing can adapt to resource-constrained embedded environments; coverage data is traced back to specific model elements by indexes allocated according to the model structure, and the test results correspond one-to-one with the model structure; platform library functions are excluded from the instrumentation scope, and the coverage metric is precisely focused on the model logic. The entire solution transforms coverage testing from being oriented towards code text to being oriented towards model structure, forming a complete closed loop of model generating code, code carrying probes, probes producing data, and data regressing the model. Attached Figure Description

[0046] Figure 1 A flowchart illustrating a code coverage testing method for model-driven code generation provided in this application embodiment; Figure 2 This is a schematic diagram of the structure of a code coverage testing device for model-driven code generation provided in an embodiment of this application; Figure 3 This application provides a schematic diagram of the structure of a computing device. Detailed Implementation

[0047] To make the objectives, technical solutions, and advantages of this application clearer, the embodiments of this application will be described in further detail below with reference to the accompanying drawings.

[0048] In model-driven development (MDT) workflows, MDT platforms automatically generate code based on user-built models. This automatically generated code is often deployed in resource-constrained embedded target environments. How to conduct coverage testing on such code with controllable runtime overhead and results traceable back to the model is a practical problem faced in safety-critical domains. General coverage tools in related technologies treat code as unstructured text, failing to understand the model semantics behind the code. They cannot perform targeted optimizations for instrumentation and initialization, nor can they establish a correspondence between coverage data and model structure.

[0049] In view of this, the embodiments of this application utilize the prior knowledge of the model-driven development platform regarding its generated code to deeply integrate coverage testing with model semantics. Specifically, for the target code automatically generated by the model-driven development platform based on the target model, the model entry function corresponding to the target model in the target code is identified, and the initialization code of the coverage probe is aggregated into the model entry function, thus centralizing the scattered initialization operations; an index is assigned to the coverage probe according to the model structure of the target model, making the index a bridge for coverage data to trace back to the model structure; based on model semantics, the platform library functions in the target code are determined, and coverage probes are inserted in the parts other than the platform library functions, so that the coverage data focuses on the model logic built by the user; the target code after inserting the coverage probe is executed, and coverage data is collected based on the index; the coverage data is mapped to the model structure of the target model according to the index, and the coverage test results are output. The entire solution forms a complete closed loop of "model generating code, code carrying probes, probes producing data, and data regressing the model".

[0050] For ease of understanding, the terms used in the embodiments of this application are explained below.

[0051] (1) Model-Driven Development (MDD): A development approach centered on visual models. Developers build models consisting of model elements and the connections between them within a model-driven development platform. The platform's code generator automatically generates code based on the model-to-code mapping rules. Model elements include, but are not limited to, input modules, computation modules, logic modules, output modules, and subsystems. Model structure refers to the overall organizational form constituted by the connections, hierarchical relationships, and execution order between model elements.

[0052] (2) Model-driven development platform: A software platform that supports model-driven development, with a model building environment and a code generator. For example, the model-driven development platform includes, but is not limited to, the GCKontrol platform, Simulink and EmbeddedCoder code generation toolchain, SCADE platform, etc.

[0053] (3) Model entry function: The entry function in the code generated by the model-driven development platform that corresponds to the target model is used to be scheduled and executed to complete the calculation corresponding to the target model. One type of implementation is the main step function, such as the main step function named doStep in the GCKontrol platform, or the model step function generated by the Simulink and Embedded Coder toolchains.

[0054] (4) Coverage probes and instrumentation: Coverage probes are recording points inserted into the code to collect coverage data during code execution. Instrumentation refers to the process of strategically inserting coverage probes into the code. Types of coverage probes include, but are not limited to, statement probes, function call probes, branch probes, condition probes, and loop probes.

[0055] (5) Bitmap array: An array that records the probe status of each coverage probe in bits. Each coverage probe occupies 1 bit of storage space. One lower-level implementation of the bitmap array is an unsigned 8-bit integer (uint8_T) array.

[0056] (6) Modified condition / decision coverage (MC / DC): A coverage criterion that requires each atomic condition in a composite condition to be proven to independently affect the decision result. MC / DC is a coverage dimension required by high safety standards such as the Airborne Software Airworthiness Standard (DO-178C) and the Road Vehicle Functional Safety Standard (ISO 26262).

[0057] (7) Probe Description File: A file that records the metadata of the coverage probe, including the index of the coverage probe, the location of the coverage probe in the code, the type of the coverage probe, etc. One lower-level implementation is a .gccn file, which uses the Extensible Markup Language (XML) format as a unified data interface between the instrumentation end and the analysis end.

[0058] (8) Embedded target platform: The target hardware environment for running instrumented code, including but not limited to microcontroller units (MCUs), digital signal processors (DSPs), etc. Embedded target platforms often operate in a bare-metal environment or a real-time operating system environment without a file system.

[0059] (9) Analysis end: A software tool that reads coverage data and generates coverage test results. One lower-level implementation is a test management tool (TestManager).

[0060] The coverage testing scheme provided in this application involves three parties working together: a model-driven development platform and instrumentation engine running on the development host (collectively referred to as the instrumentation end), an embedded target platform running the instrumented code, and an analysis end that reads data and generates reports.

[0061] The overall process of the code coverage testing method for model-driven code generation provided in this application includes five steps: First, the developer builds a model in the model-driven development platform, and the platform generates C code; Second, the platform automatically triggers the instrumentation process, which includes semantic recognition, probe classification and insertion, and logical structure expansion; Third, the instrumentation end generates a bit-compressed probe data mechanism (i.e., the instrumented target code) and a probe description file; Fourth, the instrumented target code is compiled and downloaded to the embedded target platform for testing, collecting bit array data; Fifth, the test management tool (TestManager) reads the bit array data and the probe description file to generate a coverage report.

[0062] Regarding the operating environment, the development host includes, but is not limited to, a personal computer, workstation, or server. The development host installs a model-driven development platform, an instrumentation engine, and analysis tools. The embedded target platform connects to the development host via a simulator, debug interface, or communication bus. The acquired bit array data is transmitted back to the development host via the debug interface, serial port, or shared storage medium. The analysis and instrumentation ends can be deployed on the same development host or on different hosts and exchange data through probe description files; this embodiment does not impose such limitations.

[0063] The application scenarios of this application include, but are not limited to: the development and testing of automotive electronic control software, such as engine control and body control, which need to meet the coverage requirements of the ISO 26262 standard; the development and testing of airborne software, such as flight control, which need to meet the MC / DC coverage requirements of the DO-178C standard; and other software testing scenarios that adopt model-driven development and are deployed in an embedded environment.

[0064] Please refer to Figure 1 , Figure 1 A flowchart illustrating a code coverage testing method for model-driven code generation provided in this application embodiment. Figure 1 The method shown uses a coverage testing system as the execution entity. The coverage testing system includes an instrumentation engine deployed on the development host, test management tools corresponding to the analysis end, and an embedded target platform connected to the development host. For example... Figure 1 As shown, the method includes steps S101 to S106.

[0065] Step S101: Obtain the target code.

[0066] The instrumentation engine obtains the target code. The target code is automatically generated by the model-driven development platform based on the target model. The target model is built by the developer on the canvas of the model-driven development platform, and the code generator converts the target model into target code according to the model-to-code mapping rules. The target code language includes, but is not limited to, C and C++; this embodiment uses C code as an example. Unlike manually written code, automatically generated target code has a definite organizational pattern. For example, functions are arranged according to the model topology, the top-level entry function has a fixed name, and the platform library functions have clear boundaries. These patterns constitute prior knowledge that can be used in subsequent steps.

[0067] Step S102: Identify the model entry function in the target code and aggregate the initialization code of the coverage probe into the model entry function.

[0068] The instrumentation engine performs semantic recognition on the target code to identify the model entry function. The model entry function is the entry function in the target code generated by the model-driven development platform that corresponds to the target model. Coverage probes are used to collect coverage data during the execution of the target code. Before use, coverage probes need to be initialized, which means resetting the storage area that records the probe's state. "Aggregation" refers to concentrating the initialization code, which would otherwise be scattered across various functions, into the model entry function for execution. After identifying the model entry function, it is called deterministically in each execution cycle. With the initialization code aggregated to the model entry function, individual sub-functions no longer retain their own initialization operations.

[0069] Step S103: Assign an index to each coverage probe according to the model structure of the target model.

[0070] The instrumentation engine assigns indexes to each coverage probe according to the target model's structure. An index is the mapping key between the coverage probe and the model structure. The index is used to map the coverage data collected by the coverage probe back to the model structure; that is, data collected by any coverage probe can be used to locate the corresponding model element in the target model using that probe's index. The model structure contains the hierarchy and execution order of model elements; assigning indexes according to the model structure ensures that the organization order of the coverage data is consistent with the model's organization method.

[0071] Step S104: Identify the platform library functions in the target code and insert coverage probes in the parts of the target code other than the platform library functions.

[0072] The instrumentation engine determines platform library functions in the target code based on model semantics. Platform library functions are those provided by the model-driven development platform, such as platform-provided mathematical operation library functions, fixed-point conversion library functions, and runtime support functions. Platform library functions are determined by the platform, not the user model, and their coverage does not reflect the logic of the user-built model. The instrumentation engine inserts coverage probes into the target code outside of platform library functions; coverage probes are not inserted within platform library functions themselves.

[0073] Step S105: Execute the target code after inserting the coverage probes, and collect coverage data based on the index of each coverage probe.

[0074] After the coverage probes are inserted, the target code is compiled and downloaded to the embedded target platform for execution. Test cases drive the execution of the target code. Each time a coverage probe is executed, the probe status is written to the corresponding storage location according to its own index. At the end of an execution cycle or after a batch of test cases has been executed, the collected coverage data is sent back from the embedded target platform to the development host.

[0075] Step S106: Map the coverage data to the model structure of the target model according to the index of each coverage probe, and obtain and output the coverage test results.

[0076] The analysis unit reads the coverage data and maps it to the target model's structure according to the index of each coverage probe. Since the indexes are already associated with the model structure during allocation, the mapping process does not require re-parsing the source code. After mapping, the coverage test results are obtained and output in report form for developers to view the coverage of each model element.

[0077] Steps S102, S103, and S104 are all performed during the pile driving stage. Figure 1 The strict timing of the three processes is not directly expressed. In this embodiment, the instrumentation engine first completes the semantic recognition at the function level (the recognition part of step S102 and the platform library function determination in step S104), and then performs index allocation and probe insertion. In an optional implementation, the index allocation in step S103 and the probe insertion in step S104 are performed simultaneously, that is, an index is allocated and a probe is inserted for each probe position determined. The aggregation of the initialization code in step S102 is executed after the total number of probes is determined. This embodiment does not make an absolute restriction on the order of the steps.

[0078] In this embodiment, because the instrumentation engine identifies the model entry function corresponding to the target model and aggregates the initialization code to that entry point, the initialization operations that were originally scattered in each function are merged into a single operation at the entry point. This reduces the total amount of initialization code and the runtime initialization overhead. Therefore, the size and execution overhead of the target code are compressed after instrumentation, enabling coverage testing to adapt to resource-constrained embedded environments. Since the coverage probes are indexed according to the target model's structure, the organization order of the coverage data is consistent with the model execution flow. Each coverage data point can be traced back to a specific model element using the index. Therefore, the coverage test results correspond one-to-one with the model structure, allowing developers to directly locate uncovered code areas from the model's perspective without manual comparison between files and line numbers. Because platform library functions are determined based on model semantics and instrumentation is excluded, the coverage data no longer contains execution information from platform library functions. The statistical object focuses on the user-built model logic, resulting in more accurate coverage metrics. This eliminates the need for developers to manually filter out coverage data for platform library functions from the report. The three model semantic features work together to transform coverage testing from "code text-oriented" to "model structure-oriented", forming a complete closed loop of "model generating code, code carrying probes, probes producing data, and data regressing the model".

[0079] The above embodiments describe a complete instrumentation and acquisition process, but the specific code to be instrumented and when the instrumentation is triggered are not detailed. If the instrumentation logic is hard-coded into the code generator, the core logic of the code generator will become entangled with the test logic, requiring regression verification of the instrumentation function with each generator upgrade, making maintenance difficult. If developers manually instrument hundreds or thousands of probe positions, it is inefficient and prone to errors. To solve the problem of decoupling test logic from code generation logic, this embodiment provides a specific implementation of the method for obtaining the target code in step S101.

[0080] The acquisition of target code is divided into two phases. In the first phase, the instrumentation engine acquires the product code generated by the model-driven development platform based on the target model. This product code is clean and contains no test logic; it is used for product delivery. In the second phase, the instrumentation engine triggers instrumentation on a copy of the product code to obtain the target code, which is used for coverage testing. The product code and target code share the same origin but are used differently: the product code directly enters the product build chain, while the target code enters the coverage testing chain; the two do not interfere with each other.

[0081] Because instrumentation operates on a copy of the product code, the code generator is unaware of the coverage tests, and the product code output by the code generator remains pure. Model semantic knowledge is passed to the instrumentation engine through the decoupled architecture: the instrumentation engine obtains prior knowledge such as the location of the model entry function, the topological order of functions, and the boundaries of platform library functions by parsing function names, code generation tags, and file organization in the product code.

[0082] In a specific example, let's take the GCKontrol platform. Developers build a control model on the GCKontrol platform's canvas. The platform's code generator generates clean, production-grade C code files according to the model-to-code mapping rules, ensuring the product code generation logic remains independent and maintainable. After the product code generation is complete, the platform automatically triggers the instrumentation process. The instrumentation engine performs semantic recognition, probe classification and insertion, and logical structure expansion on a copy of the product code to obtain target code for coverage testing.

[0083] Alternatively, instrumentation can be triggered in ways including, but not limited to: automatic triggering by the platform after code generation; manual triggering by developers via command line or graphical interface; or automatic triggering as an independent step in a continuous integration pipeline. Methods for obtaining a copy of the product code include copying files, version control branches, etc., and this embodiment does not limit these methods.

[0084] Because the product code generation logic and coverage instrumentation logic are completely decoupled, instrumentation only applies to a copy of the product code, which contains no test code. Therefore, the code delivered to the customer is identical to the original, uninstrumented generated code, ensuring the purity of the product code and preventing testing activities from contaminating the deliverables. Since the instrumentation engine exists as an independent component, the test logic is flexibly pluggable. Enabling, disabling, and upgrading coverage testing capabilities do not involve modifying the code generator. Therefore, the code generator and instrumentation engine can evolve independently, improving system maintainability. Compared to manual instrumentation, automatic triggering eliminates the workload and error risks of manually inserting probes, thus ensuring the efficiency and accuracy of instrumentation.

[0085] In related technologies, general-purpose tools, such as the open-source coverage testing tool (gcov), allocate 4 to 8 bytes of counters for each probe. 1000 probes would require 4 to 8 KB of memory, and they rely on the file system service provided by the operating system to persist coverage data. Target platforms in the embedded control field often run on bare metal or real-time operating systems without a file system, with memory measured in KB. The storage solutions of general-purpose tools are not feasible on such platforms. Unlike the above methods, this embodiment provides a data acquisition scheme combining bit-compressed storage and index mapping, as well as a runtime-dependent bit operation implementation.

[0086] Part 1: Bit-compressed storage and index mapping.

[0087] In this embodiment, the specific method for collecting coverage data based on the index of each coverage probe is as follows: the probe status of each coverage probe is stored in a bitmap array, and the storage space occupied by each coverage probe in the bitmap array is 1 bit. The probe status of each coverage probe is written into the bitmap array corresponding to the index according to the index of the coverage probe, so that the bits in the bitmap array correspond to the model structure through the index.

[0088] The probe status indicates whether the probe has been executed; 1 bit is sufficient to carry both "executed" and "not executed" statuses. The conversion relationship between the index and storage location is as follows: the coverage probe with index idx corresponds to the idx%8th bit of the idx / 8th byte in the bitmap array. The capacity of the bitmap array is determined by the total number of probes. For example, when the total number of probes is totalProbeCount, the bitmap array is defined as uint8_T cov_array[totalProbeCount / 8+1], which is the total number of bits rounded up to the byte boundary.

[0089] In a specific example, suppose there are 1000 coverage probes in the target code. A general-purpose counter scheme requires 4 to 8 KB of memory; the bitmap array used in this embodiment requires only about 125 bytes. Memory usage is reduced by approximately 97% to 98%. Because the indices are allocated according to the model structure, adjacent bits in the bitmap array correspond to adjacent model elements in the model, and the physical arrangement of the bitmap array naturally carries model structure information.

[0090] In this embodiment, since the probe status of each coverage probe occupies only 1 bit, the storage requirement for 1000 probes is reduced from 4 to 8 KB to approximately 125 bytes, saving about 97% to 98% of memory. Therefore, the memory usage of coverage data storage on the target platform is significantly reduced, enabling even MCUs with only KB of random access memory (RAM) to handle complete coverage testing. Limited memory resources no longer pose a barrier to coverage testing. Furthermore, since the probe status is written to the corresponding bit according to the index, and the index is allocated according to the model structure, the arrangement order of the bits in the bitmap array is consistent with the model structure. Therefore, the bitmap array itself is a digital mirror of the model structure, allowing the analysis end to trace back the data to the model without reordering the original data.

[0091] Part Two: Zero-Dependency Bitwise Operation Macros

[0092] Based on the bitmap array scheme described above, the probe state of each coverage probe is written to the bitmap array through predefined bit manipulation macros. These bit manipulation macros are expanded at compile time and do not depend on the operating system's application programming interface (API) or the file system.

[0093] One specific implementation provides bit manipulation capabilities through a header file containing pure macro definitions, for example, named GBitOper.h. An example of the core macro definitions in the header file is as follows: #define Set7 (0x1U << 7U) ... #define Set0 (0x1U << 0U) #define SetBit(operand, bitNum) (((operand) |= (bitNum))) #define ResetBit(operand, bitNum) (((operand) &= (bitNum))) In the macro definitions above, Set0 to Set7 are bit mask constants. The SetBit macro has two parameters: operand is an array element in the bitmap array, and bitNum is the bitmask. The SetBit macro sets the bit in operand corresponding to bitNum to 1 using a bitwise OR operation, indicating that the corresponding coverage probe has been executed. The ResetBit macro clears the corresponding bit using a bitwise AND operation. All operations within the macro body are standard C bitwise operations. The compiler expands the macro into several bitwise operation instructions at compile time, requiring no library function calls at runtime. During instrumentation, each coverage probe is expanded into a SetBit macro call before its corresponding code location.

[0094] Alternatively, the array element type of the bitmap array can be 16-bit or 32-bit unsigned integers in addition to uint8_T; this embodiment does not limit this. Bit operations can be implemented using macro definitions, inline functions, or compiler-built-in bit manipulation instructions. Coverage data can be returned from the embedded target platform via methods such as reading from the debug interface, serial port transmission, and shared memory dumping, all of which are independent of the file system.

[0095] Because bitwise operation macros expand into several bitwise operation instructions at compile time, the instrumented target code does not call any external runtime services at runtime, nor does it depend on operating system APIs or file systems. Therefore, the target code can be directly compiled and run in bare-metal environments of MCUs and DSPs without file systems. This frees coverage testing from dependence on external runtime environments, achieving true "bare-metal compatibility." Compared to solutions that rely on file systems to persist coverage data, the zero-dependency solution does not require configuring configuration systems or porting runtime libraries on the target platform, thus significantly reducing the cost of porting coverage testing to various embedded target platforms.

[0096] Figure 1 The example proposes aggregating the coverage probe's initialization code into the model entry function, but how this "aggregation" is implemented and the specific form of the model entry function still need further clarification. To provide a reproducible implementation, this example elaborates on the specific operations of aggregation initialization and the concretization of the model entry function.

[0097] Part 1: The specific implementation of aggregation initialization.

[0098] In this embodiment, aggregating the initialization code of coverage probes into the model entry function involves two steps. First, the instrumentation engine counts the total number of coverage probes in the target code. The engine iterates through the functions in the target code, determines the coverage probes to be inserted in each function, and accumulates them to obtain the total number of probes, `totalProbeCount`. Second, based on the total number of probes, the instrumentation engine inserts the definition code for the storage array and the clearing code for a one-time zeroing of the storage array at the entry position of the model entry function. The storage array is used to store the probe state of each coverage probe.

[0099] In a specific example, the instrumentation engine inserts the following code at the entry point of the model's entry function: uint8_T cov_array[totalProbeCount / 8+1]; memset(cov_array, 0, sizeof(cov_array)); The first line defines a storage array `cov_array` based on the total number of probes, with the array capacity rounded up to the byte boundary by the total number of bits. The second line calls a memory clearing function to clear the storage array all at once. Each time the model entry function is executed, the probe state of all coverage probes is uniformly reset at the entry point, and no initialization code appears inside any sub-functions, so the initialization overhead of the sub-functions is zero.

[0100] Because the instrumentation engine first counts the total number of probes, and then defines and clears the storage array at the entry point of the model entry function according to the total number, the initialization operation is reduced from "once per function" to "once at the entry point of each execution cycle". The redundant initialization code scattered in each function is eliminated as a whole. Therefore, the size of the target code and the runtime initialization overhead are further compressed after instrumentation. Thus, when combined with the bit compression storage in Example 3, the additional overhead introduced by instrumentation is controlled within the range that the embedded platform can bear.

[0101] Part Two: Model Entry Function Concretization into Main Step Function

[0102] In this embodiment, the model entry function is the main step function generated by the code generator of the model-driven development platform. The main step function is scheduled to be executed to complete the single-step calculation corresponding to the target model. In model-driven development, both the simulation of the model and the execution of the generated code follow a "step" rhythm. Each step cycle completes a full process from input sampling, model calculation to output update, and the main step function is the carrier of this process in the code.

[0103] In a specific example, the top-level main entry function in the code generated by the GCKontrol platform is always named `doStep`, which stands for main step function. The instrumentation engine can identify `doStep` through fixed name matching or by identifying the main step function through code generation tags. In the Simulink and Embedded Coder toolchains, the corresponding function to the main step function is the model step function, which is also identified through fixed name matching or code generation tag recognition.

[0104] Alternatively, in addition to calling the memory clearing function, a one-time clear can also be achieved by repeatedly assigning values ​​byte by byte. The clearing execution frequency can be once per step cycle, or it can be executed once after the first frame of the test sequence and then continuously accumulated; this embodiment does not limit this.

[0105] Because the model's entry function is specifically defined as the main step function generated by the code generator, and this main step function is scheduled deterministically in each step cycle, the zeroing operation aggregated in the main step function is strictly synchronized with the model's execution rhythm. Therefore, coverage acquisition in each step cycle starts from a definite all-zero state, resulting in a one-to-one correspondence between the coverage data acquired frame by frame and the model's step cycle, ensuring the temporal consistency and reproducibility of the coverage data. Furthermore, the main step function has a fixed name or explicit code generation marker, eliminating the need for manual specification during the identification process, thus automatically and accurately determining the trigger position for aggregation initialization.

[0106] The model-driven development platform follows an inherent rule when generating code: the order of functions and code segments is determined by the topological order of model elements, with the code corresponding to the model element first reached by the signal flow appearing first. This rule is a priori knowledge unique to the platform's code generation. Utilizing this characteristic, this embodiment provides a specific implementation of the index allocation method in step S103.

[0107] In this embodiment, the specific method for assigning indexes to each coverage probe according to the model structure of the target model is as follows: according to the topological sorting of each model element in the target model, the indexes of the coverage probes are assigned to the code parts in the target code corresponding to each model element in turn, so that the index order of each coverage probe is consistent with the execution order of the target model.

[0108] Topological sorting refers to ordering model elements according to their signal dependencies, with upstream model elements preceding downstream model elements. The instrumentation engine traverses the code sections corresponding to the model elements in topological sorting, assigning indices to each code section in ascending order. After allocation, the order of index values ​​reflects the execution sequence of the model elements.

[0109] In a specific example, suppose the target model consists of an input module, a gain module, a summation module, and an output module connected in sequence, with the topology being input module → gain module → summation module → output module. The instrumentation engine assigns indices 0 to 2 to the code corresponding to the input module, indices 3 to 5 to the code corresponding to the gain module, indices 6 to 8 to the code corresponding to the summation module, and indices 9 to 11 to the code corresponding to the output module. The direction of the continuously increasing indices is consistent with the direction of signal flow in the model.

[0110] Because the indexes are allocated according to the topological sorting of model elements, the index order is consistent with the execution order of the target model. The physical arrangement of coverage data in the bitmap array reflects the direction of model execution flow. Therefore, the distribution of probes in the coverage report presents a spatial layout consistent with the model structure, allowing developers to intuitively locate uncovered code areas by reading the report along the signal flow. Compared to the linear allocation of indexes according to file order, topological sorting makes the organization of coverage data naturally fit the model, thus eliminating the need for developers to manually compare the linear probe distribution with the model structure.

[0111] Figure 1 The implementation example requires excluding platform library functions during instrumentation, which presupposes accurate identification. The accuracy of identification directly determines the purity of the coverage data: missed identification will cause library function data to be mixed into the report, while misidentification will cause user model code to lose probes. To make the exclusion mechanism feasible, this implementation example provides a specific method for identifying platform library functions.

[0112] In this embodiment, the instrumentation engine identifies platform library functions generated by the model-driven development platform in the target code based on at least one of the following: function file path, naming rules, or code generation tags. The three identification criteria are shown in Table 1 below.

[0113] Table 1

[0114] The three identification criteria can be used individually or in combination. In one implementation, the instrumentation engine identifies based solely on file paths, making it the simplest approach. In another implementation, the instrumentation engine combines file paths with naming rules, first narrowing down the candidate range by path and then confirming by naming rules, reducing the probability of false identification. In yet another implementation, the three criteria are used in combination with a majority-decision strategy; any function identified as a platform library function by two or more criteria is excluded. This embodiment does not limit the combination of criteria.

[0115] Because the identification criteria include at least one of file paths, naming rules, and code generation tags, and these three criteria are independent yet mutually corroborative, the identification process does not rely on a single clue. Therefore, the identification mechanism remains stable even when the project directory structure is adjusted or the function naming style changes, thus ensuring robustness against platform library functions. Accurate identification prevents the execution information of platform library functions from being mixed into the coverage data, and the statistical objects are strictly limited to the code generated by the user-built model. As a result, the coverage metric truly reflects the adequacy of the model logic testing, and developers do not need to manually screen the reports.

[0116] The else if chain expands into nested conditional branches.

[0117] In actual testing, the branch coverage statistics of the target code generated by the same model were inconsistent after compilation by different compilers. In-depth analysis revealed that the inconsistency stemmed from the chained conditional branching structure (else if chain). Different compilers employ different optimization strategies for else if chains; some merge multiple conditional jumps, while others generate a shared jump table, resulting in different branch counts for the same source code under different compilation environments. Based on this finding, this embodiment proposes a deterministic logical structure expansion scheme.

[0118] In this embodiment, before inserting coverage probes into parts of the target code other than platform library functions, the instrumentation engine first expands the chained conditional branch structure in the target code into a nested conditional branch structure, and inserts the corresponding coverage probes into the expanded nested conditional branch structure so that the execution of each layer of conditional branches is independently collected by the corresponding coverage probes.

[0119] The instrumentation engine identifies chained conditional branch structures through lexical analysis. Lexical analysis scans the target code at the granularity of lexical units (tokens), automatically expanding and rewriting chained structures in the form of "if(A)... else if(B)... else ..." into nested structures in the form of "if(A)... else { if(B)... else {...}}". After expansion, each of the original else if branches occupies an independent if / else structure, and each independent if / else structure is a clear statement-level branch point. Coverage probes are then inserted into each independent if / else structure.

[0120] In a specific example, the code snippet before expansion is as follows: if (A) { x = 1;} else if (B) { x = 2;} else { x = 3;} The expanded code snippet is as follows: if (A) { x = 1;} else { if (B) { x = 2;} else { x = 3;} } The two code snippets before and after expansion are semantically equivalent and produce identical execution results; the difference lies in the fact that the expanded code explicitly expresses each branch at the syntactic level. After the probe is inserted, the evaluation of condition B and the execution of the innermost else branch are collected by independent coverage probes.

[0121] Alternatively, the logical structure expansion can be achieved through lexical analysis or through abstract syntax tree transformation; this embodiment does not limit this.

[0122] Because the expanded nested conditional branching structure explicitly expresses each branch level at the syntactic level, any compiler can only generate jump instructions according to the explicit nested structure. Differences in compiler optimization strategies no longer affect the number and position of branch points. Therefore, coverage statistics remain consistent and deterministic across different compilation environments, making coverage data for the same model comparable across compilers and platforms. Furthermore, since each else if branch occupies an independent if / else structure and is instrumented independently, the execution of each condition in the conditional chain is recorded separately. Therefore, the statistical granularity of branch coverage is refined to each condition level, thus avoiding the coverage blind spots that occur in chained structures where some branches are executed but the statistical results are indistinguishable.

[0123] Ternary operator recursive expansion and independent instrumentation

[0124] The above embodiments solve the deterministic problem of chained conditional branching structures, but another type of hidden logical structure exists in the target code: the ternary operator. The ternary operator compresses the condition, truth value, and false value into a single expression, making it impossible for probes to directly insert into the expression. Whether the function call inside the ternary operator is executed is difficult to measure precisely. To enable coverage sampling to penetrate the expression layer, this embodiment provides a deterministic expansion scheme for the ternary operator.

[0125] In this embodiment, before inserting coverage probes into parts of the target code other than platform library functions, the instrumentation engine recursively expands the ternary operator expression in the target code into a conditional branch structure, and inserts corresponding coverage probes into the function calls in the conditional part, truth part, and false part of the ternary operator expression.

[0126] The expansion algorithm works recursively: for each ternary operator expression encountered, it is converted into an equivalent if / else block; after conversion, if the truth or false part still contains nested ternary operators, the nested part is expanded again until no more ternary operators exist. After expansion, the instrumentation engine extracts the function calls contained in the original conditional, truth, and false parts, and inserts an independent function call probe for each function call in the corresponding if / else branch.

[0127] In a specific example, the expression before expansion is: y = cond ? f(x) : g(x); The expanded and instrumented code is as follows: if (cond) { y = f(x); SetBit(cov_array[index / 8], bitmask corresponding to the index); function call probe for f / } else { y = g(x); SetBit(cov_array[index / 8], bitmask corresponding to the index); g function call probe / } After expansion, the execution of function f and function g are recorded by independent function call probes, and the evaluation path of condition cond is also clearly expressed.

[0128] Because recursive expansion elevates the branches hidden within expressions to statement-level conditional branch structures, function calls in the conditional, truth, and false parts each acquire independent coverage probes. Therefore, the statistical precision of function call coverage is refined to each component of the ternary operator expression, eliminating coverage blind spots caused by the ternary operator. Even function calls nested deep within expressions can be accurately measured. Furthermore, the expanded statement-level structure, like the expansion result in Example 7, is free from the influence of compiler optimization strategy differences. Therefore, the coverage statistics of code containing ternary operators are equally certain under different compilation environments, thus forming a complete deterministic logic refactoring scheme together with else if chain expansion.

[0129] Composite condition decomposition and MC / DC minimum test case set

[0130] In related technologies, general coverage tools only support statement coverage and branch coverage, resulting in a single coverage dimension. Industry standards in safety-critical fields such as aviation and automotive require compliance with MC / DC coverage, meaning that it must be proven that each atomic condition in a composite condition can independently affect the decision result, which general tools cannot achieve. Unlike the above methods, this embodiment automatically decomposes the composite condition during the instrumentation phase and generates a minimum test case set that satisfies the MC / DC criterion.

[0131] In this embodiment, the coverage testing method further includes two steps. First, the instrumentation engine decomposes the composite conditions in the target code to obtain the atomic conditions contained within each composite condition. A composite condition is a decision expression composed of multiple atomic conditions connected by logical operators; atomic conditions are indivisible basic conditions. The decomposition is based on short-circuit evaluation semantics, that is, the evaluation order of each atomic condition is determined according to the short-circuit rules of logical AND and logical OR. Second, the instrumentation engine generates a minimum test case set to verify the independent influence of each atomic condition on the decision result of the composite condition, according to the modified condition decision coverage criterion. The minimum test case set is used to drive the execution of the target code after the coverage probe is inserted. When the number of atomic conditions contained in the composite condition is N, the minimum test case set includes N+1 sets of test cases, where N is a positive integer. The minimum test case set is written into the probe description file along with the probe metadata (see Embodiment 10) for use by the analysis end for matching and judgment.

[0132] In a specific example, suppose the composite condition in the target code is "A && (B || C)", the atomic conditions are A, B, and C, the number of atomic conditions is N, and the minimum test case set includes N+1, or 4 sets of test cases, as shown in the table below.

[0133]

[0134] The pairing relationship means that: Test Case 1 and Test Case 2 differ only in the value of atomic condition B and have opposite decision results, proving that B can independently affect the decision result; Test Case 2 and Test Case 3 differ only in the value of atomic condition C and have opposite decision results, proving that C can independently affect the decision result; Test Case 1 and Test Case 4 differ only in the value of atomic condition A and have opposite decision results, proving that A can independently affect the decision result. Four test cases complete the verification of the independent influence of the three atomic conditions, while exhaustively listing all possible value combinations requires eight test cases. During test execution, the minimum test case set drives the target code after inserting the coverage probe to run group by group. The analysis end matches the collected probe status with the test case set in the probe description file to obtain the MC / DC coverage conclusion.

[0135] Because N+1 minimum test cases are automatically generated according to the modified condition coverage criteria, the number of test cases required to verify the independent effects of N atomic conditions is reduced from 2^N exhaustive test cases to N+1 sets. The number of test cases increases linearly with the number of atomic conditions rather than exponentially, thus significantly reducing the execution cost of MC / DC verification. This makes MC / DC testing practically feasible in engineering practice without compromising coverage standards. Since composite condition decomposition and test case set generation are completed automatically during the instrumentation phase, testers do not need to manually design MC / DC test cases. Therefore, the coverage capabilities required by high security standards are natively integrated into the testing process, allowing the solution to directly support the mandatory MC / DC coverage requirements of standards such as DO-178C and ISO 26262.

[0136] probe description file

[0137] The aforementioned embodiments completed instrumentation and data acquisition, but the acquired coverage data is merely a string of bits in the bitmap array. When the analysis end faces the bitmap array, it needs to know which probe corresponds to each bit, where the probe is located, and what type it is in order to reconstruct meaningful coverage information from the data. To establish a data path between the instrumentation end and the analysis end, this embodiment introduces a probe description file as a unified data interface.

[0138] In this embodiment, the instrumentation engine generates a probe description file during the instrumentation process. The probe description file records the index of each coverage probe, its position in the target code, and its type. The position of the coverage probe in the target code includes the source file name, line number, and function name; the types of coverage probes include statement probes, function call probes, branch probes, condition probes, and loop probes. Correspondingly, the specific method for mapping coverage data to the target model's structure according to the index of each coverage probe in step S106 is as follows: the analysis end maps the coverage data to the target model's structure based on the probe description file. The analysis end reads a bit from the bitmap array, determines the corresponding index, position, and type of that bit through the probe description file, and then, combining the correspondence between the index and the model structure, locates the coverage information to the specific model element.

[0139] In a specific example, one lower-level implementation of the probe description file is a .gccn file. The .gccn file uses XML format and records metadata such as probe index, line number, type, and MC / DC test case set, serving as a unified data exchange format between the instrumentation and analysis ends. One lower-level implementation on the analysis end is the test management tool TestManager. TestManager reads the .gccn file, parses the probe metadata, then parses the bitmap array frame by frame, accumulates the probe execution count, and performs matching determination based on the MC / DC test case set in the .gccn file.

[0140] Alternatively, the probe description file can use data formats other than XML, such as object notation (JSON) or binary serialization format. This embodiment does not limit the specific format used.

[0141] Because the probe's metadata, such as index, location, and type, is transmitted between the instrumentation and analysis ends in the form of independent description files, the analysis end can interpret the meaning of each bit in the bitmap array without re-parsed the source code. Therefore, the instrumentation and coverage calculation stages are decoupled into two independently runnable phases, allowing the instrumentation and analysis ends to be upgraded and deployed independently. Simultaneously, the description files link the instrumentation metadata and coverage calculation into a complete closed loop from instrumentation to coverage calculation, with a one-to-one correspondence between the bit array data and metadata, thus forming an integrated, automatically flowing test workflow.

[0142] Coverage report displayed by model level

[0143] After coverage data is mapped back to the model structure, how it is presented to developers still directly impacts testing efficiency. Text-based coverage reports in related technologies are organized using "filename + line number," requiring developers to switch back and forth between the report and the model canvas, manually comparing data, and locating an uncovered area is often time-consuming. To shorten the feedback path from coverage results to model modifications, this embodiment provides a specific implementation of how coverage test results are output.

[0144] In this embodiment, the coverage test results are output as follows: the coverage test results are displayed according to the hierarchical structure of the target model, and the coverage test results are associated with the model elements in the target model's model file. The target model has a hierarchical structure; for example, the top-level model contains several subsystems, and each subsystem contains basic model elements. The report is organized in the same hierarchy: developers first see the overall coverage of the top-level model, and then expand layer by layer to see the coverage of each subsystem and each model element. Each coverage entry in the report is bidirectionally associated with a model element in the model file. When a developer clicks on a model element in the report, the corresponding module in the model canvas is highlighted; conversely, when a developer selects a module in the model canvas, the corresponding coverage entry in the report is displayed.

[0145] In a specific example, the test management tool TestManager calculates coverage across four dimensions: lines, function calls, branches, and MC / DC, generating a report in Hypertext Markup Language (HTML) format. The left side of the report page displays a navigation tree organized by model hierarchy, while the right side shows the coverage details for the selected node. Covered probes are marked with a style that distinguishes them from covered probes.

[0146] Alternatively, in addition to HTML pages, the report can also be presented in a graphical interface within an integrated development environment with embedded highlighting and printable document formats. This embodiment does not limit the presentation of such formats.

[0147] Because the report is organized hierarchically according to the target model and displayed in association with model elements in the model file, developers no longer face abstract files and line numbers, but rather the model structure they have built themselves. Uncovered areas can be directly located to specific model modules. Therefore, the feedback path from coverage results to model modifications is significantly shortened, thereby improving the efficiency of test iterations. The hierarchical display also allows managers to grasp the overall test adequacy at the subsystem level, making test progress assessment and task allocation more intuitive.

[0148] The foregoing embodiments have been illustrated using specific implementations such as the GControl platform, uint8_T bitmap arrays, bit manipulation macros, and HTML reports. The following provides alternative and modified solutions from multiple perspectives to illustrate the diverse implementation methods of the embodiments in this application.

[0149] (1) Alternative Implementations of Model-Driven Development Platforms. Model-driven development platforms are a higher-level concept, with at least two lower-level implementations. Implementation 1: The GCKontrol platform, where the top-level main entry function of the generated code is fixedly named `doStep`, functions are arranged according to the model topology, and the platform's built-in library functions have clear boundaries. Implementation 2: Simulink and Embedded Coder code generation toolchains, where the generated code corresponds to the model step function, and the platform's runtime library functions are concentrated in the runtime library directory. Furthermore, platforms such as SCADE, which have model building and automatic code generation capabilities, are also applicable. For different platforms, the instrumentation engine only needs to adapt the corresponding main step function naming and library function boundary knowledge; the method flow described in Examples 1 to 11 remains unchanged.

[0150] (2) Alternatives to bitwise operations. Besides being implemented using compile-time expanded bitwise macros, probe states can also be written using inline functions, which similarly do not introduce external library dependencies. If the target compiler supports this, it can also be implemented using built-in bitwise operations. The array element width of the bitmap array can be 8 bits, 16 bits, or 32 bits. In addition to the single-bit semantics of "executed / not executed," the semantics of probe states can be extended to a multi-bit execution count when memory allows.

[0151] (3) Alternative report formats. In addition to HTML reports, coverage test results can also be output in the following formats: an embedded highlighted view integrated into the graphical interface of the model-driven development platform, which directly marks the coverage on the model canvas using coloring; a structured data file for secondary analysis by third-party tools; or a printable document format report.

[0152] (4) Other alternatives. The target code can be in languages ​​other than C, such as C++, generated by the model-driven development platform. The return channel for coverage data can be Ethernet, CAN bus dump, etc., in addition to the debugging interface and serial port. Regarding the deployment of the execution entity, all steps of instrumentation and analysis can be executed on a single development host, or by the instrumentation server and analysis host working together. The instrumentation engine can also be integrated into the model-driven development platform as a plug-in. This application does not limit these aspects.

[0153] Figure 2This is a schematic diagram of a code coverage testing device 200 for model-driven code generation provided in an embodiment of this application. The device 200 includes: The acquisition module 210 is used to acquire target code, which is code automatically generated by the model-driven development platform based on the target model; The identification and aggregation module 220 is used to identify the model entry function in the target code and aggregate the initialization code of the coverage probe to the model entry function; wherein, the model entry function is the entry function in the target code generated by the model-driven development platform that corresponds to the target model, and the coverage probe is used to collect coverage data during the execution of the target code; The index allocation module 230 is used to allocate an index to each of the coverage probes according to the model structure of the target model. The index is used to map the coverage data collected by the coverage probes back to the model structure. Instrumentation module 240 is used to identify platform library functions in the target code and insert the coverage probe into the part of the target code other than the platform library functions, wherein the platform library functions are library functions provided by the model-driven development platform. The acquisition module 250 is used to execute the target code after the coverage probe is inserted, and to acquire the coverage data based on the index of each coverage probe; The mapping output module 260 is used to map the coverage data to the model structure of the target model according to the index of each coverage probe, and to obtain and output the coverage test results.

[0154] Appendix Figure 2 The described device embodiments are merely illustrative. For example, the division of the units described above is only a logical functional division. In actual implementation, there may be other division methods. For example, multiple units or components may be combined or integrated into another system, or some features may be ignored or not executed. The functional units in the various embodiments of this application may be integrated into one processing unit, or each unit may exist physically separately, or two or more units may be integrated into one unit.

[0155] Figure 3 This application provides a schematic diagram of the structure of a computing device 300, which includes a processor 301 coupled to a memory 302. The memory 302 stores at least one computer program instruction, which is loaded and executed by the processor 301 to enable the computing device 300 to perform the aforementioned functions. Figure 1 The methods provided.

[0156] This application also provides a computer-readable storage medium. The computer-readable storage medium stores a computer program, which, when executed by a processor, implements the steps in any of the foregoing method embodiments. The computer-readable storage medium includes, but is not limited to, a read-only memory, a random access memory, a magnetic disk, an optical disk, or flash memory.

[0157] This application also provides a computer program product. The computer program product includes one or more computer program instructions. When the computer program instructions are loaded and run by a computer, the computer performs the steps in any of the foregoing method embodiments.

[0158] The various embodiments in this specification are described in a progressive manner. The same or similar parts between the various embodiments can be referred to each other. Each embodiment focuses on describing the differences from other embodiments.

[0159] A references B, which means that A is the same as B or A is a simple variation of B.

[0160] The above embodiments can be implemented, in whole or in part, by software, hardware, firmware, or any combination thereof. When implemented in software, they can be implemented, in whole or in part, as a computer program product. The computer program product includes one or more computer instructions. When the computer program instructions are loaded and executed on a computer, all or part of the processes or functions described in the embodiments of this application are generated. The computer can be a general-purpose computer, a special-purpose computer, a computer network, or other programmable device. The computer instructions can be stored in a computer-readable storage medium or transmitted from one computer-readable storage medium to another. For example, the computer instructions can be transmitted from one website, computer, server, or data center to another website, computer, server, or data center via wired (e.g., coaxial cable, fiber optic, digital subscriber line (DSL)) or wireless (e.g., infrared, wireless, microwave, etc.) means. The computer-readable storage medium can be any available medium that a computer can access or a data storage device such as a server or data center that integrates one or more available media. The available medium can be a magnetic medium (e.g., floppy disk, hard disk, magnetic tape), an optical medium (e.g., DVD), or a semiconductor medium (e.g., a solid-state drive (SSD)).

[0161] The above embodiments are only used to illustrate the technical solutions of this application, and are not intended to limit it. Although this application has been described in detail with reference to the foregoing embodiments, those skilled in the art should understand that modifications can still be made to the technical solutions described in the foregoing embodiments, or equivalent substitutions can be made to some of the technical features. Such modifications or substitutions do not cause the essence of the corresponding technical solutions to deviate from the scope of the technical solutions of the embodiments of this application.

Claims

1. A code coverage testing method for model-driven code generation, characterized in that, include: Obtain the target code, which is the code automatically generated by the model-driven development platform based on the target model; Identify the model entry function in the target code and aggregate the initialization code of the coverage probe to the model entry function; wherein, the model entry function is the entry function in the target code generated by the model-driven development platform that corresponds to the target model, and the coverage probe is used to collect coverage data during the execution of the target code; An index is assigned to each coverage probe according to the model structure of the target model. The index is used to map the coverage data collected by the coverage probe back to the model structure. Identify the platform library functions in the target code, and insert the coverage probe into the portion of the target code other than the platform library functions, where the platform library functions are library functions provided by the model-driven development platform; Execute the target code after inserting the coverage probe, and collect the coverage data based on the index of each coverage probe; The coverage data is mapped to the model structure of the target model according to the index of each coverage probe, and the coverage test results are obtained and output.

2. The method according to claim 1, characterized in that, The acquisition of the target code includes: Obtain the product code generated by the model-driven development platform based on the target model; Instrumentation is triggered on a copy of the product code to obtain the target code; The product code is used for product delivery, and the target code is used for coverage testing.

3. The method according to claim 1, characterized in that, The collection of coverage data based on the index of each coverage probe includes: The probe state of each coverage probe is stored in a bitmap array, and each coverage probe occupies 1 bit of storage space in the bitmap array; The probe state of each coverage probe is written into the bitmap array corresponding to the index according to the index of the coverage probe, so that the bit in the bitmap array corresponds to the model structure through the index.

4. The method according to claim 1, characterized in that, The aggregation of the coverage probe initialization code into the model entry function includes: Count the total number of coverage probes in the target code; According to the total number, the definition code for inserting the storage array at the entry position of the model entry function and the clearing code for clearing the storage array once are inserted. The storage array is used to store the probe status of each coverage probe.

5. The method according to claim 1, characterized in that, The model entry function is the main step function generated by the code generator of the model-driven development platform. The main step function is scheduled to be executed to complete the single-step calculation corresponding to the target model.

6. The method according to claim 1, characterized in that, Assigning indices to each coverage probe according to the model structure of the target model includes: According to the topological sorting of each model element in the target model, the index of the coverage probe is assigned to the code portion in the target code corresponding to each model element in turn, so that the index order of each coverage probe is consistent with the execution order of the target model.

7. The method according to claim 1, characterized in that, The step of determining the platform library functions in the target code includes: Identify platform library functions generated by the model-driven development platform in the target code based on at least one of the function's file path, naming rules, or code generation tags.

8. The method according to claim 1, characterized in that, Before inserting the coverage probe into the portion of the target code other than the platform library functions, the method further includes: The chained conditional branch structure in the target code is expanded into a nested conditional branch structure, and the corresponding coverage probe is inserted into the expanded nested conditional branch structure so that the execution of each layer of conditional branch is independently collected by the corresponding coverage probe.

9. The method according to claim 1, characterized in that, Before inserting the coverage probe into the portion of the target code other than the platform library functions, the method further includes: The ternary operator expression in the target code is recursively expanded into a conditional branch structure, and the corresponding coverage probes are inserted into the function calls in the conditional part, truth part, and false part of the ternary operator expression, respectively.

10. The method according to claim 1, characterized in that, The method further includes: The composite conditions in the target code are decomposed to obtain the individual atomic conditions contained in the composite conditions; According to the modified condition determination coverage criterion, a minimum test case set is generated to verify the independent influence of each atomic condition on the determination result of the composite condition. The minimum test case set is used to drive the execution of the target code after the coverage probe is inserted. When the number of atomic conditions included in the composite condition is N, the minimum test case set includes N+1 test cases.

11. The method according to claim 1, characterized in that, The method further includes: Generate a probe description file, which records the index of each coverage probe, the position of the coverage probe in the target code, and the type of the coverage probe; The step of mapping the coverage data to the model structure of the target model according to the index of each coverage probe includes: mapping the coverage data to the model structure of the target model according to the probe description file.

12. The method according to claim 1, characterized in that, The output coverage test results include: The coverage test results are displayed according to the hierarchical structure of the target model, and the coverage test results are associated with the model elements in the model file of the target model.

13. The method according to claim 3, characterized in that, The probe state of each coverage probe is written to the bitmap array through a predefined bit operation macro. The bit operation macro is expanded at compile time and does not depend on the operating system's application programming interface and file system.

14. A code coverage testing device for model-driven code generation, characterized in that, include: The acquisition module is used to acquire the target code, which is code automatically generated by the model-driven development platform based on the target model. The identification and aggregation module is used to identify the model entry function in the target code and aggregate the initialization code of the coverage probe to the model entry function; wherein, the model entry function is the entry function in the target code generated by the model-driven development platform that corresponds to the target model, and the coverage probe is used to collect coverage data during the execution of the target code; An index allocation module is used to allocate an index to each of the coverage probes according to the model structure of the target model. The index is used to map the coverage data collected by the coverage probes back to the model structure. An instrumentation module is used to identify platform library functions in the target code and insert the coverage probe into the portion of the target code other than the platform library functions, wherein the platform library functions are library functions provided by the model-driven development platform. The acquisition module is used to execute the target code after the coverage probe is inserted, and to acquire the coverage data based on the index of each coverage probe; The mapping output module is used to map the coverage data to the model structure of the target model according to the index of each coverage probe, and to obtain and output the coverage test results.

15. A computer device comprising a memory and a processor, wherein the memory stores a computer program, characterized in that, When the processor executes the computer program, it implements the steps of the method as described in any one of claims 1 to 13.

16. A computer-readable storage medium having a computer program stored thereon, characterized in that, When the computer program is executed by a processor, it implements the steps of the method as described in any one of claims 1 to 13.