]>
Commit | Line | Data |
---|---|---|
7c673cae | 1 | // Copyright (c) 2011-present, Facebook, Inc. All rights reserved. |
11fdf7f2 TL |
2 | // This source code is licensed under both the GPLv2 (found in the |
3 | // COPYING file in the root directory) and Apache 2.0 License | |
4 | // (found in the LICENSE.Apache file in the root directory). | |
7c673cae FG |
5 | |
6 | #ifndef ROCKSDB_LITE | |
7 | ||
8 | #include <map> | |
9 | #include <set> | |
10 | #include <string> | |
11 | ||
12 | #include "rocksdb/utilities/json_document.h" | |
13 | ||
14 | #include "util/testutil.h" | |
15 | #include "util/testharness.h" | |
16 | ||
17 | namespace rocksdb { | |
18 | namespace { | |
19 | void AssertField(const JSONDocument& json, const std::string& field) { | |
20 | ASSERT_TRUE(json.Contains(field)); | |
21 | ASSERT_TRUE(json[field].IsNull()); | |
22 | } | |
23 | ||
24 | void AssertField(const JSONDocument& json, const std::string& field, | |
25 | const std::string& expected) { | |
26 | ASSERT_TRUE(json.Contains(field)); | |
27 | ASSERT_TRUE(json[field].IsString()); | |
28 | ASSERT_EQ(expected, json[field].GetString()); | |
29 | } | |
30 | ||
31 | void AssertField(const JSONDocument& json, const std::string& field, | |
32 | int64_t expected) { | |
33 | ASSERT_TRUE(json.Contains(field)); | |
34 | ASSERT_TRUE(json[field].IsInt64()); | |
35 | ASSERT_EQ(expected, json[field].GetInt64()); | |
36 | } | |
37 | ||
38 | void AssertField(const JSONDocument& json, const std::string& field, | |
39 | bool expected) { | |
40 | ASSERT_TRUE(json.Contains(field)); | |
41 | ASSERT_TRUE(json[field].IsBool()); | |
42 | ASSERT_EQ(expected, json[field].GetBool()); | |
43 | } | |
44 | ||
45 | void AssertField(const JSONDocument& json, const std::string& field, | |
46 | double expected) { | |
47 | ASSERT_TRUE(json.Contains(field)); | |
48 | ASSERT_TRUE(json[field].IsDouble()); | |
49 | ASSERT_DOUBLE_EQ(expected, json[field].GetDouble()); | |
50 | } | |
51 | } // namespace | |
52 | ||
53 | class JSONDocumentTest : public testing::Test { | |
54 | public: | |
55 | JSONDocumentTest() | |
56 | : rnd_(101) | |
57 | {} | |
58 | ||
59 | void AssertSampleJSON(const JSONDocument& json) { | |
60 | AssertField(json, "title", std::string("json")); | |
61 | AssertField(json, "type", std::string("object")); | |
62 | // properties | |
63 | ASSERT_TRUE(json.Contains("properties")); | |
64 | ASSERT_TRUE(json["properties"].Contains("flags")); | |
65 | ASSERT_TRUE(json["properties"]["flags"].IsArray()); | |
66 | ASSERT_EQ(3u, json["properties"]["flags"].Count()); | |
67 | ASSERT_TRUE(json["properties"]["flags"][0].IsInt64()); | |
68 | ASSERT_EQ(10, json["properties"]["flags"][0].GetInt64()); | |
69 | ASSERT_TRUE(json["properties"]["flags"][1].IsString()); | |
70 | ASSERT_EQ("parse", json["properties"]["flags"][1].GetString()); | |
71 | ASSERT_TRUE(json["properties"]["flags"][2].IsObject()); | |
72 | AssertField(json["properties"]["flags"][2], "tag", std::string("no")); | |
73 | AssertField(json["properties"]["flags"][2], std::string("status")); | |
74 | AssertField(json["properties"], "age", 110.5e-4); | |
75 | AssertField(json["properties"], "depth", static_cast<int64_t>(-10)); | |
76 | // test iteration | |
77 | std::set<std::string> expected({"flags", "age", "depth"}); | |
78 | for (auto item : json["properties"].Items()) { | |
79 | auto iter = expected.find(item.first); | |
80 | ASSERT_TRUE(iter != expected.end()); | |
81 | expected.erase(iter); | |
82 | } | |
83 | ASSERT_EQ(0U, expected.size()); | |
84 | ASSERT_TRUE(json.Contains("latlong")); | |
85 | ASSERT_TRUE(json["latlong"].IsArray()); | |
86 | ASSERT_EQ(2u, json["latlong"].Count()); | |
87 | ASSERT_TRUE(json["latlong"][0].IsDouble()); | |
88 | ASSERT_EQ(53.25, json["latlong"][0].GetDouble()); | |
89 | ASSERT_TRUE(json["latlong"][1].IsDouble()); | |
90 | ASSERT_EQ(43.75, json["latlong"][1].GetDouble()); | |
91 | AssertField(json, "enabled", true); | |
92 | } | |
93 | ||
94 | const std::string kSampleJSON = | |
95 | "{ \"title\" : \"json\", \"type\" : \"object\", \"properties\" : { " | |
96 | "\"flags\": [10, \"parse\", {\"tag\": \"no\", \"status\": null}], " | |
97 | "\"age\": 110.5e-4, \"depth\": -10 }, \"latlong\": [53.25, 43.75], " | |
98 | "\"enabled\": true }"; | |
99 | ||
100 | const std::string kSampleJSONDifferent = | |
101 | "{ \"title\" : \"json\", \"type\" : \"object\", \"properties\" : { " | |
102 | "\"flags\": [10, \"parse\", {\"tag\": \"no\", \"status\": 2}], " | |
103 | "\"age\": 110.5e-4, \"depth\": -10 }, \"latlong\": [53.25, 43.75], " | |
104 | "\"enabled\": true }"; | |
105 | ||
106 | Random rnd_; | |
107 | }; | |
108 | ||
109 | TEST_F(JSONDocumentTest, MakeNullTest) { | |
110 | JSONDocument x; | |
111 | ASSERT_TRUE(x.IsNull()); | |
112 | ASSERT_TRUE(x.IsOwner()); | |
113 | ASSERT_TRUE(!x.IsBool()); | |
114 | } | |
115 | ||
116 | TEST_F(JSONDocumentTest, MakeBoolTest) { | |
117 | { | |
118 | JSONDocument x(true); | |
119 | ASSERT_TRUE(x.IsOwner()); | |
120 | ASSERT_TRUE(x.IsBool()); | |
121 | ASSERT_TRUE(!x.IsInt64()); | |
122 | ASSERT_EQ(x.GetBool(), true); | |
123 | } | |
124 | ||
125 | { | |
126 | JSONDocument x(false); | |
127 | ASSERT_TRUE(x.IsOwner()); | |
128 | ASSERT_TRUE(x.IsBool()); | |
129 | ASSERT_TRUE(!x.IsInt64()); | |
130 | ASSERT_EQ(x.GetBool(), false); | |
131 | } | |
132 | } | |
133 | ||
134 | TEST_F(JSONDocumentTest, MakeInt64Test) { | |
135 | JSONDocument x(static_cast<int64_t>(16)); | |
136 | ASSERT_TRUE(x.IsInt64()); | |
137 | ASSERT_TRUE(x.IsInt64()); | |
138 | ASSERT_TRUE(!x.IsBool()); | |
139 | ASSERT_TRUE(x.IsOwner()); | |
140 | ASSERT_EQ(x.GetInt64(), 16); | |
141 | } | |
142 | ||
143 | TEST_F(JSONDocumentTest, MakeStringTest) { | |
144 | JSONDocument x("string"); | |
145 | ASSERT_TRUE(x.IsOwner()); | |
146 | ASSERT_TRUE(x.IsString()); | |
147 | ASSERT_TRUE(!x.IsBool()); | |
148 | ASSERT_EQ(x.GetString(), "string"); | |
149 | } | |
150 | ||
151 | TEST_F(JSONDocumentTest, MakeDoubleTest) { | |
152 | JSONDocument x(5.6); | |
153 | ASSERT_TRUE(x.IsOwner()); | |
154 | ASSERT_TRUE(x.IsDouble()); | |
155 | ASSERT_TRUE(!x.IsBool()); | |
156 | ASSERT_EQ(x.GetDouble(), 5.6); | |
157 | } | |
158 | ||
159 | TEST_F(JSONDocumentTest, MakeByTypeTest) { | |
160 | { | |
161 | JSONDocument x(JSONDocument::kNull); | |
162 | ASSERT_TRUE(x.IsNull()); | |
163 | } | |
164 | { | |
165 | JSONDocument x(JSONDocument::kBool); | |
166 | ASSERT_TRUE(x.IsBool()); | |
167 | } | |
168 | { | |
169 | JSONDocument x(JSONDocument::kString); | |
170 | ASSERT_TRUE(x.IsString()); | |
171 | } | |
172 | { | |
173 | JSONDocument x(JSONDocument::kInt64); | |
174 | ASSERT_TRUE(x.IsInt64()); | |
175 | } | |
176 | { | |
177 | JSONDocument x(JSONDocument::kDouble); | |
178 | ASSERT_TRUE(x.IsDouble()); | |
179 | } | |
180 | { | |
181 | JSONDocument x(JSONDocument::kObject); | |
182 | ASSERT_TRUE(x.IsObject()); | |
183 | } | |
184 | { | |
185 | JSONDocument x(JSONDocument::kArray); | |
186 | ASSERT_TRUE(x.IsArray()); | |
187 | } | |
188 | } | |
189 | ||
190 | TEST_F(JSONDocumentTest, Parsing) { | |
191 | std::unique_ptr<JSONDocument> parsed_json( | |
192 | JSONDocument::ParseJSON(kSampleJSON.c_str())); | |
193 | ASSERT_TRUE(parsed_json->IsOwner()); | |
194 | ASSERT_TRUE(parsed_json != nullptr); | |
195 | AssertSampleJSON(*parsed_json); | |
196 | ||
197 | // test deep copying | |
198 | JSONDocument copied_json_document(*parsed_json); | |
199 | AssertSampleJSON(copied_json_document); | |
200 | ASSERT_TRUE(copied_json_document == *parsed_json); | |
201 | ||
202 | std::unique_ptr<JSONDocument> parsed_different_sample( | |
203 | JSONDocument::ParseJSON(kSampleJSONDifferent.c_str())); | |
204 | ASSERT_TRUE(parsed_different_sample != nullptr); | |
205 | ASSERT_TRUE(!(*parsed_different_sample == copied_json_document)); | |
206 | ||
207 | // parse error | |
208 | const std::string kFaultyJSON = | |
209 | kSampleJSON.substr(0, kSampleJSON.size() - 10); | |
210 | ASSERT_TRUE(JSONDocument::ParseJSON(kFaultyJSON.c_str()) == nullptr); | |
211 | } | |
212 | ||
213 | TEST_F(JSONDocumentTest, Serialization) { | |
214 | std::unique_ptr<JSONDocument> parsed_json( | |
215 | JSONDocument::ParseJSON(kSampleJSON.c_str())); | |
216 | ASSERT_TRUE(parsed_json != nullptr); | |
217 | ASSERT_TRUE(parsed_json->IsOwner()); | |
218 | std::string serialized; | |
219 | parsed_json->Serialize(&serialized); | |
220 | ||
221 | std::unique_ptr<JSONDocument> deserialized_json( | |
222 | JSONDocument::Deserialize(Slice(serialized))); | |
223 | ASSERT_TRUE(deserialized_json != nullptr); | |
224 | AssertSampleJSON(*deserialized_json); | |
225 | ||
226 | // deserialization failure | |
227 | ASSERT_TRUE(JSONDocument::Deserialize( | |
228 | Slice(serialized.data(), serialized.size() - 10)) == nullptr); | |
229 | } | |
230 | ||
231 | TEST_F(JSONDocumentTest, OperatorEqualsTest) { | |
232 | // kNull | |
233 | ASSERT_TRUE(JSONDocument() == JSONDocument()); | |
234 | ||
235 | // kBool | |
236 | ASSERT_TRUE(JSONDocument(false) != JSONDocument()); | |
237 | ASSERT_TRUE(JSONDocument(false) == JSONDocument(false)); | |
238 | ASSERT_TRUE(JSONDocument(true) == JSONDocument(true)); | |
239 | ASSERT_TRUE(JSONDocument(false) != JSONDocument(true)); | |
240 | ||
241 | // kString | |
242 | ASSERT_TRUE(JSONDocument("test") != JSONDocument()); | |
243 | ASSERT_TRUE(JSONDocument("test") == JSONDocument("test")); | |
244 | ||
245 | // kInt64 | |
246 | ASSERT_TRUE(JSONDocument(static_cast<int64_t>(15)) != JSONDocument()); | |
247 | ASSERT_TRUE(JSONDocument(static_cast<int64_t>(15)) != | |
248 | JSONDocument(static_cast<int64_t>(14))); | |
249 | ASSERT_TRUE(JSONDocument(static_cast<int64_t>(15)) == | |
250 | JSONDocument(static_cast<int64_t>(15))); | |
251 | ||
252 | unique_ptr<JSONDocument> arrayWithInt8Doc(JSONDocument::ParseJSON("[8]")); | |
253 | ASSERT_TRUE(arrayWithInt8Doc != nullptr); | |
254 | ASSERT_TRUE(arrayWithInt8Doc->IsArray()); | |
255 | ASSERT_TRUE((*arrayWithInt8Doc)[0].IsInt64()); | |
256 | ASSERT_TRUE((*arrayWithInt8Doc)[0] == JSONDocument(static_cast<int64_t>(8))); | |
257 | ||
258 | unique_ptr<JSONDocument> arrayWithInt16Doc(JSONDocument::ParseJSON("[512]")); | |
259 | ASSERT_TRUE(arrayWithInt16Doc != nullptr); | |
260 | ASSERT_TRUE(arrayWithInt16Doc->IsArray()); | |
261 | ASSERT_TRUE((*arrayWithInt16Doc)[0].IsInt64()); | |
262 | ASSERT_TRUE((*arrayWithInt16Doc)[0] == | |
263 | JSONDocument(static_cast<int64_t>(512))); | |
264 | ||
265 | unique_ptr<JSONDocument> arrayWithInt32Doc( | |
266 | JSONDocument::ParseJSON("[1000000]")); | |
267 | ASSERT_TRUE(arrayWithInt32Doc != nullptr); | |
268 | ASSERT_TRUE(arrayWithInt32Doc->IsArray()); | |
269 | ASSERT_TRUE((*arrayWithInt32Doc)[0].IsInt64()); | |
270 | ASSERT_TRUE((*arrayWithInt32Doc)[0] == | |
271 | JSONDocument(static_cast<int64_t>(1000000))); | |
272 | ||
273 | // kDouble | |
274 | ASSERT_TRUE(JSONDocument(15.) != JSONDocument()); | |
275 | ASSERT_TRUE(JSONDocument(15.) != JSONDocument(14.)); | |
276 | ASSERT_TRUE(JSONDocument(15.) == JSONDocument(15.)); | |
277 | } | |
278 | ||
279 | TEST_F(JSONDocumentTest, JSONDocumentBuilderTest) { | |
280 | unique_ptr<JSONDocument> parsedArray( | |
281 | JSONDocument::ParseJSON("[1, [123, \"a\", \"b\"], {\"b\":\"c\"}]")); | |
282 | ASSERT_TRUE(parsedArray != nullptr); | |
283 | ||
284 | JSONDocumentBuilder builder; | |
285 | ASSERT_TRUE(builder.WriteStartArray()); | |
286 | ASSERT_TRUE(builder.WriteJSONDocument(1)); | |
287 | ||
288 | ASSERT_TRUE(builder.WriteStartArray()); | |
289 | ASSERT_TRUE(builder.WriteJSONDocument(123)); | |
290 | ASSERT_TRUE(builder.WriteJSONDocument("a")); | |
291 | ASSERT_TRUE(builder.WriteJSONDocument("b")); | |
292 | ASSERT_TRUE(builder.WriteEndArray()); | |
293 | ||
294 | ASSERT_TRUE(builder.WriteStartObject()); | |
295 | ASSERT_TRUE(builder.WriteKeyValue("b", "c")); | |
296 | ASSERT_TRUE(builder.WriteEndObject()); | |
297 | ||
298 | ASSERT_TRUE(builder.WriteEndArray()); | |
299 | ||
300 | ASSERT_TRUE(*parsedArray == builder.GetJSONDocument()); | |
301 | } | |
302 | ||
303 | TEST_F(JSONDocumentTest, OwnershipTest) { | |
304 | std::unique_ptr<JSONDocument> parsed( | |
305 | JSONDocument::ParseJSON(kSampleJSON.c_str())); | |
306 | ASSERT_TRUE(parsed != nullptr); | |
307 | ASSERT_TRUE(parsed->IsOwner()); | |
308 | ||
309 | // Copy constructor from owner -> owner | |
310 | JSONDocument copy_constructor(*parsed); | |
311 | ASSERT_TRUE(copy_constructor.IsOwner()); | |
312 | ||
313 | // Copy constructor from non-owner -> non-owner | |
314 | JSONDocument non_owner((*parsed)["properties"]); | |
315 | ASSERT_TRUE(!non_owner.IsOwner()); | |
316 | ||
317 | // Move constructor from owner -> owner | |
318 | JSONDocument moved_from_owner(std::move(copy_constructor)); | |
319 | ASSERT_TRUE(moved_from_owner.IsOwner()); | |
320 | ||
321 | // Move constructor from non-owner -> non-owner | |
322 | JSONDocument moved_from_non_owner(std::move(non_owner)); | |
323 | ASSERT_TRUE(!moved_from_non_owner.IsOwner()); | |
324 | } | |
325 | ||
326 | } // namespace rocksdb | |
327 | ||
328 | int main(int argc, char** argv) { | |
329 | ::testing::InitGoogleTest(&argc, argv); | |
330 | return RUN_ALL_TESTS(); | |
331 | } | |
332 | ||
333 | #else | |
334 | #include <stdio.h> | |
335 | ||
11fdf7f2 | 336 | int main(int /*argc*/, char** /*argv*/) { |
7c673cae FG |
337 | fprintf(stderr, "SKIPPED as JSONDocument is not supported in ROCKSDB_LITE\n"); |
338 | return 0; | |
339 | } | |
340 | ||
341 | #endif // !ROCKSDB_LITE |