test/TestValues.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 the original TestValues.cpp by Chris Morley
22  *
23  */
24 
25 // TestValues.cpp : Test XML encoding and decoding of XmlRpcValues.
26 
27 #include <stdlib.h>
28 #include <string>
29 
30 #include "xmlrpcpp/XmlRpcValue.h"
32 
33 #include <gtest/gtest.h>
34 
35 using namespace XmlRpc;
36 
37 TEST(XmlRpc, Bool) {
38  XmlRpcValue v(bool(false));
39 
40  EXPECT_EQ("<value><boolean>0</boolean></value>", v.toXml());
41 
42  XmlRpcValue v2;
43  v2[0] = int(1);
44  v2[1] = std::string();
45  v2[2] = XmlRpcValue(false);
46  EXPECT_EQ("<value><array><data><value><i4>1</i4></value><value></"
47  "value><value><boolean>0</boolean></value></data></array></value>",
48  v2.toXml());
49 }
50 
52  XmlRpcValue booleanFalse(false);
53  XmlRpcValue booleanTrue(true);
54  int offset = 0;
55  XmlRpcValue booleanFalseXml("<value><boolean>0</boolean></value>", &offset);
56  offset = 0;
57  XmlRpcValue booleanTrueXml("<value><boolean>1</boolean></value>", &offset);
58  EXPECT_NE(booleanFalse, booleanTrue);
59  EXPECT_EQ(booleanFalse, booleanFalseXml);
60  EXPECT_NE(booleanFalse, booleanTrueXml);
61 
62  EXPECT_FALSE(bool(booleanFalse));
63 
64  EXPECT_TRUE(bool(booleanTrue));
65 
66  // Test stream operator.
67  std::stringstream ss;
68  ss << booleanFalse;
69  EXPECT_EQ("0", ss.str());
70 
71  std::stringstream ss2;
72  ss2 << booleanTrue;
73  EXPECT_EQ("1", ss2.str());
74 }
75 
76 // Int
78  XmlRpcValue int0(0);
79  ASSERT_EQ(XmlRpcValue::TypeInt, int0.getType());
80 
81  XmlRpcValue int1(1);
82  ASSERT_EQ(XmlRpcValue::TypeInt, int1.getType());
83 
84  XmlRpcValue int10(10);
85  ASSERT_EQ(XmlRpcValue::TypeInt, int10.getType());
86 
87  XmlRpcValue int_1(-1);
88  ASSERT_EQ(XmlRpcValue::TypeInt, int_1.getType());
89 
90  int offset = 0;
91  XmlRpcValue int0Xml("<value><int>0</int></value>", &offset);
92  ASSERT_EQ(XmlRpcValue::TypeInt, int0Xml.getType());
93  EXPECT_EQ(0, int(int0Xml));
94 
95  offset = 0;
96  XmlRpcValue int9Xml("<value><i4>9</i4></value>", &offset);
97  ASSERT_EQ(XmlRpcValue::TypeInt, int9Xml.getType());
98  EXPECT_EQ(9, int(int9Xml));
99 
100  EXPECT_EQ(int0, int0Xml);
101  EXPECT_EQ(int(int10) - int(int1), int(int9Xml));
102  EXPECT_EQ(9, int(int9Xml));
103  EXPECT_EQ(int(int10) + int(int_1), int(int9Xml));
104 
105  // Test stream operator.
106  std::stringstream ss;
107  ss << int9Xml;
108  EXPECT_EQ("9", ss.str());
109 }
110 
112  // Double
113  XmlRpcValue d(43.7);
114  ASSERT_EQ(XmlRpcValue::TypeDouble, d.getType());
115  EXPECT_EQ("<value><double>43.700000000000003</double></value>", d.toXml());
116  EXPECT_DOUBLE_EQ(43.7, double(d));
117 
118  int offset = 0;
119  XmlRpcValue dXml("<value><double>56.3</double></value>", &offset);
120  ASSERT_EQ(XmlRpcValue::TypeDouble, dXml.getType());
121  EXPECT_DOUBLE_EQ(56.3, double(dXml));
122 
123  EXPECT_DOUBLE_EQ(100.0, double(d) + double(dXml));
124 
125  // Test stream operator.
126  std::stringstream ss;
127  ss << d;
128  EXPECT_EQ("43.7", ss.str());
129 }
130 
132  // String
133  XmlRpcValue s("Now is the time <&");
134  ASSERT_EQ(XmlRpcValue::TypeString, s.getType());
135  EXPECT_EQ(18, s.size());
136  EXPECT_EQ("<value>Now is the time &lt;&amp;</value>", s.toXml());
137 
138  char csxml[] = "<value><string>Now is the time &lt;&amp;</string></value>";
139  std::string ssxml = csxml;
140 
141  int offset = 0;
142  XmlRpcValue vscXml(csxml, &offset);
143  EXPECT_EQ(s, vscXml);
144 
145  offset = 0;
146  XmlRpcValue vssXml(ssxml, &offset);
147  EXPECT_EQ(s, vssXml);
148 
149  offset = 0;
150  XmlRpcValue fromXml(vssXml.toXml(), &offset);
151  EXPECT_EQ(s, fromXml);
152 
153  // Empty or blank strings with no <string> tags
154  std::string emptyStringXml("<value></value>");
155  offset = 0;
156  XmlRpcValue emptyStringVal1(emptyStringXml, &offset);
157  XmlRpcValue emptyStringVal2("");
158  EXPECT_EQ(emptyStringVal1, emptyStringVal2);
159 
160  emptyStringXml = "<value> </value>";
161  offset = 0;
162  XmlRpcValue blankStringVal(emptyStringXml, &offset);
163  EXPECT_EQ(std::string(blankStringVal), " ");
164 
165  // Implicitly initialized string.
166  XmlRpcValue s2;
167  std::string tmp = s2;
168  EXPECT_EQ("", tmp);
169  EXPECT_EQ("", (std::string)s2);
170 
171  // Test stream operator.
172  std::stringstream ss;
173  ss << s;
174  EXPECT_EQ("Now is the time <&", ss.str());
175 }
176 
178  // DateTime
179  int offset = 0;
180  // Construct from XML
181  XmlRpcValue dateTime(
182  "<value><dateTime.iso8601>19040503T03:12:35</dateTime.iso8601></value>",
183  &offset);
184  ASSERT_EQ(XmlRpcValue::TypeDateTime, dateTime.getType());
185  struct tm t = dateTime;
186  EXPECT_EQ(t.tm_year, 1904);
187  EXPECT_EQ(t.tm_min, 12);
188  EXPECT_EQ(t.tm_sec, 35);
189  EXPECT_EQ(t.tm_hour, 3);
190  EXPECT_EQ(t.tm_mday, 3);
191  EXPECT_EQ(t.tm_mon, 5);
192 
193  EXPECT_EQ(
194  "<value><dateTime.iso8601>19040503T03:12:35</dateTime.iso8601></value>",
195  dateTime.toXml());
196 
197  // Constructor from struct tm.
198  XmlRpcValue dateTime2(&t);
199  ASSERT_EQ(XmlRpcValue::TypeDateTime, dateTime2.getType());
200  t = dateTime2;
201  EXPECT_EQ(t.tm_year, 1904);
202  EXPECT_EQ(t.tm_min, 12);
203 
204  // Implicit initialization by cast.
205  XmlRpcValue dateTime3;
206  t = dateTime3;
207  ASSERT_EQ(XmlRpcValue::TypeDateTime, dateTime3.getType());
208  EXPECT_EQ(t.tm_year, 0);
209  EXPECT_EQ(t.tm_min, 0);
210 
211  // Test stream operator.
212  std::stringstream ss;
213  ss << dateTime;
214  EXPECT_EQ("19040503T03:12:35", ss.str());
215 
216  // Tests for DateTime equality operator
217  EXPECT_EQ(dateTime, dateTime2);
218 
219  // Copy operator
220  dateTime3 = dateTime;
221  EXPECT_EQ(dateTime, dateTime3);
222 
223  // Explicit mutable reference into dateTime2 so that we can modify it to make
224  // it not equal to dateTime in various ways.
225  t = dateTime;
226  struct tm& tm2 = dateTime2;
227  // Seconds not equal.
228  tm2.tm_sec = 0;
229  EXPECT_NE(dateTime, dateTime2);
230  tm2 = t;
231  ASSERT_EQ(dateTime, dateTime2);
232 
233  // Minutes not equal.
234  tm2.tm_min = 0;
235  EXPECT_NE(dateTime, dateTime2);
236  tm2 = t;
237  ASSERT_EQ(dateTime, dateTime2);
238 
239  // Hours not equal.
240  tm2.tm_hour = 0;
241  EXPECT_NE(dateTime, dateTime2);
242  tm2 = t;
243  ASSERT_EQ(dateTime, dateTime2);
244 
245  // Day not equal.
246  tm2.tm_mday = 1;
247  EXPECT_NE(dateTime, dateTime2);
248  tm2 = t;
249  ASSERT_EQ(dateTime, dateTime2);
250 
251  // Month not equal.
252  tm2.tm_mon = 1;
253  EXPECT_NE(dateTime, dateTime2);
254  tm2 = t;
255  ASSERT_EQ(dateTime, dateTime2);
256 
257  // Year not equal.
258  tm2.tm_year = 1988;
259  EXPECT_NE(dateTime, dateTime2);
260 }
261 
263  XmlRpcValue d(43.7);
264  // Array
265  XmlRpcValue a;
266  a.setSize(4);
267  a[0] = 1;
268  a[1] = std::string("two");
269  a[2] = 43.7;
270  a[3] = "four";
271  EXPECT_EQ(XmlRpcValue::TypeArray, a.getType());
272  EXPECT_EQ(int(a[0]), 1);
273  EXPECT_EQ(a[2], d);
274 
275  char csaXml[] = "<value><array>\n"
276  " <data>\n"
277  " <value><i4>1</i4></value> \n"
278  " <value> <string>two</string></value>\n"
279  " <value><double>43.7</double></value>\n"
280  " <value>four</value>\n"
281  " </data>\n"
282  "</array></value>";
283 
284  int offset = 0;
285  XmlRpcValue aXml(csaXml, &offset);
286  EXPECT_EQ(a, aXml);
287 
288  // Array copy works
289  XmlRpcValue copy(a);
290  ASSERT_EQ(a.getType(), copy.getType());
291  ASSERT_EQ(a.size(), copy.size());
292  for (int i = 0; i < 3; i++) {
293  EXPECT_EQ(a[i], copy[i]);
294  }
295  // Test that comparison operator works.
296  EXPECT_EQ(a, copy);
297 
298  // Test that comparison for unlike types returns false.
299  EXPECT_NE(a, d);
300 
301  // Test stream operator.
302  std::stringstream ss;
303  ss << a;
304  EXPECT_EQ("{1,two,43.7,four}", ss.str());
305 }
306 
308  // Struct
309  XmlRpcValue struct1;
310  struct1["i4"] = 1;
311  struct1["str"] = "two";
312  struct1["d"] = 43.7;
313  EXPECT_EQ(3, struct1.size());
314  EXPECT_EQ(XmlRpcValue::TypeStruct, struct1.getType());
315  EXPECT_TRUE(struct1.hasMember("i4"));
316  EXPECT_FALSE(struct1.hasMember("nowhere"));
317 
318  // Test stream operator.
319  std::stringstream ss;
320  ss << struct1;
321  EXPECT_EQ("[d:43.7,i4:1,str:two]", ss.str());
322 
323  XmlRpcValue a;
324  a.setSize(4);
325  a[0] = 1;
326  a[1] = std::string("two");
327  a[2] = 43.7;
328  a[3] = "four";
329 
330  EXPECT_EQ(struct1["d"], a[2]);
331 
332  char csStructXml[] = "<value><struct>\n"
333  " <member>\n"
334  " <name>i4</name> \n"
335  " <value><i4>1</i4></value> \n"
336  " </member>\n"
337  " <member>\n"
338  " <name>d</name> \n"
339  " <value><double>43.7</double></value>\n"
340  " </member>\n"
341  " <member>\n"
342  " <name>str</name> \n"
343  " <value> <string>two</string></value>\n"
344  " </member>\n"
345  "</struct></value>";
346 
347  int offset = 0;
348  XmlRpcValue structXml(csStructXml, &offset);
349  EXPECT_EQ(struct1, structXml);
350 
351  for (XmlRpcValue::iterator itr = struct1.begin(); itr != struct1.end();
352  itr++) {
353  }
354 
355  XmlRpcValue astruct;
356  astruct["array"] = a;
357  EXPECT_EQ(astruct["array"][2], struct1["d"]);
358 
359  for (int i = 0; i < 10; i++) {
360  XmlRpcValue Event;
361  Event["Name"] = "string";
362 
363  Event.clear();
364 
365  const int NELMTS = 100;
366  int ii;
367 
368  for (ii = 0; ii < NELMTS; ++ii) {
369  char buf[40];
370  sprintf(buf, "%d", ii);
371  Event[std::string(buf)] = buf;
372  }
373 
374  Event.clear();
375 
376  for (ii = 0; ii < NELMTS; ++ii) {
377  char buf[40];
378  sprintf(buf, "%d", ii);
379  if (ii != NELMTS / 2)
380  Event[std::string(buf)] = ii;
381  else
382  for (int jj = 0; jj < NELMTS; ++jj) {
383  char bufj[40];
384  sprintf(bufj, "%d", jj);
385  Event[std::string(buf)][std::string(bufj)] = bufj;
386  }
387  }
388 
389  for (ii = 0; ii < NELMTS; ++ii) {
390  char buf[40];
391  sprintf(buf, "%d", ii);
392  if (ii != NELMTS / 2)
393  EXPECT_EQ(Event[std::string(buf)], XmlRpcValue(ii));
394  else
395  EXPECT_EQ(Event[std::string(buf)].size(), NELMTS);
396  }
397  }
398 }
399 
401  char data[] = {1, 2};
402  XmlRpcValue bin(data, 2);
403 
404  EXPECT_EQ(XmlRpcValue::TypeBase64, bin.getType());
405  EXPECT_EQ(2, bin.size());
406 
407  XmlRpcValue::BinaryData d = bin;
408  EXPECT_EQ(d[0], 1);
409  EXPECT_EQ(d[1], 2);
410 
411  EXPECT_EQ("<value><base64>AQI=\n</base64></value>", bin.toXml());
412 
413  // Test stream operator.
414  std::stringstream ss;
415  ss << bin;
416  EXPECT_EQ("AQI=\n", ss.str());
417 
418  // Constructor from XML
419  int offset = 0;
420  XmlRpcValue bin2("<value><base64>AQI=</base64></value>", &offset);
421  EXPECT_EQ(XmlRpcValue::TypeBase64, bin2.getType());
422  EXPECT_EQ(2, bin2.size());
423 
424  d = bin2;
425  EXPECT_EQ(d[0], 1);
426  EXPECT_EQ(d[1], 2);
427 
428  EXPECT_EQ(bin, bin2);
429 
430  // Implicit initialization.
431  XmlRpcValue bin3;
432  d = bin3;
433  EXPECT_EQ(XmlRpcValue::TypeBase64, bin3.getType());
434  EXPECT_EQ(0, bin3.size());
435  EXPECT_EQ(0u, d.size());
436 
437  // Copy operator
438  XmlRpcValue bin4;
439  bin4 = bin;
440 
441  EXPECT_EQ(XmlRpcValue::TypeBase64, bin4.getType());
442  EXPECT_EQ(2, bin4.size());
443 
444  d = bin4;
445  EXPECT_EQ(d[0], 1);
446  EXPECT_EQ(d[1], 2);
447 }
448 
449 TEST(XmpRpc, errors) {
450  // Value is initially invalid.
451  XmlRpcValue value;
452  EXPECT_FALSE(value.valid());
453  EXPECT_EQ("", value.toXml());
454 
455  // Implicit bool initialization.
456  bool v = (bool)value;
457  EXPECT_FALSE(v);
458 
459  // Conversions to other types should now throw an XmlRpcException.
460  EXPECT_THROW((void)(int)value, XmlRpcException);
461  EXPECT_THROW(value[0], XmlRpcException);
462  EXPECT_THROW(value["bar"], XmlRpcException);
463 
464  // Tests on const objects.
465  const XmlRpcValue& ref = value;
466  EXPECT_THROW(ref[0], XmlRpcException);
467  // TODO(austin): is this really allowed on non-struct objects?
468  EXPECT_FALSE(ref.hasMember("bar"));
469 
470  // Check that the exception that is thrown is populated correctly.
471  try {
472  (void)int(value);
473  } catch (XmlRpcException& e) {
474  EXPECT_EQ("type error", e.getMessage());
475  EXPECT_EQ(-1, e.getCode());
476  }
477 
478  // size() on bool should throw.
479  EXPECT_THROW(value.size(), XmlRpcException);
480 
481  // Clear should result in invalid again.
482  value.clear();
483  EXPECT_FALSE(value.valid());
484 }
485 
486 TEST(XmlRpc, int_errors) {
487  XmlRpcValue value;
488  // Implicit int initialization.
489  int v = (int)value;
490  EXPECT_EQ(0, v);
491  EXPECT_EQ(0, (int)value);
492 
493  // Conversion to other types should now thrown an exception.
494  EXPECT_THROW((void)(bool)value, XmlRpcException);
495 }
496 
497 TEST(XmlRpc, array_errors) {
498  XmlRpcValue value;
499  // Implicit array creation.
500  int v = value[0];
501  EXPECT_EQ(0, v);
502  EXPECT_THROW((void)(bool)value, XmlRpcException);
503  EXPECT_EQ(1, value.size());
504 
505  // Access on a non-const array should implicitly create another element.
506  EXPECT_EQ(0, (int)value[1]);
507  EXPECT_EQ(2, value.size());
508 
509  // Access to a const array should throw an exception if the index is out of
510  // bounds.
511  const XmlRpcValue& ref = value;
512  EXPECT_THROW(ref[2], XmlRpcException);
513 }
514 
515 int main(int argc, char **argv)
516 {
517  ::testing::InitGoogleTest(&argc, argv);
518  return RUN_ALL_TESTS();
519 }
const std::string & getMessage() const
Return the error message.
ValueStruct::iterator iterator
Definition: XmlRpcValue.h:44
RPC method arguments and results are represented by Values.
Definition: XmlRpcValue.h:24
void testArray(XmlRpcValue const &d)
int size() const
Return the size for string, base64, array, and struct values.
XmlRpcServer s
Definition: HelloServer.cpp:11
bool valid() const
Return true if the value has been set to something.
Definition: XmlRpcValue.h:108
int getCode() const
Return the error code.
TEST(xmlrpcvalue_base64, empty_string)
Type const & getType() const
Return the type of the value stored.
Definition: XmlRpcValue.h:111
void clear()
Erase the current value.
Definition: XmlRpcValue.h:79
std::string toXml() const
Encode the Value in xml.
void setSize(int size)
Specify the size for array values. Array values will grow beyond this size if needed.
Definition: XmlRpcValue.h:117
void testBoolean()
bool hasMember(const std::string &name) const
Check for the existence of a struct member by name.
void testDateTime()
std::vector< char > BinaryData
Definition: XmlRpcValue.h:41
int main(int argc, char **argv)
Definition: decode.h:13
XmlRpcValue fromXml(std::string const &data)


xmlrpcpp
Author(s): Chris Morley, Konstantin Pilipchuk, Morgan Quigley, Austin Hendrix
autogenerated on Sun Feb 3 2019 03:29:51