* start out a unit test for our buffered I/O; copy bind/accept/select stuff from...
authorWilfried Göesgens <willi@citadel.org>
Sat, 3 Oct 2009 11:45:22 +0000 (11:45 +0000)
committerWilfried Göesgens <willi@citadel.org>
Sat, 3 Oct 2009 11:45:22 +0000 (11:45 +0000)
libcitadel/tests/Makefile.in
libcitadel/tests/stringbuf_IO_test.c [new file with mode: 0644]

index e222bd0b358ea9151d044d45e0e6d57771fca794..7d24aaa9365c65b382ace78999af1b43ad2f4cb8 100644 (file)
@@ -16,7 +16,7 @@ top_builddir=`pwd`
 
 # End of configuration section
 
-TARGETS=stringbuf_test 
+TARGETS=stringbuf_test stringbuf_IO_test
 all: $(TARGETS)
 
 
@@ -36,6 +36,12 @@ stringbuf_test:      $(LIBOBJS) stringbuf_test.o
        -o stringbuf_test \
        $(LIBS)
 
+stringbuf_IO_test:     $(LIBOBJS) stringbuf_IO_test.o 
+       $(CC) $(LDFLAGS) $(LIBOBJS) $(LIBS) \
+       stringbuf_IO_test.o \
+       -o stringbuf_io_test \
+       $(LIBS)
+
 .c.o:
        $(CC) $(CFLAGS) $(DEFS) -c  $<
 
diff --git a/libcitadel/tests/stringbuf_IO_test.c b/libcitadel/tests/stringbuf_IO_test.c
new file mode 100644 (file)
index 0000000..1097b96
--- /dev/null
@@ -0,0 +1,355 @@
+
+/*
+ *  CUnit - A Unit testing framework library for C.
+ *  Copyright (C) 2001  Anil Kumar
+ *  
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Library General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  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
+ *  Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <sys/select.h>
+
+#include <ctype.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <limits.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/un.h>
+#include <netdb.h>
+#include <sys/poll.h>
+#include <string.h>
+#include <pwd.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <pthread.h>
+#include <signal.h>
+#include <sys/utsname.h>
+
+
+typedef void testfunc(int Sock);
+
+#define LISTEN_QUEUE_LENGTH 100
+#include <string.h>
+
+#include "stringbuf_test.h"
+#include "../lib/libcitadel.h"
+
+int msock;                     /* master listening socket */
+int BindPort;
+int time_to_die=0;
+int listen_port=6666;
+int n_Lines_to_read = 0;
+int blobsize = 0;
+int timeout = 5;
+int selres = 1;
+char ip_addr[256]="0.0.0.0";
+
+
+static void TestRevalidateStrBuf(StrBuf *Buf)
+{
+       CU_ASSERT(strlen(ChrPtr(Buf)) == StrLength(Buf));
+}
+
+/* 
+ * This is a generic function to set up a master socket for listening on
+ * a TCP port.  The server shuts down if the bind fails.
+ *
+ * ip_addr     IP address to bind
+ * port_number port number to bind
+ * queue_len   number of incoming connections to allow in the queue
+ */
+static int ig_tcp_server(char *ip_addr, int port_number, int queue_len)
+{
+       struct protoent *p;
+       struct sockaddr_in sin;
+       int s, i;
+
+       memset(&sin, 0, sizeof(sin));
+       sin.sin_family = AF_INET;
+       if (ip_addr == NULL) {
+               sin.sin_addr.s_addr = INADDR_ANY;
+       } else {
+               sin.sin_addr.s_addr = inet_addr(ip_addr);
+       }
+
+       if (sin.sin_addr.s_addr == INADDR_NONE) {
+               sin.sin_addr.s_addr = INADDR_ANY;
+       }
+
+       if (port_number == 0) {
+               printf("Cannot start: no port number specified.\n");
+               return (-1);
+       }
+       sin.sin_port = htons((u_short) port_number);
+
+       p = getprotobyname("tcp");
+
+       s = socket(PF_INET, SOCK_STREAM, (p->p_proto));
+       if (s < 0) {
+               printf("Can't create a socket: %s\n", strerror(errno));
+               return (-2);
+       }
+       /* Set some socket options that make sense. */
+       i = 1;
+       setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i));
+
+       #ifndef __APPLE__
+       fcntl(s, F_SETFL, O_NONBLOCK); /* maide: this statement is incorrect
+                                         there should be a preceding F_GETFL
+                                         and a bitwise OR with the previous
+                                         fd flags */
+       #endif
+       
+       if (bind(s, (struct sockaddr *) &sin, sizeof(sin)) < 0) {
+               printf("Can't bind: %s\n", strerror(errno));
+               return (-3);
+       }
+       if (listen(s, queue_len) < 0) {
+               printf("Can't listen: %s\n", strerror(errno));
+               return (-4);
+       }
+       return (s);
+}
+
+
+
+/*
+ * Entry point for worker threads
+ */
+static void worker_entry(testfunc F)
+{
+       int ssock;
+       int i = 0;
+       int fail_this_transaction = 0;
+       int ret;
+       struct timeval tv;
+       fd_set readset, tempset;
+
+       
+       tv.tv_sec = 0;
+       tv.tv_usec = 10000;
+       FD_ZERO(&readset);
+       FD_SET(msock, &readset);
+
+       do {
+               /* Only one thread can accept at a time */
+               fail_this_transaction = 0;
+               ssock = -1; 
+               errno = EAGAIN;
+               do {
+                       ret = -1; /* just one at once should select... */
+                       
+                       FD_ZERO(&tempset);
+                       if (msock > 0) FD_SET(msock, &tempset);
+                       tv.tv_sec = 0;
+                       tv.tv_usec = 10000;
+                       if (msock > 0)  
+                               ret = select(msock+1, &tempset, NULL, NULL,  &tv);
+                       if ((ret < 0) && (errno != EINTR) && (errno != EAGAIN))
+                       {/* EINTR and EAGAIN are thrown but not of interest. */
+                               printf("accept() failed:%d %s\n",
+                                       errno, strerror(errno));
+                       }
+                       else if ((ret > 0) && (msock > 0) && FD_ISSET(msock, &tempset))
+                       {/* Successfully selected, and still not shutting down? Accept! */
+                               ssock = accept(msock, NULL, 0);
+                       }
+                       
+               } while ((msock > 0) && (ssock < 0)  && (time_to_die == 0));
+
+               if ((msock == -1)||(time_to_die))
+               {/* ok, we're going down. */
+                       exit(0);
+               }
+               if (ssock < 0 ) continue;
+
+               if (msock < 0) {
+                       if (ssock > 0) close (ssock);
+                       printf( "inbetween.");
+                       return;
+               } else { /* Got it? do some real work! */
+                       /* Set the SO_REUSEADDR socket option */
+                       int fdflags; 
+                       i = 1;
+                       setsockopt(ssock, SOL_SOCKET, SO_REUSEADDR,
+                                  &i, sizeof(i));
+
+                       fdflags = fcntl(ssock, F_GETFL);
+                       if (fdflags < 0)
+                               printf("unable to get server socket flags! %s \n",
+                                       strerror(errno));
+                       fdflags = fdflags | O_NONBLOCK;
+                       if (fcntl(ssock, F_SETFL, fdflags) < 0)
+                               printf("unable to set server socket nonblocking flags! %s \n",
+                                       strerror(errno));
+
+
+                       F(ssock);
+               }
+
+       } while (!time_to_die);
+       printf ("bye\n");
+}
+
+
+static void SimpleLineBufTestFunc(int sock)
+{
+       StrBuf *ReadBuffer;
+       StrBuf *Line;
+       const char *Pos = NULL;
+       const char *err;
+       int i;
+
+       ReadBuffer = NewStrBuf();
+       Line = NewStrBuf();
+
+       for (i = 0; i < n_Lines_to_read; i++) {
+               StrBufTCP_read_buffered_line_fast(Line, 
+                                                 ReadBuffer, 
+                                                 &Pos,
+                                                 &sock,
+                                                 timeout,
+                                                 selres,
+                                                 &err);
+               if (err != NULL)
+                       printf("%s", err);
+               CU_ASSERT_PTR_NOT_NULL(err);
+               CU_ASSERT_NOT_EQUAL(sock, -1);
+               if (sock == -1)
+                       break;
+               printf("LINE: >%s<\n", ChrPtr(Line));
+       }
+       FreeStrBuf(&ReadBuffer);
+       FreeStrBuf(&Line);
+       time_to_die = 1;
+}
+
+
+static void SimpleLinebufferTest(void)
+{
+       msock = ig_tcp_server(ip_addr, listen_port, LISTEN_QUEUE_LENGTH);
+
+       worker_entry(SimpleLineBufTestFunc);
+}
+
+/*
+Some samples from the original...
+       CU_ASSERT_EQUAL(10, 10);
+       CU_ASSERT_EQUAL(0, -0);
+       CU_ASSERT_EQUAL(-12, -12);
+       CU_ASSERT_NOT_EQUAL(10, 11);
+       CU_ASSERT_NOT_EQUAL(0, -1);
+       CU_ASSERT_NOT_EQUAL(-12, -11);
+       CU_ASSERT_PTR_EQUAL((void*)0x100, (void*)0x100);
+       CU_ASSERT_PTR_NOT_EQUAL((void*)0x100, (void*)0x101);
+       CU_ASSERT_PTR_NULL(NULL);
+       CU_ASSERT_PTR_NULL(0x0);
+       CU_ASSERT_PTR_NOT_NULL((void*)0x23);
+       CU_ASSERT_STRING_EQUAL(str1, str2);
+       CU_ASSERT_STRING_NOT_EQUAL(str1, str2);
+       CU_ASSERT_NSTRING_EQUAL(str1, str2, strlen(str1));
+       CU_ASSERT_NSTRING_EQUAL(str1, str1, strlen(str1));
+       CU_ASSERT_NSTRING_EQUAL(str1, str1, strlen(str1) + 1);
+       CU_ASSERT_NSTRING_NOT_EQUAL(str1, str2, 3);
+       CU_ASSERT_NSTRING_NOT_EQUAL(str1, str3, strlen(str1) + 1);
+       CU_ASSERT_DOUBLE_EQUAL(10, 10.0001, 0.0001);
+       CU_ASSERT_DOUBLE_EQUAL(10, 10.0001, -0.0001);
+       CU_ASSERT_DOUBLE_EQUAL(-10, -10.0001, 0.0001);
+       CU_ASSERT_DOUBLE_EQUAL(-10, -10.0001, -0.0001);
+       CU_ASSERT_DOUBLE_NOT_EQUAL(10, 10.001, 0.0001);
+       CU_ASSERT_DOUBLE_NOT_EQUAL(10, 10.001, -0.0001);
+       CU_ASSERT_DOUBLE_NOT_EQUAL(-10, -10.001, 0.0001);
+       CU_ASSERT_DOUBLE_NOT_EQUAL(-10, -10.001, -0.0001);
+*/
+
+
+
+
+
+static void AddStrBufSimlpeTests(void)
+{
+       CU_pSuite pGroup = NULL;
+       CU_pTest pTest = NULL;
+
+       pGroup = CU_add_suite("TestStringBufSimpleAppenders", NULL, NULL);
+       pTest = CU_add_test(pGroup, "testSimpleLinebufferTest", SimpleLinebufferTest);
+
+
+}
+
+
+int main(int argc, char* argv[])
+{
+       char a;
+       setvbuf(stdout, NULL, _IONBF, 0);
+
+
+       while ((a = getopt(argc, argv, "p:i:n:b:t:s")) != EOF)
+       {
+               switch (a) {
+
+               case 'p':
+                       listen_port = atoi(optarg);
+                       break;
+               case 'i':
+                       safestrncpy(ip_addr, optarg, sizeof ip_addr);
+                       break;
+               case 'n':
+                       n_Lines_to_read = atoi(optarg);
+                       break;
+               case 'b':
+                       blobsize = atoi(optarg);
+                       break;
+               case 't':
+                       timeout = atoi(optarg);
+                       break;
+               case 's':
+                       selres = atoi(optarg);
+                       break;
+               }
+       }
+
+
+       StartLibCitadel(8);
+       CU_BOOL Run = CU_FALSE ;
+       
+       CU_set_output_filename("TestAutomated");
+       if (CU_initialize_registry()) {
+               printf("\nInitialize of test Registry failed.");
+       }
+       
+       Run = CU_TRUE ;
+       AddStrBufSimlpeTests();
+       
+       if (CU_TRUE == Run) {
+               //CU_console_run_tests();
+    printf("\nTests completed with return value %d.\n", CU_basic_run_tests());
+    
+    ///CU_automated_run_tests();
+       }
+       
+       CU_cleanup_registry();
+
+       return 0;
+}