5#define MCHECK(MSG, ...) do { if (!strstr (MSG.c_str(), "\"error\":")) break; fprintf (stderr, "%s:%d: ERROR: %s\n", __FILE__, __LINE__, MSG.c_str()); abort(); } while (0)
50 void set_nested (
const NestedCopyable &nested) { nested_ = nested; }
53 void dummy0 () {
printf (
"dummy0: NOP\n"); }
54 bool dummy1 (
bool b,
KVInts kvi) {
printf (
"dummy1: b=%s kvi=%zd\n", b ?
"true" :
"false", kvi.size());
return b; }
56 size_t dummy3 (
Derived &d,
KVFloats kvf)
const {
printf (
"dummy3: Derived=%p this=%p kvf=%zd\n", &d,
this, kvf.size());
return size_t (&d); }
57 bool dummy4 (
float f,
std::string s,
long l) {
printf (
"dummy4: this=%s %f '%s' %ld\n", name_.
c_str(), f, s.
c_str(), l);
return 1; }
58 void dummy5 (
const char *c,
double d,
Pair p) {
printf (
"dummy5: this=%s %d '%s' %f\n", name_.
c_str(), p.first, c, d); }
60 Derived* dummy7 () {
return NULL; }
61 Derived& dummy8 () {
return *dummy7(); }
62 Derived dummy9 () {
return dummy8(); }
64 signed a4 = -4,
float a5 = -0.5,
const char *a6 =
"a6",
double a7 = 0.7,
65 size_t a8 = 8,
Copyable *a9 =
nullptr,
67 template<
class C>
static void
70 c.set_d (
"defaults", &Derived::defaults, {
72 signed (-4),
float (-0.5),
"a6", 1e-70,
80json_objectid (
const Jsonipc::JsonValue &value)
84 auto it = value.FindMember (
"$id");
85 if (it != value.MemberEnd())
86 return Jsonipc::from_json<size_t> (it->value);
92parse_result (
size_t id,
const std::string json_reply)
94 rapidjson::Document document;
95 document.Parse<Jsonipc::rapidjson_parse_flags> (json_reply.
data(), json_reply.
size());
96 if (!document.HasParseError())
99 const Jsonipc::JsonValue *result = NULL;
100 for (
const auto &m : document.GetObject())
102 id_ = Jsonipc::from_json<
size_t> (m.value, 0);
103 else if (m.name ==
"result")
105 if (id_ ==
id && result)
106 return Jsonipc::from_json<R> (*result);
112test_jsonipc (
bool dispatcher_shell,
bool printer)
114 using namespace Jsonipc;
117 rapidjson::Document doc;
118 auto &a = doc.GetAllocator();
121 JSONIPC_ASSERT_RETURN (
false == from_json<bool> (JsonValue()));
122 JSONIPC_ASSERT_RETURN (
true == from_json<bool> (JsonValue (
true)));
123 JSONIPC_ASSERT_RETURN (
true == from_json<bool> (JsonValue(),
true));
124 JSONIPC_ASSERT_RETURN (
false == from_json<bool> (JsonValue(),
false));
125 JSONIPC_ASSERT_RETURN (from_json<bool> (to_json (
true, a)) ==
true);
126 JSONIPC_ASSERT_RETURN (from_json<bool> (to_json (
false, a)) ==
false);
127 JSONIPC_ASSERT_RETURN (from_json<size_t> (to_json (1337, a)) == 1337);
128 JSONIPC_ASSERT_RETURN (from_json<ssize_t> (to_json (-1337, a)) == -1337);
129 JSONIPC_ASSERT_RETURN (from_json<float> (to_json (-0.5, a)) == -0.5);
130 JSONIPC_ASSERT_RETURN (from_json<double> (to_json (1e20, a)) == 1e20);
131 JSONIPC_ASSERT_RETURN (from_json<const char*> (to_json (
"Om", a)) ==
std::string (
"Om"));
132 JSONIPC_ASSERT_RETURN (from_json<std::string> (to_json (
std::string (
"Ah"), a)) ==
"Ah");
133 JSONIPC_ASSERT_RETURN (strcmp (
"HUM", from_json<const char*> (to_json ((
const char*)
"HUM", a))) == 0);
138 .set (ErrorType::NONE,
"NONE")
139 .set (ErrorType::INVALID,
"INVALID")
140 .set (ErrorType::FATAL,
"FATAL")
145 .
set (
"need_copyablep", &Base::need_copyablep)
149 class_NestedCopyable.
set (
"nested", &NestedCopyable::nested);
153 .
set (
"i", &Copyable::i)
154 .
set (
"f", &Copyable::f)
155 .
set (
"hello", &Copyable::hello)
158 class_LinkedCopyable.
set (
"next", &LinkedCopyable::next);
162 .set (
"dummy0", &Derived::dummy0)
163 .set (
"dummy1", &Derived::dummy1)
164 .set (
"dummy2", &Derived::dummy2)
165 .set (
"dummy3", &Derived::dummy3)
166 .set (
"dummy4", &Derived::dummy4)
167 .set (
"dummy5", &Derived::dummy5)
168 .set (
"dummy6", &Derived::dummy6)
169 .set (
"dummy7", &Derived::dummy7)
170 .set (
"dummy8", &Derived::dummy8)
171 .set (
"dummy9", &Derived::dummy9)
172 .set (
"randomize", &Derived::randomize)
173 .set (
"nested", &Derived::nested, &Derived::set_nested)
174 .set (
"linked", &Derived::linked, &Derived::set_linked)
177 Derived::set_dflt (class_Derived);
180 const Names derived_methods = {
"defaults",
"dummy0",
"dummy1",
"dummy2",
"dummy3",
"dummy4",
"dummy5",
"dummy6",
"dummy7",
181 "dummy8",
"dummy9",
"get/linked",
"get/nested",
"need_copyablep",
"randomize",
182 "set/linked",
"set/nested" };
187 Scope temporary_scope (imap);
188 const auto nested = from_json<NestedCopyable> (to_json (
NestedCopyable{}, a));
189 JSONIPC_ASSERT_RETURN (nested.nested.i == 111 && nested.nested.hello ==
"hello");
194 JSONIPC_ASSERT_RETURN (to_json (obja, a) == to_json (obja, a));
195 JSONIPC_ASSERT_RETURN (&obja == from_json<Derived*> (to_json (obja, a)));
196 JSONIPC_ASSERT_RETURN (ptrdiff_t (&
static_cast<Base&
> (obja)) == ptrdiff_t (&obja));
197 JSONIPC_ASSERT_RETURN (ptrdiff_t (&
static_cast<Base2&
> (obja)) > ptrdiff_t (&obja));
199 JSONIPC_ASSERT_RETURN (&obja == from_json<Base*> (to_json (obja, a)));
200 JSONIPC_ASSERT_RETURN (from_json<Base2*> (to_json (obja, a)) == &
static_cast<Base2&
> (obja));
203 JSONIPC_ASSERT_RETURN (&obja != &objb);
206 JSONIPC_ASSERT_RETURN (ptrdiff_t (&
static_cast<Base&
> (objb)) == ptrdiff_t (&objb));
207 JSONIPC_ASSERT_RETURN (ptrdiff_t (&
static_cast<Base2&
> (objb)) > ptrdiff_t (&objb));
210 JSONIPC_ASSERT_RETURN (to_json (obja, a) != to_json (objb, a));
213 JSONIPC_ASSERT_RETURN (&objc == &from_json<Derived&> (to_json (objc, a)));
214 JSONIPC_ASSERT_RETURN (&objc == &from_json<Base&> (to_json (objc, a)));
215 JSONIPC_ASSERT_RETURN (&objc == &from_json<Base2&> (to_json (objc, a)));
216 JSONIPC_ASSERT_RETURN (to_json (objb, a) != to_json (objc, a));
217 JSONIPC_ASSERT_RETURN (to_json (objc, a) == to_json (objc, a));
218 const JsonValue jva = to_json (obja, a);
219 const JsonValue jvb = to_json (objb, a);
220 const JsonValue jvc = to_json (objc, a);
221 JSONIPC_ASSERT_RETURN (from_json<Derived*> (jva) == &obja);
222 JSONIPC_ASSERT_RETURN (&from_json<Derived> (jvb) == &objb);
223 JSONIPC_ASSERT_RETURN (&from_json<Derived&> (jvc) == &objc);
228 JsonValue jvc1 = to_json (c1, a);
229 Copyable c2 = from_json<Copyable&> (jvc1);
230 JSONIPC_ASSERT_RETURN (c1.i == c2.i && c1.f == c2.f && c1.hello == c2.hello);
236 JsonValue jvd1 = to_json (d1, a);
237 const size_t d1id = json_objectid (jvd1);
238 JSONIPC_ASSERT_RETURN (d1id == 4);
239 JSONIPC_ASSERT_RETURN (InstanceMap::scope_lookup_wrapper (jvd1)->list_methods() == derived_methods);
240 result = dispatcher.dispatch_message (R
"( {"id":123,"method":"randomize","params":[{"$id":4}]} )");
243 const Copyable *c3 = parse_result<Copyable*> (123, result);
244 JSONIPC_ASSERT_RETURN (c3 && (c3->i != c0.i || c3->f != c0.f));
245 result = dispatcher.dispatch_message (R
"( {"id":123,"method":"need_copyablep","params":[{"$id":4},{}]} )");
247 result = dispatcher.dispatch_message (R"( {"id":444,"method":"randomize","params":[{"$id":4}]} )");
249 const Copyable *c4 = parse_result<Copyable*> (444, result);
250 JSONIPC_ASSERT_RETURN (c4 && (c4->i != c3->i || c4->f != c3->f));
251 result = dispatcher.dispatch_message (R
"( {"id":111,"method":"randomize","params":[{"$id":4}]} )");
253 const Copyable *c5 = parse_result<Copyable*> (111, result);
254 JSONIPC_ASSERT_RETURN (c5 && (c5->i != c4->i || c5->f != c4->f));
256 if (printer && Jsonipc::g_binding_printer) {
257 const auto bindings = Jsonipc::g_binding_printer->finish();
259 for (
const auto *expected : {
"nested: Copyable = new Copyable()",
"next: LinkedCopyable = null",
260 "this.$get (\"nested\", new NestedCopyable())",
"this.$get (\"linked\", null)" })
261 if (bindings.find (expected) == std::string::npos)
263 if (!missing.
empty())
265 dprintf (1,
"%s\n", bindings.c_str());
269 if (dispatcher_shell)
278 forget_json_id (json_objectid (jva));
279 JSONIPC_ASSERT_RETURN (from_json<Derived*> (jva) ==
nullptr);
280 forget_json_id (json_objectid (jvb));
281 JSONIPC_ASSERT_RETURN (from_json<Derived*> (jvb) == (
Derived*)
nullptr);
282 forget_json_id (json_objectid (jvc));
283 JSONIPC_ASSERT_RETURN (from_json<Derived*> (jvc) == (
Derived*)
nullptr);
285 printf (
" OK %s\n", __func__);
290main (
int argc,
char *argv[])
292 const bool dispatcher_shell = argc > 1 && 0 ==
strcmp (argv[1],
"--shell");
293 const bool printer = argc > 1 && 0 ==
strcmp (argv[1],
"--print");
294 test_jsonipc (dispatcher_shell, printer);
Maps C++ shared_ptr instances to JSON-wrapped objects with unique IDs, supporting polymorphic upcasti...
Keep track of temporary instances during IpcDispatcher::dispatch_message().
Class & set(const char *name, const F &method)
Add a member function pointer.
Registers C++ enum values with string names for JSON serialization and TypeScript binding generation.
Jsonipc wrapper type for objects that support field-wise serialization to/from JSON.
Serializable & set(const char *name, A attribute)
Add a member object pointer.