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 #include <climits>
30 
31 #include "xmlrpcpp/XmlRpcValue.h"
33 #include "xmlrpcpp/XmlRpcUtil.h"
34 
35 #include <gtest/gtest.h>
36 
37 using namespace XmlRpc;
38 
39 TEST(XmlRpc, Bool) {
40  XmlRpcValue v(bool(false));
41 
42  EXPECT_EQ("<value><boolean>0</boolean></value>", v.toXml());
43 
44  XmlRpcValue v2;
45  v2[0] = int(1);
46  v2[1] = std::string();
47  v2[2] = XmlRpcValue(false);
48  EXPECT_EQ("<value><array><data><value><i4>1</i4></value><value></"
49  "value><value><boolean>0</boolean></value></data></array></value>",
50  v2.toXml());
51 }
52 
54  const XmlRpcValue booleanFalse(false);
55  XmlRpcValue booleanTrue(true);
56  int offset = 0;
57  XmlRpcValue booleanFalseXml("<value><boolean>0</boolean></value>", &offset);
58  offset = 0;
59  XmlRpcValue booleanTrueXml("<value><boolean>1</boolean></value>", &offset);
60  EXPECT_NE(booleanFalse, booleanTrue);
61  EXPECT_EQ(booleanFalse, booleanFalseXml);
62  EXPECT_NE(booleanFalse, booleanTrueXml);
63 
64  EXPECT_FALSE(bool(booleanFalse));
65 
66  EXPECT_TRUE(bool(booleanTrue));
67 
68  // Test stream operator.
69  std::stringstream ss;
70  ss << booleanFalse;
71  EXPECT_EQ("0", ss.str());
72 
73  std::stringstream ss2;
74  ss2 << booleanTrue;
75  EXPECT_EQ("1", ss2.str());
76 
77  // Test that printing the value with GTest printer works
78  EXPECT_EQ(booleanFalse.toXml(), ::testing::PrintToString(booleanFalse));
79 }
80 
81 // Int
83  const XmlRpcValue int0(0);
84  ASSERT_EQ(XmlRpcValue::TypeInt, int0.getType());
85 
86  XmlRpcValue int1(1);
87  ASSERT_EQ(XmlRpcValue::TypeInt, int1.getType());
88 
89  XmlRpcValue int10(10);
90  ASSERT_EQ(XmlRpcValue::TypeInt, int10.getType());
91 
92  XmlRpcValue int_1(-1);
93  ASSERT_EQ(XmlRpcValue::TypeInt, int_1.getType());
94 
95  int offset = 0;
96  XmlRpcValue int0Xml("<value><int>0</int></value>", &offset);
97  ASSERT_EQ(XmlRpcValue::TypeInt, int0Xml.getType());
98  EXPECT_EQ(0, int(int0Xml));
99 
100  offset = 0;
101  XmlRpcValue int9Xml("<value><i4>9</i4></value>", &offset);
102  ASSERT_EQ(XmlRpcValue::TypeInt, int9Xml.getType());
103  EXPECT_EQ(9, int(int9Xml));
104 
105  EXPECT_EQ(int0, int0Xml);
106  EXPECT_EQ(int(int10) - int(int1), int(int9Xml));
107  EXPECT_EQ(9, int(int9Xml));
108  EXPECT_EQ(int(int10) + int(int_1), int(int9Xml));
109 
110  // Test stream operator.
111  std::stringstream ss;
112  ss << int9Xml;
113  EXPECT_EQ("9", ss.str());
114 
115  // Test that printing the value with GTest printer works
116  EXPECT_EQ(int0.toXml(), ::testing::PrintToString(int0));
117 }
118 
120  // Double
121  const XmlRpcValue d(43.7);
122  ASSERT_EQ(XmlRpcValue::TypeDouble, d.getType());
123  EXPECT_EQ("<value><double>43.700000000000003</double></value>", d.toXml());
124  EXPECT_DOUBLE_EQ(43.7, double(d));
125 
126  int offset = 0;
127  XmlRpcValue dXml("<value><double>56.3</double></value>", &offset);
128  ASSERT_EQ(XmlRpcValue::TypeDouble, dXml.getType());
129  EXPECT_DOUBLE_EQ(56.3, double(dXml));
130 
131  EXPECT_DOUBLE_EQ(100.0, double(d) + double(dXml));
132 
133  // Test stream operator.
134  std::stringstream ss;
135  ss << d;
136  EXPECT_EQ("43.7", ss.str());
137  ss.str("");
138 
139  // Test format
140  const XmlRpc::XmlRpcValue a(2.0);
141  ASSERT_EQ(XmlRpcValue::TypeDouble, d.getType());
142  const std::string save_format = XmlRpc::XmlRpcValue::getDoubleFormat();
143 
145  ss << a;
146  EXPECT_EQ(" 2.0000000000", ss.str());
147  ss.str("");
148 
150  ss << a;
151  EXPECT_EQ("2.00000000000000000000000000000000", ss.str());
152  ss.str("");
153 
155  ss << a;
156  EXPECT_EQ(" "
157  " "
158  " "
159  " 2.000000000", ss.str());
160  ss.str("");
161 
163  ss << a;
164  EXPECT_EQ("2.000000000000000000000000000000"
165  "00000000000000000000000000000000"
166  "00000000000000000000000000000000"
167  "000000000000000000000000000000000", ss.str());
168  ss.str("");
169 
170  XmlRpc::XmlRpcValue::setDoubleFormat(save_format.c_str());
171 
172  // Test that printing the value with GTest printer works
173  EXPECT_EQ(d.toXml(), ::testing::PrintToString(d));
174 }
175 
177  // String
178  const XmlRpcValue s("Now is the time <&");
179  ASSERT_EQ(XmlRpcValue::TypeString, s.getType());
180  EXPECT_EQ(18, s.size());
181  EXPECT_EQ("<value>Now is the time &lt;&amp;</value>", s.toXml());
182 
183  char csxml[] = "<value><string>Now is the time &lt;&amp;</string></value>";
184  std::string ssxml = csxml;
185 
186  int offset = 0;
187  XmlRpcValue vscXml(csxml, &offset);
188  EXPECT_EQ(s, vscXml);
189 
190  offset = 0;
191  XmlRpcValue vssXml(ssxml, &offset);
192  EXPECT_EQ(s, vssXml);
193 
194  offset = 0;
195  XmlRpcValue fromXml(vssXml.toXml(), &offset);
196  EXPECT_EQ(s, fromXml);
197 
198  // Empty or blank strings with no <string> tags
199  std::string emptyStringXml("<value></value>");
200  offset = 0;
201  XmlRpcValue emptyStringVal1(emptyStringXml, &offset);
202  XmlRpcValue emptyStringVal2("");
203  EXPECT_EQ(emptyStringVal1, emptyStringVal2);
204 
205  emptyStringXml = "<value> </value>";
206  offset = 0;
207  XmlRpcValue blankStringVal(emptyStringXml, &offset);
208  EXPECT_EQ(std::string(blankStringVal), " ");
209 
210  // Implicitly initialized string.
211  XmlRpcValue s2;
212  std::string tmp = s2;
213  EXPECT_EQ("", tmp);
214  EXPECT_EQ("", (std::string)s2);
215 
216  // Test stream operator.
217  std::stringstream ss;
218  ss << s;
219  EXPECT_EQ("Now is the time <&", ss.str());
220 
221  // Test that printing the value with GTest printer works
222  EXPECT_EQ(s.toXml(), ::testing::PrintToString(s));
223 }
224 
225 //Test decoding of a well-formed but overly large XML input
226 TEST(XmlRpc, testOversizeString) {
227  try {
228  std::string xml = "<tag><nexttag>";
229  xml += std::string(INT_MAX, 'a');
230  xml += "a</nexttag></tag>";
231  int offset;
232 
233  offset = 0;
234  EXPECT_EQ(XmlRpcUtil::parseTag("<tag>", xml, &offset), std::string());
235  EXPECT_EQ(offset, 0);
236 
237  offset = 0;
238  EXPECT_FALSE(XmlRpcUtil::findTag("<tag>", xml, &offset));
239  EXPECT_EQ(offset, 0);
240 
241  offset = 0;
242  EXPECT_FALSE(XmlRpcUtil::nextTagIs("<tag>", xml, &offset));
243  EXPECT_EQ(offset, 0);
244 
245  offset = 0;
246  EXPECT_EQ(XmlRpcUtil::getNextTag(xml, &offset), std::string());
247  EXPECT_EQ(offset, 0);
248  }
249  catch (std::bad_alloc& err) {
250 #ifdef GTEST_SKIP
251  GTEST_SKIP() << "Unable to allocate memory to run test\n";
252 #else
253  std::cerr << "[ SKIPPED ] XmlRpc.testOversizeString Unable to allocate memory to run test\n";
254 #endif
255  }
256 }
257 
258 TEST(XmlRpc, testParseTag) {
259  int offset = 0;
260 
261  // Test a null tag
262  EXPECT_EQ(XmlRpcUtil::parseTag(NULL, "", &offset), std::string());
263  EXPECT_EQ(offset, 0);
264 
265  // Test a null offset
266  EXPECT_EQ(XmlRpcUtil::parseTag("<tag>", "", NULL), std::string());
267  EXPECT_EQ(offset, 0);
268 
269  // Test if the offset is beyond the end of the input xml
270  offset = 20;
271  EXPECT_EQ(XmlRpcUtil::parseTag("<tag>", "", &offset), std::string());
272  EXPECT_EQ(offset, 20);
273 
274  // Test if the tag is not found in the input xml
275  offset = 0;
276  EXPECT_EQ(XmlRpcUtil::parseTag("<tag>", "<foo></foo>", &offset), std::string());
277  EXPECT_EQ(offset, 0);
278 
279  // Test if the tag is found, but the end tag is not
280  EXPECT_EQ(XmlRpcUtil::parseTag("<tag>", "<tag>", &offset), std::string());
281  EXPECT_EQ(offset, 0);
282 
283  // Test if the tag is found, the end tag is found, and there is a value in the middle
284  EXPECT_EQ(XmlRpcUtil::parseTag("<tag>", "<tag>foo</tag>", &offset), "foo");
285  EXPECT_EQ(offset, 14);
286 }
287 
288 TEST(XmlRpc, testFindTag) {
289  int offset = 0;
290 
291  // Test a null tag
292  EXPECT_FALSE(XmlRpcUtil::findTag(NULL, "", &offset));
293  EXPECT_EQ(offset, 0);
294 
295  // Test a null offset
296  EXPECT_FALSE(XmlRpcUtil::findTag("<tag>", "", NULL));
297  EXPECT_EQ(offset, 0);
298 
299  // Test if the offset is beyond the end of the input xml
300  offset = 20;
301  EXPECT_FALSE(XmlRpcUtil::findTag("<tag>", "", &offset));
302  EXPECT_EQ(offset, 20);
303 
304  // Test that the offset moves when finding a tag
305  offset = 0;
306  EXPECT_TRUE(XmlRpcUtil::findTag("<subtag>", "<tag><subtag></subtag></tag>", &offset));
307  EXPECT_EQ(offset, 13);
308 }
309 
310 TEST(XmlRpc, testNextTagIs) {
311  int offset = 0;
312 
313  // Test a null tag
314  EXPECT_FALSE(XmlRpcUtil::nextTagIs(NULL, "", &offset));
315  EXPECT_EQ(offset, 0);
316 
317  // Test a null offset
318  EXPECT_FALSE(XmlRpcUtil::nextTagIs("<tag>", "", NULL));
319  EXPECT_EQ(offset, 0);
320 
321  // Test if the offset is beyond the end of the input xml
322  offset = 20;
323  EXPECT_FALSE(XmlRpcUtil::nextTagIs("<tag>", "", &offset));
324  EXPECT_EQ(offset, 20);
325 
326  // Test that the offset moves when finding a tag with no whitespace
327  offset = 0;
328  EXPECT_TRUE(XmlRpcUtil::nextTagIs("<tag>", "<tag></tag>", &offset));
329  EXPECT_EQ(offset, 5);
330 
331  // Test that the offset moves when finding a tag with whitespace
332  offset = 0;
333  EXPECT_TRUE(XmlRpcUtil::nextTagIs("<tag>", " <tag></tag>", &offset));
334  EXPECT_EQ(offset, 11);
335 
336  // Test that the offset doesn't move when the tag is not found
337  offset = 0;
338  EXPECT_FALSE(XmlRpcUtil::nextTagIs("<tag>", " <footag></footag>", &offset));
339  EXPECT_EQ(offset, 0);
340 }
341 
342 TEST(XmlRpc, testGetNextTag) {
343  int offset = 0;
344 
345  // Test a null offset
346  EXPECT_EQ(XmlRpcUtil::getNextTag("", NULL), std::string());
347  EXPECT_EQ(offset, 0);
348 
349  // Test if the offset is beyond the end of the input xml
350  offset = 20;
351  EXPECT_EQ(XmlRpcUtil::getNextTag("<tag>", &offset), std::string());
352  EXPECT_EQ(offset, 20);
353 
354  // Test that the offset moves when finding a tag with no whitespace
355  offset = 0;
356  EXPECT_EQ(XmlRpcUtil::getNextTag("<tag></tag>", &offset), "<tag>");
357  EXPECT_EQ(offset, 5);
358 
359  // Test that the offset moves when finding a tag with whitespace
360  offset = 0;
361  EXPECT_EQ(XmlRpcUtil::getNextTag(" <tag></tag>", &offset), "<tag>");
362  EXPECT_EQ(offset, 11);
363 
364  // Test that the offset doesn't move if there are no tags
365  offset = 0;
366  EXPECT_EQ(XmlRpcUtil::getNextTag(" foo", &offset), std::string());
367  EXPECT_EQ(offset, 0);
368 
369  // Test that the offset moves if there is a start < but no end >
370  offset = 0;
371  // FIXME: this should fail, but currently does not
372  EXPECT_EQ(XmlRpcUtil::getNextTag("<foo", &offset), "<foo");
373  EXPECT_EQ(offset, 4);
374 
375  // Test what happens if there is no data in the tag
376  offset = 0;
377  EXPECT_EQ(XmlRpcUtil::getNextTag("<>", &offset), "<>");
378  EXPECT_EQ(offset, 2);
379 }
380 
381 TEST(XmlRpc, testNextTagData)
382 {
383  int offset = 0;
384 
385  // Test a null tag
386  EXPECT_EQ(XmlRpcUtil::nextTagData(NULL, "", &offset), std::string());
387  EXPECT_EQ(offset, 0);
388 
389  // Test a null offset
390  EXPECT_EQ(XmlRpcUtil::nextTagData("<tag>", "", NULL), std::string());
391  EXPECT_EQ(offset, 0);
392 
393  // Test if the offset is beyond the end of the input xml
394  offset = 20;
395  EXPECT_EQ(XmlRpcUtil::nextTagData("<tag>", "", &offset), std::string());
396  EXPECT_EQ(offset, 20);
397 
398  // Test that the offset moves when finding a tag with no whitespace
399  offset = 0;
400  EXPECT_EQ(XmlRpcUtil::nextTagData("<tag>", "<tag></tag>", &offset), "");
401  EXPECT_EQ(offset, 11);
402 
403  // Test that the offset moves when finding a tag with whitespace
404  offset = 0;
405  EXPECT_EQ(XmlRpcUtil::nextTagData("<tag>", " <tag></tag>", &offset), "");
406  EXPECT_EQ(offset, 14);
407 
408  // Test that the offset moves when finding a tag with whitespace
409  offset = 0;
410  EXPECT_EQ(XmlRpcUtil::nextTagData("<tag>", " <tag>foo</tag>", &offset), "foo");
411  EXPECT_EQ(offset, 17);
412 
413  // Test that the offset doesn't move when missing the tag
414  offset = 0;
415  EXPECT_EQ(XmlRpcUtil::nextTagData("<tag>", " <foo></foo>", &offset), "");
416  EXPECT_EQ(offset, 0);
417 
418  // Test that the offset doesn't move when the close tag is after other tags
419  offset = 0;
420  EXPECT_EQ(XmlRpcUtil::nextTagData("<tag>", " <tag><foo></tag>", &offset), "");
421  EXPECT_EQ(offset, 0);
422 
423  // Test that the offset doesn't move if there is no closing tag
424  offset = 0;
425  EXPECT_EQ(XmlRpcUtil::nextTagData("<tag>", " <tag>foo", &offset), "");
426  EXPECT_EQ(offset, 0);
427 }
428 
430  // DateTime
431  int offset = 0;
432  // Construct from XML
433  const XmlRpcValue dateTime(
434  "<value><dateTime.iso8601>19040503T03:12:35</dateTime.iso8601></value>",
435  &offset);
436  ASSERT_EQ(XmlRpcValue::TypeDateTime, dateTime.getType());
437  struct tm t = dateTime;
438  EXPECT_EQ(t.tm_year, 1904);
439  EXPECT_EQ(t.tm_min, 12);
440  EXPECT_EQ(t.tm_sec, 35);
441  EXPECT_EQ(t.tm_hour, 3);
442  EXPECT_EQ(t.tm_mday, 3);
443  EXPECT_EQ(t.tm_mon, 5);
444 
445  EXPECT_EQ(
446  "<value><dateTime.iso8601>19040503T03:12:35</dateTime.iso8601></value>",
447  dateTime.toXml());
448 
449  // Constructor from struct tm.
450  XmlRpcValue dateTime2(&t);
451  ASSERT_EQ(XmlRpcValue::TypeDateTime, dateTime2.getType());
452  t = dateTime2;
453  EXPECT_EQ(t.tm_year, 1904);
454  EXPECT_EQ(t.tm_min, 12);
455 
456  // Implicit initialization by cast.
457  XmlRpcValue dateTime3;
458  t = dateTime3;
459  ASSERT_EQ(XmlRpcValue::TypeDateTime, dateTime3.getType());
460  EXPECT_EQ(t.tm_year, 0);
461  EXPECT_EQ(t.tm_min, 0);
462 
463  // Test stream operator.
464  std::stringstream ss;
465  ss << dateTime;
466  EXPECT_EQ("19040503T03:12:35", ss.str());
467 
468  // Tests for DateTime equality operator
469  EXPECT_EQ(dateTime, dateTime2);
470 
471  // Copy operator
472  dateTime3 = dateTime;
473  EXPECT_EQ(dateTime, dateTime3);
474 
475  // Explicit mutable reference into dateTime2 so that we can modify it to make
476  // it not equal to dateTime in various ways.
477  t = dateTime;
478  struct tm& tm2 = dateTime2;
479  // Seconds not equal.
480  tm2.tm_sec = 0;
481  EXPECT_NE(dateTime, dateTime2);
482  tm2 = t;
483  ASSERT_EQ(dateTime, dateTime2);
484 
485  // Minutes not equal.
486  tm2.tm_min = 0;
487  EXPECT_NE(dateTime, dateTime2);
488  tm2 = t;
489  ASSERT_EQ(dateTime, dateTime2);
490 
491  // Hours not equal.
492  tm2.tm_hour = 0;
493  EXPECT_NE(dateTime, dateTime2);
494  tm2 = t;
495  ASSERT_EQ(dateTime, dateTime2);
496 
497  // Day not equal.
498  tm2.tm_mday = 1;
499  EXPECT_NE(dateTime, dateTime2);
500  tm2 = t;
501  ASSERT_EQ(dateTime, dateTime2);
502 
503  // Month not equal.
504  tm2.tm_mon = 1;
505  EXPECT_NE(dateTime, dateTime2);
506  tm2 = t;
507  ASSERT_EQ(dateTime, dateTime2);
508 
509  // Year not equal.
510  tm2.tm_year = 1988;
511  EXPECT_NE(dateTime, dateTime2);
512 }
513 
515  XmlRpcValue d(43.7);
516  // Array
517  XmlRpcValue a;
518  a.setSize(4);
519  a[0] = 1;
520  a[1] = std::string("two");
521  a[2] = 43.7;
522  a[3] = "four";
523  EXPECT_EQ(XmlRpcValue::TypeArray, a.getType());
524  EXPECT_EQ(int(a[0]), 1);
525  EXPECT_EQ(a[2], d);
526 
527  char csaXml[] = "<value><array>\n"
528  " <data>\n"
529  " <value><i4>1</i4></value> \n"
530  " <value> <string>two</string></value>\n"
531  " <value><double>43.7</double></value>\n"
532  " <value>four</value>\n"
533  " </data>\n"
534  "</array></value>";
535 
536  int offset = 0;
537  XmlRpcValue aXml(csaXml, &offset);
538  EXPECT_EQ(a, aXml);
539 
540  // Array copy works
541  const XmlRpcValue copy(a);
542  ASSERT_EQ(a.getType(), copy.getType());
543  ASSERT_EQ(a.size(), copy.size());
544  for (int i = 0; i < 3; i++) {
545  EXPECT_EQ(a[i], copy[i]);
546  }
547  // Test that comparison operator works.
548  EXPECT_EQ(a, copy);
549 
550  // Test that comparison for unlike types returns false.
551  EXPECT_NE(a, d);
552 
553  // Test stream operator.
554  std::stringstream ss;
555  ss << a;
556  EXPECT_EQ("{1,two,43.7,four}", ss.str());
557 
558  // Test that printing the value with GTest printer works
559  EXPECT_EQ(a.toXml(), ::testing::PrintToString(a));
560 }
561 
563  // Struct
564  XmlRpcValue struct1;
565  struct1["i4"] = 1;
566  struct1["str"] = "two";
567  struct1["d"] = 43.7;
568  EXPECT_EQ(3, struct1.size());
569  EXPECT_EQ(XmlRpcValue::TypeStruct, struct1.getType());
570  EXPECT_TRUE(struct1.hasMember("i4"));
571  EXPECT_FALSE(struct1.hasMember("nowhere"));
572 
573  // Test stream operator.
574  std::stringstream ss;
575  ss << struct1;
576  EXPECT_EQ("[d:43.7,i4:1,str:two]", ss.str());
577 
578  XmlRpcValue a;
579  a.setSize(4);
580  a[0] = 1;
581  a[1] = std::string("two");
582  a[2] = 43.7;
583  a[3] = "four";
584 
585  EXPECT_EQ(struct1["d"], a[2]);
586 
587  char csStructXml[] = "<value><struct>\n"
588  " <member>\n"
589  " <name>i4</name> \n"
590  " <value><i4>1</i4></value> \n"
591  " </member>\n"
592  " <member>\n"
593  " <name>d</name> \n"
594  " <value><double>43.7</double></value>\n"
595  " </member>\n"
596  " <member>\n"
597  " <name>str</name> \n"
598  " <value> <string>two</string></value>\n"
599  " </member>\n"
600  "</struct></value>";
601 
602  int offset = 0;
603  const XmlRpcValue structXml(csStructXml, &offset);
604  EXPECT_EQ(struct1, structXml);
605 
606  for (XmlRpcValue::iterator itr = struct1.begin(); itr != struct1.end();
607  itr++) {
608  }
609 
610  XmlRpcValue astruct;
611  astruct["array"] = a;
612  EXPECT_EQ(astruct["array"][2], struct1["d"]);
613 
614  for (int i = 0; i < 10; i++) {
615  XmlRpcValue Event;
616  Event["Name"] = "string";
617 
618  Event.clear();
619 
620  const int NELMTS = 100;
621  int ii;
622 
623  for (ii = 0; ii < NELMTS; ++ii) {
624  char buf[40];
625  sprintf(buf, "%d", ii);
626  Event[std::string(buf)] = buf;
627  }
628 
629  Event.clear();
630 
631  for (ii = 0; ii < NELMTS; ++ii) {
632  char buf[40];
633  sprintf(buf, "%d", ii);
634  if (ii != NELMTS / 2)
635  Event[std::string(buf)] = ii;
636  else
637  for (int jj = 0; jj < NELMTS; ++jj) {
638  char bufj[40];
639  sprintf(bufj, "%d", jj);
640  Event[std::string(buf)][std::string(bufj)] = bufj;
641  }
642  }
643 
644  for (ii = 0; ii < NELMTS; ++ii) {
645  char buf[40];
646  sprintf(buf, "%d", ii);
647  if (ii != NELMTS / 2)
648  EXPECT_EQ(Event[std::string(buf)], XmlRpcValue(ii));
649  else
650  EXPECT_EQ(Event[std::string(buf)].size(), NELMTS);
651  }
652  }
653  // Test that printing the value with GTest printer works
654  EXPECT_EQ(struct1.toXml(), ::testing::PrintToString(struct1));
655 }
656 
658  char data[] = {1, 2};
659  const XmlRpcValue bin(data, 2);
660 
661  EXPECT_EQ(XmlRpcValue::TypeBase64, bin.getType());
662  EXPECT_EQ(2, bin.size());
663 
664  XmlRpcValue::BinaryData d = bin;
665  EXPECT_EQ(d[0], 1);
666  EXPECT_EQ(d[1], 2);
667 
668  EXPECT_EQ("<value><base64>AQI=\n</base64></value>", bin.toXml());
669 
670  // Test stream operator.
671  std::stringstream ss;
672  ss << bin;
673  EXPECT_EQ("AQI=\n", ss.str());
674 
675  // Constructor from XML
676  int offset = 0;
677  XmlRpcValue bin2("<value><base64>AQI=</base64></value>", &offset);
678  EXPECT_EQ(XmlRpcValue::TypeBase64, bin2.getType());
679  EXPECT_EQ(2, bin2.size());
680 
681  d = bin2;
682  EXPECT_EQ(d[0], 1);
683  EXPECT_EQ(d[1], 2);
684 
685  EXPECT_EQ(bin, bin2);
686 
687  // Implicit initialization.
688  XmlRpcValue bin3;
689  d = bin3;
690  EXPECT_EQ(XmlRpcValue::TypeBase64, bin3.getType());
691  EXPECT_EQ(0, bin3.size());
692  EXPECT_EQ(0u, d.size());
693 
694  // Copy operator
695  XmlRpcValue bin4;
696  bin4 = bin;
697 
698  EXPECT_EQ(XmlRpcValue::TypeBase64, bin4.getType());
699  EXPECT_EQ(2, bin4.size());
700 
701  d = bin4;
702  EXPECT_EQ(d[0], 1);
703  EXPECT_EQ(d[1], 2);
704 
705  // Test that printing the value with GTest printer works
706  EXPECT_EQ(bin.toXml(), ::testing::PrintToString(bin));
707 }
708 
709 TEST(XmpRpc, errors) {
710  // Value is initially invalid.
711  XmlRpcValue value;
712  EXPECT_FALSE(value.valid());
713  EXPECT_EQ("", value.toXml());
714 
715  // Implicit bool initialization.
716  bool v = (bool)value;
717  EXPECT_FALSE(v);
718 
719  // Conversions to other types should now throw an XmlRpcException.
720  EXPECT_THROW((void)(int)value, XmlRpcException);
721  EXPECT_THROW(value[0], XmlRpcException);
722  EXPECT_THROW(value["bar"], XmlRpcException);
723 
724  // Tests on const objects.
725  const XmlRpcValue& ref = value;
726  EXPECT_THROW(ref[0], XmlRpcException);
727  // TODO(austin): is this really allowed on non-struct objects?
728  EXPECT_FALSE(ref.hasMember("bar"));
729 
730  // Check that the exception that is thrown is populated correctly.
731  try {
732  (void)int(value);
733  } catch (XmlRpcException& e) {
734  EXPECT_EQ("type error", e.getMessage());
735  EXPECT_EQ(-1, e.getCode());
736  }
737 
738  // size() on bool should throw.
739  EXPECT_THROW(value.size(), XmlRpcException);
740 
741  // Clear should result in invalid again.
742  value.clear();
743  EXPECT_FALSE(value.valid());
744 }
745 
746 TEST(XmlRpc, int_errors) {
747  XmlRpcValue value;
748  // Implicit int initialization.
749  int v = (int)value;
750  EXPECT_EQ(0, v);
751  EXPECT_EQ(0, (int)value);
752 
753  // Conversion to other types should now thrown an exception.
754  EXPECT_THROW((void)(bool)value, XmlRpcException);
755 }
756 
757 TEST(XmlRpc, array_errors) {
758  XmlRpcValue value;
759  // Implicit array creation.
760  int v = value[0];
761  EXPECT_EQ(0, v);
762  EXPECT_THROW((void)(bool)value, XmlRpcException);
763  EXPECT_EQ(1, value.size());
764 
765  // Access on a non-const array should implicitly create another element.
766  EXPECT_EQ(0, (int)value[1]);
767  EXPECT_EQ(2, value.size());
768 
769  // Access to a const array should throw an exception if the index is out of
770  // bounds.
771  const XmlRpcValue& ref = value;
772  EXPECT_THROW(ref[2], XmlRpcException);
773 }
774 
775 TEST(XmlRpc, fromXmlInvalid) {
776  int offset = 0;
777  XmlRpcValue val;
778 
779  // Test what happens with a null offset
780  val.fromXml("", NULL);
781  EXPECT_EQ(val.getType(), XmlRpcValue::Type::TypeInvalid);
782 
783  // Test what happens with an offset far beyond the xml
784  offset = 20;
785  val.fromXml("", &offset);
786  EXPECT_EQ(val.getType(), XmlRpcValue::Type::TypeInvalid);
787  EXPECT_EQ(offset, 20);
788 
789  // Test what happens with no <value> tag
790  offset = 0;
791  val.fromXml("<foo>", &offset);
792  EXPECT_EQ(val.getType(), XmlRpcValue::Type::TypeInvalid);
793  EXPECT_EQ(offset, 0);
794 
795  // Test what happens with <value> tag but nothing else
796  offset = 0;
797  val.fromXml("<value>", &offset);
798  EXPECT_EQ(val.getType(), XmlRpcValue::Type::TypeInvalid);
799  EXPECT_EQ(offset, 0);
800 
801  // A <value><invalid></invalid></value> is invalid
802  offset = 0;
803  val.fromXml("<value><invalid></invalid></value>", &offset);
804  EXPECT_EQ(val.getType(), XmlRpcValue::Type::TypeInvalid);
805  EXPECT_EQ(offset, 0);
806 
807  // A <value></value> combination is an implicit empty string
808  offset = 0;
809  val.fromXml("<value></value>", &offset);
810  EXPECT_EQ(val.getType(), XmlRpcValue::Type::TypeString);
811  EXPECT_EQ(offset, 15);
812  EXPECT_EQ(static_cast<std::string>(val), "");
813 }
814 
815 TEST(XmlRpc, fromXmlBoolean) {
816  int offset = 0;
817  XmlRpcValue val;
818 
819  // A <value><boolean></boolean></value> is invalid
820  offset = 0;
821  val.fromXml("<value><boolean></boolean></value>", &offset);
822  EXPECT_EQ(val.getType(), XmlRpcValue::Type::TypeInvalid);
823  EXPECT_EQ(offset, 0);
824 
825  // A <value><boolean></value> is invalid
826  offset = 0;
827  val.fromXml("<value><boolean></value>", &offset);
828  EXPECT_EQ(val.getType(), XmlRpcValue::Type::TypeInvalid);
829  EXPECT_EQ(offset, 0);
830 
831  // A <value><boolean>foo</boolean></value> is invalid
832  offset = 0;
833  val.fromXml("<value><boolean>foo</boolean></value>", &offset);
834  EXPECT_EQ(val.getType(), XmlRpcValue::Type::TypeInvalid);
835  EXPECT_EQ(offset, 0);
836 
837  // A <value><boolean>25</boolean></value> is invalid
838  offset = 0;
839  val.fromXml("<value><boolean>25</boolean></value>", &offset);
840  EXPECT_EQ(val.getType(), XmlRpcValue::Type::TypeInvalid);
841  EXPECT_EQ(offset, 0);
842 
843  // A <value><boolean>1foo</boolean></value> is valid
844  offset = 0;
845  // FIXME: this should fail, but currently does not
846  val.fromXml("<value><boolean>1foo</boolean></value>", &offset);
847  EXPECT_EQ(val.getType(), XmlRpcValue::Type::TypeBoolean);
848  EXPECT_EQ(offset, 38);
849  EXPECT_EQ(static_cast<bool>(val), true);
850 
851  // A <value><boolean>1</value> is valid
852  offset = 0;
853  // FIXME: this should fail, but currently does not
854  val.fromXml("<value><boolean>1</value>", &offset);
855  EXPECT_EQ(val.getType(), XmlRpcValue::Type::TypeBoolean);
856  EXPECT_EQ(offset, 25);
857  EXPECT_EQ(static_cast<bool>(val), true);
858 
859  // A <value><boolean>0</boolean></value> is valid
860  offset = 0;
861  val.fromXml("<value><boolean>0</boolean></value>", &offset);
862  EXPECT_EQ(val.getType(), XmlRpcValue::Type::TypeBoolean);
863  EXPECT_EQ(offset, 35);
864  EXPECT_EQ(static_cast<bool>(val), false);
865 
866  // A <value><boolean>1</boolean></value> is valid
867  offset = 0;
868  val.fromXml("<value><boolean>1</boolean></value>", &offset);
869  EXPECT_EQ(val.getType(), XmlRpcValue::Type::TypeBoolean);
870  EXPECT_EQ(offset, 35);
871  EXPECT_EQ(static_cast<bool>(val), true);
872 }
873 
874 TEST(XmlRpc, fromXmlI4) {
875  int offset = 0;
876  XmlRpcValue val;
877 
878  // A <value><i4></i4></value> is invalid
879  offset = 0;
880  val.fromXml("<value><i4></i4></value>", &offset);
881  EXPECT_EQ(val.getType(), XmlRpcValue::Type::TypeInvalid);
882  EXPECT_EQ(offset, 0);
883 
884  // A <value><i4></value> is invalid
885  offset = 0;
886  val.fromXml("<value><i4></value>", &offset);
887  EXPECT_EQ(val.getType(), XmlRpcValue::Type::TypeInvalid);
888  EXPECT_EQ(offset, 0);
889 
890  // A <value><i4>foo</i4></value> is invalid
891  offset = 0;
892  val.fromXml("<value><i4>foo</i4></value>", &offset);
893  EXPECT_EQ(val.getType(), XmlRpcValue::Type::TypeInvalid);
894  EXPECT_EQ(offset, 0);
895 
896  // A <value><i4>25</i4></value> is valid
897  offset = 0;
898  val.fromXml("<value><i4>25</i4></value>", &offset);
899  EXPECT_EQ(val.getType(), XmlRpcValue::Type::TypeInt);
900  EXPECT_EQ(offset, 26);
901  EXPECT_EQ(static_cast<int>(val), 25);
902 
903  // A <value><i4>1foo</i4></value> is valid
904  offset = 0;
905  // FIXME: this should fail, but currently does not
906  val.fromXml("<value><i4>1foo</i4></value>", &offset);
907  EXPECT_EQ(val.getType(), XmlRpcValue::Type::TypeInt);
908  EXPECT_EQ(offset, 28);
909  EXPECT_EQ(static_cast<int>(val), 1);
910 
911  // A <value><i4>1</value> is valid
912  offset = 0;
913  // FIXME: this should fail, but currently does not
914  val.fromXml("<value><i4>99</value>", &offset);
915  EXPECT_EQ(val.getType(), XmlRpcValue::Type::TypeInt);
916  EXPECT_EQ(offset, 21);
917  EXPECT_EQ(static_cast<int>(val), 99);
918 }
919 
920 TEST(XmlRpc, fromXmlInt) {
921  int offset = 0;
922  XmlRpcValue val;
923 
924  // A <value><int></int></value> is invalid
925  offset = 0;
926  val.fromXml("<value><int></int></value>", &offset);
927  EXPECT_EQ(val.getType(), XmlRpcValue::Type::TypeInvalid);
928  EXPECT_EQ(offset, 0);
929 
930  // A <value><int></value> is invalid
931  offset = 0;
932  val.fromXml("<value><int></value>", &offset);
933  EXPECT_EQ(val.getType(), XmlRpcValue::Type::TypeInvalid);
934  EXPECT_EQ(offset, 0);
935 
936  // A <value><int>foo</int></value> is invalid
937  offset = 0;
938  val.fromXml("<value><int>foo</int></value>", &offset);
939  EXPECT_EQ(val.getType(), XmlRpcValue::Type::TypeInvalid);
940  EXPECT_EQ(offset, 0);
941 
942  // A <value><int>25</int></value> is valid
943  offset = 0;
944  val.fromXml("<value><int>25</int></value>", &offset);
945  EXPECT_EQ(val.getType(), XmlRpcValue::Type::TypeInt);
946  EXPECT_EQ(offset, 28);
947  EXPECT_EQ(static_cast<int>(val), 25);
948 
949  // A <value><int>1foo</int></value> is valid
950  offset = 0;
951  // FIXME: this should fail, but currently does not
952  val.fromXml("<value><int>1foo</int></value>", &offset);
953  EXPECT_EQ(val.getType(), XmlRpcValue::Type::TypeInt);
954  EXPECT_EQ(offset, 30);
955  EXPECT_EQ(static_cast<int>(val), 1);
956 
957  // A <value><int>1</value> is valid
958  offset = 0;
959  // FIXME: this should fail, but currently does not
960  val.fromXml("<value><int>99</value>", &offset);
961  EXPECT_EQ(val.getType(), XmlRpcValue::Type::TypeInt);
962  EXPECT_EQ(offset, 22);
963  EXPECT_EQ(static_cast<int>(val), 99);
964 }
965 
966 TEST(XmlRpc, fromXmlDouble) {
967  int offset = 0;
968  XmlRpcValue val;
969 
970  // A <value><double></double></value> is invalid
971  offset = 0;
972  val.fromXml("<value><double></double></value>", &offset);
973  EXPECT_EQ(val.getType(), XmlRpcValue::Type::TypeInvalid);
974  EXPECT_EQ(offset, 0);
975 
976  // A <value><double></value> is invalid
977  offset = 0;
978  val.fromXml("<value><double></value>", &offset);
979  EXPECT_EQ(val.getType(), XmlRpcValue::Type::TypeInvalid);
980  EXPECT_EQ(offset, 0);
981 
982  // A <value><double>foo</double></value> is invalid
983  offset = 0;
984  val.fromXml("<value><double>foo</double></value>", &offset);
985  EXPECT_EQ(val.getType(), XmlRpcValue::Type::TypeInvalid);
986  EXPECT_EQ(offset, 0);
987 
988  // A <value><double>25</double></value> is valid
989  offset = 0;
990  val.fromXml("<value><double>25</double></value>", &offset);
991  EXPECT_EQ(val.getType(), XmlRpcValue::Type::TypeDouble);
992  EXPECT_EQ(offset, 34);
993  EXPECT_EQ(static_cast<double>(val), 25.0);
994 
995  // A <value><double>25.876</double></value> is valid
996  offset = 0;
997  val.fromXml("<value><double>25.876</double></value>", &offset);
998  EXPECT_EQ(val.getType(), XmlRpcValue::Type::TypeDouble);
999  EXPECT_EQ(offset, 38);
1000  EXPECT_NEAR(static_cast<double>(val), 25.876, 0.01);
1001 
1002  // A <value><double>1foo</double></value> is valid
1003  offset = 0;
1004  // FIXME: this should fail, but currently does not
1005  val.fromXml("<value><double>1foo</double></value>", &offset);
1006  EXPECT_EQ(val.getType(), XmlRpcValue::Type::TypeDouble);
1007  EXPECT_EQ(offset, 36);
1008  EXPECT_EQ(static_cast<double>(val), 1);
1009 }
1010 
1011 TEST(XmlRpc, fromXmlImplicitString) {
1012  int offset = 0;
1013  XmlRpcValue val;
1014 
1015  // A <value><foo></foo></value> is invalid
1016  offset = 0;
1017  val.fromXml("<value><foo></foo></value>", &offset);
1018  EXPECT_EQ(val.getType(), XmlRpcValue::Type::TypeInvalid);
1019  EXPECT_EQ(offset, 0);
1020 
1021  // A <value>foo</value> is valid
1022  offset = 0;
1023  val.fromXml("<value>foo</value>", &offset);
1024  EXPECT_EQ(val.getType(), XmlRpcValue::Type::TypeString);
1025  EXPECT_EQ(offset, 18);
1026  EXPECT_EQ(static_cast<std::string>(val), "foo");
1027  EXPECT_EQ(val.size(), 3);
1028 }
1029 
1030 TEST(XmlRpc, fromXmlExplicitString) {
1031  int offset = 0;
1032  XmlRpcValue val;
1033 
1034  // A <value><string> is invalid
1035  offset = 0;
1036  val.fromXml("<value><string>", &offset);
1037  EXPECT_EQ(val.getType(), XmlRpcValue::Type::TypeInvalid);
1038  EXPECT_EQ(offset, 0);
1039 
1040  // A <value><string></value> is valid
1041  offset = 0;
1042  // FIXME: this should fail, but currently does not
1043  val.fromXml("<value><string></value>", &offset);
1044  EXPECT_EQ(val.getType(), XmlRpcValue::Type::TypeString);
1045  EXPECT_EQ(offset, 23);
1046  EXPECT_EQ(static_cast<std::string>(val), "");
1047  EXPECT_EQ(val.size(), 0);
1048 
1049  // A <value><string>foo</string></value> is valid
1050  offset = 0;
1051  val.fromXml("<value><string>foo</string></value>", &offset);
1052  EXPECT_EQ(val.getType(), XmlRpcValue::Type::TypeString);
1053  EXPECT_EQ(offset, 35);
1054  EXPECT_EQ(static_cast<std::string>(val), "foo");
1055  EXPECT_EQ(val.size(), 3);
1056 }
1057 
1058 TEST(XmlRpc, fromXmlDateTime) {
1059  int offset = 0;
1060  XmlRpcValue val;
1061  struct tm expected{};
1062  struct tm returned;
1063 
1064  // A <value><dateTime.iso8601></dateTime.iso8601></value> is invalid
1065  offset = 0;
1066  val.fromXml("<value><dateTime.iso8601></dateTime.iso8601></value>", &offset);
1067  EXPECT_EQ(val.getType(), XmlRpcValue::Type::TypeInvalid);
1068  EXPECT_EQ(offset, 0);
1069 
1070  // A <value><dateTime.iso8601> is invalid
1071  offset = 0;
1072  val.fromXml("<value><dateTime.iso8601>", &offset);
1073  EXPECT_EQ(val.getType(), XmlRpcValue::Type::TypeInvalid);
1074  EXPECT_EQ(offset, 0);
1075 
1076  // A <value><dateTime.iso8601></value> is invalid
1077  offset = 0;
1078  val.fromXml("<value><dateTime.iso8601></value>", &offset);
1079  EXPECT_EQ(val.getType(), XmlRpcValue::Type::TypeInvalid);
1080  EXPECT_EQ(offset, 0);
1081 
1082  // A <value><dateTime.iso8601>0000000T00:00<dateTime.iso8601></value> is invalid
1083  offset = 0;
1084  val.fromXml("<value><dateTime.iso8601>0000000T00:00<dateTime.iso8601></value>", &offset);
1085  EXPECT_EQ(val.getType(), XmlRpcValue::Type::TypeInvalid);
1086  EXPECT_EQ(offset, 0);
1087 
1088  // A <value><dateTime.iso8601>000000T00:00:00<dateTime.iso8601></value> is invalid
1089  offset = 0;
1090  val.fromXml("<value><dateTime.iso8601>000000T00:00:00<dateTime.iso8601></value>", &offset);
1091  EXPECT_EQ(val.getType(), XmlRpcValue::Type::TypeInvalid);
1092  EXPECT_EQ(offset, 0);
1093 
1094  // A <value><dateTime.iso8601>0000000T00:00:00</value> is valid
1095  offset = 0;
1096  // FIXME: this should fail, but currently does not
1097  // FIXME: this currently leaves the returned struct tm fields 'tm_wday' and 'tm_yday' uninitialized
1098  val.fromXml("<value><dateTime.iso8601>0000000T00:00:00</value>", &offset);
1099  EXPECT_EQ(val.getType(), XmlRpcValue::Type::TypeDateTime);
1100  EXPECT_EQ(offset, 49);
1101  returned = static_cast<struct tm>(val);
1102  EXPECT_EQ(returned.tm_sec, expected.tm_sec);
1103  EXPECT_EQ(returned.tm_min, expected.tm_min);
1104  EXPECT_EQ(returned.tm_hour, expected.tm_hour);
1105  EXPECT_EQ(returned.tm_mday, expected.tm_mday);
1106  EXPECT_EQ(returned.tm_mon, expected.tm_mon);
1107  EXPECT_EQ(returned.tm_year, expected.tm_year);
1108  EXPECT_EQ(returned.tm_isdst, -1);
1109 
1110  // A <value><dateTime.iso8601>0000000T00:00:0<dateTime.iso8601></value> is valid
1111  offset = 0;
1112  // FIXME: this should fail, but currently does not
1113  val.fromXml("<value><dateTime.iso8601>0000000T00:00:0<dateTime.iso8601></value>", &offset);
1114  EXPECT_EQ(val.getType(), XmlRpcValue::Type::TypeDateTime);
1115  EXPECT_EQ(offset, 66);
1116  returned = static_cast<struct tm>(val);
1117  EXPECT_EQ(returned.tm_sec, expected.tm_sec);
1118  EXPECT_EQ(returned.tm_min, expected.tm_min);
1119  EXPECT_EQ(returned.tm_hour, expected.tm_hour);
1120  EXPECT_EQ(returned.tm_mday, expected.tm_mday);
1121  EXPECT_EQ(returned.tm_mon, expected.tm_mon);
1122  EXPECT_EQ(returned.tm_year, expected.tm_year);
1123  EXPECT_EQ(returned.tm_isdst, -1);
1124 
1125  // A <value><dateTime.iso8601>0000000T00:00:00<dateTime.iso8601></value> is valid
1126  offset = 0;
1127  // FIXME: this currently leaves the returned struct tm fields 'tm_wday' and 'tm_yday' uninitialized
1128  val.fromXml("<value><dateTime.iso8601>0000000T00:00:00<dateTime.iso8601></value>", &offset);
1129  EXPECT_EQ(val.getType(), XmlRpcValue::Type::TypeDateTime);
1130  EXPECT_EQ(offset, 67);
1131  returned = static_cast<struct tm>(val);
1132  EXPECT_EQ(returned.tm_sec, expected.tm_sec);
1133  EXPECT_EQ(returned.tm_min, expected.tm_min);
1134  EXPECT_EQ(returned.tm_hour, expected.tm_hour);
1135  EXPECT_EQ(returned.tm_mday, expected.tm_mday);
1136  EXPECT_EQ(returned.tm_mon, expected.tm_mon);
1137  EXPECT_EQ(returned.tm_year, expected.tm_year);
1138  EXPECT_EQ(returned.tm_isdst, -1);
1139 }
1140 
1141 TEST(XmlRpc, fromXmlBase64) {
1142  int offset = 0;
1143  XmlRpcValue val;
1144 
1145  // A <value><base64> is invalid
1146  offset = 0;
1147  val.fromXml("<value><base64>", &offset);
1148  EXPECT_EQ(val.getType(), XmlRpcValue::Type::TypeInvalid);
1149  EXPECT_EQ(offset, 0);
1150 
1151  // A <value><base64></base64></value> is valid
1152  offset = 0;
1153  val.fromXml("<value><base64></base64></value>", &offset);
1154  EXPECT_EQ(val.getType(), XmlRpcValue::Type::TypeBase64);
1155  EXPECT_EQ(offset, 32);
1156  EXPECT_EQ(static_cast<const XmlRpc::XmlRpcValue::BinaryData &>(val), XmlRpc::XmlRpcValue::BinaryData());
1157  EXPECT_EQ(val.size(), 0);
1158 
1159  // A <value><base64>____</base64></value> is valid
1160  offset = 0;
1161  // FIXME: the underscore character is illegal in base64, so this should thrown an error
1162  val.fromXml("<value><base64>____</base64></value>", &offset);
1163  EXPECT_EQ(val.getType(), XmlRpcValue::Type::TypeBase64);
1164  EXPECT_EQ(offset, 36);
1165  EXPECT_EQ(static_cast<const XmlRpc::XmlRpcValue::BinaryData &>(val), XmlRpc::XmlRpcValue::BinaryData());
1166  EXPECT_EQ(val.size(), 0);
1167 
1168  // A <value><base64>aGVsbG8=</base64></value> is valid
1169  XmlRpc::XmlRpcValue::BinaryData expected{'h', 'e', 'l', 'l', 'o'};
1170  offset = 0;
1171  val.fromXml("<value><base64>aGVsbG8=</base64></value>", &offset);
1172  EXPECT_EQ(val.getType(), XmlRpcValue::Type::TypeBase64);
1173  EXPECT_EQ(offset, 40);
1174  EXPECT_EQ(static_cast<const XmlRpc::XmlRpcValue::BinaryData &>(val), expected);
1175  EXPECT_EQ(val.size(), 5);
1176 }
1177 
1178 TEST(XmlRpc, fromXmlArray) {
1179  int offset = 0;
1180  XmlRpcValue val;
1181 
1182  // A <value><array> is invalid
1183  offset = 0;
1184  val.fromXml("<value><array>", &offset);
1185  EXPECT_EQ(val.getType(), XmlRpcValue::Type::TypeInvalid);
1186  EXPECT_EQ(offset, 0);
1187 
1188  // A <value><array></array></value> is invalid (no <data> tag)
1189  offset = 0;
1190  val.fromXml("<value><array></array></value>", &offset);
1191  EXPECT_EQ(val.getType(), XmlRpcValue::Type::TypeInvalid);
1192  EXPECT_EQ(offset, 0);
1193 
1194  // A <value><array><data></data></array></value> is valid
1195  offset = 0;
1196  val.fromXml("<value><array><data></data></array></value>", &offset);
1197  EXPECT_EQ(val.getType(), XmlRpcValue::Type::TypeArray);
1198  EXPECT_EQ(offset, 43);
1199  EXPECT_EQ(val.size(), 0);
1200 
1201  // A <value><array><data><value><boolean>1</boolean></value></data></array></value> is valid
1202  offset = 0;
1203  val.fromXml("<value><array><data><value><boolean>1</boolean></value></data></array></value>", &offset);
1204  EXPECT_EQ(val.getType(), XmlRpcValue::Type::TypeArray);
1205  EXPECT_EQ(offset, 78);
1206  EXPECT_EQ(val.size(), 1);
1207  EXPECT_EQ(static_cast<bool>(val[0]), true);
1208 
1209  // A <value><array><data><value><boolean>1</boolean></value></array></value> is valid
1210  offset = 0;
1211  // FIXME: this should fail (missing an end </data>), but currently does not
1212  val.fromXml("<value><array><data><value><boolean>1</boolean></value></array></value>", &offset);
1213  EXPECT_EQ(val.getType(), XmlRpcValue::Type::TypeArray);
1214  EXPECT_EQ(offset, 71);
1215  EXPECT_EQ(val.size(), 1);
1216  EXPECT_EQ(static_cast<bool>(val[0]), true);
1217 
1218  // A <value><array><data><value><boolean>1</boolean></value><value><double>23.4</double></value></data></array></value> is valid
1219  offset = 0;
1220  val.fromXml("<value><array><data><value><boolean>1</boolean></value><value><double>23.4</double></value></data></array></value>", &offset);
1221  EXPECT_EQ(val.getType(), XmlRpcValue::Type::TypeArray);
1222  EXPECT_EQ(offset, 114);
1223  EXPECT_EQ(val.size(), 2);
1224  EXPECT_EQ(static_cast<bool>(val[0]), true);
1225  EXPECT_NEAR(static_cast<double>(val[1]), 23.4, 0.01);
1226 }
1227 
1228 TEST(XmlRpc, fromXmlStruct) {
1229  int offset = 0;
1230  XmlRpcValue val;
1231 
1232  // A <value><struct> is valid
1233  offset = 0;
1234  // FIXME: this should fail, but currently does not
1235  val.fromXml("<value><struct>", &offset);
1236  EXPECT_EQ(val.getType(), XmlRpcValue::Type::TypeStruct);
1237  EXPECT_EQ(offset, 15);
1238  EXPECT_EQ(val.size(), 0);
1239 
1240  // A <value><struct><member><value><boolean>1</value> is valid
1241  offset = 0;
1242  // FIXME: this should fail (it is missing many end tags and a <name> tag), but currently does not
1243  val.fromXml("<value><struct><member><value><boolean>1</value>", &offset);
1244  EXPECT_EQ(val.getType(), XmlRpcValue::Type::TypeStruct);
1245  EXPECT_EQ(offset, 48);
1246  EXPECT_EQ(val.size(), 1);
1247  EXPECT_EQ(static_cast<bool>(val[""]), true);
1248 
1249  // A <value><struct><member><value><boolean>1</boolean></value></member></struct></value> is valid
1250  offset = 0;
1251  // FIXME: this should fail (it is missing a <name> tag), but currently does not
1252  val.fromXml("<value><struct><member><value><boolean>1</boolean></value></member></struct></value>", &offset);
1253  EXPECT_EQ(val.getType(), XmlRpcValue::Type::TypeStruct);
1254  EXPECT_EQ(offset, 84);
1255  EXPECT_EQ(val.size(), 1);
1256  EXPECT_EQ(static_cast<bool>(val[""]), true);
1257 
1258  // A <value><struct><member><name></name><value><boolean>1</boolean></value></member></struct></value> is valid
1259  offset = 0;
1260  // FIXME: this should fail (the name tag is empty), but currently does not
1261  val.fromXml("<value><struct><member><name></name><value><boolean>1</boolean></value></member></struct></value>", &offset);
1262  EXPECT_EQ(val.getType(), XmlRpcValue::Type::TypeStruct);
1263  EXPECT_EQ(offset, 97);
1264  EXPECT_EQ(val.size(), 1);
1265  EXPECT_EQ(static_cast<bool>(val[""]), true);
1266 
1267  // A <value><struct><member><name>foo</name><value><boolean>1</boolean></value></member></struct></value> is valid
1268  offset = 0;
1269  val.fromXml("<value><struct><member><name>foo</name><value><boolean>1</boolean></value></member></struct></value>", &offset);
1270  EXPECT_EQ(val.getType(), XmlRpcValue::Type::TypeStruct);
1271  EXPECT_EQ(offset, 100);
1272  EXPECT_EQ(val.size(), 1);
1273  EXPECT_EQ(static_cast<bool>(val["foo"]), true);
1274 }
1275 
1276 int main(int argc, char **argv)
1277 {
1278  ::testing::InitGoogleTest(&argc, argv);
1279  return RUN_ALL_TESTS();
1280 }
XmlRpc::XmlRpcValue::size
int size() const
Return the size for string, base64, array, and struct values.
Definition: XmlRpcValue.cpp:211
XmlRpc::XmlRpcValue::toXml
std::string toXml() const
Encode the Value in xml.
Definition: XmlRpcValue.cpp:277
XmlRpc::XmlRpcValue::BinaryData
std::vector< char > BinaryData
Definition: XmlRpcValue.h:41
XmlRpc::XmlRpcValue::TypeBase64
@ TypeBase64
Definition: XmlRpcValue.h:35
XmlRpc::XmlRpcException::getMessage
const std::string & getMessage() const
Return the error message.
Definition: XmlRpcException.h:32
s
XmlRpcServer s
Definition: HelloServer.cpp:11
XmlRpc::XmlRpcValue::fromXml
bool fromXml(std::string const &valueXml, int *offset)
Decode xml. Destroys any existing value.
Definition: XmlRpcValue.cpp:232
XmlRpcValue.h
XmlRpc::XmlRpcValue::TypeInt
@ TypeInt
Definition: XmlRpcValue.h:31
XmlRpc
Definition: XmlRpcClient.h:20
testArray
void testArray(XmlRpcValue const &d)
Definition: standalone-tests/TestValues.cpp:100
XmlRpc::XmlRpcUtil::parseTag
static std::string parseTag(const char *tag, std::string const &xml, int *offset)
Definition: XmlRpcUtil.cpp:112
XmlRpc::XmlRpcValue::TypeStruct
@ TypeStruct
Definition: XmlRpcValue.h:37
base64
Definition: decode.h:15
XmlRpc::XmlRpcValue::clear
void clear()
Erase the current value.
Definition: XmlRpcValue.h:79
XmlRpc::XmlRpcValue::getDoubleFormat
static std::string const & getDoubleFormat()
Return the format used to write double values.
Definition: XmlRpcValue.h:146
testDouble
void testDouble()
Definition: standalone-tests/TestValues.cpp:51
XmlRpc::XmlRpcValue::TypeDouble
@ TypeDouble
Definition: XmlRpcValue.h:32
XmlRpc::XmlRpcUtil::findTag
static bool findTag(const char *tag, std::string const &xml, int *offset)
Returns true if the tag is found and updates offset to the char after the tag.
Definition: XmlRpcUtil.cpp:133
XmlRpc::XmlRpcUtil::nextTagData
static std::string nextTagData(const char *tag, std::string const &xml, int *offset)
Definition: XmlRpcUtil.cpp:173
XmlRpc::XmlRpcValue::TypeString
@ TypeString
Definition: XmlRpcValue.h:33
XmlRpc::XmlRpcUtil::nextTagIs
static bool nextTagIs(const char *tag, std::string const &xml, int *offset)
Definition: XmlRpcUtil.cpp:150
main
int main(int argc, char **argv)
Definition: test/TestValues.cpp:1276
XmlRpc::TEST
TEST(xmlrpcvalue_base64, empty_string)
Definition: xmlrpcvalue_base64.cpp:52
XmlRpc::XmlRpcException::getCode
int getCode() const
Return the error code.
Definition: XmlRpcException.h:35
testBoolean
void testBoolean()
Definition: standalone-tests/TestValues.cpp:15
testDateTime
void testDateTime()
Definition: standalone-tests/TestValues.cpp:90
XmlRpc::XmlRpcValue::iterator
ValueStruct::iterator iterator
Definition: XmlRpcValue.h:44
XmlRpc::XmlRpcValue::getType
const Type & getType() const
Return the type of the value stored.
Definition: XmlRpcValue.h:124
XmlRpc::XmlRpcValue::TypeArray
@ TypeArray
Definition: XmlRpcValue.h:36
XmlRpc::XmlRpcException
Definition: XmlRpcException.h:23
XmlRpc::XmlRpcValue::hasMember
bool hasMember(const std::string &name) const
Check for the existence of a struct member by name.
Definition: XmlRpcValue.cpp:225
XmlRpc::XmlRpcValue::valid
bool valid() const
Return true if the value has been set to something.
Definition: XmlRpcValue.h:121
testStruct
void testStruct()
Definition: standalone-tests/TestValues.cpp:127
XmlRpc::XmlRpcValue::setDoubleFormat
static void setDoubleFormat(const char *f)
Specify the format used to write double values.
Definition: XmlRpcValue.h:149
XmlRpcException.h
XmlRpc::XmlRpcValue::setSize
void setSize(int size)
Specify the size for array values. Array values will grow beyond this size if needed.
Definition: XmlRpcValue.h:130
XmlRpc::fromXml
XmlRpcValue fromXml(std::string const &data)
Definition: xmlrpcvalue_base64.cpp:22
XmlRpc::XmlRpcValue::TypeDateTime
@ TypeDateTime
Definition: XmlRpcValue.h:34
testInt
void testInt()
Definition: standalone-tests/TestValues.cpp:35
XmlRpcUtil.h
XmlRpc::XmlRpcValue
RPC method arguments and results are represented by Values.
Definition: XmlRpcValue.h:24
XmlRpc::XmlRpcUtil::getNextTag
static std::string getNextTag(std::string const &xml, int *offset)
Definition: XmlRpcUtil.cpp:225
testString
void testString()
Definition: standalone-tests/TestValues.cpp:60


xmlrpcpp
Author(s): Chris Morley, Konstantin Pilipchuk, Morgan Quigley, Austin Hendrix, Dirk Thomas , Jacob Perron
autogenerated on Sat Sep 14 2024 02:59:32