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