%% Use Justification Rules to Filter Code Coverage Outcomes
% This example shows how to filter code coverage outcomes in the coverage
% report after collecting coverage for a model in software-in-the-loop
% (SIL) or processor-in-the-loop (PIL) mode.

% Copyright 2020 The MathWorks, Inc.

%%
%

modelName = 'slvnvdemo_counter';
open_system(modelName)

%% Generate Code Coverage Data
% First, put the model into SIL/PIL mode. In the Simulink&reg; window,
% click *Apps* and, under *Code Verification, Validation, and Test*, click
% *SIL/PIL Manager*. On the *SIL/PIL* tab, change *Automated Verification*
% to *SIL/PIL Simulation Only*.

covSet = Simulink.SimulationInput(modelName);
covSet = covSet.setModelParameter('CovEnable','on');
covSet = covSet.setModelParameter('CovMetricStructuralLevel','MCDC');
covSet = covSet.setModelParameter('CovSFcnEnable','on');
covSet = covSet.setModelParameter('CovSaveSingleToWorkspaceVar','on');
covSet = covSet.setModelParameter('CovSaveName','covData');
covSet = covSet.setModelParameter('SimAnalyzeCustomCode','on');
covSet = covSet.setModelParameter('SimulationMode','Software-In-The-Loop');
covSet = covSet.setModelParameter('RTWVerbose','off');

%%
% In this example model, coverage is enabled by default. If you are using
% your own model, enable coverage in the *Configuration Parameters* window.
% For more information about coverage settings, see
% <docid:slcoverage_ug#bstx626-1 Specify Coverage Options>.

%%
% Simulate the model and collect coverage by clicking *Run SIL/PIL*. When
% you simulate the model, a docked pane opens next to the Simulink&reg;
% model. Click the *Coverage Details* tab to see the code coverage report.

%%
%
% <<../dockedCovRpt.png>>
%

simOut = sim(covSet);
cvmodelview(covData);

%% Justify Missing Code Coverage Using Coverage Filters
% If your model has unreachable logic that is intentional, such as defensive
% model design or exception handling, you can justify this missing
% coverage using coverage filters.

%%
% The *Summary* section of the code coverage report
% links to each source file and function. In this example, click
% |slvnvdemo_counter_step|. The code coverage report jumps to the function
% named |slvnvdemo_counter_step|. In section 2.1, you can see that both
% conditions inside the decision |(!(slvnvdemo_counter_U.upper >=z
% rtb_input)) ||| (!rtb_inputGElower)| are false for all time steps. 

%%
%
% <<../unfilteredRpt.png>>
%

sel1 = slcoverage.CodeSelector(slcoverage.CodeSelectorType.ConditionOutcome,...
    'slvnvdemo_counter.c','slvnvdemo_counter_step',...
    '(!(slvnvdemo_counter_U.upper >= rtb_input)) || (!rtb_inputGElower)',1,1,1);

%%
% To justify a missing coverage outcome, in the *Conditions
% analyzed* table, next to the condition |slvnvdemo_counter_U.upper >=
% rtb_input|, click the *Add justification rule* icon. The Coverage Results
% Explorer opens and creates a filter rule to justify the |false| outcome
% of the condition |slvnvdemo_counter_U.upper >= rtb_input|.

%%
%
% <<../resultsExplorer1Filter.png>>
%

%% 
% In the Filter Editor pane, set the *Name*
% field to |myCodeCovFilter|. You can set the *Description* field to
% any descriptive text. The *Filter Rules* section has two tabs, *Model* and
% *Code*. In this case, the filter appears on the *Code* tab
% because you are filtering from the code coverage report. You can
% double-click the *Rationale* field to add a reason, for
% example "Expected result."

filt = slcoverage.Filter;
rule1 = slcoverage.FilterRule(sel1,'Tested elsewhere',...
        slcoverage.FilterMode.Justify);
addRule(filt,rule1);
setFilterName(filt,'myCodeCovFilter');
setFilterDescription(filt,'Justify the conditions inside slvnvdemo_counter_step');

%%
% Near the top of the Filter Editor, under the *Filename* field, click
% *Save as*. In the Save filter window, name the filter file |myCodeCovFilter|. Note
% that the filter name and the filter file name do not have to be the same.

%%
% When you save the filter, the code coverage report updates and displays
% the justified outcome.

%%
%
% <<../filteredOutcome1.png>>
%

%%
% Justify the false case of the second condition by clicking the *Add
% justification rule* filter next to |rtb_inputGElower| and following the
% steps listed above. This second rule is added to the same filter file
% that you created for the first rule.

sel2 = slcoverage.CodeSelector(slcoverage.CodeSelectorType.ConditionOutcome,...
    'slvnvdemo_counter.c','slvnvdemo_counter_step',...
    '(!(slvnvdemo_counter_U.upper >= rtb_input)) || (!rtb_inputGElower)',2,1,1);
rule2 = slcoverage.FilterRule(sel2,'Tested elsewhere',...
        slcoverage.FilterMode.Justify);
addRule(filt,rule2);
save(filt,'myCodeCovFilter');
covData.filter = 'myCodeCovFilter';

%%
%
% <<../resultsExplorer2FilterRules.png>>
%

%%
%
% <<../filteredOutcome2.png>>
%

%%
% You can create a new code coverage report after applying coverage filters
% by clicking *Current Cumulative Data (H)* in the left pane of the
% Coverage Results Explorer, and then clicking *Generate report* at the
% bottom of the *Coverage Data* pane. This link creates a standalone
% report which you can use for archiving or sharing reports.

%%
%
% <<../resultsExplorerCovData.png>>
%

%%
% The summary section of the code coverage report reflects the improved
% condition coverage due to the filter rules. 

cvhtml('covDatRpt',covData)

%%
%
% <<../filteredRptSummary.png>>
%

%%
% Additionally, the code coverage report now shows a section titled
% *Objects Filtered from Coverage Analysis* that displays the filter
% rules and rationales.

%%
%
% <<../objectsFiltered.png>>
%
