Ticket #156: patch

File patch, 10.6 KB (added by Richard Boulton, 17 years ago)

Implementation of this suggestion

  • tests/harness/testsuite.h

     
    7474//  needless generation of diagnostic output in cases when it's expensive.
    7575extern bool verbose;
    7676
     77/// A global flag which a test should set if it knows that it's going to fail
     78/// in a particular situation.  Known failures will not cause the test suite to
     79/// fail, but will be listed at the end of the test run.
     80extern bool global_known_failure;
     81
    7782/// The exception type we were expecting in TEST_EXCEPTION.
    7883//  Used to detect if such an exception was mishandled by a the
    7984//  compiler/runtime.
     
    97102            /// The number of tests which failed.
    98103            unsigned int failed;
    99104
    100             /// The number of tests which were skipped
     105            /// The number of tests which were skipped.
    101106            unsigned int skipped;
     107
     108            /// The number of known failures which occurred.
     109            unsigned int known_failures;
     110
     111            /// The number of tests marked as known failures which failed to fail.
     112            unsigned int known_failures_passed;
    102113        };
    103114
    104115        /** Add a test-specific command line option.
     
    154165        test_driver(const test_driver &);
    155166        test_driver & operator = (const test_driver &);
    156167
    157         typedef enum { PASS = 1, FAIL = 0, SKIP = -1 } test_result;
     168        typedef enum { KNOWN_FAIL_PASSED=3, KNOWN_FAIL=2, PASS = 1, FAIL = 0, SKIP = -1 } test_result;
    158169
    159170        static std::map<int, std::string *> short_opts;
    160171
     
    250261        "Expected `"STRINGIZE(a)"' and `"STRINGIZE(b)"' not to be equal:" \
    251262        " were " << (a) << " and " << (b))
    252263
     264/// Mark a test as known-to-fail.  This is intended to be used temporarily to /
     265/// mark tests for known bugs before the bugs are fixed.  The test failure will
     266/// be displayed as a known failure, and not cause the test suite to return a
     267/// failure code.  It should be called from inside the testcase.  If the case
     268/// is only known to fail in certain situations (for example, only for some
     269/// backends), the macro can be called only in those situations.
     270#define KNOWN_FAILURE do { global_known_failure = 1; } while (0)
     271
    253272#endif // OM_HGUARD_TESTSUITE_H
  • tests/harness/testsuite.cc

     
    6464/// The global verbose flag.
    6565bool verbose;
    6666
     67/// A global flag which a test should set if it knows that it's going to fail
     68/// in a particular situation.  Known failures will not cause the test suite to
     69/// fail, but will be listed at the end of the test run.
     70bool global_known_failure;
     71
    6772#ifdef HAVE_VALGRIND
    6873static int vg_log_fd = -1;
    6974#endif
     
    7883om_ostringstream tout;
    7984
    8085int test_driver::runs = 0;
    81 test_driver::result test_driver::total = {0, 0, 0};
     86test_driver::result test_driver::total = {0, 0, 0, 0, 0};
    8287string test_driver::argv0;
    8388string test_driver::opt_help;
    8489map<int, string *> test_driver::short_opts;
     
    198203//  If this test driver is used for anything other than
    199204//  Xapian tests, then this ought to be provided by
    200205//  the client, really.
    201 //  return: test_driver::PASS, test_driver::FAIL, or test_driver::SKIP
     206//  return: test_driver::PASS, test_driver::FAIL, test_driver::SKIP,
     207//  test_driver::KNOWN_FAIL or test_driver::KNOWN_FAIL_PASSED
    202208test_driver::test_result
    203209test_driver::runtest(const test_desc *test)
    204210{
     
    339345                    if (s[s.size() - 1] != '\n') out << endl;
    340346                    tout.str("");
    341347                }
    342                 out << " " << col_red << "FAILED" << col_reset;
    343                 return FAIL;
     348                if (global_known_failure) {
     349                    out << " " << col_yellow << "KNOWN FAILURE" << col_reset;
     350                    return KNOWN_FAIL;
     351                } else {
     352                    out << " " << col_red << "FAILED" << col_reset;
     353                    return FAIL;
     354                }
    344355            } catch (const TestSkip &) {
    345356                string s = tout.str();
    346357                if (!s.empty()) {
     
    362373                    if (s[s.size() - 1] != '\n') out << endl;
    363374                    tout.str("");
    364375                }
    365                 out << " " << col_red << errclass << col_reset;
     376                if (global_known_failure) {
     377                    out << " " << col_yellow << "KNOWN FAILURE: " << errclass << col_reset << endl;
     378                } else {
     379                    out << " " << col_red << errclass << col_reset;
     380                }
    366381                if (verbose) {
    367382                    out << err.get_type() << " exception: " << err.get_msg();
    368383                    if (!err.get_context().empty())
     
    371386                        out << " (" << err.get_error_string() << ")";
    372387                    out << endl;
    373388                }
     389                if (global_known_failure) {
     390                    return KNOWN_FAIL;
     391                }
    374392                return FAIL;
    375393            } catch (const string & msg) {
    376394                string s = tout.str();
     
    379397                    if (s[s.size() - 1] != '\n') out << endl;
    380398                    tout.str("");
    381399                }
    382                 out << " " << col_red << "EXCEPTION: ";
     400                if (global_known_failure) {
     401                    out << " " << col_yellow << "KNOWN FAILURE: EXCEPTION: " << col_reset;
     402                } else {
     403                    out << " " << col_red << "EXCEPTION: ";
     404                }
    383405                size_t cutoff = min(size_t(40), msg.size());
    384406                cutoff = find(msg.begin(), msg.begin() + cutoff, '\n') - msg.begin();
    385407                if (cutoff == msg.size()) out << msg; else out << msg.substr(0, cutoff) << "...";
     
    387409                if (verbose && cutoff != msg.size()) {
    388410                    out << msg << endl;
    389411                }
     412                if (global_known_failure) {
     413                    return KNOWN_FAIL;
     414                }
    390415                return FAIL;
    391416            } catch (...) {
    392417                string s = tout.str();
     
    395420                    if (s[s.size() - 1] != '\n') out << endl;
    396421                    tout.str("");
    397422                }
    398                 out << " " << col_red << "UNKNOWN EXCEPTION" << col_reset;
    399                 return FAIL;
     423                if (global_known_failure) {
     424                    out << " " << col_yellow << "KNOWN FAILURE: UNKNOWN EXCEPTION" << col_reset;
     425                    return KNOWN_FAIL;
     426                } else {
     427                    out << " " << col_red << "UNKNOWN EXCEPTION" << col_reset;
     428                    return FAIL;
     429                }
    400430            }
    401431        } else {
    402432            // caught signal
     
    418448                case SIGSTKFLT: signame = "SIGSTKFLT"; break;
    419449#endif
    420450            }
    421             out << " " << col_red << signame << col_reset;
    422             return FAIL;
     451            if (global_known_failure) {
     452                out << " " << col_yellow << "KNOWN FAILURE: " << signame << col_reset;
     453                return KNOWN_FAIL;
     454            } else {
     455                out << " " << col_red << signame << col_reset;
     456                return FAIL;
     457            }
    423458        }
     459        if (global_known_failure) {
     460            out << col_red << " KNOWN FAILURE PASSED" << col_reset;
     461            return KNOWN_FAIL_PASSED;
     462        }
    424463        return PASS;
    425464    }
    426465}
     
    446485    set<string> m(b, e);
    447486    bool check_name = !m.empty();
    448487
    449     test_driver::result res = {0, 0, 0};
     488    test_driver::result res = {0, 0, 0, 0, 0};
    450489
    451490    for (const test_desc *test = tests; test->name; test++) {
    452491        bool do_this_test = !check_name;
     
    466505        if (do_this_test) {
    467506            out << "Running test: " << test->name << "...";
    468507            out.flush();
     508            global_known_failure = 0;
    469509            switch (runtest(test)) {
    470510                case PASS:
    471511                    ++res.succeeded;
     
    475515                        out << "\r                                                                               \r";
    476516                    }
    477517                    break;
     518                case KNOWN_FAIL:
     519                    ++res.known_failures;
     520                    out << endl;
     521                    break;
    478522                case FAIL:
    479523                    ++res.failed;
    480524                    out << endl;
     
    483527                        return res;
    484528                    }
    485529                    break;
     530                case KNOWN_FAIL_PASSED:
     531                    ++res.known_failures_passed;
     532                    out << endl;
     533                    if (abort_on_error) {
     534                        out << "Test passed, but marked as a known failure - aborting further tests." << endl;
     535                        return res;
     536                    }
     537                    break;
    486538                case SKIP:
    487539                    ++res.skipped;
    488540                    out << endl;
     
    509561    if (r.succeeded != 0 || r.failed != 0) {
    510562        cout << argv0 << " " << desc << ": ";
    511563
    512         if (r.failed == 0)
     564        if (r.failed == 0 && r.known_failures_passed == 0)
    513565            cout << "All ";
    514566
    515567        cout << col_green << r.succeeded << col_reset << " tests passed";
     
    517569        if (r.failed != 0)
    518570            cout << ", " << col_red << r.failed << col_reset << " failed";
    519571
     572        if (r.known_failures_passed != 0)
     573            cout << ", " << col_red << r.known_failures_passed << col_reset << " known failures passed";
     574
     575        if (r.known_failures != 0)
     576            cout << ", " << col_yellow << r.known_failures << col_reset << " known failures";
     577
    520578        if (r.skipped) {
    521579            cout << ", " << col_yellow << r.skipped << col_reset
    522580                 << " skipped." << endl;
     
    655713    total.succeeded += myresult.succeeded;
    656714    total.failed += myresult.failed;
    657715    total.skipped += myresult.skipped;
     716    total.known_failures += myresult.known_failures;
     717    total.known_failures_passed += myresult.known_failures_passed;
    658718
    659     return bool(myresult.failed); // if 0, then everything passed
     719    return bool(myresult.failed || myresult.known_failures_passed); // if 0, then everything passed
    660720}
    661721
    662722bool
  • tests/queryparsertest.cc

     
    10621062// Test NumberValueRangeProcessors with actual data..
    10631063static bool test_qp_value_range3()
    10641064{
     1065    // This test currently fails because the numeric range stuff doesn't yet
     1066    // marshall the numbers into a representation which sorts in string order
     1067    // corrently.
     1068    KNOWN_FAILURE;
     1069
    10651070    Xapian::WritableDatabase db(Xapian::InMemory::open());
    10661071    int low = 0;  // FIXME - should it work with negative numbers?
    10671072                  // If so, test it with some by setting low to -10
    1068     int high = 9; // Currently the test passes if high is 9, but not if it is 10.
     1073    int high = 10;
    10691074
    10701075    for (int i = low; i <= high; ++i) {
    10711076        Xapian::Document doc;
  • HACKING

     
    856856   changes stop it working as intended.
    857857 * If you've fixed a bug, make sure there's a regression test which
    858858   fails on the existing code and succeeds after your changes.
     859 * If you're adding a new testcase to exhibit an existing bug, and not checking
     860   a fix in at the same time, mark the testcase as a known failure (by calling
     861   the macro "KNOWN_FAILURE" somewhere in your testcase), so that the build
     862   continues to succeed.  This allows the automated build systems to continue
     863   to work, whilst displaying the error to developers.  Fixing the bug is then
     864   a priority - we can't generally make a release while there are known
     865   failures.  Note that failures which are due to valgrind finding memory
     866   errors are not affected by this macro, because this would cause the
     867   testsuite to fail for users without valgrind.  Also, test failures which are
     868   only shown by valgrind won't cause problems for the automated builds, which
     869   don't currently use valgrind.
    859870 * Make sure all existing tests continue to pass.
    860871
    861872If you don't know how to write tests using the Xapian test rig, then