PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
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-2017, 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 
99  snprintf(inprg, sizeof(inprg), "%s/%s", inputdir, testname);
100 
101  testname_dash = strdup(testname);
102  replace_string(testname_dash, "/", "-");
103  snprintf(expectfile_stdout, sizeof(expectfile_stdout),
104  "%s/expected/%s.stdout",
105  outputdir, testname_dash);
106  snprintf(expectfile_stderr, sizeof(expectfile_stderr),
107  "%s/expected/%s.stderr",
108  outputdir, testname_dash);
109  snprintf(expectfile_source, sizeof(expectfile_source),
110  "%s/expected/%s.c",
111  outputdir, testname_dash);
112 
113  /*
114  * We can use replace_string() here because the replacement string does
115  * not occupy more space than the replaced one.
116  */
117  outfile_stdout = strdup(expectfile_stdout);
118  replace_string(outfile_stdout, "/expected/", "/results/");
119  outfile_stderr = strdup(expectfile_stderr);
120  replace_string(outfile_stderr, "/expected/", "/results/");
121  outfile_source = strdup(expectfile_source);
122  replace_string(outfile_source, "/expected/", "/results/");
123 
124  add_stringlist_item(resultfiles, outfile_stdout);
125  add_stringlist_item(expectfiles, expectfile_stdout);
126  add_stringlist_item(tags, "stdout");
127 
128  add_stringlist_item(resultfiles, outfile_stderr);
129  add_stringlist_item(expectfiles, expectfile_stderr);
130  add_stringlist_item(tags, "stderr");
131 
132  add_stringlist_item(resultfiles, outfile_source);
133  add_stringlist_item(expectfiles, expectfile_source);
134  add_stringlist_item(tags, "source");
135 
136  snprintf(insource, sizeof(insource), "%s.c", testname);
137  ecpg_filter(insource, outfile_source);
138 
139  snprintf(inprg, sizeof(inprg), "%s/%s", inputdir, testname);
140 
141  snprintf(cmd, sizeof(cmd),
142  "\"%s\" >\"%s\" 2>\"%s\"",
143  inprg,
144  outfile_stdout,
145  outfile_stderr);
146 
147  pid = spawn_process(cmd);
148 
149  if (pid == INVALID_PID)
150  {
151  fprintf(stderr, _("could not start process for test %s\n"),
152  testname);
153  exit(2);
154  }
155 
156  free(outfile_stdout);
157  free(outfile_stderr);
158  free(outfile_source);
159 
160  return pid;
161 }
162 
163 static void
164 ecpg_init(int argc, char *argv[])
165 {
166  /* nothing to do here at the moment */
167 }
168 
169 int
170 main(int argc, char *argv[])
171 {
172  return regression_main(argc, argv, ecpg_init, ecpg_start_test);
173 }
static void static void static void void add_stringlist_item(_stringlist **listhead, const char *str)
Definition: pg_regress.c:154
static void ecpg_init(int argc, char *argv[])
#define PID_TYPE
Definition: pg_regress.h:14
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
void replace_string(char *string, char *replace, char *replacement)
Definition: pg_regress.c:440
PID_TYPE spawn_process(const char *cmdline)
Definition: pg_regress.c:1126
#define malloc(a)
Definition: header.h:50
#define MAXPGPATH
#define INVALID_PID
Definition: pg_regress.h:15
#define LINEBUFSIZE
char * outputdir
Definition: pg_regress.c:75
char * inputdir
Definition: pg_regress.c:74
#define free(a)
Definition: header.h:65
#define NULL
Definition: c.h:229
#define StrNCpy(dst, src, len)
Definition: c.h:830
static PID_TYPE ecpg_start_test(const char *testname, _stringlist **resultfiles, _stringlist **expectfiles, _stringlist **tags)
static void ecpg_filter(const char *sourcefile, const char *outfile)
int main(int argc, char *argv[])
static char * outfile
#define _(x)
Definition: elog.c:84
int regression_main(int argc, char *argv[], init_function ifunc, test_function tfunc)
Definition: pg_regress.c:2025