%% C Code Verification with Simulink Test
% Perform verification and coverage analysis for C Code used in a model.

% Copyright 2018 The MathWorks, Inc.


%%
% This example shows how to verify C code with two tests: An interactive
% test using HMI controls, and a logical test of the code output during
% simulation.

%%
% The C Code is integrated into a model with a C Caller block. The tests
% use the
% Test Manager, test harnesses, Test Sequence block, Test Assessment block,
% and Simulink(R) Dashboard blocks. Test results include signal outputs and
% model coverage. |verify| statements assess the C code during simulation.

%% Open the Example Project
% 1. Create and open a working copy of the Simulink
% Project files. 
% The models and test harness files are in the |Models| folder.
% The source and header files for the custom C code are in the |CCode|
% folder. The test file is in the |Tests| folder.
[projectFolder,~]=matlab.internal.project.example.projectDemoSetUp...
    (fullfile(matlabroot,'toolbox','simulinktest','simulinktestdemos',...
    'sltestCCodeIntegration.zip'),[],[]);
proj = simulinkproject(projectFolder);

%%
% 2. Open the |sltestCruiseControlExample| model. 
mdl = 'sltestCruiseControlExample';
open_system(mdl);

%%
% The block |C Function Caller| integrates C code defined in
% |RejectDoublePress.c|. The C code is a utility
% function that detects when the |Coast/Set| and
% |Accelerate/Resume| inputs are simultaneously set to |true| by the
% user, and outputs |false| for both signals. Otherwise, the input values
% are transferred to the outputs:
%
%   void RejectDoublePress(unsigned char CoastSetSwIN, unsigned char AccelResSwIN, 
%   unsigned char *CoastSetSwOUT, unsigned char *AccelResSwOUT)
%   {
%     unsigned char LogicalOperator;
%     LogicalOperator = !(CoastSetSwIN && AccelResSwIN);
%     *CoastSetSwOUT = (LogicalOperator && CoastSetSwIN);
%     *AccelResSwOUT = (LogicalOperator && AccelResSwIN);
%   }


%% Interactive Testing with HMI Controls
% The C Caller block has two test harnesses. Open
% |sltestCruiseControlSimpleHarness|:
% 
% 1. Click the harness perspective badge at the bottom right corner of the
% |C Function Caller| block.
%
% 2. Click the |sltestCruiseControlSimpleHarness| tile.
sltest.harness.open([mdl, '/C Function Caller'], 'sltestCruiseControlSimpleHarness');

%%
% The test harness implements an interactive test of the
% C algorithm. You can control the |Coast/Set| and |Accelerate/Resume|
% inputs with the slider switches. Lamps display the component output
% values. 
%
% 3. Run the test harness simulation by clicking *Play* in the Simulink
% toolstrip.
%
% 4. Toggle the inputs to try various input combinations. Verify the
% expected behavior, in particular that the outputs are |false| when both
% inputs are |true|.
%
% 5. Click the *Stop* button to end the simulation.
%%
% 6. Close the test harness.
close_system('sltestCruiseControlSimpleHarness', 0);

%% Logical Test with the Test Sequence Block
%
% You can use a Test Sequence block to test combinations of inputs and
% verify expected behavior. Open the
% |sltestCruiseControlTestSeqHarness| harness, the Test Sequence block, and
% the Test Assessment block. 
sltest.harness.open([mdl, '/C Function Caller'], 'sltestCruiseControlTestSeqHarness');
open_system('sltestCruiseControlTestSeqHarness/Test Sequence');
open_system('sltestCruiseControlTestSeqHarness/Test Assessment');

%%
% The Test Sequence block
% steps through the four possible Boolean input combinations. The Test
% Assessment block uses the active step of the Test
% Sequence block to activate verifications of the expected outputs for each
% of the corresponding input conditions. In particular, when both inputs are
% |true|, both outputs are verified to be |false|.


%% Run the Logical Test
% Run the test and view the results of the |verify| statements:
%
% 1. Open the Test Manager.
sltest.testmanager.view;

%%
% 2. Open the |sltestCruiseControlCTests.mldatx| test file. The test file
% has a single test case that runs the |sltestCruiseControlTestSeqHarness|
% test harness.
sltest.testmanager.load('sltestCruiseControlCTests.mldatx');

%%
% 3. Run the test file by clicking *Play* in the Test Manager toolstrip.
sltest.testmanager.run;

%%
% Each |verify| statement in the Test Assessment block
% produces a signal trace in the test results. Verify that each statement 
% passes for the time steps that it is active.
%%
% <<ccode_integration_verify_result.png>>

%%
% The test also returns coverage for the C Code. In the *Results and
% Artifacts* pane of the Test Manager, highlight the test case and
% expand the *Aggregated Coverage Results* section. The code coverage is
% 100% for decision, condition, and MCDC metrics. For more information, see
% <docid:slcoverage_ug#bumk_v9>.

%%
% <<ccode_integration_cov_result.png>>

%% Cleanup
% Clear results, close open windows, and close models.
close_system(mdl, 0);
clear mdl;
sltest.testmanager.clear;
sltest.testmanager.clearResults;
close(proj);
sltest.testmanager.close;
Simulink.sdi.close;

displayEndOfDemoMessage(mfilename)

