pike.git / bin / test_pike.pike

version» Context lines:

pike.git/bin/test_pike.pike:1:   #! /usr/bin/env pike    - /* $Id: test_pike.pike,v 1.99 2004/04/23 16:38:45 grubba Exp $ */ + /* $Id: test_pike.pike,v 1.100 2007/06/12 08:08:55 grubba Exp $ */      #if !constant(_verify_internals)   #define _verify_internals()   #endif      #if !constant(_dmalloc_set_name)   void _dmalloc_set_name(mixed ... args) {}   #endif      int foo(string opt)
pike.git/bin/test_pike.pike:30:    lambda(string s) {    return sprintf("\\%o", s[0]);    })->feed(test)->drain()/"\n";    foreach(lines; int r; string line) {    werror("%3d: %s\n", r+1, line);    }    werror("\n");    return;   }    + void report_size() + { + #if 0 +  werror("\n"); +  Process.system(sprintf("/usr/proc/bin/pmap %d|tail -1", getpid())); + #endif + } +    array find_testsuites(string dir)   {    array(string) ret=({});    if(array(string) s=get_dir(dir||"."))    {    if(has_value(s,"no_testsuites")) return ret;    foreach(s, string file)    { -  +  string name=combine_path(dir||"",file); +  if(Stdio.is_dir(name)) { +  ret+=find_testsuites(name); +  continue; +  }    switch(file)    {    case "testsuite":    case "module_testsuite":    ret+=({ combine_path(dir||"",file) });    }    } -  -  foreach(s, string file) -  { -  string name=combine_path(dir||"",file); -  if(Stdio.is_dir(name)) -  ret+=find_testsuites(name); +     } -  } +     return ret;   }      array(string) read_tests( string fn ) {    string|array(string) tests = Stdio.read_file( fn );    if(!tests) {    werror("Failed to read test file %O, errno=%d.\n",    fn, errno());    exit(1);    }    -  +  if(has_prefix(tests, "START")) { +  tests = tests[6..]; +  if(!has_suffix(tests, "END\n")) +  werror("%s: Missing end marker.\n", fn); +  else +  tests = tests[..sizeof(tests)-1-4]; +  } +     tests = tests/"\n....\n";    return tests[0..sizeof(tests)-2];   }    -  + mapping(string:int) pushed_warnings = ([]); +    class WarningFlag {    int(0..1) warning;    array(string) warnings = ({});       void compile_warning(string file, int line, string text) { -  +  if (pushed_warnings[text]) return;    warnings += ({ line+": "+text });    warning = 1;    }       void compile_error(string file, int line, string text) {    werror("%s:%d: %s\n", file,line,text);    }   }      //
pike.git/bin/test_pike.pike:373:    if (t) forked += ({ "--trace=" + t });    if (check) forked += ({ "--check=" + check });    if (asmdebug) forked += ({ "--asm=" + asmdebug });    if (mem) forked += ({ "--memory" });    // auto already handled.    if (all_constants()->regression) forked += ({ "--regression" });    // debug port not propagated.    //werror("forked:%O\n", forked);    }    -  add_constant("_verbose", verbose); -  if(verbose) -  write("Begin tests at "+ctime(time())); +  // Move stdout to a higher fd, so that close on exec works. +  // This makes sure the original stdout gets closed even if +  // some subprocess hangs. +  Stdio.File stdout = Stdio.File(); +  Stdio.stdout->dup2(stdout); +  //stdout->assign(Stdio.stdout->_fd->dup()); +  Stdio.stderr->dup2(Stdio.stdout); +  stdout->set_close_on_exec(1);      #ifdef WATCHDOG    int watchdog_time=time();       if(use_watchdog && !forked)    { -  +  object watchdog_tmp;   #ifdef WATCHDOG_PIPE -  object watchdog_tmp=Stdio.File(); -  watchdog_pipe=watchdog_tmp->pipe(Stdio.PROP_IPC); -  watchdog=Process.create_process( -  backtrace()[0][3] + ({ "--watchdog="+getpid() }), -  (["stdin":watchdog_tmp ])); -  destruct(watchdog_tmp); +  watchdog_tmp = Stdio.File(); +  watchdog_pipe = watchdog_tmp->pipe(Stdio.PROP_IPC); +  add_constant("__signal_watchdog",lambda(){});   #endif -  - #ifdef WATCHDOG_SIGNAL +     watchdog=Process.create_process( -  backtrace()[0][3] + ({ "--watchdog="+getpid() }) ); - #endif +  backtrace()[0][3] + ({ "--watchdog="+getpid() }), +  ([ +  "stdin" :watchdog_tmp || Stdio.stdin, +  "stdout":Stdio.stderr, +  "stderr":Stdio.stderr, +  ])); +  if (watchdog_tmp) destruct(watchdog_tmp);    } -  + #endif + #if defined(WATCHDOG_SIGNAL) && defined(WATCHDOG)    add_constant("__signal_watchdog",signal_watchdog); - #else + #else // WATCHDOG_PIPE or !WATCHDOG    add_constant("__signal_watchdog",lambda(){}); - #endif // else WATCHDOG_PIPE + #endif // WATCHDOG_SIGNAL && WATCHDOG    -  +  add_constant("_verbose", verbose); +  if(verbose) +  stdout->write("Begin tests at "+ctime(time())); +     testsuites += Getopt.get_args(argv, 1)[1..]; -  if(!sizeof(testsuites)) -  { -  werror("No tests found. Use --help for more information.\n"); -  exit(1); +  foreach(testsuites; int pos; string ts) { +  if(Stdio.is_dir(ts)) +  testsuites[pos] = ts = combine_path(ts, "testsuite"); +  if(!file_stat(ts)) +  exit(1, "Could not find test %O.\n", ts);    }    -  +  if(!sizeof(testsuites)) +  exit(1, "No tests found. Use --help for more information.\n"); +    #if 1    // Store the name of all constants so that we can see    // if any constant has been leaked from the testsuite.    array const_names = indices(all_constants());   #endif      #if constant(_assembler_debug)    if(asmdebug)    _assembler_debug(asmdebug);   #endif       while(loop--)    {    successes=errors=0;    if (forked) {    foreach(testsuites, string testsuite) {    Stdio.File p = Stdio.File();    Stdio.File p2 = p->pipe(); -  +  if(!p2) { +  werror("Failed to create pipe.\n"); +  if(fail) exit(1); +  errors++; +  continue; +  }    object pid =    Process.create_process(forked + ({ testsuite }),    ([ "stdout":p2 ]));    p2->close();    string raw_results;    string results = lower_case(raw_results = p->read());    int err = pid->wait();    int total = 0;    int failed = 0;    int skip = 0;    if (((sscanf(results, "%*sfailed tests:%d", failed) != 2) +    (sscanf(results, "%*stotal tests:%d", total) != 2) +    (sscanf(results, "%*s(%d tests skipped)", skip) != 2)) == 3) {    // Failed to parse the result totally. -  werror("Failed to parse subresult for testsuite %O (exitcode:%d):\n" -  "%s", testsuite, err, raw_results); +  if (err == -1) { +  werror("Failed to parse subresult for testsuite %O " +  "(died of signal %d).\n" +  "%O", testsuite, pid->last_signal(), raw_results); +  } else { +  werror("Failed to parse subresult for testsuite %O " +  "(exitcode:%d):\n" +  "%O", testsuite, err, raw_results); +  }    errors++;    } else {    werror("Subresult: %d tests, %d failed, %d skipped\n",    total, failed, skip);    errors += failed;    successes += total - failed;    skipped += skip; -  +  werror("Accumulated: %d tests, %d failed, %d skipped\n", +  successes + errors, errors, skipped);    }    if (fail && errors) {    exit(1);    }    }    } else {    testloop:    foreach(testsuites, string testsuite)    {    tests = read_tests( testsuite );       werror("Doing tests in %s (%d tests)\n", testsuite, sizeof(tests));    int qmade, qskipped, qmadep, qskipp;       int testno, testline;    for(e=start;e<sizeof(tests);e++)    {    signal_watchdog();    -  +  if (!((e-start) % 10)) +  report_size(); +     int skip=0, prev_errors = errors;    object o;    mixed a,b;       // Extra consistency checks?    if(check)    {    if(check>0 || (e % -check)==0 )    _verify_internals();    }
pike.git/bin/test_pike.pike:849:    werror(pad_on_error + fname + " failed.\n");    print_code(test);    werror(sprintf("o->a(): %O\n",a));    errors++;    }    else {    successes++;    }    break;    +  case "PUSH_WARNING": +  if (!stringp(a)) { +  werror(pad_on_error + fname + " failed.\n"); +  print_code(test); +  werror(sprintf("o->a(): %O\n", a)); +  } else { +  pushed_warnings[a]++; +  } +  break; +  +  case "POP_WARNING": +  if (!stringp(a)) { +  werror(pad_on_error + fname + " failed.\n"); +  print_code(test); +  werror(sprintf("o->a(): %O\n", a)); +  } else if (pushed_warnings[a]) { +  if (!--pushed_warnings[a]) { +  m_delete(pushed_warnings, a); +  } +  } else { +  werror(pad_on_error + fname + " failed.\n"); +  print_code(test); +  werror(sprintf("o->a(): %O not pushed!\n", a)); +  } +  break; +     case "RUN":    successes++;    break;       case "RUNCT":    if(!a || !arrayp(a) || sizeof(a)!=2 || !intp(a[0]) || !intp(a[1])) {    werror(pad_on_error + fname + " failed to return proper results.\n");    print_code(test);    werror(sprintf("o->a(): %O\n",a));    errors++;
pike.git/bin/test_pike.pike:956:    else if(!qskipp) werror("Made all tests\n");    else if(!qmadep) werror("Skipped all tests\n");    else if(qmade) werror(" Made %d test%s.\n", qmade, qmade==1?"":"s");    else if(qskipped) werror(" Skipped %d test%s.\n", qskipped, qskipped==1?"":"s");    }    else {    werror("\n");    }    }    } +  report_size();    if(mem)    {    int total;    tests=0;    gc();    mapping tmp=_memory_usage();    werror(sprintf("%-10s: %6s %10s\n","Category","num","bytes"));    foreach(sort(indices(tmp)),string foo)    {    if(sscanf(foo,"%s_bytes",foo))
pike.git/bin/test_pike.pike:980:    tmp[foo+"_bytes"]));    total+=tmp[foo+"_bytes"];    }    }    werror( "%-10s: %6s %10d\n",    "Total", "", total );    }    }    if(errors || verbose>1)    { -  write("Failed tests: "+errors+".\n"); +  stdout->write("Failed tests: "+errors+".\n");    }    -  write("Total tests: %d (%d tests skipped)\n",successes+errors,skipped); +  stdout->write(sprintf("Total tests: %d (%d tests skipped)\n", +  successes+errors, skipped));    if(verbose) -  write("Finished tests at "+ctime(time())); +  stdout->write("Finished tests at "+ctime(time()));      #if 1    if(verbose && sizeof(all_constants())!=sizeof(const_names)) {    multiset const_names = (multiset)const_names;    foreach(indices(all_constants()), string const)    if( !const_names[const] )    werror("Leaked constant %O\n", const);    }   #endif   
pike.git/bin/test_pike.pike:1019:    }   #endif       return errors;   }      constant doc = #"   Usage: test_pike [args] [testfiles]      --no-watchdog Watchdog will not be used. - --watchdog=pid Run only the watchdog and monitor the process with the given -  pid. + --watchdog=pid Run only the watchdog and monitor the process with +  the given pid.   -h, --help Prints this message.   -v[level], - --verbose[=level] Select the level of verbosity. Every verbose level includes -  the printouts from the levels below. + --verbose[=level] Select the level of verbosity. Every verbosity level +  includes the printouts from the levels below.    0 No extra printouts.    1 Some additional information printed out after every    finished block of tests. -  2 Some extra information about test that will or won't be +  2 Some extra information about tests that will or won't be    run.    3 Every test is printed out. -  4 Time spent in individual tests are printed out. +  4 Time spent in individual tests is printed out.    10 The actual Pike code compiled, including wrappers, is    printed.   -p, --prompt The user will be asked before every test is run. - -sX, --start-test=X Where in the testsuite testing should start, e.g. ignores X + -sX, --start-test=X Where in the testsuite testing should start, i.e. ignores X    tests in every testsuite.   -eX, --end-after=X How many tests should be run.   -f, --fail If set, the test program exits on first failure.   -F, --forking If set, each testsuite will run in a separate process.   -lX, --loop=X The number of times the testsuite should be run. Default is    1.   -tX, --trace=X Run tests with trace level X.   -c[X], --check[=X] The level of extra Pike consistency checks performed.    1 _verify_internals is run before every test.    2 _verify_internals is run after every compilation.    3 _verify_internals is run after every test.    4 An extra gc and _verify_internals is run before    every test.    X<0 For values below zero, _verify_internals will be run    before every n:th test, where n=abs(X).   -m, --mem, --memory Print out memory allocations after the tests. - -a, --auto[=dir] Let the test program find the testsuits self. + -a, --auto[=dir] Let the test program find the testsuites automatically.   -T, --notty Format output for non-tty.   -d, --debug Opens a debug port.   ";