HelloTest.cpp
Go to the documentation of this file.
1 /*
2  * Unit tests for XmlRpc++
3  *
4  * Copyright (C) 2017, Zoox Inc
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  *
20  * Author: Austin Hendrix <austin@zoox.com>
21  * Loosely based on HelloServer.cpp and HelloClient.cpp by Chris Morley
22  *
23  */
24 
25 #include "xmlrpcpp/XmlRpc.h"
26 #include "xmlrpcpp/XmlRpcClient.h"
27 #include "xmlrpcpp/XmlRpcServer.h"
29 
30 #include <iostream>
31 #include <stdlib.h>
32 #include <boost/thread/thread.hpp>
33 #include <boost/thread/mutex.hpp>
34 #include <functional>
35 
36 #include <gtest/gtest.h>
37 
42 
43 // No arguments, result is "Hello".
44 class Hello : public XmlRpcServerMethod
45 {
46 public:
48 
49  void execute(XmlRpcValue& params, XmlRpcValue& result)
50  {
51  (void)params;
52  result = "Hello";
53  }
54 
55  std::string help()
56  {
57  return std::string("Say hello");
58  }
59 };
60 
61 // One argument is passed, result is "Hello, " + arg.
62 class HelloName : public XmlRpcServerMethod
63 {
64 public:
65  HelloName(XmlRpcServer* s) : XmlRpcServerMethod("HelloName", s) {}
66 
67  void execute(XmlRpcValue& params, XmlRpcValue& result)
68  {
69  std::string resultString = "Hello, ";
70  resultString += std::string(params[0]);
71  result = resultString;
72  }
73 };
74 
75 // A variable number of arguments are passed, all doubles, result is their sum.
76 class Sum : public XmlRpcServerMethod
77 {
78 public:
80 
81  void execute(XmlRpcValue& params, XmlRpcValue& result)
82  {
83  int nArgs = params.size();
84  double sum = 0.0;
85  for (int i = 0; i < nArgs; ++i)
86  sum += double(params[i]);
87  result = sum;
88  }
89 };
90 
91 class XmlRpcTest : public ::testing::Test
92 {
93 protected:
94  XmlRpcTest() : hello(&s), helloName(&s), sum(&s), port(0), done(false) {}
95 
96  void work()
97  {
98  while (!done)
99  {
100  s.work(0.1); // run the worker queue for 100ms
101  }
102  }
103 
104  virtual void SetUp()
105  {
106  // XmlRpc::setVerbosity(5);
107 
108  // Create the server socket. Passing 0 for the port number requests that
109  // the OS randomly select an available port.
110  s.bindAndListen(0);
111  // Retrieve the assigned port number.
112  port = s.get_port();
113 
114  // Enable introspection.
115  s.enableIntrospection(true);
116 
117  // Start the worker thread.
118  server_thread = boost::thread(boost::mem_fn(&XmlRpcTest::work), this);
119  }
120 
121  virtual void TearDown()
122  {
123  // TODO(austin): determine if we need to do anything here to avoid
124  // leaking resources
125  done = true;
126  server_thread.join();
127  s.shutdown();
128  }
129 
130  // The server and its methods
135 
136  // Server port number (for clients)
137  int port;
138 
139  // Server thread
140  bool done;
141  boost::thread server_thread;
142 };
143 
144 TEST_F(XmlRpcTest, Introspection)
145 {
146  XmlRpcClient c("localhost", port);
147 
148  // Use introspection API to look up the supported methods
149  XmlRpcValue noArgs, result;
150 
151  ASSERT_TRUE(c.execute("system.listMethods", noArgs, result));
152 
153  XmlRpcValue methods;
154  methods[0] = "Hello";
155  methods[1] = "HelloName";
156  methods[2] = "Sum";
157  methods[3] = "system.listMethods";
158  methods[4] = "system.methodHelp";
159  methods[5] = "system.multicall";
160  EXPECT_EQ(result, methods);
161 
162  // Use introspection API to get the help string for the Hello method
163  XmlRpcValue oneArg;
164  oneArg[0] = "Hello";
165 
166  ASSERT_TRUE(c.execute("system.methodHelp", oneArg, result));
167 
168  EXPECT_EQ(result, XmlRpcValue("Say hello"));
169 
170  // Use introspection API to get the help string for the HelloName method
171  // This should be the default help string, ie empty string.
172  oneArg[0] = "HelloName";
173 
174  ASSERT_TRUE(c.execute("system.methodHelp", oneArg, result));
175 
176  EXPECT_EQ(result, XmlRpcValue(""));
177 }
178 
180 {
181  XmlRpcClient c("localhost", port);
182  XmlRpcValue noArgs, result;
183 
184  // Call the Hello method
185  ASSERT_TRUE(c.execute("Hello", noArgs, result));
186 
187  EXPECT_EQ(result, XmlRpcValue("Hello"));
188 }
189 
190 TEST_F(XmlRpcTest, HelloURI)
191 {
192  XmlRpcClient c("localhost", port, "/");
193  XmlRpcValue noArgs, result;
194 
195  // Call the Hello method
196  ASSERT_TRUE(c.execute("Hello", noArgs, result));
197 
198  EXPECT_EQ(result, XmlRpcValue("Hello"));
199 }
200 
202 {
203  XmlRpcClient c("localhost", port);
204  XmlRpcValue oneArg, result;
205 
206  // Call the HelloName method
207  oneArg[0] = "Chris";
208  ASSERT_TRUE(c.execute("HelloName", oneArg, result));
209 
210  EXPECT_EQ(result, XmlRpcValue("Hello, Chris"));
211 }
212 
214 {
215  XmlRpcClient c("localhost", port);
216  XmlRpcValue result;
217 
218  // Add up an array of numbers
219  XmlRpcValue numbers;
220  numbers[0] = 33.33;
221  numbers[1] = 112.57;
222  numbers[2] = 76.1;
223  EXPECT_EQ(numbers.size(), 3);
224 
225  ASSERT_TRUE(c.execute("Sum", numbers, result));
226  EXPECT_DOUBLE_EQ(double(result), 222.0);
227 
228  // Test the "no such method" fault
229  ASSERT_TRUE(c.execute("NoSuchMethod", numbers, result));
230  EXPECT_TRUE(c.isFault());
231 
232  XmlRpcValue fault;
233  fault["faultCode"] = -1;
234  fault["faultString"] = "NoSuchMethod: unknown method name";
235  EXPECT_EQ(result, fault);
236 }
237 
238 TEST_F(XmlRpcTest, Multicall)
239 {
240  XmlRpcClient c("localhost", port);
241  XmlRpcValue result;
242 
243  // Test the multicall method. It accepts one arg, an array of structs
244  XmlRpcValue multicall, expected_result;
245  multicall[0][0]["methodName"] = "Sum";
246  multicall[0][0]["params"][0] = 5.0;
247  multicall[0][0]["params"][1] = 9.0;
248  expected_result[0][0] = 14.0;
249 
250  multicall[0][1]["methodName"] = "NoSuchMethod";
251  multicall[0][1]["params"][0] = "";
252  expected_result[1]["faultCode"] = -1;
253  expected_result[1]["faultString"] = "NoSuchMethod: unknown method name";
254 
255  multicall[0][2]["methodName"] = "Sum";
256  // Missing params
257  expected_result[2]["faultCode"] = -1;
258  expected_result[2]["faultString"] = "system.multicall: Invalid argument "
259  "(expected a struct with members "
260  "methodName and params)";
261 
262  multicall[0][3]["methodName"] = "Sum";
263  multicall[0][3]["params"][0] = 10.5;
264  multicall[0][3]["params"][1] = 12.5;
265  expected_result[3][0] = 23.0;
266 
267  ASSERT_TRUE(c.execute("system.multicall", multicall, result));
268  EXPECT_EQ(result, expected_result);
269  EXPECT_EQ(result.toXml(), expected_result.toXml());
270 }
271 
272 int main(int argc, char **argv)
273 {
274  ::testing::InitGoogleTest(&argc, argv);
275  return RUN_ALL_TESTS();
276 }
HelloName helloName
Definition: HelloTest.cpp:133
int size() const
Return the size for string, base64, array, and struct values.
HelloName(XmlRpcServer *s)
Definition: HelloTest.cpp:65
RPC method arguments and results are represented by Values.
Definition: XmlRpcValue.h:24
void shutdown()
Close all connections with clients and the socket file descriptor.
int main(int argc, char **argv)
Definition: HelloTest.cpp:272
void work(double msTime)
Process client requests for the specified time.
bool bindAndListen(int port, int backlog=5)
XmlRpcServer s
Definition: HelloServer.cpp:11
Sum(XmlRpcServer *s)
Definition: HelloTest.cpp:79
Abstract class representing a single RPC method.
Hello(XmlRpcServer *s)
Definition: HelloTest.cpp:47
virtual void SetUp()
Definition: HelloTest.cpp:104
void enableIntrospection(bool enabled=true)
Specify whether introspection is enabled or not. Default is not enabled.
void execute(XmlRpcValue &params, XmlRpcValue &result)
Execute the method. Subclasses must provide a definition for this method.
Definition: HelloTest.cpp:49
A class to handle XML RPC requests.
Definition: XmlRpcServer.h:41
void work()
Definition: HelloTest.cpp:96
A class to send XML RPC requests to a server and return the results.
Definition: XmlRpcClient.h:26
virtual void TearDown()
Definition: HelloTest.cpp:121
void execute(XmlRpcValue &params, XmlRpcValue &result)
Execute the method. Subclasses must provide a definition for this method.
Definition: HelloTest.cpp:81
TEST_F(XmlRpcTest, Introspection)
Definition: HelloTest.cpp:144
std::string help()
Definition: HelloTest.cpp:55
std::string toXml() const
Encode the Value in xml.
bool execute(const char *method, XmlRpcValue const &params, XmlRpcValue &result)
XmlRpcServer s
Definition: HelloTest.cpp:131
boost::thread server_thread
Definition: HelloTest.cpp:141
Hello hello
Definition: HelloTest.cpp:132
bool isFault() const
Returns true if the result of the last execute() was a fault response.
Definition: XmlRpcClient.h:65
void execute(XmlRpcValue &params, XmlRpcValue &result)
Execute the method. Subclasses must provide a definition for this method.
Definition: HelloTest.cpp:67


xmlrpcpp
Author(s): Chris Morley, Konstantin Pilipchuk, Morgan Quigley, Austin Hendrix, Dirk Thomas
autogenerated on Mon Feb 28 2022 23:33:22