LCOV - code coverage report
Current view: top level - src/ctlib/unittests - timeout.c (source / functions) Hit Total Coverage
Test: FreeTDS coverage Lines: 36 42 85.7 %
Date: 2025-01-18 11:50:39 Functions: 4 4 100.0 %

          Line data    Source code
       1             : /*
       2             :  * Purpose: Test handling of timeouts with callbacks
       3             :  */
       4             : 
       5             : #include "common.h"
       6             : #include <freetds/macros.h>
       7             : #include <time.h>
       8             : 
       9             : static int ntimeouts = 0, ncancels = 0;
      10             : static int max_timeouts = 2, timeout_seconds = 2, cancel_timeout = 10;
      11             : static time_t start_time;
      12             : static const char sql[] =
      13             :         "select getdate() as 'begintime'\n"
      14             :         "waitfor delay '00:00:30'\n"
      15             :         "select getdate() as 'endtime'";
      16             : 
      17             : static int
      18          48 : on_interrupt(CS_CONNECTION *con TDS_UNUSED)
      19             : {
      20          48 :         printf("In on_interrupt, %ld seconds elapsed.\n", (long int) (time(NULL) - start_time));
      21          48 :         return CS_INT_CONTINUE;
      22             : }
      23             : 
      24             : static int
      25          28 : on_client_msg(CS_CONTEXT *ctx, CS_CONNECTION *con, CS_CLIENTMSG *errmsg)
      26             : {
      27          28 :         if (errmsg->msgnumber == 20003) {    /* TDSETIME */
      28          24 :                 fprintf(stderr, "%d timeout(s) received in %ld seconds; ", ++ntimeouts, (long int) (time(NULL) - start_time));
      29          24 :                 if (ntimeouts > max_timeouts) {
      30           8 :                         if (++ncancels > 1) {
      31           0 :                                 fputs("could not time out cleanly;"
      32             :                                       " breaking connection.\n", stderr);
      33           0 :                                 ncancels = 0;
      34           0 :                                 return CS_FAIL;
      35             :                         }
      36           8 :                         fputs("lost patience;"
      37             :                               " cancelling (allowing 10 seconds)\n", stderr);
      38           8 :                         check_call(ct_con_props, (con, CS_SET, CS_TIMEOUT, &cancel_timeout, CS_UNUSED, NULL));
      39           8 :                         return CS_FAIL;
      40             :                 }
      41          16 :                 fputs("continuing to wait.\n", stderr);
      42          16 :                 return CS_SUCCEED;
      43             :         }
      44           4 :         return clientmsg_cb(ctx, con, errmsg);
      45             : }
      46             : 
      47             : static void
      48           8 : test(CS_CONNECTION *con, CS_COMMAND *cmd)
      49             : {
      50           8 :         CS_INT result_type = 0;
      51             :         CS_RETCODE ret;
      52             : 
      53           8 :         ntimeouts = 0;
      54           8 :         ncancels = 0;
      55             : 
      56           8 :         printf("Using %d-second query timeouts.\n", timeout_seconds);
      57             : 
      58           8 :         check_call(ct_con_props, (con, CS_SET, CS_TIMEOUT, &timeout_seconds, CS_UNUSED, NULL));
      59             : 
      60             :         /* Send something that will take a while to execute. */
      61           8 :         printf("Issuing a query that will take 30 seconds.\n");
      62           8 :         check_call(ct_command, (cmd, CS_LANG_CMD, (void *) sql, sizeof(sql) - 1, CS_UNUSED));
      63             : 
      64           8 :         start_time = time(NULL);        /* Track for reporting purposes. */
      65           8 :         ntimeouts = 0;
      66           8 :         check_call(ct_callback, (NULL, con, CS_SET, CS_CLIENTMSG_CB, &on_client_msg));
      67           8 :         check_call(ct_callback, (NULL, con, CS_SET, CS_INTERRUPT_CB, &on_interrupt));
      68             : 
      69           8 :         check_call(ct_send,(cmd));
      70             : 
      71           8 :         ret = ct_results(cmd, &result_type);
      72           8 :         if (ret == CS_SUCCEED) {
      73           0 :                 fprintf(stderr, "Query unexpectedly succeeded, with result type %d.\n", result_type);
      74             :         } else {
      75           8 :                 printf("Query failed as expected, with return code %d.\n", ret);
      76             :         }
      77           8 : }
      78             : 
      79             : int
      80           8 : main(int argc, char **argv)
      81             : {
      82             :         CS_CONTEXT *ctx;
      83             :         CS_CONNECTION *con;
      84             :         CS_COMMAND *cmd;
      85             : 
      86           8 :         if (CS_SUCCEED != try_ctlogin_with_options(argc, argv, &ctx, &con, &cmd, false)) {
      87           0 :                 fputs("Customary setup failed.\n", stderr);
      88           0 :                 return 1;
      89             :         }
      90           8 :         test(con, cmd);
      91           8 :         try_ctlogout(ctx, con, cmd, false);
      92           8 :         return 0;
      93             : }

Generated by: LCOV version 1.13