aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--gm/gm_expectations.h191
-rw-r--r--gm/gmmain.cpp17
-rw-r--r--gm/tests/outputs/compared-against-different-pixels-json/output-expected/command_line1
-rw-r--r--gm/tests/outputs/compared-against-different-pixels-json/output-expected/json-summary.txt25
-rw-r--r--gm/tests/outputs/compared-against-different-pixels-json/output-expected/return_value1
-rw-r--r--gm/tests/outputs/compared-against-different-pixels-json/output-expected/stdout3
-rw-r--r--gm/tests/outputs/compared-against-identical-bytes-json/output-expected/command_line1
-rw-r--r--gm/tests/outputs/compared-against-identical-bytes-json/output-expected/json-summary.txt25
-rw-r--r--gm/tests/outputs/compared-against-identical-bytes-json/output-expected/return_value1
-rw-r--r--gm/tests/outputs/compared-against-identical-bytes-json/output-expected/stdout3
-rw-r--r--gm/tests/outputs/compared-against-identical-pixels-json/output-expected/command_line1
-rw-r--r--gm/tests/outputs/compared-against-identical-pixels-json/output-expected/json-summary.txt25
-rw-r--r--gm/tests/outputs/compared-against-identical-pixels-json/output-expected/return_value1
-rw-r--r--gm/tests/outputs/compared-against-identical-pixels-json/output-expected/stdout3
-rwxr-xr-xgm/tests/run.sh3
15 files changed, 280 insertions, 21 deletions
diff --git a/gm/gm_expectations.h b/gm/gm_expectations.h
index 07f0e60dbd..acff9d478b 100644
--- a/gm/gm_expectations.h
+++ b/gm/gm_expectations.h
@@ -10,9 +10,11 @@
#include "gm.h"
#include "SkBitmap.h"
#include "SkBitmapChecksummer.h"
+#include "SkData.h"
#include "SkImageDecoder.h"
#include "SkOSFile.h"
#include "SkRefCnt.h"
+#include "SkStream.h"
#include "SkTArray.h"
#ifdef SK_BUILD_FOR_WIN
@@ -21,11 +23,25 @@
#pragma warning(push)
#pragma warning(disable : 4530)
#endif
+#include "json/reader.h"
#include "json/value.h"
#ifdef SK_BUILD_FOR_WIN
#pragma warning(pop)
#endif
+#define DEBUGFAIL_SEE_STDERR SkDEBUGFAIL("see stderr for message")
+
+const static char kJsonKey_ActualResults[] = "actual-results";
+const static char kJsonKey_ActualResults_Failed[] = "failed";
+const static char kJsonKey_ActualResults_FailureIgnored[]= "failure-ignored";
+const static char kJsonKey_ActualResults_NoComparison[] = "no-comparison";
+const static char kJsonKey_ActualResults_Succeeded[] = "succeeded";
+const static char kJsonKey_ActualResults_AnyStatus_Checksum[] = "checksum";
+
+const static char kJsonKey_ExpectedResults[] = "expected-results";
+const static char kJsonKey_ExpectedResults_Checksums[] = "checksums";
+const static char kJsonKey_ExpectedResults_IgnoreFailure[] = "ignore-failure";
+
namespace skiagm {
// The actual type we use to represent a checksum is hidden in here.
@@ -33,6 +49,9 @@ namespace skiagm {
static inline Json::Value asJsonValue(Checksum checksum) {
return checksum;
}
+ static inline Checksum asChecksum(Json::Value jsonValue) {
+ return jsonValue.asUInt64();
+ }
static SkString make_filename(const char path[],
const char renderModeDescriptor[],
@@ -54,27 +73,69 @@ namespace skiagm {
public:
/**
* No expectations at all.
- *
- * We set ignoreFailure to false by default, but it doesn't really
- * matter... the result will always be "no-comparison" anyway.
*/
- Expectations(bool ignoreFailure=false) {
+ Expectations(bool ignoreFailure=kDefaultIgnoreFailure) {
fIgnoreFailure = ignoreFailure;
}
/**
* Expect exactly one image (appropriate for the case when we
* are comparing against a single PNG file).
- *
- * By default, DO NOT ignore failures.
*/
- Expectations(const SkBitmap& bitmap, bool ignoreFailure=false) {
+ Expectations(const SkBitmap& bitmap, bool ignoreFailure=kDefaultIgnoreFailure) {
fBitmap = bitmap;
fIgnoreFailure = ignoreFailure;
fAllowedChecksums.push_back() = SkBitmapChecksummer::Compute64(bitmap);
}
/**
+ * Create Expectations from a JSON element as found within the
+ * kJsonKey_ExpectedResults section.
+ *
+ * It's fine if the jsonElement is null or empty; in that case, we just
+ * don't have any expectations.
+ */
+ Expectations(Json::Value jsonElement) {
+ if (jsonElement.empty()) {
+ fIgnoreFailure = kDefaultIgnoreFailure;
+ } else {
+ Json::Value ignoreFailure = jsonElement[kJsonKey_ExpectedResults_IgnoreFailure];
+ if (ignoreFailure.isNull()) {
+ fIgnoreFailure = kDefaultIgnoreFailure;
+ } else if (!ignoreFailure.isBool()) {
+ fprintf(stderr, "found non-boolean json value for key '%s' in element '%s'\n",
+ kJsonKey_ExpectedResults_IgnoreFailure,
+ jsonElement.toStyledString().c_str());
+ DEBUGFAIL_SEE_STDERR;
+ fIgnoreFailure = kDefaultIgnoreFailure;
+ } else {
+ fIgnoreFailure = ignoreFailure.asBool();
+ }
+
+ Json::Value allowedChecksums = jsonElement[kJsonKey_ExpectedResults_Checksums];
+ if (allowedChecksums.isNull()) {
+ // ok, we'll just assume there aren't any expected checksums to compare against
+ } else if (!allowedChecksums.isArray()) {
+ fprintf(stderr, "found non-array json value for key '%s' in element '%s'\n",
+ kJsonKey_ExpectedResults_Checksums,
+ jsonElement.toStyledString().c_str());
+ DEBUGFAIL_SEE_STDERR;
+ } else {
+ for (Json::ArrayIndex i=0; i<allowedChecksums.size(); i++) {
+ Json::Value checksumElement = allowedChecksums[i];
+ if (!checksumElement.isIntegral()) {
+ fprintf(stderr, "found non-integer checksum in json element '%s'\n",
+ jsonElement.toStyledString().c_str());
+ DEBUGFAIL_SEE_STDERR;
+ } else {
+ fAllowedChecksums.push_back() = asChecksum(checksumElement);
+ }
+ }
+ }
+ }
+ }
+
+ /**
* Returns true iff we want to ignore failed expectations.
*/
bool ignoreFailure() const { return this->fIgnoreFailure; }
@@ -126,6 +187,8 @@ namespace skiagm {
}
private:
+ const static bool kDefaultIgnoreFailure = false;
+
SkTArray<Checksum> fAllowedChecksums;
bool fIgnoreFailure;
SkBitmap fBitmap;
@@ -181,5 +244,119 @@ namespace skiagm {
const bool fNotifyOfMissingFiles;
};
+ /**
+ * Return Expectations based on JSON summary file.
+ */
+ class JsonExpectationsSource : public ExpectationsSource {
+ public:
+ /**
+ * Create an ExpectationsSource that will return Expectations based on
+ * a JSON file.
+ *
+ * jsonPath: path to JSON file to read
+ */
+ JsonExpectationsSource(const char *jsonPath) {
+ parse(jsonPath, &fJsonRoot);
+ fJsonExpectedResults = fJsonRoot[kJsonKey_ExpectedResults];
+ }
+
+ Expectations get(const char *testName) SK_OVERRIDE {
+ return Expectations(fJsonExpectedResults[testName]);
+ }
+
+ private:
+
+ /**
+ * Read as many bytes as possible (up to maxBytes) from the stream into
+ * an SkData object.
+ *
+ * If the returned SkData contains fewer than maxBytes, then EOF has been
+ * reached and no more data would be available from subsequent calls.
+ * (If EOF has already been reached, then this call will return an empty
+ * SkData object immediately.)
+ *
+ * If there are fewer than maxBytes bytes available to read from the
+ * stream, but the stream has not been closed yet, this call will block
+ * until there are enough bytes to read or the stream has been closed.
+ *
+ * It is up to the caller to call unref() on the returned SkData object
+ * once the data is no longer needed, so that the underlying buffer will
+ * be freed. For example:
+ *
+ * {
+ * size_t maxBytes = 256;
+ * SkAutoDataUnref dataRef(readIntoSkData(stream, maxBytes));
+ * if (NULL != dataRef.get()) {
+ * size_t bytesActuallyRead = dataRef.get()->size();
+ * // use the data...
+ * }
+ * }
+ * // underlying buffer has been freed, thanks to auto unref
+ *
+ */
+ // TODO(epoger): Move this, into SkStream.[cpp|h] as attempted in
+ // https://codereview.appspot.com/7300071 ?
+ // And maybe readFileIntoSkData() also?
+ static SkData* readIntoSkData(SkStream &stream, size_t maxBytes) {
+ if (0 == maxBytes) {
+ return SkData::NewEmpty();
+ }
+ char* bufStart = reinterpret_cast<char *>(sk_malloc_throw(maxBytes));
+ char* bufPtr = bufStart;
+ size_t bytesRemaining = maxBytes;
+ while (bytesRemaining > 0) {
+ size_t bytesReadThisTime = stream.read(bufPtr, bytesRemaining);
+ if (0 == bytesReadThisTime) {
+ break;
+ }
+ bytesRemaining -= bytesReadThisTime;
+ bufPtr += bytesReadThisTime;
+ }
+ return SkData::NewFromMalloc(bufStart, maxBytes - bytesRemaining);
+ }
+
+ /**
+ * Wrapper around readIntoSkData for files: reads the entire file into
+ * an SkData object.
+ */
+ static SkData* readFileIntoSkData(SkFILEStream &stream) {
+ return readIntoSkData(stream, stream.getLength());
+ }
+
+ /**
+ * Read the file contents from jsonPath and parse them into jsonRoot.
+ *
+ * Returns true if successful.
+ */
+ static bool parse(const char *jsonPath, Json::Value *jsonRoot) {
+ SkFILEStream inFile(jsonPath);
+ if (!inFile.isValid()) {
+ fprintf(stderr, "unable to read JSON file %s\n", jsonPath);
+ DEBUGFAIL_SEE_STDERR;
+ return false;
+ }
+
+ SkAutoDataUnref dataRef(readFileIntoSkData(inFile));
+ if (NULL == dataRef.get()) {
+ fprintf(stderr, "error reading JSON file %s\n", jsonPath);
+ DEBUGFAIL_SEE_STDERR;
+ return false;
+ }
+
+ const char *bytes = reinterpret_cast<const char *>(dataRef.get()->data());
+ size_t size = dataRef.get()->size();
+ Json::Reader reader;
+ if (!reader.parse(bytes, bytes+size, *jsonRoot)) {
+ fprintf(stderr, "error parsing JSON file %s\n", jsonPath);
+ DEBUGFAIL_SEE_STDERR;
+ return false;
+ }
+ return true;
+ }
+
+ Json::Value fJsonRoot;
+ Json::Value fJsonExpectedResults;
+ };
+
}
#endif
diff --git a/gm/gmmain.cpp b/gm/gmmain.cpp
index da7b79e70b..a3e28338a6 100644
--- a/gm/gmmain.cpp
+++ b/gm/gmmain.cpp
@@ -94,17 +94,6 @@ const static ErrorBitfield ERROR_IMAGE_MISMATCH = 0x02;
const static ErrorBitfield ERROR_READING_REFERENCE_IMAGE = 0x08;
const static ErrorBitfield ERROR_WRITING_REFERENCE_IMAGE = 0x10;
-const static char kJsonKey_ActualResults[] = "actual-results";
-const static char kJsonKey_ActualResults_Failed[] = "failed";
-const static char kJsonKey_ActualResults_FailureIgnored[]= "failure-ignored";
-const static char kJsonKey_ActualResults_NoComparison[] = "no-comparison";
-const static char kJsonKey_ActualResults_Succeeded[] = "succeeded";
-const static char kJsonKey_ActualResults_AnyStatus_Checksum[] = "checksum";
-
-const static char kJsonKey_ExpectedResults[] = "expected-results";
-const static char kJsonKey_ExpectedResults_Checksums[] = "checksums";
-const static char kJsonKey_ExpectedResults_IgnoreFailure[] = "ignore-failure";
-
using namespace skiagm;
struct FailRec {
@@ -1392,10 +1381,10 @@ int tool_main(int argc, char** argv) {
IndividualImageExpectationsSource,
(readPath, notifyMissingReadReference)));
} else {
- fprintf(stderr, "reading expectations from JSON summary file %s ",
+ fprintf(stderr, "reading expectations from JSON summary file %s\n",
readPath);
- fprintf(stderr, "BUT WE DON'T KNOW HOW TO DO THIS YET!\n");
- return -1;
+ gmmain.fExpectationsSource.reset(SkNEW_ARGS(
+ JsonExpectationsSource, (readPath)));
}
}
if (writePath) {
diff --git a/gm/tests/outputs/compared-against-different-pixels-json/output-expected/command_line b/gm/tests/outputs/compared-against-different-pixels-json/output-expected/command_line
new file mode 100644
index 0000000000..1226cf28fc
--- /dev/null
+++ b/gm/tests/outputs/compared-against-different-pixels-json/output-expected/command_line
@@ -0,0 +1 @@
+out/Debug/gm --hierarchy --match dashing2 --config 8888 --config 565 -r gm/tests/inputs/json/different-pixels.json --writeJsonSummary gm/tests/outputs/compared-against-different-pixels-json/output-actual/json-summary.txt
diff --git a/gm/tests/outputs/compared-against-different-pixels-json/output-expected/json-summary.txt b/gm/tests/outputs/compared-against-different-pixels-json/output-expected/json-summary.txt
new file mode 100644
index 0000000000..37709e1ffc
--- /dev/null
+++ b/gm/tests/outputs/compared-against-different-pixels-json/output-expected/json-summary.txt
@@ -0,0 +1,25 @@
+{
+ "actual-results" : {
+ "failed" : {
+ "565/dashing2" : {
+ "checksum" : FAKE
+ },
+ "8888/dashing2" : {
+ "checksum" : FAKE
+ }
+ },
+ "failure-ignored" : null,
+ "no-comparison" : null,
+ "succeeded" : null
+ },
+ "expected-results" : {
+ "565/dashing2" : {
+ "checksums" : [ FAKE ],
+ "ignore-failure" : false
+ },
+ "8888/dashing2" : {
+ "checksums" : [ FAKE ],
+ "ignore-failure" : false
+ }
+ }
+}
diff --git a/gm/tests/outputs/compared-against-different-pixels-json/output-expected/return_value b/gm/tests/outputs/compared-against-different-pixels-json/output-expected/return_value
new file mode 100644
index 0000000000..ace9d03621
--- /dev/null
+++ b/gm/tests/outputs/compared-against-different-pixels-json/output-expected/return_value
@@ -0,0 +1 @@
+255
diff --git a/gm/tests/outputs/compared-against-different-pixels-json/output-expected/stdout b/gm/tests/outputs/compared-against-different-pixels-json/output-expected/stdout
new file mode 100644
index 0000000000..9194b40bf5
--- /dev/null
+++ b/gm/tests/outputs/compared-against-different-pixels-json/output-expected/stdout
@@ -0,0 +1,3 @@
+reading expectations from JSON summary file gm/tests/inputs/json/different-pixels.json
+drawing... dashing2 [640 480]
+Ran 1 tests: 0 passed, 1 failed, 0 missing reference images
diff --git a/gm/tests/outputs/compared-against-identical-bytes-json/output-expected/command_line b/gm/tests/outputs/compared-against-identical-bytes-json/output-expected/command_line
new file mode 100644
index 0000000000..e8fb0b97e6
--- /dev/null
+++ b/gm/tests/outputs/compared-against-identical-bytes-json/output-expected/command_line
@@ -0,0 +1 @@
+out/Debug/gm --hierarchy --match dashing2 --config 8888 --config 565 -r gm/tests/inputs/json/identical-bytes.json --writeJsonSummary gm/tests/outputs/compared-against-identical-bytes-json/output-actual/json-summary.txt
diff --git a/gm/tests/outputs/compared-against-identical-bytes-json/output-expected/json-summary.txt b/gm/tests/outputs/compared-against-identical-bytes-json/output-expected/json-summary.txt
new file mode 100644
index 0000000000..bed3b2d3b4
--- /dev/null
+++ b/gm/tests/outputs/compared-against-identical-bytes-json/output-expected/json-summary.txt
@@ -0,0 +1,25 @@
+{
+ "actual-results" : {
+ "failed" : null,
+ "failure-ignored" : null,
+ "no-comparison" : null,
+ "succeeded" : {
+ "565/dashing2" : {
+ "checksum" : FAKE
+ },
+ "8888/dashing2" : {
+ "checksum" : FAKE
+ }
+ }
+ },
+ "expected-results" : {
+ "565/dashing2" : {
+ "checksums" : [ FAKE ],
+ "ignore-failure" : false
+ },
+ "8888/dashing2" : {
+ "checksums" : [ FAKE ],
+ "ignore-failure" : false
+ }
+ }
+}
diff --git a/gm/tests/outputs/compared-against-identical-bytes-json/output-expected/return_value b/gm/tests/outputs/compared-against-identical-bytes-json/output-expected/return_value
new file mode 100644
index 0000000000..573541ac97
--- /dev/null
+++ b/gm/tests/outputs/compared-against-identical-bytes-json/output-expected/return_value
@@ -0,0 +1 @@
+0
diff --git a/gm/tests/outputs/compared-against-identical-bytes-json/output-expected/stdout b/gm/tests/outputs/compared-against-identical-bytes-json/output-expected/stdout
new file mode 100644
index 0000000000..afa854c231
--- /dev/null
+++ b/gm/tests/outputs/compared-against-identical-bytes-json/output-expected/stdout
@@ -0,0 +1,3 @@
+reading expectations from JSON summary file gm/tests/inputs/json/identical-bytes.json
+drawing... dashing2 [640 480]
+Ran 1 tests: 1 passed, 0 failed, 0 missing reference images
diff --git a/gm/tests/outputs/compared-against-identical-pixels-json/output-expected/command_line b/gm/tests/outputs/compared-against-identical-pixels-json/output-expected/command_line
new file mode 100644
index 0000000000..a596064846
--- /dev/null
+++ b/gm/tests/outputs/compared-against-identical-pixels-json/output-expected/command_line
@@ -0,0 +1 @@
+out/Debug/gm --hierarchy --match dashing2 --config 8888 --config 565 -r gm/tests/inputs/json/identical-pixels.json --writeJsonSummary gm/tests/outputs/compared-against-identical-pixels-json/output-actual/json-summary.txt
diff --git a/gm/tests/outputs/compared-against-identical-pixels-json/output-expected/json-summary.txt b/gm/tests/outputs/compared-against-identical-pixels-json/output-expected/json-summary.txt
new file mode 100644
index 0000000000..bed3b2d3b4
--- /dev/null
+++ b/gm/tests/outputs/compared-against-identical-pixels-json/output-expected/json-summary.txt
@@ -0,0 +1,25 @@
+{
+ "actual-results" : {
+ "failed" : null,
+ "failure-ignored" : null,
+ "no-comparison" : null,
+ "succeeded" : {
+ "565/dashing2" : {
+ "checksum" : FAKE
+ },
+ "8888/dashing2" : {
+ "checksum" : FAKE
+ }
+ }
+ },
+ "expected-results" : {
+ "565/dashing2" : {
+ "checksums" : [ FAKE ],
+ "ignore-failure" : false
+ },
+ "8888/dashing2" : {
+ "checksums" : [ FAKE ],
+ "ignore-failure" : false
+ }
+ }
+}
diff --git a/gm/tests/outputs/compared-against-identical-pixels-json/output-expected/return_value b/gm/tests/outputs/compared-against-identical-pixels-json/output-expected/return_value
new file mode 100644
index 0000000000..573541ac97
--- /dev/null
+++ b/gm/tests/outputs/compared-against-identical-pixels-json/output-expected/return_value
@@ -0,0 +1 @@
+0
diff --git a/gm/tests/outputs/compared-against-identical-pixels-json/output-expected/stdout b/gm/tests/outputs/compared-against-identical-pixels-json/output-expected/stdout
new file mode 100644
index 0000000000..3b2671aad5
--- /dev/null
+++ b/gm/tests/outputs/compared-against-identical-pixels-json/output-expected/stdout
@@ -0,0 +1,3 @@
+reading expectations from JSON summary file gm/tests/inputs/json/identical-pixels.json
+drawing... dashing2 [640 480]
+Ran 1 tests: 1 passed, 0 failed, 0 missing reference images
diff --git a/gm/tests/run.sh b/gm/tests/run.sh
index e1b6ce7707..a90db38b2b 100755
--- a/gm/tests/run.sh
+++ b/gm/tests/run.sh
@@ -145,12 +145,15 @@ create_inputs_dir $GM_INPUTS
# Compare generated image against an input image file with identical bytes.
gm_test "--hierarchy --match dashing2 $CONFIGS -r $GM_INPUTS/images/identical-bytes" "$GM_OUTPUTS/compared-against-identical-bytes-images"
+gm_test "--hierarchy --match dashing2 $CONFIGS -r $GM_INPUTS/json/identical-bytes.json" "$GM_OUTPUTS/compared-against-identical-bytes-json"
# Compare generated image against an input image file with identical pixels but different PNG encoding.
gm_test "--hierarchy --match dashing2 $CONFIGS -r $GM_INPUTS/images/identical-pixels" "$GM_OUTPUTS/compared-against-identical-pixels-images"
+gm_test "--hierarchy --match dashing2 $CONFIGS -r $GM_INPUTS/json/identical-pixels.json" "$GM_OUTPUTS/compared-against-identical-pixels-json"
# Compare generated image against an input image file with different pixels.
gm_test "--hierarchy --match dashing2 $CONFIGS -r $GM_INPUTS/images/different-pixels" "$GM_OUTPUTS/compared-against-different-pixels-images"
+gm_test "--hierarchy --match dashing2 $CONFIGS -r $GM_INPUTS/json/different-pixels.json" "$GM_OUTPUTS/compared-against-different-pixels-json"
# Compare generated image against an empty "expected image" dir.
gm_test "--hierarchy --match dashing2 $CONFIGS -r $GM_INPUTS/images/empty-dir" "$GM_OUTPUTS/compared-against-empty-dir"