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