summaryrefslogtreecommitdiffstats
path: root/chromium/third_party/skia/gm/gm_expectations.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/skia/gm/gm_expectations.cpp')
-rw-r--r--chromium/third_party/skia/gm/gm_expectations.cpp239
1 files changed, 239 insertions, 0 deletions
diff --git a/chromium/third_party/skia/gm/gm_expectations.cpp b/chromium/third_party/skia/gm/gm_expectations.cpp
new file mode 100644
index 00000000000..70890707cf1
--- /dev/null
+++ b/chromium/third_party/skia/gm/gm_expectations.cpp
@@ -0,0 +1,239 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ *
+ * TODO(epoger): Combine this with tools/image_expectations.cpp, or eliminate one of the two.
+ */
+
+#include "gm_expectations.h"
+#include "SkBitmapHasher.h"
+#include "SkData.h"
+#include "SkImageDecoder.h"
+
+#define DEBUGFAIL_SEE_STDERR SkDEBUGFAIL("see stderr for message")
+
+// See gm_json.py for descriptions of each of these JSON keys.
+// These constants must be kept in sync with the ones in that Python file!
+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_ExpectedResults[] = "expected-results";
+const static char kJsonKey_ExpectedResults_AllowedDigests[] = "allowed-digests";
+const static char kJsonKey_ExpectedResults_IgnoreFailure[] = "ignore-failure";
+
+// Types of result hashes we support in the JSON file.
+const static char kJsonKey_Hashtype_Bitmap_64bitMD5[] = "bitmap-64bitMD5";
+
+
+namespace skiagm {
+
+ 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;
+ }
+
+ // GmResultDigest class...
+
+ GmResultDigest::GmResultDigest(const SkBitmap &bitmap) {
+ fIsValid = SkBitmapHasher::ComputeDigest(bitmap, &fHashDigest);
+ }
+
+ GmResultDigest::GmResultDigest(const Json::Value &jsonTypeValuePair) {
+ fIsValid = false;
+ if (!jsonTypeValuePair.isArray()) {
+ SkDebugf("found non-array json value when parsing GmResultDigest: %s\n",
+ jsonTypeValuePair.toStyledString().c_str());
+ DEBUGFAIL_SEE_STDERR;
+ } else if (2 != jsonTypeValuePair.size()) {
+ SkDebugf("found json array with wrong size when parsing GmResultDigest: %s\n",
+ jsonTypeValuePair.toStyledString().c_str());
+ DEBUGFAIL_SEE_STDERR;
+ } else {
+ // TODO(epoger): The current implementation assumes that the
+ // result digest is always of type kJsonKey_Hashtype_Bitmap_64bitMD5
+ Json::Value jsonHashValue = jsonTypeValuePair[1];
+ if (!jsonHashValue.isIntegral()) {
+ SkDebugf("found non-integer jsonHashValue when parsing GmResultDigest: %s\n",
+ jsonTypeValuePair.toStyledString().c_str());
+ DEBUGFAIL_SEE_STDERR;
+ } else {
+ fHashDigest = jsonHashValue.asUInt64();
+ fIsValid = true;
+ }
+ }
+ }
+
+ bool GmResultDigest::isValid() const {
+ return fIsValid;
+ }
+
+ bool GmResultDigest::equals(const GmResultDigest &other) const {
+ // TODO(epoger): The current implementation assumes that this
+ // and other are always of type kJsonKey_Hashtype_Bitmap_64bitMD5
+ return (this->fIsValid && other.fIsValid && (this->fHashDigest == other.fHashDigest));
+ }
+
+ Json::Value GmResultDigest::asJsonTypeValuePair() const {
+ // TODO(epoger): The current implementation assumes that the
+ // result digest is always of type kJsonKey_Hashtype_Bitmap_64bitMD5
+ Json::Value jsonTypeValuePair;
+ if (fIsValid) {
+ jsonTypeValuePair.append(Json::Value(kJsonKey_Hashtype_Bitmap_64bitMD5));
+ jsonTypeValuePair.append(Json::UInt64(fHashDigest));
+ } else {
+ jsonTypeValuePair.append(Json::Value("INVALID"));
+ }
+ return jsonTypeValuePair;
+ }
+
+ SkString GmResultDigest::getHashType() const {
+ // TODO(epoger): The current implementation assumes that the
+ // result digest is always of type kJsonKey_Hashtype_Bitmap_64bitMD5
+ return SkString(kJsonKey_Hashtype_Bitmap_64bitMD5);
+ }
+
+ SkString GmResultDigest::getDigestValue() const {
+ // TODO(epoger): The current implementation assumes that the
+ // result digest is always of type kJsonKey_Hashtype_Bitmap_64bitMD5
+ SkString retval;
+ retval.appendU64(fHashDigest);
+ return retval;
+ }
+
+
+ // Expectations class...
+
+ Expectations::Expectations(bool ignoreFailure) {
+ fIgnoreFailure = ignoreFailure;
+ }
+
+ Expectations::Expectations(const SkBitmap& bitmap, bool ignoreFailure) {
+ fBitmap = bitmap;
+ fIgnoreFailure = ignoreFailure;
+ fAllowedResultDigests.push_back(GmResultDigest(bitmap));
+ }
+
+ Expectations::Expectations(const BitmapAndDigest& bitmapAndDigest) {
+ fBitmap = bitmapAndDigest.fBitmap;
+ fIgnoreFailure = false;
+ fAllowedResultDigests.push_back(bitmapAndDigest.fDigest);
+ }
+
+ 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()) {
+ SkDebugf("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 allowedDigests = jsonElement[kJsonKey_ExpectedResults_AllowedDigests];
+ if (allowedDigests.isNull()) {
+ // ok, we'll just assume there aren't any AllowedDigests to compare against
+ } else if (!allowedDigests.isArray()) {
+ SkDebugf("found non-array json value for key '%s' in element '%s'\n",
+ kJsonKey_ExpectedResults_AllowedDigests,
+ jsonElement.toStyledString().c_str());
+ DEBUGFAIL_SEE_STDERR;
+ } else {
+ for (Json::ArrayIndex i=0; i<allowedDigests.size(); i++) {
+ fAllowedResultDigests.push_back(GmResultDigest(allowedDigests[i]));
+ }
+ }
+ }
+ }
+
+ bool Expectations::match(GmResultDigest actualGmResultDigest) const {
+ for (int i=0; i < this->fAllowedResultDigests.count(); i++) {
+ GmResultDigest allowedResultDigest = this->fAllowedResultDigests[i];
+ if (allowedResultDigest.equals(actualGmResultDigest)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ Json::Value Expectations::asJsonValue() const {
+ Json::Value allowedDigestArray;
+ if (!this->fAllowedResultDigests.empty()) {
+ for (int i=0; i < this->fAllowedResultDigests.count(); i++) {
+ allowedDigestArray.append(this->fAllowedResultDigests[i].asJsonTypeValuePair());
+ }
+ }
+
+ Json::Value jsonExpectations;
+ jsonExpectations[kJsonKey_ExpectedResults_AllowedDigests] = allowedDigestArray;
+ jsonExpectations[kJsonKey_ExpectedResults_IgnoreFailure] = this->ignoreFailure();
+ return jsonExpectations;
+ }
+
+ // IndividualImageExpectationsSource class...
+
+ Expectations IndividualImageExpectationsSource::get(const char *testName) const {
+ SkString path = SkOSPath::SkPathJoin(fRootDir.c_str(), testName);
+ SkBitmap referenceBitmap;
+ bool decodedReferenceBitmap =
+ SkImageDecoder::DecodeFile(path.c_str(), &referenceBitmap, kN32_SkColorType,
+ 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) const {
+ return Expectations(fJsonExpectedResults[testName]);
+ }
+
+ /*static*/ bool JsonExpectationsSource::Parse(const char *jsonPath, Json::Value *jsonRoot) {
+ SkAutoDataUnref dataRef(SkData::NewFromFileName(jsonPath));
+ if (NULL == dataRef.get()) {
+ SkDebugf("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)) {
+ SkDebugf("error parsing JSON file %s\n", jsonPath);
+ DEBUGFAIL_SEE_STDERR;
+ return false;
+ }
+ return true;
+ }
+}