Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(13)

Side by Side Diff: gm/gmmain.cpp

Issue 12851022: gm: display summary of all results by ErrorType (Closed) Base URL: http://skia.googlecode.com/svn/trunk/
Patch Set: split_summary_line Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 /* 1 /*
2 * Copyright 2011 Google Inc. 2 * Copyright 2011 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 /* 8 /*
9 * Code for the "gm" (Golden Master) rendering comparison tool. 9 * Code for the "gm" (Golden Master) rendering comparison tool.
10 * 10 *
(...skipping 16 matching lines...) Expand all
27 #include "SkDrawFilter.h" 27 #include "SkDrawFilter.h"
28 #include "SkGPipe.h" 28 #include "SkGPipe.h"
29 #include "SkGraphics.h" 29 #include "SkGraphics.h"
30 #include "SkImageDecoder.h" 30 #include "SkImageDecoder.h"
31 #include "SkImageEncoder.h" 31 #include "SkImageEncoder.h"
32 #include "SkOSFile.h" 32 #include "SkOSFile.h"
33 #include "SkPicture.h" 33 #include "SkPicture.h"
34 #include "SkRefCnt.h" 34 #include "SkRefCnt.h"
35 #include "SkStream.h" 35 #include "SkStream.h"
36 #include "SkTArray.h" 36 #include "SkTArray.h"
37 #include "SkTDict.h"
37 #include "SkTileGridPicture.h" 38 #include "SkTileGridPicture.h"
38 #include "SamplePipeControllers.h" 39 #include "SamplePipeControllers.h"
39 40
40 #ifdef SK_BUILD_FOR_WIN 41 #ifdef SK_BUILD_FOR_WIN
41 // json includes xlocale which generates warning 4530 because we're compilin g without 42 // json includes xlocale which generates warning 4530 because we're compilin g without
42 // exceptions; see https://code.google.com/p/skia/issues/detail?id=1067 43 // exceptions; see https://code.google.com/p/skia/issues/detail?id=1067
43 #pragma warning(push) 44 #pragma warning(push)
44 #pragma warning(disable : 4530) 45 #pragma warning(disable : 4530)
45 #endif 46 #endif
46 #include "json/value.h" 47 #include "json/value.h"
(...skipping 10 matching lines...) Expand all
57 static int gGpuCacheSizeBytes; 58 static int gGpuCacheSizeBytes;
58 static int gGpuCacheSizeCount; 59 static int gGpuCacheSizeCount;
59 #else 60 #else
60 class GrContextFactory; 61 class GrContextFactory;
61 class GrContext; 62 class GrContext;
62 class GrRenderTarget; 63 class GrRenderTarget;
63 typedef int GLContextType; 64 typedef int GLContextType;
64 #endif 65 #endif
65 66
66 extern bool gSkSuppressFontCachePurgeSpew; 67 extern bool gSkSuppressFontCachePurgeSpew;
68 const static int kAnyIntValue = 1; // when it doesn't matter what int value, jus t SOMETHING
borenet 2013/04/03 12:46:48 What if we counted the number of times we encounte
epoger 2013/04/03 14:28:25 Done. Note that this now takes twice as long, sin
67 69
68 #ifdef SK_SUPPORT_PDF 70 #ifdef SK_SUPPORT_PDF
69 #include "SkPDFDevice.h" 71 #include "SkPDFDevice.h"
70 #include "SkPDFDocument.h" 72 #include "SkPDFDocument.h"
71 #endif 73 #endif
72 74
73 // Until we resolve http://code.google.com/p/skia/issues/detail?id=455 , 75 // Until we resolve http://code.google.com/p/skia/issues/detail?id=455 ,
74 // stop writing out XPS-format image baselines in gm. 76 // stop writing out XPS-format image baselines in gm.
75 #undef SK_SUPPORT_XPS 77 #undef SK_SUPPORT_XPS
76 #ifdef SK_SUPPORT_XPS 78 #ifdef SK_SUPPORT_XPS
77 #include "SkXPSDevice.h" 79 #include "SkXPSDevice.h"
78 #endif 80 #endif
79 81
80 #ifdef SK_BUILD_FOR_MAC 82 #ifdef SK_BUILD_FOR_MAC
81 #include "SkCGUtils.h" 83 #include "SkCGUtils.h"
82 #define CAN_IMAGE_PDF 1 84 #define CAN_IMAGE_PDF 1
83 #else 85 #else
84 #define CAN_IMAGE_PDF 0 86 #define CAN_IMAGE_PDF 0
85 #endif 87 #endif
86 88
87 using namespace skiagm; 89 using namespace skiagm;
88 90
89 struct FailRec {
90 SkString fName;
91 bool fIsPixelError;
92
93 FailRec() : fIsPixelError(false) {}
94 FailRec(const SkString& name) : fName(name), fIsPixelError(false) {}
95 };
96
97 class Iter { 91 class Iter {
98 public: 92 public:
99 Iter() { 93 Iter() {
100 this->reset(); 94 this->reset();
101 } 95 }
102 96
103 void reset() { 97 void reset() {
104 fReg = GMRegistry::Head(); 98 fReg = GMRegistry::Head();
105 } 99 }
106 100
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
177 171
178 static PipeFlagComboData gPipeWritingFlagCombos[] = { 172 static PipeFlagComboData gPipeWritingFlagCombos[] = {
179 { "", 0 }, 173 { "", 0 },
180 { " cross-process", SkGPipeWriter::kCrossProcess_Flag }, 174 { " cross-process", SkGPipeWriter::kCrossProcess_Flag },
181 { " cross-process, shared address", SkGPipeWriter::kCrossProcess_Flag 175 { " cross-process, shared address", SkGPipeWriter::kCrossProcess_Flag
182 | SkGPipeWriter::kSharedAddressSpace_Flag } 176 | SkGPipeWriter::kSharedAddressSpace_Flag }
183 }; 177 };
184 178
185 class GMMain { 179 class GMMain {
186 public: 180 public:
187 GMMain() { 181 GMMain() : fRenderModesEncountered(1) {
borenet 2013/04/03 12:46:48 Do you mind moving fUseFileHierarchy, fMismatchPat
epoger 2013/04/03 14:28:25 Done.
188 // Set default values of member variables, which tool_main() 182 // Set default values of member variables, which tool_main()
189 // may override. 183 // may override.
190 fUseFileHierarchy = false; 184 fUseFileHierarchy = false;
191 fIgnorableErrorCombination.add(kMissingExpectations_ErrorType); 185 fIgnorableErrorCombination.add(kMissingExpectations_ErrorType);
192 fMismatchPath = NULL; 186 fMismatchPath = NULL;
187 fTestsRun = 0;
188 fRenderModesEncountered.reset();
193 } 189 }
194 190
195 SkString make_name(const char shortName[], const char configName[]) { 191 SkString make_name(const char shortName[], const char configName[]) {
196 SkString name; 192 SkString name;
197 if (0 == strlen(configName)) { 193 if (0 == strlen(configName)) {
198 name.append(shortName); 194 name.append(shortName);
199 } else if (fUseFileHierarchy) { 195 } else if (fUseFileHierarchy) {
200 name.appendf("%s%c%s", configName, SkPATH_SEPARATOR, shortName); 196 name.appendf("%s%c%s", configName, SkPATH_SEPARATOR, shortName);
201 } else { 197 } else {
202 name.appendf("%s_%s", shortName, configName); 198 name.appendf("%s_%s", shortName, configName);
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
236 // TODO(epoger): Now that we have removed force_all_opaque() 232 // TODO(epoger): Now that we have removed force_all_opaque()
237 // from this method, we should be able to get rid of the 233 // from this method, we should be able to get rid of the
238 // transformation to 8888 format also. 234 // transformation to 8888 format also.
239 SkBitmap copy; 235 SkBitmap copy;
240 bitmap.copyTo(&copy, SkBitmap::kARGB_8888_Config); 236 bitmap.copyTo(&copy, SkBitmap::kARGB_8888_Config);
241 return SkImageEncoder::EncodeFile(path.c_str(), copy, 237 return SkImageEncoder::EncodeFile(path.c_str(), copy,
242 SkImageEncoder::kPNG_Type, 100); 238 SkImageEncoder::kPNG_Type, 100);
243 } 239 }
244 240
245 /** 241 /**
246 * Records the errors encountered in fFailedTests, except for any error 242 * Add all render modes encountered thus far to the "modes" array.
247 * types we want to ignore.
248 */ 243 */
249 void RecordError(const ErrorCombination& errorCombination, const SkString& n ame, 244 void GetRenderModesEncountered(SkTArray<SkString> &modes) {
250 const char renderModeDescriptor []) { 245 SkTDict<int>::Iter iter(this->fRenderModesEncountered);
251 // The common case: no error means nothing to record. 246 const char* mode;
247 while ((mode = iter.next(NULL)) != NULL) {
248 SkString modeAsString = SkString(mode);
249 // TODO(epoger): It seems a bit silly that all of these modes were
250 // recorded with a leading "-" which we have to remove here
251 // (except for mode "", which means plain old original mode).
252 // But that's how renderModeDescriptor has been passed into
253 // compare_test_results_to_reference_bitmap() historically,
254 // and changing that now may affect other parts of our code.
255 if (modeAsString.startsWith("-")) {
256 modeAsString.remove(0, 1);
257 modes.push_back(modeAsString);
258 }
259 }
260 }
261
262 /**
263 * Records the results of this test in fTestsRun and fFailedTests.
264 *
265 * We even record successes, and errors that we regard as
266 * "ignorable"; we can filter them out later.
267 */
268 void RecordTestResults(const ErrorCombination& errorCombination, const SkStr ing& name,
269 const char renderModeDescriptor []) {
270 // Things to do regardless of errorCombination.
271 fTestsRun++;
272 this->fRenderModesEncountered.set(renderModeDescriptor, kAnyIntValue);
273
252 if (errorCombination.isEmpty()) { 274 if (errorCombination.isEmpty()) {
253 return; 275 return;
254 } 276 }
255 277
256 // If only certain error type(s) were reported, we know we can ignore th em. 278 // Things to do only if there is some error condition.
257 if (errorCombination.minus(fIgnorableErrorCombination).isEmpty()) { 279 SkString fullName = make_name(name.c_str(), renderModeDescriptor);
258 return; 280 for (int typeInt = 0; typeInt <= kLast_ErrorType; typeInt++) {
259 } 281 ErrorType type = static_cast<ErrorType>(typeInt);
260 282 if (errorCombination.includes(type)) {
261 FailRec& rec = fFailedTests.push_back(make_name(name.c_str(), renderMode Descriptor)); 283 fFailedTests[type].push_back(fullName);
262 rec.fIsPixelError = errorCombination.includes(kImageMismatch_ErrorType);
263 }
264
265 // List contents of fFailedTests via SkDebug.
266 void ListErrors() {
267 for (int i = 0; i < fFailedTests.count(); ++i) {
268 if (fFailedTests[i].fIsPixelError) {
269 gm_fprintf(stderr, "\t\t%s pixel_error\n", fFailedTests[i].fName .c_str());
270 } else {
271 gm_fprintf(stderr, "\t\t%s\n", fFailedTests[i].fName.c_str());
272 } 284 }
273 } 285 }
274 } 286 }
275 287
288 /**
289 * Return the number of significant (non-ignorable) errors we have
290 * encountered so far.
291 */
292 int NumSignificantErrors() {
293 int significantErrors = 0;
294 for (int typeInt = 0; typeInt <= kLast_ErrorType; typeInt++) {
295 ErrorType type = static_cast<ErrorType>(typeInt);
296 if (!fIgnorableErrorCombination.includes(type)) {
297 significantErrors += fFailedTests[type].count();
298 }
299 }
300 return significantErrors;
301 }
302
303 /**
304 * List contents of fFailedTests to stdout.
305 */
306 void ListErrors() {
307 // First, print a single summary line.
308 SkString summary;
309 summary.appendf("Ran %d tests:", fTestsRun);
310 for (int typeInt = 0; typeInt <= kLast_ErrorType; typeInt++) {
311 ErrorType type = static_cast<ErrorType>(typeInt);
312 summary.appendf(" %s=%d", getErrorTypeName(type), fFailedTests[type] .count());
313 }
314 gm_fprintf(stdout, "%s\n", summary.c_str());
315
316 // Now, for each failure type, list the tests that failed that way.
317 for (int typeInt = 0; typeInt <= kLast_ErrorType; typeInt++) {
318 SkString line;
319 ErrorType type = static_cast<ErrorType>(typeInt);
320 if (fIgnorableErrorCombination.includes(type)) {
321 line.append("[ ] ");
322 } else {
323 line.append("[*] ");
324 }
325
326 SkTArray<SkString> *failedTestsOfThisType = &fFailedTests[type];
327 int count = failedTestsOfThisType->count();
328 line.appendf("%d %s:", count, getErrorTypeName(type));
329 for (int i = 0; i < count; ++i) {
330 line.append(" ");
331 line.append((*failedTestsOfThisType)[i]);
332 }
333 gm_fprintf(stdout, "%s\n", line.c_str());
334 }
335 gm_fprintf(stdout, "(results marked with [*] will cause nonzero return v alue)\n");
336 }
337
276 static bool write_document(const SkString& path, 338 static bool write_document(const SkString& path,
277 const SkDynamicMemoryWStream& document) { 339 const SkDynamicMemoryWStream& document) {
278 SkFILEWStream stream(path.c_str()); 340 SkFILEWStream stream(path.c_str());
279 SkAutoDataUnref data(document.copyToData()); 341 SkAutoDataUnref data(document.copyToData());
280 return stream.writeData(data.get()); 342 return stream.writeData(data.get());
281 } 343 }
282 344
283 /** 345 /**
284 * Prepare an SkBitmap to render a GM into. 346 * Prepare an SkBitmap to render a GM into.
285 * 347 *
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after
503 if (kXPS_Backend == gRec.fBackend) { 565 if (kXPS_Backend == gRec.fBackend) {
504 path = make_filename(writePath, renderModeDescriptor, name.c_str(), 566 path = make_filename(writePath, renderModeDescriptor, name.c_str(),
505 "xps"); 567 "xps");
506 success = write_document(path, *document); 568 success = write_document(path, *document);
507 } 569 }
508 if (success) { 570 if (success) {
509 return kEmpty_ErrorCombination; 571 return kEmpty_ErrorCombination;
510 } else { 572 } else {
511 gm_fprintf(stderr, "FAILED to write %s\n", path.c_str()); 573 gm_fprintf(stderr, "FAILED to write %s\n", path.c_str());
512 ErrorCombination errors(kWritingReferenceImage_ErrorType); 574 ErrorCombination errors(kWritingReferenceImage_ErrorType);
513 RecordError(errors, name, renderModeDescriptor); 575 // TODO(epoger): Don't call RecordTestResults() here...
576 // Instead, we should make sure to call RecordTestResults
577 // exactly ONCE per test. (Otherwise, gmmain.fTestsRun
578 // will be incremented twice for this test: once in
579 // compare_test_results_to_stored_expectations() before
580 // that method calls this one, and again here.)
581 //
582 // When we make that change, we should probably add a
583 // WritingReferenceImage test to the gm self-tests.)
584 RecordTestResults(errors, name, renderModeDescriptor);
514 return errors; 585 return errors;
515 } 586 }
516 } 587 }
517 588
518 /** 589 /**
519 * Log more detail about the mistmatch between expectedBitmap and 590 * Log more detail about the mistmatch between expectedBitmap and
520 * actualBitmap. 591 * actualBitmap.
521 */ 592 */
522 void report_bitmap_diffs(const SkBitmap& expectedBitmap, const SkBitmap& act ualBitmap, 593 void report_bitmap_diffs(const SkBitmap& expectedBitmap, const SkBitmap& act ualBitmap,
523 const char *testName) { 594 const char *testName) {
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
615 write_bitmap(path, actualBitmap); 686 write_bitmap(path, actualBitmap);
616 } 687 }
617 688
618 // If we have access to a single expected bitmap, log more 689 // If we have access to a single expected bitmap, log more
619 // detail about the mismatch. 690 // detail about the mismatch.
620 const SkBitmap *expectedBitmapPtr = expectations.asBitmap(); 691 const SkBitmap *expectedBitmapPtr = expectations.asBitmap();
621 if (NULL != expectedBitmapPtr) { 692 if (NULL != expectedBitmapPtr) {
622 report_bitmap_diffs(*expectedBitmapPtr, actualBitmap, completeNa me); 693 report_bitmap_diffs(*expectedBitmapPtr, actualBitmap, completeNa me);
623 } 694 }
624 } 695 }
625 RecordError(errors, baseNameString, renderModeDescriptor); 696 RecordTestResults(errors, baseNameString, renderModeDescriptor);
626 697
627 if (addToJsonSummary) { 698 if (addToJsonSummary) {
628 add_actual_results_to_json_summary(completeName, actualChecksum, err ors, 699 add_actual_results_to_json_summary(completeName, actualChecksum, err ors,
629 expectations.ignoreFailure()); 700 expectations.ignoreFailure());
630 add_expected_results_to_json_summary(completeName, expectations); 701 add_expected_results_to_json_summary(completeName, expectations);
631 } 702 }
632 703
633 return errors; 704 return errors;
634 } 705 }
635 706
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
731 errors.add(compare_to_expectations(expectations, actualBitmap, 802 errors.add(compare_to_expectations(expectations, actualBitmap,
732 name, "", true)); 803 name, "", true));
733 } else { 804 } else {
734 // If we are running without expectations, we still want to 805 // If we are running without expectations, we still want to
735 // record the actual results. 806 // record the actual results.
736 Checksum actualChecksum = 807 Checksum actualChecksum =
737 SkBitmapChecksummer::Compute64(actualBitmap); 808 SkBitmapChecksummer::Compute64(actualBitmap);
738 add_actual_results_to_json_summary(name.c_str(), actualChecksum, 809 add_actual_results_to_json_summary(name.c_str(), actualChecksum,
739 ErrorCombination(kMissingExpectat ions_ErrorType), 810 ErrorCombination(kMissingExpectat ions_ErrorType),
740 false); 811 false);
812 RecordTestResults(ErrorCombination(kMissingExpectations_ErrorType), name, "");
741 } 813 }
742 814
743 // TODO: Consider moving this into compare_to_expectations(), 815 // TODO: Consider moving this into compare_to_expectations(),
744 // similar to fMismatchPath... for now, we don't do that, because 816 // similar to fMismatchPath... for now, we don't do that, because
745 // we don't want to write out the actual bitmaps for all 817 // we don't want to write out the actual bitmaps for all
746 // renderModes of all tests! That would be a lot of files. 818 // renderModes of all tests! That would be a lot of files.
747 if (writePath && (gRec.fFlags & kWrite_ConfigFlag)) { 819 if (writePath && (gRec.fFlags & kWrite_ConfigFlag)) {
748 errors.add(write_reference_image(gRec, writePath, "", 820 errors.add(write_reference_image(gRec, writePath, "",
749 name, actualBitmap, pdf)); 821 name, actualBitmap, pdf));
750 } 822 }
751 823
752 return errors; 824 return errors;
753 } 825 }
754 826
755 /** 827 /**
756 * Compare actualBitmap to referenceBitmap. 828 * Compare actualBitmap to referenceBitmap.
757 * 829 *
758 * @param gm which test generated the bitmap 830 * @param gm which test generated the bitmap
759 * @param gRec 831 * @param gRec
760 * @param renderModeDescriptor 832 * @param renderModeDescriptor
761 * @param actualBitmap actual bitmap generated by this run 833 * @param actualBitmap actual bitmap generated by this run
762 * @param referenceBitmap bitmap we expected to be generated 834 * @param referenceBitmap bitmap we expected to be generated
763 */ 835 */
764 ErrorCombination compare_test_results_to_reference_bitmap( 836 ErrorCombination compare_test_results_to_reference_bitmap(
765 GM* gm, const ConfigData& gRec, const char renderModeDescriptor [], 837 GM* gm, const ConfigData& gRec, const char renderModeDescriptor [],
766 SkBitmap& actualBitmap, const SkBitmap* referenceBitmap) { 838 SkBitmap& actualBitmap, const SkBitmap* referenceBitmap) {
767 839
840 // TODO(epoger): This method is run to compare results across
841 // different rendering modes (as opposed to
842 // compare_test_results_to_stored_expectations(), which
843 // compares results against expectations stored on disk). If
844 // we would like the GenerateGMs step to distinguish between
845 // those two types of mismatches, we should report image
846 // mismatches in here with a different ErrorType.
768 SkASSERT(referenceBitmap); 847 SkASSERT(referenceBitmap);
769 SkString name = make_name(gm->shortName(), gRec.fName); 848 SkString name = make_name(gm->shortName(), gRec.fName);
770 Expectations expectations(*referenceBitmap); 849 Expectations expectations(*referenceBitmap);
771 return compare_to_expectations(expectations, actualBitmap, 850 return compare_to_expectations(expectations, actualBitmap,
772 name, renderModeDescriptor); 851 name, renderModeDescriptor);
773 } 852 }
774 853
775 static SkPicture* generate_new_picture(GM* gm, BbhType bbhType, uint32_t rec ordFlags, 854 static SkPicture* generate_new_picture(GM* gm, BbhType bbhType, uint32_t rec ordFlags,
776 SkScalar scale = SK_Scalar1) { 855 SkScalar scale = SK_Scalar1) {
777 // Pictures are refcounted so must be on heap 856 // Pictures are refcounted so must be on heap
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
873 // -deferred image, we exit early! We should fix this 952 // -deferred image, we exit early! We should fix this
874 // ASAP, because it is hiding -deferred errors... but for 953 // ASAP, because it is hiding -deferred errors... but for
875 // now, I'm leaving the logic as it is so that the 954 // now, I'm leaving the logic as it is so that the
876 // refactoring change 955 // refactoring change
877 // https://codereview.chromium.org/12992003/ is unblocked. 956 // https://codereview.chromium.org/12992003/ is unblocked.
878 // 957 //
879 // Filed as https://code.google.com/p/skia/issues/detail?id=1180 958 // Filed as https://code.google.com/p/skia/issues/detail?id=1180
880 // ('image-surface gm test is failing in "deferred" mode, 959 // ('image-surface gm test is failing in "deferred" mode,
881 // and gm is not reporting the failure') 960 // and gm is not reporting the failure')
882 if (errors.isEmpty()) { 961 if (errors.isEmpty()) {
962 // TODO(epoger): Report this as a new ErrorType,
963 // something like kImageGeneration_ErrorType?
883 return kEmpty_ErrorCombination; 964 return kEmpty_ErrorCombination;
884 } 965 }
885 return compare_test_results_to_reference_bitmap( 966 return compare_test_results_to_reference_bitmap(
886 gm, gRec, "-deferred", bitmap, &referenceBitmap); 967 gm, gRec, "-deferred", bitmap, &referenceBitmap);
887 } 968 }
888 return kEmpty_ErrorCombination; 969 return kEmpty_ErrorCombination;
889 } 970 }
890 971
891 ErrorCombination test_pipe_playback(GM* gm, 972 ErrorCombination test_pipe_playback(GM* gm,
892 const ConfigData& gRec, 973 const ConfigData& gRec,
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
946 // 1027 //
947 // member variables. 1028 // member variables.
948 // They are public for now, to allow easier setting by tool_main(). 1029 // They are public for now, to allow easier setting by tool_main().
949 // 1030 //
950 1031
951 bool fUseFileHierarchy; 1032 bool fUseFileHierarchy;
952 ErrorCombination fIgnorableErrorCombination; 1033 ErrorCombination fIgnorableErrorCombination;
953 1034
954 const char* fMismatchPath; 1035 const char* fMismatchPath;
955 1036
956 // information about all failed tests we have encountered so far 1037 // collection of tests that have failed with each ErrorType
957 SkTArray<FailRec> fFailedTests; 1038 SkTArray<SkString> fFailedTests[kLast_ErrorType+1];
1039 int fTestsRun;
1040 SkTDict<int> fRenderModesEncountered;
958 1041
959 // Where to read expectations (expected image checksums, etc.) from. 1042 // Where to read expectations (expected image checksums, etc.) from.
960 // If unset, we don't do comparisons. 1043 // If unset, we don't do comparisons.
961 SkAutoTUnref<ExpectationsSource> fExpectationsSource; 1044 SkAutoTUnref<ExpectationsSource> fExpectationsSource;
962 1045
963 // JSON summaries that we generate as we go (just for output). 1046 // JSON summaries that we generate as we go (just for output).
964 Json::Value fJsonExpectedResults; 1047 Json::Value fJsonExpectedResults;
965 Json::Value fJsonActualResults_Failed; 1048 Json::Value fJsonActualResults_Failed;
966 Json::Value fJsonActualResults_FailureIgnored; 1049 Json::Value fJsonActualResults_FailureIgnored;
967 Json::Value fJsonActualResults_NoComparison; 1050 Json::Value fJsonActualResults_NoComparison;
(...skipping 290 matching lines...) Expand 10 before | Expand all | Expand 10 after
1258 */ 1341 */
1259 ErrorCombination run_multiple_modes(GMMain &gmmain, GM *gm, const ConfigData &co mpareConfig, 1342 ErrorCombination run_multiple_modes(GMMain &gmmain, GM *gm, const ConfigData &co mpareConfig,
1260 const SkBitmap &comparisonBitmap, 1343 const SkBitmap &comparisonBitmap,
1261 const SkTDArray<SkScalar> &tileGridReplaySca les); 1344 const SkTDArray<SkScalar> &tileGridReplaySca les);
1262 ErrorCombination run_multiple_modes(GMMain &gmmain, GM *gm, const ConfigData &co mpareConfig, 1345 ErrorCombination run_multiple_modes(GMMain &gmmain, GM *gm, const ConfigData &co mpareConfig,
1263 const SkBitmap &comparisonBitmap, 1346 const SkBitmap &comparisonBitmap,
1264 const SkTDArray<SkScalar> &tileGridReplaySca les) { 1347 const SkTDArray<SkScalar> &tileGridReplaySca les) {
1265 ErrorCombination errorsForAllModes; 1348 ErrorCombination errorsForAllModes;
1266 uint32_t gmFlags = gm->getFlags(); 1349 uint32_t gmFlags = gm->getFlags();
1267 1350
1268 // run the picture centric GM steps 1351 // TODO(epoger): We should start recording any per-GM skipped
1352 // modes (i.e. those we skipped due to gmFlags) with a new
1353 // ErrorType, perhaps named kIntentionallySkipped_ErrorType.
1269 if (!(gmFlags & GM::kSkipPicture_Flag)) { 1354 if (!(gmFlags & GM::kSkipPicture_Flag)) {
1270 1355
1271 ErrorCombination pictErrors; 1356 ErrorCombination pictErrors;
1272 1357
1273 //SkAutoTUnref<SkPicture> pict(generate_new_picture(gm)); 1358 //SkAutoTUnref<SkPicture> pict(generate_new_picture(gm));
1274 SkPicture* pict = gmmain.generate_new_picture(gm, kNone_BbhType, 0); 1359 SkPicture* pict = gmmain.generate_new_picture(gm, kNone_BbhType, 0);
1275 SkAutoUnref aur(pict); 1360 SkAutoUnref aur(pict);
1276 1361
1277 if (FLAGS_replay) { 1362 if (FLAGS_replay) {
1278 SkBitmap bitmap; 1363 SkBitmap bitmap;
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
1352 if ((pipeErrors.isEmpty()) && 1437 if ((pipeErrors.isEmpty()) &&
1353 FLAGS_tiledPipe && !(gmFlags & GM::kSkipTiled_Flag)) { 1438 FLAGS_tiledPipe && !(gmFlags & GM::kSkipTiled_Flag)) {
1354 pipeErrors.add(gmmain.test_tiled_pipe_playback(gm, compareConfig, co mparisonBitmap)); 1439 pipeErrors.add(gmmain.test_tiled_pipe_playback(gm, compareConfig, co mparisonBitmap));
1355 } 1440 }
1356 1441
1357 errorsForAllModes.add(pipeErrors); 1442 errorsForAllModes.add(pipeErrors);
1358 } 1443 }
1359 return errorsForAllModes; 1444 return errorsForAllModes;
1360 } 1445 }
1361 1446
1447 /**
1448 * Return a list of all entries in an array of strings as a single string
1449 * of this form:
1450 * "item1", "item2", "item3"
1451 */
1452 SkString list_all(const SkTArray<SkString> &stringArray);
1453 SkString list_all(const SkTArray<SkString> &stringArray) {
1454 SkString total;
1455 for (int i = 0; i < stringArray.count(); i++) {
1456 if (i > 0) {
1457 total.append(", ");
1458 }
1459 total.append("\"");
1460 total.append(stringArray[i]);
1461 total.append("\"");
1462 }
1463 return total;
1464 }
1465
1466 /**
1467 * Return a list of configuration names, as a single string of this form:
1468 * "item1", "item2", "item3"
1469 *
1470 * @param configs configurations, as a list of indices into gRec
1471 */
1472 SkString list_all_config_names(const SkTDArray<size_t> &configs);
1473 SkString list_all_config_names(const SkTDArray<size_t> &configs) {
1474 SkString total;
1475 for (int i = 0; i < configs.count(); i++) {
1476 if (i > 0) {
1477 total.append(", ");
1478 }
1479 total.append("\"");
1480 total.append(gRec[configs[i]].fName);
1481 total.append("\"");
1482 }
1483 return total;
1484 }
1485
1362 int tool_main(int argc, char** argv); 1486 int tool_main(int argc, char** argv);
1363 int tool_main(int argc, char** argv) { 1487 int tool_main(int argc, char** argv) {
1364 1488
1365 #if SK_ENABLE_INST_COUNT 1489 #if SK_ENABLE_INST_COUNT
1366 gPrintInstCount = true; 1490 gPrintInstCount = true;
1367 #endif 1491 #endif
1368 1492
1369 SkGraphics::Init(); 1493 SkGraphics::Init();
1370 // we don't need to see this during a run 1494 // we don't need to see this during a run
1371 gSkSuppressFontCachePurgeSpew = true; 1495 gSkSuppressFontCachePurgeSpew = true;
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after
1533 gm_fprintf(stderr, "reading resources from %s\n", FLAGS_resourcePath[0]) ; 1657 gm_fprintf(stderr, "reading resources from %s\n", FLAGS_resourcePath[0]) ;
1534 } 1658 }
1535 1659
1536 if (moduloDivisor <= 0) { 1660 if (moduloDivisor <= 0) {
1537 moduloRemainder = -1; 1661 moduloRemainder = -1;
1538 } 1662 }
1539 if (moduloRemainder < 0 || moduloRemainder >= moduloDivisor) { 1663 if (moduloRemainder < 0 || moduloRemainder >= moduloDivisor) {
1540 moduloRemainder = -1; 1664 moduloRemainder = -1;
1541 } 1665 }
1542 1666
1543 // Accumulate success of all tests. 1667 int gmsRun = 0;
1544 int testsRun = 0;
1545 int testsPassed = 0;
1546 int testsFailed = 0;
1547 int testsMissingReferenceImages = 0;
1548
1549 int gmIndex = -1; 1668 int gmIndex = -1;
1550 SkString moduloStr; 1669 SkString moduloStr;
1551 1670
1552 // If we will be writing out files, prepare subdirectories. 1671 // If we will be writing out files, prepare subdirectories.
1553 if (FLAGS_writePath.count() == 1) { 1672 if (FLAGS_writePath.count() == 1) {
1554 if (!sk_mkdir(FLAGS_writePath[0])) { 1673 if (!sk_mkdir(FLAGS_writePath[0])) {
1555 return -1; 1674 return -1;
1556 } 1675 }
1557 if (gmmain.fUseFileHierarchy) { 1676 if (gmmain.fUseFileHierarchy) {
1558 for (int i = 0; i < configs.count(); i++) { 1677 for (int i = 0; i < configs.count(); i++) {
(...skipping 19 matching lines...) Expand all
1578 } 1697 }
1579 moduloStr.printf("[%d.%d] ", gmIndex, moduloDivisor); 1698 moduloStr.printf("[%d.%d] ", gmIndex, moduloDivisor);
1580 } 1699 }
1581 1700
1582 const char* shortName = gm->shortName(); 1701 const char* shortName = gm->shortName();
1583 if (skip_name(FLAGS_match, shortName)) { 1702 if (skip_name(FLAGS_match, shortName)) {
1584 SkDELETE(gm); 1703 SkDELETE(gm);
1585 continue; 1704 continue;
1586 } 1705 }
1587 1706
1707 gmsRun++;
1588 SkISize size = gm->getISize(); 1708 SkISize size = gm->getISize();
1589 gm_fprintf(stdout, "%sdrawing... %s [%d %d]\n", moduloStr.c_str(), short Name, 1709 gm_fprintf(stdout, "%sdrawing... %s [%d %d]\n", moduloStr.c_str(), short Name,
1590 size.width(), size.height()); 1710 size.width(), size.height());
1591 1711
1592 ErrorCombination testErrors; 1712 run_multiple_configs(gmmain, gm, configs, grFactory);
1593 testErrors.add(run_multiple_configs(gmmain, gm, configs, grFactory));
1594 1713
1595 SkBitmap comparisonBitmap; 1714 SkBitmap comparisonBitmap;
1596 const ConfigData compareConfig = 1715 const ConfigData compareConfig =
1597 { SkBitmap::kARGB_8888_Config, kRaster_Backend, kDontCare_GLContextT ype, 0, kRW_ConfigFlag, "comparison", false }; 1716 { SkBitmap::kARGB_8888_Config, kRaster_Backend, kDontCare_GLContextT ype, 0, kRW_ConfigFlag, "comparison", false };
1598 testErrors.add(gmmain.generate_image( 1717 gmmain.generate_image(gm, compareConfig, NULL, NULL, &comparisonBitmap, false);
1599 gm, compareConfig, NULL, NULL, &comparisonBitmap, false));
1600 1718
1601 // TODO(epoger): only run this if gmmain.generate_image() succeeded? 1719 // TODO(epoger): only run this if gmmain.generate_image() succeeded?
1602 // Otherwise, what are we comparing against? 1720 // Otherwise, what are we comparing against?
1603 testErrors.add(run_multiple_modes(gmmain, gm, compareConfig, comparisonB itmap, 1721 run_multiple_modes(gmmain, gm, compareConfig, comparisonBitmap, tileGrid ReplayScales);
1604 tileGridReplayScales));
1605
1606 // Update overall results.
1607 // We only tabulate the particular error types that we currently
1608 // care about (e.g., missing reference images). Later on, if we
1609 // want to also tabulate other error types, we can do so.
1610 testsRun++;
1611 if (!gmmain.fExpectationsSource.get() ||
1612 (testErrors.includes(kMissingExpectations_ErrorType))) {
1613 testsMissingReferenceImages++;
1614 }
1615 if (testErrors.minus(gmmain.fIgnorableErrorCombination).isEmpty()) {
1616 testsPassed++;
1617 } else {
1618 testsFailed++;
1619 }
1620 1722
1621 SkDELETE(gm); 1723 SkDELETE(gm);
1622 } 1724 }
1623 gm_fprintf(stdout, "Ran %d tests: %d passed, %d failed, %d missing reference images\n", 1725
1624 testsRun, testsPassed, testsFailed, testsMissingReferenceImages); 1726 SkTArray<SkString> modes;
1727 gmmain.GetRenderModesEncountered(modes);
1728
1729 // Output summary to stdout.
1730 gm_fprintf(stdout, "Ran %d GMs\n", gmsRun);
1731 gm_fprintf(stdout, "... over %2d configs [%s]\n", configs.count(),
1732 list_all_config_names(configs).c_str());
1733 gm_fprintf(stdout, "... and %2d modes [%s]\n", modes.count(), list_all(mode s).c_str());
1734 gm_fprintf(stdout, "... so there should be a total of %d tests.\n",
1735 gmsRun * (configs.count() + modes.count()));
1736
1737 // TODO(epoger): Ultimately, we should signal an error if the
1738 // expected total number of tests (displayed above) does not match
1739 // gmmain.fTestsRun. But for now, there are cases where those
1740 // numbers won't match: specifically, if some configs/modes are
1741 // skipped on a per-GM basis (due to gm->getFlags() for a specific
1742 // GM). Later on, we should record tests like that using some new
1743 // ErrorType, like kIntentionallySkipped_ErrorType. Then we could
1744 // signal an error if the totals didn't match up.
1625 gmmain.ListErrors(); 1745 gmmain.ListErrors();
1626 1746
1627 if (FLAGS_writeJsonSummaryPath.count() == 1) { 1747 if (FLAGS_writeJsonSummaryPath.count() == 1) {
1628 Json::Value actualResults; 1748 Json::Value actualResults;
1629 actualResults[kJsonKey_ActualResults_Failed] = 1749 actualResults[kJsonKey_ActualResults_Failed] =
1630 gmmain.fJsonActualResults_Failed; 1750 gmmain.fJsonActualResults_Failed;
1631 actualResults[kJsonKey_ActualResults_FailureIgnored] = 1751 actualResults[kJsonKey_ActualResults_FailureIgnored] =
1632 gmmain.fJsonActualResults_FailureIgnored; 1752 gmmain.fJsonActualResults_FailureIgnored;
1633 actualResults[kJsonKey_ActualResults_NoComparison] = 1753 actualResults[kJsonKey_ActualResults_NoComparison] =
1634 gmmain.fJsonActualResults_NoComparison; 1754 gmmain.fJsonActualResults_NoComparison;
(...skipping 19 matching lines...) Expand all
1654 gm_fprintf(stdout, "config: %s %x\n", config.fName, gr); 1774 gm_fprintf(stdout, "config: %s %x\n", config.fName, gr);
1655 gr->printCacheStats(); 1775 gr->printCacheStats();
1656 } 1776 }
1657 } 1777 }
1658 #endif 1778 #endif
1659 1779
1660 delete grFactory; 1780 delete grFactory;
1661 #endif 1781 #endif
1662 SkGraphics::Term(); 1782 SkGraphics::Term();
1663 1783
1664 return (0 == testsFailed) ? 0 : -1; 1784 return (0 == gmmain.NumSignificantErrors()) ? 0 : -1;
1665 } 1785 }
1666 1786
1667 void GMMain::installFilter(SkCanvas* canvas) { 1787 void GMMain::installFilter(SkCanvas* canvas) {
1668 if (FLAGS_forceBWtext) { 1788 if (FLAGS_forceBWtext) {
1669 canvas->setDrawFilter(SkNEW(BWTextDrawFilter))->unref(); 1789 canvas->setDrawFilter(SkNEW(BWTextDrawFilter))->unref();
1670 } 1790 }
1671 } 1791 }
1672 1792
1673 #if !defined(SK_BUILD_FOR_IOS) && !defined(SK_BUILD_FOR_NACL) 1793 #if !defined(SK_BUILD_FOR_IOS) && !defined(SK_BUILD_FOR_NACL)
1674 int main(int argc, char * const argv[]) { 1794 int main(int argc, char * const argv[]) {
1675 return tool_main(argc, (char**) argv); 1795 return tool_main(argc, (char**) argv);
1676 } 1796 }
1677 #endif 1797 #endif
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698