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