OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2014 Google Inc. | 2 * Copyright 2014 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 "SkBitmap.h" | 8 #include "SkBitmap.h" |
9 #include "SkBitmapHasher.h" | 9 #include "SkBitmapHasher.h" |
10 #include "SkData.h" | 10 #include "SkData.h" |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
46 const static char kJsonValue_Image_ChecksumAlgorithm_Bitmap64bitMD5[] = "bitmap-
64bitMD5"; | 46 const static char kJsonValue_Image_ChecksumAlgorithm_Bitmap64bitMD5[] = "bitmap-
64bitMD5"; |
47 const static char kJsonValue_Image_ComparisonResult_Failed[] = "failed"; | 47 const static char kJsonValue_Image_ComparisonResult_Failed[] = "failed"; |
48 const static char kJsonValue_Image_ComparisonResult_FailureIgnored[] = "failure-
ignored"; | 48 const static char kJsonValue_Image_ComparisonResult_FailureIgnored[] = "failure-
ignored"; |
49 const static char kJsonValue_Image_ComparisonResult_NoComparison[] = "no-compari
son"; | 49 const static char kJsonValue_Image_ComparisonResult_NoComparison[] = "no-compari
son"; |
50 const static char kJsonValue_Image_ComparisonResult_Succeeded[] = "succeeded"; | 50 const static char kJsonValue_Image_ComparisonResult_Succeeded[] = "succeeded"; |
51 | 51 |
52 namespace sk_tools { | 52 namespace sk_tools { |
53 | 53 |
54 // ImageDigest class... | 54 // ImageDigest class... |
55 | 55 |
56 ImageDigest::ImageDigest(const SkBitmap &bitmap) { | 56 ImageDigest::ImageDigest(const SkBitmap &bitmap) : |
57 if (!SkBitmapHasher::ComputeDigest(bitmap, &fHashValue)) { | 57 fBitmap(bitmap), fHashValue(0), fComputedHashValue(false) {} |
58 SkFAIL("unable to compute image digest"); | 58 |
| 59 ImageDigest::ImageDigest(const SkString &hashType, uint64_t hashValue) : |
| 60 fBitmap(), fHashValue(hashValue), fComputedHashValue(true) { |
| 61 if (!hashType.equals(kJsonValue_Image_ChecksumAlgorithm_Bitmap64bitMD5))
{ |
| 62 SkDebugf("unsupported hashType '%s'\n", hashType.c_str()); |
| 63 SkFAIL("unsupported hashType (see above)"); |
59 } | 64 } |
60 } | 65 } |
61 | 66 |
62 ImageDigest::ImageDigest(const SkString &hashType, uint64_t hashValue) { | 67 bool ImageDigest::equals(ImageDigest &other) { |
63 if (!hashType.equals(kJsonValue_Image_ChecksumAlgorithm_Bitmap64bitMD5))
{ | 68 // TODO(epoger): The current implementation assumes that this |
64 SkFAIL((SkString("unsupported hashType ")+=hashType).c_str()); | 69 // and other always have hashType kJsonKey_Hashtype_Bitmap_64bitMD5 |
65 } else { | 70 return (this->getHashValue() == other.getHashValue()); |
66 fHashValue = hashValue; | |
67 } | |
68 } | 71 } |
69 | 72 |
70 SkString ImageDigest::getHashType() const { | 73 SkString ImageDigest::getHashType() { |
71 // TODO(epoger): The current implementation assumes that the | 74 // TODO(epoger): The current implementation assumes that the |
72 // result digest is always of type kJsonValue_Image_ChecksumAlgorithm_Bi
tmap64bitMD5 . | 75 // result digest is always of type kJsonValue_Image_ChecksumAlgorithm_Bi
tmap64bitMD5 . |
73 return SkString(kJsonValue_Image_ChecksumAlgorithm_Bitmap64bitMD5); | 76 return SkString(kJsonValue_Image_ChecksumAlgorithm_Bitmap64bitMD5); |
74 } | 77 } |
75 | 78 |
76 uint64_t ImageDigest::getHashValue() const { | 79 uint64_t ImageDigest::getHashValue() { |
77 return fHashValue; | 80 if (!this->fComputedHashValue) { |
| 81 if (!SkBitmapHasher::ComputeDigest(this->fBitmap, &this->fHashValue)
) { |
| 82 SkFAIL("unable to compute image digest"); |
| 83 } |
| 84 this->fComputedHashValue = true; |
| 85 } |
| 86 return this->fHashValue; |
78 } | 87 } |
79 | 88 |
80 // BitmapAndDigest class... | 89 // BitmapAndDigest class... |
81 | 90 |
82 BitmapAndDigest::BitmapAndDigest(const SkBitmap &bitmap) : fBitmap(bitmap) { | 91 BitmapAndDigest::BitmapAndDigest(const SkBitmap &bitmap) : |
83 } | 92 fBitmap(bitmap), fImageDigest(bitmap) {} |
84 | 93 |
85 const ImageDigest *BitmapAndDigest::getImageDigestPtr() { | 94 const SkBitmap *BitmapAndDigest::getBitmapPtr() const {return &fBitmap;} |
86 if (NULL == fImageDigestRef.get()) { | |
87 fImageDigestRef.reset(SkNEW_ARGS(ImageDigest, (fBitmap))); | |
88 } | |
89 return fImageDigestRef.get(); | |
90 } | |
91 | 95 |
92 const SkBitmap *BitmapAndDigest::getBitmapPtr() const { | 96 ImageDigest *BitmapAndDigest::getImageDigestPtr() {return &fImageDigest;} |
93 return &fBitmap; | 97 |
| 98 // Expectation class... |
| 99 |
| 100 // For when we need a valid ImageDigest, but we don't care what it is. |
| 101 static const ImageDigest kDummyImageDigest( |
| 102 SkString(kJsonValue_Image_ChecksumAlgorithm_Bitmap64bitMD5), 0); |
| 103 |
| 104 Expectation::Expectation(bool ignoreFailure) : |
| 105 fIsEmpty(true), fIgnoreFailure(ignoreFailure), fImageDigest(kDummyImageD
igest) {} |
| 106 |
| 107 Expectation::Expectation(const SkString &hashType, uint64_t hashValue, bool
ignoreFailure) : |
| 108 fIsEmpty(false), fIgnoreFailure(ignoreFailure), fImageDigest(hashType, h
ashValue) {} |
| 109 |
| 110 Expectation::Expectation(const SkBitmap& bitmap, bool ignoreFailure) : |
| 111 fIsEmpty(false), fIgnoreFailure(ignoreFailure), fImageDigest(bitmap) {} |
| 112 |
| 113 bool Expectation::ignoreFailure() const { return this->fIgnoreFailure; } |
| 114 |
| 115 bool Expectation::empty() const { return this->fIsEmpty; } |
| 116 |
| 117 bool Expectation::matches(ImageDigest &imageDigest) { |
| 118 return !(this->fIsEmpty) && (this->fImageDigest.equals(imageDigest)); |
94 } | 119 } |
95 | 120 |
96 // ImageResultsAndExpectations class... | 121 // ImageResultsAndExpectations class... |
97 | 122 |
98 bool ImageResultsAndExpectations::readExpectationsFile(const char *jsonPath)
{ | 123 bool ImageResultsAndExpectations::readExpectationsFile(const char *jsonPath)
{ |
99 if (NULL == jsonPath) { | 124 if (NULL == jsonPath) { |
100 SkDebugf("JSON expectations filename not specified\n"); | 125 SkDebugf("JSON expectations filename not specified\n"); |
101 return false; | 126 return false; |
102 } | 127 } |
103 SkFILE* filePtr = sk_fopen(jsonPath, kRead_SkFILE_Flag); | 128 SkFILE* filePtr = sk_fopen(jsonPath, kRead_SkFILE_Flag); |
(...skipping 25 matching lines...) Expand all Loading... |
129 if (headerRevision.asInt() != kJsonValue_Header_Revision) { | 154 if (headerRevision.asInt() != kJsonValue_Header_Revision) { |
130 SkDebugf("JSON expectations file '%s': expected headerRevision %d, f
ound %d\n", | 155 SkDebugf("JSON expectations file '%s': expected headerRevision %d, f
ound %d\n", |
131 jsonPath, kJsonValue_Header_Revision, headerRevision.asInt(
)); | 156 jsonPath, kJsonValue_Header_Revision, headerRevision.asInt(
)); |
132 return false; | 157 return false; |
133 } | 158 } |
134 fExpectedResults = fExpectedJsonRoot[kJsonKey_ExpectedResults]; | 159 fExpectedResults = fExpectedJsonRoot[kJsonKey_ExpectedResults]; |
135 return true; | 160 return true; |
136 } | 161 } |
137 | 162 |
138 void ImageResultsAndExpectations::add(const char *sourceName, const char *fi
leName, | 163 void ImageResultsAndExpectations::add(const char *sourceName, const char *fi
leName, |
139 const ImageDigest &digest, const int *
tileNumber) { | 164 ImageDigest &digest, const int *tileNu
mber) { |
140 // Get expectation, if any. | 165 // Get expectation, if any. |
141 Json::Value expectedImage; | 166 Expectation expectation = this->getExpectation(sourceName, tileNumber); |
142 if (!fExpectedResults.isNull()) { | |
143 if (NULL == tileNumber) { | |
144 expectedImage = fExpectedResults[sourceName][kJsonKey_Source_Who
leImage]; | |
145 } else { | |
146 expectedImage = fExpectedResults[sourceName][kJsonKey_Source_Til
edImages] | |
147 [*tileNumber]; | |
148 } | |
149 } | |
150 | 167 |
151 // Fill in info about the actual result itself. | 168 // Fill in info about the actual result. |
152 Json::Value actualChecksumAlgorithm = digest.getHashType().c_str(); | 169 Json::Value actualChecksumAlgorithm = digest.getHashType().c_str(); |
153 Json::Value actualChecksumValue = Json::UInt64(digest.getHashValue()); | 170 Json::Value actualChecksumValue = Json::UInt64(digest.getHashValue()); |
154 Json::Value actualImage; | 171 Json::Value actualImage; |
155 actualImage[kJsonKey_Image_ChecksumAlgorithm] = actualChecksumAlgorithm; | 172 actualImage[kJsonKey_Image_ChecksumAlgorithm] = actualChecksumAlgorithm; |
156 actualImage[kJsonKey_Image_ChecksumValue] = actualChecksumValue; | 173 actualImage[kJsonKey_Image_ChecksumValue] = actualChecksumValue; |
157 actualImage[kJsonKey_Image_Filepath] = fileName; | 174 actualImage[kJsonKey_Image_Filepath] = fileName; |
158 | 175 |
159 // Compare against expectedImage to fill in comparisonResult. | 176 // Compare against expectedImage to fill in comparisonResult. |
160 Json::Value comparisonResult = kJsonValue_Image_ComparisonResult_NoCompa
rison; | 177 Json::Value comparisonResult; |
161 if (!expectedImage.isNull()) { | 178 if (expectation.empty()) { |
162 if ((actualChecksumAlgorithm == expectedImage[kJsonKey_Image_Checksu
mAlgorithm]) && | 179 comparisonResult = kJsonValue_Image_ComparisonResult_NoComparison; |
163 (actualChecksumValue == expectedImage[kJsonKey_Image_ChecksumVal
ue])) { | 180 } else if (expectation.matches(digest)) { |
164 comparisonResult = kJsonValue_Image_ComparisonResult_Succeeded; | 181 comparisonResult = kJsonValue_Image_ComparisonResult_Succeeded; |
165 } else if (expectedImage[kJsonKey_Image_IgnoreFailure] == true) { | 182 } else if (expectation.ignoreFailure()) { |
166 comparisonResult = kJsonValue_Image_ComparisonResult_FailureIgno
red; | 183 comparisonResult = kJsonValue_Image_ComparisonResult_FailureIgnored; |
167 } else { | 184 } else { |
168 comparisonResult = kJsonValue_Image_ComparisonResult_Failed; | 185 comparisonResult = kJsonValue_Image_ComparisonResult_Failed; |
169 } | |
170 } | 186 } |
171 actualImage[kJsonKey_Image_ComparisonResult] = comparisonResult; | 187 actualImage[kJsonKey_Image_ComparisonResult] = comparisonResult; |
172 | 188 |
173 // Add this actual result to our collection. | 189 // Add this actual result to our collection. |
174 if (NULL == tileNumber) { | 190 if (NULL == tileNumber) { |
175 fActualResults[sourceName][kJsonKey_Source_WholeImage] = actualImage
; | 191 fActualResults[sourceName][kJsonKey_Source_WholeImage] = actualImage
; |
176 } else { | 192 } else { |
177 fActualResults[sourceName][kJsonKey_Source_TiledImages][*tileNumber]
= actualImage; | 193 fActualResults[sourceName][kJsonKey_Source_TiledImages][*tileNumber]
= actualImage; |
178 } | 194 } |
179 } | 195 } |
180 | 196 |
181 void ImageResultsAndExpectations::addDescription(const char *key, const char
*value) { | 197 void ImageResultsAndExpectations::addDescription(const char *key, const char
*value) { |
182 fDescriptions[key] = value; | 198 fDescriptions[key] = value; |
183 } | 199 } |
184 | 200 |
185 bool ImageResultsAndExpectations::matchesExpectation(const char *sourceName, | 201 Expectation ImageResultsAndExpectations::getExpectation(const char *sourceNa
me, |
186 const ImageDigest &dige
st, | 202 const int *tileNumbe
r) { |
187 const int *tileNumber)
{ | |
188 if (fExpectedResults.isNull()) { | 203 if (fExpectedResults.isNull()) { |
189 return false; | 204 return Expectation(); |
190 } | 205 } |
191 | 206 |
192 Json::Value expectedImage; | 207 Json::Value expectedImage; |
193 if (NULL == tileNumber) { | 208 if (NULL == tileNumber) { |
194 expectedImage = fExpectedResults[sourceName][kJsonKey_Source_WholeIm
age]; | 209 expectedImage = fExpectedResults[sourceName][kJsonKey_Source_WholeIm
age]; |
195 } else { | 210 } else { |
196 expectedImage = fExpectedResults[sourceName][kJsonKey_Source_TiledIm
ages][*tileNumber]; | 211 expectedImage = fExpectedResults[sourceName][kJsonKey_Source_TiledIm
ages][*tileNumber]; |
197 } | 212 } |
198 if (expectedImage.isNull()) { | 213 if (expectedImage.isNull()) { |
199 return false; | 214 return Expectation(); |
200 } | 215 } |
201 | 216 |
202 Json::Value actualChecksumAlgorithm = digest.getHashType().c_str(); | 217 bool ignoreFailure = (expectedImage[kJsonKey_Image_IgnoreFailure] == tru
e); |
203 Json::Value actualChecksumValue = Json::UInt64(digest.getHashValue()); | 218 return Expectation(SkString(expectedImage[kJsonKey_Image_ChecksumAlgorit
hm].asCString()), |
204 return ((actualChecksumAlgorithm == expectedImage[kJsonKey_Image_Checksu
mAlgorithm]) && | 219 expectedImage[kJsonKey_Image_ChecksumValue].asUInt64(
), |
205 (actualChecksumValue == expectedImage[kJsonKey_Image_ChecksumVal
ue])); | 220 ignoreFailure); |
206 } | 221 } |
207 | 222 |
208 void ImageResultsAndExpectations::writeToFile(const char *filename) const { | 223 void ImageResultsAndExpectations::writeToFile(const char *filename) const { |
209 Json::Value header; | 224 Json::Value header; |
210 header[kJsonKey_Header_Type] = kJsonValue_Header_Type; | 225 header[kJsonKey_Header_Type] = kJsonValue_Header_Type; |
211 header[kJsonKey_Header_Revision] = kJsonValue_Header_Revision; | 226 header[kJsonKey_Header_Revision] = kJsonValue_Header_Revision; |
212 Json::Value root; | 227 Json::Value root; |
213 root[kJsonKey_ActualResults] = fActualResults; | 228 root[kJsonKey_ActualResults] = fActualResults; |
214 root[kJsonKey_Descriptions] = fDescriptions; | 229 root[kJsonKey_Descriptions] = fDescriptions; |
215 root[kJsonKey_Header] = header; | 230 root[kJsonKey_Header] = header; |
(...skipping 13 matching lines...) Expand all Loading... |
229 size_t size = dataRef.get()->size(); | 244 size_t size = dataRef.get()->size(); |
230 Json::Reader reader; | 245 Json::Reader reader; |
231 if (!reader.parse(bytes, bytes+size, *jsonRoot)) { | 246 if (!reader.parse(bytes, bytes+size, *jsonRoot)) { |
232 return false; | 247 return false; |
233 } | 248 } |
234 | 249 |
235 return true; | 250 return true; |
236 } | 251 } |
237 | 252 |
238 } // namespace sk_tools | 253 } // namespace sk_tools |
OLD | NEW |