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

Generated by: LCOV version 1.13