Commit Friday evening.
PDFA and EXFO Laser are now part of the family
This commit is contained in:
@@ -0,0 +1,164 @@
|
||||
function saveHashTable(status, varargin)
|
||||
% SAVEHASHTABLE saves the references hashes for the Matlab2Tikz tests
|
||||
%
|
||||
% Usage:
|
||||
% SAVEHASHTABLE(status)
|
||||
%
|
||||
% SAVEHASHTABLE(status, 'dryrun', BOOL, ...) determines whether or not to
|
||||
% write the constructed hash table to file (false) or to stdout (true).
|
||||
% Default: false
|
||||
%
|
||||
% SAVEHASHTABLE(status, 'removedTests', CHAR, ...) specifies which action to
|
||||
% execute on "removed tests" (i.e. test that have a hash recorded in the file,
|
||||
% but which are not present in `status`). Three values are possible:
|
||||
% - 'ask' (default): Ask what to do for each such test.
|
||||
% - 'remove': Remove the test from the file.
|
||||
% This is appropriate if the test has been removed from the suite.
|
||||
% - 'keep': Keep the test hash in the file.
|
||||
% This is appropriate when the test has not executed all tests.
|
||||
%
|
||||
% Inputs:
|
||||
% - status: output cell array of the testing functions
|
||||
%
|
||||
% See also: runMatlab2TikzTests, testMatlab2tikz
|
||||
ipp = m2tInputParser();
|
||||
ipp = ipp.addRequired(ipp, 'status', @iscell);
|
||||
ipp = ipp.addParamValue(ipp, 'dryrun', false, @islogical);
|
||||
ipp = ipp.addParamValue(ipp, 'removedTests', 'ask', @isValidAction);
|
||||
ipp = ipp.parse(ipp, status, varargin{:});
|
||||
|
||||
%% settings
|
||||
suite = status{1}.testsuite; %TODO: handle multiple test suites in a single array
|
||||
filename = hashTableName(suite);
|
||||
READFORMAT = '%s : %s';
|
||||
WRITEFORMAT = [READFORMAT '\n'];
|
||||
|
||||
%% process the hash table
|
||||
oldHashes = readHashesFromFile(filename);
|
||||
newHashes = updateHashesFromStatus(oldHashes, status);
|
||||
writeHashesToFile(filename, newHashes);
|
||||
|
||||
% --------------------------------------------------------------------------
|
||||
function hashes = updateHashesFromStatus(hashes, status)
|
||||
% update hashes from the test results in status
|
||||
oldFunctions = fieldnames(hashes);
|
||||
newFunctions = cellfun(@(s) s.function, status, 'UniformOutput', false);
|
||||
|
||||
% add hashes from all executed tests
|
||||
for iFunc = 1:numel(status)
|
||||
S = status{iFunc};
|
||||
thisFunc = S.function;
|
||||
thisHash = '';
|
||||
if isfield(S.hashStage,'found')
|
||||
thisHash = S.hashStage.found;
|
||||
elseif S.skip
|
||||
if isfield(hashes, thisFunc)
|
||||
% Test skipped, but reference hash present in file
|
||||
% Probably this means that the developer doesn't have access
|
||||
% to a certain toolbox.
|
||||
warning('SaveHashTable:CannotUpdateSkippedTest', ...
|
||||
'Test "%s" was skipped. Cannot update hash!',...
|
||||
thisFunc);
|
||||
else
|
||||
% Test skipped and reference hash absent.
|
||||
% Probably the test is skipped because something is tested
|
||||
% that relies on HG1/HG2/Octace-specific features and we are
|
||||
% in the wrong environment for the test.
|
||||
end
|
||||
else
|
||||
warning('SaveHashTable:NoHashFound',...
|
||||
'No hash found for "%s"!', thisFunc);
|
||||
end
|
||||
if ~isempty(thisHash)
|
||||
hashes.(thisFunc) = thisHash;
|
||||
end
|
||||
end
|
||||
|
||||
% ask what to do with tests for which we have a hash, but no test results
|
||||
removedTests = setdiff(oldFunctions, newFunctions);
|
||||
if ~isempty(removedTests)
|
||||
fprintf(1, 'Some tests in the file were not in the build status.\n');
|
||||
end
|
||||
for iTest = 1:numel(removedTests)
|
||||
thisTest = removedTests{iTest};
|
||||
|
||||
action = askActionToPerformOnRemovedTest(thisTest);
|
||||
switch action
|
||||
case 'remove'
|
||||
% useful for test that no longer exist
|
||||
fprintf(1, 'Removed hash for "%s"\n', thisTest);
|
||||
hashes = rmfield(hashes, thisTest);
|
||||
|
||||
case 'keep'
|
||||
% useful when not all tests were executed by the tester
|
||||
fprintf(1, 'Kept hash for "%s"\n', thisTest);
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
function action = askActionToPerformOnRemovedTest(testName)
|
||||
% ask which action to carry out on a removed test
|
||||
action = lower(ipp.Results.removedTests);
|
||||
while ~isActualAction(action)
|
||||
query = sprintf('Keep or remove "%s"? [Kr]:', testName);
|
||||
answer = strtrim(input(query,'s'));
|
||||
|
||||
if isempty(answer) || strcmpi(answer(1), 'K')
|
||||
action = 'keep';
|
||||
elseif strcmpi(answer(1), 'R')
|
||||
action = 'remove';
|
||||
else
|
||||
action = 'ask again';
|
||||
% just keep asking until we get a reasonable answer
|
||||
end
|
||||
end
|
||||
end
|
||||
function writeHashesToFile(filename, hashes)
|
||||
% write hashes to a file (or stdout when dry-running)
|
||||
if ~ipp.Results.dryrun
|
||||
fid = fopen(filename, 'w+');
|
||||
finally_fclose_fid = onCleanup(@() fclose(fid));
|
||||
else
|
||||
fid = 1; % Use stdout to print everything
|
||||
fprintf(fid, '\n\n Output: \n\n');
|
||||
end
|
||||
|
||||
funcNames = sort(fieldnames(hashes));
|
||||
for iFunc = 1:numel(funcNames)
|
||||
func = funcNames{iFunc};
|
||||
fprintf(fid, WRITEFORMAT, func, hashes.(func));
|
||||
end
|
||||
end
|
||||
function hashes = readHashesFromFile(filename)
|
||||
% read hashes from a file
|
||||
if exist(filename,'file')
|
||||
fid = fopen(filename, 'r');
|
||||
finally_fclose_fid = onCleanup(@() fclose(fid));
|
||||
|
||||
data = textscan(fid, READFORMAT);
|
||||
% data is now a cell array with 2 elements, each a (row) cell array
|
||||
% - the first is all the function names
|
||||
% - the second is all the hashes
|
||||
|
||||
% Transform `data` into {function1, hash1, function2, hash2, ...}'
|
||||
% First step is to transpose the data concatenate both fields under
|
||||
% each other. Since MATLAB indexing uses "column major order",
|
||||
% traversing the concatenated array is in the order we want.
|
||||
data = [data{:}]';
|
||||
allValues = data(:)';
|
||||
else
|
||||
allValues = {};
|
||||
end
|
||||
hashes = struct(allValues{:});
|
||||
end
|
||||
end
|
||||
% ==============================================================================
|
||||
function bool = isValidAction(str)
|
||||
% returns true for valid actions (keep/remove/ask) on "removedTests":
|
||||
bool = ismember(lower(str), {'keep','remove','ask'});
|
||||
end
|
||||
function bool = isActualAction(str)
|
||||
% returns true for actual actions (keep/remove) on "removedTests"
|
||||
bool = ismember(lower(str), {'keep','remove'});
|
||||
end
|
||||
% ==============================================================================
|
||||
Reference in New Issue
Block a user