From 62bd1a69ea49318aa5022151262c842887e0ecf4 Mon Sep 17 00:00:00 2001 From: mtklein Date: Tue, 27 Jan 2015 14:46:26 -0800 Subject: add -r to DM $ out/Debug/dm -w good $ out/Debug/dm -r good -w bad && echo "hooray no diffs!" BUG=skia: Review URL: https://codereview.chromium.org/863093003 --- dm/DM.cpp | 91 +++++++++++++++++++++++++++++++++++++++++++---------- dm/DMJsonWriter.cpp | 28 +++++++++++++++++ dm/DMJsonWriter.h | 7 +++++ 3 files changed, 110 insertions(+), 16 deletions(-) diff --git a/dm/DM.cpp b/dm/DM.cpp index 708d8558f3..5b99a4c214 100644 --- a/dm/DM.cpp +++ b/dm/DM.cpp @@ -4,11 +4,13 @@ #include "OverwriteLine.h" #include "ProcStats.h" #include "SkBBHFactory.h" +#include "SkChecksum.h" #include "SkCommonFlags.h" #include "SkForceLinking.h" #include "SkGraphics.h" #include "SkMD5.h" #include "SkOSFile.h" +#include "SkTDynamicHash.h" #include "SkTaskGroup.h" #include "Test.h" #include "Timer.h" @@ -28,6 +30,8 @@ DEFINE_string(blacklist, "", "'--blacklist gpu skp _' will blacklist all SKPs drawn into the gpu config.\n" "'--blacklist gpu skp _ 8888 gm aarects' will also blacklist the aarects GM on 8888."); +DEFINE_string2(readPath, r, "", "If set check for equality with golden results in this directory."); + __SK_FORCE_IMAGE_DECODER_LINKING; using namespace DM; @@ -62,6 +66,40 @@ static void done(double ms, ImplicitString config, ImplicitString src, ImplicitS /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ +struct Gold : public SkString { + Gold(ImplicitString sink, ImplicitString src, ImplicitString name, ImplicitString md5) + : SkString("") { + this->append(sink); + this->append(src); + this->append(name); + this->append(md5); + while (this->size() % 4) { + this->append("!"); // Pad out if needed so we can pass this to Murmur3. + } + } + static const Gold& GetKey(const Gold& g) { return g; } + static uint32_t Hash(const Gold& g) { + return SkChecksum::Murmur3((const uint32_t*)g.c_str(), g.size()); + } +}; +static SkTDynamicHash gGold; + +static void add_gold(JsonWriter::BitmapResult r) { + gGold.add(new Gold(r.config, r.sourceType, r.name, r.md5)); // We'll let these leak. Lazybones. +} + +static void gather_gold() { + if (!FLAGS_readPath.isEmpty()) { + SkString path(FLAGS_readPath[0]); + path.append("/dm.json"); + if (!JsonWriter::ReadJson(path.c_str(), add_gold)) { + fail(SkStringPrintf("Couldn't read %s for golden results.", path.c_str())); + } + } +} + +/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ + template struct Tagged : public SkAutoTDelete { const char* tag; }; @@ -256,14 +294,40 @@ struct Task { name.c_str(), err.c_str())); } + SkAutoTDelete data(stream.detachAsStream()); + + SkString md5; + if (!FLAGS_writePath.isEmpty() || !FLAGS_readPath.isEmpty()) { + SkMD5 hash; + if (data->getLength()) { + hash.writeStream(data, data->getLength()); + data->rewind(); + } else { + hash.write(bitmap.getPixels(), bitmap.getSize()); + } + SkMD5::Digest digest; + hash.finish(digest); + for (int i = 0; i < 16; i++) { + md5.appendf("%02x", digest.data[i]); + } + } + + if (!FLAGS_readPath.isEmpty() && + !gGold.find(Gold(task->sink.tag, task->src.tag, name, md5))) { + fail(SkStringPrintf("%s not found for %s %s %s in %s", + md5.c_str(), + task->sink.tag, + task->src.tag, + name.c_str(), + FLAGS_readPath[0])); + } + if (!FLAGS_writePath.isEmpty()) { const char* ext = task->sink->fileExtension(); - if (stream.bytesWritten() == 0) { - SkMemoryStream pixels(bitmap.getPixels(), bitmap.getSize()); - WriteToDisk(*task, &pixels, bitmap.getSize(), &bitmap, ext); + if (data->getLength()) { + WriteToDisk(*task, md5, ext, data, data->getLength(), NULL); } else { - SkAutoTDelete data(stream.detachAsStream()); - WriteToDisk(*task, data, data->getLength(), NULL, ext); + WriteToDisk(*task, md5, ext, NULL, 0, &bitmap); } } } @@ -275,22 +339,16 @@ struct Task { } static void WriteToDisk(const Task& task, + SkString md5, + const char* ext, SkStream* data, size_t len, - const SkBitmap* bitmap, - const char* ext) { - SkMD5 hash; - hash.writeStream(data, len); - SkMD5::Digest digest; - hash.finish(digest); - + const SkBitmap* bitmap) { JsonWriter::BitmapResult result; result.name = task.src->name(); result.config = task.sink.tag; result.sourceType = task.src.tag; result.ext = ext; - for (int i = 0; i < 16; i++) { - result.md5.appendf("%02x", digest.data[i]); - } + result.md5 = md5; JsonWriter::AddBitmapResult(result); const char* dir = FLAGS_writePath[0]; @@ -323,7 +381,6 @@ struct Task { return; } - data->rewind(); if (bitmap) { // We can't encode A8 bitmaps as PNGs. Convert them to 8888 first. SkBitmap converted; @@ -418,6 +475,8 @@ int dm_main() { SkAutoGraphics ag; SkTaskGroup::Enabler enabled(FLAGS_threads); + gather_gold(); + gather_srcs(); gather_sinks(); gather_tests(); diff --git a/dm/DMJsonWriter.cpp b/dm/DMJsonWriter.cpp index 8aea814aed..56c1301df1 100644 --- a/dm/DMJsonWriter.cpp +++ b/dm/DMJsonWriter.cpp @@ -8,6 +8,7 @@ #include "DMJsonWriter.h" #include "SkCommonFlags.h" +#include "SkData.h" #include "SkJSONCPP.h" #include "SkOSFile.h" #include "SkStream.h" @@ -79,4 +80,31 @@ void JsonWriter::DumpJson() { stream.flush(); } +bool JsonWriter::ReadJson(const char* path, void(*callback)(BitmapResult)) { + SkAutoTUnref json(SkData::NewFromFileName(path)); + if (!json) { + return false; + } + + Json::Reader reader; + Json::Value root; + const char* data = (const char*)json->data(); + if (!reader.parse(data, data+json->size(), root)) { + return false; + } + + const Json::Value& results = root["results"]; + BitmapResult br; + for (unsigned i = 0; i < results.size(); i++) { + const Json::Value& r = results[i]; + br.name = r["key"]["name"].asCString(); + br.config = r["key"]["config"].asCString(); + br.sourceType = r["key"]["source_type"].asCString(); + br.ext = r["ext"].asCString(); + br.md5 = r["md5"].asCString(); + callback(br); + } + return true; +} + } // namespace DM diff --git a/dm/DMJsonWriter.h b/dm/DMJsonWriter.h index 58d85d358d..593484688b 100644 --- a/dm/DMJsonWriter.h +++ b/dm/DMJsonWriter.h @@ -44,7 +44,14 @@ public: * Write all collected results to the file FLAGS_writePath[0]/dm.json. */ static void DumpJson(); + + /** + * Read JSON file at path written by DumpJson, calling callback for each + * BitmapResult recorded in the file. Return success. + */ + static bool ReadJson(const char* path, void(*callback)(BitmapResult)); }; + } // namespace DM #endif // DMJsonWriter_DEFINED -- cgit v1.2.3