% UTP_RUN  Runs the UTP tests found in the 'utps' directory. If no output
% argument is specified a results report is generated and printed to screen,
% otherwise the results are returned.
%
% USAGE:
% 
%   >> % run all the tests in the 'utps' directory
%   >> utp_run();
%
%   >> % run the UTPs with the given names
%   >> utp_run('utp_classname_fcn1', 'utp_classname_fcn2', ...);
%
%   >> % run a reduced set of UTPs operating on the listed classes
%   >> utp_run('classname1', 'classname2', ...);
%
% EXAMPLES:
%
%   >> utp_run();
%   >> utp_run('utp_ao_ao');
%   >> utp_run('utp_ao_ao', 'utp_ao_abs');
%   >> utp_run('ao', 'tsdata', 'fsdata');
%   >> utp_run('ao', 'tsdata', 'fsdata', pl);
%
%  pl keys
%     'tests'         - cell array of strings above
%     'no repository' - true/false
%     'skip tests'    - cell array of tests to skip
%     'skip classes'  - cell array of classes to skip
%
%
%
% $Id: utp_run.m,v 1.20 2010/08/09 16:38:49 ingo Exp $

function varargout = utp_run(varargin)
  
  % save current path
  oldpath = path();
  
  [pl, dummy, rest] = utils.helper.collect_objects(varargin(:), 'plist');
  
  % Make sure that pl is a PLIST
  pl = combine(plist(), pl);
  
  skipClasses  = pl.find('skip classes', '');
  skipTests    = pl.find('skip tests', '');
  tests        = pl.find('tests', '');
  noRepository = pl.find('no repository', false);

  hostname = pl.find('hostname', '130.75.117.67');
  database = pl.find('database', 'ltpda_test');
  username = pl.find('username', 'tester');
  password = pl.find('password', 'a1b2c3d4');
  
  setappdata(0, 'LTPDAUtpRepositoryHostname', hostname);
  setappdata(0, 'LTPDAUtpRepositoryDatabase', database);
  setappdata(0, 'LTPDAUtpRepositoryUsername', username);
  setappdata(0, 'LTPDAUtpRepositoryPassword', password);
  
  if ~isempty(rest) && ~isempty(tests)
    tests = [reshape(cellstr(tests), 1, []), reshape(rest, 1, [])];
  elseif ~isempty(tests)
    tests = cellstr(tests);
  elseif ~isempty(rest)
    tests = rest;
  end

  try
    % add support functions and UTPs folders to path
    utppath = fileparts(which('utp_run'));
    addpath(genpath(utppath));

    % list of the classes for which we have UTPs
    classes = {};
    
    % cell array to hold UTP function names to run
    utps = {};
    
    % check for input arguments
    if numel(tests) > 0
      
      % check if input argument is a list of UTP function names
      if all(strncmp(tests, 'utp_', 4))
        % add the given UTPs to the list of test functions to run
        for kk = 1:numel(tests)
          uname = tests{kk};
          % check if the given UTPs exist
          if exist(uname, 'file') == 2
            utps = addUtpTest(utps, tests(kk));
          else
            error('### test ''%s'' not found\n', uname);
          end
        end
      else
        % assume input argument is a list of classes
        for kk = 1:numel(tests)
          cname = tests{kk};          
          % check if it exists
          if exist(fullfile(utppath, 'utps', cname), 'dir')
            classes = [classes {cname}];
          else
            error('### test class ''%s'' not found\n', cname);
          end
        end
      end
      
    else

      % list of all the classes we have UTPs for
      d = dir(fullfile(utppath, 'utps'));
      for kk = 1:numel(d)
        if ~d(kk).isdir
          continue;
        end
        if d(kk).name(1) == '.'
          continue;
        end
        if strcmp(d(kk).name, 'CVS')
          continue;
        end
        
        % Skip classes
        if utils.helper.ismember(d(kk).name, skipClasses)
          continue;
        end
        classes = [classes {d(kk).name}];
      end
      
    end

    % add to the UPTs function name list the UTPs for each class in the list
    for kk = 1:numel(classes)
      mfiles = dir(fullfile(utppath, 'utps', classes{kk}));
      % identify all UTP functions
      for jj=1:length(mfiles)
        [pathstr, name, ext] = fileparts(mfiles(jj).name);
        if ~strcmp(ext, '.m')
          continue;
        end
        try
          utps = addUtpTest(utps, name);
        end
      end
    end

    % number of collected UTPs to run
    fprintf('%d UTPs to run\n', numel(utps));
    
    % initialize timer to measure UTPs execution time
    tic();
    
    % call each UTP function and collect the results
    results = [];
    for jj=1:length(utps)
      try
        results = [results eval(utps{jj})]
      catch ex
        % report the error failure in running the UTP
        stack.name = 'xx';
        message = ['exception: ' ex.message];
        results = [results utp_prepare_result(false, false, stack, utps{jj}, message)];
        % show error on console
        fprintf(2, ['\n' ex.getReport()]);
        fprintf(1, '\n');
      end
    end
    
    % set output
    if nargout == 1
      varargout{1} = results;
    else
      display_utp_results(results)
    end

  catch ex
    % restore original path
    path(oldpath);
    % remove appdata
    rmappdata(0, 'LTPDAUtpRepositoryHostname');
    rmappdata(0, 'LTPDAUtpRepositoryDatabase');
    rmappdata(0, 'LTPDAUtpRepositoryUsername');
    rmappdata(0, 'LTPDAUtpRepositoryPassword');
    % propagate exception
    rethrow(ex);
  end

  % restore original path
  path(oldpath);
  % remove appdata
  rmappdata(0, 'LTPDAUtpRepositoryHostname');
  rmappdata(0, 'LTPDAUtpRepositoryDatabase');
  rmappdata(0, 'LTPDAUtpRepositoryUsername');
  rmappdata(0, 'LTPDAUtpRepositoryPassword');

  
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %
  % FUNCTION:    addUtpTest
  %
  % DESCRIPTION: Local method which adds an UTP to the UTP list if it pass
  %              all conditions.
  %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  function utpsLocal = addUtpTest(utpsLocal, utpIn)

    utpIn = cellstr(utpIn);
    
    % Check if the UTP name is a UTP
    if feval(utpIn{1}, 'isutp')

      addUTP = true;
      % Skip the UTPs if it needs a repository.
      if noRepository && feval(utpIn{1}, 'needs repository') == 2
        addUTP = false;
      end
      % Skip the UTPs if it is in the skil list.
      if utils.helper.ismember(utpIn{1}, skipTests)
        addUTP = false;
      end
    
      if addUTP
        utpsLocal = [utpsLocal utpIn];
      end
      
    end
    
  end
  
end

