Age Owner Branch data TLA Line data Source code
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-2024, 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 "common/string.h"
22 : : #include "lib/stringinfo.h"
23 : : #include "pg_regress.h"
24 : :
25 : :
26 : : /*
27 : : * Create a filtered copy of sourcefile, removing any path
28 : : * appearing in #line directives; for example, replace
29 : : * #line x "./../bla/foo.h" with #line x "foo.h".
30 : : * This is needed because the path part can vary depending
31 : : * on compiler, platform, build options, etc.
32 : : */
33 : : static void
1189 tgl@sss.pgh.pa.us 34 :CBC 65 : ecpg_filter_source(const char *sourcefile, const char *outfile)
35 : : {
36 : : FILE *s,
37 : : *t;
38 : : StringInfoData linebuf;
39 : :
6151 magnus@hagander.net 40 : 65 : s = fopen(sourcefile, "r");
41 [ - + ]: 65 : if (!s)
42 : : {
6151 magnus@hagander.net 43 :UBC 0 : fprintf(stderr, "Could not open file %s for reading\n", sourcefile);
4486 peter_e@gmx.net 44 : 0 : exit(2);
45 : : }
6151 magnus@hagander.net 46 :CBC 65 : t = fopen(outfile, "w");
47 [ - + ]: 65 : if (!t)
48 : : {
6151 magnus@hagander.net 49 :UBC 0 : fprintf(stderr, "Could not open file %s for writing\n", outfile);
4486 peter_e@gmx.net 50 : 0 : exit(2);
51 : : }
52 : :
1316 tgl@sss.pgh.pa.us 53 :CBC 65 : initStringInfo(&linebuf);
54 : :
1300 55 [ + + ]: 17183 : while (pg_get_line_buf(s, &linebuf))
56 : : {
57 : : /* check for "#line " in the beginning */
1316 58 [ + + ]: 17118 : if (strstr(linebuf.data, "#line ") == linebuf.data)
59 : : {
60 : 2851 : char *p = strchr(linebuf.data, '"');
5995 bruce@momjian.us 61 : 2851 : int plen = 1;
62 : :
6151 magnus@hagander.net 63 [ + - + + : 214005 : while (*p && (*(p + plen) == '.' || strchr(p + plen, '/') != NULL))
+ + ]
64 : : {
65 : 211154 : plen++;
66 : : }
67 : : /* plen is one more than the number of . and / characters */
68 [ + - ]: 2851 : if (plen > 1)
69 : : {
1316 tgl@sss.pgh.pa.us 70 : 2851 : memmove(p + 1, p + plen, strlen(p + plen) + 1);
71 : : /* we don't bother to fix up linebuf.len */
72 : : }
73 : : }
74 : 17118 : fputs(linebuf.data, t);
75 : : }
76 : :
77 : 65 : pfree(linebuf.data);
6151 magnus@hagander.net 78 : 65 : fclose(s);
79 : 65 : fclose(t);
80 : 65 : }
81 : :
82 : : /*
83 : : * Remove the details of connection failure error messages
84 : : * in a test result file, since the target host/pathname and/or port
85 : : * can vary. Rewrite the result file in-place.
86 : : *
87 : : * At some point it might be interesting to unify this with
88 : : * ecpg_filter_source, but building a general pattern matcher
89 : : * is no fun, nor does it seem desirable to introduce a
90 : : * dependency on an external one.
91 : : */
92 : : static void
1189 tgl@sss.pgh.pa.us 93 : 65 : ecpg_filter_stderr(const char *resultfile, const char *tmpfile)
94 : : {
95 : : FILE *s,
96 : : *t;
97 : : StringInfoData linebuf;
98 : :
99 : 65 : s = fopen(resultfile, "r");
100 [ - + ]: 65 : if (!s)
101 : : {
1189 tgl@sss.pgh.pa.us 102 :UBC 0 : fprintf(stderr, "Could not open file %s for reading\n", resultfile);
103 : 0 : exit(2);
104 : : }
1189 tgl@sss.pgh.pa.us 105 :CBC 65 : t = fopen(tmpfile, "w");
106 [ - + ]: 65 : if (!t)
107 : : {
1189 tgl@sss.pgh.pa.us 108 :UBC 0 : fprintf(stderr, "Could not open file %s for writing\n", tmpfile);
109 : 0 : exit(2);
110 : : }
111 : :
1189 tgl@sss.pgh.pa.us 112 :CBC 65 : initStringInfo(&linebuf);
113 : :
114 [ + + ]: 6785 : while (pg_get_line_buf(s, &linebuf))
115 : : {
1179 116 : 6720 : char *p1 = strstr(linebuf.data, "connection to server ");
117 : :
1189 118 [ + + ]: 6720 : if (p1)
119 : : {
1179 120 : 1 : char *p2 = strstr(p1, "failed: ");
121 : :
1189 122 [ + - ]: 1 : if (p2)
123 : : {
1179 124 : 1 : memmove(p1 + 21, p2, strlen(p2) + 1);
125 : : /* we don't bother to fix up linebuf.len */
126 : : }
127 : : }
1189 128 : 6720 : fputs(linebuf.data, t);
129 : : }
130 : :
131 : 65 : pfree(linebuf.data);
132 : 65 : fclose(s);
133 : 65 : fclose(t);
134 [ - + ]: 65 : if (rename(tmpfile, resultfile) != 0)
135 : : {
1189 tgl@sss.pgh.pa.us 136 :UBC 0 : fprintf(stderr, "Could not overwrite file %s with %s\n",
137 : : resultfile, tmpfile);
138 : 0 : exit(2);
139 : : }
1189 tgl@sss.pgh.pa.us 140 :CBC 65 : }
141 : :
142 : : /*
143 : : * start an ecpg test process for specified file (including redirection),
144 : : * and return process ID
145 : : */
146 : :
147 : : static PID_TYPE
6151 magnus@hagander.net 148 : 65 : ecpg_start_test(const char *testname,
149 : : _stringlist **resultfiles,
150 : : _stringlist **expectfiles,
151 : : _stringlist **tags)
152 : : {
153 : : PID_TYPE pid;
154 : : char inprg[MAXPGPATH];
155 : : char insource[MAXPGPATH];
156 : : StringInfoData testname_dash;
157 : : char outfile_stdout[MAXPGPATH],
158 : : expectfile_stdout[MAXPGPATH];
159 : : char outfile_stderr[MAXPGPATH],
160 : : expectfile_stderr[MAXPGPATH];
161 : : char outfile_source[MAXPGPATH],
162 : : expectfile_source[MAXPGPATH];
163 : : char cmd[MAXPGPATH * 3];
164 : : char *appnameenv;
165 : :
166 : 65 : snprintf(inprg, sizeof(inprg), "%s/%s", inputdir, testname);
603 andres@anarazel.de 167 : 65 : snprintf(insource, sizeof(insource), "%s/%s.c", inputdir, testname);
168 : :
169 : : /* make a version of the test name that has dashes in place of slashes */
1316 tgl@sss.pgh.pa.us 170 : 65 : initStringInfo(&testname_dash);
171 : 65 : appendStringInfoString(&testname_dash, testname);
846 172 [ + + ]: 1083 : for (char *c = testname_dash.data; *c != '\0'; c++)
173 : : {
174 [ + + ]: 1018 : if (*c == '/')
175 : 65 : *c = '-';
176 : : }
177 : :
6151 magnus@hagander.net 178 : 65 : snprintf(expectfile_stdout, sizeof(expectfile_stdout),
179 : : "%s/expected/%s.stdout",
180 : : expecteddir, testname_dash.data);
181 : 65 : snprintf(expectfile_stderr, sizeof(expectfile_stderr),
182 : : "%s/expected/%s.stderr",
183 : : expecteddir, testname_dash.data);
184 : 65 : snprintf(expectfile_source, sizeof(expectfile_source),
185 : : "%s/expected/%s.c",
186 : : expecteddir, testname_dash.data);
187 : :
1316 tgl@sss.pgh.pa.us 188 : 65 : snprintf(outfile_stdout, sizeof(outfile_stdout),
189 : : "%s/results/%s.stdout",
190 : : outputdir, testname_dash.data);
191 : 65 : snprintf(outfile_stderr, sizeof(outfile_stderr),
192 : : "%s/results/%s.stderr",
193 : : outputdir, testname_dash.data);
194 : 65 : snprintf(outfile_source, sizeof(outfile_source),
195 : : "%s/results/%s.c",
196 : : outputdir, testname_dash.data);
197 : :
6151 magnus@hagander.net 198 : 65 : add_stringlist_item(resultfiles, outfile_stdout);
199 : 65 : add_stringlist_item(expectfiles, expectfile_stdout);
200 : 65 : add_stringlist_item(tags, "stdout");
201 : :
202 : 65 : add_stringlist_item(resultfiles, outfile_stderr);
203 : 65 : add_stringlist_item(expectfiles, expectfile_stderr);
204 : 65 : add_stringlist_item(tags, "stderr");
205 : :
206 : 65 : add_stringlist_item(resultfiles, outfile_source);
207 : 65 : add_stringlist_item(expectfiles, expectfile_source);
208 : 65 : add_stringlist_item(tags, "source");
209 : :
1189 tgl@sss.pgh.pa.us 210 : 65 : ecpg_filter_source(insource, outfile_source);
211 : :
6151 magnus@hagander.net 212 : 65 : snprintf(cmd, sizeof(cmd),
213 : : "\"%s\" >\"%s\" 2>\"%s\"",
214 : : inprg,
215 : : outfile_stdout,
216 : : outfile_stderr);
217 : :
1201 tgl@sss.pgh.pa.us 218 : 65 : appnameenv = psprintf("ecpg/%s", testname_dash.data);
219 : 65 : setenv("PGAPPNAME", appnameenv, 1);
220 : 65 : free(appnameenv);
221 : :
6151 magnus@hagander.net 222 : 65 : pid = spawn_process(cmd);
223 : :
224 [ - + ]: 65 : if (pid == INVALID_PID)
225 : : {
6151 magnus@hagander.net 226 :UBC 0 : fprintf(stderr, _("could not start process for test %s\n"),
227 : : testname);
4486 peter_e@gmx.net 228 : 0 : exit(2);
229 : : }
230 : :
1692 tgl@sss.pgh.pa.us 231 :CBC 65 : unsetenv("PGAPPNAME");
232 : :
1316 233 : 65 : free(testname_dash.data);
234 : :
6151 magnus@hagander.net 235 : 65 : return pid;
236 : : }
237 : :
238 : : static void
1189 tgl@sss.pgh.pa.us 239 : 195 : ecpg_postprocess_result(const char *filename)
240 : : {
241 : 195 : int nlen = strlen(filename);
242 : :
243 : : /* Only stderr files require filtering, at the moment */
244 [ + - + + ]: 195 : if (nlen > 7 && strcmp(filename + nlen - 7, ".stderr") == 0)
245 : : {
246 : 65 : char *tmpfile = psprintf("%s.tmp", filename);
247 : :
248 : 65 : ecpg_filter_stderr(filename, tmpfile);
249 : 65 : pfree(tmpfile);
250 : : }
251 : 195 : }
252 : :
253 : : static void
3809 rhaas@postgresql.org 254 : 1 : ecpg_init(int argc, char *argv[])
255 : : {
256 : : /* nothing to do here at the moment */
6151 magnus@hagander.net 257 : 1 : }
258 : :
259 : : int
260 : 1 : main(int argc, char *argv[])
261 : : {
1189 tgl@sss.pgh.pa.us 262 : 1 : return regression_main(argc, argv,
263 : : ecpg_init,
264 : : ecpg_start_test,
265 : : ecpg_postprocess_result);
266 : : }
|