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 "SkJSONCPP.h"
14 #include "SkMutex.h"
15 #include "SkOSFile.h"
16 #include "SkStream.h"
17 #include "SkTArray.h"
18 
19 namespace DM {
20 
21 SkTArray<JsonWriter::BitmapResult> gBitmapResults;
22 SK_DECLARE_STATIC_MUTEX(gBitmapResultLock);
23 
AddBitmapResult(const BitmapResult & result)24 void JsonWriter::AddBitmapResult(const BitmapResult& result) {
25     SkAutoMutexAcquire lock(&gBitmapResultLock);
26     gBitmapResults.push_back(result);
27 }
28 
29 SkTArray<skiatest::Failure> gFailures;
30 SK_DECLARE_STATIC_MUTEX(gFailureLock);
31 
AddTestFailure(const skiatest::Failure & failure)32 void JsonWriter::AddTestFailure(const skiatest::Failure& failure) {
33     SkAutoMutexAcquire lock(gFailureLock);
34     gFailures.push_back(failure);
35 }
36 
DumpJson()37 void JsonWriter::DumpJson() {
38     if (FLAGS_writePath.isEmpty()) {
39         return;
40     }
41 
42     Json::Value root;
43 
44     for (int i = 1; i < FLAGS_properties.count(); i += 2) {
45         root[FLAGS_properties[i-1]] = FLAGS_properties[i];
46     }
47     for (int i = 1; i < FLAGS_key.count(); i += 2) {
48         root["key"][FLAGS_key[i-1]] = FLAGS_key[i];
49     }
50 
51     {
52         SkAutoMutexAcquire lock(&gBitmapResultLock);
53         for (int i = 0; i < gBitmapResults.count(); i++) {
54             Json::Value result;
55             result["key"]["name"]        = gBitmapResults[i].name.c_str();
56             result["key"]["config"]      = gBitmapResults[i].config.c_str();
57             result["key"]["source_type"] = gBitmapResults[i].sourceType.c_str();
58             result["options"]["ext"]     = gBitmapResults[i].ext.c_str();
59             result["md5"]                = gBitmapResults[i].md5.c_str();
60 
61             // Source options only need to be part of the key if they exist.
62             // Source type by source type, we either always set options or never set options.
63             if (!gBitmapResults[i].sourceOptions.isEmpty()) {
64                 result["key"]["source_options"] = gBitmapResults[i].sourceOptions.c_str();
65             }
66 
67             root["results"].append(result);
68         }
69     }
70 
71     {
72         SkAutoMutexAcquire lock(gFailureLock);
73         for (int i = 0; i < gFailures.count(); i++) {
74             Json::Value result;
75             result["file_name"]     = gFailures[i].fileName;
76             result["line_no"]       = gFailures[i].lineNo;
77             result["condition"]     = gFailures[i].condition;
78             result["message"]       = gFailures[i].message.c_str();
79 
80             root["test_results"]["failures"].append(result);
81         }
82     }
83 
84     int maxResidentSetSizeMB = sk_tools::getMaxResidentSetSizeMB();
85     if (maxResidentSetSizeMB != -1) {
86         root["max_rss_MB"] = sk_tools::getMaxResidentSetSizeMB();
87     }
88 
89     SkString path = SkOSPath::Join(FLAGS_writePath[0], "dm.json");
90     sk_mkdir(FLAGS_writePath[0]);
91     SkFILEWStream stream(path.c_str());
92     stream.writeText(Json::StyledWriter().write(root).c_str());
93     stream.flush();
94 }
95 
ReadJson(const char * path,void (* callback)(BitmapResult))96 bool JsonWriter::ReadJson(const char* path, void(*callback)(BitmapResult)) {
97     SkAutoTUnref<SkData> json(SkData::NewFromFileName(path));
98     if (!json) {
99         return false;
100     }
101 
102     Json::Reader reader;
103     Json::Value root;
104     const char* data = (const char*)json->data();
105     if (!reader.parse(data, data+json->size(), root)) {
106         return false;
107     }
108 
109     const Json::Value& results = root["results"];
110     BitmapResult br;
111     for (unsigned i = 0; i < results.size(); i++) {
112         const Json::Value& r = results[i];
113         br.name       = r["key"]["name"].asCString();
114         br.config     = r["key"]["config"].asCString();
115         br.sourceType = r["key"]["source_type"].asCString();
116         br.ext        = r["options"]["ext"].asCString();
117         br.md5        = r["md5"].asCString();
118 
119         if (!r["key"]["source_options"].isNull()) {
120             br.sourceOptions = r["key"]["source_options"].asCString();
121         }
122         callback(br);
123     }
124     return true;
125 }
126 
127 } // namespace DM
128