function test_suite = test_randperm
% tests for cosmo_randperm
%
% # 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_randperm_no_seed
helper_test_deterministic(false);
function test_randperm_with_seed
helper_test_deterministic(true);
function helper_test_deterministic(with_seed)
if with_seed
seed = ceil(rand() * 1e5);
args = {'seed', seed};
else
args = {};
end
f = @(varargin)cosmo_randperm(varargin{:}, args{:});
% single input
n = randint();
x1 = f(n);
assertEqual(size(x1), [1 n]);
assertEqual(sort(x1), 1:n);
x1a = f(n);
if with_seed
assertEqual(x1, x1a);
else
assert(~isequal(x1, x1a));
end
% two inputs, select all
x1a = f(n, n);
if with_seed
assertEqual(x1, x1a);
else
assert(~isequal(x1, x1a));
end
% two inputs, k<n
k = randint();
n = k + randint();
assert(k < n);
x2 = f(n, k);
assertEqual(size(x2), [1 k]);
msk = bsxfun(@eq, (1:n)', x2);
assertEqual(sum(msk(:) == 1), k);
assertEqual(sum(sum(msk == 1, 1), 2), k); % each column has one 1
assertEqual(sum(sum(msk == 1, 2), 1), k); % each row has one 1
if with_seed
% deterministic
x2a = f(n, k);
assertEqual(x2, x2a);
else
found = false;
for attempt = 1:10
x2a = f(n, k);
if ~isequal(x2, x2a)
found = true;
break
end
end
if ~found
error('Different calls do not lead to different outputs');
end
end
x3 = f(0);
assertTrue(isempty(x3));
x4 = f(1);
assertEqual(x4, 1);
x5 = f(1, 1);
assertEqual(x5, 1);
function test_randperm_different_seeds
count = 10;
seed = 0;
result = cell(count, 1);
for k = 1:count
seed = seed + randint();
result{k} = cosmo_randperm(1000, 'seed', seed);
for j = 1:(k - 1)
assertFalse(isequal(result{j}, result{k}));
end
end
function test_randperm_exceptions
aet = @(varargin)assertExceptionThrown(@() ...
cosmo_randperm(varargin{:}), '');
illegal_args = {-1, .5, [1 2], 'foo', struct, cell(0)};
narg = numel(illegal_args);
% illegal first and/or second arguments
for k = 1:narg
for second_arg = [false, true]
for j = 1:narg
if second_arg
args = illegal_args([k j]);
elseif j > 1
continue
else
% single arg if j==1
args = illegal_args(k);
end
aet(args{:});
end
end
end
% illegal seed arguments
for k = 1:narg
arg = illegal_args(k);
aet(4, 2, 'seed', arg{:});
end
% missing seed
aet(4, 2, 'seed');
% double seed
aet(4, 2, 'seed', 1, 'seed', 1);
% 3 numeric arguments
aet(4, 2, 1);
% second argument greater than first
aet(2, 4);
aet(2, 4, 'seed', 1);
% unknown keyword
aet(2, 'foo', 1);
aet(2, 'foo');
function x = randint(n)
x = ceil(10 + rand() * 50);