GM: specify that currently used checksums are CityHashes of SkBitmaps
authorepoger@google.com <epoger@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Fri, 26 Apr 2013 15:06:44 +0000 (15:06 +0000)
committerepoger@google.com <epoger@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Fri, 26 Apr 2013 15:06:44 +0000 (15:06 +0000)
(distinct from other hash algorithms we may switch to, or hashes of
files such as PDFs that cannot be read into an SkBitmap)

Review URL: https://codereview.chromium.org/14284018

git-svn-id: http://skia.googlecode.com/svn/trunk@8877 2bbb7eff-a529-9590-31e7-b0007b416f81

16 files changed:
gm/gm_expectations.cpp [new file with mode: 0644]
gm/gm_expectations.h
gm/gmmain.cpp
gm/tests/outputs/compared-against-different-pixels-images/output-expected/json-summary.txt
gm/tests/outputs/compared-against-different-pixels-json/output-expected/json-summary.txt
gm/tests/outputs/compared-against-empty-dir/output-expected/json-summary.txt
gm/tests/outputs/compared-against-identical-bytes-images/output-expected/json-summary.txt
gm/tests/outputs/compared-against-identical-bytes-json/output-expected/json-summary.txt
gm/tests/outputs/compared-against-identical-pixels-images/output-expected/json-summary.txt
gm/tests/outputs/compared-against-identical-pixels-json/output-expected/json-summary.txt
gm/tests/outputs/ignore-expectations-mismatch/output-expected/json-summary.txt
gm/tests/outputs/intentionally-skipped-tests/output-expected/json-summary.txt
gm/tests/outputs/no-readpath/output-expected/json-summary.txt
gm/tests/outputs/nonverbose/output-expected/json-summary.txt
gm/tests/outputs/pipe-playback-failure/output-expected/json-summary.txt
gyp/gm.gyp

diff --git a/gm/gm_expectations.cpp b/gm/gm_expectations.cpp
new file mode 100644 (file)
index 0000000..1aa1ef4
--- /dev/null
@@ -0,0 +1,215 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "gm_expectations.h"
+#include "SkBitmapHasher.h"
+#include "SkImageDecoder.h"
+
+#define DEBUGFAIL_SEE_STDERR SkDEBUGFAIL("see stderr for message")
+
+const static char kJsonKey_ActualResults[]   = "actual-results";
+const static char kJsonKey_ActualResults_Failed[]        = "failed";
+const static char kJsonKey_ActualResults_FailureIgnored[]= "failure-ignored";
+const static char kJsonKey_ActualResults_NoComparison[]  = "no-comparison";
+const static char kJsonKey_ActualResults_Succeeded[]     = "succeeded";
+const static char kJsonKey_ActualResults_AnyStatus_BitmapCityhash[]  = "bitmap-cityhash";
+
+const static char kJsonKey_ExpectedResults[] = "expected-results";
+const static char kJsonKey_ExpectedResults_AllowedBitmapCityhashes[] = "allowed-bitmap-cityhashes";
+const static char kJsonKey_ExpectedResults_IgnoreFailure[]           = "ignore-failure";
+
+namespace skiagm {
+
+    // TODO(epoger): This currently assumes that the result SkHashDigest was
+    // generated as a CityHash of an SkBitmap.  We'll need to allow for other
+    // hash types to cover non-bitmaps, MD5 instead of CityHash, etc.
+    Json::Value ActualResultAsJsonValue(const SkHashDigest& result) {
+        Json::Value jsonValue;
+        jsonValue[kJsonKey_ActualResults_AnyStatus_BitmapCityhash] = asJsonValue(result);
+        return jsonValue;
+    }
+
+    Json::Value CreateJsonTree(Json::Value expectedResults,
+                               Json::Value actualResultsFailed,
+                               Json::Value actualResultsFailureIgnored,
+                               Json::Value actualResultsNoComparison,
+                               Json::Value actualResultsSucceeded) {
+        Json::Value actualResults;
+        actualResults[kJsonKey_ActualResults_Failed] = actualResultsFailed;
+        actualResults[kJsonKey_ActualResults_FailureIgnored] = actualResultsFailureIgnored;
+        actualResults[kJsonKey_ActualResults_NoComparison] = actualResultsNoComparison;
+        actualResults[kJsonKey_ActualResults_Succeeded] = actualResultsSucceeded;
+        Json::Value root;
+        root[kJsonKey_ActualResults] = actualResults;
+        root[kJsonKey_ExpectedResults] = expectedResults;
+        return root;
+    }
+
+
+    // Expectations class...
+
+    Expectations::Expectations(bool ignoreFailure) {
+        fIgnoreFailure = ignoreFailure;
+    }
+
+    Expectations::Expectations(const SkBitmap& bitmap, bool ignoreFailure) {
+        fBitmap = bitmap;
+        fIgnoreFailure = ignoreFailure;
+        SkHashDigest digest;
+        // TODO(epoger): Better handling for error returned by ComputeDigest()?
+        // For now, we just report a digest of 0 in error cases, like before.
+        if (!SkBitmapHasher::ComputeDigest(bitmap, &digest)) {
+            digest = 0;
+        }
+        fAllowedBitmapCityhashes.push_back() = digest;
+    }
+
+    Expectations::Expectations(Json::Value jsonElement) {
+        if (jsonElement.empty()) {
+            fIgnoreFailure = kDefaultIgnoreFailure;
+        } else {
+            Json::Value ignoreFailure = jsonElement[kJsonKey_ExpectedResults_IgnoreFailure];
+            if (ignoreFailure.isNull()) {
+                fIgnoreFailure = kDefaultIgnoreFailure;
+            } else if (!ignoreFailure.isBool()) {
+                gm_fprintf(stderr, "found non-boolean json value"
+                           " for key '%s' in element '%s'\n",
+                           kJsonKey_ExpectedResults_IgnoreFailure,
+                           jsonElement.toStyledString().c_str());
+                DEBUGFAIL_SEE_STDERR;
+                fIgnoreFailure = kDefaultIgnoreFailure;
+            } else {
+                fIgnoreFailure = ignoreFailure.asBool();
+            }
+
+            Json::Value allowedChecksums =
+                jsonElement[kJsonKey_ExpectedResults_AllowedBitmapCityhashes];
+            if (allowedChecksums.isNull()) {
+                // ok, we'll just assume there aren't any expected checksums to compare against
+            } else if (!allowedChecksums.isArray()) {
+                gm_fprintf(stderr, "found non-array json value"
+                           " for key '%s' in element '%s'\n",
+                           kJsonKey_ExpectedResults_AllowedBitmapCityhashes,
+                           jsonElement.toStyledString().c_str());
+                DEBUGFAIL_SEE_STDERR;
+            } else {
+                for (Json::ArrayIndex i=0; i<allowedChecksums.size(); i++) {
+                    Json::Value checksumElement = allowedChecksums[i];
+                    if (!checksumElement.isIntegral()) {
+                        gm_fprintf(stderr, "found non-integer checksum"
+                                   " in json element '%s'\n",
+                                   jsonElement.toStyledString().c_str());
+                        DEBUGFAIL_SEE_STDERR;
+                    } else {
+                        fAllowedBitmapCityhashes.push_back() = asChecksum(checksumElement);
+                    }
+                }
+            }
+        }
+    }
+
+    bool Expectations::match(Checksum actualChecksum) const {
+        for (int i=0; i < this->fAllowedBitmapCityhashes.count(); i++) {
+            Checksum allowedChecksum = this->fAllowedBitmapCityhashes[i];
+            if (allowedChecksum == actualChecksum) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    Json::Value Expectations::asJsonValue() const {
+        Json::Value allowedChecksumArray;
+        if (!this->fAllowedBitmapCityhashes.empty()) {
+            for (int i=0; i < this->fAllowedBitmapCityhashes.count(); i++) {
+                Checksum allowedChecksum = this->fAllowedBitmapCityhashes[i];
+                allowedChecksumArray.append(Json::UInt64(allowedChecksum));
+            }
+        }
+
+        Json::Value jsonValue;
+        jsonValue[kJsonKey_ExpectedResults_AllowedBitmapCityhashes] = allowedChecksumArray;
+        jsonValue[kJsonKey_ExpectedResults_IgnoreFailure] = this->ignoreFailure();
+        return jsonValue;
+    }
+
+
+    // IndividualImageExpectationsSource class...
+
+    Expectations IndividualImageExpectationsSource::get(const char *testName) {
+        SkString path = make_filename(fRootDir.c_str(), "", testName,
+                                      "png");
+        SkBitmap referenceBitmap;
+        bool decodedReferenceBitmap =
+            SkImageDecoder::DecodeFile(path.c_str(), &referenceBitmap,
+                                       SkBitmap::kARGB_8888_Config,
+                                       SkImageDecoder::kDecodePixels_Mode,
+                                       NULL);
+        if (decodedReferenceBitmap) {
+            return Expectations(referenceBitmap);
+        } else {
+            return Expectations();
+        }
+    }
+
+
+    // JsonExpectationsSource class...
+
+    JsonExpectationsSource::JsonExpectationsSource(const char *jsonPath) {
+        parse(jsonPath, &fJsonRoot);
+        fJsonExpectedResults = fJsonRoot[kJsonKey_ExpectedResults];
+    }
+
+    Expectations JsonExpectationsSource::get(const char *testName) {
+        return Expectations(fJsonExpectedResults[testName]);
+    }
+
+    /*static*/ SkData* JsonExpectationsSource::readIntoSkData(SkStream &stream, size_t maxBytes) {
+        if (0 == maxBytes) {
+            return SkData::NewEmpty();
+        }
+        char* bufStart = reinterpret_cast<char *>(sk_malloc_throw(maxBytes));
+        char* bufPtr = bufStart;
+        size_t bytesRemaining = maxBytes;
+        while (bytesRemaining > 0) {
+            size_t bytesReadThisTime = stream.read(bufPtr, bytesRemaining);
+            if (0 == bytesReadThisTime) {
+                break;
+            }
+            bytesRemaining -= bytesReadThisTime;
+            bufPtr += bytesReadThisTime;
+        }
+        return SkData::NewFromMalloc(bufStart, maxBytes - bytesRemaining);
+    }
+
+    /*static*/ bool JsonExpectationsSource::parse(const char *jsonPath, Json::Value *jsonRoot) {
+        SkFILEStream inFile(jsonPath);
+        if (!inFile.isValid()) {
+            gm_fprintf(stderr, "unable to read JSON file %s\n", jsonPath);
+            DEBUGFAIL_SEE_STDERR;
+            return false;
+        }
+
+        SkAutoDataUnref dataRef(readFileIntoSkData(inFile));
+        if (NULL == dataRef.get()) {
+            gm_fprintf(stderr, "error reading JSON file %s\n", jsonPath);
+            DEBUGFAIL_SEE_STDERR;
+            return false;
+        }
+
+        const char *bytes = reinterpret_cast<const char *>(dataRef.get()->data());
+        size_t size = dataRef.get()->size();
+        Json::Reader reader;
+        if (!reader.parse(bytes, bytes+size, *jsonRoot)) {
+            gm_fprintf(stderr, "error parsing JSON file %s\n", jsonPath);
+            DEBUGFAIL_SEE_STDERR;
+            return false;
+        }
+        return true;
+    }
+
+}
index 84cb7fe..df99c6e 100644 (file)
@@ -7,12 +7,10 @@
 #ifndef gm_expectations_DEFINED
 #define gm_expectations_DEFINED
 
-#include <stdarg.h>
 #include "gm.h"
 #include "SkBitmap.h"
 #include "SkBitmapHasher.h"
 #include "SkData.h"
-#include "SkImageDecoder.h"
 #include "SkOSFile.h"
 #include "SkRefCnt.h"
 #include "SkStream.h"
     #pragma warning(pop)
 #endif
 
-#define DEBUGFAIL_SEE_STDERR SkDEBUGFAIL("see stderr for message")
-
-const static char kJsonKey_ActualResults[]   = "actual-results";
-const static char kJsonKey_ActualResults_Failed[]        = "failed";
-const static char kJsonKey_ActualResults_FailureIgnored[]= "failure-ignored";
-const static char kJsonKey_ActualResults_NoComparison[]  = "no-comparison";
-const static char kJsonKey_ActualResults_Succeeded[]     = "succeeded";
-const static char kJsonKey_ActualResults_AnyStatus_Checksum[]    = "checksum";
-
-const static char kJsonKey_ExpectedResults[] = "expected-results";
-const static char kJsonKey_ExpectedResults_Checksums[]     = "checksums";
-const static char kJsonKey_ExpectedResults_IgnoreFailure[] = "ignore-failure";
-
 namespace skiagm {
 
     // The actual type we use to represent a checksum is hidden in here.
@@ -75,6 +60,14 @@ namespace skiagm {
         return filename;
     }
 
+    Json::Value ActualResultAsJsonValue(const SkHashDigest& result);
+
+    Json::Value CreateJsonTree(Json::Value expectedResults,
+                               Json::Value actualResultsFailed,
+                               Json::Value actualResultsFailureIgnored,
+                               Json::Value actualResultsNoComparison,
+                               Json::Value actualResultsSucceeded);
+
     /**
      * Test expectations (allowed image checksums, etc.)
      */
@@ -83,25 +76,13 @@ namespace skiagm {
         /**
          * No expectations at all.
          */
-        Expectations(bool ignoreFailure=kDefaultIgnoreFailure) {
-            fIgnoreFailure = ignoreFailure;
-        }
+        Expectations(bool ignoreFailure=kDefaultIgnoreFailure);
 
         /**
          * Expect exactly one image (appropriate for the case when we
          * are comparing against a single PNG file).
          */
-        Expectations(const SkBitmap& bitmap, bool ignoreFailure=kDefaultIgnoreFailure) {
-            fBitmap = bitmap;
-            fIgnoreFailure = ignoreFailure;
-            SkHashDigest digest;
-            // TODO(epoger): Better handling for error returned by ComputeDigest()?
-            // For now, we just report a digest of 0 in error cases, like before.
-            if (!SkBitmapHasher::ComputeDigest(bitmap, &digest)) {
-                digest = 0;
-            }
-            fAllowedChecksums.push_back() = digest;
-        }
+        Expectations(const SkBitmap& bitmap, bool ignoreFailure=kDefaultIgnoreFailure);
 
         /**
          * Create Expectations from a JSON element as found within the
@@ -110,48 +91,7 @@ namespace skiagm {
          * It's fine if the jsonElement is null or empty; in that case, we just
          * don't have any expectations.
          */
-        Expectations(Json::Value jsonElement) {
-            if (jsonElement.empty()) {
-                fIgnoreFailure = kDefaultIgnoreFailure;
-            } else {
-                Json::Value ignoreFailure = jsonElement[kJsonKey_ExpectedResults_IgnoreFailure];
-                if (ignoreFailure.isNull()) {
-                    fIgnoreFailure = kDefaultIgnoreFailure;
-                } else if (!ignoreFailure.isBool()) {
-                    gm_fprintf(stderr, "found non-boolean json value"
-                               " for key '%s' in element '%s'\n",
-                               kJsonKey_ExpectedResults_IgnoreFailure,
-                               jsonElement.toStyledString().c_str());
-                    DEBUGFAIL_SEE_STDERR;
-                    fIgnoreFailure = kDefaultIgnoreFailure;
-                } else {
-                    fIgnoreFailure = ignoreFailure.asBool();
-                }
-
-                Json::Value allowedChecksums = jsonElement[kJsonKey_ExpectedResults_Checksums];
-                if (allowedChecksums.isNull()) {
-                    // ok, we'll just assume there aren't any expected checksums to compare against
-                } else if (!allowedChecksums.isArray()) {
-                    gm_fprintf(stderr, "found non-array json value"
-                               " for key '%s' in element '%s'\n",
-                               kJsonKey_ExpectedResults_Checksums,
-                               jsonElement.toStyledString().c_str());
-                    DEBUGFAIL_SEE_STDERR;
-                } else {
-                    for (Json::ArrayIndex i=0; i<allowedChecksums.size(); i++) {
-                        Json::Value checksumElement = allowedChecksums[i];
-                        if (!checksumElement.isIntegral()) {
-                            gm_fprintf(stderr, "found non-integer checksum"
-                                       " in json element '%s'\n",
-                                       jsonElement.toStyledString().c_str());
-                            DEBUGFAIL_SEE_STDERR;
-                        } else {
-                            fAllowedChecksums.push_back() = asChecksum(checksumElement);
-                        }
-                    }
-                }
-            }
-        }
+        Expectations(Json::Value jsonElement);
 
         /**
          * Returns true iff we want to ignore failed expectations.
@@ -161,22 +101,14 @@ namespace skiagm {
         /**
          * Returns true iff there are no allowed checksums.
          */
-        bool empty() const { return this->fAllowedChecksums.empty(); }
+        bool empty() const { return this->fAllowedBitmapCityhashes.empty(); }
 
         /**
          * Returns true iff actualChecksum matches any allowedChecksum,
          * regardless of fIgnoreFailure.  (The caller can check
          * that separately.)
          */
-        bool match(Checksum actualChecksum) const {
-            for (int i=0; i < this->fAllowedChecksums.count(); i++) {
-                Checksum allowedChecksum = this->fAllowedChecksums[i];
-                if (allowedChecksum == actualChecksum) {
-                    return true;
-                }
-            }
-            return false;
-        }
+        bool match(Checksum actualChecksum) const;
 
         /**
          * If this Expectation is based on a single SkBitmap, return a
@@ -189,25 +121,14 @@ namespace skiagm {
         }
 
         /**
-         * Return a JSON representation of the allowed checksums.
-         * This does NOT include any information about whether to
-         * ignore failures.
+         * Return a JSON representation of the expectations.
          */
-        Json::Value allowedChecksumsAsJson() const {
-            Json::Value allowedChecksumArray;
-            if (!this->fAllowedChecksums.empty()) {
-                for (int i=0; i < this->fAllowedChecksums.count(); i++) {
-                    Checksum allowedChecksum = this->fAllowedChecksums[i];
-                    allowedChecksumArray.append(asJsonValue(allowedChecksum));
-                }
-            }
-            return allowedChecksumArray;
-        }
+        Json::Value asJsonValue() const;
 
     private:
         const static bool kDefaultIgnoreFailure = false;
 
-        SkTArray<Checksum> fAllowedChecksums;
+        SkTArray<Checksum> fAllowedBitmapCityhashes;
         bool fIgnoreFailure;
         SkBitmap fBitmap;
     };
@@ -234,21 +155,7 @@ namespace skiagm {
          */
         IndividualImageExpectationsSource(const char *rootDir) : fRootDir(rootDir) {}
 
-        Expectations get(const char *testName) SK_OVERRIDE {
-            SkString path = make_filename(fRootDir.c_str(), "", testName,
-                                          "png");
-            SkBitmap referenceBitmap;
-            bool decodedReferenceBitmap =
-                SkImageDecoder::DecodeFile(path.c_str(), &referenceBitmap,
-                                           SkBitmap::kARGB_8888_Config,
-                                           SkImageDecoder::kDecodePixels_Mode,
-                                           NULL);
-            if (decodedReferenceBitmap) {
-                return Expectations(referenceBitmap);
-            } else {
-                return Expectations();
-            }
-        }
+        Expectations get(const char *testName) SK_OVERRIDE ;
 
     private:
         const SkString fRootDir;
@@ -265,14 +172,9 @@ namespace skiagm {
          *
          * jsonPath: path to JSON file to read
          */
-        JsonExpectationsSource(const char *jsonPath) {
-            parse(jsonPath, &fJsonRoot);
-            fJsonExpectedResults = fJsonRoot[kJsonKey_ExpectedResults];
-        }
+        JsonExpectationsSource(const char *jsonPath);
 
-        Expectations get(const char *testName) SK_OVERRIDE {
-            return Expectations(fJsonExpectedResults[testName]);
-        }
+        Expectations get(const char *testName) SK_OVERRIDE;
 
     private:
 
@@ -307,23 +209,7 @@ namespace skiagm {
         // TODO(epoger): Move this, into SkStream.[cpp|h] as attempted in
         // https://codereview.appspot.com/7300071 ?
         // And maybe readFileIntoSkData() also?
-        static SkData* readIntoSkData(SkStream &stream, size_t maxBytes) {
-            if (0 == maxBytes) {
-                return SkData::NewEmpty();
-            }
-            char* bufStart = reinterpret_cast<char *>(sk_malloc_throw(maxBytes));
-            char* bufPtr = bufStart;
-            size_t bytesRemaining = maxBytes;
-            while (bytesRemaining > 0) {
-                size_t bytesReadThisTime = stream.read(bufPtr, bytesRemaining);
-                if (0 == bytesReadThisTime) {
-                    break;
-                }
-                bytesRemaining -= bytesReadThisTime;
-                bufPtr += bytesReadThisTime;
-            }
-            return SkData::NewFromMalloc(bufStart, maxBytes - bytesRemaining);
-        }
+        static SkData* readIntoSkData(SkStream &stream, size_t maxBytes);
 
         /**
          * Wrapper around readIntoSkData for files: reads the entire file into
@@ -338,31 +224,7 @@ namespace skiagm {
          *
          * Returns true if successful.
          */
-        static bool parse(const char *jsonPath, Json::Value *jsonRoot) {
-            SkFILEStream inFile(jsonPath);
-            if (!inFile.isValid()) {
-                gm_fprintf(stderr, "unable to read JSON file %s\n", jsonPath);
-                DEBUGFAIL_SEE_STDERR;
-                return false;
-            }
-
-            SkAutoDataUnref dataRef(readFileIntoSkData(inFile));
-            if (NULL == dataRef.get()) {
-                gm_fprintf(stderr, "error reading JSON file %s\n", jsonPath);
-                DEBUGFAIL_SEE_STDERR;
-                return false;
-            }
-
-            const char *bytes = reinterpret_cast<const char *>(dataRef.get()->data());
-            size_t size = dataRef.get()->size();
-            Json::Reader reader;
-            if (!reader.parse(bytes, bytes+size, *jsonRoot)) {
-                gm_fprintf(stderr, "error parsing JSON file %s\n", jsonPath);
-                DEBUGFAIL_SEE_STDERR;
-                return false;
-            }
-            return true;
-        }
+        static bool parse(const char *jsonPath, Json::Value *jsonRoot);
 
         Json::Value fJsonRoot;
         Json::Value fJsonExpectedResults;
index e68ec81..420b684 100644 (file)
@@ -63,6 +63,8 @@ class GrSurface;
 typedef int GLContextType;
 #endif
 
+#define DEBUGFAIL_SEE_STDERR SkDEBUGFAIL("see stderr for message")
+
 extern bool gSkSuppressFontCachePurgeSpew;
 
 #ifdef SK_SUPPORT_PDF
@@ -768,17 +770,15 @@ public:
 
     /**
      * Add this result to the appropriate JSON collection of actual results,
-     * depending on status.
+     * depending on errors encountered.
      */
     void add_actual_results_to_json_summary(const char testName[],
-                                            const SkHashDigest& actualBitmapHash,
-                                            ErrorCombination result,
+                                            const SkHashDigest& actualResult,
+                                            ErrorCombination errors,
                                             bool ignoreFailure) {
-        Json::Value actualResults;
-        actualResults[kJsonKey_ActualResults_AnyStatus_Checksum] =
-            asJsonValue(actualBitmapHash);
-        if (result.isEmpty()) {
-            this->fJsonActualResults_Succeeded[testName] = actualResults;
+        Json::Value jsonActualResults = ActualResultAsJsonValue(actualResult);
+        if (errors.isEmpty()) {
+            this->fJsonActualResults_Succeeded[testName] = jsonActualResults;
         } else {
             if (ignoreFailure) {
                 // TODO: Once we have added the ability to compare
@@ -788,9 +788,9 @@ public:
                 // failures (both for kMissingExpectations_ErrorType
                 // and kExpectationsMismatch_ErrorType).
                 this->fJsonActualResults_FailureIgnored[testName] =
-                    actualResults;
+                    jsonActualResults;
             } else {
-                if (result.includes(kMissingExpectations_ErrorType)) {
+                if (errors.includes(kMissingExpectations_ErrorType)) {
                     // TODO: What about the case where there IS an
                     // expected image hash digest, but that gm test
                     // doesn't actually run?  For now, those cases
@@ -803,11 +803,11 @@ public:
                     // (and add a test case for which an expectation
                     // is given but the test is never run).
                     this->fJsonActualResults_NoComparison[testName] =
-                        actualResults;
+                        jsonActualResults;
                 }
-                if (result.includes(kExpectationsMismatch_ErrorType) ||
-                    result.includes(kRenderModeMismatch_ErrorType)) {
-                    this->fJsonActualResults_Failed[testName] = actualResults;
+                if (errors.includes(kExpectationsMismatch_ErrorType) ||
+                    errors.includes(kRenderModeMismatch_ErrorType)) {
+                    this->fJsonActualResults_Failed[testName] = jsonActualResults;
                 }
             }
         }
@@ -818,15 +818,7 @@ public:
      */
     void add_expected_results_to_json_summary(const char testName[],
                                               Expectations expectations) {
-        // For now, we assume that this collection starts out empty and we
-        // just fill it in as we go; once gm accepts a JSON file as input,
-        // we'll have to change that.
-        Json::Value expectedResults;
-        expectedResults[kJsonKey_ExpectedResults_Checksums] =
-            expectations.allowedChecksumsAsJson();
-        expectedResults[kJsonKey_ExpectedResults_IgnoreFailure] =
-            expectations.ignoreFailure();
-        this->fJsonExpectedResults[testName] = expectedResults;
+        this->fJsonExpectedResults[testName] = expectations.asJsonValue();
     }
 
     /**
@@ -1959,18 +1951,10 @@ int tool_main(int argc, char** argv) {
 #endif
 
     if (FLAGS_writeJsonSummaryPath.count() == 1) {
-        Json::Value actualResults;
-        actualResults[kJsonKey_ActualResults_Failed] =
-            gmmain.fJsonActualResults_Failed;
-        actualResults[kJsonKey_ActualResults_FailureIgnored] =
-            gmmain.fJsonActualResults_FailureIgnored;
-        actualResults[kJsonKey_ActualResults_NoComparison] =
-            gmmain.fJsonActualResults_NoComparison;
-        actualResults[kJsonKey_ActualResults_Succeeded] =
-            gmmain.fJsonActualResults_Succeeded;
-        Json::Value root;
-        root[kJsonKey_ActualResults] = actualResults;
-        root[kJsonKey_ExpectedResults] = gmmain.fJsonExpectedResults;
+        Json::Value root = CreateJsonTree(
+            gmmain.fJsonExpectedResults,
+            gmmain.fJsonActualResults_Failed, gmmain.fJsonActualResults_FailureIgnored,
+            gmmain.fJsonActualResults_NoComparison, gmmain.fJsonActualResults_Succeeded);
         std::string jsonStdString = root.toStyledString();
         SkFILEWStream stream(FLAGS_writeJsonSummaryPath[0]);
         stream.write(jsonStdString.c_str(), jsonStdString.length());
index 4cfe151..5214f7a 100644 (file)
@@ -2,10 +2,10 @@
    "actual-results" : {
       "failed" : {
          "565/selftest1" : {
-            "checksum" : 9512553915271796906
+            "bitmap-cityhash" : 9512553915271796906
          },
          "8888/selftest1" : {
-            "checksum" : 14022967492765711532
+            "bitmap-cityhash" : 14022967492765711532
          }
       },
       "failure-ignored" : null,
    },
    "expected-results" : {
       "565/selftest1" : {
-         "checksums" : [ 11071285354315388429 ],
+         "allowed-bitmap-cityhashes" : [ 11071285354315388429 ],
          "ignore-failure" : false
       },
       "8888/selftest1" : {
-         "checksums" : [ 16527650414256125612 ],
+         "allowed-bitmap-cityhashes" : [ 16527650414256125612 ],
          "ignore-failure" : false
       }
    }
index 4cfe151..5214f7a 100644 (file)
@@ -2,10 +2,10 @@
    "actual-results" : {
       "failed" : {
          "565/selftest1" : {
-            "checksum" : 9512553915271796906
+            "bitmap-cityhash" : 9512553915271796906
          },
          "8888/selftest1" : {
-            "checksum" : 14022967492765711532
+            "bitmap-cityhash" : 14022967492765711532
          }
       },
       "failure-ignored" : null,
    },
    "expected-results" : {
       "565/selftest1" : {
-         "checksums" : [ 11071285354315388429 ],
+         "allowed-bitmap-cityhashes" : [ 11071285354315388429 ],
          "ignore-failure" : false
       },
       "8888/selftest1" : {
-         "checksums" : [ 16527650414256125612 ],
+         "allowed-bitmap-cityhashes" : [ 16527650414256125612 ],
          "ignore-failure" : false
       }
    }
index 69ef127..31892c9 100644 (file)
@@ -4,21 +4,21 @@
       "failure-ignored" : null,
       "no-comparison" : {
          "565/selftest1" : {
-            "checksum" : 9512553915271796906
+            "bitmap-cityhash" : 9512553915271796906
          },
          "8888/selftest1" : {
-            "checksum" : 14022967492765711532
+            "bitmap-cityhash" : 14022967492765711532
          }
       },
       "succeeded" : null
    },
    "expected-results" : {
       "565/selftest1" : {
-         "checksums" : null,
+         "allowed-bitmap-cityhashes" : null,
          "ignore-failure" : false
       },
       "8888/selftest1" : {
-         "checksums" : null,
+         "allowed-bitmap-cityhashes" : null,
          "ignore-failure" : false
       }
    }
index cfaf455..417e3d8 100644 (file)
@@ -5,20 +5,20 @@
       "no-comparison" : null,
       "succeeded" : {
          "565/selftest1" : {
-            "checksum" : 9512553915271796906
+            "bitmap-cityhash" : 9512553915271796906
          },
          "8888/selftest1" : {
-            "checksum" : 14022967492765711532
+            "bitmap-cityhash" : 14022967492765711532
          }
       }
    },
    "expected-results" : {
       "565/selftest1" : {
-         "checksums" : [ 9512553915271796906 ],
+         "allowed-bitmap-cityhashes" : [ 9512553915271796906 ],
          "ignore-failure" : false
       },
       "8888/selftest1" : {
-         "checksums" : [ 14022967492765711532 ],
+         "allowed-bitmap-cityhashes" : [ 14022967492765711532 ],
          "ignore-failure" : false
       }
    }
index cfaf455..417e3d8 100644 (file)
@@ -5,20 +5,20 @@
       "no-comparison" : null,
       "succeeded" : {
          "565/selftest1" : {
-            "checksum" : 9512553915271796906
+            "bitmap-cityhash" : 9512553915271796906
          },
          "8888/selftest1" : {
-            "checksum" : 14022967492765711532
+            "bitmap-cityhash" : 14022967492765711532
          }
       }
    },
    "expected-results" : {
       "565/selftest1" : {
-         "checksums" : [ 9512553915271796906 ],
+         "allowed-bitmap-cityhashes" : [ 9512553915271796906 ],
          "ignore-failure" : false
       },
       "8888/selftest1" : {
-         "checksums" : [ 14022967492765711532 ],
+         "allowed-bitmap-cityhashes" : [ 14022967492765711532 ],
          "ignore-failure" : false
       }
    }
index cfaf455..417e3d8 100644 (file)
@@ -5,20 +5,20 @@
       "no-comparison" : null,
       "succeeded" : {
          "565/selftest1" : {
-            "checksum" : 9512553915271796906
+            "bitmap-cityhash" : 9512553915271796906
          },
          "8888/selftest1" : {
-            "checksum" : 14022967492765711532
+            "bitmap-cityhash" : 14022967492765711532
          }
       }
    },
    "expected-results" : {
       "565/selftest1" : {
-         "checksums" : [ 9512553915271796906 ],
+         "allowed-bitmap-cityhashes" : [ 9512553915271796906 ],
          "ignore-failure" : false
       },
       "8888/selftest1" : {
-         "checksums" : [ 14022967492765711532 ],
+         "allowed-bitmap-cityhashes" : [ 14022967492765711532 ],
          "ignore-failure" : false
       }
    }
index cfaf455..417e3d8 100644 (file)
@@ -5,20 +5,20 @@
       "no-comparison" : null,
       "succeeded" : {
          "565/selftest1" : {
-            "checksum" : 9512553915271796906
+            "bitmap-cityhash" : 9512553915271796906
          },
          "8888/selftest1" : {
-            "checksum" : 14022967492765711532
+            "bitmap-cityhash" : 14022967492765711532
          }
       }
    },
    "expected-results" : {
       "565/selftest1" : {
-         "checksums" : [ 9512553915271796906 ],
+         "allowed-bitmap-cityhashes" : [ 9512553915271796906 ],
          "ignore-failure" : false
       },
       "8888/selftest1" : {
-         "checksums" : [ 14022967492765711532 ],
+         "allowed-bitmap-cityhashes" : [ 14022967492765711532 ],
          "ignore-failure" : false
       }
    }
index 4cfe151..5214f7a 100644 (file)
@@ -2,10 +2,10 @@
    "actual-results" : {
       "failed" : {
          "565/selftest1" : {
-            "checksum" : 9512553915271796906
+            "bitmap-cityhash" : 9512553915271796906
          },
          "8888/selftest1" : {
-            "checksum" : 14022967492765711532
+            "bitmap-cityhash" : 14022967492765711532
          }
       },
       "failure-ignored" : null,
    },
    "expected-results" : {
       "565/selftest1" : {
-         "checksums" : [ 11071285354315388429 ],
+         "allowed-bitmap-cityhashes" : [ 11071285354315388429 ],
          "ignore-failure" : false
       },
       "8888/selftest1" : {
-         "checksums" : [ 16527650414256125612 ],
+         "allowed-bitmap-cityhashes" : [ 16527650414256125612 ],
          "ignore-failure" : false
       }
    }
index a3ac39f..1ee2207 100644 (file)
@@ -4,16 +4,16 @@
       "failure-ignored" : null,
       "no-comparison" : {
          "565/selftest1" : {
-            "checksum" : 9512553915271796906
+            "bitmap-cityhash" : 9512553915271796906
          },
          "565/selftest2" : {
-            "checksum" : 11071285354315388429
+            "bitmap-cityhash" : 11071285354315388429
          },
          "8888/selftest1" : {
-            "checksum" : 14022967492765711532
+            "bitmap-cityhash" : 14022967492765711532
          },
          "8888/selftest2" : {
-            "checksum" : 16527650414256125612
+            "bitmap-cityhash" : 16527650414256125612
          }
       },
       "succeeded" : null
index 0e19ec1..c2325d0 100644 (file)
@@ -4,10 +4,10 @@
       "failure-ignored" : null,
       "no-comparison" : {
          "565/selftest1" : {
-            "checksum" : 9512553915271796906
+            "bitmap-cityhash" : 9512553915271796906
          },
          "8888/selftest1" : {
-            "checksum" : 14022967492765711532
+            "bitmap-cityhash" : 14022967492765711532
          }
       },
       "succeeded" : null
index 69ef127..31892c9 100644 (file)
@@ -4,21 +4,21 @@
       "failure-ignored" : null,
       "no-comparison" : {
          "565/selftest1" : {
-            "checksum" : 9512553915271796906
+            "bitmap-cityhash" : 9512553915271796906
          },
          "8888/selftest1" : {
-            "checksum" : 14022967492765711532
+            "bitmap-cityhash" : 14022967492765711532
          }
       },
       "succeeded" : null
    },
    "expected-results" : {
       "565/selftest1" : {
-         "checksums" : null,
+         "allowed-bitmap-cityhashes" : null,
          "ignore-failure" : false
       },
       "8888/selftest1" : {
-         "checksums" : null,
+         "allowed-bitmap-cityhashes" : null,
          "ignore-failure" : false
       }
    }
index 249fe09..54e0bde 100644 (file)
@@ -2,31 +2,31 @@
    "actual-results" : {
       "failed" : {
          "comparison/selftest1-pipe" : {
-            "checksum" : 4259036727585789440
+            "bitmap-cityhash" : 4259036727585789440
          }
       },
       "failure-ignored" : null,
       "no-comparison" : null,
       "succeeded" : {
          "565/selftest1" : {
-            "checksum" : 9512553915271796906
+            "bitmap-cityhash" : 9512553915271796906
          },
          "8888/selftest1" : {
-            "checksum" : 14022967492765711532
+            "bitmap-cityhash" : 14022967492765711532
          }
       }
    },
    "expected-results" : {
       "565/selftest1" : {
-         "checksums" : [ 9512553915271796906 ],
+         "allowed-bitmap-cityhashes" : [ 9512553915271796906 ],
          "ignore-failure" : false
       },
       "8888/selftest1" : {
-         "checksums" : [ 14022967492765711532 ],
+         "allowed-bitmap-cityhashes" : [ 14022967492765711532 ],
          "ignore-failure" : false
       },
       "comparison/selftest1-pipe" : {
-         "checksums" : [ 14022967492765711532 ],
+         "allowed-bitmap-cityhashes" : [ 14022967492765711532 ],
          "ignore-failure" : false
       }
    }
index 3458107..f0e466d 100644 (file)
@@ -26,6 +26,7 @@
         '../debugger/SkObjectParser.cpp',
 
         '../gm/gm.cpp',
+        '../gm/gm_expectations.cpp',
         '../gm/gmmain.cpp',
         '../gm/system_preferences_default.cpp',