LCOV - code coverage report
Current view: top level - src/odbc/unittests - prepclose.c (source / functions) Hit Total Coverage
Test: FreeTDS coverage Lines: 26 30 86.7 %
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             : #if HAVE_SYS_SOCKET_H
       8             : #include <sys/socket.h>
       9             : #endif /* HAVE_SYS_SOCKET_H */
      10             : 
      11             : #if HAVE_SYS_STAT_H
      12             : #include <sys/stat.h>
      13             : #endif /* HAVE_SYS_STAT_H */
      14             : 
      15             : #if HAVE_SYS_IOCTL_H
      16             : #include <sys/ioctl.h>
      17             : #endif /* HAVE_SYS_IOCTL_H */
      18             : 
      19             : #if HAVE_SYS_WAIT_H
      20             : #include <sys/wait.h>
      21             : #endif /* HAVE_SYS_WAIT_H */
      22             : 
      23             : #include <freetds/utils.h>
      24             : 
      25             : /*
      26             :  * test error on connection close 
      27             :  * With a trick we simulate a connection close then we try to 
      28             :  * prepare or execute a query. This should fail and return an error message.
      29             :  */
      30             : 
      31             : #ifdef _WIN32
      32             : #define SHUT_RDWR SD_BOTH
      33             : #endif
      34             : 
      35             : static int
      36          32 : close_last_socket(void)
      37             : {
      38          32 :         TDS_SYS_SOCKET max_socket = odbc_find_last_socket();
      39             : 
      40          32 :         if (max_socket < 0) {
      41           0 :                 fprintf(stderr, "Error finding last socket\n");
      42           0 :                 return 0;
      43             :         }
      44             : 
      45             :         /* close connection */
      46          32 :         shutdown(max_socket, SHUT_RDWR);
      47             : 
      48          32 :         return 1;
      49             : }
      50             : 
      51             : static int
      52          32 : Test(int direct, int long_query)
      53             : {
      54             :         SQLTCHAR buf[256];
      55             :         SQLTCHAR sqlstate[6];
      56             :         char sql[5100];
      57             : 
      58          32 :         odbc_mark_sockets_opened();
      59          32 :         odbc_connect();
      60             : 
      61          32 :         if (!close_last_socket()) {
      62           0 :                 fprintf(stderr, "Error closing connection\n");
      63           0 :                 return 1;
      64             :         }
      65             : 
      66          32 :         if (long_query) {
      67          16 :                 memset(sql, '-', sizeof(sql));
      68          16 :                 strcpy(sql + 5000, "\nSELECT 1");
      69             :         } else {
      70          16 :                 strcpy(sql, "SELECT 1");
      71             :         }
      72             : 
      73             :         /* force disconnection closing socket */
      74          32 :         if (direct) {
      75          16 :                 CHKExecDirect(T(sql), SQL_NTS, "E");
      76             :         } else {
      77             :                 SQLSMALLINT cols;
      78             :                 /* use prepare, force dialog with server */
      79          16 :                 if (CHKPrepare(T(sql), SQL_NTS, "SE") == SQL_SUCCESS)
      80          12 :                         CHKNumResultCols(&cols, "E");
      81             :         }
      82             : 
      83          32 :         CHKGetDiagRec(SQL_HANDLE_STMT, odbc_stmt, 1, sqlstate, NULL, buf, TDS_VECTOR_SIZE(buf), NULL, "SI");
      84          32 :         sqlstate[5] = 0;
      85          32 :         printf("state=%s err=%s\n", C(sqlstate), C(buf));
      86             :         
      87          32 :         odbc_disconnect();
      88             : 
      89          32 :         printf("Done.\n");
      90          32 :         return 0;
      91             : }
      92             : 
      93             : int
      94           8 : main(void)
      95             : {
      96             :         /* check with short queries */
      97           8 :         if (Test(0, 0) || Test(1, 0))
      98             :                 return 1;
      99             : 
     100             :         /* check with large queries, this will trigger different paths */
     101           8 :         if (Test(0, 1) || Test(1, 1))
     102             :                 return 1;
     103             :         return 0;
     104             : }

Generated by: LCOV version 1.13