1 : // Copyright 2015 Google Inc. All Rights Reserved.
2 : //
3 : // Licensed under the Apache License, Version 2.0 (the "License");
4 : // you may not use this file except in compliance with the License.
5 : // You may obtain a copy of the License at
6 : //
7 : // http://www.apache.org/licenses/LICENSE-2.0
8 : //
9 : // Unless required by applicable law or agreed to in writing, software
10 : // distributed under the License is distributed on an "AS IS" BASIS,
11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : // See the License for the specific language governing permissions and
13 : // limitations under the License.
14 :
15 : #include "syzygy/crashdata/json.h"
16 :
17 : #include "gtest/gtest.h"
18 :
19 : namespace crashdata {
20 :
21 : namespace {
22 :
23 : void TestConversion(bool pretty_print,
24 : const Value& value,
25 E : const char* expected_json) {
26 E : std::string json;
27 E : EXPECT_TRUE(ToJson(pretty_print, &value, &json));
28 E : EXPECT_EQ(json, expected_json);
29 E : }
30 :
31 : } // namespace
32 :
33 E : TEST(CrashDataJsonTest, BadValueFails) {
34 E : Value value;
35 E : std::string json;
36 :
37 E : for (size_t i = Value_Type_Type_MIN; i <= Value_Type_Type_MAX; ++i) {
38 E : value.set_type(static_cast<Value_Type>(i));
39 E : EXPECT_FALSE(ToJson(true, &value, &json));
40 E : EXPECT_TRUE(json.empty());
41 E : }
42 E : }
43 :
44 E : TEST(CrashDataJsonTest, BadLeafFails) {
45 E : Value value;
46 E : Leaf* leaf = ValueGetLeaf(&value);
47 E : std::string json;
48 :
49 E : for (size_t i = Leaf_Type_Type_MIN; i <= Leaf_Type_Type_MAX; ++i) {
50 E : leaf->set_type(static_cast<Leaf_Type>(i));
51 E : EXPECT_FALSE(ToJson(true, &value, &json));
52 E : EXPECT_TRUE(json.empty());
53 E : }
54 E : }
55 :
56 E : TEST(CrashDataJsonTest, BadKeyValue) {
57 E : Value value;
58 E : value.set_type(Value_Type_DICTIONARY);
59 E : Dictionary* dict = value.mutable_dictionary();
60 E : KeyValue* kv = dict->add_values();
61 E : std::string json;
62 :
63 : // No key and no value should fail.
64 E : EXPECT_FALSE(ToJson(true, &value, &json));
65 E : EXPECT_TRUE(json.empty());
66 :
67 : // A key and no value should fail.
68 E : kv->set_key("key");
69 E : EXPECT_FALSE(ToJson(true, &value, &json));
70 E : EXPECT_TRUE(json.empty());
71 :
72 : // No key and a valid value should fail.
73 E : kv->clear_key();
74 E : Value* value2 = kv->mutable_value();
75 E : Leaf* leaf = ValueGetLeaf(value2);
76 E : leaf->set_type(Leaf_Type_INTEGER);
77 E : leaf->set_integer(42);
78 E : EXPECT_FALSE(ToJson(true, &value, &json));
79 E : EXPECT_TRUE(json.empty());
80 E : }
81 :
82 E : TEST(CrashDataJsonTest, ValueLeafInteger) {
83 E : Value value;
84 E : LeafSetInt(-48, ValueGetLeaf(&value));
85 :
86 E : const char kExpected[] = "-48";
87 E : TestConversion(true, value, kExpected);
88 E : TestConversion(false, value, kExpected);;
89 E : }
90 :
91 E : TEST(CrashDataJsonTest, ValueLeafUnsignedInteger) {
92 E : Value value;
93 E : LeafSetUInt(653, ValueGetLeaf(&value));
94 :
95 E : const char kExpected[] = "653";
96 E : TestConversion(true, value, kExpected);
97 E : TestConversion(false, value, kExpected);;
98 E : }
99 :
100 E : TEST(CrashDataJsonTest, ValueLeafReal) {
101 E : Value value;
102 E : LeafSetReal(2.0e99, ValueGetLeaf(&value));
103 :
104 E : const char kExpected[] = "1.9999999999999999E+99";
105 E : TestConversion(true, value, kExpected);
106 E : TestConversion(false, value, kExpected);
107 E : }
108 :
109 E : TEST(CrashDataJsonTest, ValueLeafString) {
110 E : Value value;
111 E : *LeafGetString(ValueGetLeaf(&value)) = "foo \"\\ bar";
112 :
113 E : const char kExpected[] = "\"foo \\\"\\\\ bar\"";
114 E : TestConversion(true, value, kExpected);
115 E : TestConversion(false, value, kExpected);
116 E : }
117 :
118 E : TEST(CrashDataJsonTest, ValueLeafAddress) {
119 E : Value value;
120 E : LeafGetAddress(ValueGetLeaf(&value))->set_address(0xBADBEEF);
121 :
122 E : const char kExpected[] = "\"0x0BADBEEF\"";
123 E : TestConversion(true, value, kExpected);
124 E : TestConversion(false, value, kExpected);;
125 E : }
126 :
127 E : TEST(CrashDataJsonTest, ValueLeafStackTrace) {
128 E : Value value;
129 E : StackTrace* stack = LeafGetStackTrace(ValueGetLeaf(&value));
130 E : stack->add_frames(0xDEADBEEF);
131 E : stack->add_frames(0xBADF00D);
132 E : stack->add_frames(0x10000000);
133 E : stack->add_frames(0x20000000);
134 E : stack->add_frames(0x30000000);
135 E : stack->add_frames(0x40000000);
136 :
137 E : const char kExpectedPretty[] =
138 : "[\n"
139 : " \"0xDEADBEEF\", \"0x0BADF00D\", \"0x10000000\", \"0x20000000\",\n"
140 : " \"0x30000000\", \"0x40000000\"\n"
141 : "]";
142 E : TestConversion(true, value, kExpectedPretty);
143 :
144 E : const char kExpectedCompact[] = "[\"0xDEADBEEF\",\"0x0BADF00D\","
145 : "\"0x10000000\",\"0x20000000\",\"0x30000000\",\"0x40000000\"]";
146 E : TestConversion(false, value, kExpectedCompact);
147 E : }
148 :
149 E : TEST(CrashDataJsonTest, ValueLeafBlob) {
150 E : Value value;
151 E : Blob* blob = LeafGetBlob(ValueGetLeaf(&value));
152 E : blob->mutable_address()->set_address(0xF00);
153 E : std::string* data = blob->mutable_data();
154 E : for (size_t i = 0; i < 3; ++i) {
155 E : data->push_back(static_cast<unsigned char>(0xDE));
156 E : data->push_back(static_cast<unsigned char>(0xAD));
157 E : data->push_back(static_cast<unsigned char>(0xBE));
158 E : data->push_back(static_cast<unsigned char>(0xEF));
159 E : }
160 :
161 E : const char kExpectedPretty[] =
162 : "{\n"
163 : " \"type\": \"blob\",\n"
164 : " \"address\": \"0x00000F00\",\n"
165 : " \"size\": null,\n"
166 : " \"data\": [\n"
167 : " \"0xDE\", \"0xAD\", \"0xBE\", \"0xEF\", \"0xDE\", \"0xAD\","
168 : " \"0xBE\", \"0xEF\",\n"
169 : " \"0xDE\", \"0xAD\", \"0xBE\", \"0xEF\"\n"
170 : " ]\n"
171 : "}";
172 E : TestConversion(true, value, kExpectedPretty);
173 :
174 E : const char kExpectedCompact[] =
175 : "{\"type\":\"blob\",\"address\":\"0x00000F00\",\"size\":null,"
176 : "\"data\":[\"0xDE\",\"0xAD\",\"0xBE\",\"0xEF\",\"0xDE\",\"0xAD\","
177 : "\"0xBE\",\"0xEF\",\"0xDE\",\"0xAD\",\"0xBE\",\"0xEF\"]}";
178 E : TestConversion(false, value, kExpectedCompact);
179 E : }
180 :
181 E : TEST(CrashDataJsonTest, ValueList) {
182 E : Value value;
183 E : ValueList* list = ValueGetValueList(&value);
184 :
185 E : LeafGetAddress(ValueGetLeaf(list->add_values()))->set_address(0xDEADF00D);
186 E : LeafSetInt(42, ValueGetLeaf(list->add_values()));
187 :
188 E : const char kExpectedPretty[] =
189 : "[\n"
190 : " \"0xDEADF00D\",\n"
191 : " 42\n"
192 : "]";
193 E : TestConversion(true, value, kExpectedPretty);
194 :
195 E : const char kExpectedCompact[] = "[\"0xDEADF00D\",42]";
196 E : TestConversion(false, value, kExpectedCompact);
197 E : }
198 :
199 E : TEST(CrashDataJsonTest, ValueDict) {
200 E : Value value;
201 E : Dictionary* dict = ValueGetDict(&value);
202 :
203 E : LeafGetAddress(ValueGetLeaf(DictAddValue("key1", dict)))->set_address(
204 : 0xDEADF00D);
205 E : LeafSetInt(42, ValueGetLeaf(DictAddValue("key2", dict)));
206 :
207 E : const char kExpectedPretty[] =
208 : "{\n"
209 : " \"key1\": \"0xDEADF00D\",\n"
210 : " \"key2\": 42\n"
211 : "}";
212 E : TestConversion(true, value, kExpectedPretty);
213 :
214 E : const char kExpectedCompact[] = "{\"key1\":\"0xDEADF00D\",\"key2\":42}";
215 E : TestConversion(false, value, kExpectedCompact);
216 E : }
217 :
218 E : TEST(CrashDataJsonTest, AllTypes) {
219 E : Value value;
220 E : value.set_type(Value_Type_DICTIONARY);
221 E : Dictionary* dict = value.mutable_dictionary();
222 :
223 : // One of each type of leaf.
224 E : LeafSetInt(-42, ValueGetLeaf(DictAddValue("int", dict)));
225 E : LeafSetUInt(42, ValueGetLeaf(DictAddValue("uint", dict)));
226 E : LeafSetReal(2.0e99, ValueGetLeaf(DictAddValue("real", dict)));
227 E : *LeafGetString(ValueGetLeaf(DictAddValue("string", dict))) = "foobar";
228 E : LeafGetAddress(ValueGetLeaf(DictAddValue("address", dict)))->set_address(
229 : 0xDEADF00D);
230 : LeafGetStackTrace(ValueGetLeaf(DictAddValue("stack-trace", dict)))
231 E : ->add_frames(0xBAADBEEF);
232 : LeafGetBlob(ValueGetLeaf(DictAddValue("blob", dict)))->mutable_data()
233 E : ->append("hey");
234 :
235 : // Nested dictionary with a single element.
236 E : LeafSetInt(100, ValueGetLeaf(DictAddValue("INT", ValueGetDict(
237 : DictAddValue("dict", dict)))));
238 :
239 : // Nested list with a single element
240 E : ValueList* list = ValueGetValueList(DictAddValue("list", dict));
241 E : LeafSetInt(200, ValueGetLeaf(list->add_values()));
242 :
243 E : const char kExpectedPretty[] =
244 : "{\n"
245 : " \"int\": -42,\n"
246 : " \"uint\": 42,\n"
247 : " \"real\": 1.9999999999999999E+99,\n"
248 : " \"string\": \"foobar\",\n"
249 : " \"address\": \"0xDEADF00D\",\n"
250 : " \"stack-trace\": [\n"
251 : " \"0xBAADBEEF\"\n"
252 : " ],\n"
253 : " \"blob\": {\n"
254 : " \"type\": \"blob\",\n"
255 : " \"address\": null,\n"
256 : " \"size\": null,\n"
257 : " \"data\": [\n"
258 : " \"0x68\", \"0x65\", \"0x79\"\n"
259 : " ]\n"
260 : " },\n"
261 : " \"dict\": {\n"
262 : " \"INT\": 100\n"
263 : " },\n"
264 : " \"list\": [\n"
265 : " 200\n"
266 : " ]\n"
267 : "}";
268 E : TestConversion(true, value, kExpectedPretty);
269 :
270 E : const char kExpectedCompact[] =
271 : "{"
272 : "\"int\":-42,"
273 : "\"uint\":42,"
274 : "\"real\":1.9999999999999999E+99,"
275 : "\"string\":\"foobar\","
276 : "\"address\":\"0xDEADF00D\","
277 : "\"stack-trace\":[\"0xBAADBEEF\"],"
278 : "\"blob\":{"
279 : "\"type\":\"blob\","
280 : "\"address\":null,"
281 : "\"size\":null,"
282 : "\"data\":[\"0x68\",\"0x65\",\"0x79\"]"
283 : "},"
284 : "\"dict\":{"
285 : "\"INT\":100"
286 : "},"
287 : "\"list\":["
288 : "200"
289 : "]"
290 : "}";
291 E : TestConversion(false, value, kExpectedCompact);
292 E : }
293 :
294 : } // namespace crashdata
|