Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 /* | |
| 2 * Copyright 2013 Google Inc. | |
| 3 * | |
| 4 * Use of this source code is governed by a BSD-style license that can be | |
| 5 * found in the LICENSE file. | |
| 6 */ | |
| 7 | |
| 8 #include "gm_expectations.h" | |
| 9 #include "SkBitmapHasher.h" | |
| 10 #include "SkImageDecoder.h" | |
| 11 | |
| 12 #define DEBUGFAIL_SEE_STDERR SkDEBUGFAIL("see stderr for message") | |
| 13 | |
| 14 const static char kJsonKey_ActualResults[] = "actual-results"; | |
|
epoger
2013/04/25 19:17:42
patchset 3 moves all the json field names into gm_
| |
| 15 const static char kJsonKey_ActualResults_Failed[] = "failed"; | |
| 16 const static char kJsonKey_ActualResults_FailureIgnored[]= "failure-ignored"; | |
| 17 const static char kJsonKey_ActualResults_NoComparison[] = "no-comparison"; | |
| 18 const static char kJsonKey_ActualResults_Succeeded[] = "succeeded"; | |
| 19 const static char kJsonKey_ActualResults_AnyStatus_BitmapCityhash[] = "bitmap-c ityhash"; | |
| 20 | |
| 21 const static char kJsonKey_ExpectedResults[] = "expected-results"; | |
| 22 const static char kJsonKey_ExpectedResults_AllowedBitmapCityhashes[] = "allowed- bitmap-cityhashes"; | |
| 23 const static char kJsonKey_ExpectedResults_IgnoreFailure[] = "ignore-f ailure"; | |
| 24 | |
| 25 // EPOGER: misc cleanup (including 100 char wraps) | |
| 26 namespace skiagm { | |
| 27 | |
| 28 Json::Value ActualResultAsJsonValue(const SkHashDigest& result) { | |
| 29 Json::Value jsonValue; | |
| 30 jsonValue[kJsonKey_ActualResults_AnyStatus_BitmapCityhash] = asJsonValue (result); | |
| 31 return jsonValue; | |
| 32 } | |
| 33 | |
| 34 Json::Value CreateJsonTree(Json::Value expectedResults, | |
| 35 Json::Value actualResultsFailed, | |
| 36 Json::Value actualResultsFailureIgnored, | |
| 37 Json::Value actualResultsNoComparison, | |
| 38 Json::Value actualResultsSucceeded) { | |
| 39 Json::Value actualResults; | |
| 40 actualResults[kJsonKey_ActualResults_Failed] = actualResultsFailed; | |
| 41 actualResults[kJsonKey_ActualResults_FailureIgnored] = actualResultsFail ureIgnored; | |
| 42 actualResults[kJsonKey_ActualResults_NoComparison] = actualResultsNoComp arison; | |
| 43 actualResults[kJsonKey_ActualResults_Succeeded] = actualResultsSucceeded ; | |
| 44 Json::Value root; | |
| 45 root[kJsonKey_ActualResults] = actualResults; | |
| 46 root[kJsonKey_ExpectedResults] = expectedResults; | |
| 47 return root; | |
| 48 } | |
| 49 | |
| 50 | |
| 51 // Expectations class... | |
| 52 | |
| 53 Expectations::Expectations(bool ignoreFailure) { | |
| 54 fIgnoreFailure = ignoreFailure; | |
| 55 } | |
| 56 | |
| 57 Expectations::Expectations(const SkBitmap& bitmap, bool ignoreFailure) { | |
| 58 fBitmap = bitmap; | |
| 59 fIgnoreFailure = ignoreFailure; | |
| 60 SkHashDigest digest; | |
| 61 // TODO(epoger): Better handling for error returned by ComputeDigest()? | |
| 62 // For now, we just report a digest of 0 in error cases, like before. | |
| 63 if (!SkBitmapHasher::ComputeDigest(bitmap, &digest)) { | |
| 64 digest = 0; | |
| 65 } | |
| 66 fAllowedBitmapCityhashes.push_back() = digest; | |
| 67 } | |
| 68 | |
| 69 Expectations::Expectations(Json::Value jsonElement) { | |
| 70 if (jsonElement.empty()) { | |
| 71 fIgnoreFailure = kDefaultIgnoreFailure; | |
| 72 } else { | |
| 73 Json::Value ignoreFailure = jsonElement[kJsonKey_ExpectedResults_Ign oreFailure]; | |
| 74 if (ignoreFailure.isNull()) { | |
| 75 fIgnoreFailure = kDefaultIgnoreFailure; | |
| 76 } else if (!ignoreFailure.isBool()) { | |
| 77 gm_fprintf(stderr, "found non-boolean json value" | |
| 78 " for key '%s' in element '%s'\n", | |
| 79 kJsonKey_ExpectedResults_IgnoreFailure, | |
| 80 jsonElement.toStyledString().c_str()); | |
| 81 DEBUGFAIL_SEE_STDERR; | |
| 82 fIgnoreFailure = kDefaultIgnoreFailure; | |
| 83 } else { | |
| 84 fIgnoreFailure = ignoreFailure.asBool(); | |
| 85 } | |
| 86 | |
| 87 Json::Value allowedChecksums = jsonElement[kJsonKey_ExpectedResults_ AllowedBitmapCityhashes]; | |
| 88 if (allowedChecksums.isNull()) { | |
| 89 // ok, we'll just assume there aren't any expected checksums to compare against | |
| 90 } else if (!allowedChecksums.isArray()) { | |
| 91 gm_fprintf(stderr, "found non-array json value" | |
| 92 " for key '%s' in element '%s'\n", | |
| 93 kJsonKey_ExpectedResults_AllowedBitmapCityhashes, | |
| 94 jsonElement.toStyledString().c_str()); | |
| 95 DEBUGFAIL_SEE_STDERR; | |
| 96 } else { | |
| 97 for (Json::ArrayIndex i=0; i<allowedChecksums.size(); i++) { | |
| 98 Json::Value checksumElement = allowedChecksums[i]; | |
| 99 if (!checksumElement.isIntegral()) { | |
| 100 gm_fprintf(stderr, "found non-integer checksum" | |
| 101 " in json element '%s'\n", | |
| 102 jsonElement.toStyledString().c_str()); | |
| 103 DEBUGFAIL_SEE_STDERR; | |
| 104 } else { | |
| 105 fAllowedBitmapCityhashes.push_back() = asChecksum(checks umElement); | |
| 106 } | |
| 107 } | |
| 108 } | |
| 109 } | |
| 110 } | |
| 111 | |
| 112 bool Expectations::match(Checksum actualChecksum) const { | |
| 113 for (int i=0; i < this->fAllowedBitmapCityhashes.count(); i++) { | |
| 114 Checksum allowedChecksum = this->fAllowedBitmapCityhashes[i]; | |
| 115 if (allowedChecksum == actualChecksum) { | |
| 116 return true; | |
| 117 } | |
| 118 } | |
| 119 return false; | |
| 120 } | |
| 121 | |
| 122 Json::Value Expectations::allowedChecksumsAsJson() const { | |
| 123 Json::Value allowedChecksumArray; | |
| 124 if (!this->fAllowedBitmapCityhashes.empty()) { | |
| 125 for (int i=0; i < this->fAllowedBitmapCityhashes.count(); i++) { | |
| 126 Checksum allowedChecksum = this->fAllowedBitmapCityhashes[i]; | |
| 127 allowedChecksumArray.append(Json::UInt64(allowedChecksum)); | |
| 128 } | |
| 129 } | |
| 130 return allowedChecksumArray; | |
| 131 } | |
| 132 | |
| 133 Json::Value Expectations::asJsonValue() const { | |
| 134 Json::Value jsonValue; | |
| 135 jsonValue[kJsonKey_ExpectedResults_AllowedBitmapCityhashes] = | |
| 136 this->allowedChecksumsAsJson(); | |
| 137 jsonValue[kJsonKey_ExpectedResults_IgnoreFailure] = | |
| 138 this->ignoreFailure(); | |
| 139 return jsonValue; | |
| 140 } | |
| 141 | |
| 142 | |
| 143 // IndividualImageExpectationsSource class... | |
| 144 | |
| 145 Expectations IndividualImageExpectationsSource::get(const char *testName) SK _OVERRIDE { | |
| 146 SkString path = make_filename(fRootDir.c_str(), "", testName, | |
| 147 "png"); | |
| 148 SkBitmap referenceBitmap; | |
| 149 bool decodedReferenceBitmap = | |
| 150 SkImageDecoder::DecodeFile(path.c_str(), &referenceBitmap, | |
| 151 SkBitmap::kARGB_8888_Config, | |
| 152 SkImageDecoder::kDecodePixels_Mode, | |
| 153 NULL); | |
| 154 if (decodedReferenceBitmap) { | |
| 155 return Expectations(referenceBitmap); | |
| 156 } else { | |
| 157 return Expectations(); | |
| 158 } | |
| 159 } | |
| 160 | |
| 161 | |
| 162 // JsonExpectationsSource class... | |
| 163 | |
| 164 JsonExpectationsSource::JsonExpectationsSource(const char *jsonPath) { | |
| 165 parse(jsonPath, &fJsonRoot); | |
| 166 fJsonExpectedResults = fJsonRoot[kJsonKey_ExpectedResults]; | |
| 167 } | |
| 168 | |
| 169 Expectations JsonExpectationsSource::get(const char *testName) SK_OVERRIDE { | |
| 170 return Expectations(fJsonExpectedResults[testName]); | |
| 171 } | |
| 172 | |
| 173 /*static*/ SkData* JsonExpectationsSource::readIntoSkData(SkStream &stream, size_t maxBytes) { | |
| 174 if (0 == maxBytes) { | |
| 175 return SkData::NewEmpty(); | |
| 176 } | |
| 177 char* bufStart = reinterpret_cast<char *>(sk_malloc_throw(maxBytes)); | |
| 178 char* bufPtr = bufStart; | |
| 179 size_t bytesRemaining = maxBytes; | |
| 180 while (bytesRemaining > 0) { | |
| 181 size_t bytesReadThisTime = stream.read(bufPtr, bytesRemaining); | |
| 182 if (0 == bytesReadThisTime) { | |
| 183 break; | |
| 184 } | |
| 185 bytesRemaining -= bytesReadThisTime; | |
| 186 bufPtr += bytesReadThisTime; | |
| 187 } | |
| 188 return SkData::NewFromMalloc(bufStart, maxBytes - bytesRemaining); | |
| 189 } | |
| 190 | |
| 191 /*static*/ bool JsonExpectationsSource::parse(const char *jsonPath, Json::Va lue *jsonRoot) { | |
| 192 SkFILEStream inFile(jsonPath); | |
| 193 if (!inFile.isValid()) { | |
| 194 gm_fprintf(stderr, "unable to read JSON file %s\n", jsonPath); | |
| 195 DEBUGFAIL_SEE_STDERR; | |
| 196 return false; | |
| 197 } | |
| 198 | |
| 199 SkAutoDataUnref dataRef(readFileIntoSkData(inFile)); | |
| 200 if (NULL == dataRef.get()) { | |
| 201 gm_fprintf(stderr, "error reading JSON file %s\n", jsonPath); | |
| 202 DEBUGFAIL_SEE_STDERR; | |
| 203 return false; | |
| 204 } | |
| 205 | |
| 206 const char *bytes = reinterpret_cast<const char *>(dataRef.get()->data() ); | |
| 207 size_t size = dataRef.get()->size(); | |
| 208 Json::Reader reader; | |
| 209 if (!reader.parse(bytes, bytes+size, *jsonRoot)) { | |
| 210 gm_fprintf(stderr, "error parsing JSON file %s\n", jsonPath); | |
| 211 DEBUGFAIL_SEE_STDERR; | |
| 212 return false; | |
| 213 } | |
| 214 return true; | |
| 215 } | |
| 216 | |
| 217 } | |
| OLD | NEW |