| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2013 Google Inc. | 2 * Copyright 2013 Google Inc. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 * | 6 * |
| 7 * TODO(epoger): Combine this with tools/image_expectations.cpp, or eliminate on
e of the two. | 7 * TODO(epoger): Combine this with tools/image_expectations.cpp, or eliminate on
e of the two. |
| 8 */ | 8 */ |
| 9 | 9 |
| 10 #include "gm_expectations.h" | 10 #include "gm_expectations.h" |
| (...skipping 13 matching lines...) Expand all Loading... |
| 24 const static char kJsonKey_ExpectedResults[] = "expected-results"; | 24 const static char kJsonKey_ExpectedResults[] = "expected-results"; |
| 25 const static char kJsonKey_ExpectedResults_AllowedDigests[] = "allowed-digests"; | 25 const static char kJsonKey_ExpectedResults_AllowedDigests[] = "allowed-digests"; |
| 26 const static char kJsonKey_ExpectedResults_IgnoreFailure[] = "ignore-failure"; | 26 const static char kJsonKey_ExpectedResults_IgnoreFailure[] = "ignore-failure"; |
| 27 | 27 |
| 28 // Types of result hashes we support in the JSON file. | 28 // Types of result hashes we support in the JSON file. |
| 29 const static char kJsonKey_Hashtype_Bitmap_64bitMD5[] = "bitmap-64bitMD5"; | 29 const static char kJsonKey_Hashtype_Bitmap_64bitMD5[] = "bitmap-64bitMD5"; |
| 30 | 30 |
| 31 | 31 |
| 32 namespace skiagm { | 32 namespace skiagm { |
| 33 | 33 |
| 34 #ifdef SK_BUILD_JSON_WRITER |
| 34 Json::Value CreateJsonTree(Json::Value expectedResults, | 35 Json::Value CreateJsonTree(Json::Value expectedResults, |
| 35 Json::Value actualResultsFailed, | 36 Json::Value actualResultsFailed, |
| 36 Json::Value actualResultsFailureIgnored, | 37 Json::Value actualResultsFailureIgnored, |
| 37 Json::Value actualResultsNoComparison, | 38 Json::Value actualResultsNoComparison, |
| 38 Json::Value actualResultsSucceeded) { | 39 Json::Value actualResultsSucceeded) { |
| 39 Json::Value actualResults; | 40 Json::Value actualResults; |
| 40 actualResults[kJsonKey_ActualResults_Failed] = actualResultsFailed; | 41 actualResults[kJsonKey_ActualResults_Failed] = actualResultsFailed; |
| 41 actualResults[kJsonKey_ActualResults_FailureIgnored] = actualResultsFail
ureIgnored; | 42 actualResults[kJsonKey_ActualResults_FailureIgnored] = actualResultsFail
ureIgnored; |
| 42 actualResults[kJsonKey_ActualResults_NoComparison] = actualResultsNoComp
arison; | 43 actualResults[kJsonKey_ActualResults_NoComparison] = actualResultsNoComp
arison; |
| 43 actualResults[kJsonKey_ActualResults_Succeeded] = actualResultsSucceeded
; | 44 actualResults[kJsonKey_ActualResults_Succeeded] = actualResultsSucceeded
; |
| 44 Json::Value root; | 45 Json::Value root; |
| 45 root[kJsonKey_ActualResults] = actualResults; | 46 root[kJsonKey_ActualResults] = actualResults; |
| 46 root[kJsonKey_ExpectedResults] = expectedResults; | 47 root[kJsonKey_ExpectedResults] = expectedResults; |
| 47 return root; | 48 return root; |
| 48 } | 49 } |
| 49 | 50 #endif |
| 50 | 51 |
| 51 // GmResultDigest class... | 52 // GmResultDigest class... |
| 52 | 53 |
| 53 GmResultDigest::GmResultDigest(const SkBitmap &bitmap) { | 54 GmResultDigest::GmResultDigest(const SkBitmap &bitmap) { |
| 54 fIsValid = SkBitmapHasher::ComputeDigest(bitmap, &fHashDigest); | 55 fIsValid = SkBitmapHasher::ComputeDigest(bitmap, &fHashDigest); |
| 55 } | 56 } |
| 56 | 57 |
| 58 #ifdef SK_BUILD_JSON_WRITER |
| 57 GmResultDigest::GmResultDigest(const Json::Value &jsonTypeValuePair) { | 59 GmResultDigest::GmResultDigest(const Json::Value &jsonTypeValuePair) { |
| 58 fIsValid = false; | 60 fIsValid = false; |
| 59 if (!jsonTypeValuePair.isArray()) { | 61 if (!jsonTypeValuePair.isArray()) { |
| 60 SkDebugf("found non-array json value when parsing GmResultDigest: %s
\n", | 62 SkDebugf("found non-array json value when parsing GmResultDigest: %s
\n", |
| 61 jsonTypeValuePair.toStyledString().c_str()); | 63 jsonTypeValuePair.toStyledString().c_str()); |
| 62 DEBUGFAIL_SEE_STDERR; | 64 DEBUGFAIL_SEE_STDERR; |
| 63 } else if (2 != jsonTypeValuePair.size()) { | 65 } else if (2 != jsonTypeValuePair.size()) { |
| 64 SkDebugf("found json array with wrong size when parsing GmResultDige
st: %s\n", | 66 SkDebugf("found json array with wrong size when parsing GmResultDige
st: %s\n", |
| 65 jsonTypeValuePair.toStyledString().c_str()); | 67 jsonTypeValuePair.toStyledString().c_str()); |
| 66 DEBUGFAIL_SEE_STDERR; | 68 DEBUGFAIL_SEE_STDERR; |
| 67 } else { | 69 } else { |
| 68 // TODO(epoger): The current implementation assumes that the | 70 // TODO(epoger): The current implementation assumes that the |
| 69 // result digest is always of type kJsonKey_Hashtype_Bitmap_64bitMD5 | 71 // result digest is always of type kJsonKey_Hashtype_Bitmap_64bitMD5 |
| 70 Json::Value jsonHashValue = jsonTypeValuePair[1]; | 72 Json::Value jsonHashValue = jsonTypeValuePair[1]; |
| 71 if (!jsonHashValue.isIntegral()) { | 73 if (!jsonHashValue.isIntegral()) { |
| 72 SkDebugf("found non-integer jsonHashValue when parsing GmResultD
igest: %s\n", | 74 SkDebugf("found non-integer jsonHashValue when parsing GmResultD
igest: %s\n", |
| 73 jsonTypeValuePair.toStyledString().c_str()); | 75 jsonTypeValuePair.toStyledString().c_str()); |
| 74 DEBUGFAIL_SEE_STDERR; | 76 DEBUGFAIL_SEE_STDERR; |
| 75 } else { | 77 } else { |
| 76 fHashDigest = jsonHashValue.asUInt64(); | 78 fHashDigest = jsonHashValue.asUInt64(); |
| 77 fIsValid = true; | 79 fIsValid = true; |
| 78 } | 80 } |
| 79 } | 81 } |
| 80 } | 82 } |
| 83 #endif |
| 81 | 84 |
| 82 bool GmResultDigest::isValid() const { | 85 bool GmResultDigest::isValid() const { |
| 83 return fIsValid; | 86 return fIsValid; |
| 84 } | 87 } |
| 85 | 88 |
| 86 bool GmResultDigest::equals(const GmResultDigest &other) const { | 89 bool GmResultDigest::equals(const GmResultDigest &other) const { |
| 87 // TODO(epoger): The current implementation assumes that this | 90 // TODO(epoger): The current implementation assumes that this |
| 88 // and other are always of type kJsonKey_Hashtype_Bitmap_64bitMD5 | 91 // and other are always of type kJsonKey_Hashtype_Bitmap_64bitMD5 |
| 89 return (this->fIsValid && other.fIsValid && (this->fHashDigest == other.
fHashDigest)); | 92 return (this->fIsValid && other.fIsValid && (this->fHashDigest == other.
fHashDigest)); |
| 90 } | 93 } |
| 91 | 94 |
| 95 #ifdef SK_BUILD_JSON_WRITER |
| 92 Json::Value GmResultDigest::asJsonTypeValuePair() const { | 96 Json::Value GmResultDigest::asJsonTypeValuePair() const { |
| 93 // TODO(epoger): The current implementation assumes that the | 97 // TODO(epoger): The current implementation assumes that the |
| 94 // result digest is always of type kJsonKey_Hashtype_Bitmap_64bitMD5 | 98 // result digest is always of type kJsonKey_Hashtype_Bitmap_64bitMD5 |
| 95 Json::Value jsonTypeValuePair; | 99 Json::Value jsonTypeValuePair; |
| 96 if (fIsValid) { | 100 if (fIsValid) { |
| 97 jsonTypeValuePair.append(Json::Value(kJsonKey_Hashtype_Bitmap_64bitM
D5)); | 101 jsonTypeValuePair.append(Json::Value(kJsonKey_Hashtype_Bitmap_64bitM
D5)); |
| 98 jsonTypeValuePair.append(Json::UInt64(fHashDigest)); | 102 jsonTypeValuePair.append(Json::UInt64(fHashDigest)); |
| 99 } else { | 103 } else { |
| 100 jsonTypeValuePair.append(Json::Value("INVALID")); | 104 jsonTypeValuePair.append(Json::Value("INVALID")); |
| 101 } | 105 } |
| 102 return jsonTypeValuePair; | 106 return jsonTypeValuePair; |
| 103 } | 107 } |
| 108 #endif |
| 104 | 109 |
| 105 SkString GmResultDigest::getHashType() const { | 110 SkString GmResultDigest::getHashType() const { |
| 106 // TODO(epoger): The current implementation assumes that the | 111 // TODO(epoger): The current implementation assumes that the |
| 107 // result digest is always of type kJsonKey_Hashtype_Bitmap_64bitMD5 | 112 // result digest is always of type kJsonKey_Hashtype_Bitmap_64bitMD5 |
| 108 return SkString(kJsonKey_Hashtype_Bitmap_64bitMD5); | 113 return SkString(kJsonKey_Hashtype_Bitmap_64bitMD5); |
| 109 } | 114 } |
| 110 | 115 |
| 111 SkString GmResultDigest::getDigestValue() const { | 116 SkString GmResultDigest::getDigestValue() const { |
| 112 // TODO(epoger): The current implementation assumes that the | 117 // TODO(epoger): The current implementation assumes that the |
| 113 // result digest is always of type kJsonKey_Hashtype_Bitmap_64bitMD5 | 118 // result digest is always of type kJsonKey_Hashtype_Bitmap_64bitMD5 |
| (...skipping 14 matching lines...) Expand all Loading... |
| 128 fIgnoreFailure = ignoreFailure; | 133 fIgnoreFailure = ignoreFailure; |
| 129 fAllowedResultDigests.push_back(GmResultDigest(bitmap)); | 134 fAllowedResultDigests.push_back(GmResultDigest(bitmap)); |
| 130 } | 135 } |
| 131 | 136 |
| 132 Expectations::Expectations(const BitmapAndDigest& bitmapAndDigest) { | 137 Expectations::Expectations(const BitmapAndDigest& bitmapAndDigest) { |
| 133 fBitmap = bitmapAndDigest.fBitmap; | 138 fBitmap = bitmapAndDigest.fBitmap; |
| 134 fIgnoreFailure = false; | 139 fIgnoreFailure = false; |
| 135 fAllowedResultDigests.push_back(bitmapAndDigest.fDigest); | 140 fAllowedResultDigests.push_back(bitmapAndDigest.fDigest); |
| 136 } | 141 } |
| 137 | 142 |
| 143 #ifdef SK_BUILD_JSON_WRITER |
| 138 Expectations::Expectations(Json::Value jsonElement) { | 144 Expectations::Expectations(Json::Value jsonElement) { |
| 139 if (jsonElement.empty()) { | 145 if (jsonElement.empty()) { |
| 140 fIgnoreFailure = kDefaultIgnoreFailure; | 146 fIgnoreFailure = kDefaultIgnoreFailure; |
| 141 } else { | 147 } else { |
| 142 Json::Value ignoreFailure = jsonElement[kJsonKey_ExpectedResults_Ign
oreFailure]; | 148 Json::Value ignoreFailure = jsonElement[kJsonKey_ExpectedResults_Ign
oreFailure]; |
| 143 if (ignoreFailure.isNull()) { | 149 if (ignoreFailure.isNull()) { |
| 144 fIgnoreFailure = kDefaultIgnoreFailure; | 150 fIgnoreFailure = kDefaultIgnoreFailure; |
| 145 } else if (!ignoreFailure.isBool()) { | 151 } else if (!ignoreFailure.isBool()) { |
| 146 SkDebugf("found non-boolean json value for key '%s' in element '
%s'\n", | 152 SkDebugf("found non-boolean json value for key '%s' in element '
%s'\n", |
| 147 kJsonKey_ExpectedResults_IgnoreFailure, | 153 kJsonKey_ExpectedResults_IgnoreFailure, |
| (...skipping 12 matching lines...) Expand all Loading... |
| 160 kJsonKey_ExpectedResults_AllowedDigests, | 166 kJsonKey_ExpectedResults_AllowedDigests, |
| 161 jsonElement.toStyledString().c_str()); | 167 jsonElement.toStyledString().c_str()); |
| 162 DEBUGFAIL_SEE_STDERR; | 168 DEBUGFAIL_SEE_STDERR; |
| 163 } else { | 169 } else { |
| 164 for (Json::ArrayIndex i=0; i<allowedDigests.size(); i++) { | 170 for (Json::ArrayIndex i=0; i<allowedDigests.size(); i++) { |
| 165 fAllowedResultDigests.push_back(GmResultDigest(allowedDigest
s[i])); | 171 fAllowedResultDigests.push_back(GmResultDigest(allowedDigest
s[i])); |
| 166 } | 172 } |
| 167 } | 173 } |
| 168 } | 174 } |
| 169 } | 175 } |
| 176 #endif |
| 170 | 177 |
| 171 bool Expectations::match(GmResultDigest actualGmResultDigest) const { | 178 bool Expectations::match(GmResultDigest actualGmResultDigest) const { |
| 172 for (int i=0; i < this->fAllowedResultDigests.count(); i++) { | 179 for (int i=0; i < this->fAllowedResultDigests.count(); i++) { |
| 173 GmResultDigest allowedResultDigest = this->fAllowedResultDigests[i]; | 180 GmResultDigest allowedResultDigest = this->fAllowedResultDigests[i]; |
| 174 if (allowedResultDigest.equals(actualGmResultDigest)) { | 181 if (allowedResultDigest.equals(actualGmResultDigest)) { |
| 175 return true; | 182 return true; |
| 176 } | 183 } |
| 177 } | 184 } |
| 178 return false; | 185 return false; |
| 179 } | 186 } |
| 180 | 187 |
| 188 #ifdef SK_BUILD_JSON_WRITER |
| 181 Json::Value Expectations::asJsonValue() const { | 189 Json::Value Expectations::asJsonValue() const { |
| 182 Json::Value allowedDigestArray; | 190 Json::Value allowedDigestArray; |
| 183 if (!this->fAllowedResultDigests.empty()) { | 191 if (!this->fAllowedResultDigests.empty()) { |
| 184 for (int i=0; i < this->fAllowedResultDigests.count(); i++) { | 192 for (int i=0; i < this->fAllowedResultDigests.count(); i++) { |
| 185 allowedDigestArray.append(this->fAllowedResultDigests[i].asJsonT
ypeValuePair()); | 193 allowedDigestArray.append(this->fAllowedResultDigests[i].asJsonT
ypeValuePair()); |
| 186 } | 194 } |
| 187 } | 195 } |
| 188 | 196 |
| 189 Json::Value jsonExpectations; | 197 Json::Value jsonExpectations; |
| 190 jsonExpectations[kJsonKey_ExpectedResults_AllowedDigests] = allowedDiges
tArray; | 198 jsonExpectations[kJsonKey_ExpectedResults_AllowedDigests] = allowedDiges
tArray; |
| 191 jsonExpectations[kJsonKey_ExpectedResults_IgnoreFailure] = this->ignore
Failure(); | 199 jsonExpectations[kJsonKey_ExpectedResults_IgnoreFailure] = this->ignore
Failure(); |
| 192 return jsonExpectations; | 200 return jsonExpectations; |
| 193 } | 201 } |
| 194 | 202 #endif |
| 195 | 203 |
| 196 // IndividualImageExpectationsSource class... | 204 // IndividualImageExpectationsSource class... |
| 197 | 205 |
| 198 Expectations IndividualImageExpectationsSource::get(const char *testName) co
nst { | 206 Expectations IndividualImageExpectationsSource::get(const char *testName) co
nst { |
| 199 SkString path = SkOSPath::SkPathJoin(fRootDir.c_str(), testName); | 207 SkString path = SkOSPath::SkPathJoin(fRootDir.c_str(), testName); |
| 200 SkBitmap referenceBitmap; | 208 SkBitmap referenceBitmap; |
| 201 bool decodedReferenceBitmap = | 209 bool decodedReferenceBitmap = |
| 202 SkImageDecoder::DecodeFile(path.c_str(), &referenceBitmap, | 210 SkImageDecoder::DecodeFile(path.c_str(), &referenceBitmap, |
| 203 SkBitmap::kARGB_8888_Config, | 211 SkBitmap::kARGB_8888_Config, |
| 204 SkImageDecoder::kDecodePixels_Mode, | 212 SkImageDecoder::kDecodePixels_Mode, |
| 205 NULL); | 213 NULL); |
| 206 if (decodedReferenceBitmap) { | 214 if (decodedReferenceBitmap) { |
| 207 return Expectations(referenceBitmap); | 215 return Expectations(referenceBitmap); |
| 208 } else { | 216 } else { |
| 209 return Expectations(); | 217 return Expectations(); |
| 210 } | 218 } |
| 211 } | 219 } |
| 212 | 220 |
| 213 | 221 |
| 222 #ifdef SK_BUILD_JSON_WRITER |
| 214 // JsonExpectationsSource class... | 223 // JsonExpectationsSource class... |
| 215 | 224 |
| 216 JsonExpectationsSource::JsonExpectationsSource(const char *jsonPath) { | 225 JsonExpectationsSource::JsonExpectationsSource(const char *jsonPath) { |
| 217 Parse(jsonPath, &fJsonRoot); | 226 Parse(jsonPath, &fJsonRoot); |
| 218 fJsonExpectedResults = fJsonRoot[kJsonKey_ExpectedResults]; | 227 fJsonExpectedResults = fJsonRoot[kJsonKey_ExpectedResults]; |
| 219 } | 228 } |
| 220 | 229 |
| 221 Expectations JsonExpectationsSource::get(const char *testName) const { | 230 Expectations JsonExpectationsSource::get(const char *testName) const { |
| 222 return Expectations(fJsonExpectedResults[testName]); | 231 return Expectations(fJsonExpectedResults[testName]); |
| 223 } | 232 } |
| 224 | 233 |
| 225 /*static*/ bool JsonExpectationsSource::Parse(const char *jsonPath, Json::Va
lue *jsonRoot) { | 234 /*static*/ bool JsonExpectationsSource::Parse(const char *jsonPath, Json::Va
lue *jsonRoot) { |
| 226 SkAutoDataUnref dataRef(SkData::NewFromFileName(jsonPath)); | 235 SkAutoDataUnref dataRef(SkData::NewFromFileName(jsonPath)); |
| 227 if (NULL == dataRef.get()) { | 236 if (NULL == dataRef.get()) { |
| 228 SkDebugf("error reading JSON file %s\n", jsonPath); | 237 SkDebugf("error reading JSON file %s\n", jsonPath); |
| 229 DEBUGFAIL_SEE_STDERR; | 238 DEBUGFAIL_SEE_STDERR; |
| 230 return false; | 239 return false; |
| 231 } | 240 } |
| 232 | 241 |
| 233 const char *bytes = reinterpret_cast<const char *>(dataRef.get()->data()
); | 242 const char *bytes = reinterpret_cast<const char *>(dataRef.get()->data()
); |
| 234 size_t size = dataRef.get()->size(); | 243 size_t size = dataRef.get()->size(); |
| 235 Json::Reader reader; | 244 Json::Reader reader; |
| 236 if (!reader.parse(bytes, bytes+size, *jsonRoot)) { | 245 if (!reader.parse(bytes, bytes+size, *jsonRoot)) { |
| 237 SkDebugf("error parsing JSON file %s\n", jsonPath); | 246 SkDebugf("error parsing JSON file %s\n", jsonPath); |
| 238 DEBUGFAIL_SEE_STDERR; | 247 DEBUGFAIL_SEE_STDERR; |
| 239 return false; | 248 return false; |
| 240 } | 249 } |
| 241 return true; | 250 return true; |
| 242 } | 251 } |
| 243 | 252 #endif |
| 244 } | 253 } |
| OLD | NEW |