| Index: gm/gmmain.cpp
|
| ===================================================================
|
| --- gm/gmmain.cpp (revision 8514)
|
| +++ gm/gmmain.cpp (working copy)
|
| @@ -34,7 +34,6 @@
|
| #include "SkRefCnt.h"
|
| #include "SkStream.h"
|
| #include "SkTArray.h"
|
| -#include "SkTDict.h"
|
| #include "SkTileGridPicture.h"
|
| #include "SamplePipeControllers.h"
|
|
|
| @@ -86,6 +85,14 @@
|
|
|
| using namespace skiagm;
|
|
|
| +struct FailRec {
|
| + SkString fName;
|
| + bool fIsPixelError;
|
| +
|
| + FailRec() : fIsPixelError(false) {}
|
| + FailRec(const SkString& name) : fName(name), fIsPixelError(false) {}
|
| +};
|
| +
|
| class Iter {
|
| public:
|
| Iter() {
|
| @@ -176,9 +183,12 @@
|
|
|
| class GMMain {
|
| public:
|
| - GMMain() : fUseFileHierarchy(false), fMismatchPath(NULL), fTestsRun(0),
|
| - fRenderModesEncountered(1) {
|
| + GMMain() {
|
| + // Set default values of member variables, which tool_main()
|
| + // may override.
|
| + fUseFileHierarchy = false;
|
| fIgnorableErrorCombination.add(kMissingExpectations_ErrorType);
|
| + fMismatchPath = NULL;
|
| }
|
|
|
| SkString make_name(const char shortName[], const char configName[]) {
|
| @@ -232,103 +242,34 @@
|
| }
|
|
|
| /**
|
| - * Add all render modes encountered thus far to the "modes" array.
|
| + * Records the errors encountered in fFailedTests, except for any error
|
| + * types we want to ignore.
|
| */
|
| - void GetRenderModesEncountered(SkTArray<SkString> &modes) {
|
| - SkTDict<int>::Iter iter(this->fRenderModesEncountered);
|
| - const char* mode;
|
| - while ((mode = iter.next(NULL)) != NULL) {
|
| - SkString modeAsString = SkString(mode);
|
| - // TODO(epoger): It seems a bit silly that all of these modes were
|
| - // recorded with a leading "-" which we have to remove here
|
| - // (except for mode "", which means plain old original mode).
|
| - // But that's how renderModeDescriptor has been passed into
|
| - // compare_test_results_to_reference_bitmap() historically,
|
| - // and changing that now may affect other parts of our code.
|
| - if (modeAsString.startsWith("-")) {
|
| - modeAsString.remove(0, 1);
|
| - modes.push_back(modeAsString);
|
| - }
|
| - }
|
| - }
|
| -
|
| - /**
|
| - * Records the results of this test in fTestsRun and fFailedTests.
|
| - *
|
| - * We even record successes, and errors that we regard as
|
| - * "ignorable"; we can filter them out later.
|
| - */
|
| - void RecordTestResults(const ErrorCombination& errorCombination, const SkString& name,
|
| - const char renderModeDescriptor []) {
|
| - // Things to do regardless of errorCombination.
|
| - fTestsRun++;
|
| - int renderModeCount = 0;
|
| - this->fRenderModesEncountered.find(renderModeDescriptor, &renderModeCount);
|
| - renderModeCount++;
|
| - this->fRenderModesEncountered.set(renderModeDescriptor, renderModeCount);
|
| -
|
| + void RecordError(const ErrorCombination& errorCombination, const SkString& name,
|
| + const char renderModeDescriptor []) {
|
| + // The common case: no error means nothing to record.
|
| if (errorCombination.isEmpty()) {
|
| return;
|
| }
|
|
|
| - // Things to do only if there is some error condition.
|
| - SkString fullName = make_name(name.c_str(), renderModeDescriptor);
|
| - for (int typeInt = 0; typeInt <= kLast_ErrorType; typeInt++) {
|
| - ErrorType type = static_cast<ErrorType>(typeInt);
|
| - if (errorCombination.includes(type)) {
|
| - fFailedTests[type].push_back(fullName);
|
| - }
|
| + // If only certain error type(s) were reported, we know we can ignore them.
|
| + if (errorCombination.minus(fIgnorableErrorCombination).isEmpty()) {
|
| + return;
|
| }
|
| - }
|
|
|
| - /**
|
| - * Return the number of significant (non-ignorable) errors we have
|
| - * encountered so far.
|
| - */
|
| - int NumSignificantErrors() {
|
| - int significantErrors = 0;
|
| - for (int typeInt = 0; typeInt <= kLast_ErrorType; typeInt++) {
|
| - ErrorType type = static_cast<ErrorType>(typeInt);
|
| - if (!fIgnorableErrorCombination.includes(type)) {
|
| - significantErrors += fFailedTests[type].count();
|
| - }
|
| - }
|
| - return significantErrors;
|
| + FailRec& rec = fFailedTests.push_back(make_name(name.c_str(), renderModeDescriptor));
|
| + rec.fIsPixelError = errorCombination.includes(kImageMismatch_ErrorType);
|
| }
|
|
|
| - /**
|
| - * List contents of fFailedTests to stdout.
|
| - */
|
| + // List contents of fFailedTests via SkDebug.
|
| void ListErrors() {
|
| - // First, print a single summary line.
|
| - SkString summary;
|
| - summary.appendf("Ran %d tests:", fTestsRun);
|
| - for (int typeInt = 0; typeInt <= kLast_ErrorType; typeInt++) {
|
| - ErrorType type = static_cast<ErrorType>(typeInt);
|
| - summary.appendf(" %s=%d", getErrorTypeName(type), fFailedTests[type].count());
|
| - }
|
| - gm_fprintf(stdout, "%s\n", summary.c_str());
|
| -
|
| - // Now, for each failure type, list the tests that failed that way.
|
| - for (int typeInt = 0; typeInt <= kLast_ErrorType; typeInt++) {
|
| - SkString line;
|
| - ErrorType type = static_cast<ErrorType>(typeInt);
|
| - if (fIgnorableErrorCombination.includes(type)) {
|
| - line.append("[ ] ");
|
| + for (int i = 0; i < fFailedTests.count(); ++i) {
|
| + if (fFailedTests[i].fIsPixelError) {
|
| + gm_fprintf(stderr, "\t\t%s pixel_error\n", fFailedTests[i].fName.c_str());
|
| } else {
|
| - line.append("[*] ");
|
| + gm_fprintf(stderr, "\t\t%s\n", fFailedTests[i].fName.c_str());
|
| }
|
| -
|
| - SkTArray<SkString> *failedTestsOfThisType = &fFailedTests[type];
|
| - int count = failedTestsOfThisType->count();
|
| - line.appendf("%d %s:", count, getErrorTypeName(type));
|
| - for (int i = 0; i < count; ++i) {
|
| - line.append(" ");
|
| - line.append((*failedTestsOfThisType)[i]);
|
| - }
|
| - gm_fprintf(stdout, "%s\n", line.c_str());
|
| }
|
| - gm_fprintf(stdout, "(results marked with [*] will cause nonzero return value)\n");
|
| }
|
|
|
| static bool write_document(const SkString& path,
|
| @@ -601,16 +542,7 @@
|
| } else {
|
| gm_fprintf(stderr, "FAILED to write %s\n", path.c_str());
|
| ErrorCombination errors(kWritingReferenceImage_ErrorType);
|
| - // TODO(epoger): Don't call RecordTestResults() here...
|
| - // Instead, we should make sure to call RecordTestResults
|
| - // exactly ONCE per test. (Otherwise, gmmain.fTestsRun
|
| - // will be incremented twice for this test: once in
|
| - // compare_test_results_to_stored_expectations() before
|
| - // that method calls this one, and again here.)
|
| - //
|
| - // When we make that change, we should probably add a
|
| - // WritingReferenceImage test to the gm self-tests.)
|
| - RecordTestResults(errors, name, renderModeDescriptor);
|
| + RecordError(errors, name, renderModeDescriptor);
|
| return errors;
|
| }
|
| }
|
| @@ -722,7 +654,7 @@
|
| report_bitmap_diffs(*expectedBitmapPtr, actualBitmap, completeName);
|
| }
|
| }
|
| - RecordTestResults(errors, baseNameString, renderModeDescriptor);
|
| + RecordError(errors, baseNameString, renderModeDescriptor);
|
|
|
| if (addToJsonSummary) {
|
| add_actual_results_to_json_summary(completeName, actualChecksum, errors,
|
| @@ -838,7 +770,6 @@
|
| add_actual_results_to_json_summary(name.c_str(), actualChecksum,
|
| ErrorCombination(kMissingExpectations_ErrorType),
|
| false);
|
| - RecordTestResults(ErrorCombination(kMissingExpectations_ErrorType), name, "");
|
| }
|
|
|
| // TODO: Consider moving this into compare_to_expectations(),
|
| @@ -866,13 +797,6 @@
|
| GM* gm, const ConfigData& gRec, const char renderModeDescriptor [],
|
| SkBitmap& actualBitmap, const SkBitmap* referenceBitmap) {
|
|
|
| - // TODO(epoger): This method is run to compare results across
|
| - // different rendering modes (as opposed to
|
| - // compare_test_results_to_stored_expectations(), which
|
| - // compares results against expectations stored on disk). If
|
| - // we would like the GenerateGMs step to distinguish between
|
| - // those two types of mismatches, we should report image
|
| - // mismatches in here with a different ErrorType.
|
| SkASSERT(referenceBitmap);
|
| SkString name = make_name(gm->shortName(), gRec.fName);
|
| Expectations expectations(*referenceBitmap);
|
| @@ -986,8 +910,6 @@
|
| // ('image-surface gm test is failing in "deferred" mode,
|
| // and gm is not reporting the failure')
|
| if (errors.isEmpty()) {
|
| - // TODO(epoger): Report this as a new ErrorType,
|
| - // something like kImageGeneration_ErrorType?
|
| return kEmpty_ErrorCombination;
|
| }
|
| return compare_test_results_to_reference_bitmap(
|
| @@ -1061,10 +983,8 @@
|
|
|
| const char* fMismatchPath;
|
|
|
| - // collection of tests that have failed with each ErrorType
|
| - SkTArray<SkString> fFailedTests[kLast_ErrorType+1];
|
| - int fTestsRun;
|
| - SkTDict<int> fRenderModesEncountered;
|
| + // information about all failed tests we have encountered so far
|
| + SkTArray<FailRec> fFailedTests;
|
|
|
| // Where to read expectations (expected image checksums, etc.) from.
|
| // If unset, we don't do comparisons.
|
| @@ -1372,9 +1292,7 @@
|
| ErrorCombination errorsForAllModes;
|
| uint32_t gmFlags = gm->getFlags();
|
|
|
| - // TODO(epoger): We should start recording any per-GM skipped
|
| - // modes (i.e. those we skipped due to gmFlags) with a new
|
| - // ErrorType, perhaps named kIntentionallySkipped_ErrorType.
|
| + // run the picture centric GM steps
|
| if (!(gmFlags & GM::kSkipPicture_Flag)) {
|
|
|
| ErrorCombination pictErrors;
|
| @@ -1472,45 +1390,6 @@
|
| return errorsForAllModes;
|
| }
|
|
|
| -/**
|
| - * Return a list of all entries in an array of strings as a single string
|
| - * of this form:
|
| - * "item1", "item2", "item3"
|
| - */
|
| -SkString list_all(const SkTArray<SkString> &stringArray);
|
| -SkString list_all(const SkTArray<SkString> &stringArray) {
|
| - SkString total;
|
| - for (int i = 0; i < stringArray.count(); i++) {
|
| - if (i > 0) {
|
| - total.append(", ");
|
| - }
|
| - total.append("\"");
|
| - total.append(stringArray[i]);
|
| - total.append("\"");
|
| - }
|
| - return total;
|
| -}
|
| -
|
| -/**
|
| - * Return a list of configuration names, as a single string of this form:
|
| - * "item1", "item2", "item3"
|
| - *
|
| - * @param configs configurations, as a list of indices into gRec
|
| - */
|
| -SkString list_all_config_names(const SkTDArray<size_t> &configs);
|
| -SkString list_all_config_names(const SkTDArray<size_t> &configs) {
|
| - SkString total;
|
| - for (int i = 0; i < configs.count(); i++) {
|
| - if (i > 0) {
|
| - total.append(", ");
|
| - }
|
| - total.append("\"");
|
| - total.append(gRec[configs[i]].fName);
|
| - total.append("\"");
|
| - }
|
| - return total;
|
| -}
|
| -
|
| int tool_main(int argc, char** argv);
|
| int tool_main(int argc, char** argv) {
|
|
|
| @@ -1692,7 +1571,12 @@
|
| moduloRemainder = -1;
|
| }
|
|
|
| - int gmsRun = 0;
|
| + // Accumulate success of all tests.
|
| + int testsRun = 0;
|
| + int testsPassed = 0;
|
| + int testsFailed = 0;
|
| + int testsMissingReferenceImages = 0;
|
| +
|
| int gmIndex = -1;
|
| SkString moduloStr;
|
|
|
| @@ -1732,44 +1616,42 @@
|
| continue;
|
| }
|
|
|
| - gmsRun++;
|
| SkISize size = gm->getISize();
|
| gm_fprintf(stdout, "%sdrawing... %s [%d %d]\n", moduloStr.c_str(), shortName,
|
| size.width(), size.height());
|
|
|
| - run_multiple_configs(gmmain, gm, configs, grFactory);
|
| + ErrorCombination testErrors;
|
| + testErrors.add(run_multiple_configs(gmmain, gm, configs, grFactory));
|
|
|
| SkBitmap comparisonBitmap;
|
| const ConfigData compareConfig =
|
| { SkBitmap::kARGB_8888_Config, kRaster_Backend, kDontCare_GLContextType, 0, kRW_ConfigFlag, "comparison", false };
|
| - gmmain.generate_image(gm, compareConfig, NULL, &comparisonBitmap, false);
|
| + testErrors.add(gmmain.generate_image(gm, compareConfig, NULL, &comparisonBitmap, false));
|
|
|
| // TODO(epoger): only run this if gmmain.generate_image() succeeded?
|
| // Otherwise, what are we comparing against?
|
| - run_multiple_modes(gmmain, gm, compareConfig, comparisonBitmap, tileGridReplayScales);
|
| + testErrors.add(run_multiple_modes(gmmain, gm, compareConfig, comparisonBitmap,
|
| + tileGridReplayScales));
|
|
|
| + // Update overall results.
|
| + // We only tabulate the particular error types that we currently
|
| + // care about (e.g., missing reference images). Later on, if we
|
| + // want to also tabulate other error types, we can do so.
|
| + testsRun++;
|
| + if (!gmmain.fExpectationsSource.get() ||
|
| + (testErrors.includes(kMissingExpectations_ErrorType))) {
|
| + testsMissingReferenceImages++;
|
| + }
|
| + if (testErrors.minus(gmmain.fIgnorableErrorCombination).isEmpty()) {
|
| + testsPassed++;
|
| + } else {
|
| + testsFailed++;
|
| + }
|
| +
|
| SkDELETE(gm);
|
| }
|
| -
|
| - SkTArray<SkString> modes;
|
| - gmmain.GetRenderModesEncountered(modes);
|
| -
|
| - // Output summary to stdout.
|
| - gm_fprintf(stdout, "Ran %d GMs\n", gmsRun);
|
| - gm_fprintf(stdout, "... over %2d configs [%s]\n", configs.count(),
|
| - list_all_config_names(configs).c_str());
|
| - gm_fprintf(stdout, "... and %2d modes [%s]\n", modes.count(), list_all(modes).c_str());
|
| - gm_fprintf(stdout, "... so there should be a total of %d tests.\n",
|
| - gmsRun * (configs.count() + modes.count()));
|
| -
|
| - // TODO(epoger): Ultimately, we should signal an error if the
|
| - // expected total number of tests (displayed above) does not match
|
| - // gmmain.fTestsRun. But for now, there are cases where those
|
| - // numbers won't match: specifically, if some configs/modes are
|
| - // skipped on a per-GM basis (due to gm->getFlags() for a specific
|
| - // GM). Later on, we should record tests like that using some new
|
| - // ErrorType, like kIntentionallySkipped_ErrorType. Then we could
|
| - // signal an error if the totals didn't match up.
|
| + gm_fprintf(stdout, "Ran %d tests: %d passed, %d failed, %d missing reference images\n",
|
| + testsRun, testsPassed, testsFailed, testsMissingReferenceImages);
|
| gmmain.ListErrors();
|
|
|
| if (FLAGS_writeJsonSummaryPath.count() == 1) {
|
| @@ -1809,7 +1691,7 @@
|
| #endif
|
| SkGraphics::Term();
|
|
|
| - return (0 == gmmain.NumSignificantErrors()) ? 0 : -1;
|
| + return (0 == testsFailed) ? 0 : -1;
|
| }
|
|
|
| void GMMain::installFilter(SkCanvas* canvas) {
|
|
|