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
AddBitmapResult(const BitmapResult & result)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
AddTestFailure(const skiatest::Failure & failure)34 void JsonWriter::AddTestFailure(const skiatest::Failure& failure) {
35 SkAutoMutexAcquire lock(gFailureLock);
36 gFailures.push_back(failure);
37 }
38
DumpJson()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
ReadJson(const char * path,void (* callback)(BitmapResult))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