diff options
Diffstat (limited to 'chromium/third_party/skia/gm/gm_expectations.cpp')
-rw-r--r-- | chromium/third_party/skia/gm/gm_expectations.cpp | 239 |
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; + } +} |