LCOV - code coverage report
Current view: top level - src/interfaces/ecpg/test - pg_regress_ecpg.c (source / functions) Coverage Total Hit
Test: Code coverage Lines: 0.0 % 125 0
Test Date: 2026-01-26 10:56:24 Functions: 0.0 % 6 0
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /*-------------------------------------------------------------------------
       2              :  *
       3              :  * pg_regress_ecpg --- regression test driver for ecpg
       4              :  *
       5              :  * This is a C implementation of the previous shell script for running
       6              :  * the regression tests, and should be mostly compatible with it.
       7              :  * Initial author of C translation: Magnus Hagander
       8              :  *
       9              :  * This code is released under the terms of the PostgreSQL License.
      10              :  *
      11              :  * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
      12              :  * Portions Copyright (c) 1994, Regents of the University of California
      13              :  *
      14              :  * src/interfaces/ecpg/test/pg_regress_ecpg.c
      15              :  *
      16              :  *-------------------------------------------------------------------------
      17              :  */
      18              : 
      19              : #include "postgres_fe.h"
      20              : 
      21              : #include "common/string.h"
      22              : #include "lib/stringinfo.h"
      23              : #include "pg_regress.h"
      24              : 
      25              : 
      26              : /*
      27              :  * Create a filtered copy of sourcefile, removing any path
      28              :  * appearing in #line directives; for example, replace
      29              :  * #line x "./../bla/foo.h" with #line x "foo.h".
      30              :  * This is needed because the path part can vary depending
      31              :  * on compiler, platform, build options, etc.
      32              :  */
      33              : static void
      34            0 : ecpg_filter_source(const char *sourcefile, const char *outfile)
      35              : {
      36            0 :         FILE       *s,
      37              :                            *t;
      38            0 :         StringInfoData linebuf;
      39              : 
      40            0 :         s = fopen(sourcefile, "r");
      41            0 :         if (!s)
      42              :         {
      43            0 :                 fprintf(stderr, "Could not open file %s for reading\n", sourcefile);
      44            0 :                 exit(2);
      45              :         }
      46            0 :         t = fopen(outfile, "w");
      47            0 :         if (!t)
      48              :         {
      49            0 :                 fprintf(stderr, "Could not open file %s for writing\n", outfile);
      50            0 :                 exit(2);
      51              :         }
      52              : 
      53            0 :         initStringInfo(&linebuf);
      54              : 
      55            0 :         while (pg_get_line_buf(s, &linebuf))
      56              :         {
      57              :                 /* check for "#line " in the beginning */
      58            0 :                 if (strstr(linebuf.data, "#line ") == linebuf.data)
      59              :                 {
      60            0 :                         char       *p = strchr(linebuf.data, '"');
      61            0 :                         int                     plen = 1;
      62              : 
      63            0 :                         while (*p && (*(p + plen) == '.' || strchr(p + plen, '/') != NULL))
      64              :                         {
      65            0 :                                 plen++;
      66              :                         }
      67              :                         /* plen is one more than the number of . and / characters */
      68            0 :                         if (plen > 1)
      69              :                         {
      70            0 :                                 memmove(p + 1, p + plen, strlen(p + plen) + 1);
      71              :                                 /* we don't bother to fix up linebuf.len */
      72            0 :                         }
      73            0 :                 }
      74            0 :                 fputs(linebuf.data, t);
      75              :         }
      76              : 
      77            0 :         pfree(linebuf.data);
      78            0 :         fclose(s);
      79            0 :         fclose(t);
      80            0 : }
      81              : 
      82              : /*
      83              :  * Remove the details of connection failure error messages
      84              :  * in a test result file, since the target host/pathname and/or port
      85              :  * can vary.  Rewrite the result file in-place.
      86              :  *
      87              :  * At some point it might be interesting to unify this with
      88              :  * ecpg_filter_source, but building a general pattern matcher
      89              :  * is no fun, nor does it seem desirable to introduce a
      90              :  * dependency on an external one.
      91              :  */
      92              : static void
      93            0 : ecpg_filter_stderr(const char *resultfile, const char *tmpfile)
      94              : {
      95            0 :         FILE       *s,
      96              :                            *t;
      97            0 :         StringInfoData linebuf;
      98              : 
      99            0 :         s = fopen(resultfile, "r");
     100            0 :         if (!s)
     101              :         {
     102            0 :                 fprintf(stderr, "Could not open file %s for reading\n", resultfile);
     103            0 :                 exit(2);
     104              :         }
     105            0 :         t = fopen(tmpfile, "w");
     106            0 :         if (!t)
     107              :         {
     108            0 :                 fprintf(stderr, "Could not open file %s for writing\n", tmpfile);
     109            0 :                 exit(2);
     110              :         }
     111              : 
     112            0 :         initStringInfo(&linebuf);
     113              : 
     114            0 :         while (pg_get_line_buf(s, &linebuf))
     115              :         {
     116            0 :                 char       *p1 = strstr(linebuf.data, "connection to server ");
     117              : 
     118            0 :                 if (p1)
     119              :                 {
     120            0 :                         char       *p2 = strstr(p1, "failed: ");
     121              : 
     122            0 :                         if (p2)
     123              :                         {
     124            0 :                                 memmove(p1 + 21, p2, strlen(p2) + 1);
     125              :                                 /* we don't bother to fix up linebuf.len */
     126            0 :                         }
     127            0 :                 }
     128            0 :                 fputs(linebuf.data, t);
     129            0 :         }
     130              : 
     131            0 :         pfree(linebuf.data);
     132            0 :         fclose(s);
     133            0 :         fclose(t);
     134            0 :         if (rename(tmpfile, resultfile) != 0)
     135              :         {
     136            0 :                 fprintf(stderr, "Could not overwrite file %s with %s\n",
     137            0 :                                 resultfile, tmpfile);
     138            0 :                 exit(2);
     139              :         }
     140            0 : }
     141              : 
     142              : /*
     143              :  * start an ecpg test process for specified file (including redirection),
     144              :  * and return process ID
     145              :  */
     146              : 
     147              : static PID_TYPE
     148            0 : ecpg_start_test(const char *testname,
     149              :                                 _stringlist **resultfiles,
     150              :                                 _stringlist **expectfiles,
     151              :                                 _stringlist **tags)
     152              : {
     153            0 :         PID_TYPE        pid;
     154            0 :         char            inprg[MAXPGPATH];
     155            0 :         char            insource[MAXPGPATH];
     156            0 :         StringInfoData testname_dash;
     157            0 :         char            outfile_stdout[MAXPGPATH],
     158              :                                 expectfile_stdout[MAXPGPATH];
     159            0 :         char            outfile_stderr[MAXPGPATH],
     160              :                                 expectfile_stderr[MAXPGPATH];
     161            0 :         char            outfile_source[MAXPGPATH],
     162              :                                 expectfile_source[MAXPGPATH];
     163            0 :         char            cmd[MAXPGPATH * 3];
     164            0 :         char       *appnameenv;
     165              : 
     166            0 :         snprintf(inprg, sizeof(inprg), "%s/%s", inputdir, testname);
     167            0 :         snprintf(insource, sizeof(insource), "%s/%s.c", inputdir, testname);
     168              : 
     169              :         /* make a version of the test name that has dashes in place of slashes */
     170            0 :         initStringInfo(&testname_dash);
     171            0 :         appendStringInfoString(&testname_dash, testname);
     172            0 :         for (char *c = testname_dash.data; *c != '\0'; c++)
     173              :         {
     174            0 :                 if (*c == '/')
     175            0 :                         *c = '-';
     176            0 :         }
     177              : 
     178            0 :         snprintf(expectfile_stdout, sizeof(expectfile_stdout),
     179              :                          "%s/expected/%s.stdout",
     180            0 :                          expecteddir, testname_dash.data);
     181            0 :         snprintf(expectfile_stderr, sizeof(expectfile_stderr),
     182              :                          "%s/expected/%s.stderr",
     183            0 :                          expecteddir, testname_dash.data);
     184            0 :         snprintf(expectfile_source, sizeof(expectfile_source),
     185              :                          "%s/expected/%s.c",
     186            0 :                          expecteddir, testname_dash.data);
     187              : 
     188            0 :         snprintf(outfile_stdout, sizeof(outfile_stdout),
     189              :                          "%s/results/%s.stdout",
     190            0 :                          outputdir, testname_dash.data);
     191            0 :         snprintf(outfile_stderr, sizeof(outfile_stderr),
     192              :                          "%s/results/%s.stderr",
     193            0 :                          outputdir, testname_dash.data);
     194            0 :         snprintf(outfile_source, sizeof(outfile_source),
     195              :                          "%s/results/%s.c",
     196            0 :                          outputdir, testname_dash.data);
     197              : 
     198            0 :         add_stringlist_item(resultfiles, outfile_stdout);
     199            0 :         add_stringlist_item(expectfiles, expectfile_stdout);
     200            0 :         add_stringlist_item(tags, "stdout");
     201              : 
     202            0 :         add_stringlist_item(resultfiles, outfile_stderr);
     203            0 :         add_stringlist_item(expectfiles, expectfile_stderr);
     204            0 :         add_stringlist_item(tags, "stderr");
     205              : 
     206            0 :         add_stringlist_item(resultfiles, outfile_source);
     207            0 :         add_stringlist_item(expectfiles, expectfile_source);
     208            0 :         add_stringlist_item(tags, "source");
     209              : 
     210            0 :         ecpg_filter_source(insource, outfile_source);
     211              : 
     212            0 :         snprintf(cmd, sizeof(cmd),
     213              :                          "\"%s\" >\"%s\" 2>\"%s\"",
     214            0 :                          inprg,
     215            0 :                          outfile_stdout,
     216            0 :                          outfile_stderr);
     217              : 
     218            0 :         appnameenv = psprintf("ecpg/%s", testname_dash.data);
     219            0 :         setenv("PGAPPNAME", appnameenv, 1);
     220            0 :         free(appnameenv);
     221              : 
     222            0 :         pid = spawn_process(cmd);
     223              : 
     224            0 :         if (pid == INVALID_PID)
     225              :         {
     226            0 :                 fprintf(stderr, _("could not start process for test %s\n"),
     227            0 :                                 testname);
     228            0 :                 exit(2);
     229              :         }
     230              : 
     231            0 :         unsetenv("PGAPPNAME");
     232              : 
     233            0 :         free(testname_dash.data);
     234              : 
     235            0 :         return pid;
     236            0 : }
     237              : 
     238              : static void
     239            0 : ecpg_postprocess_result(const char *filename)
     240              : {
     241            0 :         int                     nlen = strlen(filename);
     242              : 
     243              :         /* Only stderr files require filtering, at the moment */
     244            0 :         if (nlen > 7 && strcmp(filename + nlen - 7, ".stderr") == 0)
     245              :         {
     246            0 :                 char       *tmpfile = psprintf("%s.tmp", filename);
     247              : 
     248            0 :                 ecpg_filter_stderr(filename, tmpfile);
     249            0 :                 pfree(tmpfile);
     250            0 :         }
     251            0 : }
     252              : 
     253              : static void
     254            0 : ecpg_init(int argc, char *argv[])
     255              : {
     256              :         /* nothing to do here at the moment */
     257            0 : }
     258              : 
     259              : int
     260            0 : main(int argc, char *argv[])
     261              : {
     262            0 :         return regression_main(argc, argv,
     263              :                                                    ecpg_init,
     264              :                                                    ecpg_start_test,
     265              :                                                    ecpg_postprocess_result);
     266              : }
        

Generated by: LCOV version 2.3.2-1