test disp

function test_suite = test_disp
% tests for cosmo_disp
%
% #   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_disp_array()
    if ~has_evalc()
        cosmo_notify_test_skipped('No support for ''evalc''');
        return;
    end

    aeq=@(s,y) assertEqual([s repmat(sprintf('\n'),size(s,1),1)],...
                                        evalc('cosmo_disp(y)'));

    aeq(['[ 1         2         3  ...  '...
                '8         9        10 ]@1x10'],1:10);

function test_disp_struct()
    if ~has_evalc()
        cosmo_notify_test_skipped('No support for ''evalc''');
        return;
    end

    aeq=@(s,y) assertEqual([s repmat(sprintf('\n'),size(s,1),1)],...
                                        evalc('cosmo_disp(y)'));

    x=struct();
    x.a_cell={[],{'cell in cell',[1 2; 3 4]}};
    x.a_matrix=[10 11 12; 13 14 15];
    x.a_string='hello world';
    x.a_struct.another_struct.name='me';

    s=sprintf(['.a_cell                                        \n'...
                '  { [  ]  { ''cell in cell''  [ 1         2      \n'...
                '                              3         4 ] } }\n'...
                '.a_matrix                                      \n'...
                '  [ 10        11        12                     \n'...
                '    13        14        15 ]                   \n'...
                '.a_string                                      \n'...
                '  ''hello world''                                \n'...
                '.a_struct                                      \n'...
                '  .another_struct                              \n'...
                '    .name                                      \n'...
                '      ''me''                                     ']);



    aeq(s,x);

function test_disp_cases
    if ~has_evalc
        cosmo_notify_test_skipped('No support for ''evalc''');
        return;
    end

    x=1:5;
    assert_equal_disp(x,'threshold',Inf,...
    '[ 1         2         3         4         5 ]\n'...
    );

    x=1:5;
    assert_equal_disp(x,'edgeitems',2,'threshold',1,...
    '[ 1         2  ...  4         5 ]@1x5\n'...
    );

    x=1:5;
    assert_equal_disp(x,'edgeitems',1,'threshold',2,...
    '[ 1  ...  5 ]@1x5\n'...
    );

    x=1:5;
    assert_equal_disp(x,'edgeitems',3,...
    '[ 1         2         3         4         5 ]\n'...
    );

    x='a':'z';
    assert_equal_disp(x,...
    '''abcdefg ... tuvwxyz''\n'...
    );

    x=@abs;
    assert_equal_disp(x,...
    '@abs\n'...
    );

    x={{1,2}};
    assert_equal_disp(x,'depth',1,...
    '{ <cell>@1x2 }\n'...
    );

    x=[13e-20,pi(),13e20];
    assert_equal_disp(x,...
    '[ 1.3e-19      3.14   1.3e+21 ]\n'...
    );

    x=[13e-20,pi(),13e20];
    assert_equal_disp(x,'precision',5,...
    '[ 1.3e-19      3.1416     1.3e+21 ]\n'...
    );

    x=struct();y=x([]);
    assert_equal_disp(y,...
    'struct (empty)\n'...
    );

    x=struct('x',1);
    assert_equal_disp(x,...
     ['.x     \n'...
      '  [ 1 ]\n'...
      ]);

    x=struct('x',{1 2; 3 4});
    assert_equal_disp(x,...
     ['<struct>@2x2   \n'...
      '   (1,1).x     \n'...
      '          [ 1 ]\n'...
      '   (2,1).x     \n'...
      '          [ 3 ]\n'...
      '   (1,2).x     \n'...
      '          [ 2 ]\n'...
      '   (2,2).x     \n'...
      '          [ 4 ]\n'...
      ]);

    x=struct('x',{1 2; 3 4});
    x3=cat(3,x,x,x);
    assert_equal_disp(x3,...
     ['<struct>@2x2x3   \n'...
      '   (1,1,1).x     \n'...
      '            [ 1 ]\n'...
      '   (2,1,1).x     \n'...
      '            [ 3 ]\n'...
      '   (1,2,1).x     \n'...
      '            [ 2 ]\n'...
      '     :        :  \n'...
      '   (2,1,3).x     \n'...
      '            [ 3 ]\n'...
      '   (1,2,3).x     \n'...
      '            [ 2 ]\n'...
      '   (2,2,3).x     \n'...
      '            [ 4 ]\n'...
      ]);

    x=struct('x',{1 2; 3 4});
    y=repmat({x},10,10);
    x3=cat(3,y{:});
    assert_equal_disp(x3,...
     ['<struct>@2x2x100   \n'...
      '   (1,1,1)  .x     \n'...
      '              [ 1 ]\n'...
      '   (2,1,1)  .x     \n'...
      '              [ 3 ]\n'...
      '   (1,2,1)  .x     \n'...
      '              [ 2 ]\n'...
      '      :         :  \n'...
      '   (2,1,100).x     \n'...
      '              [ 3 ]\n'...
      '   (1,2,100).x     \n'...
      '              [ 2 ]\n'...
      '   (2,2,100).x     \n'...
      '              [ 4 ]\n'...
      ]);

    x=zeros([2 2 1 2 3]);
    x(:)=2*(1:numel(x));
    assert_equal_disp(x,...
     ['<double>@2x2x1x2x3               \n'...
      '   (:,:,1,1,1) = [ 2         6   \n'...
      '                   4         8 ] \n'...
      '   (:,:,1,2,1) = [ 10        14  \n'...
      '                   12        16 ]\n'...
      '   (:,:,1,1,2) = [ 18        22  \n'...
      '                   20        24 ]\n'...
      '   (:,:,1,2,2) = [ 26        30  \n'...
      '                   28        32 ]\n'...
      '   (:,:,1,1,3) = [ 34        38  \n'...
      '                   36        40 ]\n'...
      '   (:,:,1,2,3) = [ 42        46  \n'...
      '                   44        48 ]\n'...
      ]);

    x=num2cell(1:10);
    assert_equal_disp(x,...
    '{ [ 1 ]  [ 2 ]  [ 3 ] ... [ 8 ]  [ 9 ]  [ 10 ]   }@1x10\n'...
    );

    x=reshape(num2cell(1:100),10,10);
    assert_equal_disp(x,...
     ['{ [ 1 ]   [ 11 ]  [ 21 ] ... [ 71 ]  [ 81 ]  [ 91 ]           \n'...
      '  [ 2 ]   [ 12 ]  [ 22 ] ... [ 72 ]  [ 82 ]  [ 92 ]           \n'...
      '  [ 3 ]   [ 13 ]  [ 23 ] ... [ 73 ]  [ 83 ]  [ 93 ]           \n'...
      '    :       :       :          :       :       :              \n'...
      '  [ 8 ]   [ 18 ]  [ 28 ] ... [ 78 ]  [ 88 ]  [ 98 ]           \n'...
      '  [ 9 ]   [ 19 ]  [ 29 ] ... [ 79 ]  [ 89 ]  [ 99 ]           \n'...
      '  [ 10 ]  [ 20 ]  [ 30 ] ... [ 80 ]  [ 90 ]  [ 100 ]   }@10x10\n'...
      ]);

    x=reshape(1:100,10,10);
    assert_equal_disp(x,...
     ['[  1        11        21  ...  71        81        91        \n'...
      '   2        12        22  ...  72        82        92        \n'...
      '   3        13        23  ...  73        83        93        \n'...
      '   :         :         :        :         :        :         \n'...
      '   8        18        28  ...  78        88        98        \n'...
      '   9        19        29  ...  79        89        99        \n'...
      '  10        20        30  ...  80        90       100 ]@10x10\n'...
      ]);

function test_disp_nosize()
    if ~has_evalc() || cosmo_wtf('is_octave');
        cosmo_notify_test_skipped(['No support for testing evalc '...
                                    'on data with no size']);
        return;
    end
    orig_pwd=pwd();
    pwd_resetter=onCleanup(@()cd(orig_pwd));
    temp_dir=fullfile(orig_pwd,cosmo_make_temp_filename());
    dir_cleaner=onCleanup(@()remove_dir_helper(temp_dir));

    % override 'size' method for double
    mkdir(temp_dir);
    temp_double_dir=fullfile(temp_dir,'@double');
    mkdir(temp_double_dir);

    size_fn=fullfile(temp_double_dir,'size.m');
    fid=fopen(size_fn,'w');
    fprintf(fid,'function size(varargin)\nerror(''undefined'');');
    fclose(fid);

    cd(temp_dir);
    assert_equal_disp(1,'<double>\n');


function tf=has_evalc()
    tf=exist('evalc','builtin') || ~isempty(which('evalc'));

function remove_dir_helper(tmp_dir)
    if cosmo_wtf('is_octave')
        rmdir_state=confirm_recursive_rmdir();
        state_resetter=onCleanup(@()confirm_recursive_rmdir(rmdir_state));
        confirm_recursive_rmdir(false,'local');
    end
    rmdir(tmp_dir,'s');


function assert_equal_disp(varargin)
    args=varargin(1:(end-1));
    str=varargin{end};

    cmd='cosmo_disp(args{:})';
    assertEqual(evalc(cmd),sprintf(str));