function result = runElkTest(testCase, mode)
% unit testing module for ELK
%
% Syntax: runElkTest
%
% A set of test cases is executed that covers a large percentage of the
%   provided features. It is recommended to execute it once for a new
%   installation to become aware of issues that cannot be covered during
%   development: MATLAB version, compiler version, operating system.
%
% You need to install the MATLAB xunit Test Framework to run this function.
%   It can be obtained, in the <a href="http://www.mathworks.com/matlabcentral/fileexchange/22846-matlab-xunit-test-framework">MATLAB Central</a>.
%
% See also: configElk

% The elk-library: convex geometry applied to crystallization modeling.
%   Copyright (C) 2012 Alexander Reinhold
%
% This program is free software: you can redistribute it and/or modify it 
%   under the terms of the GNU General Public License as published by the 
%   Free Software Foundation, either version 3 of the License, or (at your 
%   option) any later version.
%
% This program is distributed in the hope that it will be useful, but 
%   WITHOUT ANY WARRANTY; without even the implied warranty of 
%   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
%   General Public License for more details.
%
% You should have received a copy of the GNU General Public License along 
%   with this program.  If not, see <http://www.gnu.org/licenses/>.

%% Setup test sets
% the following registers folder and case-name pairs OR aggregates already
%   registered pais to test-sets
testList.tmpThis =  {'polytope/test', 'testPolytopeConversion:testConvertHrepToVrepUnbounded'};
testList.polytopeCore = {'polytope/test', 'testPolytopeCore'};
testList.polytopeConversion = {'polytope/test', 'testPolytopeConversion'};
testList.polytopeOperation = {'polytope/test', 'testPolytopeOperation'};
testList.polytopeView = {'polytope/test', 'testPolytopeView'};
testList.polytopeMeasure = {'polytope/test', 'testPolytopeMeasure'};
testList.polytopeBugList = {'polytope/test', 'testPolytopeBugList'};
testList.crystalCore = {'crystal/test', 'testCrystal'};
testList.decompositionCore = {'decomposition/test', 'testDecompositionCore'};
testList.distributionCore = {'distribution/test', 'testDistributionCore'};
testList.basicTest = {...
    testList.polytopeCore, ...
    testList.polytopeConversion, ...
    testList.polytopeOperation, ...
    testList.polytopeView, ...
    testList.polytopeMeasure, ...
    testList.crystalCore, ...
    testList.decompositionCore, ...
    testList.distributionCore};
testList.extraTest = {...
    testList.polytopeBugList};

%% Input handling
if ~exist('mode', 'var') || isempty(mode)
    mode = 'manual';
end
if ~exist('testCase', 'var') || isempty(testCase)
    testCase = 'basicTest';
end
if ~isfield(testList, testCase)
    error('elk:test:invalidCase', 'The specified test case does not exist, try ''basicTest''.');
end
result = 0;

%% Initialize utilities and location
callLocation = pwd;
myLocation = fileparts(mfilename('fullpath'));
cd(myLocation);
run ../../extern/mxunit/configMxUnit

%% Start tests
clc
% ensure expected format: cell array of cell arrays of path/case-name
%   pairs.
thisTestSet = testList.(testCase);
if ischar(thisTestSet{1})
    thisTestSet = {thisTestSet};
end
% cycle through file/case-name pairs
for iTestCase = 1:length(thisTestSet)
    thisFolder = fullfile(['..' filesep thisTestSet{iTestCase}{1}]);
    thisFile = thisTestSet{iTestCase}{2};
    thisLogFile = [thisTestSet{iTestCase}{2} '.log'];
    
    % execute from test-file location (these are private functions)
    cd(thisFolder)
    switch mode
        case 'auto'
            thisResult = runtests(thisFile, '-verbose', ...
                '-logfile', thisLogFile);
            type(thisLogFile);
        case 'manual'
            thisResult = runtests(thisFile);
            disp(' ')
            disp('--------------------------------------------------------------------------');
        otherwise
            error('elk:test:invalidCase', ...
                'The specified test mode does not exist, try ''manual'' or ''auto''.');
    end
    % go back to /test folder
    cd(myLocation);
    
    % store number of passed tests
    result = result + thisResult;
end

%% post conditioning
% give a wanring on changed search path
warning OFF BACKTRACE
warning('elk:searchPath', 'MATLAB search path was changed to use mxunit.');
warning ON BACKTRACE
% go back to callers location
cd(callLocation)

%% display summary
disp('');
if result == length(thisTestSet)
    disp(['SUMMARY: PASSED (' num2str(result) ' out of ' ...
          num2str(length(thisTestSet)) ')']);
else
    disp(['SUMMARY: FAILED (' num2str(result) ' out of ' ...
          num2str(length(thisTestSet)) ')']);
    error('elk:test:issuesFound', 'unit testing found issues (see above)');
end

%% handle output
if nargout == 0
    clear result;
end

end
