LCOV - code coverage report
Current view: top level - src/interfaces/ecpg/test - pg_regress_ecpg.c (source / functions) Hit Total Coverage
Test: PostgreSQL 14devel Lines: 79 91 86.8 %
Date: 2021-05-13 09:07:15 Functions: 6 6 100.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-2021, 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 "pg_regress.h"
      22             : #include "common/string.h"
      23             : #include "lib/stringinfo.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         250 : ecpg_filter_source(const char *sourcefile, const char *outfile)
      35             : {
      36             :     FILE       *s,
      37             :                *t;
      38             :     StringInfoData linebuf;
      39             : 
      40         250 :     s = fopen(sourcefile, "r");
      41         250 :     if (!s)
      42             :     {
      43           0 :         fprintf(stderr, "Could not open file %s for reading\n", sourcefile);
      44           0 :         exit(2);
      45             :     }
      46         250 :     t = fopen(outfile, "w");
      47         250 :     if (!t)
      48             :     {
      49           0 :         fprintf(stderr, "Could not open file %s for writing\n", outfile);
      50           0 :         exit(2);
      51             :     }
      52             : 
      53         250 :     initStringInfo(&linebuf);
      54             : 
      55       65950 :     while (pg_get_line_buf(s, &linebuf))
      56             :     {
      57             :         /* check for "#line " in the beginning */
      58       65700 :         if (strstr(linebuf.data, "#line ") == linebuf.data)
      59             :         {
      60       10938 :             char       *p = strchr(linebuf.data, '"');
      61       10938 :             int         plen = 1;
      62             : 
      63       13646 :             while (*p && (*(p + plen) == '.' || strchr(p + plen, '/') != NULL))
      64             :             {
      65        2708 :                 plen++;
      66             :             }
      67             :             /* plen is one more than the number of . and / characters */
      68       10938 :             if (plen > 1)
      69             :             {
      70         384 :                 memmove(p + 1, p + plen, strlen(p + plen) + 1);
      71             :                 /* we don't bother to fix up linebuf.len */
      72             :             }
      73             :         }
      74       65700 :         fputs(linebuf.data, t);
      75             :     }
      76             : 
      77         250 :     pfree(linebuf.data);
      78         250 :     fclose(s);
      79         250 :     fclose(t);
      80         250 : }
      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         250 : ecpg_filter_stderr(const char *resultfile, const char *tmpfile)
      94             : {
      95             :     FILE       *s,
      96             :                *t;
      97             :     StringInfoData linebuf;
      98             : 
      99         250 :     s = fopen(resultfile, "r");
     100         250 :     if (!s)
     101             :     {
     102           0 :         fprintf(stderr, "Could not open file %s for reading\n", resultfile);
     103           0 :         exit(2);
     104             :     }
     105         250 :     t = fopen(tmpfile, "w");
     106         250 :     if (!t)
     107             :     {
     108           0 :         fprintf(stderr, "Could not open file %s for writing\n", tmpfile);
     109           0 :         exit(2);
     110             :     }
     111             : 
     112         250 :     initStringInfo(&linebuf);
     113             : 
     114       26060 :     while (pg_get_line_buf(s, &linebuf))
     115             :     {
     116       25810 :         char       *p1 = strstr(linebuf.data, "connection to server ");
     117             : 
     118       25810 :         if (p1)
     119             :         {
     120          16 :             char       *p2 = strstr(p1, "failed: ");
     121             : 
     122          16 :             if (p2)
     123             :             {
     124          16 :                 memmove(p1 + 21, p2, strlen(p2) + 1);
     125             :                 /* we don't bother to fix up linebuf.len */
     126             :             }
     127             :         }
     128       25810 :         fputs(linebuf.data, t);
     129             :     }
     130             : 
     131         250 :     pfree(linebuf.data);
     132         250 :     fclose(s);
     133         250 :     fclose(t);
     134         250 :     if (rename(tmpfile, resultfile) != 0)
     135             :     {
     136           0 :         fprintf(stderr, "Could not overwrite file %s with %s\n",
     137             :                 resultfile, tmpfile);
     138           0 :         exit(2);
     139             :     }
     140         250 : }
     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         250 : ecpg_start_test(const char *testname,
     149             :                 _stringlist **resultfiles,
     150             :                 _stringlist **expectfiles,
     151             :                 _stringlist **tags)
     152             : {
     153             :     PID_TYPE    pid;
     154             :     char        inprg[MAXPGPATH];
     155             :     char        insource[MAXPGPATH];
     156             :     StringInfoData testname_dash;
     157             :     char        outfile_stdout[MAXPGPATH],
     158             :                 expectfile_stdout[MAXPGPATH];
     159             :     char        outfile_stderr[MAXPGPATH],
     160             :                 expectfile_stderr[MAXPGPATH];
     161             :     char        outfile_source[MAXPGPATH],
     162             :                 expectfile_source[MAXPGPATH];
     163             :     char        cmd[MAXPGPATH * 3];
     164             :     char       *appnameenv;
     165             : 
     166         250 :     snprintf(inprg, sizeof(inprg), "%s/%s", inputdir, testname);
     167         250 :     snprintf(insource, sizeof(insource), "%s.c", testname);
     168             : 
     169         250 :     initStringInfo(&testname_dash);
     170         250 :     appendStringInfoString(&testname_dash, testname);
     171         250 :     replace_string(&testname_dash, "/", "-");
     172             : 
     173         250 :     snprintf(expectfile_stdout, sizeof(expectfile_stdout),
     174             :              "%s/expected/%s.stdout",
     175             :              outputdir, testname_dash.data);
     176         250 :     snprintf(expectfile_stderr, sizeof(expectfile_stderr),
     177             :              "%s/expected/%s.stderr",
     178             :              outputdir, testname_dash.data);
     179         250 :     snprintf(expectfile_source, sizeof(expectfile_source),
     180             :              "%s/expected/%s.c",
     181             :              outputdir, testname_dash.data);
     182             : 
     183         250 :     snprintf(outfile_stdout, sizeof(outfile_stdout),
     184             :              "%s/results/%s.stdout",
     185             :              outputdir, testname_dash.data);
     186         250 :     snprintf(outfile_stderr, sizeof(outfile_stderr),
     187             :              "%s/results/%s.stderr",
     188             :              outputdir, testname_dash.data);
     189         250 :     snprintf(outfile_source, sizeof(outfile_source),
     190             :              "%s/results/%s.c",
     191             :              outputdir, testname_dash.data);
     192             : 
     193         250 :     add_stringlist_item(resultfiles, outfile_stdout);
     194         250 :     add_stringlist_item(expectfiles, expectfile_stdout);
     195         250 :     add_stringlist_item(tags, "stdout");
     196             : 
     197         250 :     add_stringlist_item(resultfiles, outfile_stderr);
     198         250 :     add_stringlist_item(expectfiles, expectfile_stderr);
     199         250 :     add_stringlist_item(tags, "stderr");
     200             : 
     201         250 :     add_stringlist_item(resultfiles, outfile_source);
     202         250 :     add_stringlist_item(expectfiles, expectfile_source);
     203         250 :     add_stringlist_item(tags, "source");
     204             : 
     205         250 :     ecpg_filter_source(insource, outfile_source);
     206             : 
     207         250 :     snprintf(cmd, sizeof(cmd),
     208             :              "\"%s\" >\"%s\" 2>\"%s\"",
     209             :              inprg,
     210             :              outfile_stdout,
     211             :              outfile_stderr);
     212             : 
     213         250 :     appnameenv = psprintf("ecpg/%s", testname_dash.data);
     214         250 :     setenv("PGAPPNAME", appnameenv, 1);
     215         250 :     free(appnameenv);
     216             : 
     217         250 :     pid = spawn_process(cmd);
     218             : 
     219         250 :     if (pid == INVALID_PID)
     220             :     {
     221           0 :         fprintf(stderr, _("could not start process for test %s\n"),
     222             :                 testname);
     223           0 :         exit(2);
     224             :     }
     225             : 
     226         250 :     unsetenv("PGAPPNAME");
     227             : 
     228         250 :     free(testname_dash.data);
     229             : 
     230         250 :     return pid;
     231             : }
     232             : 
     233             : static void
     234         750 : ecpg_postprocess_result(const char *filename)
     235             : {
     236         750 :     int         nlen = strlen(filename);
     237             : 
     238             :     /* Only stderr files require filtering, at the moment */
     239         750 :     if (nlen > 7 && strcmp(filename + nlen - 7, ".stderr") == 0)
     240             :     {
     241         250 :         char       *tmpfile = psprintf("%s.tmp", filename);
     242             : 
     243         250 :         ecpg_filter_stderr(filename, tmpfile);
     244         250 :         pfree(tmpfile);
     245             :     }
     246         750 : }
     247             : 
     248             : static void
     249           4 : ecpg_init(int argc, char *argv[])
     250             : {
     251             :     /* nothing to do here at the moment */
     252           4 : }
     253             : 
     254             : int
     255           4 : main(int argc, char *argv[])
     256             : {
     257           4 :     return regression_main(argc, argv,
     258             :                            ecpg_init,
     259             :                            ecpg_start_test,
     260             :                            ecpg_postprocess_result);
     261             : }

Generated by: LCOV version 1.13