PostgreSQL Source Code  git master
pg_regress_ecpg.c
Go to the documentation of this file.
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-2020, 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 static void
27 ecpg_filter(const char *sourcefile, const char *outfile)
28 {
29  /*
30  * Create a filtered copy of sourcefile, replacing #line x
31  * "./../bla/foo.h" with #line x "foo.h"
32  */
33  FILE *s,
34  *t;
35  StringInfoData linebuf;
36 
37  s = fopen(sourcefile, "r");
38  if (!s)
39  {
40  fprintf(stderr, "Could not open file %s for reading\n", sourcefile);
41  exit(2);
42  }
43  t = fopen(outfile, "w");
44  if (!t)
45  {
46  fprintf(stderr, "Could not open file %s for writing\n", outfile);
47  exit(2);
48  }
49 
50  initStringInfo(&linebuf);
51 
52  while (pg_get_line_buf(s, &linebuf))
53  {
54  /* check for "#line " in the beginning */
55  if (strstr(linebuf.data, "#line ") == linebuf.data)
56  {
57  char *p = strchr(linebuf.data, '"');
58  int plen = 1;
59 
60  while (*p && (*(p + plen) == '.' || strchr(p + plen, '/') != NULL))
61  {
62  plen++;
63  }
64  /* plen is one more than the number of . and / characters */
65  if (plen > 1)
66  {
67  memmove(p + 1, p + plen, strlen(p + plen) + 1);
68  /* we don't bother to fix up linebuf.len */
69  }
70  }
71  fputs(linebuf.data, t);
72  }
73 
74  pfree(linebuf.data);
75  fclose(s);
76  fclose(t);
77 }
78 
79 /*
80  * start an ecpg test process for specified file (including redirection),
81  * and return process ID
82  */
83 
84 static PID_TYPE
85 ecpg_start_test(const char *testname,
86  _stringlist **resultfiles,
87  _stringlist **expectfiles,
88  _stringlist **tags)
89 {
90  PID_TYPE pid;
91  char inprg[MAXPGPATH];
92  char insource[MAXPGPATH];
93  StringInfoData testname_dash;
94  char outfile_stdout[MAXPGPATH],
95  expectfile_stdout[MAXPGPATH];
96  char outfile_stderr[MAXPGPATH],
97  expectfile_stderr[MAXPGPATH];
98  char outfile_source[MAXPGPATH],
99  expectfile_source[MAXPGPATH];
100  char cmd[MAXPGPATH * 3];
101  char *appnameenv;
102 
103  snprintf(inprg, sizeof(inprg), "%s/%s", inputdir, testname);
104  snprintf(insource, sizeof(insource), "%s.c", testname);
105 
106  initStringInfo(&testname_dash);
107  appendStringInfoString(&testname_dash, testname);
108  replace_string(&testname_dash, "/", "-");
109 
110  snprintf(expectfile_stdout, sizeof(expectfile_stdout),
111  "%s/expected/%s.stdout",
112  outputdir, testname_dash.data);
113  snprintf(expectfile_stderr, sizeof(expectfile_stderr),
114  "%s/expected/%s.stderr",
115  outputdir, testname_dash.data);
116  snprintf(expectfile_source, sizeof(expectfile_source),
117  "%s/expected/%s.c",
118  outputdir, testname_dash.data);
119 
120  snprintf(outfile_stdout, sizeof(outfile_stdout),
121  "%s/results/%s.stdout",
122  outputdir, testname_dash.data);
123  snprintf(outfile_stderr, sizeof(outfile_stderr),
124  "%s/results/%s.stderr",
125  outputdir, testname_dash.data);
126  snprintf(outfile_source, sizeof(outfile_source),
127  "%s/results/%s.c",
128  outputdir, testname_dash.data);
129 
130  add_stringlist_item(resultfiles, outfile_stdout);
131  add_stringlist_item(expectfiles, expectfile_stdout);
132  add_stringlist_item(tags, "stdout");
133 
134  add_stringlist_item(resultfiles, outfile_stderr);
135  add_stringlist_item(expectfiles, expectfile_stderr);
136  add_stringlist_item(tags, "stderr");
137 
138  add_stringlist_item(resultfiles, outfile_source);
139  add_stringlist_item(expectfiles, expectfile_source);
140  add_stringlist_item(tags, "source");
141 
142  ecpg_filter(insource, outfile_source);
143 
144  snprintf(cmd, sizeof(cmd),
145  "\"%s\" >\"%s\" 2>\"%s\"",
146  inprg,
147  outfile_stdout,
148  outfile_stderr);
149 
150  appnameenv = psprintf("PGAPPNAME=ecpg/%s", testname_dash.data);
151  putenv(appnameenv);
152 
153  pid = spawn_process(cmd);
154 
155  if (pid == INVALID_PID)
156  {
157  fprintf(stderr, _("could not start process for test %s\n"),
158  testname);
159  exit(2);
160  }
161 
162  unsetenv("PGAPPNAME");
163  free(appnameenv);
164 
165  free(testname_dash.data);
166 
167  return pid;
168 }
169 
170 static void
171 ecpg_init(int argc, char *argv[])
172 {
173  /* nothing to do here at the moment */
174 }
175 
176 int
177 main(int argc, char *argv[])
178 {
179  return regression_main(argc, argv, ecpg_init, ecpg_start_test);
180 }
bool pg_get_line_buf(FILE *stream, StringInfo buf)
Definition: pg_get_line.c:88
static void static void static void void add_stringlist_item(_stringlist **listhead, const char *str)
Definition: pg_regress.c:157
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46
static void ecpg_init(int argc, char *argv[])
#define PID_TYPE
Definition: pg_regress.h:14
#define fprintf
Definition: port.h:219
PID_TYPE spawn_process(const char *cmdline)
Definition: pg_regress.c:1169
void pfree(void *pointer)
Definition: mcxt.c:1057
#define MAXPGPATH
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
#define INVALID_PID
Definition: pg_regress.h:15
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59
char * outputdir
Definition: pg_regress.c:78
char * inputdir
Definition: pg_regress.c:77
#define free(a)
Definition: header.h:65
static PID_TYPE ecpg_start_test(const char *testname, _stringlist **resultfiles, _stringlist **expectfiles, _stringlist **tags)
#define putenv(x)
Definition: win32_port.h:502
void replace_string(StringInfo string, const char *replace, const char *replacement)
Definition: pg_regress.c:447
static void ecpg_filter(const char *sourcefile, const char *outfile)
int main(int argc, char *argv[])
static char * outfile
#define snprintf
Definition: port.h:215
#define _(x)
Definition: elog.c:88
#define unsetenv(x)
Definition: win32_port.h:503
int regression_main(int argc, char *argv[], init_function ifunc, test_function tfunc)
Definition: pg_regress.c:2097