function [passed,results] = run_meq_tests(test_case, coverage_report)
% Template test runner for toolbox tests
%
% [+MEQ MatlabEQuilibrium Toolbox+] Swiss Plasma Center EPFL Lausanne 2022. All rights reserved.

% F. Felici, EPFL federico.felici@epfl.ch

if nargin==0 || isempty(test_case)
  test_case = 'basic'; % default
end

if nargin < 2
  coverage_report = false; % default
end

if coverage_report
  assert(~verLessThan('matlab','9.6.0'),'coverage_report=true needs MATLAB 9.6.0 or later');
  assert( strcmpi(test_case,'coverage'),'coverage_report=true should only be used with test_case=''coverage''');
end

needXML=~isempty(getenv('GITLAB_CI')) && ~verLessThan('matlab','8.6.0');
needCOV=~isempty(getenv('GITLAB_CI')) && ~verLessThan('matlab','9.6.0') || coverage_report;

%% Default outputs
passed=false; results=[];

%% Import some classes we need
import matlab.unittest.selectors.HasTag;
import matlab.unittest.constraints.ContainsSubstring;
import matlab.unittest.selectors.HasName;
import matlab.unittest.TestRunner

%% Paths
tbxpath = fileparts(mfilename('fullpath'));
projectpath = getenv('CI_PROJECT_DIR');
if isempty(projectpath), projectpath = tbxpath; end
% add local genlib for testing purposes
P=path; cleanup = onCleanup(@() path(P));
addpath(tbxpath,'genlib');

%% Name
tbxname = getenv('TBXTARGET');
if isempty(tbxname)
  % Fallback value: name of folder
  [~,tbxname] = fileparts(tbxpath);
end

%% Generate test suite
testspath = fullfile(tbxpath,'tests');

lastwarn('',''); % clear last warning
suite_all = matlab.unittest.TestSuite.fromFolder(testspath);
[~,s] = lastwarn();
if isequal(s,'MATLAB:unittest:TestSuite:FileExcluded')
  fprintf('File excluded during test suite creation - possible syntax errors in a test class\n');
  return
end
% Identify tests without any tags
mask = cellfun(@isempty,{suite_all.Tags});
if any(mask)
  fprintf('Some tests do not have TestTags set and are unreachable from run_meq_tests:\n');
  fprintf('\t%s\n',suite_all(mask).Name);
  return
end
useparallel = false; % switch for parallel testing using parallel toolbox
paravail = ~isempty(ver('distcomp')); % check if parallel toolbox is installed

fprintf('running %s\n',mfilename('fullpath'))
switch lower(test_case)
  case {'unit','basic'}
    s = HasTag('Unit')&~HasTag('Slow');
  case {'integration'}
    s = HasTag('Integration');
  case 'tcv'
    s = HasTag('TCV');
  case 'create'
    s = HasTag('CREATE');
  case 'simulink'
    s = HasTag('Simulink')&~HasTag('SLX-checks'); 
  case 'slx-checks'
    s = HasTag('SLX-checks');
  case 'fgs'
    s = HasTag('fgs');
  case 'fge'
    s = HasTag('fge');
  case 'fgelin'
    s = HasTag('fgelin');
  case 'profile'
    s = HasTag('profile');
  case 'liuqe-tcv-all'
    useparallel = true;
    if paravail && isempty(gcp('nocreate'))
      parpool(4);
    end
    suite_all = testsuite('tests/slow');
    s = HasName(ContainsSubstring('liutcv_tests_all'));
  case 'coverage'
    s = ~HasTag('Slow')&~HasTag('SLX-checks');
  otherwise
    % assume tag with this name
    s = HasTag(test_case);
end
suite = suite_all.selectIf(s);

if isempty(suite)
  fprintf('\nEmpty test suite returned for TestTag=''%s''\n',test_case); return;
end

%% run it
fprintf('Main Test File: %s\nStart test case: %s\n%s\n\n',mfilename('fullpath'),test_case,datestr(now));
runner = matlab.unittest.TestRunner.withTextOutput;
if needXML || needCOV
  prefix = sprintf('test_%s',tbxname);
  suffix = version('-release');
end
if needXML
  % Add some JUnit XML file with tests results
  xmlFile = fullfile(projectpath,sprintf('%s_%s_%s_junit.xml',prefix,test_case,suffix));
  p = matlab.unittest.plugins.XMLPlugin.producingJUnitFormat(xmlFile);
  runner.addPlugin(p)
end
if needCOV
  % Add some code coverage report
  switch lower(test_case)
    case 'coverage'
      % Produce HTML report
      reportFolder = fullfile(projectpath,sprintf('%s_%s_cov',prefix,suffix));
      reportFormat = matlab.unittest.plugins.codecoverage.CoverageReport(reportFolder);
    otherwise
      % Produce XML file in Cobertura format (for Gitlab MR viz.)
      xmlFile = fullfile(projectpath,sprintf('%s_%s_%s_cov.xml',prefix,test_case,suffix));
      reportFormat = matlab.unittest.plugins.codecoverage.CoberturaFormat(xmlFile);
  end
  p = matlab.unittest.plugins.CodeCoveragePlugin.forFolder({tbxpath,fullfile(tbxpath,'mexm'),testspath},...
    'IncludingSubfolders',false,'Producing',reportFormat);
  runner.addPlugin(p)
end
if useparallel && paravail
  results = runInParallel(runner,suite);
else
  results = run(runner,suite);
end
fprintf('\nTotal test duration: %5.2fs\n',sum(table(results).Duration))

%%

% close any parallel pools
if paravail, delete(gcp('nocreate')); end

%% Display results
fprintf('Passed tests: \n');
disp(table(results([results.Passed])));
if all([results.Passed])
  fprintf('\nPassed all tests\n')
  passed = true;
elseif any([results.Failed])
  fprintf('\nSome tests Failed\n')
  disp(table(results([results.Failed])))
  passed = false;
elseif any([results.Incomplete])
  fprintf('\nSome tests Incomplete\n')
  disp(table(results([results.Incomplete])));
  passed = true; % pass tests even if some were skipped
else
  % the conditions above should cover all cases, otherwise 
  error('something is very wrong - please check')
end

end
