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

Generated by: LCOV version 1.13