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 | 7 |
8 #include "gm_expectations.h" | 8 #include "gm_expectations.h" |
9 #include "SkBitmapHasher.h" | 9 #include "SkBitmapHasher.h" |
10 #include "SkImageDecoder.h" | 10 #include "SkImageDecoder.h" |
11 | 11 |
12 #define DEBUGFAIL_SEE_STDERR SkDEBUGFAIL("see stderr for message") | 12 #define DEBUGFAIL_SEE_STDERR SkDEBUGFAIL("see stderr for message") |
13 | 13 |
14 // See gm_json.py for descriptions of each of these JSON keys. | 14 // See gm_json.py for descriptions of each of these JSON keys. |
15 // These constants must be kept in sync with the ones in that Python file! | 15 // These constants must be kept in sync with the ones in that Python file! |
16 const static char kJsonKey_ActualResults[] = "actual-results"; | 16 const static char kJsonKey_ActualResults[] = "actual-results"; |
17 const static char kJsonKey_ActualResults_Failed[] = "failed"; | 17 const static char kJsonKey_ActualResults_Failed[] = "failed"; |
18 const static char kJsonKey_ActualResults_FailureIgnored[]= "failure-ignored"; | 18 const static char kJsonKey_ActualResults_FailureIgnored[]= "failure-ignored"; |
19 const static char kJsonKey_ActualResults_NoComparison[] = "no-comparison"; | 19 const static char kJsonKey_ActualResults_NoComparison[] = "no-comparison"; |
20 const static char kJsonKey_ActualResults_Succeeded[] = "succeeded"; | 20 const static char kJsonKey_ActualResults_Succeeded[] = "succeeded"; |
21 const static char kJsonKey_ExpectedResults[] = "expected-results"; | 21 const static char kJsonKey_ExpectedResults[] = "expected-results"; |
22 const static char kJsonKey_ExpectedResults_AllowedDigests[] = "allowed-digests"; | 22 const static char kJsonKey_ExpectedResults_AllowedDigests[] = "allowed-digests"; |
23 const static char kJsonKey_ExpectedResults_IgnoreFailure[] = "ignore-failure"; | 23 const static char kJsonKey_ExpectedResults_IgnoreFailure[] = "ignore-failure"; |
24 | 24 |
25 // Types of result hashes we support in the JSON file. | 25 // Types of result hashes we support in the JSON file. |
26 const static char kJsonKey_Hashtype_Bitmap_64bitMD5[] = "bitmap-64bitMD5"; | 26 const static char kJsonKey_Hashtype_Bitmap_64bitMD5[] = "bitmap-64bitMD5"; |
27 | 27 |
28 | 28 |
29 namespace skiagm { | 29 namespace skiagm { |
30 void gm_fprintf(FILE *stream, const char format[], ...) { | |
31 va_list args; | |
32 va_start(args, format); | |
33 fprintf(stream, "GM: "); | |
34 vfprintf(stream, format, args); | |
35 #ifdef SK_BUILD_FOR_WIN | |
36 if (stderr == stream || stdout == stream) { | |
37 fflush(stream); | |
38 } | |
39 #endif | |
40 va_end(args); | |
41 } | |
42 | 30 |
43 Json::Value CreateJsonTree(Json::Value expectedResults, | 31 Json::Value CreateJsonTree(Json::Value expectedResults, |
44 Json::Value actualResultsFailed, | 32 Json::Value actualResultsFailed, |
45 Json::Value actualResultsFailureIgnored, | 33 Json::Value actualResultsFailureIgnored, |
46 Json::Value actualResultsNoComparison, | 34 Json::Value actualResultsNoComparison, |
47 Json::Value actualResultsSucceeded) { | 35 Json::Value actualResultsSucceeded) { |
48 Json::Value actualResults; | 36 Json::Value actualResults; |
49 actualResults[kJsonKey_ActualResults_Failed] = actualResultsFailed; | 37 actualResults[kJsonKey_ActualResults_Failed] = actualResultsFailed; |
50 actualResults[kJsonKey_ActualResults_FailureIgnored] = actualResultsFail
ureIgnored; | 38 actualResults[kJsonKey_ActualResults_FailureIgnored] = actualResultsFail
ureIgnored; |
51 actualResults[kJsonKey_ActualResults_NoComparison] = actualResultsNoComp
arison; | 39 actualResults[kJsonKey_ActualResults_NoComparison] = actualResultsNoComp
arison; |
52 actualResults[kJsonKey_ActualResults_Succeeded] = actualResultsSucceeded
; | 40 actualResults[kJsonKey_ActualResults_Succeeded] = actualResultsSucceeded
; |
53 Json::Value root; | 41 Json::Value root; |
54 root[kJsonKey_ActualResults] = actualResults; | 42 root[kJsonKey_ActualResults] = actualResults; |
55 root[kJsonKey_ExpectedResults] = expectedResults; | 43 root[kJsonKey_ExpectedResults] = expectedResults; |
56 return root; | 44 return root; |
57 } | 45 } |
58 | 46 |
59 | 47 |
60 // GmResultDigest class... | 48 // GmResultDigest class... |
61 | 49 |
62 GmResultDigest::GmResultDigest(const SkBitmap &bitmap) { | 50 GmResultDigest::GmResultDigest(const SkBitmap &bitmap) { |
63 fIsValid = SkBitmapHasher::ComputeDigest(bitmap, &fHashDigest); | 51 fIsValid = SkBitmapHasher::ComputeDigest(bitmap, &fHashDigest); |
64 } | 52 } |
65 | 53 |
66 GmResultDigest::GmResultDigest(const Json::Value &jsonTypeValuePair) { | 54 GmResultDigest::GmResultDigest(const Json::Value &jsonTypeValuePair) { |
67 fIsValid = false; | 55 fIsValid = false; |
68 if (!jsonTypeValuePair.isArray()) { | 56 if (!jsonTypeValuePair.isArray()) { |
69 gm_fprintf(stderr, "found non-array json value when parsing GmResult
Digest: %s\n", | 57 SkDebugf("found non-array json value when parsing GmResultDigest: %s
\n", |
70 jsonTypeValuePair.toStyledString().c_str()); | 58 jsonTypeValuePair.toStyledString().c_str()); |
71 DEBUGFAIL_SEE_STDERR; | 59 DEBUGFAIL_SEE_STDERR; |
72 } else if (2 != jsonTypeValuePair.size()) { | 60 } else if (2 != jsonTypeValuePair.size()) { |
73 gm_fprintf(stderr, "found json array with wrong size when parsing Gm
ResultDigest: %s\n", | 61 SkDebugf("found json array with wrong size when parsing GmResultDige
st: %s\n", |
74 jsonTypeValuePair.toStyledString().c_str()); | 62 jsonTypeValuePair.toStyledString().c_str()); |
75 DEBUGFAIL_SEE_STDERR; | 63 DEBUGFAIL_SEE_STDERR; |
76 } else { | 64 } else { |
77 // TODO(epoger): The current implementation assumes that the | 65 // TODO(epoger): The current implementation assumes that the |
78 // result digest is always of type kJsonKey_Hashtype_Bitmap_64bitMD5 | 66 // result digest is always of type kJsonKey_Hashtype_Bitmap_64bitMD5 |
79 Json::Value jsonHashValue = jsonTypeValuePair[1]; | 67 Json::Value jsonHashValue = jsonTypeValuePair[1]; |
80 if (!jsonHashValue.isIntegral()) { | 68 if (!jsonHashValue.isIntegral()) { |
81 gm_fprintf(stderr, | 69 SkDebugf("found non-integer jsonHashValue when parsing GmResultD
igest: %s\n", |
82 "found non-integer jsonHashValue when parsing GmResul
tDigest: %s\n", | 70 jsonTypeValuePair.toStyledString().c_str()); |
83 jsonTypeValuePair.toStyledString().c_str()); | |
84 DEBUGFAIL_SEE_STDERR; | 71 DEBUGFAIL_SEE_STDERR; |
85 } else { | 72 } else { |
86 fHashDigest = jsonHashValue.asUInt64(); | 73 fHashDigest = jsonHashValue.asUInt64(); |
87 fIsValid = true; | 74 fIsValid = true; |
88 } | 75 } |
89 } | 76 } |
90 } | 77 } |
91 | 78 |
92 bool GmResultDigest::isValid() const { | 79 bool GmResultDigest::isValid() const { |
93 return fIsValid; | 80 return fIsValid; |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
146 } | 133 } |
147 | 134 |
148 Expectations::Expectations(Json::Value jsonElement) { | 135 Expectations::Expectations(Json::Value jsonElement) { |
149 if (jsonElement.empty()) { | 136 if (jsonElement.empty()) { |
150 fIgnoreFailure = kDefaultIgnoreFailure; | 137 fIgnoreFailure = kDefaultIgnoreFailure; |
151 } else { | 138 } else { |
152 Json::Value ignoreFailure = jsonElement[kJsonKey_ExpectedResults_Ign
oreFailure]; | 139 Json::Value ignoreFailure = jsonElement[kJsonKey_ExpectedResults_Ign
oreFailure]; |
153 if (ignoreFailure.isNull()) { | 140 if (ignoreFailure.isNull()) { |
154 fIgnoreFailure = kDefaultIgnoreFailure; | 141 fIgnoreFailure = kDefaultIgnoreFailure; |
155 } else if (!ignoreFailure.isBool()) { | 142 } else if (!ignoreFailure.isBool()) { |
156 gm_fprintf(stderr, "found non-boolean json value" | 143 SkDebugf("found non-boolean json value for key '%s' in element '
%s'\n", |
157 " for key '%s' in element '%s'\n", | 144 kJsonKey_ExpectedResults_IgnoreFailure, |
158 kJsonKey_ExpectedResults_IgnoreFailure, | 145 jsonElement.toStyledString().c_str()); |
159 jsonElement.toStyledString().c_str()); | |
160 DEBUGFAIL_SEE_STDERR; | 146 DEBUGFAIL_SEE_STDERR; |
161 fIgnoreFailure = kDefaultIgnoreFailure; | 147 fIgnoreFailure = kDefaultIgnoreFailure; |
162 } else { | 148 } else { |
163 fIgnoreFailure = ignoreFailure.asBool(); | 149 fIgnoreFailure = ignoreFailure.asBool(); |
164 } | 150 } |
165 | 151 |
166 Json::Value allowedDigests = jsonElement[kJsonKey_ExpectedResults_Al
lowedDigests]; | 152 Json::Value allowedDigests = jsonElement[kJsonKey_ExpectedResults_Al
lowedDigests]; |
167 if (allowedDigests.isNull()) { | 153 if (allowedDigests.isNull()) { |
168 // ok, we'll just assume there aren't any AllowedDigests to comp
are against | 154 // ok, we'll just assume there aren't any AllowedDigests to comp
are against |
169 } else if (!allowedDigests.isArray()) { | 155 } else if (!allowedDigests.isArray()) { |
170 gm_fprintf(stderr, "found non-array json value" | 156 SkDebugf("found non-array json value for key '%s' in element '%s
'\n", |
171 " for key '%s' in element '%s'\n", | 157 kJsonKey_ExpectedResults_AllowedDigests, |
172 kJsonKey_ExpectedResults_AllowedDigests, | 158 jsonElement.toStyledString().c_str()); |
173 jsonElement.toStyledString().c_str()); | |
174 DEBUGFAIL_SEE_STDERR; | 159 DEBUGFAIL_SEE_STDERR; |
175 } else { | 160 } else { |
176 for (Json::ArrayIndex i=0; i<allowedDigests.size(); i++) { | 161 for (Json::ArrayIndex i=0; i<allowedDigests.size(); i++) { |
177 fAllowedResultDigests.push_back(GmResultDigest(allowedDigest
s[i])); | 162 fAllowedResultDigests.push_back(GmResultDigest(allowedDigest
s[i])); |
178 } | 163 } |
179 } | 164 } |
180 } | 165 } |
181 } | 166 } |
182 | 167 |
183 bool Expectations::match(GmResultDigest actualGmResultDigest) const { | 168 bool Expectations::match(GmResultDigest actualGmResultDigest) const { |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
248 } | 233 } |
249 bytesRemaining -= bytesReadThisTime; | 234 bytesRemaining -= bytesReadThisTime; |
250 bufPtr += bytesReadThisTime; | 235 bufPtr += bytesReadThisTime; |
251 } | 236 } |
252 return SkData::NewFromMalloc(bufStart, maxBytes - bytesRemaining); | 237 return SkData::NewFromMalloc(bufStart, maxBytes - bytesRemaining); |
253 } | 238 } |
254 | 239 |
255 /*static*/ bool JsonExpectationsSource::Parse(const char *jsonPath, Json::Va
lue *jsonRoot) { | 240 /*static*/ bool JsonExpectationsSource::Parse(const char *jsonPath, Json::Va
lue *jsonRoot) { |
256 SkFILEStream inFile(jsonPath); | 241 SkFILEStream inFile(jsonPath); |
257 if (!inFile.isValid()) { | 242 if (!inFile.isValid()) { |
258 gm_fprintf(stderr, "unable to read JSON file %s\n", jsonPath); | 243 SkDebugf("unable to read JSON file %s\n", jsonPath); |
259 DEBUGFAIL_SEE_STDERR; | 244 DEBUGFAIL_SEE_STDERR; |
260 return false; | 245 return false; |
261 } | 246 } |
262 | 247 |
263 SkAutoDataUnref dataRef(ReadFileIntoSkData(inFile)); | 248 SkAutoDataUnref dataRef(ReadFileIntoSkData(inFile)); |
264 if (NULL == dataRef.get()) { | 249 if (NULL == dataRef.get()) { |
265 gm_fprintf(stderr, "error reading JSON file %s\n", jsonPath); | 250 SkDebugf("error reading JSON file %s\n", jsonPath); |
266 DEBUGFAIL_SEE_STDERR; | 251 DEBUGFAIL_SEE_STDERR; |
267 return false; | 252 return false; |
268 } | 253 } |
269 | 254 |
270 const char *bytes = reinterpret_cast<const char *>(dataRef.get()->data()
); | 255 const char *bytes = reinterpret_cast<const char *>(dataRef.get()->data()
); |
271 size_t size = dataRef.get()->size(); | 256 size_t size = dataRef.get()->size(); |
272 Json::Reader reader; | 257 Json::Reader reader; |
273 if (!reader.parse(bytes, bytes+size, *jsonRoot)) { | 258 if (!reader.parse(bytes, bytes+size, *jsonRoot)) { |
274 gm_fprintf(stderr, "error parsing JSON file %s\n", jsonPath); | 259 SkDebugf("error parsing JSON file %s\n", jsonPath); |
275 DEBUGFAIL_SEE_STDERR; | 260 DEBUGFAIL_SEE_STDERR; |
276 return false; | 261 return false; |
277 } | 262 } |
278 return true; | 263 return true; |
279 } | 264 } |
280 | 265 |
281 } | 266 } |
OLD | NEW |