LCOV - code coverage report
Current view: top level - src/ctlib/unittests - cancel.c (source / functions) Hit Total Coverage
Test: FreeTDS coverage Lines: 65 82 79.3 %
Date: 2025-01-18 11:50:39 Functions: 3 3 100.0 %

          Line data    Source code
       1             : #include "common.h"
       2             : 
       3             : #include <freetds/time.h>
       4             : 
       5             : #include <sys/types.h>
       6             : 
       7             : #if HAVE_UNISTD_H
       8             : #include <unistd.h>
       9             : #endif /* HAVE_UNISTD_H */
      10             : 
      11             : #include <signal.h>
      12             : 
      13             : #include <freetds/macros.h>
      14             : 
      15             : #if defined(HAVE_ALARM) && defined(HAVE_SETITIMER)
      16             : 
      17             : /* protos */
      18             : int do_fetch(CS_COMMAND * cmd, int *cnt);
      19             : void catch_alrm(int);
      20             : 
      21             : /* Globals */
      22             : static volatile CS_COMMAND *g_cmd = NULL;
      23             : 
      24             : void
      25          49 : catch_alrm(int sig_num TDS_UNUSED)
      26             : {
      27          49 :         signal(SIGALRM, catch_alrm);
      28             : 
      29          49 :         printf("- SIGALRM\n");
      30             : 
      31             :         /* Cancel current command */
      32          49 :         if (g_cmd)
      33          49 :                 ct_cancel(NULL, (CS_COMMAND *) g_cmd, CS_CANCEL_ATTN);
      34             : 
      35          49 :         fflush(stdout);
      36          49 : }
      37             : 
      38             : /* Testing: Test asynchronous ct_cancel() */
      39             : int
      40           8 : main(void)
      41             : {
      42             :         CS_CONTEXT *ctx;
      43             :         CS_CONNECTION *conn;
      44             :         CS_COMMAND *cmd;
      45           8 :         int i, verbose = 0, cnt = 0;
      46             : 
      47             :         CS_RETCODE ret;
      48             :         CS_INT result_type;
      49             : 
      50             :         struct itimerval timer;
      51             :         char query[1024];
      52             : 
      53           8 :         unsigned clock = 200000;
      54             : 
      55           8 :         printf("%s: Check asynchronous called ct_cancel()\n", __FILE__);
      56             : 
      57             :         /* disable dump for this test, there are some issues with concurrent
      58             :          * execution of this test if logging is enabled. */
      59           8 :         unsetenv("TDSDUMP");
      60           8 :         unsetenv("TDSDUMPCONFIG");
      61             : 
      62             :         if (verbose) {
      63             :                 printf("Trying login\n");
      64             :         }
      65           8 :         check_call(try_ctlogin, (&ctx, &conn, &cmd, verbose));
      66             : 
      67             :         /* Create needed tables */
      68           8 :         check_call(run_command, (cmd, "CREATE TABLE #t0010 (id int, col1 varchar(255))"));
      69             : 
      70          88 :         for (i = 0; i < 10; i++) {
      71          80 :                 sprintf(query, "INSERT #t0010 (id, col1) values (%d, 'This is field no %d')", i, i);
      72             : 
      73          80 :                 check_call(run_command, (cmd, query));
      74             :         }
      75             : 
      76             :         /* Set SIGALRM signal handler */
      77           8 :         signal(SIGALRM, catch_alrm);
      78             : 
      79             :         for (;;) {
      80             :                 /* TODO better to use alarm AFTER ct_send ?? */
      81             :                 /* Set timer */
      82           8 :                 timer.it_interval.tv_sec = 0;
      83           8 :                 timer.it_interval.tv_usec = clock;
      84           8 :                 timer.it_value.tv_sec = 0;
      85           8 :                 timer.it_value.tv_usec = clock;
      86           8 :                 if (0 != setitimer(ITIMER_REAL, &timer, NULL)) {
      87           0 :                         fprintf(stderr, "Could not set realtime timer.\n");
      88           0 :                         return 1;
      89             :                 }
      90             : 
      91             :                 /* Issue a command returning many rows */
      92           8 :                 check_call(ct_command, 
      93             :                            (cmd, CS_LANG_CMD, "SELECT * FROM #t0010 t1, #t0010 t2, #t0010 t3, #t0010 t4", CS_NULLTERM, CS_UNUSED));
      94             : 
      95           8 :                 check_call(ct_send, (cmd));
      96             : 
      97             :                 /* Save a global reference for the interrupt handler */
      98           8 :                 g_cmd = cmd;
      99             : 
     100          24 :                 while ((ret = ct_results(cmd, &result_type)) == CS_SUCCEED) {
     101           8 :                         printf("More results?...\n");
     102           8 :                         if (result_type == CS_STATUS_RESULT)
     103           0 :                                 continue;
     104             : 
     105           8 :                         switch ((int) result_type) {
     106           8 :                         case CS_ROW_RESULT:
     107           8 :                                 printf("do_fetch() returned: %d\n", do_fetch(cmd, &cnt));
     108           8 :                                 break;
     109             :                         }
     110             :                 }
     111             : 
     112             :                 /* We should not have received all rows, as the alarm signal cancelled it... */
     113           8 :                 if (cnt < 10000)
     114             :                         break;
     115             : 
     116           0 :                 if (clock <= 5000) {
     117           0 :                         fprintf(stderr, "All rows read, this may not occur.\n");
     118           0 :                         return 1;
     119             :                 }
     120           0 :                 g_cmd = NULL;
     121           0 :                 clock /= 2;
     122             :         }
     123             : 
     124             :         /* Remove timer */
     125           8 :         timer.it_interval.tv_sec = 0;
     126           8 :         timer.it_interval.tv_usec = 0;
     127           8 :         timer.it_value.tv_sec = 0;
     128           8 :         timer.it_value.tv_usec = 0;
     129           8 :         if (0 != setitimer(ITIMER_REAL, &timer, NULL)) {
     130           0 :                 fprintf(stderr, "Could not remove realtime timer.\n");
     131           0 :                 return 1;
     132             :         }
     133             : 
     134             :         /*
     135             :          * Issue another command, this will be executed after a ct_cancel, 
     136             :          * to test if wire state is consistent 
     137             :          */
     138           8 :         check_call(ct_command, (cmd, CS_LANG_CMD, "SELECT * FROM #t0010 t1, #t0010 t2, #t0010 t3", CS_NULLTERM, CS_UNUSED));
     139             : 
     140           8 :         check_call(ct_send, (cmd));
     141             : 
     142          32 :         while ((ret = ct_results(cmd, &result_type)) == CS_SUCCEED) {
     143          16 :                 printf("More results?...\n");
     144          16 :                 if (result_type == CS_STATUS_RESULT)
     145           0 :                         continue;
     146             : 
     147          16 :                 switch ((int) result_type) {
     148           8 :                 case CS_ROW_RESULT:
     149           8 :                         printf("do_fetch() returned: %d\n", do_fetch(cmd, &cnt));
     150           8 :                         break;
     151             :                 }
     152             :         }
     153             : 
     154           8 :         if (1000 != cnt) {
     155             :                 /* This time, all rows must have been received */
     156           0 :                 fprintf(stderr, "Incorrect number of rows read.\n");
     157           0 :                 return 1;
     158             :         }
     159             : 
     160             :         if (verbose) {
     161             :                 printf("Trying logout\n");
     162             :         }
     163           8 :         check_call(try_ctlogout, (ctx, conn, cmd, verbose));
     164             : 
     165           8 :         printf("%s: asynchronous cancel test: PASSED\n", __FILE__);
     166             : 
     167           8 :         return 0;
     168             : }
     169             : 
     170             : int
     171          16 : do_fetch(CS_COMMAND * cmd, int *cnt)
     172             : {
     173          16 :         CS_INT count, row_count = 0;
     174             :         CS_RETCODE ret;
     175             : 
     176       13318 :         while ((ret = ct_fetch(cmd, CS_UNUSED, CS_UNUSED, CS_UNUSED, &count)) == CS_SUCCEED) {
     177             :                 /* printf ("ct_fetch() == CS_SUCCEED\n"); */
     178       13286 :                 row_count += count;
     179             :         }
     180             : 
     181          16 :         (*cnt) = row_count;
     182          16 :         if (ret == CS_ROW_FAIL) {
     183           0 :                 fprintf(stderr, "ct_fetch() CS_ROW_FAIL on row %d.\n", row_count);
     184           0 :                 return 1;
     185          16 :         } else if (ret == CS_END_DATA) {
     186           8 :                 printf("do_fetch retrieved %d rows\n", row_count);
     187           8 :                 return 0;
     188           8 :         } else if (ret == CS_CMD_FAIL) {
     189           0 :                 printf("do_fetch(): command aborted after receiving %d rows\n", row_count);
     190           0 :                 return 0;
     191             :         } else {
     192           8 :                 fprintf(stderr, "ct_fetch() unexpected return %d on row %d.\n", ret, row_count);
     193           8 :                 return 1;
     194             :         }
     195             : }
     196             : 
     197             : #else
     198             : 
     199             : int
     200             : main(void)
     201             : {
     202             :         return 0;
     203             : }
     204             : #endif
     205             : 

Generated by: LCOV version 1.13