Skip to content

Commit 800d93f

Browse files
committed
Allow pg_regress.c wrappers to postprocess test result files.
Add an optional callback to regression_main() that, if provided, is invoked on each test output file before we try to compare it to the expected-result file. The main and isolation test programs don't need this (yet). In pg_regress_ecpg, add a filter that eliminates target-host details from "could not connect" error reports. This filter doesn't do anything as of this commit, but it will be needed by the next one. In the long run we might want to provide some more general, perhaps pattern-based, filtering mechanism for test output. For now, this will solve the immediate problem. Discussion: https://postgr.es/m/BN6PR05MB3492948E4FD76C156E747E8BC9160@BN6PR05MB3492.namprd05.prod.outlook.com
1 parent ffa2e46 commit 800d93f

File tree

5 files changed

+134
-24
lines changed

5 files changed

+134
-24
lines changed

src/interfaces/ecpg/test/pg_regress_ecpg.c

+88-7
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,16 @@
2323
#include "lib/stringinfo.h"
2424

2525

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+
*/
2633
static void
27-
ecpg_filter(const char *sourcefile, const char *outfile)
34+
ecpg_filter_source(const char *sourcefile, const char *outfile)
2835
{
29-
/*
30-
* Create a filtered copy of sourcefile, replacing #line x
31-
* "./../bla/foo.h" with #line x "foo.h"
32-
*/
3336
FILE *s,
3437
*t;
3538
StringInfoData linebuf;
@@ -76,6 +79,66 @@ ecpg_filter(const char *sourcefile, const char *outfile)
7679
fclose(t);
7780
}
7881

82+
/*
83+
* Remove the details of "could not connect to ...: " 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
93+
ecpg_filter_stderr(const char *resultfile, const char *tmpfile)
94+
{
95+
FILE *s,
96+
*t;
97+
StringInfoData linebuf;
98+
99+
s = fopen(resultfile, "r");
100+
if (!s)
101+
{
102+
fprintf(stderr, "Could not open file %s for reading\n", resultfile);
103+
exit(2);
104+
}
105+
t = fopen(tmpfile, "w");
106+
if (!t)
107+
{
108+
fprintf(stderr, "Could not open file %s for writing\n", tmpfile);
109+
exit(2);
110+
}
111+
112+
initStringInfo(&linebuf);
113+
114+
while (pg_get_line_buf(s, &linebuf))
115+
{
116+
char *p1 = strstr(linebuf.data, "could not connect to ");
117+
118+
if (p1)
119+
{
120+
char *p2 = strstr(p1, ": ");
121+
122+
if (p2)
123+
{
124+
memmove(p1 + 17, p2, strlen(p2) + 1);
125+
/* we don't bother to fix up linebuf.len */
126+
}
127+
}
128+
fputs(linebuf.data, t);
129+
}
130+
131+
pfree(linebuf.data);
132+
fclose(s);
133+
fclose(t);
134+
if (rename(tmpfile, resultfile) != 0)
135+
{
136+
fprintf(stderr, "Could not overwrite file %s with %s\n",
137+
resultfile, tmpfile);
138+
exit(2);
139+
}
140+
}
141+
79142
/*
80143
* start an ecpg test process for specified file (including redirection),
81144
* and return process ID
@@ -139,7 +202,7 @@ ecpg_start_test(const char *testname,
139202
add_stringlist_item(expectfiles, expectfile_source);
140203
add_stringlist_item(tags, "source");
141204

142-
ecpg_filter(insource, outfile_source);
205+
ecpg_filter_source(insource, outfile_source);
143206

144207
snprintf(cmd, sizeof(cmd),
145208
"\"%s\" >\"%s\" 2>\"%s\"",
@@ -167,6 +230,21 @@ ecpg_start_test(const char *testname,
167230
return pid;
168231
}
169232

233+
static void
234+
ecpg_postprocess_result(const char *filename)
235+
{
236+
int nlen = strlen(filename);
237+
238+
/* Only stderr files require filtering, at the moment */
239+
if (nlen > 7 && strcmp(filename + nlen - 7, ".stderr") == 0)
240+
{
241+
char *tmpfile = psprintf("%s.tmp", filename);
242+
243+
ecpg_filter_stderr(filename, tmpfile);
244+
pfree(tmpfile);
245+
}
246+
}
247+
170248
static void
171249
ecpg_init(int argc, char *argv[])
172250
{
@@ -176,5 +254,8 @@ ecpg_init(int argc, char *argv[])
176254
int
177255
main(int argc, char *argv[])
178256
{
179-
return regression_main(argc, argv, ecpg_init, ecpg_start_test);
257+
return regression_main(argc, argv,
258+
ecpg_init,
259+
ecpg_start_test,
260+
ecpg_postprocess_result);
180261
}

src/test/isolation/isolation_main.c

+4-1
Original file line numberDiff line numberDiff line change
@@ -145,5 +145,8 @@ isolation_init(int argc, char **argv)
145145
int
146146
main(int argc, char *argv[])
147147
{
148-
return regression_main(argc, argv, isolation_init, isolation_start_test);
148+
return regression_main(argc, argv,
149+
isolation_init,
150+
isolation_start_test,
151+
NULL /* no postfunc needed */ );
149152
}

src/test/regress/pg_regress.c

+19-10
Original file line numberDiff line numberDiff line change
@@ -731,7 +731,7 @@ static void
731731
initialize_environment(void)
732732
{
733733
/*
734-
* Set default application_name. (The test_function may choose to
734+
* Set default application_name. (The test_start_function may choose to
735735
* override this, but if it doesn't, we have something useful in place.)
736736
*/
737737
setenv("PGAPPNAME", "pg_regress", 1);
@@ -1616,7 +1616,8 @@ log_child_failure(int exitstatus)
16161616
* Run all the tests specified in one schedule file
16171617
*/
16181618
static void
1619-
run_schedule(const char *schedule, test_function tfunc)
1619+
run_schedule(const char *schedule, test_start_function startfunc,
1620+
postprocess_result_function postfunc)
16201621
{
16211622
#define MAX_PARALLEL_TESTS 100
16221623
char *tests[MAX_PARALLEL_TESTS];
@@ -1730,7 +1731,7 @@ run_schedule(const char *schedule, test_function tfunc)
17301731
if (num_tests == 1)
17311732
{
17321733
status(_("test %-28s ... "), tests[0]);
1733-
pids[0] = (tfunc) (tests[0], &resultfiles[0], &expectfiles[0], &tags[0]);
1734+
pids[0] = (startfunc) (tests[0], &resultfiles[0], &expectfiles[0], &tags[0]);
17341735
INSTR_TIME_SET_CURRENT(starttimes[0]);
17351736
wait_for_tests(pids, statuses, stoptimes, NULL, 1);
17361737
/* status line is finished below */
@@ -1756,7 +1757,7 @@ run_schedule(const char *schedule, test_function tfunc)
17561757
tests + oldest, i - oldest);
17571758
oldest = i;
17581759
}
1759-
pids[i] = (tfunc) (tests[i], &resultfiles[i], &expectfiles[i], &tags[i]);
1760+
pids[i] = (startfunc) (tests[i], &resultfiles[i], &expectfiles[i], &tags[i]);
17601761
INSTR_TIME_SET_CURRENT(starttimes[i]);
17611762
}
17621763
wait_for_tests(pids + oldest, statuses + oldest,
@@ -1769,7 +1770,7 @@ run_schedule(const char *schedule, test_function tfunc)
17691770
status(_("parallel group (%d tests): "), num_tests);
17701771
for (i = 0; i < num_tests; i++)
17711772
{
1772-
pids[i] = (tfunc) (tests[i], &resultfiles[i], &expectfiles[i], &tags[i]);
1773+
pids[i] = (startfunc) (tests[i], &resultfiles[i], &expectfiles[i], &tags[i]);
17731774
INSTR_TIME_SET_CURRENT(starttimes[i]);
17741775
}
17751776
wait_for_tests(pids, statuses, stoptimes, tests, num_tests);
@@ -1801,6 +1802,8 @@ run_schedule(const char *schedule, test_function tfunc)
18011802
{
18021803
bool newdiff;
18031804

1805+
if (postfunc)
1806+
(*postfunc) (rl->str);
18041807
newdiff = results_differ(tests[i], rl->str, el->str);
18051808
if (newdiff && tl)
18061809
{
@@ -1867,7 +1870,8 @@ run_schedule(const char *schedule, test_function tfunc)
18671870
* Run a single test
18681871
*/
18691872
static void
1870-
run_single_test(const char *test, test_function tfunc)
1873+
run_single_test(const char *test, test_start_function startfunc,
1874+
postprocess_result_function postfunc)
18711875
{
18721876
PID_TYPE pid;
18731877
instr_time starttime;
@@ -1882,7 +1886,7 @@ run_single_test(const char *test, test_function tfunc)
18821886
bool differ = false;
18831887

18841888
status(_("test %-28s ... "), test);
1885-
pid = (tfunc) (test, &resultfiles, &expectfiles, &tags);
1889+
pid = (startfunc) (test, &resultfiles, &expectfiles, &tags);
18861890
INSTR_TIME_SET_CURRENT(starttime);
18871891
wait_for_tests(&pid, &exit_status, &stoptime, NULL, 1);
18881892

@@ -1900,6 +1904,8 @@ run_single_test(const char *test, test_function tfunc)
19001904
{
19011905
bool newdiff;
19021906

1907+
if (postfunc)
1908+
(*postfunc) (rl->str);
19031909
newdiff = results_differ(test, rl->str, el->str);
19041910
if (newdiff && tl)
19051911
{
@@ -2083,7 +2089,10 @@ help(void)
20832089
}
20842090

20852091
int
2086-
regression_main(int argc, char *argv[], init_function ifunc, test_function tfunc)
2092+
regression_main(int argc, char *argv[],
2093+
init_function ifunc,
2094+
test_start_function startfunc,
2095+
postprocess_result_function postfunc)
20872096
{
20882097
static struct option long_options[] = {
20892098
{"help", no_argument, NULL, 'h'},
@@ -2554,12 +2563,12 @@ regression_main(int argc, char *argv[], init_function ifunc, test_function tfunc
25542563

25552564
for (sl = schedulelist; sl != NULL; sl = sl->next)
25562565
{
2557-
run_schedule(sl->str, tfunc);
2566+
run_schedule(sl->str, startfunc, postfunc);
25582567
}
25592568

25602569
for (sl = extra_tests; sl != NULL; sl = sl->next)
25612570
{
2562-
run_single_test(sl->str, tfunc);
2571+
run_single_test(sl->str, startfunc, postfunc);
25632572
}
25642573

25652574
/*

src/test/regress/pg_regress.h

+19-5
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,23 @@ typedef struct _stringlist
2727
struct _stringlist *next;
2828
} _stringlist;
2929

30-
typedef PID_TYPE(*test_function) (const char *,
31-
_stringlist **,
32-
_stringlist **,
33-
_stringlist **);
30+
/*
31+
* Callback function signatures for test programs that use regression_main()
32+
*/
33+
34+
/* Initialize at program start */
3435
typedef void (*init_function) (int argc, char **argv);
3536

37+
/* Launch one test case */
38+
typedef PID_TYPE(*test_start_function) (const char *testname,
39+
_stringlist **resultfiles,
40+
_stringlist **expectfiles,
41+
_stringlist **tags);
42+
43+
/* Postprocess one result file (optional) */
44+
typedef void (*postprocess_result_function) (const char *filename);
45+
46+
3647
extern char *bindir;
3748
extern char *libdir;
3849
extern char *datadir;
@@ -48,7 +59,10 @@ extern const char *basic_diff_opts;
4859
extern const char *pretty_diff_opts;
4960

5061
int regression_main(int argc, char *argv[],
51-
init_function ifunc, test_function tfunc);
62+
init_function ifunc,
63+
test_start_function startfunc,
64+
postprocess_result_function postfunc);
65+
5266
void add_stringlist_item(_stringlist **listhead, const char *str);
5367
PID_TYPE spawn_process(const char *cmdline);
5468
void replace_string(struct StringInfoData *string,

src/test/regress/pg_regress_main.c

+4-1
Original file line numberDiff line numberDiff line change
@@ -119,5 +119,8 @@ psql_init(int argc, char **argv)
119119
int
120120
main(int argc, char *argv[])
121121
{
122-
return regression_main(argc, argv, psql_init, psql_start_test);
122+
return regression_main(argc, argv,
123+
psql_init,
124+
psql_start_test,
125+
NULL /* no postfunc needed */ );
123126
}

0 commit comments

Comments
 (0)