initial load of upstream version 1.06.32
[xmlrpc-c] / src / cpp / test / server_abyss.cpp
diff --git a/src/cpp/test/server_abyss.cpp b/src/cpp/test/server_abyss.cpp
new file mode 100644 (file)
index 0000000..b1a6bda
--- /dev/null
@@ -0,0 +1,215 @@
+/*=============================================================================
+                                  server_abyss
+===============================================================================
+  Test the Abyss server C++ facilities of XML-RPC for C/C++.
+  
+=============================================================================*/
+#include <sys/unistd.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <errno.h>
+#include <string>
+#include <iostream>
+#include <vector>
+#include <sstream>
+#include <memory>
+#include <time.h>
+#include <cstring>
+
+#include "xmlrpc-c/girerr.hpp"
+using girerr::error;
+using girerr::throwf;
+#include "xmlrpc-c/base.hpp"
+#include "xmlrpc-c/registry.hpp"
+#include "xmlrpc-c/server_abyss.hpp"
+
+#include "tools.hpp"
+#include "server_abyss.hpp"
+
+using namespace xmlrpc_c;
+using namespace std;
+
+
+
+class boundSocket {
+
+public:
+    boundSocket(short const portNumber) {
+        this->fd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
+
+        if (this->fd < 0)
+            throwf("socket() failed.  errno=%d (%s)",
+                   errno, strerror(errno));
+        
+        struct sockaddr_in sockAddr;
+        int rc;
+
+        sockAddr.sin_family = AF_INET;
+        sockAddr.sin_port   = htons(portNumber);
+        sockAddr.sin_addr.s_addr = 0;
+
+        rc = bind(this->fd, (struct sockaddr *)&sockAddr, sizeof(sockAddr));
+        
+        if (rc != 0) {
+            close(this->fd);
+            throwf("Couldn't bind.  bind() failed with errno=%d (%s)",
+                   errno, strerror(errno));
+        }
+    }
+
+    ~boundSocket() {
+        close(this->fd);
+    }
+
+    int fd;
+};
+
+
+
+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 addHandlerTestSuite : public testSuite {
+
+public:
+    virtual string suiteName() {
+        return "addHandlerTestSuite";
+    }
+    virtual void runtests(unsigned int) {
+        TServer abyssServer;
+
+        ServerCreate(&abyssServer, "testserver", 8080, NULL, NULL);
+
+        registry myRegistry;
+        
+        myRegistry.addMethod("sample.add", methodPtr(new sampleAddMethod));
+        
+        registryPtr myRegistryP(new registry);
+        
+        myRegistryP->addMethod("sample.add", methodPtr(new sampleAddMethod));
+
+        server_abyss_set_handlers(&abyssServer, myRegistry);
+
+        server_abyss_set_handlers(&abyssServer, &myRegistry);
+        
+        server_abyss_set_handlers(&abyssServer, myRegistryP);
+
+        server_abyss_set_handlers(&abyssServer, myRegistry, "/RPC3");
+
+        server_abyss_set_handlers(&abyssServer, &myRegistry, "/RPC3");
+        
+        server_abyss_set_handlers(&abyssServer, myRegistryP, "/RPC3");
+
+        ServerFree(&abyssServer);
+    }
+};
+
+
+
+string
+serverAbyssTestSuite::suiteName() {
+    return "serverAbyssTestSuite";
+}
+
+
+void
+serverAbyssTestSuite::runtests(unsigned int const indentation) {
+
+    addHandlerTestSuite().run(indentation+1);
+
+    registry myRegistry;
+        
+    myRegistry.addMethod("sample.add", methodPtr(new sampleAddMethod));
+
+    registryPtr myRegistryP(new registry);
+
+    myRegistryP->addMethod("sample.add", methodPtr(new sampleAddMethod));
+
+    EXPECT_ERROR(  // No registry
+        serverAbyss::constrOpt opt;
+        serverAbyss abyssServer(opt);
+        );
+    EXPECT_ERROR(  // Both portNumber and socketFd
+        serverAbyss abyssServer(serverAbyss::constrOpt()
+                                .portNumber(8080)
+                                .socketFd(3));
+        );
+
+    // Due to the vagaries of Abyss, construction of the following
+    // objects may exit the program if it detects an error, such as
+    // port number already in use.  We need to fix Abyss some day.
+
+    {
+        serverAbyss abyssServer(serverAbyss::constrOpt()
+                                .registryP(&myRegistry)
+                                .portNumber(12345)
+            );
+    }
+    {
+        serverAbyss abyssServer(serverAbyss::constrOpt()
+                                .registryPtr(myRegistryP)
+                                .portNumber(12345)
+            );
+
+        EXPECT_ERROR(  // Both registryP and registryPtr
+            serverAbyss abyssServer(serverAbyss::constrOpt()
+                                    .registryPtr(myRegistryP)
+                                    .registryP(&myRegistry)
+                                    .portNumber(12345)
+                );
+            );
+    }
+    {
+        boundSocket socket(12345);
+        
+        serverAbyss abyssServer(serverAbyss::constrOpt()
+                                .registryP(&myRegistry)
+                                .socketFd(socket.fd)
+            );
+    }
+    {
+        serverAbyss abyssServer(serverAbyss::constrOpt()
+                                .registryP(&myRegistry)
+            );
+    }
+
+    {
+        // Test all the options
+        serverAbyss abyssServer(serverAbyss::constrOpt()
+                                .registryPtr(myRegistryP)
+                                .portNumber(12345)
+                                .logFileName("/tmp/logfile")
+                                .keepaliveTimeout(5)
+                                .keepaliveMaxConn(4)
+                                .timeout(20)
+                                .dontAdvertise(true)
+                                .uriPath("/xmlrpc")
+            );
+
+    }
+    {
+        serverAbyss abyssServer(
+            myRegistry,
+            12345,              // TCP port on which to listen
+            "/tmp/xmlrpc_log"  // Log file
+            );
+    }
+}