]>
git.proxmox.com Git - ceph.git/blob - ceph/src/test/common/test_json_formattable.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * Ceph - scalable distributed file system
6 * Copyright (C) 2018 Red Hat Inc.
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
16 #include <gtest/gtest.h>
18 #include "common/ceph_json.h"
25 static void get_jf(const string
& s
, JSONFormattable
*f
)
28 bool result
= p
.parse(s
.c_str(), s
.size());
30 cout
<< "Failed to parse: '" << s
<< "'" << std::endl
;
32 ASSERT_EQ(true, result
);
34 decode_json_obj(*f
, &p
);
35 } catch (JSONDecoder::err
& e
) {
36 ASSERT_TRUE(0 == "Failed to decode JSON object");
40 TEST(formatable
, str
) {
42 get_jf("{ \"foo\": \"bar\" }", &f
);
43 ASSERT_EQ((string
)f
["foo"], "bar");
44 ASSERT_EQ((string
)f
["fooz"], "");
45 ASSERT_EQ((string
)f
["fooz"]("lala"), "lala");
48 TEST(formatable
, str2
) {
50 get_jf("{ \"foo\": \"bar\" }", &f
);
51 ASSERT_EQ((string
)f
["foo"], "bar");
52 ASSERT_EQ((string
)f
["fooz"], "");
53 ASSERT_EQ((string
)f
["fooz"]("lala"), "lala");
56 get_jf("{ \"foo\": \"bar\", \"fooz\": \"zzz\" }", &f2
);
57 ASSERT_EQ((string
)f2
["foo"], "bar");
58 ASSERT_NE((string
)f2
["fooz"], "");
59 ASSERT_EQ((string
)f2
["fooz"], "zzz");
60 ASSERT_EQ((string
)f2
["fooz"]("lala"), "zzz");
64 TEST(formatable
, int) {
66 get_jf("{ \"foo\": 1 }", &f
);
67 ASSERT_EQ((int)f
["foo"], 1);
68 ASSERT_EQ((int)f
["fooz"], 0);
69 ASSERT_EQ((int)f
["fooz"](3), 3);
72 get_jf("{ \"foo\": \"bar\", \"fooz\": \"123\" }", &f2
);
73 ASSERT_EQ((string
)f2
["foo"], "bar");
74 ASSERT_NE((int)f2
["fooz"], 0);
75 ASSERT_EQ((int)f2
["fooz"], 123);
76 ASSERT_EQ((int)f2
["fooz"](111), 123);
79 TEST(formatable
, bool) {
81 get_jf("{ \"foo\": \"true\" }", &f
);
82 ASSERT_EQ((bool)f
["foo"], true);
83 ASSERT_EQ((bool)f
["fooz"], false);
84 ASSERT_EQ((bool)f
["fooz"](true), true);
87 get_jf("{ \"foo\": \"false\" }", &f
);
88 ASSERT_EQ((bool)f
["foo"], false);
91 TEST(formatable
, nested
) {
93 get_jf("{ \"obj\": { \"foo\": 1, \"inobj\": { \"foo\": 2 } } }", &f
);
94 ASSERT_EQ((int)f
["foo"], 0);
95 ASSERT_EQ((int)f
["obj"]["foo"], 1);
96 ASSERT_EQ((int)f
["obj"]["inobj"]["foo"], 2);
99 TEST(formatable
, array
) {
101 get_jf("{ \"arr\": [ { \"foo\": 1, \"inobj\": { \"foo\": 2 } },"
102 "{ \"foo\": 2 } ] }", &f
);
105 for (auto a
: f
.array()) {
106 ASSERT_EQ((int)a
["foo"], i
);
111 get_jf("{ \"arr\": [ 0, 1, 2, 3, 4 ]}", &f2
);
114 for (auto a
: f2
.array()) {
115 ASSERT_EQ((int)a
, i
);
120 TEST(formatable
, bin_encode
) {
121 JSONFormattable f
, f2
;
122 get_jf("{ \"arr\": [ { \"foo\": 1, \"bar\": \"aaa\", \"inobj\": { \"foo\": 2 } },"
123 "{ \"foo\": 2, \"inobj\": { \"foo\": 3 } } ] }", &f
);
126 for (auto a
: f
.array()) {
127 ASSERT_EQ((int)a
["foo"], i
);
128 ASSERT_EQ((int)a
["foo"]["inobj"], i
+ 1);
129 ASSERT_EQ((string
)a
["bar"], "aaa");
135 auto iter
= bl
.cbegin();
138 } catch (buffer::error
& err
) {
139 ASSERT_TRUE(0 == "Failed to decode object");
143 for (auto a
: f2
.array()) {
144 ASSERT_EQ((int)a
["foo"], i
);
145 ASSERT_EQ((int)a
["foo"]["inobj"], i
+ 1);
146 ASSERT_EQ((string
)a
["bar"], "aaa");
152 TEST(formatable
, json_encode
) {
153 JSONFormattable f
, f2
;
154 get_jf("{ \"arr\": [ { \"foo\": 1, \"bar\": \"aaa\", \"inobj\": { \"foo\": 2 } },"
155 "{ \"foo\": 2, \"inobj\": { \"foo\": 3 } } ] }", &f
);
157 JSONFormatter formatter
;
158 formatter
.open_object_section("bla");
159 ::encode_json("f", f
, &formatter
);
160 formatter
.close_section();
165 get_jf(ss
.str(), &f2
);
168 for (auto a
: f2
.array()) {
169 ASSERT_EQ((int)a
["foo"], i
);
170 ASSERT_EQ((int)a
["foo"]["inobj"], i
+ 1);
171 ASSERT_EQ((string
)a
["bar"], "aaa");
177 TEST(formatable
, set
) {
178 JSONFormattable f
, f2
;
180 f
.set("", "{ \"abc\": \"xyz\"}");
181 ASSERT_EQ((string
)f
["abc"], "xyz");
184 ASSERT_EQ((string
)f
["abc"], "xyz");
185 ASSERT_EQ((int)f
["aaa"], 111);
187 f
.set("obj", "{ \"a\": \"10\", \"b\": \"20\"}");
188 ASSERT_EQ((int)f
["obj"]["a"], 10);
189 ASSERT_EQ((int)f
["obj"]["b"], 20);
191 f
.set("obj.c", "30");
193 ASSERT_EQ((int)f
["obj"]["c"], 30);
196 TEST(formatable
, erase
) {
197 JSONFormattable f
, f2
;
199 f
.set("", "{ \"abc\": \"xyz\"}");
200 ASSERT_EQ((string
)f
["abc"], "xyz");
203 ASSERT_EQ((string
)f
["abc"], "xyz");
204 ASSERT_EQ((int)f
["aaa"], 111);
206 ASSERT_EQ((int)f
["aaa"], 0);
208 f
.set("obj", "{ \"a\": \"10\", \"b\": \"20\"}");
209 ASSERT_EQ((int)f
["obj"]["a"], 10);
210 ASSERT_EQ((int)f
["obj"]["b"], 20);
212 ASSERT_EQ((int)f
["obj"]["a"], 0);
213 ASSERT_EQ((int)f
["obj"]["b"], 20);
217 static void dumpt(const T
& t
, const char *n
)
219 JSONFormatter formatter
;
220 formatter
.open_object_section("bla");
221 ::encode_json(n
, t
, &formatter
);
222 formatter
.close_section();
223 formatter
.flush(cout
);
226 static void dumpf(const JSONFormattable
& f
) {
230 TEST(formatable
, set_array
) {
231 JSONFormattable f
, f2
;
233 f
.set("asd[0]", "\"xyz\"");
234 ASSERT_EQ(1u, f
["asd"].array().size());
235 ASSERT_EQ((string
)f
["asd"][0], "xyz");
237 f
.set("bbb[0][0]", "10");
238 f
.set("bbb[0][1]", "20");
239 ASSERT_EQ(1u, f
["bbb"].array().size());
240 ASSERT_EQ(2u, f
["bbb"][0].array().size());
241 ASSERT_EQ("10", (string
)f
["bbb"][0][0]);
242 ASSERT_EQ(20, (int)f
["bbb"][0][1]);
243 f
.set("bbb[0][1]", "25");
244 ASSERT_EQ(2u, f
["bbb"][0].array().size());
245 ASSERT_EQ(25, (int)f
["bbb"][0][1]);
247 f
.set("bbb[0][]", "26"); /* append operation */
248 ASSERT_EQ(26, (int)f
["bbb"][0][2]);
249 f
.set("bbb[0][-1]", "27"); /* replace last */
250 ASSERT_EQ(27, (int)f
["bbb"][0][2]);
251 ASSERT_EQ(3u, f
["bbb"][0].array().size());
253 f
.set("foo.asd[0][0]", "{ \"field\": \"xyz\"}");
254 ASSERT_EQ((string
)f
["foo"]["asd"][0][0]["field"], "xyz");
256 ASSERT_EQ(f
.set("foo[0]", "\"zzz\""), -EINVAL
); /* can't assign array to an obj entity */
258 f2
.set("[0]", "{ \"field\": \"xyz\"}");
259 ASSERT_EQ((string
)f2
[0]["field"], "xyz");
262 TEST(formatable
, erase_array
) {
265 f
.set("asd[0]", "\"xyz\"");
266 ASSERT_EQ(1u, f
["asd"].array().size());
267 ASSERT_EQ("xyz", (string
)f
["asd"][0]);
268 ASSERT_TRUE(f
["asd"].exists(0));
270 ASSERT_FALSE(f
["asd"].exists(0));
271 f
.set("asd[0]", "\"xyz\"");
272 ASSERT_TRUE(f
["asd"].exists(0));
273 f
["asd"].erase("[0]");
274 ASSERT_FALSE(f
["asd"].exists(0));
275 f
.set("asd[0]", "\"xyz\"");
276 ASSERT_TRUE(f
["asd"].exists(0));
278 ASSERT_FALSE(f
["asd"].exists(0));
279 ASSERT_FALSE(f
.exists("asd"));
281 f
.set("bbb[]", "10");
282 f
.set("bbb[]", "20");
283 f
.set("bbb[]", "30");
284 ASSERT_EQ((int)f
["bbb"][0], 10);
285 ASSERT_EQ((int)f
["bbb"][1], 20);
286 ASSERT_EQ((int)f
["bbb"][2], 30);
288 ASSERT_FALSE(f
.exists("bbb[2]"));
290 ASSERT_EQ((int)f
["bbb"][0], 10);
291 ASSERT_EQ((int)f
["bbb"][1], 30);
293 if (0) { /* for debugging when needed */
298 void formatter_convert(JSONFormatter
& formatter
, JSONFormattable
*dest
)
302 get_jf(ss
.str(), dest
);
305 TEST(formatable
, encode_simple
) {
308 encode_json("foo", "bar", &f
);
310 ASSERT_EQ((string
)f
["foo"], "bar");
313 JSONFormatter formatter
;
315 Formatter::ObjectSection
s(formatter
, "os");
316 encode_json("f", f
, &formatter
);
320 formatter_convert(formatter
, &jf2
);
322 ASSERT_EQ((string
)jf2
["f"]["foo"], "bar");
332 void *p
= (void *)this;
335 snprintf(buf
, sizeof(buf
), "%p", p
);
340 void dump(Formatter
*f
) const {
341 encode_json("i", i
, f
);
342 encode_json("s", s
, f
);
343 encode_json("b", b
, f
);
346 void decode_json(JSONObj
*obj
) {
347 JSONDecoder::decode_json("i", i
, obj
);
348 JSONDecoder::decode_json("s", s
, obj
);
349 JSONDecoder::decode_json("b", b
, obj
);
352 bool compare(const JSONFormattable
& jf
) const {
353 bool ret
= (s
== (string
)jf
["s"] &&
354 i
== (long)jf
["i"] &&
358 cout
<< "failed comparison: s=" << s
<< " jf[s]=" << (string
)jf
["s"] <<
359 " i=" << i
<< " jf[i]=" << (long)jf
["i"] << " b=" << b
<< " jf[b]=" << (bool)jf
["b"] << std::endl
;
373 void *p
= (void *)this;
375 v
.resize((i
>> 16) % 16 + 1);
378 void dump(Formatter
*f
) const {
379 encode_json("s1", s1
, f
);
380 encode_json("v", v
, f
);
383 void decode_json(JSONObj
*obj
) {
384 JSONDecoder::decode_json("s1", s1
, obj
);
385 JSONDecoder::decode_json("v", v
, obj
);
388 bool compare(const JSONFormattable
& jf
) const {
389 if (!s1
.compare(jf
["s1"])) {
390 cout
<< "s1.compare(jf[s1] failed" << std::endl
;
394 if (v
.size() != jf
["v"].array().size()) {
395 cout
<< "v.size()=" << v
.size() << " jf[v].array().size()=" << jf
["v"].array().size() << std::endl
;
399 auto viter
= v
.begin();
400 auto jiter
= jf
["v"].array().begin();
402 for (; viter
!= v
.end(); ++viter
, ++jiter
) {
403 if (!viter
->compare(*jiter
)) {
412 TEST(formatable
, encode_struct
) {
418 Formatter::ObjectSection
s(f
, "section");
419 encode_json("foo", "bar", &f
);
420 encode_json("s2", s2
, &f
);
427 ASSERT_EQ((string
)f
["foo"], "bar");
428 ASSERT_TRUE(s2
.compare(f
["s2"]));
431 JSONFormatter formatter
;
432 encode_json("f", f
, &formatter
);
436 formatter_convert(formatter
, &jf2
);
438 ASSERT_EQ((string
)jf2
["foo"], "bar");
439 ASSERT_TRUE(s2
.compare(jf2
["s2"]));