function test_suite=test_stack
% tests for cosmo_stack
%
% #   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_stack_samples

    ds=cosmo_synthetic_dataset();
    ds1=cosmo_slice(ds,[2 1 4 3 6 5]);
    ds2=cosmo_slice(ds,6:-1:1,2);



    % test first dimension
    s=cosmo_stack({ds,ds1});
    assertEqual(s.samples,[ds.samples;ds1.samples])
    assertEqual(s.sa.targets,[ds.sa.targets;ds1.sa.targets]);
    assertEqual(s.fa,ds1.fa);

    s2=cosmo_stack({ds,ds2},1,'drop_nonunique');
    assertEqual(fieldnames(s2.fa),{'k'});
    assertEqual(s2.samples,[ds.samples;ds2.samples]);
    assertExceptionThrown(@()cosmo_stack({ds,ds2},1,'unique'),'');
    assertExceptionThrown(@()cosmo_stack({ds,ds2}),'');


    s3=cosmo_stack({ds,ds2},1,'drop');
    assertTrue(isempty(fieldnames(s3.fa)));
    assertEqual(s3.sa,s2.sa);

    s4=cosmo_stack({ds,ds2},1,'drop_nonunique');
    assertEqual(s2,s4);

    s5=cosmo_stack({ds,ds2},1,2);
    assertEqual(s5.fa,ds2.fa);

    % should properly deal with NaNs
    ds.fa.i(2:4)=NaN;
    ds1.fa.i(2:4)=NaN;
    s=cosmo_stack({ds,ds1});
    assertEqual(s.fa,ds1.fa);



function test_stack_features
    ds=cosmo_synthetic_dataset();
    ds1=cosmo_slice(ds,6:-1:1,2);
    ds2=cosmo_slice(ds,[2 1 4 3 6 5]);



    % test second dimension
    s=cosmo_stack({ds,ds1},2,'drop_nonunique');
    assertEqual(s.samples,[ds.samples ds1.samples])
    assertEqual(s.fa.i,[ds.fa.i ds1.fa.i]);
    assertEqual(s.sa,ds1.sa);

    s2=cosmo_stack({ds,ds2},2,'drop_nonunique');
    assertEqual(fieldnames(s2.sa),{'chunks'});
    assertEqual(s2.samples,[ds.samples ds2.samples]);
    assertExceptionThrown(@()cosmo_stack({ds,ds2},2,'unique'),'');
    assertExceptionThrown(@()cosmo_stack({ds,ds2},2),'');


    s3=cosmo_stack({ds,ds2},2,'drop');
    assertTrue(isempty(fieldnames(s3.sa)));
    assertEqual(s3.fa,s2.fa);

    s4=cosmo_stack({ds,ds2},2,'drop_nonunique');
    assertEqual(s2,s4);

    s5=cosmo_stack({ds,ds2},2,2);
    assertEqual(s5.sa,ds2.sa);

    s6=cosmo_stack({ds},1);
    assertEqual(s6,ds);

    % should properly deal with NaNs
    ds.sa.targets(2:4)=NaN;
    ds1.sa.targets(2:4)=NaN;
    s=cosmo_stack({ds,ds},2);
    assertEqual(s.sa,ds1.sa);

function test_stack_exceptions
    % test exceptions
    ds=cosmo_synthetic_dataset();
    aet=@(varargin)assertExceptionThrown(@()cosmo_stack(varargin{:}),'');
    aet('foo');
    aet({ds},3);
    aet({ds},1,'foo');

    % sample size mismatch
    ds1=ds;
    ds1.samples=ones(1,5);
    aet({ds,ds1});

    % .sa size mismatch
    ds1=ds;
    ds1.sa.targets=1;
    aet({ds,ds1});

    % non-matching elements
    ds1=ds;
    ds2=ds;
    ds2.sa.targets=ds2.sa.targets(end:-1:1);
    aet({ds1,ds2},2);

    ds2=ds;
    ds2.fa.i=ds2.fa.i(end:-1:1);
    aet({ds1,ds2},1);


