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+099";
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 : const char kExpectedPretty[] =
138 : "[\n"
139 : " 0xDEADBEEF, 0x0BADF00D, 0x10000000, 0x20000000,\n"
140 : " 0x30000000, 0x40000000\n"
141 E : "]";
142 E : TestConversion(true, value, kExpectedPretty);
143 :
144 : const char kExpectedCompact[] = "[0xDEADBEEF,0x0BADF00D,0x10000000,"
145 E : "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 : 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, 0xBE, 0xEF,\n"
168 : " 0xDE, 0xAD, 0xBE, 0xEF\n"
169 : " ]\n"
170 E : "}";
171 E : TestConversion(true, value, kExpectedPretty);
172 :
173 : const char kExpectedCompact[] =
174 : "{\"type\":\"blob\",\"address\":0x00000F00,\"size\":null,"
175 : "\"data\":[0xDE,0xAD,0xBE,0xEF,0xDE,0xAD,0xBE,0xEF,0xDE,0xAD,"
176 E : "0xBE,0xEF]}";
177 E : TestConversion(false, value, kExpectedCompact);
178 E : }
179 :
180 E : TEST(CrashDataJsonTest, ValueList) {
181 E : Value value;
182 E : List* list = ValueGetList(&value);
183 :
184 E : LeafGetAddress(ValueGetLeaf(list->add_values()))->set_address(0xDEADF00D);
185 E : LeafSetInt(42, ValueGetLeaf(list->add_values()));
186 :
187 : const char kExpectedPretty[] =
188 : "[\n"
189 : " 0xDEADF00D,\n"
190 : " 42\n"
191 E : "]";
192 E : TestConversion(true, value, kExpectedPretty);
193 :
194 E : const char kExpectedCompact[] = "[0xDEADF00D,42]";
195 E : TestConversion(false, value, kExpectedCompact);
196 E : }
197 :
198 E : TEST(CrashDataJsonTest, ValueDict) {
199 E : Value value;
200 E : Dictionary* dict = ValueGetDict(&value);
201 :
202 : LeafGetAddress(ValueGetLeaf(DictAddValue("key1", dict)))->set_address(
203 E : 0xDEADF00D);
204 E : LeafSetInt(42, ValueGetLeaf(DictAddValue("key2", dict)));
205 :
206 : const char kExpectedPretty[] =
207 : "{\n"
208 : " \"key1\": 0xDEADF00D,\n"
209 : " \"key2\": 42\n"
210 E : "}";
211 E : TestConversion(true, value, kExpectedPretty);
212 :
213 E : const char kExpectedCompact[] = "{\"key1\":0xDEADF00D,\"key2\":42}";
214 E : TestConversion(false, value, kExpectedCompact);
215 E : }
216 :
217 E : TEST(CrashDataJsonTest, AllTypes) {
218 E : Value value;
219 E : value.set_type(Value_Type_DICTIONARY);
220 E : Dictionary* dict = value.mutable_dictionary();
221 :
222 : // One of each type of leaf.
223 E : LeafSetInt(-42, ValueGetLeaf(DictAddValue("int", dict)));
224 E : LeafSetUInt(42, ValueGetLeaf(DictAddValue("uint", dict)));
225 E : LeafSetReal(2.0e99, ValueGetLeaf(DictAddValue("real", dict)));
226 E : *LeafGetString(ValueGetLeaf(DictAddValue("string", dict))) = "foobar";
227 : LeafGetAddress(ValueGetLeaf(DictAddValue("address", dict)))->set_address(
228 E : 0xDEADF00D);
229 : LeafGetStackTrace(ValueGetLeaf(DictAddValue("stack-trace", dict)))
230 E : ->add_frames(0xBAADBEEF);
231 : LeafGetBlob(ValueGetLeaf(DictAddValue("blob", dict)))->mutable_data()
232 E : ->append("hey");
233 :
234 : // Nested dictionary with a single element.
235 : LeafSetInt(100, ValueGetLeaf(DictAddValue("INT", ValueGetDict(
236 E : DictAddValue("dict", dict)))));
237 :
238 : // Nested list with a single element
239 E : List* list = ValueGetList(DictAddValue("list", dict));
240 E : LeafSetInt(200, ValueGetLeaf(list->add_values()));
241 :
242 : const char kExpectedPretty[] =
243 : "{\n"
244 : " \"int\": -42,\n"
245 : " \"uint\": 42,\n"
246 : " \"real\": 1.9999999999999999E+099,\n"
247 : " \"string\": \"foobar\",\n"
248 : " \"address\": 0xDEADF00D,\n"
249 : " \"stack-trace\": [\n"
250 : " 0xBAADBEEF\n"
251 : " ],\n"
252 : " \"blob\": {\n"
253 : " \"type\": \"blob\",\n"
254 : " \"address\": null,\n"
255 : " \"size\": null,\n"
256 : " \"data\": [\n"
257 : " 0x68, 0x65, 0x79\n"
258 : " ]\n"
259 : " },\n"
260 : " \"dict\": {\n"
261 : " \"INT\": 100\n"
262 : " },\n"
263 : " \"list\": [\n"
264 : " 200\n"
265 : " ]\n"
266 E : "}";
267 E : TestConversion(true, value, kExpectedPretty);
268 :
269 : const char kExpectedCompact[] =
270 : "{"
271 : "\"int\":-42,"
272 : "\"uint\":42,"
273 : "\"real\":1.9999999999999999E+099,"
274 : "\"string\":\"foobar\","
275 : "\"address\":0xDEADF00D,"
276 : "\"stack-trace\":[0xBAADBEEF],"
277 : "\"blob\":{"
278 : "\"type\":\"blob\","
279 : "\"address\":null,"
280 : "\"size\":null,"
281 : "\"data\":[0x68,0x65,0x79]"
282 : "},"
283 : "\"dict\":{"
284 : "\"INT\":100"
285 : "},"
286 : "\"list\":["
287 : "200"
288 : "]"
289 E : "}";
290 E : TestConversion(false, value, kExpectedCompact);
291 E : }
292 :
293 : } // namespace crashdata
|