From 37269607334b99bf814c7dc6b426745d9b7c7e3f Mon Sep 17 00:00:00 2001 From: "epoger@google.com" Date: Sat, 19 Jan 2013 04:21:27 +0000 Subject: re-land r7258 with fixes and tests BUG=http://code.google.com/p/skia/issues/detail?id=1079 TBR=reed Review URL: https://codereview.appspot.com/7132060 git-svn-id: http://skia.googlecode.com/svn/trunk@7291 2bbb7eff-a529-9590-31e7-b0007b416f81 --- gm/gm_expectations.h | 174 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 174 insertions(+) create mode 100644 gm/gm_expectations.h (limited to 'gm/gm_expectations.h') diff --git a/gm/gm_expectations.h b/gm/gm_expectations.h new file mode 100644 index 0000000000..59a0c1c697 --- /dev/null +++ b/gm/gm_expectations.h @@ -0,0 +1,174 @@ +/* + * Copyright 2013 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ +#ifndef gm_expectations_DEFINED +#define gm_expectations_DEFINED + +#include "gm.h" +#include "SkBitmapChecksummer.h" +#include "SkImageDecoder.h" +#include "SkOSFile.h" +#include "SkRefCnt.h" +#include "SkTArray.h" + +#ifdef SK_BUILD_FOR_WIN + // json includes xlocale which generates warning 4530 because we're compiling without + // exceptions; see https://code.google.com/p/skia/issues/detail?id=1067 + #pragma warning(push) + #pragma warning(disable : 4530) +#endif +#include "json/value.h" +#ifdef SK_BUILD_FOR_WIN + #pragma warning(pop) +#endif + +namespace skiagm { + + // The actual type we use to represent a checksum is hidden in here. + typedef Json::UInt64 Checksum; + static inline Json::Value asJsonValue(Checksum checksum) { + return checksum; + } + + static SkString make_filename(const char path[], + const char renderModeDescriptor[], + const char *name, + const char suffix[]) { + SkString filename(path); + if (filename.endsWith(SkPATH_SEPARATOR)) { + filename.remove(filename.size() - 1, 1); + } + filename.appendf("%c%s%s.%s", SkPATH_SEPARATOR, + name, renderModeDescriptor, suffix); + return filename; + } + + /** + * Test expectations (allowed image checksums, etc.) + */ + class Expectations { + public: + /** + * No expectations at all. + * + * We set ignoreFailure to false by default, but it doesn't really + * matter... the result will always be "no-comparison" anyway. + */ + Expectations(bool ignoreFailure=false) { + fIgnoreFailure = ignoreFailure; + } + + /** + * Allow exactly one checksum (appropriate for the case when we + * are comparing against a single PNG file). + * + * By default, DO NOT ignore failures. + */ + Expectations(Checksum singleChecksum, bool ignoreFailure=false) { + fIgnoreFailure = ignoreFailure; + fAllowedChecksums.push_back() = singleChecksum; + } + + /** + * Returns true iff we want to ignore failed expectations. + */ + bool ignoreFailure() const { return this->fIgnoreFailure; } + + /** + * Returns true iff there are no allowed checksums. + */ + bool empty() const { return this->fAllowedChecksums.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; + } + + /** + * Return a JSON representation of the allowed checksums. + * This does NOT include any information about whether to + * ignore failures. + */ + 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; + } + + private: + SkTArray fAllowedChecksums; + bool fIgnoreFailure; + }; + + /** + * Abstract source of Expectations objects for individual tests. + */ + class ExpectationsSource : public SkRefCnt { + public: + virtual Expectations get(const char *testName) = 0; + }; + + /** + * Return Expectations based on individual image files on disk. + */ + class IndividualImageExpectationsSource : public ExpectationsSource { + public: + /** + * Create an ExpectationsSource that will return Expectations based on + * image files found within rootDir. + * + * rootDir: directory under which to look for image files + * (this string will be copied to storage within this object) + * notifyOfMissingFiles: whether to log a message to stderr if an image + * file cannot be found + */ + IndividualImageExpectationsSource(const char *rootDir, + bool notifyOfMissingFiles) : + fRootDir(rootDir), fNotifyOfMissingFiles(notifyOfMissingFiles) {} + + 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) { + Checksum checksum = SkBitmapChecksummer::Compute64( + referenceBitmap); + return Expectations(checksum); + } else { + if (fNotifyOfMissingFiles) { + fprintf(stderr, "FAILED to read %s\n", path.c_str()); + } + return Expectations(); + } + } + + private: + const SkString fRootDir; + const bool fNotifyOfMissingFiles; + }; + +} +#endif -- cgit v1.2.3