LCOV - code coverage report
Current view: top level - src/apps/unittests - defncopy.c (source / functions) Hit Total Coverage
Test: FreeTDS coverage Lines: 76 86 88.4 %
Date: 2026-05-04 13:14:38 Functions: 6 6 100.0 %

          Line data    Source code
       1             : /* FreeTDS - Library of routines accessing Sybase and Microsoft databases
       2             :  * Copyright (C) 2024  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             : 
      20             : /**
      21             :  * This tests execute some command using tsql and defncopy to check behaviour
      22             :  */
      23             : 
      24             : #include "common.h"
      25             : 
      26             : #if HAVE_STRING_H
      27             : #include <string.h>
      28             : #endif /* HAVE_STRING_H */
      29             : 
      30             : #ifdef HAVE_UNISTD_H
      31             : #include <unistd.h>
      32             : #endif
      33             : 
      34             : #include <freetds/sysdep_private.h>
      35             : #include <freetds/replacements.h>
      36             : 
      37             : /* content of output file, from command executed */
      38             : static char *output;
      39             : 
      40             : static bool
      41             : read_login_info(void)
      42             : {
      43          10 :         return read_login_info_base(&common_pwd, DEFAULT_PWD_PATH) != NULL;
      44             : }
      45             : 
      46             : static void
      47          20 : cleanup(void)
      48             : {
      49          20 :         unlink("empty");
      50          20 :         unlink(output_fn());
      51          20 :         unlink(input_fn());
      52          20 :         TDS_ZERO_FREE(output);
      53          20 : }
      54             : 
      55             : static void
      56          30 : defncopy(const char *object_name)
      57             : {
      58             :         char cmd[2048];
      59          30 :         char *const end = cmd + sizeof(cmd) - 1;
      60             :         char *p;
      61             :         FILE *f;
      62             : 
      63             :         /* empty input */
      64          30 :         f = fopen(input_fn(), "w");
      65          30 :         assert(f);
      66          30 :         fclose(f);
      67             : 
      68          30 :         strcpy(cmd, "defncopy" EXE_SUFFIX);
      69          30 :         p = strchr(cmd, 0);
      70          30 :         p = add_server(p, end);
      71          30 :         p = add_string(p, end, " ");
      72          30 :         p = quote_arg(p, end, object_name);
      73          30 :         p = add_string(p, end, "<");
      74          30 :         p = add_string(p, end, input_fn());
      75          30 :         p = add_string(p, end, " >");
      76          30 :         p = add_string(p, end, output_fn());
      77          30 :         *p = 0;
      78          30 :         printf("Executing: %s\n", cmd);
      79          30 :         if (system(cmd) != 0) {
      80           0 :                 printf("Output is:\n");
      81           0 :                 cat(output_fn(), stdout);
      82           0 :                 fprintf(stderr, "Failed command\n");
      83           0 :                 exit(1);
      84             :         }
      85          30 :         TDS_ZERO_FREE(output);
      86          30 :         output = read_file(output_fn());
      87          30 : }
      88             : 
      89             : /* table with a column name that is also a keyword, should be quoted */
      90             : static void
      91          10 : test_keyword(void)
      92             : {
      93             :         const char *sql;
      94             :         static const char clean[] =
      95             :                 "IF OBJECT_ID('dbo.table_with_column_named_key') IS NOT NULL DROP TABLE dbo.table_with_column_named_key\n";
      96             : 
      97          10 :         tsql(clean);
      98          10 :         tsql(
      99             : "IF OBJECT_ID('dbo.table_with_column_named_key') IS NOT NULL DROP TABLE dbo.table_with_column_named_key\n"
     100             : "GO\n"
     101             : "CREATE TABLE dbo.table_with_column_named_key\n"
     102             : "(\n"
     103             : "  [key]        nvarchar(4000)  NOT NULL\n"
     104             : ")\n");
     105          10 :         defncopy("dbo.table_with_column_named_key");
     106          10 :         cat(output_fn(), stdout);
     107          10 :         normalize_spaces(output);
     108          10 :         sql =
     109             : "CREATE TABLE [dbo].[table_with_column_named_key]\n"
     110             : " ( [key] nvarchar(4000) NOT NULL\n"
     111             : " )\n"
     112             : "GO";
     113          10 :         if (strstr(output, sql) == NULL) {
     114           0 :                 fprintf(stderr, "Expected SQL string not found\n");
     115           0 :                 exit(1);
     116             :         }
     117          10 :         tsql(clean);
     118          10 :         tsql(sql);
     119          10 :         tsql(clean);
     120          10 : }
     121             : 
     122             : /* table with an index with a space inside */
     123             : static void
     124          10 : test_index_name_with_space(void)
     125             : {
     126             :         const char *sql;
     127             :         static const char clean[] =
     128             :                 "IF OBJECT_ID('dbo.tblReportPeriod') IS NOT NULL DROP TABLE dbo.tblReportPeriod\n";
     129             : 
     130          10 :         tsql(clean);
     131          10 :         tsql(
     132             : "CREATE TABLE dbo.tblReportPeriod\n"
     133             : "  ( RecordID   int             NOT NULL\n"
     134             : "  , FromDate   nvarchar(40)        NULL\n"
     135             : "  , ToDate     nvarchar(40)        NULL\n"
     136             : "  )\n"
     137             : "CREATE  nonclustered INDEX [From Date] on dbo.tblReportPeriod(FromDate)\n");
     138          10 :         defncopy("dbo.tblReportPeriod");
     139          10 :         cat(output_fn(), stdout);
     140          10 :         normalize_spaces(output);
     141          10 :         sql =
     142             : "CREATE TABLE [dbo].[tblReportPeriod]\n"
     143             : " ( [RecordID] int NOT NULL\n"
     144             : " , [FromDate] nvarchar(40) NULL\n"
     145             : " , [ToDate] nvarchar(40) NULL\n"
     146             : " )\n"
     147             : "GO\n"
     148             : "\n"
     149             : "CREATE nonclustered INDEX [From Date] on [dbo].[tblReportPeriod]([FromDate])";
     150          10 :         if (strstr(output, sql) == NULL) {
     151           0 :                 fprintf(stderr, "Expected SQL string not found\n");
     152           0 :                 exit(1);
     153             :         }
     154          10 :         tsql(clean);
     155          10 :         tsql(sql);
     156          10 :         tsql(clean);
     157          10 : }
     158             : 
     159             : /* table with an index with a space inside */
     160             : static void
     161          10 : test_weird_index_names(void)
     162             : {
     163             :         const char *sql, *sql_sybase;
     164             :         static const char clean[] =
     165             :                 "IF OBJECT_ID('dbo.tblReportPeriod2') IS NOT NULL DROP TABLE dbo.tblReportPeriod2\n";
     166             : 
     167          10 :         tsql(clean);
     168          10 :         tsql(
     169             : "CREATE TABLE dbo.tblReportPeriod2\n"
     170             : "  ( RecordID   int             NOT NULL\n"
     171             : "  , [To, ]   nvarchar(40)        NULL\n"
     172             : "  , [To]     nvarchar(40)        NULL\n"
     173             : "  , [To, , ]     nvarchar(40)        NULL\n"
     174             : "  )\n"
     175             : "CREATE  nonclustered INDEX [From Date] on dbo.tblReportPeriod2([To, ],[To, , ])\n");
     176          10 :         defncopy("dbo.tblReportPeriod2");
     177          10 :         cat(output_fn(), stdout);
     178          10 :         normalize_spaces(output);
     179          10 :         sql =
     180             : "CREATE TABLE [dbo].[tblReportPeriod2]\n"
     181             : " ( [RecordID] int NOT NULL\n"
     182             : " , [To, ] nvarchar(40) NULL\n"
     183             : " , [To] nvarchar(40) NULL\n"
     184             : " , [To, , ] nvarchar(40) NULL\n"
     185             : " )\n"
     186             : "GO\n"
     187             : "\n"
     188             : "CREATE nonclustered INDEX [From Date] on [dbo].[tblReportPeriod2]([To, ],[To, , ])";
     189             :         /* Sybase remove spaces at the end */
     190          10 :         sql_sybase =
     191             : "CREATE TABLE [dbo].[tblReportPeriod2]\n"
     192             : " ( [RecordID] int NOT NULL\n"
     193             : " , [To,] nvarchar(40) NULL\n"
     194             : " , [To] nvarchar(40) NULL\n"
     195             : " , [To, ,] nvarchar(40) NULL\n"
     196             : " )\n"
     197             : "GO\n"
     198             : "\n"
     199             : "CREATE nonclustered INDEX [From Date] on [dbo].[tblReportPeriod2]([To,],[To, ,])";
     200          10 :         if (strstr(output, sql) == NULL && strstr(output, sql_sybase) == NULL) {
     201           0 :                 fprintf(stderr, "Expected SQL string not found\n");
     202           0 :                 exit(1);
     203             :         }
     204          10 :         tsql(clean);
     205          10 :         tsql(sql);
     206          10 :         tsql(clean);
     207          10 : }
     208             : 
     209          10 : TEST_MAIN()
     210             : {
     211             :         FILE *f;
     212             : 
     213          10 :         cleanup();
     214          10 :         update_path();
     215             : 
     216          10 :         if (!read_login_info())
     217             :                 return 1;
     218             : 
     219          10 :         f = fopen("empty", "w");
     220          10 :         if (f)
     221          10 :                 fclose(f);
     222             : 
     223          10 :         test_keyword();
     224          10 :         test_index_name_with_space();
     225          10 :         test_weird_index_names();
     226             : 
     227          10 :         cleanup();
     228          10 :         return 0;
     229             : }

Generated by: LCOV version 1.13