function test_suite = test_tail
% tests for cosmo_tail
%
% # For CoSMoMVPA's copyright information and license terms, #
% # see the COPYING file distributed with CoSMoMVPA. #
try % assignment of 'localfunctions' is necessary in Matlab >= 2016
test_functions = localfunctions();
catch % no problem; early Matlab versions can use initTestSuite fine
end
initTestSuite;
function test_tail_basics
nsamples = ceil(15 + rand() * 5);
nselect = floor(rand() * nsamples);
ratio = nselect / nsamples;
x = randn(nsamples, 1);
[xs, idxs] = sort(x);
mp = zeros(nsamples, 1);
mp(idxs) = 1:nsamples;
s = cellfun(@(x)char(x), num2cell(70 + mp), ...
'UniformOutput', false);
ss = sort(s);
[v, i] = cosmo_tail(x, nselect);
assertEqual(v, xs(end + (0:-1:-(nselect - 1))));
assertEqual(i, idxs(end + (0:-1:-(nselect - 1))));
[v2, i2] = cosmo_tail(x, ratio);
assertEqual(v, v2);
assertEqual(i, i2);
[v3, i3] = cosmo_tail(s, nselect);
assertEqual(v3, ss(end + (0:-1:-(nselect - 1))));
assertEqual(i, i3);
[v4, i4] = cosmo_tail(s, ratio);
assertEqual(v3, v4);
assertEqual(i, i4);
[v, i] = cosmo_tail(x, -nselect);
assertEqual(v, xs(1:nselect));
assertEqual(i, idxs(1:nselect));
[v2, i2] = cosmo_tail(x, -ratio);
assertEqual(v, v2);
assertEqual(i, i2);
[v3, i3] = cosmo_tail(s, -nselect);
assertEqual(v3, ss(1:nselect));
assertEqual(i, i3);
[v4, i4] = cosmo_tail(s, -ratio);
assertEqual(v3, v4);
assertEqual(i, i4);
function test_tail_left_right()
n = ceil(10 * rand() + 10);
xs = randn(n, 1);
n_keep = ceil(rand() * 3 + 2);
res = cosmo_tail(xs, n_keep);
assert(numel(res) == n_keep);
% ensure results match
s = sort(xs);
assertEqual(s(end - (0:(n_keep - 1))), res);
% reverse tail and results
res_inv = cosmo_tail(xs, -n_keep);
assertEqual(s(1:n_keep), res_inv);
function test_tail_exceptions
aet = @(varargin)assertExceptionThrown(@() ...
cosmo_tail(varargin{:}), '');
% not ok with non-cellstring / non-vector input
aet(struct(), 0);
aet({1, 2}, 0);
% matrix input not ok
aet(randn(4), 2);
aet({'a', 'b'; 'c', 'd'}, 1);
% outside of range not ok
aet(1:4, 5);
aet(1:4, -5);
% second argument must be numeric scaler
aet(1:4, [1 2]);
aet(1:4, struct);