LCOV - code coverage report
Current view: top level - src/dblib/unittests - iconv_partial.c (source / functions) Hit Total Coverage
Test: FreeTDS coverage Lines: 37 56 66.1 %
Date: 2026-11-07 23:58:45 Functions: 2 2 100.0 %

          Line data    Source code
       1             : /*
       2             :  * Purpose: Test that a string truncated inside a multibyte sequence is reported
       3             :  * correctly, reporting the error used to crash, see GitHub issue #227.
       4             :  * The server truncates a surrogate pair storing it in a NVARCHAR(1) column.
       5             :  */
       6             : 
       7             : #include "common.h"
       8             : 
       9             : static int conversion_errors = 0;
      10             : static int wrong_errors = 0;
      11             : 
      12             : static int
      13           8 : err_handler(DBPROCESS *dbproc, int severity, int dberr, int oserr, char *dberrstr, char *oserrstr)
      14             : {
      15           8 :         switch (dberr) {
      16           8 :         case SYBEICONVPARTIAL:
      17             :         case SYBEICONVI:
      18           8 :                 printf("got expected error %d: %s\n", dberr, dberrstr);
      19           8 :                 ++conversion_errors;
      20           8 :                 return INT_CANCEL;
      21           0 :         case SYBEICONVAVAIL:
      22           0 :                 fprintf(stderr, "conversion wrongly reported as not available: %s\n", dberrstr);
      23           0 :                 ++wrong_errors;
      24           0 :                 return INT_CANCEL;
      25             :         default:
      26             :                 break;
      27             :         }
      28           0 :         return syb_err_handler(dbproc, severity, dberr, oserr, dberrstr, oserrstr);
      29             : }
      30             : 
      31          10 : TEST_MAIN()
      32             : {
      33             :         LOGINREC *login;
      34             :         DBPROCESS *dbproc;
      35          10 :         DBINT value = 0;
      36             : 
      37          10 :         set_malloc_options();
      38             : 
      39          10 :         read_login_info(argc, argv);
      40             : 
      41          10 :         dbinit();
      42             : 
      43          10 :         dberrhandle(err_handler);
      44          10 :         dbmsghandle(syb_msg_handler);
      45             : 
      46          10 :         login = dblogin();
      47          10 :         DBSETLPWD(login, PASSWORD);
      48          10 :         DBSETLUSER(login, USER);
      49          10 :         DBSETLAPP(login, "iconv_partial");
      50             : 
      51          10 :         dbproc = dbopen(login, SERVER);
      52          10 :         if (!dbproc) {
      53           0 :                 fprintf(stderr, "Unable to connect to %s\n", SERVER);
      54           0 :                 return 1;
      55             :         }
      56          10 :         dbloginfree(login);
      57             : 
      58             :         /* requires an UTF-16 column from Microsoft server */
      59          10 :         if (dbtds(dbproc) < DBTDS_7_0) {
      60           2 :                 dbclose(dbproc);
      61           2 :                 dbexit();
      62           2 :                 return 77;
      63             :         }
      64             : 
      65           8 :         dbcmd(dbproc, "DECLARE @test NVARCHAR(1) SET @test = 0x3CD884DF SELECT @test AS test, 1234 AS n");
      66           8 :         if (dbsqlexec(dbproc) != SUCCEED) {
      67           0 :                 fprintf(stderr, "error: executing query\n");
      68           0 :                 return 1;
      69             :         }
      70             : 
      71             :         /* DECLARE can produce a result without columns, skip it */
      72             :         do {
      73          16 :                 if (dbresults(dbproc) != SUCCEED) {
      74           0 :                         fprintf(stderr, "error: expected a result set\n");
      75           0 :                         return 1;
      76             :                 }
      77          16 :         } while (dbnumcols(dbproc) == 0);
      78             : 
      79           8 :         if (dbbind(dbproc, 2, INTBIND, -1, (BYTE *) & value) != SUCCEED) {
      80           0 :                 fprintf(stderr, "error: binding column\n");
      81           0 :                 return 1;
      82             :         }
      83             : 
      84           8 :         if (dbnextrow(dbproc) != REG_ROW) {
      85           0 :                 fprintf(stderr, "error: expected a row\n");
      86           0 :                 return 1;
      87             :         }
      88             : 
      89             :         /* the conversion problem should not affect the following column */
      90           8 :         if (value != 1234) {
      91           0 :                 fprintf(stderr, "error: unexpected value %d\n", (int) value);
      92           0 :                 return 1;
      93             :         }
      94             : 
      95           8 :         dbcancel(dbproc);
      96           8 :         dbclose(dbproc);
      97           8 :         dbexit();
      98             : 
      99           8 :         if (wrong_errors || !conversion_errors) {
     100           0 :                 fprintf(stderr, "error: wrong conversion errors %d, right conversion errors %d\n", wrong_errors, conversion_errors);
     101           0 :                 return 1;
     102             :         }
     103             : 
     104           8 :         printf("OK\n");
     105           8 :         return 0;
     106             : }

Generated by: LCOV version 1.13