Main Content

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:

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
For more information about test classes, see Class-Based Unit Tests.

Equivalence tests typically do three things:

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
This equivalence test builds C code for a MEX target with inputs set to (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
This test runs twice. The first time, it executes 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
Alternatively, you can use the 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}
This example equivalence test executes and verifies the existing generated C/C++ code:
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:

  1. Use coder.config (MATLAB Coder) to create an Embedded Coder configuration parameter object.

  2. Set the VerificationMode property to PIL.

  3. Configure the Hardware (MATLAB Coder) property of your configuration parameter object for your processor hardware by using coder.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:

For more information, see Run MATLAB Tests.

See Also

Classes

Functions

Related Examples

More About