Back to index

libcitadel  8.12
stringbuf_IO_test.c
Go to the documentation of this file.
00001 /*
00002  *  CUnit - A Unit testing framework library for C.
00003  *  Copyright (C) 2001  Anil Kumar
00004  *  
00005  *  This library is open source software; you can redistribute it and/or
00006  *  modify it under the terms of the GNU Library General Public
00007  *  License as published by the Free Software Foundation; either
00008  *  version 2 of the License, or (at your option) any later version.
00009  *
00010  *  This library is distributed in the hope that it will be useful,
00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013  *  Library General Public License for more details.
00014  */
00015 
00016 #include <stdio.h>
00017 #include <stdlib.h>
00018 
00019 #include <sys/select.h>
00020 
00021 #include <ctype.h>
00022 #include <unistd.h>
00023 #include <fcntl.h>
00024 #include <signal.h>
00025 #include <sys/types.h>
00026 #include <sys/wait.h>
00027 #include <sys/socket.h>
00028 #include <sys/time.h>
00029 #include <sys/stat.h>
00030 #include <limits.h>
00031 #include <netinet/in.h>
00032 #include <arpa/inet.h>
00033 #include <sys/un.h>
00034 #include <netdb.h>
00035 #include <sys/poll.h>
00036 #include <string.h>
00037 #include <pwd.h>
00038 #include <errno.h>
00039 #include <stdarg.h>
00040 #include <pthread.h>
00041 #include <signal.h>
00042 #include <sys/utsname.h>
00043 #include <string.h>
00044 
00045 
00046 typedef void testfunc(int Sock);
00047 
00048 #define LISTEN_QUEUE_LENGTH 100
00049 #include <string.h>
00050 
00051 #include "stringbuf_test.h"
00052 #include "../lib/libcitadel.h"
00053 
00054 int msock;                  /* master listening socket */
00055 int BindPort;
00056 int time_to_die=0;
00057 int listen_port=6666;
00058 int n_Lines_to_read = 0;
00059 int blobsize = 0;
00060 int timeout = 5;
00061 int selres = 1;
00062 char ip_addr[256]="0.0.0.0";
00063 
00064 
00065 static void TestRevalidateStrBuf(StrBuf *Buf)
00066 {
00067        CU_ASSERT(strlen(ChrPtr(Buf)) == StrLength(Buf));
00068 }
00069 
00070 /* 
00071  * This is a generic function to set up a master socket for listening on
00072  * a TCP port.  The server shuts down if the bind fails.
00073  *
00074  * ip_addr    IP address to bind
00075  * port_number       port number to bind
00076  * queue_len  number of incoming connections to allow in the queue
00077  */
00078 static int ig_tcp_server(char *ip_addr, int port_number, int queue_len)
00079 {
00080        struct protoent *p;
00081        struct sockaddr_in sin;
00082        int s, i;
00083 
00084        memset(&sin, 0, sizeof(sin));
00085        sin.sin_family = AF_INET;
00086        if (ip_addr == NULL) {
00087               sin.sin_addr.s_addr = INADDR_ANY;
00088        } else {
00089               sin.sin_addr.s_addr = inet_addr(ip_addr);
00090        }
00091 
00092        if (sin.sin_addr.s_addr == INADDR_NONE) {
00093               sin.sin_addr.s_addr = INADDR_ANY;
00094        }
00095 
00096        if (port_number == 0) {
00097               printf("Cannot start: no port number specified.\n");
00098               return (-1);
00099        }
00100        sin.sin_port = htons((u_short) port_number);
00101 
00102        p = getprotobyname("tcp");
00103 
00104        s = socket(PF_INET, SOCK_STREAM, (p->p_proto));
00105        if (s < 0) {
00106               printf("Can't create a socket: %s\n", strerror(errno));
00107               return (-2);
00108        }
00109        /* Set some socket options that make sense. */
00110        i = 1;
00111        setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i));
00112 
00113        #ifndef __APPLE__
00114        fcntl(s, F_SETFL, O_NONBLOCK); /* maide: this statement is incorrect
00115                                      there should be a preceding F_GETFL
00116                                      and a bitwise OR with the previous
00117                                      fd flags */
00118        #endif
00119        
00120        if (bind(s, (struct sockaddr *) &sin, sizeof(sin)) < 0) {
00121               printf("Can't bind: %s\n", strerror(errno));
00122               return (-3);
00123        }
00124        if (listen(s, queue_len) < 0) {
00125               printf("Can't listen: %s\n", strerror(errno));
00126               return (-4);
00127        }
00128        return (s);
00129 }
00130 
00131 
00132 
00133 /*
00134  * Entry point for worker threads
00135  */
00136 static void worker_entry(testfunc F)
00137 {
00138        int ssock;
00139        int i = 0;
00140        int fail_this_transaction = 0;
00141        int ret;
00142        struct timeval tv;
00143        fd_set readset, tempset;
00144 
00145        
00146        tv.tv_sec = 0;
00147        tv.tv_usec = 10000;
00148        FD_ZERO(&readset);
00149        FD_SET(msock, &readset);
00150 
00151        do {
00152               /* Only one thread can accept at a time */
00153               fail_this_transaction = 0;
00154               ssock = -1; 
00155               errno = EAGAIN;
00156               do {
00157                      ret = -1; /* just one at once should select... */
00158                      
00159                      FD_ZERO(&tempset);
00160                      if (msock > 0) FD_SET(msock, &tempset);
00161                      tv.tv_sec = 0;
00162                      tv.tv_usec = 10000;
00163                      if (msock > 0)       
00164                             ret = select(msock+1, &tempset, NULL, NULL,  &tv);
00165                      if ((ret < 0) && (errno != EINTR) && (errno != EAGAIN))
00166                      {/* EINTR and EAGAIN are thrown but not of interest. */
00167                             printf("accept() failed:%d %s\n",
00168                                    errno, strerror(errno));
00169                      }
00170                      else if ((ret > 0) && (msock > 0) && FD_ISSET(msock, &tempset))
00171                      {/* Successfully selected, and still not shutting down? Accept! */
00172                             ssock = accept(msock, NULL, 0);
00173                      }
00174                      
00175               } while ((msock > 0) && (ssock < 0)  && (time_to_die == 0));
00176 
00177               if ((msock == -1)||(time_to_die))
00178               {/* ok, we're going down. */
00179                      return;
00180               }
00181               if (ssock < 0 ) continue;
00182 
00183               if (msock < 0) {
00184                      if (ssock > 0) close (ssock);
00185                      printf( "inbetween.");
00186                      return;
00187               } else { /* Got it? do some real work! */
00188                      /* Set the SO_REUSEADDR socket option */
00189                      int fdflags; 
00190                      i = 1;
00191                      setsockopt(ssock, SOL_SOCKET, SO_REUSEADDR,
00192                                &i, sizeof(i));
00193 
00194                      fdflags = fcntl(ssock, F_GETFL);
00195                      if (fdflags < 0)
00196                             printf("unable to get server socket flags! %s \n",
00197                                    strerror(errno));
00198                      fdflags = fdflags | O_NONBLOCK;
00199                      if (fcntl(ssock, F_SETFL, fdflags) < 0)
00200                             printf("unable to set server socket nonblocking flags! %s \n",
00201                                    strerror(errno));
00202 
00203 
00204                      F(ssock);
00205               }
00206 
00207        } while (!time_to_die);
00208        printf ("bye\n");
00209 }
00210 
00211 
00212 static void SimpleLineBufTestFunc(int sock)
00213 {
00214        StrBuf *ReadBuffer;
00215        StrBuf *Line;
00216        const char *Pos = NULL;
00217        const char *err = NULL;
00218        int i;
00219 
00220        ReadBuffer = NewStrBuf();
00221        Line = NewStrBuf();
00222 
00223        for (i = 0; i < n_Lines_to_read; i++) {
00224               StrBufTCP_read_buffered_line_fast(Line, 
00225                                             ReadBuffer, 
00226                                             &Pos,
00227                                             &sock,
00228                                             timeout,
00229                                             selres,
00230                                             &err);
00231               TestRevalidateStrBuf(Line);
00232               if (err != NULL)
00233                      printf("%s", err);
00234               CU_ASSERT_PTR_NULL(err);
00235               CU_ASSERT_NOT_EQUAL(sock, -1);
00236               if (sock == -1)
00237                      break;
00238               printf("LINE: >%s<\n", ChrPtr(Line));
00239        }
00240        FreeStrBuf(&ReadBuffer);
00241        FreeStrBuf(&Line);
00242        time_to_die = 1;
00243 }
00244 
00245 static void SimpleLinebufferTest(void)
00246 {
00247        msock = ig_tcp_server(ip_addr, listen_port, LISTEN_QUEUE_LENGTH);
00248 
00249        worker_entry(SimpleLineBufTestFunc);
00250        close (msock);
00251 }
00252 
00253 
00254 static void SimpleBlobTestFunc(int sock)
00255 {
00256        StrBuf *ReadBuffer;
00257        StrBuf *Blob;
00258        const char *Pos = NULL;
00259        const char *err = NULL;
00260        
00261        ReadBuffer = NewStrBuf();
00262        Blob = NewStrBuf();
00263 
00264        StrBufReadBLOBBuffered(Blob, 
00265                             ReadBuffer, 
00266                             &Pos,
00267                             &sock,
00268                             0,
00269                             blobsize,
00270                             0,
00271                             &err);
00272        TestRevalidateStrBuf(Blob);
00273        if (err != NULL)
00274               printf("%s", err);
00275        CU_ASSERT(blobsize == StrLength(Blob));
00276        CU_ASSERT_PTR_NULL(err);
00277        CU_ASSERT_NOT_EQUAL(sock, -1);
00278        if (sock == -1)
00279        printf("BLOB: >%s<\n", ChrPtr(Blob));
00280        
00281        FreeStrBuf(&ReadBuffer);
00282        FreeStrBuf(&Blob);
00283        time_to_die = 1;
00284 }
00285 
00286 
00287 static void SimpleHttpPostTestFunc(int sock)
00288 {
00289        StrBuf *ReadBuffer;
00290        StrBuf *Blob;
00291        StrBuf *Line;
00292        const char *Pos = NULL;
00293        const char *err = NULL;
00294        int blobsize = 0;
00295        int i;
00296        const char *pch;
00297        
00298        ReadBuffer = NewStrBuf();
00299        Blob = NewStrBuf();
00300        Line = NewStrBuf();
00301 
00302        for (i = 0; 1; i++) {
00303               StrBufTCP_read_buffered_line_fast(Line, 
00304                                             ReadBuffer, 
00305                                             &Pos,
00306                                             &sock,
00307                                             timeout,
00308                                             selres,
00309                                             &err);
00310               TestRevalidateStrBuf(Line);
00311               if (err != NULL)
00312                      printf("%s", err);
00313               CU_ASSERT_PTR_NULL(err);
00314               CU_ASSERT_NOT_EQUAL(sock, -1);
00315               if (sock == -1)
00316                      break;
00317               printf("LINE: >%s<\n", ChrPtr(Line));
00318               pch = strstr(ChrPtr(Line), "Content-Length");
00319               if (pch != NULL) {
00320                      blobsize = atol(ChrPtr(Line) + 
00321                                    sizeof("Content-Length:"));
00322 
00323               }
00324               if (StrLength(Line) == 0)
00325                      break;
00326               FlushStrBuf(Line);
00327        }
00328 
00329        StrBufReadBLOBBuffered(Blob, 
00330                             ReadBuffer, 
00331                             &Pos,
00332                             &sock,
00333                             0,
00334                             blobsize,
00335                             0,
00336                             &err);
00337        TestRevalidateStrBuf(Blob);
00338        if (err != NULL)
00339               printf("%s", err);
00340        printf("Blob said/read: %d / %d\n", blobsize, StrLength(Blob));
00341        CU_ASSERT(blobsize != 0);
00342        CU_ASSERT(blobsize == StrLength(Blob));
00343        CU_ASSERT_PTR_NULL(err);
00344        CU_ASSERT_NOT_EQUAL(sock, -1);
00345        if (sock == -1)
00346        printf("BLOB: >%s<\n", ChrPtr(Blob));
00347        
00348        FreeStrBuf(&ReadBuffer);
00349        FreeStrBuf(&Blob);
00350        FreeStrBuf(&Line);
00351        time_to_die = 1;
00352 }
00353 
00354 
00355 static void SimpleBLOBbufferTest(void)
00356 {
00357        msock = ig_tcp_server(ip_addr, listen_port, LISTEN_QUEUE_LENGTH);
00358 
00359        worker_entry(SimpleBlobTestFunc);
00360        close (msock);
00361 }
00362 
00363 static void SimpleMixedLineBlob(void)
00364 {
00365        msock = ig_tcp_server(ip_addr, listen_port, LISTEN_QUEUE_LENGTH);
00366 
00367        worker_entry(SimpleHttpPostTestFunc);
00368        close (msock);
00369 }
00370 
00371 
00372 
00373 
00374 
00375 /*
00376 Some samples from the original...
00377        CU_ASSERT_EQUAL(10, 10);
00378        CU_ASSERT_EQUAL(0, -0);
00379        CU_ASSERT_EQUAL(-12, -12);
00380        CU_ASSERT_NOT_EQUAL(10, 11);
00381        CU_ASSERT_NOT_EQUAL(0, -1);
00382        CU_ASSERT_NOT_EQUAL(-12, -11);
00383        CU_ASSERT_PTR_EQUAL((void*)0x100, (void*)0x100);
00384        CU_ASSERT_PTR_NOT_EQUAL((void*)0x100, (void*)0x101);
00385        CU_ASSERT_PTR_NULL(NULL);
00386        CU_ASSERT_PTR_NULL(0x0);
00387        CU_ASSERT_PTR_NOT_NULL((void*)0x23);
00388        CU_ASSERT_STRING_EQUAL(str1, str2);
00389        CU_ASSERT_STRING_NOT_EQUAL(str1, str2);
00390        CU_ASSERT_NSTRING_EQUAL(str1, str2, strlen(str1));
00391        CU_ASSERT_NSTRING_EQUAL(str1, str1, strlen(str1));
00392        CU_ASSERT_NSTRING_EQUAL(str1, str1, strlen(str1) + 1);
00393        CU_ASSERT_NSTRING_NOT_EQUAL(str1, str2, 3);
00394        CU_ASSERT_NSTRING_NOT_EQUAL(str1, str3, strlen(str1) + 1);
00395        CU_ASSERT_DOUBLE_EQUAL(10, 10.0001, 0.0001);
00396        CU_ASSERT_DOUBLE_EQUAL(10, 10.0001, -0.0001);
00397        CU_ASSERT_DOUBLE_EQUAL(-10, -10.0001, 0.0001);
00398        CU_ASSERT_DOUBLE_EQUAL(-10, -10.0001, -0.0001);
00399        CU_ASSERT_DOUBLE_NOT_EQUAL(10, 10.001, 0.0001);
00400        CU_ASSERT_DOUBLE_NOT_EQUAL(10, 10.001, -0.0001);
00401        CU_ASSERT_DOUBLE_NOT_EQUAL(-10, -10.001, 0.0001);
00402        CU_ASSERT_DOUBLE_NOT_EQUAL(-10, -10.001, -0.0001);
00403 */
00404 
00405 
00406 
00407 
00408 
00409 static void AddStrBufSimlpeTests(void)
00410 {
00411        CU_pSuite pGroup = NULL;
00412        CU_pTest pTest = NULL;
00413 
00414        pGroup = CU_add_suite("TestStringBufSimpleAppenders", NULL, NULL);
00415        if (n_Lines_to_read > 0)
00416               pTest = CU_add_test(pGroup, "testSimpleLinebufferTest", SimpleLinebufferTest);
00417        else if (blobsize > 0)
00418               pTest = CU_add_test(pGroup, "testSimpleBLOBbufferTest", SimpleBLOBbufferTest);
00419        else 
00420               pTest = CU_add_test(pGroup,"testSimpleMixedLineBlob", SimpleMixedLineBlob);
00421 
00422 }
00423 
00424 
00425 int main(int argc, char* argv[])
00426 {
00427        char a;
00428        setvbuf(stdout, NULL, _IONBF, 0);
00429 
00430 
00431        while ((a = getopt(argc, argv, "p:i:n:b:t:s")) != EOF)
00432        {
00433               switch (a) {
00434 
00435               case 'p':
00436                      listen_port = atoi(optarg);
00437                      break;
00438               case 'i':
00439                      safestrncpy(ip_addr, optarg, sizeof ip_addr);
00440                      break;
00441               case 'n':
00442                      // do linetest?
00443                      n_Lines_to_read = atoi(optarg);
00444                      break;
00445               case 'b':
00446                      // or blobtest?
00447                      blobsize = atoi(optarg);
00448                      // else run the simple http test
00449                      break;
00450               case 't':
00451                      if (optarg != NULL)
00452                             timeout = atoi(optarg);
00453                      break;
00454               case 's':
00455                      if (optarg != NULL)
00456                             selres = atoi(optarg);
00457                      break;
00458               }
00459        }
00460 
00461 
00462        StartLibCitadel(8);
00463        CU_BOOL Run = CU_FALSE ;
00464        
00465        CU_set_output_filename("TestAutomated");
00466        if (CU_initialize_registry()) {
00467               printf("\nInitialize of test Registry failed.");
00468        }
00469        
00470        Run = CU_TRUE ;
00471        AddStrBufSimlpeTests();
00472        
00473        if (CU_TRUE == Run) {
00474               //CU_console_run_tests();
00475     printf("\nTests completed with return value %d.\n", CU_basic_run_tests());
00476     
00478        }
00479        
00480        CU_cleanup_registry();
00481 
00482        return 0;
00483 }