| Index: gm/gm_expectations.cpp
|
| ===================================================================
|
| --- gm/gm_expectations.cpp (revision 0)
|
| +++ gm/gm_expectations.cpp (revision 0)
|
| @@ -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;
|
| + }
|
| +
|
| +}
|
|
|