Main Content

Unit Test External C Code with MATLAB Coder

This example shows how to test external C code by using MATLAB® unit tests with MATLAB® Coder™.

If you want to test C code, you can use MATLAB Coder to bring the code into MATLAB. You can then write unit tests by using the MATLAB testing framework. You can write richer, more flexible tests by taking advantage of the advanced numerical computing and visualization capabilities of MATLAB.

This example shows how to:

  1. Bring your C code into MATLAB as a MEX function that you generate with MATLAB Coder.

  2. Write a unit test by using the MATLAB testing framework.

  3. Run the test on the MEX function.

如果你有嵌入ded Coder®, you can run unit tests on generated standalone code (static library or shared library) by using the unit tests with software-in-the-loop (SIL) execution or processor-in-the-loop (PIL) execution.

Examine the Files

To access the files that this example uses, clickOpen Script.

kalmanfilter.c

kalmanfilter.cis the C function that the example tests. It estimates the position of a moving object based on its past positions.

kalmanfilter.h

kalmanfilter.his the header file forkalmanfilter.c.

position.mat

position.matcontains the positions of the object.

callKalmanFilter.m

callKalmanFiltercallskalmanfilterby usingcoder.ceval.

function[a,b] = callKalmanFilter(position)% Copyright 2014 - 2016 The MathWorks, Inc.numPts = size(position,2); a = zeros(2,numPts,'double');b = zeros(2,numPts,'double');y = zeros(2,1,'double');% Main loopforidx = 1: numPts z = position(:,idx);% Get the input data% Call the initialize functioncoder.ceval('kalmanfilter_initialize');% Call the C functioncoder.ceval('kalmanfilter',z,coder.ref(y));% Call the terminate functioncoder.ceval('kalmanfilter_terminate');(:, idx) = [z (1);z (2)];b (:, idx) = [y (1);y (2)];endend

TestKalmanFilter.m

TestKalmanFiltertests whether the error between the predicted position and actual position exceeds the specified tolerance. The unit tests are class-based unit tests. For more information, seeAuthor Class-Based Unit Tests in MATLAB.

Although you want to test the MEX function, the unit tests inTestKalmanFiltercall the original MATLAB function from which you generated the MEX function. When MATLAB Coder runs the tests, it replaces the calls to the MATLAB function with calls to the MEX function. You cannot run these tests directly in MATLAB because MATLAB does not recognize thecoder.cevalcalls incallKalmanFilter.

classdefTestKalmanFilter < matlab.unittest.TestCase% Copyright 2014 - 2016 The MathWorks, Inc.methods( Test )functionSSE_LessThanTolerance( testCase ) loadposition.mat; [z,y] = callKalmanFilter( position ); tolerance = 0.001;% tolerance of 0.0001 will breakA = z-1000*y; error = sum(sum(A.^2)); testCase.verifyLessThanOrEqual( error, tolerance);% For debuggingplot_kalman_filter_trajectory(z,1000*y);endfunctionSampleErrorLessThanTolerance( testCase ) loadposition.mat; [z,y] = callKalmanFilter( position ); tolerance = 0.01;% tolerance of 0.001 will breakA = z-1000*y; testCase.verifyEqual(1000*y, z,'AbsTol', tolerance);% For debuggingplot_kalman_filter_trajectory(z,1000*y); [value, location] = max(A(:)); [R,C] = ind2sub(size(A),location); disp(['Max value 'num2str(value)' is located at ['num2str(R)','num2str(C)']']);endendend

run_unit_tests_kalman.m

run_unit_tests_kalmancallsrunteststo run the tests inTestKalmanFilter.m.

% Run unit tests% Copyright 2014 - 2016 The MathWorks, Inc.runtests('TestKalmanFilter')

plot_kalman_filter_trajectory.m

plot_kalman_filter_trajectoryplots the trajectory of the estimated and actual positions of the object. Each unit test calls this function.

Generate MEX and Run Unit Tests in the MATLAB Coder App

To open the MATLAB Coder app, on the MATLAB ToolstripAppstab, underCode Generation, click the MATLAB Coder app icon.

To prepare for code generation, advance through the app steps.

  • On theSelect Source Filespage, specify that the entry-point function iscallKalmanFilter.

  • On theDefine Input Typespage, specify that the input argumentxis a 2-by-310 array of doubles.

The unit tests load the variablepositionfromposition.matand passpositiontocallKalmanFilter. Therefore, the input tocallKalmanFiltermust have the properties thatpositionhas. In the MATLAB workspace, if you loadposition.mat, you see thatpositionis a 2-by-310 array of doubles.

  • Skip theCheck for Run-Time Issuesstep for this example.

Configure the app for MEX code generation. Specify the names of the C source and header files becausecallKalmanFilterintegrates external C code.

  1. ForBuild type, specifyMEX.

  2. ClickMore Settings.

  3. On theCustom Codetab:

  • UnderCustom C Code for Generated Files, selectHeader file. In the custom code field, enter#include "kalmanfilter.h".

  • In theAdditional source filesfield, enterkalmanfilter.c.

To generate the MEX function, clickGenerate.

Run the unit tests on the generated MEX.

  1. ClickVerify Code.

  2. In the field for the test file, specifyrun_unit_tests_kalman.

  3. Make sure that you setRun usingtoGenerated code.

  4. ClickRun Generated Code.

When the app runs the test file, it replaces calls tocallKalmanFilterin the unit test with calls tocallKalmanFilter_mex. The unit tests run on the MEX function instead of the original MATLAB function.

The app displays the test output on theTest Outputtab. The unit tests pass.

From the plots, you can see that the trajectory of the estimated position converges with the trajectory of the actual position.

Run Unit Tests After Modifying C Code

When you modify the C code, to run the unit tests:

  1. Regenerate the MEX function for the MATLAB function that calls the C code.

  2. Repeat the verification step.

For example, modifykalmanfilter.cso that the value assigned toy[r2]is multiplied by 1.1.

y[r2] += (double)d_a[r2 + (i0 << 1)] * x_est[i0] * 1.1;

Editkalmanfilter.coutside of the app because you can use the app to edit only MATLAB files listed in the源代码pane of the app.

To generate the MEX function for the modified function, clickGenerate.

To run the unit tests:

  1. ClickVerify Code.

  2. Make sure that you set the test file torun_unit_testsandRun usingtoGenerated code

  3. ClickRun Generated Code.

The tests fail because the error exceeds the specified tolerance.

The plots show the error between the trajectory for the estimated position and the trajectory for the actual position.

Generate MEX and Run Unit Tests by Using the Command-Line Workflow

You can use the command-line workflow to run unit tests on external C code by usingcoder.runTest. Specify a test file that runs the unit tests on the MATLAB function that calls your C code.

Generate a MEX function for the MATLAB function that calls your C code. For this example, generate MEX forcallKalmanFilter.

Create a configuration object for MEX code generation.

cfg = coder.config('mex');

Specify the external source code and header file.

cfg.CustomSource ='kalmanfilter.c'; cfg.CustomHeaderCode ='#include "kalmanfilter.h"';

To determine the type for the input tocallKalmanFilter, load the position file.

loadposition.mat

To generate the MEX function, runcodegen. Specify that the input tocallKalmanFilter有相同的类型position.

codegen-configcfgcallKalmanFilter-argsposition
Code generation successful.

Run the units tests on the MEX function. Specify that the test file isrun_unit_tests_kalmanand that the function iscallKalmanfilter. Whencoder.runTestruns the test file, it replaces calls tocallKalmanFilterin the unit test with calls tocallKalmanFilter_mex. The unit tests run on the MEX function instead of the original MATLAB function.

coder.runTest('run_unit_tests_kalman','callKalmanFilter')
Running TestKalmanFilter Current plot held .Current plot held Max value 0.0010113 is located at [2,273] . Done TestKalmanFilter __________ ans = 1x2 TestResult array with properties: Name Passed Failed Incomplete Duration Details Totals: 2 Passed, 0 Failed, 0 Incomplete. 31.1085 seconds testing time.

See Also

Related Topics