Skip to content
Snippets Groups Projects
Verified Commit 86ab078f authored by Thomas Lambert's avatar Thomas Lambert :helicopter:
Browse files

test: add tests for savetodat and uiuccleanr

parent 7ce55752
No related branches found
No related tags found
No related merge requests found
function savecoordtodat(filename, header, x, y)
% SAVECOORDTODAT Saves the airfoil coordinates to a dat file
import af_tools.utils.vecttocol;
x = vecttocol(x);
y = vecttocol(y);
data=num2str([x, y],'%0.7f ');
contents=char(header,data);
dlmwrite(filename,contents,'delimiter','')
end
function savetodat(filename, header, varargin)
% SAVETODAT Saves input table or list of vectors to a dat file
% Note:
% This inputs need to have the same dimensions to be concatenated into a
% single output array.
import af_tools.utils.vecttocol;
import af_tools.utils.appendextension;
filename = appendextension(filename,'.dat');
datatable = [];
for i = 1:length(varargin)
col = vecttocol(varargin{i});
datatable = [datatable, col];
end
data=num2str(datatable,'%0.7f ');
contents=char(header,data);
dlmwrite(filename,contents,'delimiter','')
end
......@@ -124,7 +124,7 @@ y = [yu, fliplr(yl(1:end-1))];
if savedat
header = ['NACA',digits,' - ',spacing,' spacing'];
filename = ['naca', digits, '.dat'];
savecoordtodat(filename, header, x, y)
savetodat(filename, header, x, y)
end
end
......
......@@ -11,11 +11,11 @@ function Dat = uiuccleaner(varargin)
% used originally by Selig on the UIUC Airfoil Database.
% The first line contains the name of the airfoil, and each line after that is
% a set of coordinates. The coordinates are ordered from the trailing edge,
% along the upper surface to the leading edge and back around the lower
% along the upper surface to the leading edge and back around the lower
% surface to trailing edge.
%
% Note:
% This function can be used on many files at once in order to speed-up the
% This function can be used on many files at once in order to speed-up the
% process.
%
% <a href="https://gitlab.uliege.be/thlamb/airfoil_toolbox">Documentation (README)</a>
......@@ -23,12 +23,12 @@ function Dat = uiuccleaner(varargin)
% -----
%
% Usage:
% DAT = UIUCCLEANER prompts the user for all inputs, then converts the
% DAT = UIUCCLEANER prompts the user for all inputs, then converts the
% coordinates to the correct standard.
%
% DAT = UIUCCLEANER(INPUTDIR) converts all dat files found in INPUTDIR.
%
% DAT = UIUCCLEANER(INPUTDIR, INPUTFILES) converts only the polars
% DAT = UIUCCLEANER(INPUTDIR, INPUTFILES) converts only the polars
% specified by INPUTFILES found in INPUTDIR.
%
% DAT = UIUCCLEANER(..., 'autosave', true) saves the resulting coordinates
......@@ -44,7 +44,7 @@ function Dat = uiuccleaner(varargin)
% inputFiles : Files to select (ex: '*' (default), '*0012*', {'file1','file2'}, etc)
%
% Output:
% Dat : A structure for the results for each input file.
% Dat : A structure for the results for each input file.
% - Dat.file : original filename
% - Dat.airfoil : airfoil name, parsed from the input file
% - Dat.x : airfoil X coordinates, with 0 <= X <= 1
......@@ -96,7 +96,7 @@ for i=1:nbFiles
% No matter the file type, line 1 should always be the airfoil name
fileID = fopen(fullfile(fullpath,allFileNames{i}));
tmpAirfoil = textscan(fileID,'%s', 1, 'Delimiter','\n:','HeaderLines',0);
resultArray = cell2mat(textscan(fileID,'%f %f %*[^\n]', 'HeaderLines',0)); % ! HeaderLines is a cursor. This will start reading at line 13
resultArray = cell2mat(textscan(fileID,'%f %f %*[^\n]', 'HeaderLines',0));
fclose(fileID); clear fileID;
% Re-order file if it is needed
......@@ -114,7 +114,7 @@ for i=1:nbFiles
end
% Output structure
Dat(i).path = fullpath;
Dat(i).path = fullpath;
Dat(i).file = allFileNames{i};
Dat(i).airfoil = char(cellstr(tmpAirfoil{:}));
Dat(i).x = resultArray(:,1);
......@@ -136,7 +136,7 @@ if autosave
filename = appendextension(filename,'.dat');
filename = fullfile(Dat(i).path,filename);
header = Dat(i).airfoil;
savecoordtodat(filename, header, Dat(i).x, Dat(i).y)
savetodat(filename, header, Dat(i).x, Dat(i).y)
end
......@@ -163,7 +163,7 @@ hasNoInput = isempty(varargin) || isoption(OPTION_LIST, varargin{1});
if hasNoInput
% Prompt user for the files to read
[allFileNames, fullpath] = uigetfile('*.dat', 'Select all dat-files to aggregate', 'MultiSelect', 'on','textFiles');
[allFileNames, fullpath] = uigetfile('*.dat', 'Select all dat-files to aggregate', 'MultiSelect', 'on');
idxOpts = 1;
else
inputDir = varargin{1};
......@@ -208,7 +208,7 @@ else
AllFiles = [];
for i = 1:length(inputFiles)
inputFiles(i) = appendextension(inputFiles(i),'.txt'); % Add extension
inputFiles(i) = appendextension(inputFiles(i),'.dat'); % Add extension
dummy = dir(fullfile(fullpath,inputFiles(i)));
if isempty(dummy)
warning('MATLAB:uiuccleaner:FileNotFound', 'Could not find file %s.', fullfile(fullpath,inputFiles(i)));
......
% TEST_SAVETODAT Unitary tests for the savetodat sub-function
% Note:
% Matlab package functionality is not very test-framework friendly.
% Either the whole package has to be imported in EVERY SINGLE TEST or the
% functions must be called as <package>.function() everytime.
% The second option is preferred for the tests as it has the smaller scope.
% -----
% Copyright 2022 Thomas Lambert <t.lambert@uliege.be>
% ULiege - Aeroelasticity and Experimental Aerodynamics
% Apache 2.0 License
% https://gitlab.uliege.be/am-dept/matlab_airfoil_toolbox
% ------------------------------------------------------------------------------
%% Main test function
function tests = test_savetodat
tests = functiontests(localfunctions);
end
%% Setup and teardown
function setupOnce(testCase)
addpath('../.'); % Add repository to Matlab Path
addpath('./test_utils'); % Add utils to Matlab Path
% Set random number generator settings
testCase.TestData.currentRNG = rng;
end
function teardownOnce(testCase)
rmpath('../.'); % Remove repository from Matlab Path
rmpath('./test_utils'); % Remove utils from Matlab Path
% Restore the random number generator settings
s = testCase.TestData.currentRNG;
rng(s)
end
function teardown(~)
close all; % Close all figures that would have been openend
end
%% Test for correct output
function test_saveArray(testCase)
% Save a single array as is
filename = 'testDatArray.dat';
header = 'test-array';
array = rand(10,3);
af_tools.utils.savetodat(filename, header, array);
[headFile, arrFile] = loaddat3col(filename);
headFile = strtrim(char(headFile{:}));
verifyEqual(testCase, headFile, header);
verifyEqual(testCase, arrFile, array, 'AbsTol',1e-7)
% Cleanup
delete(filename);
end
function test_saveVectors(testCase)
% Save multiple vectors of the same size as a single array
filename = 'testDatVector.dat';
header = 'test-vectors';
vect1 = rand(10,1);
vect2 = rand(1,10);
vect3 = 1:10;
af_tools.utils.savetodat(filename, header, vect1, vect2, vect3);
[headFile, arrFile] = loaddat3col(filename);
headFile = strtrim(char(headFile{:}));
vect1 = af_tools.utils.vecttocol(vect1);
vect2 = af_tools.utils.vecttocol(vect2);
vect3 = af_tools.utils.vecttocol(vect3);
verifyEqual(testCase, headFile, header);
verifyEqual(testCase, arrFile, [vect1, vect2, vect3], 'AbsTol',1e-7)
% Cleanup
delete(filename);
end
% -------------------------------------
function [header, array] = loaddat3col(filename)
% LOADDAT Loads dat-file and split header and array
fileID = fopen(fullfile(pwd,filename));
header = textscan(fileID,'%s', 1, 'Delimiter','\n:','HeaderLines',0);
array = cell2mat(textscan(fileID,'%f %f %f %*[^\n]', 'HeaderLines',0));
fclose(fileID); clear fileID;
end
% TEST_UIUCCLEANER Unitary tests for the uiuccleaner function
% Note:
% Matlab package functionality is not very test-framework friendly.
% Either the whole package has to be imported in EVERY SINGLE TEST or the
% functions must be called as <package>.function() everytime.
% The second option is preferred for the tests as it has the smaller scope.
% -----
% Copyright 2022 Thomas Lambert <t.lambert@uliege.be>
% ULiege - Aeroelasticity and Experimental Aerodynamics
% Apache 2.0 License
% https://gitlab.uliege.be/am-dept/matlab_airfoil_toolbox
% ------------------------------------------------------------------------------
%% Main test function
function tests = test_uiuccleaner
tests = functiontests(localfunctions);
end
%% Setup and teardown
function setupOnce(testCase)
addpath('../.'); % Add repository to Matlab Path
addpath('./test_utils'); % Add utils to Matlab Path
% Set random number generator settings.
testCase.TestData.currentRNG = rng;
end
function teardownOnce(testCase)
rmpath('../.'); % Remove repository from Matlab Path
rmpath('./test_utils'); % Remove utils from Matlab Path
% Restore the random number generator settings.
s = testCase.TestData.currentRNG;
rng(s)
end
function teardown(~)
close all; % Close all figures that would have been openend
end
%% Arguments and errors tests
function test_nargin(testCase)
% Error if too many arguments
dummy = (1:10)';
verifyError(testCase, @() af_tools.uiuccleaner(dummy, dummy, dummy, 'autosave',true,'overwrite',false), 'MATLAB:narginchk:tooManyInputs')
end
function test_invalidInputsType(testCase)
% Error if base inputs are of the wrong type
empty = [];
scal = 0;
logi = true;
Struct = struct;
% 1. InputDir (char vector or string)
verifyError(testCase, @() af_tools.uiuccleaner(empty), 'MATLAB:uiuccleaner:invalidType')
verifyError(testCase, @() af_tools.uiuccleaner(scal), 'MATLAB:uiuccleaner:invalidType')
verifyError(testCase, @() af_tools.uiuccleaner(logi), 'MATLAB:uiuccleaner:invalidType')
verifyError(testCase, @() af_tools.uiuccleaner(Struct), 'MATLAB:uiuccleaner:invalidType')
% 2. cl (numeric)
verifyError(testCase, @() af_tools.uiuccleaner(scal, empty), 'MATLAB:uiuccleaner:invalidType')
verifyError(testCase, @() af_tools.uiuccleaner(scal, scal), 'MATLAB:uiuccleaner:invalidType')
verifyError(testCase, @() af_tools.uiuccleaner(scal, logi), 'MATLAB:uiuccleaner:invalidType')
verifyError(testCase, @() af_tools.uiuccleaner(scal, Struct), 'MATLAB:uiuccleaner:invalidType')
end
function test_invalidOptions(testCase)
% Error if invalid option name or missing parameter value
wrongName = 'wrongOption';
testdir = [pwd,'/test_utils'];
verifyError(testCase, @() af_tools.uiuccleaner(testdir, '*', wrongName), 'MATLAB:InputParser:ParamMissingValue')
verifyError(testCase, @() af_tools.uiuccleaner(testdir, '*', wrongName, true), 'MATLAB:InputParser:UnmatchedParameter')
verifyError(testCase, @() af_tools.uiuccleaner(testdir, 'autosave', true, wrongName), 'MATLAB:InputParser:ParamMissingValue')
verifyError(testCase, @() af_tools.uiuccleaner(testdir, 'autosave', true, wrongName, true), 'MATLAB:InputParser:UnmatchedParameter')
end
function test_invalidOptionsVal(testCase)
% Error if valid option name but invalid value
empty = [];
scal = 0;
char = 'test';
Struct = struct;
vect = 1:10;
testdir = [pwd,'/test_utils'];
verifyError(testCase, @() af_tools.uiuccleaner(testdir, 'autosave', empty), 'MATLAB:uiuccleaner:invalidType')
verifyError(testCase, @() af_tools.uiuccleaner(testdir, 'autosave', scal), 'MATLAB:uiuccleaner:invalidType')
verifyError(testCase, @() af_tools.uiuccleaner(testdir, 'autosave', char), 'MATLAB:uiuccleaner:invalidType')
verifyError(testCase, @() af_tools.uiuccleaner(testdir, 'autosave', Struct), 'MATLAB:uiuccleaner:invalidType')
verifyError(testCase, @() af_tools.uiuccleaner(testdir, 'autosave', vect), 'MATLAB:uiuccleaner:invalidType')
verifyError(testCase, @() af_tools.uiuccleaner(testdir, 'overwrite', empty), 'MATLAB:uiuccleaner:invalidType')
verifyError(testCase, @() af_tools.uiuccleaner(testdir, 'overwrite', scal), 'MATLAB:uiuccleaner:invalidType')
verifyError(testCase, @() af_tools.uiuccleaner(testdir, 'overwrite', char), 'MATLAB:uiuccleaner:invalidType')
verifyError(testCase, @() af_tools.uiuccleaner(testdir, 'overwrite', Struct), 'MATLAB:uiuccleaner:invalidType')
verifyError(testCase, @() af_tools.uiuccleaner(testdir, 'overwrite', vect), 'MATLAB:uiuccleaner:invalidType')
end
% -------------------------------------
function test_dirNotFound(testCase)
% Error if valid inputDir not found
verifyError(testCase, @() af_tools.uiuccleaner('missingdir'), 'MATLAB:uiuccleaner:dirNotFound')
end
function test_fileNotFound(testCase)
% Error if valid inputDir not found
testdir = [pwd,'/test_utils'];
verifyWarning(testCase, @() af_tools.uiuccleaner(testdir, {'clarky.dat','testdummy.dat'}), 'MATLAB:uiuccleaner:FileNotFound')
warning('off','MATLAB:uiuccleaner:FileNotFound') % remove warning first warning about FileNotFound before it throws the error
verifyError(testCase, @() af_tools.uiuccleaner(testdir, 'randomFile'), 'MATLAB:uiuccleaner:noFilesFound')
warning on % Reactivate warnings
end
%% Test if function returns expected outputs
function test_correctOrder(testCase)
% Verify if the output starts and ends at X = 1;
testdir = [pwd,'/test_utils'];
Dat = af_tools.uiuccleaner(testdir, '*');
verifyEqual(testCase, Dat(1).x(1), 1)
verifyEqual(testCase, Dat(1).x(end), 1)
verifyEqual(testCase, Dat(2).x(end), 1)
verifyEqual(testCase, Dat(2).x(end), 1)
end
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment