LCOV - code coverage report
Current view: top level - src/odbc/unittests - timeout4.c (source / functions) Hit Total Coverage
Test: FreeTDS coverage Lines: 37 43 86.0 %
Date: 2025-01-18 12:13:41 Functions: 3 3 100.0 %

          Line data    Source code
       1             : #include "common.h"
       2             : 
       3             : #if HAVE_UNISTD_H
       4             : #include <unistd.h>
       5             : #endif /* HAVE_UNISTD_H */
       6             : 
       7             : #include <freetds/time.h>
       8             : 
       9             : #if HAVE_SYS_SOCKET_H
      10             : #include <sys/socket.h>
      11             : #endif /* HAVE_SYS_SOCKET_H */
      12             : 
      13             : #if HAVE_SYS_STAT_H
      14             : #include <sys/stat.h>
      15             : #endif /* HAVE_SYS_STAT_H */
      16             : 
      17             : #if HAVE_SYS_IOCTL_H
      18             : #include <sys/ioctl.h>
      19             : #endif /* HAVE_SYS_IOCTL_H */
      20             : 
      21             : #if HAVE_SYS_WAIT_H
      22             : #include <sys/wait.h>
      23             : #endif /* HAVE_SYS_WAIT_H */
      24             : 
      25             : #include <freetds/utils.h>
      26             : 
      27             : /*
      28             :  * test error on connection close 
      29             :  * With a trick we simulate a connection close then we try to 
      30             :  * prepare or execute a query. This should fail and return an error message.
      31             :  */
      32             : 
      33             : #if HAVE_FSTAT && defined(S_IFSOCK)
      34             : 
      35             : static int end_socket = -1;
      36             : 
      37             : static int
      38          16 : shutdown_last_socket(void)
      39             : {
      40          16 :         TDS_SYS_SOCKET max_socket = odbc_find_last_socket();
      41             :         TDS_SYS_SOCKET sockets[2];
      42             : 
      43          16 :         if (max_socket < 0)
      44             :                 return 0;
      45             : 
      46             :         /* replace socket with a new one */
      47          16 :         if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockets) < 0)
      48             :                 return 0;
      49             : 
      50          16 :         tds_socket_set_nosigpipe(sockets[0], 1);
      51             : 
      52             :         /* substitute socket */
      53          16 :         close(max_socket);
      54          16 :         dup2(sockets[0], max_socket);
      55             : 
      56             :         /* close connection */
      57          16 :         close(sockets[0]);
      58          16 :         end_socket = sockets[1];
      59          16 :         return 1;
      60             : }
      61             : 
      62             : static int
      63          16 : Test(int direct)
      64             : {
      65             :         SQLTCHAR buf[256];
      66             :         SQLTCHAR sqlstate[6];
      67             :         time_t start_time, end_time;
      68             : 
      69          16 :         odbc_mark_sockets_opened();
      70          16 :         odbc_connect();
      71             : 
      72          16 :         if (!shutdown_last_socket()) {
      73           0 :                 fprintf(stderr, "Error shutting down connection\n");
      74           0 :                 return 1;
      75             :         }
      76             : 
      77          16 :         CHKSetStmtAttr(SQL_ATTR_QUERY_TIMEOUT, (SQLPOINTER) 10, SQL_IS_UINTEGER, "S");
      78             : 
      79          16 :         alarm(30);
      80          16 :         start_time = time(NULL);
      81          16 :         if (direct) {
      82           8 :                 CHKExecDirect(T("SELECT 1"), SQL_NTS, "E");
      83             :         } else {
      84             :                 SQLSMALLINT cols;
      85             :                 /* force dialog with server */
      86           8 :                 if (CHKPrepare(T("SELECT 1"), SQL_NTS, "SE") == SQL_SUCCESS)
      87           6 :                         CHKNumResultCols(&cols, "E");
      88             :         }
      89          16 :         end_time = time(NULL);
      90          16 :         alarm(0);
      91             : 
      92          16 :         memset(sqlstate, 'X', sizeof(sqlstate));
      93          16 :         CHKGetDiagRec(SQL_HANDLE_STMT, odbc_stmt, 1, sqlstate, NULL, buf, TDS_VECTOR_SIZE(buf), NULL, "SI");
      94          16 :         sqlstate[5] = 0;
      95          16 :         printf("Message: %s - %s\n", C(sqlstate), C(buf));
      96          16 :         if (strcmp(C(sqlstate), "HYT00") || !strstr(C(buf), "Timeout")) {
      97           0 :                 fprintf(stderr, "Invalid timeout message\n");
      98           0 :                 return 1;
      99             :         }
     100          16 :         if (end_time - start_time < 10 || end_time - start_time > 26) {
     101           0 :                 fprintf(stderr, "Unexpected connect timeout (%d)\n", (int) (end_time - start_time));
     102           0 :                 return 1;
     103             :         }
     104             : 
     105          16 :         odbc_disconnect();
     106             : 
     107          16 :         if (end_socket >= 0)
     108          16 :                 close(end_socket);
     109             : 
     110          16 :         printf("Done.\n");
     111          16 :         return 0;
     112             : }
     113             : 
     114             : int
     115           8 : main(void)
     116             : {
     117           8 :         odbc_use_version3 = 1;
     118             : 
     119           8 :         if (Test(0) || Test(1))
     120             :                 return 1;
     121             :         return 0;
     122             : }
     123             : 
     124             : #else
     125             : int
     126             : main(void)
     127             : {
     128             :         printf("Not possible for this platform.\n");
     129             :         odbc_test_skipped();
     130             :         return 0;
     131             : }
     132             : #endif

Generated by: LCOV version 1.13