LCOV - code coverage report
Current view: top level - src/dblib/unittests - hang.c (source / functions) Hit Total Coverage
Test: FreeTDS coverage Lines: 52 58 89.7 %
Date: 2025-01-18 12:13:41 Functions: 3 3 100.0 %

          Line data    Source code
       1             : /* 
       2             :  * Purpose: Test for dbsqlexec on closed connection
       3             :  */
       4             : 
       5             : #include "common.h"
       6             : 
       7             : #if HAVE_UNISTD_H
       8             : #include <unistd.h>
       9             : #endif /* HAVE_UNISTD_H */
      10             : 
      11             : #include <freetds/time.h>
      12             : 
      13             : #if HAVE_SYS_SOCKET_H
      14             : #include <sys/socket.h>
      15             : #endif /* HAVE_SYS_SOCKET_H */
      16             : 
      17             : #if HAVE_SYS_STAT_H
      18             : #include <sys/stat.h>
      19             : #endif /* HAVE_SYS_STAT_H */
      20             : 
      21             : #if HAVE_SYS_IOCTL_H
      22             : #include <sys/ioctl.h>
      23             : #endif /* HAVE_SYS_IOCTL_H */
      24             : 
      25             : #if HAVE_SYS_WAIT_H
      26             : #include <sys/wait.h>
      27             : #endif /* HAVE_SYS_WAIT_H */
      28             : 
      29             : #if HAVE_NETINET_IN_H
      30             : #include <netinet/in.h>
      31             : #endif /* HAVE_NET_INET_IN_H */
      32             : 
      33             : #include <freetds/utils.h>
      34             : 
      35             : char *UNITTEST;
      36             : 
      37             : #if HAVE_FSTAT && defined(S_IFSOCK)
      38             : 
      39             : static int end_socket = -1;
      40             : 
      41             : static int
      42          16 : shutdown_socket(DBPROCESS *dbproc)
      43             : {
      44             :         union {
      45             :                 struct sockaddr sa;
      46             :                 char data[256];
      47             :         } u;
      48             :         SOCKLEN_T addrlen;
      49             :         struct stat file_stat;
      50             :         TDS_SYS_SOCKET sockets[2];
      51             : 
      52          16 :         TDS_SYS_SOCKET socket = DBIOWDESC(dbproc);
      53             : 
      54          16 :         if (fstat(socket, &file_stat))
      55             :                 return 0;
      56          16 :         if ((file_stat.st_mode & S_IFSOCK) != S_IFSOCK)
      57             :                 return 0;
      58             : 
      59          16 :         addrlen = sizeof(u);
      60          16 :         if (tds_getsockname(socket, &u.sa, &addrlen) < 0 || (u.sa.sa_family != AF_INET && u.sa.sa_family != AF_INET6))
      61             :                 return 0;
      62             : 
      63             :         /* replace socket with a new one */
      64          16 :         if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockets) < 0)
      65             :                 return 0;
      66             : 
      67          16 :         tds_socket_set_nosigpipe(sockets[0], 1);
      68             : 
      69             :         /* substitute socket */
      70          16 :         close(socket);
      71          16 :         dup2(sockets[0], socket);
      72             : 
      73             :         /* close connection */
      74          16 :         close(sockets[0]);
      75          16 :         end_socket = sockets[1];
      76          16 :         return 1;
      77             : }
      78             : 
      79             : static int
      80          16 : test(int close_socket)
      81             : {
      82             :         LOGINREC *login;
      83             :         DBPROCESS *dbproc;
      84             :         RETCODE ret;
      85          16 :         int expected_error = -1;
      86             : 
      87          16 :         printf("Starting %s\n", UNITTEST);
      88             : 
      89          16 :         dbinit();
      90             : 
      91          16 :         dberrhandle(syb_err_handler);
      92          16 :         dbmsghandle(syb_msg_handler);
      93             : 
      94          16 :         printf("About to logon\n");
      95             : 
      96          16 :         login = dblogin();
      97          16 :         DBSETLPWD(login, PASSWORD);
      98          16 :         DBSETLUSER(login, USER);
      99          16 :         DBSETLAPP(login, "t0020");
     100             : 
     101          16 :         printf("About to open\n");
     102             : 
     103          16 :         dbproc = dbopen(login, SERVER);
     104          16 :         dbsetuserdata(dbproc, (BYTE*) &expected_error);
     105          16 :         if (strlen(DATABASE))
     106          16 :                 dbuse(dbproc, DATABASE);
     107          16 :         dbloginfree(login);
     108             : 
     109          16 :         dbcmd(dbproc, "select * from sysobjects");
     110          16 :         printf("dbsqlexec should not hang.\n");
     111             : 
     112          16 :         ret = dbsettime(15);
     113          16 :         if (ret != SUCCEED) {
     114           0 :                 fprintf(stderr, "Failed.  Error setting timeout.\n");
     115           0 :                 return 1;
     116             :         }
     117             : 
     118          16 :         if (!shutdown_socket(dbproc)) {
     119           0 :                 fprintf(stderr, "Error shutting down connection\n");
     120           0 :                 return 1;
     121             :         }
     122          16 :         if (close_socket)
     123           8 :                 close(end_socket);
     124             : 
     125          16 :         alarm(20);
     126          16 :         expected_error = close_socket ? 20006 : 20003;
     127          16 :         ret = dbsqlexec(dbproc);
     128          16 :         alarm(0);
     129          16 :         if (ret != FAIL) {
     130           0 :                 fprintf(stderr, "Failed.  Expected FAIL to be returned.\n");
     131           0 :                 return 1;
     132             :         }
     133             : 
     134          16 :         dbsetuserdata(dbproc, NULL);
     135          16 :         if (!close_socket)
     136           8 :                 close(end_socket);
     137          16 :         dbexit();
     138             : 
     139          16 :         printf("dblib okay on %s\n", __FILE__);
     140          16 :         return 0;
     141             : }
     142             : 
     143             : int
     144           8 : main(int argc, char **argv)
     145             : {
     146           8 :         UNITTEST = argv[0];
     147           8 :         read_login_info(argc, argv);
     148           8 :         if (test(0) || test(1))
     149             :                 return 1;
     150             :         return 0;
     151             : }
     152             : 
     153             : #else
     154             : int
     155             : main(void)
     156             : {
     157             :         fprintf(stderr, "Not possible for this platform.\n");
     158             :         return 0;
     159             : }
     160             : #endif
     161             : 

Generated by: LCOV version 1.13