LCOV - code coverage report
Current view: top level - src/dblib/unittests - t0016.c (source / functions) Hit Total Coverage
Test: FreeTDS coverage Lines: 146 176 83.0 %
Date: 2025-05-13 09:49:23 Functions: 7 8 87.5 %

          Line data    Source code
       1             : /* 
       2             :  * Purpose: Test bcp in and out, and specifically bcp_colfmt()
       3             :  * Functions: bcp_colfmt bcp_columns bcp_exec bcp_init 
       4             :  */
       5             : 
       6             : #include "common.h"
       7             : 
       8             : #include <freetds/bool.h>
       9             : #include <freetds/replacements.h>
      10             : 
      11             : static bool failed = false;
      12             : 
      13             : static void
      14           0 : failure(const char *fmt, ...)
      15             : {
      16             :         va_list ap;
      17             : 
      18           0 :         failed = true;
      19             : 
      20           0 :         va_start(ap, fmt);
      21           0 :         vfprintf(stderr, fmt, ap);
      22           0 :         va_end(ap);
      23           0 : }
      24             : 
      25             : #define INFILE_NAME "t0016"
      26             : #define TABLE_NAME "#dblib0016"
      27             : 
      28             : static void test_file(const char *fn);
      29             : static bool compare_files(const char *fn1, const char *fn2);
      30             : static unsigned count_file_rows(FILE *f);
      31             : static DBPROCESS *dbproc;
      32             : 
      33          10 : TEST_MAIN()
      34             : {
      35             :         LOGINREC *login;
      36             :         char in_file[30];
      37             :         unsigned int n;
      38             : 
      39          10 :         setbuf(stdout, NULL);
      40          10 :         setbuf(stderr, NULL);
      41             : 
      42          10 :         set_malloc_options();
      43             : 
      44          10 :         read_login_info(argc, argv);
      45          10 :         printf("Starting %s\n", argv[0]);
      46          10 :         dbsetversion(DBVERSION_100);
      47          10 :         dbinit();
      48             : 
      49          10 :         dberrhandle(syb_err_handler);
      50          10 :         dbmsghandle(syb_msg_handler);
      51             : 
      52          10 :         printf("About to logon\n");
      53             : 
      54          10 :         login = dblogin();
      55          10 :         BCP_SETL(login, TRUE);
      56          10 :         DBSETLPWD(login, PASSWORD);
      57          10 :         DBSETLUSER(login, USER);
      58          10 :         DBSETLAPP(login, "t0016");
      59          10 :         DBSETLCHARSET(login, "utf8");
      60             : 
      61          10 :         dbproc = dbopen(login, SERVER);
      62          10 :         if (strlen(DATABASE)) {
      63          10 :                 dbuse(dbproc, DATABASE);
      64             :         }
      65          10 :         dbloginfree(login);
      66          10 :         printf("After logon\n");
      67             : 
      68          10 :         strcpy(in_file, INFILE_NAME);
      69         140 :         for (n = 1; n <= 100; ++n) {
      70         140 :                 test_file(in_file);
      71         140 :                 sprintf(in_file, "%s_%d", INFILE_NAME, n);
      72         140 :                 if (sql_reopen(in_file) != SUCCEED)
      73             :                         break;
      74             :         }
      75             : 
      76          10 :         dbclose(dbproc);
      77          10 :         dbexit();
      78             : 
      79          10 :         printf("dblib %s on %s\n", (failed ? "failed!" : "okay"), __FILE__);
      80          10 :         return failed ? 1 : 0;
      81             : }
      82             : 
      83             : static bool got_error = false;
      84             : 
      85             : static int
      86          16 : ignore_msg_handler(DBPROCESS * dbproc TDS_UNUSED, DBINT msgno TDS_UNUSED, int state TDS_UNUSED, int severity TDS_UNUSED,
      87             :                    char *text TDS_UNUSED, char *server TDS_UNUSED, char *proc TDS_UNUSED, int line TDS_UNUSED)
      88             : {
      89          16 :         got_error = true;
      90          16 :         return 0;
      91             : }
      92             : 
      93             : static int
      94          16 : ignore_err_handler(DBPROCESS * dbproc TDS_UNUSED, int severity TDS_UNUSED, int dberr TDS_UNUSED,
      95             :                    int oserr TDS_UNUSED, char *dberrstr TDS_UNUSED, char *oserrstr TDS_UNUSED)
      96             : {
      97          16 :         got_error = true;
      98          16 :         return INT_CANCEL;
      99             : }
     100             : 
     101             : static char line1[1024*16];
     102             : static char line2[1024*16];
     103             : 
     104             : static void
     105         140 : test_file(const char *fn)
     106             : {
     107             :         int i;
     108             :         RETCODE ret;
     109         140 :         int num_cols = 0;
     110         140 :         const char *out_file = "t0016.out";
     111         140 :         const char *err_file = "t0016.err";
     112             :         DBINT rows_copied;
     113         140 :         unsigned num_rows = 2;
     114             : 
     115             :         FILE *input_file;
     116             : 
     117             :         char in_file[256];
     118         140 :         snprintf(in_file, sizeof(in_file), "%s/%s.in", FREETDS_SRCDIR, fn);
     119             : 
     120         140 :         input_file = fopen(in_file, "rb");
     121         140 :         if (!input_file) {
     122           0 :                 sprintf(in_file, "%s.in", fn);
     123           0 :                 input_file = fopen(in_file, "rb");
     124             :         }
     125         140 :         if (!input_file) {
     126           0 :                 fprintf(stderr, "could not open %s\n", in_file);
     127           0 :                 exit(1);
     128             :         }
     129         140 :         num_rows = count_file_rows(input_file);
     130         140 :         fclose(input_file);
     131             : 
     132         140 :         dberrhandle(ignore_err_handler);
     133         140 :         dbmsghandle(ignore_msg_handler);
     134             : 
     135         140 :         printf("Creating table '%s'\n", TABLE_NAME);
     136         140 :         got_error = false;
     137         140 :         sql_cmd(dbproc);
     138         140 :         dbsqlexec(dbproc);
     139         414 :         while (dbresults(dbproc) != NO_MORE_RESULTS)
     140         134 :                 continue;
     141             : 
     142         140 :         dberrhandle(syb_err_handler);
     143         140 :         dbmsghandle(syb_msg_handler);
     144             : 
     145         140 :         if (got_error)
     146          16 :                 return;
     147             : 
     148         124 :         ret = sql_cmd(dbproc);
     149         124 :         printf("return from dbcmd = %d\n", ret);
     150             : 
     151         124 :         ret = dbsqlexec(dbproc);
     152         124 :         printf("return from dbsqlexec = %d\n", ret);
     153             : 
     154         124 :         if (dbresults(dbproc) != FAIL) {
     155         124 :                 num_cols = dbnumcols(dbproc);
     156         124 :                 printf("Number of columns = %d\n", num_cols);
     157             : 
     158         124 :                 while (dbnextrow(dbproc) != NO_MORE_ROWS) {
     159             :                 }
     160             :         }
     161             : 
     162             :         /* BCP in */
     163             : 
     164         124 :         printf("bcp_init with in_file as '%s'\n", in_file);
     165         124 :         ret = bcp_init(dbproc, TABLE_NAME, in_file, (char*) err_file, DB_IN);
     166         124 :         if (ret != SUCCEED)
     167           0 :                 failure("bcp_init failed\n");
     168             : 
     169         124 :         printf("return from bcp_init = %d\n", ret);
     170             : 
     171         124 :         ret = bcp_columns(dbproc, num_cols);
     172         124 :         if (ret != SUCCEED)
     173           0 :                 failure("bcp_columns failed\n");
     174         124 :         printf("return from bcp_columns = %d\n", ret);
     175             : 
     176         720 :         for (i = 1; i < num_cols; i++) {
     177         596 :                 if ((ret = bcp_colfmt(dbproc, i, SYBCHAR, 0, -1, (BYTE *) "\t", sizeof(char), i)) == FAIL)
     178           0 :                         failure("return from bcp_colfmt = %d\n", ret);
     179             :         }
     180             : 
     181         124 :         if ((ret = bcp_colfmt(dbproc, num_cols, SYBCHAR, 0, -1, (BYTE *) "\n", sizeof(char), num_cols)) == FAIL)
     182           0 :                 failure("return from bcp_colfmt = %d\n", ret);
     183             : 
     184             : 
     185         124 :         ret = bcp_exec(dbproc, &rows_copied);
     186         124 :         if (ret != SUCCEED || rows_copied != num_rows)
     187           0 :                 failure("bcp_exec failed\n");
     188             : 
     189         124 :         printf("%d rows copied in\n", rows_copied);
     190             : 
     191             :         /* BCP out */
     192             : 
     193         124 :         rows_copied = 0;
     194         124 :         ret = bcp_init(dbproc, TABLE_NAME, (char *) out_file, (char *) err_file, DB_OUT);
     195         124 :         if (ret != SUCCEED)
     196           0 :                 failure("bcp_int failed\n");
     197             : 
     198         124 :         printf("select\n");
     199         124 :         sql_cmd(dbproc);
     200         124 :         dbsqlexec(dbproc);
     201             : 
     202         124 :         if (dbresults(dbproc) != FAIL) {
     203         124 :                 num_cols = dbnumcols(dbproc);
     204         124 :                 while (dbnextrow(dbproc) != NO_MORE_ROWS) {
     205             :                 }
     206             :         }
     207             : 
     208         124 :         ret = bcp_columns(dbproc, num_cols);
     209             : 
     210         720 :         for (i = 1; i < num_cols; i++) {
     211         596 :                 if ((ret = bcp_colfmt(dbproc, i, SYBCHAR, 0, -1, (BYTE *) "\t", sizeof(char), i)) == FAIL)
     212           0 :                         failure("return from bcp_colfmt = %d\n", ret);
     213             :         }
     214             : 
     215         124 :         if ((ret = bcp_colfmt(dbproc, num_cols, SYBCHAR, 0, -1, (BYTE *) "\n", sizeof(char), num_cols)) == FAIL)
     216           0 :                 failure("return from bcp_colfmt = %d\n", ret);
     217             : 
     218         124 :         ret = bcp_exec(dbproc, &rows_copied);
     219         124 :         if (ret != SUCCEED || rows_copied != num_rows)
     220           0 :                 failure("bcp_exec failed\n");
     221             : 
     222         124 :         printf("%d rows copied out\n", rows_copied);
     223             : 
     224         124 :         printf("Dropping table '%s'\n", TABLE_NAME);
     225         124 :         sql_cmd(dbproc);
     226         124 :         dbsqlexec(dbproc);
     227         372 :         while (dbresults(dbproc) != NO_MORE_RESULTS)
     228         124 :                 continue;
     229             : 
     230         124 :         if (failed)
     231             :                 return;
     232             : 
     233         124 :         if (compare_files(in_file, out_file))
     234         124 :                 printf("Input and output files are equal\n");
     235             :         else
     236           0 :                 failed = true;
     237             : }
     238             : 
     239             : static size_t
     240        1208 : fgets_raw(char *s, int len, FILE *f)
     241             : {
     242        1208 :         char *p = s;
     243             : 
     244      724630 :         while (len > 1) {
     245      723422 :                 int c = getc(f);
     246      723422 :                 if (c == EOF) {
     247         388 :                         if (ferror(f))
     248             :                                 return 0;
     249             :                         break;
     250             :                 }
     251      723034 :                 *p++ = c;
     252      723034 :                 --len;
     253      723034 :                 if (c == '\n')
     254             :                         break;
     255             :         }
     256        1208 :         if (len > 0)
     257        1208 :                 *p = 0;
     258        1208 :         return p - s;
     259             : }
     260             : 
     261             : static bool
     262         124 : compare_files(const char *fn1, const char *fn2)
     263             : {
     264         124 :         bool equal = true;
     265             :         FILE *f1, *f2;
     266             :         size_t s1, s2;
     267             : 
     268             :         /* check input and output should be the same */
     269         124 :         f1 = fopen(fn1, "r");
     270         124 :         f2 = fopen(fn2, "r");
     271         124 :         if (f1 != NULL && f2 != NULL) {
     272             :                 int line = 1;
     273             : 
     274         260 :                 for (;; ++line) {
     275         644 :                         s1 = fgets_raw(line1, sizeof(line1), f1);
     276         384 :                         s2 = fgets_raw(line2, sizeof(line2), f2);
     277             : 
     278             :                         /* EOF or error of one */
     279         384 :                         if (!!s1 != !!s2) {
     280           0 :                                 equal = false;
     281           0 :                                 failure("error reading a file or EOF of a file\n");
     282           0 :                                 break;
     283             :                         }
     284             : 
     285             :                         /* EOF or error of both */
     286         384 :                         if (!s1) {
     287         124 :                                 if (feof(f1) && feof(f2))
     288             :                                         break;
     289           0 :                                 equal = false;
     290           0 :                                 failure("error reading a file\n");
     291           0 :                                 break;
     292             :                         }
     293             : 
     294         260 :                         if (s1 != s2 || memcmp(line1, line2, s1) != 0) {
     295           0 :                                 equal = false;
     296           0 :                                 failure("File different at line %d\n"
     297             :                                         " input: %s"
     298             :                                         " output: %s",
     299             :                                         line, line1, line2);
     300             :                         }
     301             :                 }
     302             :         } else {
     303           0 :                 equal = false;
     304           0 :                 failure("error opening files\n");
     305             :         }
     306         124 :         if (f1)
     307         124 :                 fclose(f1);
     308         124 :         if (f2)
     309         124 :                 fclose(f2);
     310             : 
     311         124 :         return equal;
     312             : }
     313             : 
     314             : static unsigned
     315         140 : count_file_rows(FILE *f)
     316             : {
     317             :         size_t s;
     318         140 :         unsigned rows = 1;
     319         140 :         char last = '\n';
     320             : 
     321         140 :         assert(f);
     322             : 
     323         440 :         while ((s = fgets_raw(line1, sizeof(line1), f)) != 0) {
     324         300 :                 last = line1[s-1];
     325         300 :                 if (last == '\n')
     326         300 :                         ++rows;
     327             :         }
     328         140 :         if (last == '\n')
     329         140 :                 --rows;
     330         140 :         assert(!ferror(f));
     331         140 :         return rows;
     332             : }

Generated by: LCOV version 1.13