1 /* 2 * Copyright 2014 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 "DMJsonWriter.h" 9 10 #include "ProcStats.h" 11 #include "SkCommonFlags.h" 12 #include "SkData.h" 13 #include "SkJSON.h" 14 #include "SkJSONWriter.h" 15 #include "SkMutex.h" 16 #include "SkOSFile.h" 17 #include "SkOSPath.h" 18 #include "SkStream.h" 19 #include "SkTArray.h" 20 21 namespace DM { 22 23 SkTArray<JsonWriter::BitmapResult> gBitmapResults; 24 SK_DECLARE_STATIC_MUTEX(gBitmapResultLock); 25 26 void JsonWriter::AddBitmapResult(const BitmapResult& result) { 27 SkAutoMutexAcquire lock(&gBitmapResultLock); 28 gBitmapResults.push_back(result); 29 } 30 31 SkTArray<skiatest::Failure> gFailures; 32 SK_DECLARE_STATIC_MUTEX(gFailureLock); 33 34 void JsonWriter::AddTestFailure(const skiatest::Failure& failure) { 35 SkAutoMutexAcquire lock(gFailureLock); 36 gFailures.push_back(failure); 37 } 38 39 void JsonWriter::DumpJson() { 40 if (FLAGS_writePath.isEmpty()) { 41 return; 42 } 43 44 SkString path = SkOSPath::Join(FLAGS_writePath[0], "dm.json"); 45 sk_mkdir(FLAGS_writePath[0]); 46 SkFILEWStream stream(path.c_str()); 47 SkJSONWriter writer(&stream, SkJSONWriter::Mode::kPretty); 48 49 writer.beginObject(); // root 50 51 for (int i = 1; i < FLAGS_properties.count(); i += 2) { 52 writer.appendString(FLAGS_properties[i-1], FLAGS_properties[i]); 53 } 54 55 writer.beginObject("key"); 56 for (int i = 1; i < FLAGS_key.count(); i += 2) { 57 writer.appendString(FLAGS_key[i-1], FLAGS_key[i]); 58 } 59 writer.endObject(); 60 61 int maxResidentSetSizeMB = sk_tools::getMaxResidentSetSizeMB(); 62 if (maxResidentSetSizeMB != -1) { 63 writer.appendS32("max_rss_MB", maxResidentSetSizeMB); 64 } 65 66 { 67 SkAutoMutexAcquire lock(&gBitmapResultLock); 68 writer.beginArray("results"); 69 for (int i = 0; i < gBitmapResults.count(); i++) { 70 writer.beginObject(); 71 72 writer.beginObject("key"); 73 writer.appendString("name" , gBitmapResults[i].name.c_str()); 74 writer.appendString("config" , gBitmapResults[i].config.c_str()); 75 writer.appendString("source_type", gBitmapResults[i].sourceType.c_str()); 76 77 // Source options only need to be part of the key if they exist. 78 // Source type by source type, we either always set options or never set options. 79 if (!gBitmapResults[i].sourceOptions.isEmpty()) { 80 writer.appendString("source_options", gBitmapResults[i].sourceOptions.c_str()); 81 } 82 writer.endObject(); // key 83 84 writer.beginObject("options"); 85 writer.appendString("ext" , gBitmapResults[i].ext.c_str()); 86 writer.appendString("gamut", gBitmapResults[i].gamut.c_str()); 87 writer.appendString("transfer_fn", gBitmapResults[i].transferFn.c_str()); 88 writer.appendString("color_type", gBitmapResults[i].colorType.c_str()); 89 writer.appendString("alpha_type", gBitmapResults[i].alphaType.c_str()); 90 writer.appendString("color_depth", gBitmapResults[i].colorDepth.c_str()); 91 writer.endObject(); // options 92 93 writer.appendString("md5", gBitmapResults[i].md5.c_str()); 94 95 writer.endObject(); // 1 result 96 } 97 writer.endArray(); // results 98 } 99 100 { 101 SkAutoMutexAcquire lock(gFailureLock); 102 if (gFailures.count() > 0) { 103 writer.beginObject("test_results"); 104 writer.beginArray("failures"); 105 for (int i = 0; i < gFailures.count(); i++) { 106 writer.beginObject(); 107 writer.appendString("file_name", gFailures[i].fileName); 108 writer.appendS32 ("line_no" , gFailures[i].lineNo); 109 writer.appendString("condition", gFailures[i].condition); 110 writer.appendString("message" , gFailures[i].message.c_str()); 111 writer.endObject(); // 1 failure 112 } 113 writer.endArray(); // failures 114 writer.endObject(); // test_results 115 } 116 } 117 118 writer.endObject(); // root 119 writer.flush(); 120 stream.flush(); 121 } 122 123 using namespace skjson; 124 125 bool JsonWriter::ReadJson(const char* path, void(*callback)(BitmapResult)) { 126 sk_sp<SkData> json(SkData::MakeFromFileName(path)); 127 if (!json) { 128 return false; 129 } 130 131 DOM dom((const char*)json->data(), json->size()); 132 const ObjectValue* root = dom.root(); 133 if (!root) { 134 return false; 135 } 136 137 const ArrayValue* results = (*root)["results"]; 138 if (!results) { 139 return false; 140 } 141 142 BitmapResult br; 143 for (const ObjectValue* r : *results) { 144 const ObjectValue& key = (*r)["key"].as<ObjectValue>(); 145 const ObjectValue& options = (*r)["options"].as<ObjectValue>(); 146 147 br.name = key["name"].as<StringValue>().begin(); 148 br.config = key["config"].as<StringValue>().begin(); 149 br.sourceType = key["source_type"].as<StringValue>().begin(); 150 br.ext = options["ext"].as<StringValue>().begin(); 151 br.gamut = options["gamut"].as<StringValue>().begin(); 152 br.transferFn = options["transfer_fn"].as<StringValue>().begin(); 153 br.colorType = options["color_type"].as<StringValue>().begin(); 154 br.alphaType = options["alpha_type"].as<StringValue>().begin(); 155 br.colorDepth = options["color_depth"].as<StringValue>().begin(); 156 br.md5 = (*r)["md5"].as<StringValue>().begin(); 157 158 if (const StringValue* so = key["source_options"]) { 159 br.sourceOptions = so->begin(); 160 } 161 callback(br); 162 } 163 return true; 164 } 165 166 } // namespace DM 167