/*
 *  test_multimeter_stepping.sli
 *
 *  This file is part of NEST.
 *
 *  Copyright (C) 2004 The NEST Initiative
 *
 *  NEST is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  NEST is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with NEST.  If not, see <http://www.gnu.org/licenses/>.
 *
 */


/* BeginDocumentation
Name: testsuite::test_multimeter_stepping - test if multimeter returns same values for stepped simulation

Synopsis: (test_multimeter_stepping.sli) run -> dies if assertion fails

Description:
The script checks all models providing a "recordables" entry in their
status dict.  It creates a multimeter, sets it to record from all
recordables. The neuron receives Poisson input. This is done once for
a single 50 x MinDelay simulation and once for 50 subsequent MinDelay simulations. The test passes
if both cases produce identical results.

Author: Plesser
FirstVersion: 2010-10-05
*/

(unittest) run
/unittest using

M_ERROR setverbosity

/skip_list [ ] def

/clear_error
{ 
  counttomark npop % pop all but mark
  errordict begin /newerror false def end
} def


% single simulation run
% arg: model
% arg: continuous
/run_sim
{
  /continuous Set
  /model Set
  ResetKernel
  model GetDefaults /recordables get /recs Set
  /n model Create def
  /mm /multimeter << /record_from recs /withtime false /interval 0.1  >> Create def

  mark 
  {
    mm n Connect
    /pg /poisson_generator << /rate 1e4 >> Create def
    pg n Connect
    /minDelay 0 /min_delay get def
    continuous
    { 
      50 minDelay mul Simulate
    }
    {
      50 { minDelay Simulate } repeat
    }
    ifelse
    mm /events get [ recs ] get { cva } Map
  }
  stopped
  {
    clear_error
    pop % remove mark
    []
  }
  {
    exch pop   % remove mark
  }
  ifelse

} def

% Execute test for one model
% Argument: model name
% Result: true or false
% Returns true if model does not have recordables
/run_tests
{
  /model Set
  model GetDefaults
  /recordables known
  {
    (Testing: ) =only model =only
    model true  run_sim /res1 Set
    model false run_sim /res2 Set

    % should have two arrays of events results on the stack now, should be equal
    res1 res2 eq
    
    dup { ( ... ok) == } { ( ... FAIL) ==  } ifelse
   }
  {
    true
  }
  ifelse
} 
def

{
  modeldict keys { 
    dup skip_list exch MemberQ not
    { 
      run_tests 
    } 
    {
      pop true  % pop model, define as true
    } ifelse 
   } Map
   true exch { and } Fold
}
assert_or_die

