--- /dev/null
+#include <string>
+#include <iostream>
+#include <iomanip>
+#include <vector>
+#include <sstream>
+#include <memory>
+#include <time.h>
+#include <cstring>
+
+#include "xmlrpc-c/girerr.hpp"
+using girerr::error;
+#include "transport_config.h"
+#include "xmlrpc-c/base.hpp"
+#include "xmlrpc-c/oldcppwrapper.hpp"
+#include "xmlrpc-c/registry.hpp"
+
+#include "testclient.hpp"
+#include "server_abyss.hpp"
+#include "tools.hpp"
+
+using namespace xmlrpc_c;
+using namespace std;
+
+//=========================================================================
+// Test Harness
+//=========================================================================
+//
+// There are two styles of test in here. The older ones are vaguely
+// inspired by Kent Beck's book on eXtreme Programming (XP) and use
+// the TEST...() macros.
+//
+// But this style is not really appropriate for C++. It's based on
+// code that explicitly tests for errors, as one would do in C. In C++,
+// it is cumbersome to catch exceptions on every call, so we don't in
+// the new style.
+
+// And there's not much point in trying to count test successes and
+// failures. Any failure is a problem, so in the new style, we just
+// quit after we recognize one (again, more in line with regular exception
+// throwing). With exception throwing, you can't count what _didn't_
+// cause an exception, so there's no meaningful count of test successes.
+//
+// To run the tests, type './cpptest'.
+// To check for memory leaks, install RedHat's 'memprof' utility, and
+// type 'memprof cpptest'.
+//
+// If you add new tests to this file, please deallocate any data
+// structures you use in the appropriate fashion. This allows us to test
+// various destructor code for memory leaks.
+
+
+class sampleAddMethod : public method {
+public:
+ sampleAddMethod() {
+ this->_signature = "i:ii";
+ this->_help = "This method adds two integers together";
+ }
+ void
+ execute(xmlrpc_c::paramList const& paramList,
+ value * const retvalP) {
+
+ int const addend(paramList.getInt(0));
+ int const adder(paramList.getInt(1));
+
+ paramList.verifyEnd(2);
+
+ *retvalP = value_int(addend + adder);
+ }
+};
+
+
+
+class nameMethod : public defaultMethod {
+
+ void
+ execute(string const& methodName,
+ xmlrpc_c::paramList const& , // paramList
+ value * const retvalP) {
+
+ *retvalP = value_string(string("no such method: ") + methodName);
+ }
+};
+
+
+//=========================================================================
+// Test Suites
+//=========================================================================
+
+void
+test_fault (void) {
+
+ // Create a new fault and perform basic operations.
+ XmlRpcFault fault1 = XmlRpcFault(6, "Sample fault");
+ TEST(fault1.getFaultCode() == 6);
+ TEST(fault1.getFaultString() == "Sample fault");
+
+ // Extract and examine the underlying xmlrpc_env struct.
+ xmlrpc_env *env1 = fault1.getFaultEnv();
+ TEST(env1 != NULL);
+ TEST(env1->fault_occurred);
+ TEST(env1->fault_code == 6);
+ TEST(strcmp(env1->fault_string, "Sample fault") == 0);
+
+ // Test our copy constructor.
+ XmlRpcFault fault2 = fault1;
+ TEST(fault2.getFaultCode() == 6);
+ TEST(fault2.getFaultString() == "Sample fault");
+
+ // Construct a fault from a pre-existing xmlrpc_env structure.
+ xmlrpc_env env3;
+ xmlrpc_env_init(&env3);
+ xmlrpc_env_set_fault(&env3, 7, "Another fault");
+ XmlRpcFault fault3 = XmlRpcFault(&env3);
+ xmlrpc_env_clean(&env3);
+ TEST(fault3.getFaultCode() == 7);
+ TEST(fault3.getFaultString() == "Another fault");
+
+ // Attempt to construct a fault from a fault-free xmlrpc_env.
+ xmlrpc_env env4;
+ xmlrpc_env_init(&env4);
+ try {
+ XmlRpcFault fault4 = XmlRpcFault(&env4);
+ TEST_FAILED("Constructed invalid XmlRpcFault");
+ } catch (XmlRpcFault const& fault) {
+ TEST_PASSED();
+ TEST(fault.getFaultCode() == XMLRPC_INTERNAL_ERROR);
+ }
+ xmlrpc_env_clean(&env4);
+}
+
+
+
+void test_env (void) {
+
+ // Declare these here to prevent silly compiler warnings about
+ // potentially uninitialized variables.
+ XmlRpcEnv env1;
+ XmlRpcEnv env2;
+
+ // Perform simple environment tests.
+ TEST(!env1.hasFaultOccurred());
+ xmlrpc_env_set_fault(env1, 8, "Fault 8");
+ TEST(env1.hasFaultOccurred());
+ XmlRpcFault fault1 = env1.getFault();
+ TEST(fault1.getFaultCode() == 8);
+ TEST(fault1.getFaultString() == "Fault 8");
+
+ // Test throwIfFaultOccurred.
+ try {
+ env2.throwIfFaultOccurred();
+ TEST_PASSED();
+ } catch (XmlRpcFault const& fault) {
+ TEST_FAILED("We threw a fault when one hadn't occurred");
+ }
+ xmlrpc_env_set_fault(env2, 9, "Fault 9");
+ try {
+ env2.throwIfFaultOccurred();
+ TEST_FAILED("A fault occurred, and we didn't throw it");
+ } catch (XmlRpcFault const& fault) {
+ TEST_PASSED();
+ TEST(fault.getFaultCode() == 9);
+ TEST(fault.getFaultString() == "Fault 9");
+ }
+
+ // Make sure we can't get a fault if one hasn't occurred.
+ XmlRpcEnv env3;
+ try {
+ XmlRpcFault fault3 = env3.getFault();
+ TEST_FAILED("We retrieved a non-existant fault");
+ } catch (XmlRpcFault const& fault) {
+ TEST_PASSED();
+ TEST(fault.getFaultCode() == XMLRPC_INTERNAL_ERROR);
+ }
+}
+
+void test_value (void) {
+ XmlRpcEnv env;
+
+ // Test basic reference counting behavior.
+ xmlrpc_value *v = xmlrpc_build_value(env, "i", (xmlrpc_int32) 1);
+ env.throwIfFaultOccurred();
+ XmlRpcValue val1 = XmlRpcValue(v, XmlRpcValue::CONSUME_REFERENCE);
+ v = xmlrpc_build_value(env, "i", (xmlrpc_int32) 2);
+ env.throwIfFaultOccurred();
+ XmlRpcValue val2 = v;
+ xmlrpc_DECREF(v);
+
+ // Borrow a reference.
+ v = xmlrpc_build_value(env, "i", (xmlrpc_int32) 3);
+ env.throwIfFaultOccurred();
+ XmlRpcValue val3 = XmlRpcValue(v, XmlRpcValue::CONSUME_REFERENCE);
+ xmlrpc_value *borrowed = val3.borrowReference();
+ TEST(borrowed == v);
+
+ // Make a reference.
+ v = xmlrpc_build_value(env, "i", (xmlrpc_int32) 4);
+ env.throwIfFaultOccurred();
+ XmlRpcValue val4 = XmlRpcValue(v, XmlRpcValue::CONSUME_REFERENCE);
+ xmlrpc_value *made = val4.makeReference();
+ TEST(made == v);
+ xmlrpc_DECREF(made);
+
+ // Test our default constructor.
+ XmlRpcValue val5;
+ TEST(val5.getBool() == false);
+
+ // Test our type introspection.
+ TEST(XmlRpcValue::makeInt(0).getType() == XMLRPC_TYPE_INT);
+
+ // Test our basic data types.
+ TEST(XmlRpcValue::makeInt(30).getInt() == 30);
+ TEST(XmlRpcValue::makeInt(-30).getInt() == -30);
+ TEST(XmlRpcValue::makeBool(true).getBool() == true);
+ TEST(XmlRpcValue::makeBool(false).getBool() == false);
+ TEST(XmlRpcValue::makeDateTime("19980717T14:08:55").getRawDateTime() ==
+ "19980717T14:08:55");
+ TEST(XmlRpcValue::makeString("foo").getString() == "foo");
+ TEST(XmlRpcValue::makeString("bar", 3).getString() == "bar");
+ TEST(XmlRpcValue::makeString("bar", 3).getString() == "bar");
+ TEST(XmlRpcValue::makeString("a\0b").getString() == string("a\0b"));
+ XmlRpcValue::makeArray().getArray();
+ XmlRpcValue::makeStruct().getStruct();
+
+ // Test Base64 values.
+ const unsigned char *b64_data;
+ size_t b64_len;
+ XmlRpcValue val6 = XmlRpcValue::makeBase64((unsigned char*) "a\0\0b", 4);
+ val6.getBase64(b64_data, b64_len);
+ TEST(b64_len == 4);
+ TEST(memcmp(b64_data, "a\0\0b", 4) == 0);
+
+ // Test arrays.
+ XmlRpcValue array = XmlRpcValue::makeArray();
+ TEST(array.arraySize() == 0);
+ array.arrayAppendItem(XmlRpcValue::makeString("foo"));
+ TEST(array.arraySize() == 1);
+ array.arrayAppendItem(XmlRpcValue::makeString("bar"));
+ TEST(array.arraySize() == 2);
+ TEST(array.arrayGetItem(0).getString() == "foo");
+ TEST(array.arrayGetItem(1).getString() == "bar");
+
+ // Test structs.
+ XmlRpcValue strct = XmlRpcValue::makeStruct();
+ TEST(strct.structSize() == 0);
+ strct.structSetValue("foo", XmlRpcValue::makeString("fooval"));
+ TEST(strct.structSize() == 1);
+ strct.structSetValue("bar", XmlRpcValue::makeString("barval"));
+ TEST(strct.structSize() == 2);
+ TEST(strct.structHasKey("bar"));
+ TEST(!strct.structHasKey("nosuch"));
+ for (size_t i = 0; i < strct.structSize(); i++) {
+ string key;
+ XmlRpcValue value;
+ strct.structGetKeyAndValue(i, key, value);
+ TEST(key + "val" == value.getString());
+ }
+}
+
+
+
+static void
+testXmlRpcCpp() {
+/*----------------------------------------------------------------------------
+ Test the legacy XmlRpcCpp.cpp library
+-----------------------------------------------------------------------------*/
+ cout << "Testing XmlRpcCpp library..." << endl;
+
+ test_fault();
+ test_env();
+ test_value();
+}
+
+
+
+class intTestSuite : public testSuite {
+public:
+ virtual string suiteName() {
+ return "intTestSuite";
+ }
+ virtual void runtests(unsigned int const) {
+ value_int int1(7);
+ TEST(static_cast<int>(int1) == 7);
+ value_int int2(-7);
+ TEST(static_cast<int>(int2) == -7);
+ value val1(int1);
+ TEST(val1.type() == value::TYPE_INT);
+ value_int int3(val1);
+ TEST(static_cast<int>(int3) == 7);
+ try {
+ value_int int4(value_double(3.7));
+ TEST_FAILED("invalid cast double-int suceeded");
+ } catch (error) {}
+ }
+};
+
+
+
+class doubleTestSuite : public testSuite {
+public:
+ virtual string suiteName() {
+ return "doubleTestSuite";
+ }
+ virtual void runtests(unsigned int const) {
+ value_double double1(3.14);
+ TEST(static_cast<double>(double1) == 3.14);
+ value val1(double1);
+ TEST(val1.type() == value::TYPE_DOUBLE);
+ value_double double2(val1);
+ TEST(static_cast<double>(double2) == 3.14);
+ try {
+ value_double double4(value_int(4));
+ TEST_FAILED("invalid cast int-double suceeded");
+ } catch (error) {}
+ }
+};
+
+
+
+class booleanTestSuite : public testSuite {
+public:
+ virtual string suiteName() {
+ return "booleanTestSuite";
+ }
+ virtual void runtests(unsigned int const) {
+ value_boolean boolean1(true);
+ TEST(static_cast<bool>(boolean1) == true);
+ value_boolean boolean2(false);
+ TEST(static_cast<bool>(boolean2) == false);
+ value val1(boolean1);
+ TEST(val1.type() == value::TYPE_BOOLEAN);
+ value_boolean boolean3(val1);
+ TEST(static_cast<bool>(boolean3) == true);
+ try {
+ value_boolean boolean4(value_int(4));
+ TEST_FAILED("invalid cast int-boolean suceeded");
+ } catch (error) {}
+ }
+};
+
+
+
+class datetimeTestSuite : public testSuite {
+public:
+ virtual string suiteName() {
+ return "datetimeTestSuite";
+ }
+ virtual void runtests(unsigned int const) {
+ time_t const testTime(900684535);
+ value_datetime datetime1("19980717T14:08:55");
+ TEST(static_cast<time_t>(datetime1) == testTime);
+ value_datetime datetime2(testTime);
+ TEST(static_cast<time_t>(datetime2) == testTime);
+ value val1(datetime1);
+ TEST(val1.type() == value::TYPE_DATETIME);
+ value_datetime datetime3(val1);
+ TEST(static_cast<time_t>(datetime3) == testTime);
+ try {
+ value_datetime datetime4(value_int(4));
+ TEST_FAILED("invalid cast int-datetime suceeded");
+ } catch (error) {}
+ }
+};
+
+
+
+class stringTestSuite : public testSuite {
+public:
+ virtual string suiteName() {
+ return "stringTestSuite";
+ }
+ virtual void runtests(unsigned int const) {
+ value_string string1("hello world");
+ TEST(static_cast<string>(string1) == "hello world");
+ value_string string2("embedded\0null");
+ TEST(static_cast<string>(string2) == "embedded\0null");
+ value val1(string1);
+ TEST(val1.type() == value::TYPE_STRING);
+ value_string string3(val1);
+ TEST(static_cast<string>(string3) == "hello world");
+ try {
+ value_string string4(value_int(4));
+ TEST_FAILED("invalid cast int-string suceeded");
+ } catch (error) {}
+ }
+};
+
+
+
+class bytestringTestSuite : public testSuite {
+public:
+ virtual string suiteName() {
+ return "bytestringTestSuite";
+ }
+ virtual void runtests(unsigned int const) {
+ unsigned char bytestringArray[] = {0x10, 0x11, 0x12, 0x13, 0x14};
+ vector<unsigned char>
+ bytestringData(&bytestringArray[0], &bytestringArray[4]);
+ value_bytestring bytestring1(bytestringData);
+
+ vector<unsigned char> const dataReadBack1(
+ bytestring1.vectorUcharValue());
+ TEST(dataReadBack1 == bytestringData);
+ value val1(bytestring1);
+ TEST(val1.type() == value::TYPE_BYTESTRING);
+ value_bytestring bytestring2(val1);
+ vector<unsigned char> const dataReadBack2(
+ bytestring2.vectorUcharValue());
+ TEST(dataReadBack2 == bytestringData);
+ try {
+ value_bytestring bytestring4(value_int(4));
+ TEST_FAILED("invalid cast int-bytestring suceeded");
+ } catch (error) {}
+ }
+};
+
+
+
+class nilTestSuite : public testSuite {
+public:
+ virtual string suiteName() {
+ return "nilTestSuite";
+ }
+ virtual void runtests(unsigned int const) {
+ value_nil nil1;
+ value val1(nil1);
+ TEST(val1.type() == value::TYPE_NIL);
+ value_nil nil2(val1);
+ try {
+ value_nil nil4(value_int(4));
+ TEST_FAILED("invalid cast int-nil suceeded");
+ } catch (error) {}
+ }
+};
+
+
+
+class structTestSuite : public testSuite {
+public:
+ virtual string suiteName() {
+ return "structTestSuite";
+ }
+ virtual void runtests(unsigned int const) {
+ map<string, value> structData;
+ pair<string, value> member("the_integer", value_int(9));
+ structData.insert(member);
+
+ value_struct struct1(structData);
+
+ map<string, value> dataReadBack(struct1);
+
+ TEST(static_cast<int>(value_int(dataReadBack["the_integer"])) == 9);
+
+ value val1(struct1);
+ TEST(val1.type() == value::TYPE_STRUCT);
+ value_struct struct2(val1);
+ try {
+ value_struct struct4(value_int(4));
+ TEST_FAILED("invalid cast int-struct suceeded");
+ } catch (error) {}
+ }
+};
+
+
+
+class arrayTestSuite : public testSuite {
+public:
+ virtual string suiteName() {
+ return "arrayTestSuite";
+ }
+ virtual void runtests(unsigned int const) {
+ vector<value> arrayData;
+ arrayData.push_back(value_int(7));
+ arrayData.push_back(value_double(2.78));
+ arrayData.push_back(value_string("hello world"));
+ value_array array1(arrayData);
+
+ TEST(array1.size() == 3);
+ vector<value> dataReadBack1(array1.vectorValueValue());
+ TEST(dataReadBack1[0].type() == value::TYPE_INT);
+ TEST(static_cast<int>(value_int(dataReadBack1[0])) == 7);
+ TEST(dataReadBack1[1].type() == value::TYPE_DOUBLE);
+ TEST(static_cast<double>(value_double(dataReadBack1[1])) == 2.78);
+ TEST(dataReadBack1[2].type() == value::TYPE_STRING);
+ TEST(static_cast<string>(value_string(dataReadBack1[2])) ==
+ "hello world");
+
+ value val1(array1);
+ TEST(val1.type() == value::TYPE_ARRAY);
+ value_array array2(val1);
+ TEST(array2.size() == 3);
+ try {
+ value_array array4(value_int(4));
+ TEST_FAILED("invalid cast int-array suceeded");
+ } catch (error) {}
+ }
+};
+
+
+
+class valueTestSuite : public testSuite {
+
+public:
+ virtual string suiteName() {
+ return "valueTestSuite";
+ }
+ virtual void runtests(unsigned int const indentation) {
+
+ intTestSuite().run(indentation+1);
+ doubleTestSuite().run(indentation+1);
+ booleanTestSuite().run(indentation+1);
+ datetimeTestSuite().run(indentation+1);
+ stringTestSuite().run(indentation+1);
+ bytestringTestSuite().run(indentation+1);
+ nilTestSuite().run(indentation+1);
+ structTestSuite().run(indentation+1);
+ arrayTestSuite().run(indentation+1);
+ }
+};
+
+
+namespace {
+string const noElementFoundXml(
+ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n"
+ "<methodResponse>\r\n"
+ "<fault>\r\n"
+ "<value><struct>\r\n"
+ "<member><name>faultCode</name>\r\n"
+ "<value><i4>-503</i4></value></member>\r\n"
+ "<member><name>faultString</name>\r\n"
+ "<value><string>Call XML not a proper XML-RPC call. "
+ "Call is not valid XML. no element found</string></value>"
+ "</member>\r\n"
+ "</struct></value>\r\n"
+ "</fault>\r\n"
+ "</methodResponse>\r\n"
+ );
+
+string const sampleAddGoodCallXml(
+ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n"
+ "<methodCall>\r\n"
+ "<methodName>sample.add</methodName>\r\n"
+ "<params>\r\n"
+ "<param><value><i4>5</i4></value></param>\r\n"
+ "<param><value><i4>7</i4></value></param>\r\n"
+ "</params>\r\n"
+ "</methodCall>\r\n"
+ );
+
+string const sampleAddGoodResponseXml(
+ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n"
+ "<methodResponse>\r\n"
+ "<params>\r\n"
+ "<param><value><i4>12</i4></value></param>\r\n"
+ "</params>\r\n"
+ "</methodResponse>\r\n"
+ );
+
+
+string const sampleAddBadCallXml(
+ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n"
+ "<methodCall>\r\n"
+ "<methodName>sample.add</methodName>\r\n"
+ "<params>\r\n"
+ "<param><value><i4>5</i4></value></param>\r\n"
+ "</params>\r\n"
+ "</methodCall>\r\n"
+ );
+
+string const sampleAddBadResponseXml(
+ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n"
+ "<methodResponse>\r\n"
+ "<fault>\r\n"
+ "<value><struct>\r\n"
+ "<member><name>faultCode</name>\r\n"
+ "<value><i4>-501</i4></value></member>\r\n"
+ "<member><name>faultString</name>\r\n"
+ "<value><string>Not enough parameters</string></value></member>\r\n"
+ "</struct></value>\r\n"
+ "</fault>\r\n"
+ "</methodResponse>\r\n"
+ );
+
+
+string const nonexistentMethodCallXml(
+ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n"
+ "<methodCall>\r\n"
+ "<methodName>nosuchmethod</methodName>\r\n"
+ "<params>\r\n"
+ "<param><value><i4>5</i4></value></param>\r\n"
+ "<param><value><i4>7</i4></value></param>\r\n"
+ "</params>\r\n"
+ "</methodCall>\r\n"
+ );
+
+string const nonexistentMethodYesDefResponseXml(
+ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n"
+ "<methodResponse>\r\n"
+ "<params>\r\n"
+ "<param><value><string>no such method: nosuchmethod</string>"
+ "</value></param>\r\n"
+ "</params>\r\n"
+ "</methodResponse>\r\n"
+ );
+
+string const nonexistentMethodNoDefResponseXml(
+ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n"
+ "<methodResponse>\r\n"
+ "<fault>\r\n"
+ "<value><struct>\r\n"
+ "<member><name>faultCode</name>\r\n"
+ "<value><i4>-506</i4></value></member>\r\n"
+ "<member><name>faultString</name>\r\n"
+ "<value><string>Method 'nosuchmethod' not defined</string></value>"
+ "</member>\r\n"
+ "</struct></value>\r\n"
+ "</fault>\r\n"
+ "</methodResponse>\r\n"
+ );
+
+} // namespace
+
+
+class paramListTestSuite : public testSuite {
+
+public:
+ virtual string suiteName() {
+ return "paramListTestSuite";
+ }
+ virtual void runtests(unsigned int const) {
+
+ paramList paramList1;
+ TEST(paramList1.size() == 0);
+
+ paramList1.add(value_int(7));
+ paramList1.add(value_boolean(true));
+ paramList1.add(value_double(3.14));
+ time_t const timeZero(0);
+ paramList1.add(value_datetime(timeZero));
+ time_t const timeFuture(time(NULL)+100);
+ paramList1.add(value_datetime(timeFuture));
+ paramList1.add(value_string("hello world"));
+ unsigned char bytestringArray[] = {0x10, 0x11, 0x12, 0x13, 0x14};
+ vector<unsigned char>
+ bytestringData(&bytestringArray[0], &bytestringArray[4]);
+ paramList1.add(value_bytestring(bytestringData));
+ vector<value> arrayData;
+ arrayData.push_back(value_int(7));
+ arrayData.push_back(value_double(2.78));
+ arrayData.push_back(value_string("hello world"));
+ paramList1.add(value_array(arrayData));
+ map<string, value> structData;
+ pair<string, value> member("the_integer", value_int(9));
+ structData.insert(member);
+ paramList1.add(value_struct(structData));
+ paramList1.add(value_nil());
+
+ TEST(paramList1.size() == 10);
+
+ TEST(paramList1.getInt(0) == 7);
+ TEST(paramList1.getInt(0, 7) == 7);
+ TEST(paramList1.getInt(0, -5, 7) == 7);
+ TEST(paramList1.getBoolean(1) == true);
+ TEST(paramList1.getDouble(2) == 3.14);
+ TEST(paramList1.getDouble(2, 1) == 3.14);
+ TEST(paramList1.getDouble(2, 1, 4) == 3.14);
+ TEST(paramList1.getDatetime_sec(3) == 0);
+ TEST(paramList1.getDatetime_sec(3, paramList::TC_ANY) == timeZero);
+ TEST(paramList1.getDatetime_sec(3, paramList::TC_NO_FUTURE)
+ == timeZero);
+ TEST(paramList1.getDatetime_sec(4, paramList::TC_NO_PAST)
+ == timeFuture);
+ TEST(paramList1.getString(5) == "hello world");
+ TEST(paramList1.getBytestring(6)[0] == 0x10);
+ TEST(paramList1.getArray(7).size() == 3);
+ TEST(paramList1.getArray(7, 3).size() == 3);
+ TEST(paramList1.getArray(7, 1, 3).size() == 3);
+ paramList1.getStruct(8)["the_integer"];
+ paramList1.getNil(9);
+ paramList1.verifyEnd(10);
+
+ paramList paramList2(5);
+ TEST(paramList2.size() == 0);
+ }
+};
+
+class registryRegMethodTestSuite : public testSuite {
+
+public:
+ virtual string suiteName() {
+ return "registryRegMethodTestSuite";
+ }
+ virtual void runtests(unsigned int) {
+
+ xmlrpc_c::registry myRegistry;
+
+ myRegistry.addMethod("sample.add",
+ xmlrpc_c::methodPtr(new sampleAddMethod));
+
+ myRegistry.disableIntrospection();
+ {
+ string response;
+ myRegistry.processCall("", &response);
+ TEST(response == noElementFoundXml);
+ }
+ {
+ string response;
+ myRegistry.processCall(sampleAddGoodCallXml, &response);
+ TEST(response == sampleAddGoodResponseXml);
+ }
+ {
+ string response;
+ myRegistry.processCall(sampleAddBadCallXml, &response);
+ TEST(response == sampleAddBadResponseXml);
+ }
+ }
+};
+
+
+
+class registryDefaultMethodTestSuite : public testSuite {
+
+public:
+ virtual string suiteName() {
+ return "registryDefaultMethodTestSuite";
+ }
+ virtual void runtests(unsigned int) {
+
+ xmlrpc_c::registry myRegistry;
+
+ myRegistry.addMethod("sample.add", methodPtr(new sampleAddMethod));
+
+ {
+ string response;
+ myRegistry.processCall(sampleAddGoodCallXml, &response);
+ TEST(response == sampleAddGoodResponseXml);
+ }
+ {
+ string response;
+ myRegistry.processCall(nonexistentMethodCallXml, &response);
+ TEST(response == nonexistentMethodNoDefResponseXml);
+ }
+ // We're actually violating the spirit of setDefaultMethod by
+ // doing this to a registry that's already been used, but as long
+ // as it works, it's a convenient way to implement this test.
+ myRegistry.setDefaultMethod(defaultMethodPtr(new nameMethod));
+
+ {
+ string response;
+ myRegistry.processCall(nonexistentMethodCallXml, &response);
+ TEST(response == nonexistentMethodYesDefResponseXml);
+ }
+ }
+};
+
+
+
+class registryTestSuite : public testSuite {
+
+public:
+ virtual string suiteName() {
+ return "registryTestSuite";
+ }
+ virtual void runtests(unsigned int const indentation) {
+
+ registryRegMethodTestSuite().run(indentation+1);
+ registryDefaultMethodTestSuite().run(indentation+1);
+ }
+};
+
+
+
+//=========================================================================
+// Test Driver
+//=========================================================================
+
+int
+main(int argc, char**) {
+
+ int retval;
+
+ if (argc-1 > 0) {
+ cout << "Program takes no arguments" << endl;
+ exit(1);
+ }
+
+ bool testsPassed;
+
+ try {
+ // Add your test suites here.
+ valueTestSuite().run(0);
+ paramListTestSuite().run(0);
+ registryTestSuite().run(0);
+ serverAbyssTestSuite().run(0);
+ clientTestSuite().run(0);
+
+ testXmlRpcCpp();
+
+ testsPassed = true;
+ } catch (error const& error) {
+ cout << "Unexpected error thrown: " << error.what() << endl;
+ testsPassed = false;
+ } catch (XmlRpcFault const& fault) {
+ cout << "Unexpected XML-RPC fault when running test suites." << endl
+ << "Fault #" << fault.getFaultCode()
+ << ": " << fault.getFaultString() << endl;
+ testsPassed = false;
+ } catch (...) {
+ cout << "Unexpected exception when running test suites." << endl;
+ testsPassed = false;
+ }
+
+ if (testsPassed) {
+ cout << "PASSED" << endl;
+ retval = 0;
+ } else {
+ cout << "FAILED" << endl;
+ retval = 1;
+ }
+ return retval;
+}