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