libt2n: (gerd) fixes & real unit tests
authorGerd v. Egidy <gerd.von.egidy@intra2net.com>
Wed, 11 Oct 2006 14:04:18 +0000 (14:04 +0000)
committerGerd v. Egidy <gerd.von.egidy@intra2net.com>
Wed, 11 Oct 2006 14:04:18 +0000 (14:04 +0000)
13 files changed:
Makefile.am
configure.in
libt2n.kdevelop
src/connection.hxx
src/socket_client.hxx
src/socket_handler.cpp
src/socket_server.cpp
src/socket_server.hxx
test/Makefile.am
test/client.cpp [deleted file]
test/comm.cpp [new file with mode: 0644]
test/server.cpp [deleted file]
test/test.cpp [new file with mode: 0644]

index 1154b0a..f9360eb 100644 (file)
@@ -9,3 +9,9 @@ pkgconfigdir = $(libdir)/pkgconfig
 pkgconfig_DATA = libt2n.pc
 
 EXRA_DIST = COPYING COPYING.LIB
+
+if AUTOCHECK
+all: config.h
+       $(MAKE) $(AM_MAKEFLAGS) all-recursive
+       $(MAKE) $(AM_MAKEFLAGS) check
+endif
index 72e3e45..b7d9353 100644 (file)
@@ -11,4 +11,7 @@ dnl check for doxygen
 AC_PATH_PROG(DOXYGEN, doxygen, $PATH)
 AM_CONDITIONAL(HAVE_DOXYGEN, test -n $DOXYGEN);
 
+AM_CONDITIONAL(AUTOCHECK, test "$enable_autocheck" = yes)
+AM_PATH_CPPUNIT(1.8.0)
+
 AC_OUTPUT(Makefile doc/Doxyfile doc/Makefile src/Makefile libt2n.pc libt2n.spec test/Makefile)
index 0faf98a..7024d3f 100644 (file)
   </general>
   <kdevautoproject>
     <general>
-      <activetarget>src/libt2n.la</activetarget>
+      <activetarget>test/server</activetarget>
       <useconfiguration>debug</useconfiguration>
     </general>
     <run>
       <mainprogram>src/libt2n</mainprogram>
       <terminal>true</terminal>
       <directoryradio>executable</directoryradio>
+      <runarguments>
+        <client></client>
+        <server></server>
+        <test></test>
+      </runarguments>
     </run>
     <configurations>
       <optimized>
index 9142c52..94506e2 100644 (file)
@@ -42,7 +42,7 @@ class connection
         virtual void real_write(const std::string& data)=0;
 
     public:
-        ~connection()
+        virtual ~connection()
             { close(); }
 
         bool is_closed()
@@ -51,7 +51,7 @@ class connection
         virtual void close()
             { closed=true; }
 
-        virtual void fill_buffer(long long usec_timeout=-1)=0;
+        virtual bool fill_buffer(long long usec_timeout=-1)=0;
         bool get_packet(std::string& data);
         bool packet_available()
             { return bytes_available(); }
index 198e1a7..a17ec88 100644 (file)
@@ -45,8 +45,8 @@ class socket_client_connection : public client_connection, public socket_handler
         socket_client_connection(const std::string& _server, int _port, int _max_retries=max_retries_default);
         socket_client_connection(const std::string& _path, int _max_retries=max_retries_default);
 
-        void fill_buffer(long long usec_timeout=-1)
-            { socket_handler::fill_buffer(buffer,usec_timeout); }
+        bool fill_buffer(long long usec_timeout=-1)
+            { return socket_handler::fill_buffer(buffer,usec_timeout); }
 
         void close();
 };
index 6f9df07..f2ddcb6 100644 (file)
@@ -149,8 +149,8 @@ bool socket_handler::data_waiting(long long usec_timeout)
 
 bool socket_handler::fill_buffer(std::string& buffer, long long usec_timeout)
 {
-    // fast path for timeout==-1
-    if (usec_timeout==-1 || data_waiting(usec_timeout))
+    // fast path for timeout==0
+    if (usec_timeout==0 || data_waiting(usec_timeout))
         return fill_buffer(buffer);
     else
         return false;
@@ -192,7 +192,7 @@ bool socket_handler::fill_buffer(std::string& buffer)
         buffer.assign(socket_buffer,nbytes);
 
     // more data waiting -> recurse
-    if (data_waiting())
+    if (data_waiting(0))
         fill_buffer(buffer);
 
     if (nbytes > 0)
index 372960a..cbaaff6 100644 (file)
@@ -233,7 +233,7 @@ void socket_server::fill_connection_buffers()
     std::map<unsigned int, server_connection*>::iterator ie=connections.end();
     for(std::map<unsigned int, server_connection*>::iterator i=connections.begin(); i != ie; i++)
         if (!i->second->server_connection::is_closed())
-            i->second->fill_buffer();
+            i->second->fill_buffer(0);
 }
 
 void socket_server::remove_connection_socket(int sock)
index a9c7b3d..5dcf4f3 100644 (file)
@@ -76,8 +76,8 @@ class socket_server_connection : public socket_handler, public server_connection
             { socket_write(data); }
 
     public:
-        void fill_buffer(long long usec_timeout=-1)
-            { socket_handler::fill_buffer(buffer,usec_timeout); }
+        bool fill_buffer(long long usec_timeout=-1)
+            { return socket_handler::fill_buffer(buffer,usec_timeout); }
 
         void close();
 };
index ec58406..a7a5515 100644 (file)
@@ -1,7 +1,8 @@
-INCLUDES = -I$(top_srcdir)/src
+INCLUDES = -I$(top_srcdir)/src @CPPUNIT_CFLAGS@
 METASOURCES = AUTO
-bin_PROGRAMS = client server
-client_SOURCES = client.cpp
-client_LDADD = $(top_builddir)/src/libt2n.la
-server_LDADD = $(top_builddir)/src/libt2n.la
-server_SOURCES = server.cpp
+check_PROGRAMS = test
+
+test_LDADD = $(top_builddir)/src/libt2n.la @CPPUNIT_LIBS@
+test_SOURCES = test.cpp comm.cpp
+
+TESTS = test
diff --git a/test/client.cpp b/test/client.cpp
deleted file mode 100644 (file)
index 5d71291..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-/***************************************************************************
- *   Copyright (C) 2006 by Gerd v. Egidy                                   *
- *   gve@intra2net.com                                                     *
- *                                                                         *
- *   This library is free software; you can redistribute it and/or modify  *
- *   it under the terms of the GNU Lesser General Public License version   *
- *   2.1 as published by the Free Software Foundation.                     *
- *                                                                         *
- *   This library is distributed in the hope that it will be useful,       *
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
- *   GNU Lesser General Public License for more details.                   *
- *                                                                         *
- *   You should have received a copy of the GNU Lesser General Public      *
- *   License along with this program; if not, write to the                 *
- *   Free Software Foundation, Inc.,                                       *
- *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
- ***************************************************************************/
-
-#include <iostream>
-
-#include <socket_client.hxx>
-
-using namespace std;
-using namespace libt2n;
-
-int main()
-{
-    socket_client_connection sc("./socket");
-
-    sc.write("hallo");
-
-    return 0;
-}
diff --git a/test/comm.cpp b/test/comm.cpp
new file mode 100644 (file)
index 0000000..60907b2
--- /dev/null
@@ -0,0 +1,159 @@
+/***************************************************************************
+ *   Copyright (C) 2004 by Intra2net AG                                    *
+ *   info@intra2net.com                                                    *
+ *                                                                         *
+ ***************************************************************************/
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <errno.h>
+#include <signal.h>
+#include <stdio.h>
+
+#include <iostream>
+#include <string>
+#include <sstream>
+#include <stdexcept>
+
+#include <cppunit/extensions/TestFactoryRegistry.h>
+#include <cppunit/ui/text/TestRunner.h>
+#include <cppunit/extensions/HelperMacros.h>
+
+#include <socket_client.hxx>
+#include <socket_server.hxx>
+
+using namespace std;
+using namespace libt2n;
+using namespace CppUnit;
+
+class test_comm : public TestFixture
+{
+    CPPUNIT_TEST_SUITE(test_comm);
+
+    CPPUNIT_TEST(UnixCommToServer);
+    CPPUNIT_TEST(UnixCommToServerAndBack);
+
+    CPPUNIT_TEST_SUITE_END();
+
+    public:
+
+    void setUp()
+    { }
+
+    void tearDown()
+    { }
+
+    void UnixCommToServer()
+    {
+        pid_t pid;
+        string data;
+
+        switch(pid=fork())
+        {
+            case -1:
+            {
+                CPPUNIT_FAIL("fork error");
+                break;
+            }
+            case 0:
+            // child
+            {
+                // wait till server is up
+                sleep(1);
+                socket_client_connection sc("./socket");
+                sc.write("hello");
+                // don't call atexit and stuff
+                _exit(0);
+            }
+
+            default:
+            // parent
+            {
+                socket_server ss("./socket");
+
+                // max 10 sec
+                for (int i=0; i < 10; i++)
+                {
+                    ss.fill_buffer(1000000);
+
+                    if(ss.get_packet(data))
+                        break;
+                }
+            }
+        }
+        CPPUNIT_ASSERT_EQUAL(string("hello"),data);
+    }
+
+    void UnixCommToServerAndBack()
+    {
+        pid_t pid;
+
+        switch(pid=fork())
+        {
+            case -1:
+            {
+                CPPUNIT_FAIL("fork error");
+                break;
+            }
+            case 0:
+            // child
+            {
+                socket_server ss("./socket");
+                ss.set_logging(&cerr,debug);
+
+                // max 10 sec
+                for (int i=0; i < 10; i++)
+                {
+                    ss.fill_buffer(1000000);
+
+                    string data;
+                    unsigned int cid;
+
+                    if(ss.get_packet(data,cid))
+                    {
+                        server_connection* con=ss.get_connection(cid);
+
+                        if (data=="QUIT")
+                            break;
+
+                        if (data=="ABC")
+                            con->write("DEF");
+                        else
+                            con->write("xyz");
+                    }
+                }
+                // don't call atexit and stuff
+                _exit(0);
+            }
+
+            default:
+            // parent
+            {
+                string data;
+
+                // wait till server is up
+                sleep(1);
+                socket_client_connection sc("./socket");
+
+                sc.write("ABC");
+
+                sc.fill_buffer(1000000);
+                sc.get_packet(data);
+
+                CPPUNIT_ASSERT_EQUAL(string("DEF"),data);
+
+                sc.write("HAHA");
+
+                sc.fill_buffer(1000000);
+                sc.get_packet(data);
+
+                CPPUNIT_ASSERT_EQUAL(string("xyz"),data);
+
+                sc.write("QUIT");
+            }
+        }
+    }
+
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION(test_comm);
diff --git a/test/server.cpp b/test/server.cpp
deleted file mode 100644 (file)
index f5a0349..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-/***************************************************************************
- *   Copyright (C) 2006 by Gerd v. Egidy                                   *
- *   gve@intra2net.com                                                     *
- *                                                                         *
- *   This library is free software; you can redistribute it and/or modify  *
- *   it under the terms of the GNU Lesser General Public License version   *
- *   2.1 as published by the Free Software Foundation.                     *
- *                                                                         *
- *   This library is distributed in the hope that it will be useful,       *
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
- *   GNU Lesser General Public License for more details.                   *
- *                                                                         *
- *   You should have received a copy of the GNU Lesser General Public      *
- *   License along with this program; if not, write to the                 *
- *   Free Software Foundation, Inc.,                                       *
- *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
- ***************************************************************************/
-
-#include <socket_server.hxx>
-
-using namespace std;
-using namespace libt2n;
-
-int main()
-{
-    socket_server ss("./socket");
-
-    while(true)
-    {
-        ss.fill_buffer(1000000);
-
-        unsigned int cid;
-        string data;
-
-        while(ss.get_packet(data,cid))
-            cout << "conn " << cid << ": " << data << endl;
-    }
-
-    return 0;
-}
diff --git a/test/test.cpp b/test/test.cpp
new file mode 100644 (file)
index 0000000..4451c48
--- /dev/null
@@ -0,0 +1,84 @@
+/***************************************************************************
+ *   Copyright (C) 2004 by Intra2net AG                                    *
+ *   info@intra2net.com                                                    *
+ *                                                                         *
+ ***************************************************************************/
+
+#include <iostream>
+#include <iomanip>
+#include <string>
+
+#include <time.h>
+#include <sys/timeb.h>
+
+#include <cppunit/extensions/TestFactoryRegistry.h>
+#include <cppunit/ui/text/TestRunner.h>
+#include <cppunit/TestListener.h>
+#include <cppunit/TestFailure.h> 
+#include <cppunit/TestResult.h> 
+#include <cppunit/CompilerOutputter.h> 
+
+class VerboseTimingListener : public CppUnit::TestListener
+{
+    private:
+        double start_time;
+        std::string resultstr;
+
+        double get_time(void)
+        {
+            struct timeb tb;
+            ftime(&tb);
+            return tb.time+(static_cast<float>(tb.millitm)/1000);
+        }
+    
+    public:
+   
+        void startTest( CppUnit::Test *test )
+        {
+            resultstr="OK";
+            std::cout << test->getName() << ": ";
+            start_time=get_time();
+        }
+    
+        void endTest( CppUnit::Test *test )
+        {
+            double timediff=get_time()-start_time;
+            
+            // fix clock unpreciseness for small timespans
+            if (timediff < 0) timediff=0;
+            
+            std::cout << resultstr << " (" 
+                      << std::fixed << std::setprecision(3) 
+                      << timediff << " sec)" << std::endl;
+        }
+
+        void addFailure(const CppUnit::TestFailure &failure)
+        {
+            if(failure.isError())
+                resultstr="ERROR";
+            else
+                resultstr="FAIL";
+        }
+};
+int main(int argc, char **argv)
+{
+    CppUnit::TextTestRunner runner;
+    CppUnit::TestFactoryRegistry &registry = CppUnit::TestFactoryRegistry::getRegistry();
+    
+    // set output format that KDevelop can catch errors
+    CppUnit::CompilerOutputter *op=CppUnit::CompilerOutputter::defaultOutputter(&runner.result(),std::cout);
+    op->setLocationFormat("%p:%l: error: ");
+    runner.setOutputter(op);
+
+    // show every test with timing
+    VerboseTimingListener listener;        
+    runner.eventManager().addListener(&listener); 
+    
+    runner.addTest(registry.makeTest());
+    
+    // run all tests in registry (not using the default progress listener)
+    bool wasSucessful = runner.run("",false,true,false);
+    
+    return (wasSucessful ? 0 : 1);
+}