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