Auswertung Experiment
Database tüddelei DBHanlder läuft gut für DIESE Datanbank struktur... App begonnen aber weit entfernt von gutem Stand
This commit is contained in:
36
Libs/mat2tikz/test/private/OSVersion.m
Normal file
36
Libs/mat2tikz/test/private/OSVersion.m
Normal file
@@ -0,0 +1,36 @@
|
||||
function [formatted, OSType, OSVersion] = OSVersion()
|
||||
% determines the OS type and its (kernel) version number
|
||||
if ismac
|
||||
OSType = 'Mac OS';
|
||||
[dummy, OSVersion] = system('sw_vers -productVersion'); %#ok
|
||||
% Output like "10.10.4" for OS X Yosemite
|
||||
|
||||
elseif ispc
|
||||
OSType = 'Windows';
|
||||
[dummy, rawVersion] = system('ver'); %#ok
|
||||
% Output like "Microsoft Windows [Version 6.3.9600]" for Win8.1
|
||||
pattern = '(?<=Version )[0-9.]+';
|
||||
OSVersion = regexpi(rawVersion, pattern, 'match', 'once');
|
||||
|
||||
elseif isunix
|
||||
[dummy, OSType] = system('uname -s'); %#ok
|
||||
% This returns the kernal name
|
||||
% e.g. "Linux" on Linux, "Darwin" on Mac, "SunOS" on Solaris
|
||||
[dummy, OSVersion] = system('uname -r'); %#ok
|
||||
% Returns the kernel version. Many Linux distributions
|
||||
% include an identifier, e.g. "4.0.7-2-ARCH" on Arch Linux
|
||||
|
||||
% TODO: also use `lsb_release` in Linux for distro info
|
||||
else
|
||||
warning('OSVersion:UnknownOS', 'Could not recognize OS.');
|
||||
OSType = 'Unknown OS';
|
||||
OSVersion = '';
|
||||
|
||||
end
|
||||
|
||||
EOL = sprintf('\n');
|
||||
OSType = strrep(OSType, EOL, '');
|
||||
OSVersion = strrep(OSVersion, EOL, '');
|
||||
|
||||
formatted = strtrim([OSType ' ' OSVersion]);
|
||||
end
|
||||
74
Libs/mat2tikz/test/private/StreamMaker.m
Normal file
74
Libs/mat2tikz/test/private/StreamMaker.m
Normal file
@@ -0,0 +1,74 @@
|
||||
function SM = StreamMaker()
|
||||
% StreamMaker (Factory for fie/input/output Streams)
|
||||
%
|
||||
% A StreamMaker can make Stream PseudoObjects based on either
|
||||
% an "fid" or "filename" (and extra arguments for `fopen`).
|
||||
% The StreamMaker also contains a method `isStream` to validate whether
|
||||
% the value passed is a valid stream specifier.
|
||||
%
|
||||
% Usage
|
||||
%
|
||||
% SM = StreamMaker;
|
||||
%
|
||||
% Stream = SM.make(fid)
|
||||
% Stream = SM.make(filename, ...)
|
||||
%
|
||||
% This returns a PseudoObject Stream with the following properties:
|
||||
% - name: (file) name of the stream
|
||||
% - fid: handle (fid) of the stream
|
||||
%
|
||||
% and methods:
|
||||
% - print: prints to the stream, i.e. fprintf
|
||||
% - close: closes the stream, i.e. fclose
|
||||
%
|
||||
% It may also contain a field to automatically close the Stream when it goes
|
||||
% out of scope.
|
||||
%
|
||||
SM = PseudoObject('StreamMaker', ...
|
||||
'isStream', @isStream, ...
|
||||
'make', @constructStream);
|
||||
end
|
||||
|
||||
function PseudoObj = PseudoObject(T, varargin)
|
||||
% construct a Pseudo-Object with type T (no other fields yet)
|
||||
PseudoObj = struct('Type', T, varargin{:});
|
||||
end
|
||||
|
||||
function bool = isStream(value)
|
||||
bool = ischar(value) || ismember(value, [1,2,fopen('all')]);
|
||||
%TODO: allow others kinds of streams
|
||||
% Stream -> clipboard (write on close)
|
||||
% Stream -> string variable
|
||||
% e.g. a quick-and-dirty way would be to write the file to `tempname`
|
||||
% putting a flag to read that file back upon completion.
|
||||
end
|
||||
|
||||
function Stream = constructStream(streamSpecifier, varargin)
|
||||
% this is the actual constructor of a stream
|
||||
if ~isStream(streamSpecifier)
|
||||
error('StreamMaker:NotAStream', 'Invalid stream specifier "%s"', ...
|
||||
streamSpecifier);
|
||||
end
|
||||
|
||||
Stream = PseudoObject('Stream');
|
||||
closeAfterUse = false;
|
||||
if ischar(streamSpecifier)
|
||||
Stream.name = streamSpecifier;
|
||||
Stream.fid = fopen(Stream.name, varargin{:});
|
||||
closeAfterUse = true;
|
||||
elseif isnumeric(streamSpecifier)
|
||||
Stream.fid = streamSpecifier;
|
||||
Stream.name = fopen(Stream.fid);
|
||||
end
|
||||
|
||||
if Stream.fid == -1
|
||||
error('Stream:InvalidStream', ...
|
||||
'Unable to create stream "%s"!', streamSpecifier);
|
||||
end
|
||||
|
||||
Stream.print = @(varargin) fprintf(Stream.fid, varargin{:});
|
||||
Stream.close = @() fclose(Stream.fid);
|
||||
if closeAfterUse
|
||||
Stream.closeAfterUse = onCleanup(Stream.close);
|
||||
end
|
||||
end
|
||||
47
Libs/mat2tikz/test/private/VersionControlIdentifier.m
Normal file
47
Libs/mat2tikz/test/private/VersionControlIdentifier.m
Normal file
@@ -0,0 +1,47 @@
|
||||
function [formatted,treeish] = VersionControlIdentifier()
|
||||
% This function gives the (git) commit ID of matlab2tikz
|
||||
%
|
||||
% This assumes the standard directory structure as used by Nico's master branch:
|
||||
% SOMEPATH/src/matlab2tikz.m with a .git directory in SOMEPATH.
|
||||
%
|
||||
% The HEAD of that repository is determined from file system information only
|
||||
% by following dynamic references (e.g. ref:refs/heds/master) in branch files
|
||||
% until an absolute commit hash (e.g. 1a3c9d1...) is found.
|
||||
% NOTE: Packed branch references are NOT supported by this approach
|
||||
MAXITER = 10; % stop following dynamic references after a while
|
||||
formatted = '';
|
||||
REFPREFIX = 'ref:';
|
||||
isReference = @(treeish)(any(strfind(treeish, REFPREFIX)));
|
||||
treeish = [REFPREFIX 'HEAD'];
|
||||
try
|
||||
% get the matlab2tikz directory
|
||||
privateDir = fileparts(mfilename('fullpath'));
|
||||
gitDir = fullfile(privateDir,'..','..','.git');
|
||||
|
||||
nIter = 1;
|
||||
while isReference(treeish)
|
||||
refName = treeish(numel(REFPREFIX)+1:end);
|
||||
branchFile = fullfile(gitDir, refName);
|
||||
|
||||
if exist(branchFile, 'file') && nIter < MAXITER
|
||||
% The FID is reused in every iteration, so `onCleanup` cannot
|
||||
% be used to `fclose(fid)`. But since there is very little that
|
||||
% can go wrong in a single `fscanf`, it's probably best to leave
|
||||
% this part as it is for the time being.
|
||||
fid = fopen(branchFile,'r');
|
||||
treeish = fscanf(fid,'%s');
|
||||
fclose(fid);
|
||||
nIter = nIter + 1;
|
||||
else % no branch file or iteration limit reached
|
||||
treeish = '';
|
||||
return;
|
||||
end
|
||||
end
|
||||
catch %#ok
|
||||
treeish = '';
|
||||
end
|
||||
if ~isempty(treeish)
|
||||
formatted = [' Commit & ' treeish ' \\\\ \n'];
|
||||
end
|
||||
%TODO: do the formatting somewhere else!
|
||||
end
|
||||
35
Libs/mat2tikz/test/private/calculateMD5Hash.m
Normal file
35
Libs/mat2tikz/test/private/calculateMD5Hash.m
Normal file
@@ -0,0 +1,35 @@
|
||||
function hash = calculateMD5Hash(filename)
|
||||
% CALCULATEMD5HASH calculate a MD5 hash of a file
|
||||
%
|
||||
% This functionality is built-in into Octave but uses Java in MATLAB.
|
||||
|
||||
switch getEnvironment
|
||||
case 'Octave'
|
||||
hash = md5sum(filename);
|
||||
|
||||
case 'MATLAB'
|
||||
% There are some MD5 implementations in MATLAB, but those
|
||||
% tend to be slow and licensing is unclear.
|
||||
% Rolling our own implementation is unwanted, especially since this
|
||||
% is a cryptographic hash, even though its security has been
|
||||
% broken. Instead we make use of the Java libraries.
|
||||
% Unless the "-nojvm" flag is specified, this should work well.
|
||||
|
||||
MD5 = java.security.MessageDigest.getInstance('MD5');
|
||||
|
||||
% Open the file
|
||||
fid = fopen(filename, 'r');
|
||||
|
||||
% Make sure fid is closed
|
||||
finally_close = onCleanup(@()fclose(fid));
|
||||
|
||||
% Faster file digest based on code by Jan Simon as in
|
||||
% http://www.mathworks.com/matlabcentral/fileexchange/31272-datahash
|
||||
data = fread(fid, '*uint8');
|
||||
MD5.update(data);
|
||||
|
||||
hash = reshape(dec2hex(typecast(MD5.digest(),'uint8')).', 1, 32);
|
||||
end
|
||||
|
||||
hash = lower(hash);
|
||||
end
|
||||
19
Libs/mat2tikz/test/private/cleanFiles.m
Normal file
19
Libs/mat2tikz/test/private/cleanFiles.m
Normal file
@@ -0,0 +1,19 @@
|
||||
function cleanFiles(cleanBefore)
|
||||
% clean output files in ./tex using make
|
||||
%FIXME: this file appears to be unused (but it is useful)
|
||||
%FIXME: adapt this file to take the output directory into account
|
||||
if cleanBefore && exist(fullfile('tex','Makefile'),'file')
|
||||
fprintf(1, 'Cleaning output files...\n');
|
||||
cwd = pwd;
|
||||
try
|
||||
cd('tex');
|
||||
[exitCode, output] = system('make distclean');
|
||||
fprintf(1,'%s\n', output);
|
||||
assert(exitCode==0, 'Exit code 0 means correct execution');
|
||||
catch
|
||||
% This might happen when make is not present
|
||||
fprintf(2, '\tNot completed succesfully\n\n');
|
||||
end
|
||||
cd(cwd);
|
||||
end
|
||||
end
|
||||
4
Libs/mat2tikz/test/private/countNumberOfErrors.m
Normal file
4
Libs/mat2tikz/test/private/countNumberOfErrors.m
Normal file
@@ -0,0 +1,4 @@
|
||||
function nErrors = countNumberOfErrors(status)
|
||||
% counts the number of errors in a status cell array
|
||||
nErrors = sum(hasTestFailed(status));
|
||||
end
|
||||
4
Libs/mat2tikz/test/private/emptyStage.m
Normal file
4
Libs/mat2tikz/test/private/emptyStage.m
Normal file
@@ -0,0 +1,4 @@
|
||||
function stage = emptyStage()
|
||||
% constructs an empty (workflow) stage struct
|
||||
stage = struct('message', '', 'error' , false);
|
||||
end
|
||||
24
Libs/mat2tikz/test/private/emptyStatus.m
Normal file
24
Libs/mat2tikz/test/private/emptyStatus.m
Normal file
@@ -0,0 +1,24 @@
|
||||
function defaultStatus = emptyStatus(testsuite, testNumber)
|
||||
% constructs an empty status struct
|
||||
defaultStatus = struct(...
|
||||
'function', '', ...
|
||||
'description', '',...
|
||||
'testsuite', testsuite ,...
|
||||
'index', testNumber, ...
|
||||
'issues', [],...
|
||||
'unreliable', false, ...
|
||||
'skip', false, ... % skipped this test?
|
||||
'closeall', false, ... % call close all after?
|
||||
'extraOptions', {cell(0)}, ...
|
||||
'extraCleanfigureOptions',{cell(0)}, ...
|
||||
'plotStage', emptyStage(), ...
|
||||
'saveStage', emptyStage(), ...
|
||||
'tikzStage', emptyStage(), ...
|
||||
'hashStage', emptyStage() ...
|
||||
);
|
||||
|
||||
% for reliable tests explicitly define width and height, see #659
|
||||
% TODO: Remove explicitly setting this option.
|
||||
% After #641 is merged, this might be not needed anyhow.
|
||||
defaultStatus.extraCleanfigureOptions = {'targetResolution', [1000,500]};
|
||||
end
|
||||
41
Libs/mat2tikz/test/private/errorHandler.m
Normal file
41
Libs/mat2tikz/test/private/errorHandler.m
Normal file
@@ -0,0 +1,41 @@
|
||||
function [stage, errorHasOccurred] = errorHandler(e)
|
||||
% common error handler code: save and print to console
|
||||
errorHasOccurred = true;
|
||||
stage = emptyStage();
|
||||
stage.message = format_error_message(e);
|
||||
stage.error = errorHasOccurred;
|
||||
|
||||
disp_error_message(stage.message);
|
||||
end
|
||||
% ==============================================================================
|
||||
function msg = format_error_message(e)
|
||||
msg = '';
|
||||
if ~isempty(e.message)
|
||||
msg = sprintf('%serror: %s\n', msg, e.message);
|
||||
end
|
||||
if ~isempty(e.identifier)
|
||||
if strfind(lower(e.identifier),'testmatlab2tikz:')
|
||||
% When "errors" occur in the test framework, i.e. a hash mismatch
|
||||
% or no hash provided, there is no need to be very verbose.
|
||||
% So we don't return the msgid and the stack trace in those cases!
|
||||
return % only return the message
|
||||
end
|
||||
msg = sprintf('%serror: %s\n', msg, e.identifier);
|
||||
end
|
||||
if ~isempty(e.stack)
|
||||
msg = sprintf('%serror: called from:\n', msg);
|
||||
for ee = e.stack(:)'
|
||||
msg = sprintf('%serror: %s at line %d, in function %s\n', ...
|
||||
msg, ee.file, ee.line, ee.name);
|
||||
end
|
||||
end
|
||||
end
|
||||
% ==============================================================================
|
||||
function disp_error_message(msg)
|
||||
stderr = 2;
|
||||
% The error message should not contain any more escape sequences and
|
||||
% hence can be output literally to stderr.
|
||||
|
||||
fprintf(stderr, '%s', msg);
|
||||
end
|
||||
% ==============================================================================
|
||||
16
Libs/mat2tikz/test/private/errorHasOccurred.m
Normal file
16
Libs/mat2tikz/test/private/errorHasOccurred.m
Normal file
@@ -0,0 +1,16 @@
|
||||
function errorOccurred = errorHasOccurred(status)
|
||||
% determines whether an error has occurred from a status struct OR cell array
|
||||
% of status structs
|
||||
errorOccurred = false;
|
||||
if iscell(status)
|
||||
for iStatus = 1:numel(status)
|
||||
errorOccurred = errorOccurred || errorHasOccurred(status{iStatus});
|
||||
end
|
||||
else
|
||||
stages = getStagesFromStatus(status);
|
||||
for iStage = 1:numel(stages)
|
||||
thisStage = status.(stages{iStage});
|
||||
errorOccurred = errorOccurred || thisStage.error;
|
||||
end
|
||||
end
|
||||
end
|
||||
34
Libs/mat2tikz/test/private/execute_hash_stage.m
Normal file
34
Libs/mat2tikz/test/private/execute_hash_stage.m
Normal file
@@ -0,0 +1,34 @@
|
||||
function [status] = execute_hash_stage(status, ipp)
|
||||
% test stage: check recorded hash checksum
|
||||
calculated = '';
|
||||
expected = '';
|
||||
try
|
||||
expected = getReferenceHash(status, ipp);
|
||||
calculated = calculateMD5Hash(status.tikzStage.texFile);
|
||||
|
||||
% do the actual check
|
||||
if ~strcmpi(expected, calculated)
|
||||
% throw an error to signal the testing framework
|
||||
error('testMatlab2tikz:HashMismatch', ...
|
||||
'The hash "%s" does not match the reference hash "%s"', ...
|
||||
calculated, expected);
|
||||
end
|
||||
catch %#ok
|
||||
e = lasterror('reset'); %#ok
|
||||
[status.hashStage] = errorHandler(e);
|
||||
end
|
||||
status.hashStage.expected = expected;
|
||||
status.hashStage.found = calculated;
|
||||
end
|
||||
% ==============================================================================
|
||||
function hash = getReferenceHash(status, ipp)
|
||||
% retrieves a reference hash from a hash table
|
||||
% WARNING: do not make `hashTable` persistent, since this is slower
|
||||
|
||||
hashTable = loadHashTable(ipp.Results.testsuite);
|
||||
if isfield(hashTable.contents, status.function)
|
||||
hash = hashTable.contents.(status.function);
|
||||
else
|
||||
hash = '';
|
||||
end
|
||||
end
|
||||
45
Libs/mat2tikz/test/private/execute_plot_stage.m
Normal file
45
Libs/mat2tikz/test/private/execute_plot_stage.m
Normal file
@@ -0,0 +1,45 @@
|
||||
function [status] = execute_plot_stage(defaultStatus, ipp)
|
||||
% plot a test figure
|
||||
testsuite = ipp.Results.testsuite;
|
||||
testNumber = defaultStatus.index;
|
||||
|
||||
% open a window
|
||||
fig_handle = figure('visible',ipp.Results.figureVisible);
|
||||
errorHasOccurred = false;
|
||||
|
||||
% plot the figure
|
||||
try
|
||||
status = testsuite(testNumber);
|
||||
|
||||
catch %#ok
|
||||
e = lasterror('reset'); %#ok
|
||||
|
||||
status.description = '\textcolor{red}{Error during plot generation.}';
|
||||
[status.plotStage, errorHasOccurred] = errorHandler(e);
|
||||
|
||||
% Automaticall mark the test as unreliable
|
||||
%
|
||||
% Since metadata is not set in this case, also stat.unreliable is
|
||||
% not returned. So ideally, we should
|
||||
% FIXME: implement #484 to get access to the meta data
|
||||
% but we can work around this issue by forcefully setting that value.
|
||||
% The rationale for setting this to true:
|
||||
% - the plot part is not the main task of M2T
|
||||
% (so breaking a single test is less severe in this case),
|
||||
% - if the plotting fails, the test is not really reliable anyway,
|
||||
% - this allows to get full green on Travis.
|
||||
status.unreliable = true;
|
||||
|
||||
end
|
||||
|
||||
status = fillStruct(status, defaultStatus);
|
||||
if isempty(status.function)
|
||||
allFuncs = testsuite(0);
|
||||
status.function = func2str(allFuncs{testNumber});
|
||||
end
|
||||
status.plotStage.fig_handle = fig_handle;
|
||||
|
||||
if status.skip || errorHasOccurred
|
||||
close(fig_handle);
|
||||
end
|
||||
end
|
||||
63
Libs/mat2tikz/test/private/execute_save_stage.m
Normal file
63
Libs/mat2tikz/test/private/execute_save_stage.m
Normal file
@@ -0,0 +1,63 @@
|
||||
function [status] = execute_save_stage(status, ipp)
|
||||
% save stage: saves the figure to EPS/PDF depending on env
|
||||
testNumber = status.index;
|
||||
|
||||
basepath = fullfile(ipp.Results.output,'data','reference');
|
||||
reference_eps = fullfile(basepath, sprintf('test%d-reference.eps', testNumber));
|
||||
reference_pdf = fullfile(basepath, sprintf('test%d-reference.pdf', testNumber));
|
||||
% the reference below is for inclusion in LaTeX! Use UNIX conventions!
|
||||
reference_fig = sprintf('data/reference/test%d-reference', testNumber);
|
||||
|
||||
% Save reference output as PDF
|
||||
try
|
||||
switch getEnvironment
|
||||
case 'MATLAB'
|
||||
% MATLAB does not generate properly cropped PDF files.
|
||||
% So, we generate EPS files that are converted later on.
|
||||
print(gcf, '-depsc2', reference_eps);
|
||||
|
||||
fixLineEndingsInWindows(reference_eps);
|
||||
|
||||
case 'Octave'
|
||||
% In Octave, figures are properly cropped when using print().
|
||||
print(reference_pdf, '-dpdf', '-S415,311', '-r150');
|
||||
pause(1.0)
|
||||
otherwise
|
||||
error('matlab2tikz:UnknownEnvironment', ...
|
||||
'Unknown environment. Need MATLAB(R) or GNU Octave.')
|
||||
end
|
||||
catch %#ok
|
||||
e = lasterror('reset'); %#ok
|
||||
[status.saveStage] = errorHandler(e);
|
||||
end
|
||||
status.saveStage.epsFile = reference_eps;
|
||||
status.saveStage.pdfFile = reference_pdf;
|
||||
status.saveStage.texReference = reference_fig;
|
||||
end
|
||||
% ==============================================================================
|
||||
function fixLineEndingsInWindows(filename)
|
||||
% On R2014b Win, line endings in .eps are Unix style (LF) instead of Windows
|
||||
% style (CR+LF). This causes problems in the MikTeX `epstopdf` for some files
|
||||
% as dicussed in:
|
||||
% * https://github.com/matlab2tikz/matlab2tikz/issues/370
|
||||
% * http://tex.stackexchange.com/questions/208179
|
||||
if ispc
|
||||
fid = fopen(filename,'r+');
|
||||
finally_fclose_fid = onCleanup(@() fclose(fid));
|
||||
testline = fgets(fid);
|
||||
CRLF = sprintf('\r\n');
|
||||
endOfLine = testline(end-1:end);
|
||||
if ~strcmpi(endOfLine, CRLF)
|
||||
endOfLine = testline(end); % probably an LF
|
||||
|
||||
% Rewind, read the whole
|
||||
fseek(fid,0,'bof');
|
||||
str = fread(fid,'*char')';
|
||||
|
||||
% Replace, overwrite and close
|
||||
str = strrep(str, endOfLine, CRLF);
|
||||
fseek(fid,0,'bof');
|
||||
fprintf(fid,'%s',str);
|
||||
end
|
||||
end
|
||||
end
|
||||
43
Libs/mat2tikz/test/private/execute_tikz_stage.m
Normal file
43
Libs/mat2tikz/test/private/execute_tikz_stage.m
Normal file
@@ -0,0 +1,43 @@
|
||||
function [status] = execute_tikz_stage(status, ipp)
|
||||
% test stage: TikZ file generation
|
||||
testNumber = status.index;
|
||||
datapath = fullfile(ipp.Results.output,'data','converted');
|
||||
gen_tex = fullfile(datapath, sprintf('test%d-converted.tex', testNumber));
|
||||
% the value below is for inclusion into LaTeX report! Use UNIX convention.
|
||||
gen_pdf = sprintf('data/converted/test%d-converted.pdf', testNumber);
|
||||
cleanfigure_time = NaN;
|
||||
m2t_time = NaN;
|
||||
|
||||
% now, test matlab2tikz
|
||||
try
|
||||
%TODO: remove this once text removal has been removed
|
||||
oldWarn = warning('off','cleanfigure:textRemoval');
|
||||
|
||||
cleanfigure_time = tic;
|
||||
cleanfigure(status.extraCleanfigureOptions{:});
|
||||
cleanfigure_time = toc(cleanfigure_time);
|
||||
|
||||
warning(oldWarn);
|
||||
|
||||
m2t_time = tic;
|
||||
matlab2tikz('filename', gen_tex, ...
|
||||
'showInfo', false, ...
|
||||
'checkForUpdates', false, ...
|
||||
'dataPath', datapath, ...
|
||||
'standalone', true, ...
|
||||
ipp.Results.extraOptions{:}, ...
|
||||
status.extraOptions{:} ...
|
||||
);
|
||||
m2t_time = toc(m2t_time);
|
||||
catch %#ok
|
||||
e = lasterror('reset'); %#ok
|
||||
% Remove (corrupted) output file. This is necessary to avoid that the
|
||||
% Makefile tries to compile it and fails.
|
||||
delete(gen_tex)
|
||||
[status.tikzStage] = errorHandler(e);
|
||||
end
|
||||
status.tikzStage.texFile = gen_tex;
|
||||
status.tikzStage.pdfFile = gen_pdf;
|
||||
status.tikzStage.m2t_time = m2t_time;
|
||||
status.tikzStage.cleanfigure_time = cleanfigure_time;
|
||||
end
|
||||
15
Libs/mat2tikz/test/private/execute_type_stage.m
Normal file
15
Libs/mat2tikz/test/private/execute_type_stage.m
Normal file
@@ -0,0 +1,15 @@
|
||||
function [status] = execute_type_stage(status, ipp)
|
||||
try
|
||||
filename = status.tikzStage.texFile;
|
||||
stream = 1; % stdout
|
||||
if errorHasOccurred(status) && exist(filename, 'file')
|
||||
shortname = strrep(filename, m2troot, '$(M2TROOT)');
|
||||
fprintf(stream, '\n%%%%%%%% BEGIN FILE "%s" %%%%%%%%\n', shortname);
|
||||
type(filename);
|
||||
fprintf(stream, '\n%%%%%%%% END FILE "%s" %%%%%%%%\n', shortname);
|
||||
end
|
||||
catch
|
||||
e = lasterror('reset');
|
||||
[status.typeStage] = errorHandler(e);
|
||||
end
|
||||
end
|
||||
10
Libs/mat2tikz/test/private/fillStruct.m
Normal file
10
Libs/mat2tikz/test/private/fillStruct.m
Normal file
@@ -0,0 +1,10 @@
|
||||
function [status] = fillStruct(status, defaultStatus)
|
||||
% fills non-existant fields of |data| with those of |defaultData|
|
||||
fields = fieldnames(defaultStatus);
|
||||
for iField = 1:numel(fields)
|
||||
field = fields{iField};
|
||||
if ~isfield(status,field)
|
||||
status.(field) = defaultStatus.(field);
|
||||
end
|
||||
end
|
||||
end
|
||||
25
Libs/mat2tikz/test/private/getEnvironment.m
Normal file
25
Libs/mat2tikz/test/private/getEnvironment.m
Normal file
@@ -0,0 +1,25 @@
|
||||
function [env, versionString] = getEnvironment()
|
||||
% Determine environment (Octave, MATLAB) and version string
|
||||
% TODO: Unify private `getEnvironment` functions
|
||||
persistent cache
|
||||
|
||||
if isempty(cache)
|
||||
isOctave = exist('OCTAVE_VERSION', 'builtin') ~= 0;
|
||||
if isOctave
|
||||
env = 'Octave';
|
||||
versionString = OCTAVE_VERSION;
|
||||
else
|
||||
env = 'MATLAB';
|
||||
vData = ver(env);
|
||||
versionString = vData.Version;
|
||||
end
|
||||
|
||||
% store in cache
|
||||
cache.env = env;
|
||||
cache.versionString = versionString;
|
||||
|
||||
else
|
||||
env = cache.env;
|
||||
versionString = cache.versionString;
|
||||
end
|
||||
end
|
||||
5
Libs/mat2tikz/test/private/getStagesFromStatus.m
Normal file
5
Libs/mat2tikz/test/private/getStagesFromStatus.m
Normal file
@@ -0,0 +1,5 @@
|
||||
function stages = getStagesFromStatus(status)
|
||||
% retrieves the different (names of) stages of a status struct
|
||||
fields = fieldnames(status);
|
||||
stages = fields(cellfun(@(f) ~isempty(strfind(f,'Stage')), fields));
|
||||
end
|
||||
13
Libs/mat2tikz/test/private/hasTestFailed.m
Normal file
13
Libs/mat2tikz/test/private/hasTestFailed.m
Normal file
@@ -0,0 +1,13 @@
|
||||
function bool = hasTestFailed(status)
|
||||
% returns true when the test has failed
|
||||
|
||||
if iscell(status) % allow for vectorization of the call
|
||||
bool = cellfun(@hasTestFailed, status, 'UniformOutput', true);
|
||||
else
|
||||
stages = getStagesFromStatus(status);
|
||||
bool = false;
|
||||
for jStage = 1:numel(stages)
|
||||
bool = bool || status.(stages{jStage}).error;
|
||||
end
|
||||
end
|
||||
end
|
||||
55
Libs/mat2tikz/test/private/hashTableName.m
Normal file
55
Libs/mat2tikz/test/private/hashTableName.m
Normal file
@@ -0,0 +1,55 @@
|
||||
function filename = hashTableName(suite)
|
||||
% determines the file name of a hash table
|
||||
%
|
||||
% The MD5 file is assumed to be in the same directory as the test suite.
|
||||
% It has a file name "$SUITE.$ENV.$VER.md5"
|
||||
% where the following fields are filled:
|
||||
% $ENV: the environment (either "MATLAB" or "Octave")
|
||||
% $VER: the version (e.g. "3.8.0" for Octave, "8.3" for MATLAB 2014a)
|
||||
% $SUITE: the name (and path) of the test suite
|
||||
%
|
||||
% For the $VER-part, a fall-back mechanism is present that prefers the exact
|
||||
% version but will use the closest available file if such file does not
|
||||
% exist.
|
||||
[pathstr,name, ext] = fileparts(which(func2str(suite)));
|
||||
[env, version] = getEnvironment();
|
||||
ext = sprintf('.%s.%s.md5', env, version);
|
||||
relFilename = [name ext];
|
||||
filename = fullfile(pathstr, relFilename);
|
||||
|
||||
if ~exist(filename,'file')
|
||||
% To avoid having to create a file for each release of the environment,
|
||||
% also other versions are tried. The file for different releases are checked
|
||||
% in the following order:
|
||||
% 1. the currently running version (handled above!)
|
||||
% 2. the newest older version (e.g. use R2014b's file in R2015a)
|
||||
% 3. the oldest newer version (e.g. use R2014a's file in R2013a)
|
||||
pattern = sprintf('%s.%s.*.md5', name, env);
|
||||
candidates = dir(fullfile(pathstr, pattern));
|
||||
|
||||
% We just need the file names.
|
||||
filenames = arrayfun(@(c)c.name, candidates, 'UniformOutput', false);
|
||||
|
||||
% Add the expected version to the results, and sort the names by
|
||||
% version (this is the same as alphabetically).
|
||||
filenames = sort([filenames; {relFilename}]);
|
||||
nFiles = numel(filenames);
|
||||
iCurrent = find(ismember(filenames, relFilename));
|
||||
% determine the fall-back candidates:
|
||||
iNewestOlder = iCurrent - 1;
|
||||
iOldestNewer = iCurrent + 1;
|
||||
|
||||
inRange = @(idx)(idx <= nFiles && idx >= 1);
|
||||
if inRange(iNewestOlder)
|
||||
% use the newest older version
|
||||
relFilename = filenames{iNewestOlder};
|
||||
elseif inRange(iOldestNewer)
|
||||
% use the oldest newer version
|
||||
relFilename = filenames{iOldestNewer};
|
||||
else
|
||||
% use the exact version anyhow
|
||||
end
|
||||
|
||||
filename = fullfile(pathstr, relFilename);
|
||||
end
|
||||
end
|
||||
99
Libs/mat2tikz/test/private/initializeGlobalState.m
Normal file
99
Libs/mat2tikz/test/private/initializeGlobalState.m
Normal file
@@ -0,0 +1,99 @@
|
||||
function [orig] = initializeGlobalState()
|
||||
% Initialize global state. Set working directory and various properties of
|
||||
% the graphical root to ensure reliable output of the ACID testsuite.
|
||||
% See #542 and #552
|
||||
%
|
||||
% 1. Working directory
|
||||
% 2. Bring get(0,'Default') in line with get(0,'Factory')
|
||||
% 3. Set specific properties, required by matlab2tikz
|
||||
fprintf('Initialize global state...\n');
|
||||
orig = struct();
|
||||
|
||||
%--- Extract user defined default properties and set factory state
|
||||
default = get(0,'Default');
|
||||
factory = get(0,'Factory');
|
||||
|
||||
f = fieldnames(default); % fields of user's default state
|
||||
for i = 1:length(f)
|
||||
factory_property_name = strrep(f{i},'default','factory');
|
||||
factory_property_value = factory.(factory_property_name);
|
||||
orig.(f{i}).val = ...
|
||||
swapPropertyState(0, f{i}, factory_property_value);
|
||||
end
|
||||
|
||||
%--- Define desired global state properties
|
||||
% defaultAxesColorOrder: on HG1 'default' and 'factory' differ and
|
||||
% HG1 differs from HG2. Consequently use HG2 colors (the new standard).
|
||||
new.defaultAxesColorOrder.val = [0.000 0.447 0.741; ...
|
||||
0.850 0.325 0.098; ...
|
||||
0.929 0.694 0.125; ...
|
||||
0.494 0.184 0.556; ...
|
||||
0.466 0.674 0.188; ...
|
||||
0.301 0.745 0.933; ...
|
||||
0.635 0.0780 0.184];
|
||||
new.defaultAxesColorOrder.ignore= false;
|
||||
|
||||
% defaultFigurePosition: width and height influence cleanfigure() and
|
||||
% the number/location of axis ticks
|
||||
new.defaultFigurePosition.val = [300,200,560,420];
|
||||
new.defaultFigurePosition.ignore= false;
|
||||
|
||||
% ScreenPixelsPerInch: TODO: determine, if necessary
|
||||
% (probably needed for new line simplification algorithm)
|
||||
% not possible in octave
|
||||
new.ScreenPixelsPerInch.val = 96;
|
||||
new.ScreenPixelsPerInch.ignore = strcmpi(getEnvironment,'octave');
|
||||
|
||||
% MATLAB's factory values differ from their default values of a clean
|
||||
% MATLAB installation (observed on R2014a, Linux)
|
||||
new.defaultAxesColor.val = [1 1 1];
|
||||
new.defaultAxesColor.ignore = false;
|
||||
new.defaultLineColor.val = [0 0 0];
|
||||
new.defaultLineColor.ignore = false;
|
||||
new.defaultTextColor.val = [0 0 0];
|
||||
new.defaultTextColor.ignore = false;
|
||||
new.defaultAxesXColor.val = [0 0 0];
|
||||
new.defaultAxesXColor.ignore = false;
|
||||
new.defaultAxesYColor.val = [0 0 0];
|
||||
new.defaultAxesYColor.ignore = false;
|
||||
new.defaultAxesZColor.val = [0 0 0];
|
||||
new.defaultAxesZColor.ignore = false;
|
||||
new.defaultFigureColor.val = [0.8 0.8 0.8];
|
||||
new.defaultFigureColor.ignore = false;
|
||||
new.defaultPatchEdgeColor.val = [0 0 0];
|
||||
new.defaultPatchEdgeColor.ignore = false;
|
||||
new.defaultPatchFaceColor.val = [0 0 0];
|
||||
new.defaultPatchFaceColor.ignore = false;
|
||||
new.defaultFigurePaperType.val = 'A4';
|
||||
new.defaultFigurePaperType.ignore = false;
|
||||
new.defaultFigurePaperSize.val = [20.9840 29.6774];
|
||||
new.defaultFigurePaperSize.ignore = false;
|
||||
new.defaultFigurePaperUnits.val = 'centimeters';
|
||||
new.defaultFigurePaperUnits.ignore = false;
|
||||
|
||||
%--- Extract relevant properties and set desired state
|
||||
f = fieldnames(new); % fields of new state
|
||||
for i = 1:length(f)
|
||||
% ignore property on specified environments
|
||||
if ~new.(f{i}).ignore
|
||||
val = swapPropertyState(0, f{i}, new.(f{i}).val);
|
||||
|
||||
% store original value only, if not set by user's defaults
|
||||
if ~isfield(orig,f{i})
|
||||
orig.(f{i}).val = val;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
% =========================================================================
|
||||
function old = swapPropertyState(h, property, new)
|
||||
% read current property of graphical object
|
||||
% set new value, if not empty
|
||||
if nargin < 3, new = []; end
|
||||
|
||||
old = get(h, property);
|
||||
|
||||
if ~isempty(new)
|
||||
set(h, property, new);
|
||||
end
|
||||
end
|
||||
19
Libs/mat2tikz/test/private/loadHashTable.m
Normal file
19
Libs/mat2tikz/test/private/loadHashTable.m
Normal file
@@ -0,0 +1,19 @@
|
||||
function hashTable = loadHashTable(suite)
|
||||
% loads a reference hash table from disk
|
||||
hashTable.suite = suite;
|
||||
hashTable.contents = struct();
|
||||
filename = hashTableName(suite);
|
||||
if exist(filename, 'file')
|
||||
fid = fopen(filename, 'r');
|
||||
finally_fclose_fid = onCleanup(@() fclose(fid));
|
||||
|
||||
data = textscan(fid, '%s : %s');
|
||||
if ~isempty(data) && ~all(cellfun(@isempty, data))
|
||||
functions = cellfun(@strtrim, data{1},'UniformOutput', false);
|
||||
hashes = cellfun(@strtrim, data{2},'UniformOutput', false);
|
||||
for iFunc = 1:numel(functions)
|
||||
hashTable.contents.(functions{iFunc}) = hashes{iFunc};
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
30
Libs/mat2tikz/test/private/m2troot.m
Normal file
30
Libs/mat2tikz/test/private/m2troot.m
Normal file
@@ -0,0 +1,30 @@
|
||||
function rootpath = m2troot(varargin)
|
||||
% M2TROOT produces paths inside the matlab2tikz repository
|
||||
%
|
||||
% Usage:
|
||||
% There are two ways to call this function, the base syntax is:
|
||||
%
|
||||
% * rootpath = m2troot()
|
||||
%
|
||||
% where |rootpath| points towards the root of the repository.
|
||||
%
|
||||
% The other syntax:
|
||||
%
|
||||
% * path = m2troot(...)
|
||||
%
|
||||
% is equivalent to |fullfile(m2troot, ...)| and as such allows to
|
||||
% easily produce a path to any file within the repository.
|
||||
|
||||
m2t = which('matlab2tikz');
|
||||
if isempty(m2t)
|
||||
error('M2TRoot:NotFound', 'Matlab2tikz was not found on the PATH!')
|
||||
end
|
||||
|
||||
[srcpath] = fileparts(m2t); % this should be $(m2troot)/src
|
||||
[rootpath, srcdir] = fileparts(srcpath); % this should be $(m2troot)
|
||||
assert(strcmpi(srcdir,'src'));
|
||||
|
||||
if nargin >= 1
|
||||
rootpath = fullfile(rootpath, varargin{:});
|
||||
end
|
||||
end
|
||||
24
Libs/mat2tikz/test/private/m2tstrjoin.m
Normal file
24
Libs/mat2tikz/test/private/m2tstrjoin.m
Normal file
@@ -0,0 +1,24 @@
|
||||
function [ newstr ] = m2tstrjoin( cellstr, delimiter )
|
||||
%M2TSTRJOIN This function joins a cellstr with a separator
|
||||
%
|
||||
% This is an alternative implementation for MATLAB's `strjoin`, since that
|
||||
% one is not available before R2013a.
|
||||
%
|
||||
% See also: strjoin
|
||||
|
||||
%TODO: Unify the private `m2tstrjoin` functions
|
||||
%FIXME: differs from src/private/m2tstrjoin in functionality !!!
|
||||
|
||||
nElem = numel(cellstr);
|
||||
if nElem == 0
|
||||
newstr = '';
|
||||
return % m2tstrjoin({}, ...) -> ''
|
||||
end
|
||||
|
||||
newstr = cell(2,nElem);
|
||||
newstr(1,:) = reshape(cellstr, 1, nElem);
|
||||
newstr(2,1:nElem-1) = {delimiter}; % put delimiters in-between the elements
|
||||
newstr(2, end) = {''}; % for Octave 4 compatibility
|
||||
newstr = [newstr{:}];
|
||||
|
||||
end
|
||||
11
Libs/mat2tikz/test/private/restoreGlobalState.m
Normal file
11
Libs/mat2tikz/test/private/restoreGlobalState.m
Normal file
@@ -0,0 +1,11 @@
|
||||
function restoreGlobalState(orig)
|
||||
% Restore original properties of global state.
|
||||
% See #542 and #552
|
||||
fprintf('Restore global state...\n');
|
||||
|
||||
% Restore relevant properties
|
||||
state_fields = fieldnames(orig);
|
||||
for i = 1:length(state_fields)
|
||||
set(0, state_fields{i}, orig.(state_fields{i}).val);
|
||||
end
|
||||
end
|
||||
10
Libs/mat2tikz/test/private/splitPassFailSkippedTests.m
Normal file
10
Libs/mat2tikz/test/private/splitPassFailSkippedTests.m
Normal file
@@ -0,0 +1,10 @@
|
||||
function [passedTests, failedTests, skippedTests] = splitPassFailSkippedTests(status)
|
||||
% splits tests between passed, failed and skippedtests
|
||||
skipped = cellfun(@(s) s.skip, status);
|
||||
status_notSkipped = status(~skipped);
|
||||
failed = hasTestFailed(status_notSkipped);
|
||||
|
||||
passedTests = status_notSkipped(~failed);
|
||||
failedTests = status_notSkipped(failed);
|
||||
skippedTests = status(skipped);
|
||||
end
|
||||
7
Libs/mat2tikz/test/private/splitUnreliableTests.m
Normal file
7
Libs/mat2tikz/test/private/splitUnreliableTests.m
Normal file
@@ -0,0 +1,7 @@
|
||||
function [reliableTests, unreliableTests] = splitUnreliableTests(status)
|
||||
% splits tests between reliable and unreliable tests
|
||||
knownToFail = cellfun(@(s)s.unreliable, status);
|
||||
|
||||
unreliableTests = status( knownToFail);
|
||||
reliableTests = status(~knownToFail);
|
||||
end
|
||||
146
Libs/mat2tikz/test/private/testMatlab2tikz.m
Normal file
146
Libs/mat2tikz/test/private/testMatlab2tikz.m
Normal file
@@ -0,0 +1,146 @@
|
||||
function [status, parameters] = testMatlab2tikz(varargin)
|
||||
%TESTMATLAB2TIKZ unit test driver for matlab2tikz
|
||||
%
|
||||
% This function should NOT be called directly by the user (or even developer).
|
||||
% If you are a developer, please use some of the following functions instead:
|
||||
% * `testHeadless`
|
||||
% * `testGraphical`
|
||||
%
|
||||
% The following arguments are supported, also for the functions above.
|
||||
%
|
||||
% TESTMATLAB2TIKZ('testFunctionIndices', INDICES, ...) or
|
||||
% TESTMATLAB2TIKZ(INDICES, ...) runs the test only for the specified
|
||||
% indices. When empty, all tests are run. (Default: []).
|
||||
%
|
||||
% TESTMATLAB2TIKZ('extraOptions', {'name',value, ...}, ...)
|
||||
% passes the cell array of options to MATLAB2TIKZ. Default: {}
|
||||
%
|
||||
% TESTMATLAB2TIKZ('figureVisible', LOGICAL, ...)
|
||||
% plots the figure visibly during the test process. Default: false
|
||||
%
|
||||
% TESTMATLAB2TIKZ('testsuite', FUNCTION_HANDLE, ...)
|
||||
% Determines which test suite is to be run. Default: @ACID
|
||||
% A test suite is a function that takes a single integer argument, which:
|
||||
% when 0: returns a cell array containing the N function handles to the tests
|
||||
% when >=1 and <=N: runs the appropriate test function
|
||||
% when >N: throws an error
|
||||
%
|
||||
% TESTMATLAB2TIKZ('output', DIRECTORY, ...)
|
||||
% Sets the output directory where the output files are places.
|
||||
% The default directory is $M2TROOT/test/output/current
|
||||
%
|
||||
% See also matlab2tikz, ACID
|
||||
|
||||
% In which environment are we?
|
||||
env = getEnvironment();
|
||||
|
||||
% -----------------------------------------------------------------------
|
||||
ipp = m2tInputParser;
|
||||
|
||||
ipp = ipp.addOptional(ipp, 'testFunctionIndices', [], @isfloat);
|
||||
ipp = ipp.addParamValue(ipp, 'extraOptions', {}, @iscell);
|
||||
ipp = ipp.addParamValue(ipp, 'figureVisible', false, @islogical);
|
||||
ipp = ipp.addParamValue(ipp, 'actionsToExecute', @(varargin) varargin{1}, @isFunction);
|
||||
ipp = ipp.addParamValue(ipp, 'testsuite', @ACID, @isFunction );
|
||||
ipp = ipp.addParamValue(ipp, 'output', m2troot('test','output','current'), @ischar);
|
||||
|
||||
ipp = ipp.parse(ipp, varargin{:});
|
||||
|
||||
ipp = sanitizeInputs(ipp);
|
||||
parameters = ipp.Results;
|
||||
|
||||
% -----------------------------------------------------------------------
|
||||
if strcmpi(env, 'Octave')
|
||||
if ~ipp.Results.figureVisible
|
||||
% Use the gnuplot backend to work around an fltk bug, see
|
||||
% <http://savannah.gnu.org/bugs/?43429>.
|
||||
graphics_toolkit gnuplot
|
||||
end
|
||||
|
||||
if ispc
|
||||
% Prevent three digit exponent on Windows Octave
|
||||
% See https://github.com/matlab2tikz/matlab2tikz/pull/602
|
||||
setenv ('PRINTF_EXPONENT_DIGITS', '2')
|
||||
end
|
||||
end
|
||||
|
||||
% copy output template into output directory
|
||||
if ~exist(ipp.Results.output,'dir')
|
||||
mkdir(ipp.Results.output);
|
||||
end
|
||||
template = m2troot('test','template');
|
||||
copyfile(fullfile(template,'*'), ipp.Results.output);
|
||||
|
||||
% start overall timing
|
||||
elapsedTimeOverall = tic;
|
||||
status = runIndicatedTests(ipp);
|
||||
|
||||
% print out overall timing
|
||||
elapsedTimeOverall = toc(elapsedTimeOverall);
|
||||
stdout = 1;
|
||||
fprintf(stdout, 'overall time: %4.2fs\n\n', elapsedTimeOverall);
|
||||
end
|
||||
% INPUT VALIDATION =============================================================
|
||||
function bool = isFunction(f)
|
||||
bool = isa(f,'function_handle');
|
||||
end
|
||||
function ipp = sanitizeInputs(ipp)
|
||||
% sanitize all input arguments
|
||||
ipp = sanitizeFunctionIndices(ipp);
|
||||
ipp = sanitizeFigureVisible(ipp);
|
||||
end
|
||||
function ipp = sanitizeFunctionIndices(ipp)
|
||||
% sanitize the passed function indices to the range of the test suite
|
||||
% query the number of test functions
|
||||
testsuite = ipp.Results.testsuite;
|
||||
n = length(testsuite(0));
|
||||
|
||||
if ~isempty(ipp.Results.testFunctionIndices)
|
||||
indices = ipp.Results.testFunctionIndices;
|
||||
% kick out the illegal stuff
|
||||
I = find(indices>=1 & indices<=n);
|
||||
indices = indices(I); %#ok
|
||||
else
|
||||
indices = 1:n;
|
||||
end
|
||||
ipp.Results.testFunctionIndices = indices;
|
||||
end
|
||||
function ipp = sanitizeFigureVisible(ipp)
|
||||
% sanitizes the figure visible option from boolean to ON/OFF
|
||||
if ipp.Results.figureVisible
|
||||
ipp.Results.figureVisible = 'on';
|
||||
else
|
||||
ipp.Results.figureVisible = 'off';
|
||||
end
|
||||
end
|
||||
% TEST RUNNER ==================================================================
|
||||
function status = runIndicatedTests(ipp)
|
||||
% run all indicated tests in the test suite
|
||||
% cell array to accomodate different structure
|
||||
indices = ipp.Results.testFunctionIndices;
|
||||
testsuite = ipp.Results.testsuite;
|
||||
testsuiteName = func2str(testsuite);
|
||||
stdout = 1;
|
||||
status = cell(length(indices), 1);
|
||||
|
||||
for k = 1:length(indices)
|
||||
testNumber = indices(k);
|
||||
|
||||
fprintf(stdout, 'Executing %s test no. %d...\n', testsuiteName, indices(k));
|
||||
|
||||
status{k} = emptyStatus(testsuite, testNumber);
|
||||
|
||||
elapsedTime = tic;
|
||||
|
||||
status{k} = feval(ipp.Results.actionsToExecute, status{k}, ipp);
|
||||
|
||||
elapsedTime = toc(elapsedTime);
|
||||
status{k}.elapsedTime = elapsedTime;
|
||||
fprintf(stdout, '%s ', status{k}.function);
|
||||
if status{k}.skip
|
||||
fprintf(stdout, 'skipped (%4.2fs).\n\n', elapsedTime);
|
||||
else
|
||||
fprintf(stdout, 'done (%4.2fs).\n\n', elapsedTime);
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user