LCOV - code coverage report
Current view: top level - src/tds/unittests - utf8_2.c (source / functions) Hit Total Coverage
Test: FreeTDS coverage Lines: 79 123 64.2 %
Date: 2025-01-18 11:50:39 Functions: 3 3 100.0 %

          Line data    Source code
       1             : /* FreeTDS - Library of routines accessing Sybase and Microsoft databases
       2             :  * Copyright (C) 2003, 2004  Frediano Ziglio
       3             :  *
       4             :  * This library is free software; you can redistribute it and/or
       5             :  * modify it under the terms of the GNU Library General Public
       6             :  * License as published by the Free Software Foundation; either
       7             :  * version 2 of the License, or (at your option) any later version.
       8             :  *
       9             :  * This library is distributed in the hope that it will be useful,
      10             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      11             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      12             :  * Library General Public License for more details.
      13             :  *
      14             :  * You should have received a copy of the GNU Library General Public
      15             :  * License along with this library; if not, write to the
      16             :  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
      17             :  * Boston, MA 02111-1307, USA.
      18             :  */
      19             : #include "common.h"
      20             : 
      21             : #include <ctype.h>
      22             : #include <assert.h>
      23             : 
      24             : /* try conversion from utf8 to iso8859-1 */
      25             : 
      26             : static TDSSOCKET *tds;
      27             : static int g_result = 0;
      28             : static int einval_error = 0;
      29             : static int eilseq_error = 0;
      30             : static int einval_count = 0;
      31             : static int eilseq_count = 0;
      32             : static int e2big_count = 0;
      33             : static char test_name[128];
      34             : 
      35             : static int invalid_char = -1;
      36             : 
      37             : static void
      38        3088 : test(int n, int type)
      39             : {
      40             :         int rc;
      41             :         TDS_INT result_type;
      42             :         char buf[1024+128], tmp[1024];
      43             :         TDSCOLUMN *curcol;
      44             :         char *src;
      45             :         int done_flags;
      46             :         int i;
      47             :         char prefix[32], suffix[32];
      48             : 
      49        3088 :         sprintf(test_name, "test %d len %d", type, n);
      50             : 
      51             :         /* do a select and check all results */
      52        3088 :         prefix[0] = 0;
      53        3088 :         suffix[0] = 0;
      54        3088 :         tmp[0] = 0;
      55        3088 :         switch (type) {
      56        1544 :         case 0:
      57        1544 :                 strcpy(suffix, "C280C290");
      58        1544 :                 break;
      59        1544 :         case 1:
      60             :                 /* try two invalid in different part */
      61        1544 :                 strcpy(prefix, "C480C290");
      62        1544 :                 strcpy(suffix, "C480C290");
      63        1544 :                 break;
      64             :         }
      65             : 
      66      296448 :         for (i = 0; i < n; ++i)
      67      296448 :                 sprintf(strchr(tmp, 0), "%02X", 0x30 + (i % 10));
      68        3088 :         sprintf(buf, "select convert(varchar(255), 0x%s%s%s)", prefix, tmp, suffix);
      69        3088 :         rc = tds_submit_query(tds, buf);
      70        3088 :         if (rc != TDS_SUCCESS) {
      71           0 :                 fprintf(stderr, "tds_submit_query() failed\n");
      72           0 :                 exit(1);
      73             :         }
      74             : 
      75        3088 :         if (tds_process_tokens(tds, &result_type, NULL, TDS_TOKEN_RESULTS) != TDS_SUCCESS) {
      76           0 :                 fprintf(stderr, "tds_process_tokens() failed\n");
      77           0 :                 exit(1);
      78             :         }
      79             : 
      80        3088 :         if (result_type != TDS_ROWFMT_RESULT) {
      81           0 :                 fprintf(stderr, "expected row fmt() failed\n");
      82           0 :                 exit(1);
      83             :         }
      84             : 
      85        3088 :         if (tds_process_tokens(tds, &result_type, NULL, TDS_TOKEN_RESULTS) != TDS_SUCCESS) {
      86           0 :                 fprintf(stderr, "tds_process_tokens() failed\n");
      87           0 :                 exit(1);
      88             :         }
      89             : 
      90        3088 :         if (result_type != TDS_ROW_RESULT) {
      91           0 :                 fprintf(stderr, "expected row result() failed\n");
      92           0 :                 exit(1);
      93             :         }
      94             : 
      95             :         /* force tds to convert from utf8 to iso8859-1 (even on Sybase) */
      96        3088 :         tds_srv_charset_changed(tds->conn, "UTF-8");
      97        3088 :         tds->current_results->columns[0]->char_conv = tds->conn->char_convs[client2server_chardata];
      98             : 
      99        3088 :         rc = tds_process_tokens(tds, &result_type, NULL, TDS_STOPAT_ROWFMT|TDS_RETURN_DONE|TDS_RETURN_ROW|TDS_RETURN_COMPUTE);
     100        3088 :         if (rc != TDS_SUCCESS) {
     101           0 :                 fprintf(stderr, "tds_process_tokens() failed\n");
     102           0 :                 exit(1);
     103             :         }
     104             : 
     105        3088 :         curcol = tds->current_results->columns[0];
     106        3088 :         src = (char*) curcol->column_data;
     107             : 
     108        3088 :         if (is_blob_col(curcol)) {
     109           0 :                 TDSBLOB *blob = (TDSBLOB *) src;
     110             : 
     111           0 :                 src = blob->textvalue;
     112             :         }
     113             : 
     114        3088 :         prefix[0] = 0;
     115        3088 :         suffix[0] = 0;
     116        3088 :         tmp[0] = 0;
     117        3088 :         switch (type) {
     118        1544 :         case 0:
     119        1544 :                 strcpy(suffix, "\x80\x90");
     120        1544 :                 break;
     121        1544 :         case 1:
     122             :                 /* try two invalid in different part */
     123        1544 :                 strcpy(prefix, "?\x90");
     124        1544 :                 strcpy(suffix, "?\x90");
     125             :                 /* some platforms replace invalid sequence with a fixed char */
     126        1544 :                 if (invalid_char < 0)
     127           8 :                         invalid_char = (unsigned char) src[0];
     128        1544 :                 prefix[0] = (char) invalid_char;
     129        1544 :                 suffix[0] = (char) invalid_char;
     130        1544 :                 break;
     131             :         }
     132             : 
     133      296448 :         for (i = 0; i < n; ++i)
     134      296448 :                 sprintf(strchr(tmp, 0), "%c", "0123456789"[i % 10]);
     135        3088 :         sprintf(buf, "%s%s%s", prefix, tmp, suffix);
     136             : 
     137        3088 :         if (strlen(buf) != curcol->column_cur_size || strncmp(buf, src, curcol->column_cur_size) != 0) {
     138           0 :                 int l = curcol->column_cur_size;
     139             : 
     140           0 :                 if (l > 1000)
     141           0 :                         l = 1000;
     142           0 :                 strncpy(tmp, src, l);
     143           0 :                 tmp[l] = 0;
     144           0 :                 fprintf(stderr, "Wrong result in %s\n Got: '%s' len %d\n Expected: '%s' len %u\n", test_name, tmp,
     145           0 :                         curcol->column_cur_size, buf, (unsigned int) strlen(buf));
     146           0 :                 exit(1);
     147             :         }
     148             : 
     149        3088 :         rc = tds_process_tokens(tds, &result_type, NULL, TDS_STOPAT_ROWFMT|TDS_RETURN_DONE|TDS_RETURN_ROW|TDS_RETURN_COMPUTE);
     150        3088 :         if (rc != TDS_SUCCESS || result_type == TDS_ROW_RESULT) {
     151           0 :                 fprintf(stderr, "tds_process_tokens() unexpected return\n");
     152           0 :                 exit(1);
     153             :         }
     154             : 
     155        3088 :         while ((rc = tds_process_tokens(tds, &result_type, &done_flags, TDS_TOKEN_RESULTS)) == TDS_SUCCESS) {
     156           0 :                 switch (result_type) {
     157             :                 case TDS_NO_MORE_RESULTS:
     158             :                         break;
     159             : 
     160           0 :                 case TDS_DONE_RESULT:
     161             :                 case TDS_DONEPROC_RESULT:
     162             :                 case TDS_DONEINPROC_RESULT:
     163           0 :                         if (!(done_flags & TDS_DONE_ERROR))
     164             :                                 break;
     165             : 
     166             :                 default:
     167           0 :                         fprintf(stderr, "tds_process_tokens() unexpected result_type\n");
     168           0 :                         exit(1);
     169             :                         break;
     170             :                 }
     171           0 :         }
     172        3088 : }
     173             : 
     174             : static int
     175        1544 : err_handler(const TDSCONTEXT * tds_ctx TDS_UNUSED, TDSSOCKET * tds TDS_UNUSED, TDSMESSAGE * msg)
     176             : {
     177        1544 :         int error = 0;
     178             : 
     179        1544 :         if (strstr(msg->message, "EINVAL")) {
     180           0 :                 ++einval_count;
     181           0 :                 if (einval_error)
     182             :                         error = 1;
     183        1544 :         } else if (strstr(msg->message, "could not be converted")) {
     184        1544 :                 ++eilseq_count;
     185        1544 :                 if (eilseq_error)
     186             :                         error = 1;
     187           0 :         } else if (strstr(msg->message, "E2BIG")) {
     188           0 :                 ++e2big_count;
     189           0 :                 error = 1;
     190             :         } else {
     191             :                 error = 1;
     192             :         }
     193             : 
     194             :         if (error) {
     195           0 :                 fprintf(stderr, "Unexpected in %s error: %s\n", test_name, msg->message);
     196           0 :                 g_result = 1;
     197             :         }
     198        1544 :         return TDS_INT_CANCEL;
     199             : }
     200             : 
     201             : int
     202           8 : main(void)
     203             : {
     204             :         TDSLOGIN *login;
     205             :         int ret;
     206           8 :         int verbose = 0;
     207             :         int i;
     208             :         typedef int (*perr)(const TDSCONTEXT *, TDSSOCKET *, TDSMESSAGE *);
     209             :         const perr * my_err;
     210             : 
     211             :         /* use ISO8859-1 as our coding */
     212           8 :         strcpy(CHARSET, "ISO8859-1");
     213             : 
     214           8 :         ret = try_tds_login(&login, &tds, __FILE__, verbose);
     215           8 :         if (ret != TDS_SUCCESS) {
     216           0 :                 fprintf(stderr, "try_tds_login() failed\n");
     217           0 :                 return 1;
     218             :         }
     219             : 
     220             :         /* override a const in a safe way */
     221           8 :         my_err = &tds_get_ctx(tds)->err_handler;
     222           8 :         *((perr*)my_err) = err_handler;
     223             : 
     224             :         /* prepend some characters to check part of sequence error */
     225           8 :         einval_error = 1;
     226           8 :         eilseq_error = 1;
     227             :         /* do not stop on first error so we check conversion correct */
     228        1552 :         for (i = 0; i <= 192; ++i)
     229        1544 :                 test(i, 0);
     230             : 
     231             :         /* try creating a double conversion warning */
     232           8 :         eilseq_error = 0;
     233           8 :         einval_error = 0;       /* we already tested this error above */
     234        1552 :         for (i = 0; i <= 192; ++i) {
     235        1544 :                 eilseq_count = 0;
     236        1544 :                 test(i, 1);
     237        1544 :                 if (eilseq_count > 1) {
     238           0 :                         fprintf(stderr, "Two warnings returned instead of one in %s\n", test_name);
     239           0 :                         g_result = 1;
     240           0 :                         break;
     241             :                 }
     242        1544 :                 if (eilseq_count < 1 && invalid_char == '?') {
     243           0 :                         fprintf(stderr, "No warning returned in %s\n", test_name);
     244           0 :                         g_result = 1;
     245             :                 }
     246             :         }
     247             : 
     248           8 :         try_tds_logout(login, tds, verbose);
     249           8 :         return g_result;
     250             : }

Generated by: LCOV version 1.13