LCOV - code coverage report
Current view: top level - src/odbc/unittests - utf8_2.c (source / functions) Hit Total Coverage
Test: FreeTDS coverage Lines: 25 43 58.1 %
Date: 2025-12-03 08:48:55 Functions: 1 2 50.0 %

          Line data    Source code
       1             : #include "common.h"
       2             : #include <freetds/macros.h>
       3             : 
       4             : /* test conversion of Hebrew characters (which have shift sequences) */
       5             : 
       6             : static const char * const column_names[] = {
       7             :         "hebrew",
       8             :         "cn"
       9             : };
      10             : 
      11             : typedef struct {
      12             :         /* number of column */
      13             :         int num;
      14             :         /* hex representation, used during insert */
      15             :         const char *hex;
      16             :         /* output */
      17             :         const char *out;
      18             : } column_t;
      19             : 
      20             : static const column_t columns[] = {
      21             :         { 0, "0xde05d905d305e205", "\xd7\x9e\xd7\x99\xd7\x93\xd7\xa2" },
      22             :         { 0, "0x69006e0066006f00", "info", },
      23             :         { 0, "0xd805e705e105d805", "\xd7\x98\xd7\xa7\xd7\xa1\xd7\x98", },
      24             :         { 0, "0xd005d105db05", "\xd7\x90\xd7\x91\xd7\x9b", },
      25             :         { 1, "0xf78b7353d153278d3a00228c228c56e02000",
      26             :              "\xe8\xaf\xb7\xe5\x8d\xb3\xe5\x8f\x91\xe8\xb4\xa7\x3a\xe8\xb0\xa2\xe8\xb0\xa2\xee\x81\x96\x20", },
      27             :         { 0, NULL, NULL },
      28             : };
      29             : 
      30             : static void
      31           0 : hexdump(FILE* fp, const char* prefix, const void* p, size_t n)
      32             : {
      33           0 :         const unsigned char* cp = p;
      34             : 
      35           0 :         fprintf(fp, "%s", prefix);
      36           0 :         while (n--)
      37           0 :                 fprintf(fp, "%02X", *cp++);
      38           0 :         fprintf(fp, "\n");
      39           0 : }
      40             : 
      41          10 : TEST_MAIN()
      42             : {
      43             :         char tmp[1024];
      44             :         char out[TDS_VECTOR_SIZE(column_names)][32];
      45             :         SQLLEN n_len[TDS_VECTOR_SIZE(column_names)];
      46             :         const column_t *p;
      47             :         int n;
      48             : 
      49          10 :         odbc_use_version3 = true;
      50          10 :         odbc_conn_additional_params = "ClientCharset=UTF-8;";
      51             : 
      52          10 :         odbc_connect();
      53          10 :         if (!odbc_driver_is_freetds()) {
      54           0 :                 odbc_disconnect();
      55           0 :                 printf("Driver is not FreeTDS, exiting\n");
      56           0 :                 odbc_test_skipped();
      57           0 :                 return 0;
      58             :         }
      59             : 
      60          10 :         if (!odbc_db_is_microsoft() || odbc_db_version_int() < 0x08000000u || odbc_tds_version() < 0x701) {
      61           2 :                 odbc_disconnect();
      62             :                 /* protocol till 7.1 does not support telling encoding so we
      63             :                  * cannot understand how the string is encoded
      64             :                  */
      65           2 :                 printf("Test for MSSQL only using protocol 7.1\n");
      66           2 :                 odbc_test_skipped();
      67           0 :                 return 0;
      68             :         }
      69             : 
      70           8 :         CHKAllocStmt(&odbc_stmt, "S");
      71             : 
      72             :         /* create test table */
      73           8 :         odbc_command("CREATE TABLE #tmp (i INT"
      74             :                      ", hebrew VARCHAR(20) COLLATE Hebrew_CI_AI NULL"
      75             :                      ", cn VARCHAR(20) COLLATE Chinese_PRC_CI_AS NULL"
      76             :                      ")");
      77             : 
      78             :         /* insert with INSERT statements */
      79          48 :         for (n = 0, p = columns; p[n].hex; ++n) {
      80          80 :                 sprintf(tmp, "INSERT INTO #tmp(i, %s) VALUES(%d, CAST(%s AS NVARCHAR(20)))",
      81          40 :                              column_names[p[n].num], n+1, p[n].hex);
      82          40 :                 odbc_command(tmp);
      83             :         }
      84             : 
      85             :         /* test conversions in libTDS
      86             :          *
      87             :          * Because column type is VARCHAR with collation defined, SQL Server
      88             :          * returns the data as CP1255 (hebrew) or GB18030 (CN), and FreeTDS's
      89             :          * built-in iconv doesn't support those. So you need iconv installed
      90             :          * in Windows to pass this test.
      91             :          *
      92             :          * Using NVARCHAR makes this test work with FreeTDS's built-in iconv
      93             :          * as it causes the server to return the data in wide characters.
      94             :         */
      95             : #if HAVE_ICONV
      96           8 :         odbc_command("SELECT hebrew, cn FROM #tmp ORDER BY i");
      97             : #else
      98             :         fprintf(stderr, "Bypassing Hebrew MBCS test since iconv not installed (Forcing server to send UTF-16).\n");
      99             :         odbc_command("SELECT CAST(hebrew AS NVARCHAR(20)), CAST(cn AS NVARCHAR(20)) FROM #tmp ORDER BY i");
     100             : #endif
     101             :         /* insert with SQLPrepare/SQLBindParameter/SQLExecute */
     102          24 :         for (n = 0; n < TDS_VECTOR_SIZE(column_names); ++n)
     103          16 :                 CHKBindCol(n+1, SQL_C_CHAR, out[n], sizeof(out[0]), &n_len[n], "S");
     104          40 :         for (n = 0, p = columns; p[n].hex; ++n) {
     105          40 :                 memset(out, 0, sizeof(out));
     106          40 :                 CHKFetch("S");
     107          40 :                 if (n_len[p[n].num] != strlen(p[n].out) || strcmp(p[n].out, out[p[n].num]) != 0) {
     108           0 :                         size_t len = strlen(p[n].out);
     109             : 
     110           0 :                         fprintf(stderr, "Wrong row %d %s\n", n+1, out[p[n].num]);
     111           0 :                         hexdump(stderr, "Expect: ", p[n].out, len);
     112           0 :                         hexdump(stderr, "Got   : ", out[p[n].num], strlen(out[p[n].num]));
     113           0 :                         odbc_disconnect();
     114           0 :                         return 1;
     115             :                 }
     116             :         }
     117             : 
     118           8 :         odbc_disconnect();
     119           8 :         printf("Done.\n");
     120           8 :         return 0;
     121             : }
     122             : 

Generated by: LCOV version 1.13