test match

function test_suite = test_match
    % tests for cosmo_match
    %
    % #   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_match_()
    % helper function to convert numeric to logical array
    b = @(x)logical(x);

    % basic numeric stuff
    assertEqual(cosmo_match(5:-1:1, [2 3]), b([0, 0, 1, 1, 0]));
    assertEqual(cosmo_match((5:-1:1)', [2 3]), b([0, 0, 1, 1, 0])');

    % basic strings
    assertEqual(cosmo_match({'a', 'b', 'c'}, {'b', 'c', 'd', 'e', 'b'}), ...
                b([0 1 1]));
    assertEqual(cosmo_match({'b', 'c', 'd', 'e', 'b'}, {'a', 'b', 'c'}), ...
                b([1 1 0 0 1]));

    assertEqual(cosmo_match({'a', 'b', 'c'}', {'b', 'c', 'd', 'e', 'b'}), ...
                b([0 1 1]'));
    assertEqual(cosmo_match({'b', 'c', 'd', 'e', 'b'}', {'a', 'b', 'c'}), ...
                b([1 1 0 0 1]'));

    assertEqual(cosmo_match({'aaa', 'aa', 'a', 'aa'}, {'a'}), b([0 0 1 0]));
    assertEqual(cosmo_match({'aaa', 'aa', 'a', 'aa'}, 'a'), b([0 0 1 0]));

    assertEqual(cosmo_match({'aaa', 'aa', 'a', 'aa'}, {'aa'}), b([0 1 0 1]));
    assertEqual(cosmo_match({'aaa', 'aa', 'a', 'aa'}, {'a', 'aaa'}), ...
                b([1 0 1 0]));

    % multiple inputs
    assertEqual(cosmo_match(1:5, [2 5], 6:10, 7), b([0 1 0 0 0]));
    assertEqual(cosmo_match(1:5, [2 5], 6:10, 6), b([0 0 0 0 0]));
    assertEqual(cosmo_match(1:5, 1:10, 6:10, 7:9), b([0 1 1 1 0]));
    assertEqual(cosmo_match(1:5, 1:10, 6:10, 7:9, 2:6, 4:5), b([0 0 1 1 0]));

    assertEqual(cosmo_match({'a', 'b', 'c'}, 'b', {'d', 'e', 'f'}, {'f', 'e'}), ...
                b([0 1 0]));

    % empty inputs ok if types match
    assertEqual(cosmo_match({}, ''), b([]));
    assertEqual(cosmo_match([], []), b([]));

    assertExceptionThrown(@()cosmo_match({}, []), '');
    assertExceptionThrown(@()cosmo_match([], {}), '');

    % can use a single string
    assertEqual(cosmo_match({'b', 'c', 'd', 'e', 'b'}, 'b'), b([1 0 0 0 1]));

    % can use function handles
    assertEqual(cosmo_match(1:4, @(x)mod(x, 2) == 0), b([0 1 0 1]));
    assertEqual(cosmo_match({'b', 'c', 'd', 'c'}, @(x)x == 'c'), b([0 1 0 1]));

    % cannot deal with logical arrays
    assertExceptionThrown(@()cosmo_match(5:-1:1, b([0, 0, 1, 1, 0])), '');

    % first argument cannot be a string
    assertExceptionThrown(@()cosmo_match('', ''), '');
    assertExceptionThrown(@()cosmo_match('x', ''), '');

    % no mixed datatypes
    assertExceptionThrown(@()cosmo_match(1, ''), '');
    assertExceptionThrown(@()cosmo_match({'x'}, 1), '');
    assertExceptionThrown(@()cosmo_match({1, 2}, ''), '');
    assertExceptionThrown(@()cosmo_match('', {1, 2}), '');

    assertExceptionThrown(@()cosmo_match(['x'], 1), '');

    assertExceptionThrown(@()cosmo_match({'x', 1}, ''), '');
    assertExceptionThrown(@()cosmo_match({'x', 1}, []), '');
    assertExceptionThrown(@()cosmo_match({'x', 1}, 'x'), '');
    assertExceptionThrown(@()cosmo_match({'x', 1}, 1), '');

    % no support for 2D arrays
    assertExceptionThrown(@()cosmo_match(eye(2), 1), '');
    assertExceptionThrown(@()cosmo_match(cell(2), 1), '');

    % no structs
    assertExceptionThrown(@()cosmo_match(struct(), []), '');
    assertExceptionThrown(@()cosmo_match(struct(), ''), '');
    assertExceptionThrown(@()cosmo_match([], struct()), '');
    assertExceptionThrown(@()cosmo_match({}, struct()), '');

    % needs even number of arguments
    assertExceptionThrown(@()cosmo_match({'a'}), '');
    assertExceptionThrown(@()cosmo_match({'a'}, {'b'}, {'c'}), '');
    assertExceptionThrown(@()cosmo_match({'a'}, {'b'}, {'c'}, 1, 2), '');

    % multiple inputs must have the same size of output
    assertExceptionThrown(@()cosmo_match(1:3, 3, 6:9, 9), '');
    assertExceptionThrown(@()cosmo_match({'a', 'b'}, {'a'}, {'c'}', {'c'}), '');

    % odd elements must be cell string ro numeric
    assertExceptionThrown(@()cosmo_match('a', 'b', 'a', 'c', {'c'}), '');

    % function handle has to return boolean output
    assertExceptionThrown(@()cosmo_match(1:4, @(x)x + 1), '');