137269607334b99bf814c7dc6b426745d9b7c7e3fepoger@google.com/* 237269607334b99bf814c7dc6b426745d9b7c7e3fepoger@google.com * Copyright 2013 Google Inc. 337269607334b99bf814c7dc6b426745d9b7c7e3fepoger@google.com * 437269607334b99bf814c7dc6b426745d9b7c7e3fepoger@google.com * Use of this source code is governed by a BSD-style license that can be 537269607334b99bf814c7dc6b426745d9b7c7e3fepoger@google.com * found in the LICENSE file. 690c0fbd34947b6b644e90c5b2253752035f65b64commit-bot@chromium.org * 790c0fbd34947b6b644e90c5b2253752035f65b64commit-bot@chromium.org * TODO(epoger): Combine this with tools/image_expectations.h, or eliminate one of the two. 837269607334b99bf814c7dc6b426745d9b7c7e3fepoger@google.com */ 937269607334b99bf814c7dc6b426745d9b7c7e3fepoger@google.com#ifndef gm_expectations_DEFINED 1037269607334b99bf814c7dc6b426745d9b7c7e3fepoger@google.com#define gm_expectations_DEFINED 1137269607334b99bf814c7dc6b426745d9b7c7e3fepoger@google.com 1237269607334b99bf814c7dc6b426745d9b7c7e3fepoger@google.com#include "gm.h" 1384a1802b072d76657261eada3018955283ab29d2epoger@google.com#include "SkBitmap.h" 14908f5836626d792c5e33ad93f44c6a418a0cc8f5epoger@google.com#include "SkBitmapHasher.h" 15d271d245e97da5fef642c0f106abe3fd948c2270epoger@google.com#include "SkData.h" 16e3bb3bce3e9c1f3bc8ee779b1b3383c18e560bcecommit-bot@chromium.org#include "SkJSONCPP.h" 1737269607334b99bf814c7dc6b426745d9b7c7e3fepoger@google.com#include "SkOSFile.h" 1837269607334b99bf814c7dc6b426745d9b7c7e3fepoger@google.com#include "SkRefCnt.h" 19d271d245e97da5fef642c0f106abe3fd948c2270epoger@google.com#include "SkStream.h" 2037269607334b99bf814c7dc6b426745d9b7c7e3fepoger@google.com#include "SkTArray.h" 2137269607334b99bf814c7dc6b426745d9b7c7e3fepoger@google.com 2237269607334b99bf814c7dc6b426745d9b7c7e3fepoger@google.com 2337269607334b99bf814c7dc6b426745d9b7c7e3fepoger@google.comnamespace skiagm { 2437269607334b99bf814c7dc6b426745d9b7c7e3fepoger@google.com 2576c913db20de7ae1baa49ae66e943bf7f40781ccepoger@google.com Json::Value CreateJsonTree(Json::Value expectedResults, 2676c913db20de7ae1baa49ae66e943bf7f40781ccepoger@google.com Json::Value actualResultsFailed, 2776c913db20de7ae1baa49ae66e943bf7f40781ccepoger@google.com Json::Value actualResultsFailureIgnored, 2876c913db20de7ae1baa49ae66e943bf7f40781ccepoger@google.com Json::Value actualResultsNoComparison, 2976c913db20de7ae1baa49ae66e943bf7f40781ccepoger@google.com Json::Value actualResultsSucceeded); 3037269607334b99bf814c7dc6b426745d9b7c7e3fepoger@google.com /** 31d4993ff3605102036f83d5834d9a022d780e5488epoger@google.com * The digest of a GM test result. 32d4993ff3605102036f83d5834d9a022d780e5488epoger@google.com * 33d4993ff3605102036f83d5834d9a022d780e5488epoger@google.com * Currently, this is always a uint64_t hash digest of an SkBitmap... 34d4993ff3605102036f83d5834d9a022d780e5488epoger@google.com * but we will add other flavors soon. 35d4993ff3605102036f83d5834d9a022d780e5488epoger@google.com */ 36d4993ff3605102036f83d5834d9a022d780e5488epoger@google.com class GmResultDigest { 37d4993ff3605102036f83d5834d9a022d780e5488epoger@google.com public: 38d4993ff3605102036f83d5834d9a022d780e5488epoger@google.com /** 39d4993ff3605102036f83d5834d9a022d780e5488epoger@google.com * Create a ResultDigest representing an actual image result. 40d4993ff3605102036f83d5834d9a022d780e5488epoger@google.com */ 411d5bbb26cfe1c1d195c9525b42ff1bb7a49196b8commit-bot@chromium.org explicit GmResultDigest(const SkBitmap &bitmap); 42d4993ff3605102036f83d5834d9a022d780e5488epoger@google.com 43d4993ff3605102036f83d5834d9a022d780e5488epoger@google.com /** 44d4993ff3605102036f83d5834d9a022d780e5488epoger@google.com * Create a ResultDigest representing an allowed result 45d4993ff3605102036f83d5834d9a022d780e5488epoger@google.com * checksum within JSON expectations file, in the form 46d4993ff3605102036f83d5834d9a022d780e5488epoger@google.com * ["bitmap-64bitMD5", 12345]. 47d4993ff3605102036f83d5834d9a022d780e5488epoger@google.com */ 481d5bbb26cfe1c1d195c9525b42ff1bb7a49196b8commit-bot@chromium.org explicit GmResultDigest(const Json::Value &jsonTypeValuePair); 49d4993ff3605102036f83d5834d9a022d780e5488epoger@google.com 50d4993ff3605102036f83d5834d9a022d780e5488epoger@google.com /** 51d4993ff3605102036f83d5834d9a022d780e5488epoger@google.com * Returns true if this GmResultDigest was fully and successfully 52d4993ff3605102036f83d5834d9a022d780e5488epoger@google.com * created. 53d4993ff3605102036f83d5834d9a022d780e5488epoger@google.com */ 54d4993ff3605102036f83d5834d9a022d780e5488epoger@google.com bool isValid() const; 55d4993ff3605102036f83d5834d9a022d780e5488epoger@google.com 56d4993ff3605102036f83d5834d9a022d780e5488epoger@google.com /** 57d4993ff3605102036f83d5834d9a022d780e5488epoger@google.com * Returns true if this and other GmResultDigest could 58d4993ff3605102036f83d5834d9a022d780e5488epoger@google.com * represent identical results. 59d4993ff3605102036f83d5834d9a022d780e5488epoger@google.com */ 60d4993ff3605102036f83d5834d9a022d780e5488epoger@google.com bool equals(const GmResultDigest &other) const; 61d4993ff3605102036f83d5834d9a022d780e5488epoger@google.com 62d4993ff3605102036f83d5834d9a022d780e5488epoger@google.com /** 63d4993ff3605102036f83d5834d9a022d780e5488epoger@google.com * Returns a JSON type/value pair representing this result, 64d4993ff3605102036f83d5834d9a022d780e5488epoger@google.com * such as ["bitmap-64bitMD5", 12345]. 65d4993ff3605102036f83d5834d9a022d780e5488epoger@google.com */ 66d4993ff3605102036f83d5834d9a022d780e5488epoger@google.com Json::Value asJsonTypeValuePair() const; 67d4993ff3605102036f83d5834d9a022d780e5488epoger@google.com 686f7f14d061b045a58a888ee5450b4596797dc453epoger@google.com /** 696f7f14d061b045a58a888ee5450b4596797dc453epoger@google.com * Returns the hashtype, such as "bitmap-64bitMD5", as an SkString. 706f7f14d061b045a58a888ee5450b4596797dc453epoger@google.com */ 716f7f14d061b045a58a888ee5450b4596797dc453epoger@google.com SkString getHashType() const; 726f7f14d061b045a58a888ee5450b4596797dc453epoger@google.com 736f7f14d061b045a58a888ee5450b4596797dc453epoger@google.com /** 746f7f14d061b045a58a888ee5450b4596797dc453epoger@google.com * Returns the hash digest value, such as "12345", as an SkString. 756f7f14d061b045a58a888ee5450b4596797dc453epoger@google.com */ 766f7f14d061b045a58a888ee5450b4596797dc453epoger@google.com SkString getDigestValue() const; 776f7f14d061b045a58a888ee5450b4596797dc453epoger@google.com 78d4993ff3605102036f83d5834d9a022d780e5488epoger@google.com private: 79d4993ff3605102036f83d5834d9a022d780e5488epoger@google.com bool fIsValid; // always check this first--if it's false, other fields are meaningless 80d4993ff3605102036f83d5834d9a022d780e5488epoger@google.com uint64_t fHashDigest; 81d4993ff3605102036f83d5834d9a022d780e5488epoger@google.com }; 82d4993ff3605102036f83d5834d9a022d780e5488epoger@google.com 83d4993ff3605102036f83d5834d9a022d780e5488epoger@google.com /** 846f7f14d061b045a58a888ee5450b4596797dc453epoger@google.com * Encapsulates an SkBitmap and its GmResultDigest, guaranteed to keep them in sync. 856f7f14d061b045a58a888ee5450b4596797dc453epoger@google.com */ 866f7f14d061b045a58a888ee5450b4596797dc453epoger@google.com class BitmapAndDigest { 876f7f14d061b045a58a888ee5450b4596797dc453epoger@google.com public: 881d5bbb26cfe1c1d195c9525b42ff1bb7a49196b8commit-bot@chromium.org explicit BitmapAndDigest(const SkBitmap &bitmap) : fBitmap(bitmap), fDigest(bitmap) {} 896f7f14d061b045a58a888ee5450b4596797dc453epoger@google.com 906f7f14d061b045a58a888ee5450b4596797dc453epoger@google.com const SkBitmap fBitmap; 916f7f14d061b045a58a888ee5450b4596797dc453epoger@google.com const GmResultDigest fDigest; 926f7f14d061b045a58a888ee5450b4596797dc453epoger@google.com }; 936f7f14d061b045a58a888ee5450b4596797dc453epoger@google.com 946f7f14d061b045a58a888ee5450b4596797dc453epoger@google.com /** 95d4993ff3605102036f83d5834d9a022d780e5488epoger@google.com * Test expectations (allowed image results, etc.) 9637269607334b99bf814c7dc6b426745d9b7c7e3fepoger@google.com */ 9737269607334b99bf814c7dc6b426745d9b7c7e3fepoger@google.com class Expectations { 9837269607334b99bf814c7dc6b426745d9b7c7e3fepoger@google.com public: 9937269607334b99bf814c7dc6b426745d9b7c7e3fepoger@google.com /** 10037269607334b99bf814c7dc6b426745d9b7c7e3fepoger@google.com * No expectations at all. 10137269607334b99bf814c7dc6b426745d9b7c7e3fepoger@google.com */ 1021d5bbb26cfe1c1d195c9525b42ff1bb7a49196b8commit-bot@chromium.org explicit Expectations(bool ignoreFailure=kDefaultIgnoreFailure); 10337269607334b99bf814c7dc6b426745d9b7c7e3fepoger@google.com 10437269607334b99bf814c7dc6b426745d9b7c7e3fepoger@google.com /** 10584a1802b072d76657261eada3018955283ab29d2epoger@google.com * Expect exactly one image (appropriate for the case when we 10637269607334b99bf814c7dc6b426745d9b7c7e3fepoger@google.com * are comparing against a single PNG file). 10737269607334b99bf814c7dc6b426745d9b7c7e3fepoger@google.com */ 1085187c4313cd6b1dea82c43fa5af466576e4025f1scroggo@google.com explicit Expectations(const SkBitmap& bitmap, bool ignoreFailure=kDefaultIgnoreFailure); 1095187c4313cd6b1dea82c43fa5af466576e4025f1scroggo@google.com 1105187c4313cd6b1dea82c43fa5af466576e4025f1scroggo@google.com /** 1115187c4313cd6b1dea82c43fa5af466576e4025f1scroggo@google.com * Expect exactly one image, whose digest has already been computed. 1125187c4313cd6b1dea82c43fa5af466576e4025f1scroggo@google.com */ 1135187c4313cd6b1dea82c43fa5af466576e4025f1scroggo@google.com explicit Expectations(const BitmapAndDigest& bitmapAndDigest); 11437269607334b99bf814c7dc6b426745d9b7c7e3fepoger@google.com 11537269607334b99bf814c7dc6b426745d9b7c7e3fepoger@google.com /** 116d271d245e97da5fef642c0f106abe3fd948c2270epoger@google.com * Create Expectations from a JSON element as found within the 117d271d245e97da5fef642c0f106abe3fd948c2270epoger@google.com * kJsonKey_ExpectedResults section. 118d271d245e97da5fef642c0f106abe3fd948c2270epoger@google.com * 119d271d245e97da5fef642c0f106abe3fd948c2270epoger@google.com * It's fine if the jsonElement is null or empty; in that case, we just 120d271d245e97da5fef642c0f106abe3fd948c2270epoger@google.com * don't have any expectations. 121d271d245e97da5fef642c0f106abe3fd948c2270epoger@google.com */ 1221d5bbb26cfe1c1d195c9525b42ff1bb7a49196b8commit-bot@chromium.org explicit Expectations(Json::Value jsonElement); 123d271d245e97da5fef642c0f106abe3fd948c2270epoger@google.com 124d271d245e97da5fef642c0f106abe3fd948c2270epoger@google.com /** 12537269607334b99bf814c7dc6b426745d9b7c7e3fepoger@google.com * Returns true iff we want to ignore failed expectations. 12637269607334b99bf814c7dc6b426745d9b7c7e3fepoger@google.com */ 12737269607334b99bf814c7dc6b426745d9b7c7e3fepoger@google.com bool ignoreFailure() const { return this->fIgnoreFailure; } 12837269607334b99bf814c7dc6b426745d9b7c7e3fepoger@google.com 12937269607334b99bf814c7dc6b426745d9b7c7e3fepoger@google.com /** 130defc487aa9e6bef16f76846f286f8a1343524d45epoger@google.com * Override default setting of fIgnoreFailure. 131defc487aa9e6bef16f76846f286f8a1343524d45epoger@google.com */ 132defc487aa9e6bef16f76846f286f8a1343524d45epoger@google.com void setIgnoreFailure(bool val) { this->fIgnoreFailure = val; } 133defc487aa9e6bef16f76846f286f8a1343524d45epoger@google.com 134defc487aa9e6bef16f76846f286f8a1343524d45epoger@google.com /** 135d4993ff3605102036f83d5834d9a022d780e5488epoger@google.com * Returns true iff there are no allowed results. 13637269607334b99bf814c7dc6b426745d9b7c7e3fepoger@google.com */ 137d4993ff3605102036f83d5834d9a022d780e5488epoger@google.com bool empty() const { return this->fAllowedResultDigests.empty(); } 13837269607334b99bf814c7dc6b426745d9b7c7e3fepoger@google.com 13937269607334b99bf814c7dc6b426745d9b7c7e3fepoger@google.com /** 140d4993ff3605102036f83d5834d9a022d780e5488epoger@google.com * Returns true iff resultDigest matches any allowed result, 14137269607334b99bf814c7dc6b426745d9b7c7e3fepoger@google.com * regardless of fIgnoreFailure. (The caller can check 14237269607334b99bf814c7dc6b426745d9b7c7e3fepoger@google.com * that separately.) 14337269607334b99bf814c7dc6b426745d9b7c7e3fepoger@google.com */ 144d4993ff3605102036f83d5834d9a022d780e5488epoger@google.com bool match(GmResultDigest resultDigest) const; 14537269607334b99bf814c7dc6b426745d9b7c7e3fepoger@google.com 14637269607334b99bf814c7dc6b426745d9b7c7e3fepoger@google.com /** 14784a1802b072d76657261eada3018955283ab29d2epoger@google.com * If this Expectation is based on a single SkBitmap, return a 14884a1802b072d76657261eada3018955283ab29d2epoger@google.com * pointer to that SkBitmap. Otherwise (if the Expectation is 14984a1802b072d76657261eada3018955283ab29d2epoger@google.com * empty, or if it was based on a list of checksums rather 15084a1802b072d76657261eada3018955283ab29d2epoger@google.com * than a single bitmap), returns NULL. 15184a1802b072d76657261eada3018955283ab29d2epoger@google.com */ 15284a1802b072d76657261eada3018955283ab29d2epoger@google.com const SkBitmap *asBitmap() const { 153cba73780bbd12fd254229517aec04fcbf0b64b52commit-bot@chromium.org return (kUnknown_SkColorType == fBitmap.colorType()) ? NULL : &fBitmap; 15484a1802b072d76657261eada3018955283ab29d2epoger@google.com } 15584a1802b072d76657261eada3018955283ab29d2epoger@google.com 15684a1802b072d76657261eada3018955283ab29d2epoger@google.com /** 15776c913db20de7ae1baa49ae66e943bf7f40781ccepoger@google.com * Return a JSON representation of the expectations. 15837269607334b99bf814c7dc6b426745d9b7c7e3fepoger@google.com */ 15976c913db20de7ae1baa49ae66e943bf7f40781ccepoger@google.com Json::Value asJsonValue() const; 16037269607334b99bf814c7dc6b426745d9b7c7e3fepoger@google.com 16137269607334b99bf814c7dc6b426745d9b7c7e3fepoger@google.com private: 162d271d245e97da5fef642c0f106abe3fd948c2270epoger@google.com const static bool kDefaultIgnoreFailure = false; 163d271d245e97da5fef642c0f106abe3fd948c2270epoger@google.com 164d4993ff3605102036f83d5834d9a022d780e5488epoger@google.com SkTArray<GmResultDigest> fAllowedResultDigests; 16537269607334b99bf814c7dc6b426745d9b7c7e3fepoger@google.com bool fIgnoreFailure; 16684a1802b072d76657261eada3018955283ab29d2epoger@google.com SkBitmap fBitmap; 16737269607334b99bf814c7dc6b426745d9b7c7e3fepoger@google.com }; 16837269607334b99bf814c7dc6b426745d9b7c7e3fepoger@google.com 16937269607334b99bf814c7dc6b426745d9b7c7e3fepoger@google.com /** 17037269607334b99bf814c7dc6b426745d9b7c7e3fepoger@google.com * Abstract source of Expectations objects for individual tests. 17137269607334b99bf814c7dc6b426745d9b7c7e3fepoger@google.com */ 17237269607334b99bf814c7dc6b426745d9b7c7e3fepoger@google.com class ExpectationsSource : public SkRefCnt { 17337269607334b99bf814c7dc6b426745d9b7c7e3fepoger@google.com public: 174ef284a84f503adfd08ee52b5aee142c548698ea4commit-bot@chromium.org SK_DECLARE_INST_COUNT(ExpectationsSource) 175ef284a84f503adfd08ee52b5aee142c548698ea4commit-bot@chromium.org 1761d5bbb26cfe1c1d195c9525b42ff1bb7a49196b8commit-bot@chromium.org virtual Expectations get(const char *testName) const = 0; 177ef284a84f503adfd08ee52b5aee142c548698ea4commit-bot@chromium.org 178ef284a84f503adfd08ee52b5aee142c548698ea4commit-bot@chromium.org private: 179ef284a84f503adfd08ee52b5aee142c548698ea4commit-bot@chromium.org typedef SkRefCnt INHERITED; 18037269607334b99bf814c7dc6b426745d9b7c7e3fepoger@google.com }; 18137269607334b99bf814c7dc6b426745d9b7c7e3fepoger@google.com 18237269607334b99bf814c7dc6b426745d9b7c7e3fepoger@google.com /** 18337269607334b99bf814c7dc6b426745d9b7c7e3fepoger@google.com * Return Expectations based on individual image files on disk. 18437269607334b99bf814c7dc6b426745d9b7c7e3fepoger@google.com */ 18537269607334b99bf814c7dc6b426745d9b7c7e3fepoger@google.com class IndividualImageExpectationsSource : public ExpectationsSource { 18637269607334b99bf814c7dc6b426745d9b7c7e3fepoger@google.com public: 18737269607334b99bf814c7dc6b426745d9b7c7e3fepoger@google.com /** 18837269607334b99bf814c7dc6b426745d9b7c7e3fepoger@google.com * Create an ExpectationsSource that will return Expectations based on 18937269607334b99bf814c7dc6b426745d9b7c7e3fepoger@google.com * image files found within rootDir. 19037269607334b99bf814c7dc6b426745d9b7c7e3fepoger@google.com * 19137269607334b99bf814c7dc6b426745d9b7c7e3fepoger@google.com * rootDir: directory under which to look for image files 19237269607334b99bf814c7dc6b426745d9b7c7e3fepoger@google.com * (this string will be copied to storage within this object) 19337269607334b99bf814c7dc6b426745d9b7c7e3fepoger@google.com */ 1941d5bbb26cfe1c1d195c9525b42ff1bb7a49196b8commit-bot@chromium.org explicit IndividualImageExpectationsSource(const char *rootDir) : fRootDir(rootDir) {} 19537269607334b99bf814c7dc6b426745d9b7c7e3fepoger@google.com 1961d5bbb26cfe1c1d195c9525b42ff1bb7a49196b8commit-bot@chromium.org Expectations get(const char *testName) const SK_OVERRIDE ; 19737269607334b99bf814c7dc6b426745d9b7c7e3fepoger@google.com 19837269607334b99bf814c7dc6b426745d9b7c7e3fepoger@google.com private: 19937269607334b99bf814c7dc6b426745d9b7c7e3fepoger@google.com const SkString fRootDir; 20037269607334b99bf814c7dc6b426745d9b7c7e3fepoger@google.com }; 20137269607334b99bf814c7dc6b426745d9b7c7e3fepoger@google.com 202d271d245e97da5fef642c0f106abe3fd948c2270epoger@google.com /** 203d271d245e97da5fef642c0f106abe3fd948c2270epoger@google.com * Return Expectations based on JSON summary file. 204d271d245e97da5fef642c0f106abe3fd948c2270epoger@google.com */ 205d271d245e97da5fef642c0f106abe3fd948c2270epoger@google.com class JsonExpectationsSource : public ExpectationsSource { 206d271d245e97da5fef642c0f106abe3fd948c2270epoger@google.com public: 207d271d245e97da5fef642c0f106abe3fd948c2270epoger@google.com /** 208d271d245e97da5fef642c0f106abe3fd948c2270epoger@google.com * Create an ExpectationsSource that will return Expectations based on 209d271d245e97da5fef642c0f106abe3fd948c2270epoger@google.com * a JSON file. 210d271d245e97da5fef642c0f106abe3fd948c2270epoger@google.com * 211d271d245e97da5fef642c0f106abe3fd948c2270epoger@google.com * jsonPath: path to JSON file to read 212d271d245e97da5fef642c0f106abe3fd948c2270epoger@google.com */ 2131d5bbb26cfe1c1d195c9525b42ff1bb7a49196b8commit-bot@chromium.org explicit JsonExpectationsSource(const char *jsonPath); 214d271d245e97da5fef642c0f106abe3fd948c2270epoger@google.com 2151d5bbb26cfe1c1d195c9525b42ff1bb7a49196b8commit-bot@chromium.org Expectations get(const char *testName) const SK_OVERRIDE; 216d271d245e97da5fef642c0f106abe3fd948c2270epoger@google.com 217d271d245e97da5fef642c0f106abe3fd948c2270epoger@google.com private: 218d271d245e97da5fef642c0f106abe3fd948c2270epoger@google.com 219d271d245e97da5fef642c0f106abe3fd948c2270epoger@google.com /** 220d271d245e97da5fef642c0f106abe3fd948c2270epoger@google.com * Read the file contents from jsonPath and parse them into jsonRoot. 221d271d245e97da5fef642c0f106abe3fd948c2270epoger@google.com * 222d271d245e97da5fef642c0f106abe3fd948c2270epoger@google.com * Returns true if successful. 223d271d245e97da5fef642c0f106abe3fd948c2270epoger@google.com */ 2246843bdb7061364c100990e7e0feb3757fca08bb0scroggo@google.com static bool Parse(const char *jsonPath, Json::Value *jsonRoot); 225d271d245e97da5fef642c0f106abe3fd948c2270epoger@google.com 226d271d245e97da5fef642c0f106abe3fd948c2270epoger@google.com Json::Value fJsonRoot; 227d271d245e97da5fef642c0f106abe3fd948c2270epoger@google.com Json::Value fJsonExpectedResults; 228d271d245e97da5fef642c0f106abe3fd948c2270epoger@google.com }; 229d271d245e97da5fef642c0f106abe3fd948c2270epoger@google.com 23037269607334b99bf814c7dc6b426745d9b7c7e3fepoger@google.com} 23137269607334b99bf814c7dc6b426745d9b7c7e3fepoger@google.com#endif 232