You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
164 lines
6.6 KiB
164 lines
6.6 KiB
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 |
|
% ==============================================================================
|
|
|