Generate C/C++ Code and Test for Equivalence
You can write equivalence tests that use MATLAB® Coder™ to generate C/C++ code from MATLAB source code, execute the generated code with specified inputs, and verify that the execution of the generated code and the MATLAB source code match.
Equivalence tests can:
Use MATLAB testing framework customizations, such as parameterizations.
Qualify test results with absolute and relative tolerances.
Generate C/C++ code with code generation parameters specified in
coder.MexCodeConfig
(MATLAB Coder) orcoder.EmbeddedCodeConfig
(MATLAB Coder) objects.Execute and verify C/C++ code that you previously generated outside of the test by using
codegen
(MATLAB Coder).Execute and verify your generated production C/C++ code in software-in-the-loop (SIL) or processor-in-the-loop (PIL) mode. For more information, see Code Verification Through Software-in-the-Loop and Processor-in-the-Loop Execution (Embedded Coder).
You can also generate C/C++ code from multiple entry-point functions or with multiple signatures and then test each function or signature for equivalence with MATLAB source code. For more information, see Equivalence Test C/C++ Code for Multiple Entry-Point Functions and Function Signatures.
Note
You must have MATLAB Coder to run equivalence tests for generated C/C++ code for MEX targets and Embedded Coder® for LIB and DLL targets.
If you need to deploy C++ shared libraries, you can write equivalence tests that use MATLAB Compiler SDK™ to generate and test deployable C++ shared libraries from MATLAB source code. For more information, see Choose an Approach for Equivalence Testing Generated C++ Code.
Write Generated C/C++ Code Equivalence Tests
To write an equivalence test that generates and tests C/C++ code, define a test class
that inherits from matlabtest.coder.TestCase
. In your test class, include a
methods
block with the Test
attribute. In the
methods
block, add a function to contain the
test.
classdef tEquivalence < matlabtest.coder.TestCase methods (Test) function equivalenceTest(testCase) end end end
Equivalence tests typically do three things:
Build — Generate the C/C++ code by using the
build
function.Execute — Execute the C/C++ code by using the
execute
function.Qualify — Qualify the result by comparing the execution of the C/C++ code to the execution of the MATLAB source code by using methods such as
verifyExecutionMatchesMATLAB
. For more information, see Table of Qualifications for Equivalence Tests.
Suppose that you want to generate code for a function called
myAdd
, which adds two inputs and outputs the
result:
function y = myAdd(a,b) %#codegen y = a + b; end
(1,2)
. It executes the C code with the same inputs used to build
the code and verifies that the execution matches the MATLAB execution of the function.classdef tEquivalence < matlabtest.coder.TestCase methods(Test) function tMyAdd(testCase) buildResults = build(testCase,"myAdd",Inputs={1,2}); executionResults = execute(testCase,buildResults); verifyExecutionMatchesMATLAB(testCase,executionResults) end end end
Tip
You can generate code that accepts variable-sized inputs by using the output
of coder.typeof
(MATLAB Coder) as a build-time
input. However, if you specify build-time inputs using
coder.typeof
, you must specify real run-time inputs for
the execute
method.
By default, the test case generates code in a temporary directory. To preserve the
generated files, use the PreserveInFolder
name-value argument in the build
method. When the equivalence test fails, MATLAB preserves the generated files regardless of whether or not you use this
name-value argument.
Parameterize Equivalence Tests
Equivalence tests use the MATLAB test framework, which means you can use MATLAB test customizations such as parameterizations. Parameterized tests allow you to test different parameter combinations with less code than if you coded each combination separately. For more information, see Create Basic Parameterized Test. Parameterizing equivalence tests allows you to generate the C/C++ code once and test it with different parameter combinations.
This example equivalence test generates the C code once by using class-level properties and test setup methods, but executes the code multiple times with different inputs by using parameterization.
classdef tEquivalenceParameterized < matlabtest.coder.TestCase properties buildResults end methods (TestClassSetup) function generateCode(testCase) testCase.buildResults = build(testCase,"myAdd", ... Inputs={1,2}); end end properties (TestParameter) runTimeInputs = {{1,2},{3,5}}; end methods (Test) function tMyAdd(testCase,runTimeInputs) executionResults = execute(testCase, ... testCase.buildResults,Inputs=runTimeInputs); verifyExecutionMatchesMATLAB(testCase,executionResults) end end end
myAdd
with inputs set to (1,2)
and the second
time it executes with inputs set to (3,5)
.Generate C/C++ Code with Additional Options
To customize how MATLAB
Coder builds your C/C++ code in the equivalence test, create an instance of a
code generation configuration parameter object for your desired build type by using
coder.config
(MATLAB Coder) and pass the object to the
build
method.
This example equivalence test generates a dynamically linked library of C++ code with dynamic memory allocation disabled. The test then executes the C++ code and verifies that the generated code is functionally equivalent to the MATLAB code.
classdef tEquivalenceBuildOptions < matlabtest.coder.TestCase methods (Test) function tMyAdd(testCase) cfg = coder.config("dll",ecoder=true); cfg.TargetLang = "C++"; cfg.EnableDynamicMemoryAllocation = false; buildResults = build(testCase,"myAdd",Inputs={1,2}, ... Configuration=cfg); executionResults = execute(testCase,buildResults); verifyExecutionMatchesMATLAB(testCase,executionResults) end end end
CodeGenerationArguments
name-value argument in the build
method with values from the options
(MATLAB Coder)
input argument for the codegen
(MATLAB Coder) function. For example, you can
generate C++ code for a function called myAdd
by using this
code:buildResults = build(testCase,"myAdd", ... Inputs={1,2},CodeGenerationArguments={"-lang:c++"});
Test Existing Generated C/C++ Code
You can generate C/C++ code outside of a test and verify the code by using an
equivalence test. To test existing generated C/C++ code for equivalence, use codegen
(MATLAB Coder) to generate C/C++ code and pass the file path for the MEX
function to the execute
method.
This example code shows how to generate code for the myAdd
function
outside of a
test:
codegen myAdd -args {1,2}
classdef tEquivalenceExistingCode < matlabtest.coder.TestCase methods (Test) function tMyAdd(testCase) mexPath = "C:\Users\jdoe\generatedCodeTests\codegen" + ... "\mex\myAdd\myAdd_mex.mexw64"; executionResults = execute(testCase,mexPath,Inputs={5,5}); verifyExecutionMatchesMATLAB(testCase,executionResults) end end end
Execute and Verify in SIL or PIL Mode
With Embedded Coder, you can verify generated C/C++ code with software-in-the-loop (SIL) and processor-in-the-loop (PIL) execution. For more information about SIL and PIL execution, see Code Verification Through Software-in-the-Loop and Processor-in-the-Loop Execution (Embedded Coder).
SIL Verification
To verify generated C/C++ code in SIL mode, generate code for a LIB or DLL target. By default, the equivalence test verifies LIB and DLL targets in SIL mode even if the verification mode is set to none.
This example equivalence test generates a static C library from the function
myAdd
and executes and verifies the function in SIL
mode.
classdef tEquivalenceSIL < matlabtest.coder.TestCase methods (Test) function tMyAddSIL(testCase) buildResults = build(testCase,"myAdd",Inputs={1,2}, ... Configuration="lib"); executionResults = execute(testCase,buildResults); verifyExecutionMatchesMATLAB(testCase,executionResults) end end end
PIL Verification
To verify generated C/C++ code with PIL verification, in your equivalence test method:
Use
coder.config
(MATLAB Coder) to create an Embedded Coder configuration parameter object.Set the
VerificationMode
property toPIL
.Configure the
Hardware
(MATLAB Coder) property of your configuration parameter object for your processor hardware by usingcoder.hardware
(MATLAB Coder).
This example equivalence test generates a static C library from the
function myAdd
for an ARM®
Cortex®-M3 board. It then executes and verifies the generated code in PIL
mode.
classdef tEquivalencePIL < matlabtest.coder.TestCase methods(Test) function tMyAddPIL(testCase) cfg = coder.config("lib","ecoder",true); cfg.VerificationMode = "PIL"; cfg.Hardware = coder.hardware("ARM Cortex-M3 (QEMU)"); buildOut = build(testCase,"myAdd.m",Inputs={1,2}, ... Configuration=cfg); executionOut = execute(testCase,buildOut); verifyExecutionMatchesMATLAB(testCase,executionOut); end end end
Run Tests and View Results
You can run equivalence tests by using the:
runtests
function at the MATLAB command lineRun Tests button in the MATLAB Editor toolstrip in the Editor tab
Run button in the Test Browser
Run button in the MATLAB Test Manager
Run button in the Code Quality Dashboard
For more information, see Run MATLAB Tests.
See Also
Classes
matlabtest.coder.TestCase
|matlabtest.coder.results.BuildResults
|matlabtest.coder.results.ExecutionResults