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