1 /*
2  * Copyright (C) 2011 by Tommi Maekitalo
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * As a special exception, you may use this file as part of a free
10  * software library without restriction. Specifically, if other files
11  * instantiate templates or use macros or inline functions from this
12  * file, or you compile this file and link it with other files to
13  * produce an executable, this file does not by itself cause the
14  * resulting executable to be covered by the GNU General Public
15  * License. This exception does not however invalidate any other
16  * reasons why the executable file might be covered by the GNU Library
17  * General Public License.
18  *
19  * This library is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22  * Lesser General Public License for more details.
23  *
24  * You should have received a copy of the GNU Lesser General Public
25  * License along with this library; if not, write to the Free Software
26  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
27  */
28 #include "cxxtools/unit/testsuite.h"
29 #include "cxxtools/unit/registertest.h"
30 #include "cxxtools/json/rpcclient.h"
31 #include "cxxtools/json/rpcserver.h"
32 #include "cxxtools/remoteexception.h"
33 #include "cxxtools/remoteprocedure.h"
34 #include "cxxtools/eventloop.h"
35 #include "cxxtools/log.h"
36 #include <stdlib.h>
37 #include <sstream>
38 
39 log_define("cxxtools.test.jsonrpc")
40 
41 namespace
42 {
43     struct Color
44     {
45         int red;
46         int green;
47         int blue;
48     };
49 
50 
51     typedef std::set<int> IntSet;
52     typedef std::multiset<int> IntMultiset;
53     typedef std::map<int, int> IntMap;
54     typedef std::multimap<int, int> IntMultimap;
55 
56 
operator >>=(const cxxtools::SerializationInfo & si,Color & color)57     void operator >>=(const cxxtools::SerializationInfo& si, Color& color)
58     {
59         si.getMember("red") >>= color.red;
60         si.getMember("green") >>= color.green;
61         si.getMember("blue") >>= color.blue;
62     }
63 
64 
operator <<=(cxxtools::SerializationInfo & si,const Color & color)65     void operator <<=(cxxtools::SerializationInfo& si, const Color& color)
66     {
67         si.addMember("red") <<= color.red;
68         si.addMember("green") <<= color.green;
69         si.addMember("blue") <<= color.blue;
70     }
71 
72 }
73 
74 class JsonRpcTest : public cxxtools::unit::TestSuite
75 {
76     private:
77         cxxtools::EventLoop _loop;
78         cxxtools::json::RpcServer* _server;
79         unsigned _count;
80         unsigned short _port;
81 
82     public:
JsonRpcTest()83         JsonRpcTest()
84         : cxxtools::unit::TestSuite("jsonrpc"),
85             _port(7003)
86         {
87             registerMethod("Nothing", *this, &JsonRpcTest::Nothing);
88             registerMethod("Boolean", *this, &JsonRpcTest::Boolean);
89             registerMethod("Integer", *this, &JsonRpcTest::Integer);
90             registerMethod("Double", *this, &JsonRpcTest::Double);
91             registerMethod("String", *this, &JsonRpcTest::String);
92             registerMethod("EmptyValues", *this, &JsonRpcTest::EmptyValues);
93             registerMethod("Array", *this, &JsonRpcTest::Array);
94             registerMethod("EmptyArray", *this, &JsonRpcTest::EmptyArray);
95             registerMethod("Struct", *this, &JsonRpcTest::Struct);
96             registerMethod("Set", *this, &JsonRpcTest::Set);
97             registerMethod("Multiset", *this, &JsonRpcTest::Multiset);
98             registerMethod("Map", *this, &JsonRpcTest::Map);
99             registerMethod("Multimap", *this, &JsonRpcTest::Multimap);
100             registerMethod("UnknownMethod", *this, &JsonRpcTest::UnknownMethod);
101             registerMethod("CallPrefix", *this, &JsonRpcTest::CallPrefix);
102             registerMethod("Fault", *this, &JsonRpcTest::Fault);
103             registerMethod("Exception", *this, &JsonRpcTest::Exception);
104             registerMethod("CallbackException", *this, &JsonRpcTest::CallbackException);
105             registerMethod("ConnectError", *this, &JsonRpcTest::ConnectError);
106             registerMethod("BigRequest", *this, &JsonRpcTest::BigRequest);
107 
108             char* PORT = getenv("UTEST_PORT");
109             if (PORT)
110             {
111                 std::istringstream s(PORT);
112                 s >> _port;
113             }
114         }
115 
failTest()116         void failTest()
117         {
118             throw cxxtools::unit::Assertion("test timed out", CXXTOOLS_SOURCEINFO);
119         }
120 
setUp()121         void setUp()
122         {
123             _loop.setIdleTimeout(2000);
124             connect(_loop.timeout, *this, &JsonRpcTest::failTest);
125             connect(_loop.timeout, _loop, &cxxtools::EventLoop::exit);
126 
127             _server = new cxxtools::json::RpcServer(_loop, _port);
128             _server->minThreads(1);
129         }
130 
tearDown()131         void tearDown()
132         {
133             delete _server;
134         }
135 
136         ////////////////////////////////////////////////////////////
137         // Nothing
138         //
Nothing()139         void Nothing()
140         {
141             _server->registerMethod("multiply", *this, &JsonRpcTest::multiplyNothing);
142 
143             cxxtools::json::RpcClient client(_loop, "", _port);
144             cxxtools::RemoteProcedure<bool> multiply(client, "multiply");
145 
146             multiply.begin();
147             CXXTOOLS_UNIT_ASSERT_EQUALS(multiply.end(2000), false);
148         }
149 
multiplyNothing()150         bool multiplyNothing()
151         {
152             return false;
153         }
154 
155         ////////////////////////////////////////////////////////////
156         // CallbackException
157         //
CallbackException()158         void CallbackException()
159         {
160             _server->registerMethod("multiply", *this, &JsonRpcTest::multiplyNothing);
161 
162             cxxtools::json::RpcClient client(_loop, "", _port);
163             cxxtools::RemoteProcedure<bool> multiply(client, "multiply");
164             connect( multiply.finished, *this, &JsonRpcTest::onExceptionCallback );
165 
166             multiply.begin();
167 
168             _count = 0;
169             CXXTOOLS_UNIT_ASSERT_THROW(_loop.run(), std::runtime_error);
170             CXXTOOLS_UNIT_ASSERT_EQUALS(_count, 1);
171         }
172 
onExceptionCallback(const cxxtools::RemoteResult<bool> & r)173         void onExceptionCallback(const cxxtools::RemoteResult<bool>& r)
174         {
175             log_warn("exception callback");
176             ++_count;
177             _loop.exit();
178             throw std::runtime_error("my error");
179         }
180 
181         ////////////////////////////////////////////////////////////
182         // ConnectError
183         //
ConnectError()184         void ConnectError()
185         {
186             log_trace("ConnectError");
187 
188             cxxtools::json::RpcClient client(_loop, "", _port + 1);
189             cxxtools::RemoteProcedure<bool> multiply(client, "multiply");
190             connect( multiply.finished, *this, &JsonRpcTest::onConnectErrorCallback );
191 
192             multiply.begin();
193 
194             try
195             {
196                 _loop.run();
197             }
198             catch (const std::exception& e)
199             {
200                 log_error("loop exited with exception: " << e.what());
201                 CXXTOOLS_UNIT_ASSERT_MSG(false, std::string("unexpected exception ") + typeid(e).name() + ": " + e.what());
202             }
203         }
204 
onConnectErrorCallback(const cxxtools::RemoteResult<bool> & r)205         void onConnectErrorCallback(const cxxtools::RemoteResult<bool>& r)
206         {
207             log_debug("onConnectErrorCallback");
208             _loop.exit();
209             CXXTOOLS_UNIT_ASSERT_THROW(r.get(), std::exception);
210         }
211 
212         ////////////////////////////////////////////////////////////
213         // Boolean
214         //
Boolean()215         void Boolean()
216         {
217             _server->registerMethod("boolean", *this, &JsonRpcTest::boolean);
218 
219             cxxtools::json::RpcClient client(_loop, "", _port);
220             cxxtools::RemoteProcedure<bool, bool, bool> multiply(client, "boolean");
221 
222             multiply.begin(true, true);
223             CXXTOOLS_UNIT_ASSERT_EQUALS(multiply.end(2000), true);
224         }
225 
boolean(bool a,bool b)226         bool boolean(bool a, bool b)
227         {
228             CXXTOOLS_UNIT_ASSERT_EQUALS(a, true);
229             CXXTOOLS_UNIT_ASSERT_EQUALS(b, true);
230             return true;
231         }
232 
233         ////////////////////////////////////////////////////////////
234         // Integer
235         //
Integer()236         void Integer()
237         {
238             _server->registerMethod("multiply", *this, &JsonRpcTest::multiplyInt);
239 
240             cxxtools::json::RpcClient client(_loop, "", _port);
241             cxxtools::RemoteProcedure<int, int, int> multiply(client, "multiply");
242 
243             multiply.begin(2, 3);
244             CXXTOOLS_UNIT_ASSERT_EQUALS(multiply.end(2000), 6);
245         }
246 
multiplyInt(int a,int b)247         int multiplyInt(int a, int b)
248         {
249             return a*b;
250         }
251 
252         ////////////////////////////////////////////////////////////
253         // Double
254         //
Double()255         void Double()
256         {
257             _server->registerMethod("multiply", *this, &JsonRpcTest::multiplyDouble);
258 
259             cxxtools::json::RpcClient client(_loop, "", _port);
260             cxxtools::RemoteProcedure<double, double, double> multiply(client, "multiply");
261 
262             multiply.begin(2.0, 3.0);
263             CXXTOOLS_UNIT_ASSERT_EQUALS(multiply.end(2000), 6.0);
264         }
265 
multiplyDouble(double a,double b)266         double multiplyDouble(double a, double b)
267         {
268             return a*b;
269         }
270 
271         ////////////////////////////////////////////////////////////
272         // String
273         //
String()274         void String()
275         {
276             _server->registerMethod("echoString", *this, &JsonRpcTest::echoString);
277 
278             cxxtools::json::RpcClient client(_loop, "", _port);
279             cxxtools::RemoteProcedure<std::string, std::string> echo(client, "echoString");
280 
281             echo.begin("\xc3\xaf\xc2\xbb\xc2\xbf'\"&<> foo?");
282             CXXTOOLS_UNIT_ASSERT_EQUALS(echo.end(2000), "\xc3\xaf\xc2\xbb\xc2\xbf'\"&<> foo?");
283         }
284 
echoString(std::string a)285         std::string echoString(std::string a)
286         {
287             return a;
288         }
289 
290         ////////////////////////////////////////////////////////////
291         // EmptyValues
292         //
EmptyValues()293         void EmptyValues()
294         {
295             _server->registerMethod("multiply", *this, &JsonRpcTest::multiplyEmpty);
296 
297             cxxtools::json::RpcClient client(_loop, "", _port);
298             cxxtools::RemoteProcedure<std::string, std::string, std::string> multiply(client, "multiply");
299 
300             multiply.begin("", "");
301             CXXTOOLS_UNIT_ASSERT_EQUALS(multiply.end(2000), "4");
302         }
303 
multiplyEmpty(std::string a,std::string b)304         std::string multiplyEmpty(std::string a, std::string b)
305         {
306             CXXTOOLS_UNIT_ASSERT_EQUALS(a, "");
307             CXXTOOLS_UNIT_ASSERT_EQUALS(b, "");
308             return "4";
309         }
310 
311         ////////////////////////////////////////////////////////////
312         // Array
313         //
Array()314         void Array()
315         {
316             _server->registerMethod("multiply", *this, &JsonRpcTest::multiplyVector);
317 
318             cxxtools::json::RpcClient client(_loop, "", _port);
319             cxxtools::RemoteProcedure< std::vector<int>, std::vector<int>, std::vector<int> > multiply(client, "multiply");
320 
321             std::vector<int> vec;
322             vec.push_back(10);
323             vec.push_back(20);
324 
325             multiply.begin(vec, vec);
326             std::vector<int> r = multiply.end(2000);
327             CXXTOOLS_UNIT_ASSERT_EQUALS(r.size(), 2);
328             CXXTOOLS_UNIT_ASSERT_EQUALS(r.at(0), 100);
329             CXXTOOLS_UNIT_ASSERT_EQUALS(r.at(1), 400);
330         }
331 
multiplyVector(const std::vector<int> & a,const std::vector<int> & b)332         std::vector<int> multiplyVector(const std::vector<int>& a, const std::vector<int>& b)
333         {
334             std::vector<int> r;
335             if( a.size() )
336             {
337                 r.push_back( a.at(0) * b.at(0) );
338                 r.push_back( a.at(1) * b.at(1) );
339             }
340 
341             return r;
342         }
343 
344         ////////////////////////////////////////////////////////////
345         // EmptyArray
346         //
EmptyArray()347         void EmptyArray()
348         {
349             _server->registerMethod("multiply", *this, &JsonRpcTest::multiplyVector);
350 
351             cxxtools::json::RpcClient client(_loop, "", _port);
352             cxxtools::RemoteProcedure< std::vector<int>, std::vector<int>, std::vector<int> > multiply(client, "multiply");
353 
354             std::vector<int> vec;
355             multiply.begin(vec, vec);
356             CXXTOOLS_UNIT_ASSERT_EQUALS(multiply.end(2000).size(), 0);
357         }
358 
359         ////////////////////////////////////////////////////////////
360         // Struct
361         //
Struct()362         void Struct()
363         {
364             _server->registerMethod("multiply", *this, &JsonRpcTest::multiplyColor);
365 
366             cxxtools::json::RpcClient client(_loop, "", _port);
367             cxxtools::RemoteProcedure< Color, Color, Color > multiply(client, "multiply");
368 
369             Color a;
370             a.red = 2;
371             a.green = 3;
372             a.blue = 4;
373 
374             Color b;
375             b.red = 3;
376             b.green = 4;
377             b.blue = 5;
378 
379             multiply.begin(a, b);
380             Color r = multiply.end(2000);
381             CXXTOOLS_UNIT_ASSERT_EQUALS(r.red, 6);
382             CXXTOOLS_UNIT_ASSERT_EQUALS(r.green, 12);
383             CXXTOOLS_UNIT_ASSERT_EQUALS(r.blue, 20);
384         }
385 
multiplyColor(const Color & a,const Color & b)386         Color multiplyColor(const Color& a, const Color& b)
387         {
388             Color color;
389             color.red = a.red * b.red;
390             color.green = a.green * b.green;
391             color.blue = a.blue * b.blue;
392             return color;
393         }
394 
395         ////////////////////////////////////////////////////////////
396         // Set
397         //
Set()398         void Set()
399         {
400             _server->registerMethod("multiplyset", *this, &JsonRpcTest::multiplySet);
401 
402             cxxtools::json::RpcClient client(_loop, "", _port);
403             cxxtools::RemoteProcedure<IntSet, IntSet, int> multiply(client, "multiplyset");
404 
405             IntSet myset;
406             myset.insert(4);
407             myset.insert(5);
408             myset.insert(11);
409             myset.insert(5);
410 
411             multiply.begin(myset, 2);
412             const IntSet& v = multiply.end(2000);
413             CXXTOOLS_UNIT_ASSERT_EQUALS(v.size(), 3);
414             CXXTOOLS_UNIT_ASSERT(v.find(8) != v.end());
415             CXXTOOLS_UNIT_ASSERT(v.find(10) != v.end());
416             CXXTOOLS_UNIT_ASSERT(v.find(22) != v.end());
417         }
418 
multiplySet(const IntSet & s,int f)419         IntSet multiplySet(const IntSet& s, int f)
420         {
421             IntSet ret;
422             for (IntSet::const_iterator it = s.begin(); it != s.end(); ++it)
423                 ret.insert(*it * f);
424             return ret;
425         }
426 
427         ////////////////////////////////////////////////////////////
428         // Multiset
429         //
Multiset()430         void Multiset()
431         {
432             _server->registerMethod("multiplyset", *this, &JsonRpcTest::multiplyMultiset);
433 
434             cxxtools::json::RpcClient client(_loop, "", _port);
435             cxxtools::RemoteProcedure<IntMultiset, IntMultiset, int> multiply(client, "multiplyset");
436 
437             IntMultiset myset;
438             myset.insert(4);
439             myset.insert(5);
440             myset.insert(11);
441             myset.insert(5);
442 
443             multiply.begin(myset, 2);
444             const IntMultiset& v = multiply.end(2000);
445             CXXTOOLS_UNIT_ASSERT_EQUALS(v.size(), 4);
446             CXXTOOLS_UNIT_ASSERT_EQUALS(v.count(8), 1);
447             CXXTOOLS_UNIT_ASSERT_EQUALS(v.count(10), 2);
448             CXXTOOLS_UNIT_ASSERT_EQUALS(v.count(22), 1);
449         }
450 
multiplyMultiset(const IntMultiset & s,int f)451         IntMultiset multiplyMultiset(const IntMultiset& s, int f)
452         {
453             IntMultiset ret;
454             for (IntMultiset::const_iterator it = s.begin(); it != s.end(); ++it)
455                 ret.insert(*it * f);
456             return ret;
457         }
458 
459         ////////////////////////////////////////////////////////////
460         // Map
461         //
Map()462         void Map()
463         {
464             _server->registerMethod("multiplymap", *this, &JsonRpcTest::multiplyMap);
465 
466             cxxtools::json::RpcClient client(_loop, "", _port);
467             cxxtools::RemoteProcedure<IntMap, IntMap, int> multiply(client, "multiplymap");
468 
469             IntMap mymap;
470             mymap[2] = 4;
471             mymap[7] = 7;
472             mymap[1] = -1;
473 
474             multiply.begin(mymap, 2);
475             const IntMap& v = multiply.end(2000);
476 
477             CXXTOOLS_UNIT_ASSERT_EQUALS(v.size(), 3);
478             CXXTOOLS_UNIT_ASSERT(v.find(2) != v.end());
479             CXXTOOLS_UNIT_ASSERT_EQUALS(v.find(2)->second, 8);
480             CXXTOOLS_UNIT_ASSERT(v.find(7) != v.end());
481             CXXTOOLS_UNIT_ASSERT_EQUALS(v.find(7)->second, 14);
482             CXXTOOLS_UNIT_ASSERT(v.find(1) != v.end());
483             CXXTOOLS_UNIT_ASSERT_EQUALS(v.find(1)->second, -2);
484         }
485 
multiplyMap(const IntMap & m,int f)486         IntMap multiplyMap(const IntMap& m, int f)
487         {
488             IntMap ret;
489             for (IntMap::const_iterator it = m.begin(); it != m.end(); ++it)
490             {
491                 ret[it->first] = it->second * f;
492             }
493 
494             return ret;
495         }
496 
497         ////////////////////////////////////////////////////////////
498         // Multimap
499         //
Multimap()500         void Multimap()
501         {
502             _server->registerMethod("multiplymultimap", *this, &JsonRpcTest::multiplyMultimap);
503 
504             cxxtools::json::RpcClient client(_loop, "", _port);
505             cxxtools::RemoteProcedure<IntMultimap, IntMultimap, int> multiply(client, "multiplymultimap");
506 
507             IntMultimap mymap;
508             mymap.insert(IntMultimap::value_type(2, 4));
509             mymap.insert(IntMultimap::value_type(7, 7));
510             mymap.insert(IntMultimap::value_type(7, 8));
511             mymap.insert(IntMultimap::value_type(1, -1));
512 
513             multiply.begin(mymap, 2);
514             const IntMultimap& v = multiply.end(200);
515 
516             CXXTOOLS_UNIT_ASSERT_EQUALS(v.size(), 4);
517             CXXTOOLS_UNIT_ASSERT(v.lower_bound(2) != v.end());
518             CXXTOOLS_UNIT_ASSERT_EQUALS(v.lower_bound(2)->second, 8);
519             CXXTOOLS_UNIT_ASSERT(v.lower_bound(7) != v.end());
520             CXXTOOLS_UNIT_ASSERT_EQUALS(v.lower_bound(7)->second, 14);
521             IntMultimap::const_iterator it = v.lower_bound(7);
522             ++it;
523             CXXTOOLS_UNIT_ASSERT(it != v.end());
524             CXXTOOLS_UNIT_ASSERT_EQUALS(it->first, 7);
525             CXXTOOLS_UNIT_ASSERT_EQUALS(it->second, 16);
526             CXXTOOLS_UNIT_ASSERT(v.lower_bound(1) != v.end());
527             CXXTOOLS_UNIT_ASSERT_EQUALS(v.lower_bound(1)->second, -2);
528         }
529 
multiplyMultimap(const IntMultimap & m,int f)530         IntMultimap multiplyMultimap(const IntMultimap& m, int f)
531         {
532             IntMultimap ret;
533             for (IntMultimap::const_iterator it = m.begin(); it != m.end(); ++it)
534             {
535                 ret.insert(IntMultimap::value_type(it->first, it->second * f));
536             }
537 
538             return ret;
539         }
540 
541         ////////////////////////////////////////////////////////////
542         // CallPrefix
543         //
CallPrefix()544         void CallPrefix()
545         {
546             _server->registerMethod("somePrefix.multiply", *this, &JsonRpcTest::multiplyInt);
547 
548             cxxtools::json::RpcClient client(_loop, "", _port);
549             client.prefix("somePrefix.");
550             cxxtools::RemoteProcedure<int, int, int> multiply(client, "multiply");
551 
552             multiply.begin(2, 3);
553             CXXTOOLS_UNIT_ASSERT_EQUALS(multiply.end(2000), 6);
554         }
555 
UnknownMethod()556         void UnknownMethod()
557         {
558             cxxtools::json::RpcClient client(_loop, "", _port);
559             cxxtools::RemoteProcedure<bool> unknownMethod(client, "unknownMethod");
560 
561             unknownMethod.begin();
562 
563             CXXTOOLS_UNIT_ASSERT_THROW(unknownMethod.end(2000), cxxtools::RemoteException);
564         }
565 
566         ////////////////////////////////////////////////////////////
567         // Fault
568         //
Fault()569         void Fault()
570         {
571             _server->registerMethod("multiply", *this, &JsonRpcTest::throwFault);
572 
573             cxxtools::json::RpcClient client(_loop, "", _port);
574             cxxtools::RemoteProcedure<bool> multiply(client, "multiply");
575             multiply.begin();
576 
577             try
578             {
579                 multiply.end(2000);
580                 CXXTOOLS_UNIT_ASSERT_MSG(false, "cxxtools::RemoteException exception expected");
581             }
582             catch (const cxxtools::RemoteException& e)
583             {
584                 CXXTOOLS_UNIT_ASSERT_EQUALS(e.rc(), 7);
585                 CXXTOOLS_UNIT_ASSERT_EQUALS(e.text(), "Fault");
586             }
587         }
588 
throwFault()589         bool throwFault()
590         {
591             throw cxxtools::RemoteException("Fault", 7);
592             return false;
593         }
594 
595         ////////////////////////////////////////////////////////////
596         // Exception
597         //
Exception()598         void Exception()
599         {
600             _server->registerMethod("multiply", *this, &JsonRpcTest::throwException);
601 
602             cxxtools::json::RpcClient client(_loop, "", _port);
603             cxxtools::RemoteProcedure<bool> multiply(client, "multiply");
604 
605             multiply.begin();
606 
607             try
608             {
609                 multiply.end(2000);
610                 CXXTOOLS_UNIT_ASSERT(false);
611             }
612             catch (const cxxtools::RemoteException& e)
613             {
614                 CXXTOOLS_UNIT_ASSERT_EQUALS(e.rc(), 0);
615                 CXXTOOLS_UNIT_ASSERT_EQUALS(e.text(), "Exception");
616             }
617         }
618 
throwException()619         bool throwException()
620         {
621             throw std::runtime_error("Exception");
622             return false;
623         }
624 
625         ////////////////////////////////////////////////////////////
626         // BigRequest
627         //
BigRequest()628         void BigRequest()
629         {
630             log_trace("ConnectError");
631 
632             _server->registerMethod("countSize", *this, &JsonRpcTest::countSize);
633 
634             cxxtools::json::RpcClient client(_loop, "", _port);
635             cxxtools::RemoteProcedure<unsigned, std::vector<int> > countSize(client, "countSize");
636 
637             std::vector<int> v;
638             v.resize(5000);
639 
640             countSize.begin(v);
641 
642             try
643             {
644                 countSize.end(2000);
645             }
646             catch (const std::exception& e)
647             {
648                 log_error("loop exited with exception: " << e.what());
649                 CXXTOOLS_UNIT_ASSERT_MSG(false, std::string("unexpected exception ") + typeid(e).name() + ": " + e.what());
650             }
651         }
652 
countSize(const std::vector<int> & v)653         unsigned countSize(const std::vector<int>& v)
654         {
655             return v.size();
656         }
657 
658 };
659 
660 cxxtools::unit::RegisterTest<JsonRpcTest> register_JsonRpcTest;
661