cdece02001-01-29Per Hedbor int current_test, tests_failed;
2556b92001-01-31Per Hedbor int verbose;
6fc7c82012-02-14Martin Stjernholm constant single_thread = 0; // If this constant is set then the test will run in the backend // thread while all handler threads are on hold (which implies the // background_run queue is on hold as well). Otherwise tests are run // in one handler thread while another one is free to execute // background jobs right away.
fba4b12001-02-01Per Hedbor void create( int vb ) { verbose = vb; }
2556b92001-01-31Per Hedbor 
cdece02001-01-29Per Hedbor 
18a68b2009-09-17Martin Stjernholm string describe_test (function|string cb, array args) {
5859dd2009-09-24Martin Stjernholm  if (!stringp (cb)) { object describer = master()->Describer(); return describer->describe (cb) + "(" + describer->describe_comma_list (args, 512) + ")"; }
18a68b2009-09-17Martin Stjernholm  if (sizeof (args)) catch {return sprintf (cb, @args);}; return cb; } string pad_to_column (string str, int col, string cont_prefix) { array(string) split = str / "\n"; if (sizeof (split) > 1 && split[-1] == "") split = split[..<1]; if (sizeof (split[-1]) > col) split += ({""}); split[-1] += " " * (col - sizeof (split[-1])); return split * ("\n" + cont_prefix); } void report_1st(function|string|array cb, array args, function check )
cdece02001-01-29Per Hedbor {
2556b92001-01-31Per Hedbor  if( !verbose ) return;
30e3142001-01-31Per Hedbor  int checkid = ' '; if( check == check_error ) checkid = '#'; else if( check == check_false ) checkid = '!'; else if( check != check_is_configuration &&
c4bfff2018-02-27Karl Gustav Sterneberg  check == check_is_module )
30e3142001-01-31Per Hedbor  checkid = '~';
18a68b2009-09-17Martin Stjernholm  if (arrayp (cb)) // Got line number info. report_error ("%3d %s:%d:\n"
c4bfff2018-02-27Karl Gustav Sterneberg  " %c %s ", current_test, cb[0], cb[1], checkid, pad_to_column (describe_test (cb[2], args), 66, sprintf (" %c ", checkid)));
18a68b2009-09-17Martin Stjernholm  else report_error("%3d%c %s ", current_test, checkid,
c4bfff2018-02-27Karl Gustav Sterneberg  pad_to_column (describe_test (cb, args), 66, sprintf (" %c ", checkid)));
cdece02001-01-29Per Hedbor }
2556b92001-01-31Per Hedbor string indent( int l, string what ) { array q = what/"\n";
a85c0b2009-11-03Martin Stjernholm  int trailing_nl = q[-1] == ""; if (trailing_nl) q = q[..<1];
2556b92001-01-31Per Hedbor  string i = (" "*l+"| ");
a85c0b2009-11-03Martin Stjernholm  return i+q*("\n"+i) + (trailing_nl ? "\n" : ""); } void log (string msg, mixed... args) { if (sizeof (args)) msg = sprintf (msg, @args); report_debug (indent (2, msg)); } void log_verbose (string msg, mixed... args) { if (!verbose) return; if (sizeof (args)) msg = sprintf (msg, @args); report_debug (indent (2, msg));
2556b92001-01-31Per Hedbor }
cdece02001-01-29Per Hedbor string do_describe_error( mixed err ) {
18a68b2009-09-17Martin Stjernholm  if (!stringp (err)) err = describe_backtrace (err); if (has_suffix (err, "\n")) err = err[..<1]; return indent(2, err) + "\n";
cdece02001-01-29Per Hedbor }
18a68b2009-09-17Martin Stjernholm void report_test_failure( mixed err,
c4bfff2018-02-27Karl Gustav Sterneberg  function|string|array cb, array args, int st )
cdece02001-01-29Per Hedbor {
2556b92001-01-31Per Hedbor  if( verbose )
6c313b2012-02-14Martin Stjernholm  report_debug(" ################ FAILED\n");
18a68b2009-09-17Martin Stjernholm  else { if (arrayp (cb)) { // Got line number info.
6c313b2012-02-14Martin Stjernholm  report_debug (indent (2, sprintf ("################ %s:%d: FAILED",
c4bfff2018-02-27Karl Gustav Sterneberg  cb[0], cb[1])) + "\n" + do_describe_error(describe_test (cb[2], args)));
18a68b2009-09-17Martin Stjernholm  } else
6c313b2012-02-14Martin Stjernholm  report_debug(indent (2, "################ " +
c4bfff2018-02-27Karl Gustav Sterneberg  describe_test (cb, args) + " FAILED\n"));
18a68b2009-09-17Martin Stjernholm  }
2556b92001-01-31Per Hedbor  if( err ) report_debug( do_describe_error( err ) );
18a68b2009-09-17Martin Stjernholm  report_debug ("\n");
cdece02001-01-29Per Hedbor  tests_failed++; }
18a68b2009-09-17Martin Stjernholm void report_test_ok( mixed err, function|string|array cb, array args, int st )
cdece02001-01-29Per Hedbor {
2556b92001-01-31Per Hedbor  if( verbose ) { int tt = (gethrtime()-st); if( tt > 200000 ) report_debug(" %4dms\n", tt/1000); else report_debug( " PASS\n" ); // if( err ) report_error( do_describe_error( err ) ); }
cdece02001-01-29Per Hedbor }
92d7312018-02-27Karl Gustav Sterneberg private mixed test_generic_low( function check_return, function|array cb, bool throw_error, mixed ... args )
cdece02001-01-29Per Hedbor { current_test++; mixed result;
30e3142001-01-31Per Hedbor  report_1st( cb, args, check_return );
cdece02001-01-29Per Hedbor  int st = gethrtime();
18a68b2009-09-17Martin Stjernholm  function test_fn = arrayp (cb) ? cb[2] : cb;
cdece02001-01-29Per Hedbor  mixed err = catch {
18a68b2009-09-17Martin Stjernholm  result = test_fn( @args );
cdece02001-01-29Per Hedbor  };
92d7312018-02-27Karl Gustav Sterneberg  if( err && throw_error ) { report_test_failure( err, cb, args, st ); throw( err ); } // Not all check-functions support the extra throw_error arg. if ( check_return && throw_error ) { check_return( result, err, cb, args,st, throw_error); } else if( check_return )
cdece02001-01-29Per Hedbor  check_return( result, err, cb, args,st ); else if( err ) report_test_failure( err, cb, args,st ); else report_test_ok( err, cb, args,st ); return result; }
92d7312018-02-27Karl Gustav Sterneberg mixed test_generic( function check_return, function|array cb, mixed ... args ) { return test_generic_low( check_return, cb, false, @args ); } mixed assert_generic( function check_return, function|array cb, mixed ... args ) { return test_generic_low( check_return, cb, true, @args ); }
18a68b2009-09-17Martin Stjernholm mixed test_really_generic( function check_return, function(void:mixed) test_fn,
92d7312018-02-27Karl Gustav Sterneberg  string|array test_text, array test_text_args, bool|void throw_error )
18a68b2009-09-17Martin Stjernholm { current_test++; mixed result; int st = gethrtime(); mixed err = catch { result = test_fn(); };
5859dd2009-09-24Martin Stjernholm  // Write out the test after running it, since the macros change // test_text_args in the test. report_1st( test_text, test_text_args, check_return );
92d7312018-02-27Karl Gustav Sterneberg  if( err && throw_error ) { report_test_failure( err, test_text, test_text_args, st ); throw( err ); }
7792d12018-02-27Karl Gustav Sterneberg  if( check_return && throw_error ) check_return( result, err, test_text, test_text_args, st, throw_error ); else if( check_return )
18a68b2009-09-17Martin Stjernholm  check_return( result, err, test_text, test_text_args,st ); else if( err ) report_test_failure( err, test_text, test_text_args,st ); else report_test_ok( err, test_text, test_text_args,st ); return result; }
cdece02001-01-29Per Hedbor 
18a68b2009-09-17Martin Stjernholm void check_error( mixed res, mixed err,
92d7312018-02-27Karl Gustav Sterneberg  function|string|array cb, array args, int st, bool|void throw_error )
cdece02001-01-29Per Hedbor {
92d7312018-02-27Karl Gustav Sterneberg  if( err ) {
cdece02001-01-29Per Hedbor  report_test_ok( err, cb, args, st );
92d7312018-02-27Karl Gustav Sterneberg  } else {
cdece02001-01-29Per Hedbor  report_test_failure( "Expected error", cb, args, st );
92d7312018-02-27Karl Gustav Sterneberg  if( throw_error ) {
2c11482018-03-20Henrik Grubbström (Grubba)  error( "Expected error but none was thrown.\n" );
92d7312018-02-27Karl Gustav Sterneberg  } } } private void assert_throws_error( mixed res, mixed err, function|string|array cb, array args, int st ) { check_error( res, err, cb, args, st, true );
cdece02001-01-29Per Hedbor }
18a68b2009-09-17Martin Stjernholm void check_is_module( mixed res, mixed err,
c4bfff2018-02-27Karl Gustav Sterneberg  function|string|array cb, array args, int st )
cdece02001-01-29Per Hedbor { if( err ) report_test_failure( err, cb, args, st ); else if( !objectp(res) || !res->is_module || !res->my_configuration() ) report_test_failure( sprintf("Got %O, expected module", res),cb,args,
c4bfff2018-02-27Karl Gustav Sterneberg  st);
cdece02001-01-29Per Hedbor  else report_test_ok( err, cb, args, st ); }
18a68b2009-09-17Martin Stjernholm void check_is_configuration( mixed res, mixed err,
c4bfff2018-02-27Karl Gustav Sterneberg  function|string|array cb, array args, int st)
cdece02001-01-29Per Hedbor { if( err ) report_test_failure( err, cb, args, st ); else if( !objectp(res) || !res->is_configuration ) report_test_failure( sprintf("Got %O, expected configuration", res),cb,args, st); else report_test_ok( err, cb, args, st ); }
5859dd2009-09-24Martin Stjernholm void silent_check_true( mixed res, mixed err,
7792d12018-02-27Karl Gustav Sterneberg  function|string|array cb, array args, int st, bool|void throw_error )
5859dd2009-09-24Martin Stjernholm {
7792d12018-02-27Karl Gustav Sterneberg  if( err || !res ) {
5859dd2009-09-24Martin Stjernholm  report_test_failure( err, cb, args, st );
7792d12018-02-27Karl Gustav Sterneberg  if( throw_error ) { if( err ) { throw( err ); } else {
2c11482018-03-20Henrik Grubbström (Grubba)  error( "Condition failed.\n" );
7792d12018-02-27Karl Gustav Sterneberg  } } } else {
5859dd2009-09-24Martin Stjernholm  report_test_ok( 0, cb, args, st );
7792d12018-02-27Karl Gustav Sterneberg  }
5859dd2009-09-24Martin Stjernholm }
cdece02001-01-29Per Hedbor 
18a68b2009-09-17Martin Stjernholm void check_true( mixed res, mixed err,
92d7312018-02-27Karl Gustav Sterneberg  function|string|array cb, array args, int st, bool|void throw_error )
cdece02001-01-29Per Hedbor {
92d7312018-02-27Karl Gustav Sterneberg  if( err ) {
cdece02001-01-29Per Hedbor  report_test_failure( err, cb, args, st );
92d7312018-02-27Karl Gustav Sterneberg  if( throw_error ) { throw( err ); } }
7792d12018-02-27Karl Gustav Sterneberg  else if( !res ) { report_test_failure( sprintf ("expected non-zero, got %O", res), cb, args, st); if( throw_error ) {
2c11482018-03-20Henrik Grubbström (Grubba)  error( sprintf ("expected non-zero, got %O\n", res) );
92d7312018-02-27Karl Gustav Sterneberg  }
7792d12018-02-27Karl Gustav Sterneberg  } else { report_test_ok( err, cb, args, st ); }
cdece02001-01-29Per Hedbor }
6a6a8c2001-01-30Per Hedbor 
92d7312018-02-27Karl Gustav Sterneberg private void assert_result_true( mixed res, mixed err, function|string|array cb, array args, int st ) { check_true(res, err, cb, args, st, true); }
18a68b2009-09-17Martin Stjernholm void check_false( mixed res, mixed err,
92d7312018-02-27Karl Gustav Sterneberg  function|string|array cb, array args, int st, bool|void throw_error )
30e3142001-01-31Per Hedbor {
92d7312018-02-27Karl Gustav Sterneberg  if( err ) {
30e3142001-01-31Per Hedbor  report_test_failure( err, cb, args, st );
92d7312018-02-27Karl Gustav Sterneberg  if( throw_error ) { throw( err ); } }
30e3142001-01-31Per Hedbor  else
92d7312018-02-27Karl Gustav Sterneberg  if( res ) {
30e3142001-01-31Per Hedbor  report_test_failure( sprintf("expected zero, got %O",res), cb, args, st);
92d7312018-02-27Karl Gustav Sterneberg  if( throw_error ) {
2c11482018-03-20Henrik Grubbström (Grubba)  error( sprintf("expected zero, got %O\n", res) );
92d7312018-02-27Karl Gustav Sterneberg  } }
30e3142001-01-31Per Hedbor  else report_test_ok( err, cb, args, st ); }
92d7312018-02-27Karl Gustav Sterneberg private void assert_result_false( mixed res, mixed err, function|string|array cb, array args, int st ) { check_false( res, err, cb, args, st, true ); }
6a6a8c2001-01-30Per Hedbor  function check_is( mixed m ) { return
18a68b2009-09-17Martin Stjernholm  lambda( mixed res, mixed err, function|string|array cb, array args, int st )
6a6a8c2001-01-30Per Hedbor  { if( err )
c4bfff2018-02-27Karl Gustav Sterneberg  report_test_failure( err, cb, args, st );
6a6a8c2001-01-30Per Hedbor  else
c4bfff2018-02-27Karl Gustav Sterneberg  if( res != m ) report_test_failure(sprintf("Got %O, expected %O", res,m), cb,args,st); else report_test_ok( err, cb, args, st );
6a6a8c2001-01-30Per Hedbor  }; }
30e3142001-01-31Per Hedbor mixed pass( mixed arg ) { return arg; }
6a6a8c2001-01-30Per Hedbor function check_equal( mixed m ) { return
92d7312018-02-27Karl Gustav Sterneberg  lambda( mixed res, mixed err, function|string|array cb, array args, int st, bool|void throw_error )
6a6a8c2001-01-30Per Hedbor  {
92d7312018-02-27Karl Gustav Sterneberg  if( err ) {
c4bfff2018-02-27Karl Gustav Sterneberg  report_test_failure( err, cb, args, st );
92d7312018-02-27Karl Gustav Sterneberg  if( throw_error ) { throw( err ); } } else if( !equal( res, m )) {
2c11482018-03-20Henrik Grubbström (Grubba)  string message = sprintf("Got %O, expected %O.\n", res,m);
92d7312018-02-27Karl Gustav Sterneberg  report_test_failure( message, cb, args, st ); if( throw_error ) { error( message ); } } else { report_test_ok( err, cb, args, st ); }
6a6a8c2001-01-30Per Hedbor  }; } function check_not_equal( mixed m ) { return
92d7312018-02-27Karl Gustav Sterneberg  lambda( mixed res, mixed err, function|string|array cb, array args, int st, bool|void throw_error )
6a6a8c2001-01-30Per Hedbor  {
92d7312018-02-27Karl Gustav Sterneberg  if( err ) {
c4bfff2018-02-27Karl Gustav Sterneberg  report_test_failure( err, cb, args, st );
92d7312018-02-27Karl Gustav Sterneberg  if( throw_error ) { throw( err ); } } else if( equal( res, m )) {
2c11482018-03-20Henrik Grubbström (Grubba)  string message = sprintf("Got %O, expected different value.\n", res);
92d7312018-02-27Karl Gustav Sterneberg  report_test_failure( message, cb, args, st ); if( throw_error ) { error( message ); } } else { report_test_ok( err, cb, args, st ); }
6a6a8c2001-01-30Per Hedbor  }; }
2556b92001-01-31Per Hedbor 
18a68b2009-09-17Martin Stjernholm mixed cpp_test_true (string file, int line, function(void:mixed) test_fn,
c4bfff2018-02-27Karl Gustav Sterneberg  string test_text, array test_text_args)
18a68b2009-09-17Martin Stjernholm {
5859dd2009-09-24Martin Stjernholm  return test_really_generic (silent_check_true, test_fn,
c4bfff2018-02-27Karl Gustav Sterneberg  ({file, line, test_text}), test_text_args);
18a68b2009-09-17Martin Stjernholm }
92d7312018-02-27Karl Gustav Sterneberg mixed cpp_assert_true (string file, int line, function(void:mixed) test_fn, string test_text, array test_text_args) { return test_really_generic (silent_check_true, test_fn, ({file, line, test_text}), test_text_args, true); }
18a68b2009-09-17Martin Stjernholm mixed test( function|array f, mixed ... args )
2556b92001-01-31Per Hedbor { return test_generic( 0, f, @args ); }
92d7312018-02-27Karl Gustav Sterneberg mixed assert( function|array f, mixed ... args ) { return assert_generic( 0, f, @args ); }
18a68b2009-09-17Martin Stjernholm mixed test_true( function|array f, mixed ... args )
2556b92001-01-31Per Hedbor { return test_generic( check_true, f, @args ); }
92d7312018-02-27Karl Gustav Sterneberg mixed assert_true( function|array f, mixed ... args ) { return assert_generic( assert_result_true, f, @args ); }
18a68b2009-09-17Martin Stjernholm mixed test_false( function|array f, mixed ... args )
2556b92001-01-31Per Hedbor { return test_generic( check_false, f, @args ); }
92d7312018-02-27Karl Gustav Sterneberg mixed assert_false( function|array f, mixed ... args ) { return assert_generic( assert_result_false, f, @args ); }
18a68b2009-09-17Martin Stjernholm mixed test_error( function|array f, mixed ... args )
2556b92001-01-31Per Hedbor { return test_generic( check_error, f, @args ); }
92d7312018-02-27Karl Gustav Sterneberg mixed assert_error( function|array f, mixed ... args ) { return assert_generic( assert_throws_error, f, @args ); }
18a68b2009-09-17Martin Stjernholm mixed test_equal( mixed what, function|array f, mixed ... args )
2556b92001-01-31Per Hedbor { return test_generic( check_equal( what ), f, @args ); }
92d7312018-02-27Karl Gustav Sterneberg mixed assert_equal( mixed what, function|array f, mixed ... args ) { return assert_generic( check_equal( what ), f, @args ); }
18a68b2009-09-17Martin Stjernholm mixed test_not_equal( mixed what, function|array f, mixed ... args )
2556b92001-01-31Per Hedbor { return test_generic( check_not_equal( what ), f, @args ); }
92d7312018-02-27Karl Gustav Sterneberg mixed assert_not_equal( mixed what, function|array f, mixed ... args ) { return test_generic( check_not_equal( what ), f, @args ); }
7cad992001-02-01Per Hedbor  void run_tests( Configuration c ); void low_run_tests( Configuration c,
c4bfff2018-02-27Karl Gustav Sterneberg  function go_on )
7cad992001-02-01Per Hedbor {
49374b2001-02-05Per Hedbor  mixed err = catch { run_tests( c ); };
b183312009-09-14Martin Stjernholm  if( err ) {
6c313b2012-02-14Martin Stjernholm  write( "################ " + describe_backtrace( err ) );
b183312009-09-14Martin Stjernholm  go_on (++current_test, ++tests_failed); } else go_on (++current_test, tests_failed);
7cad992001-02-01Per Hedbor }