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
ecpg_filter(const char * sourcefile,const char * outfile)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
ecpg_start_test(const char * testname,_stringlist ** resultfiles,_stringlist ** expectfiles,_stringlist ** tags)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
ecpg_init(int argc,char * argv[])164 ecpg_init(int argc, char *argv[])
165 {
166 /* nothing to do here at the moment */
167 }
168
169 int
main(int argc,char * argv[])170 main(int argc, char *argv[])
171 {
172 return regression_main(argc, argv, ecpg_init, ecpg_start_test);
173 }
174