Age Owner TLA Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * isolation_main --- pg_regress test launcher for isolation tests
4 : *
5 : * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
6 : * Portions Copyright (c) 1994, Regents of the University of California
7 : *
8 : * src/test/isolation/isolation_main.c
9 : *
10 : *-------------------------------------------------------------------------
11 : */
12 :
13 : #include "postgres_fe.h"
14 :
15 : #include "pg_regress.h"
16 :
17 : char saved_argv0[MAXPGPATH];
18 : char isolation_exec[MAXPGPATH];
19 : bool looked_up_isolation_exec = false;
20 :
21 : #define PG_ISOLATION_VERSIONSTR "isolationtester (PostgreSQL) " PG_VERSION "\n"
22 :
23 : /*
24 : * start an isolation tester process for specified file (including
25 : * redirection), and return process ID
26 : */
27 : static PID_TYPE
4444 heikki.linnakangas 28 CBC 131 : isolation_start_test(const char *testname,
29 : _stringlist **resultfiles,
30 : _stringlist **expectfiles,
31 : _stringlist **tags)
32 : {
33 : PID_TYPE pid;
34 : char infile[MAXPGPATH];
35 : char outfile[MAXPGPATH];
36 : char expectfile[MAXPGPATH];
37 : char psql_cmd[MAXPGPATH * 3];
38 131 : size_t offset = 0;
39 : char *appnameenv;
40 :
41 : /* need to do the path lookup here, check isolation_init() for details */
3435 rhaas 42 131 : if (!looked_up_isolation_exec)
43 : {
44 : /* look for isolationtester binary */
45 7 : if (find_other_exec(saved_argv0, "isolationtester",
46 : PG_ISOLATION_VERSIONSTR, isolation_exec) != 0)
47 : {
3435 rhaas 48 UBC 0 : fprintf(stderr, _("could not find proper isolationtester binary\n"));
49 0 : exit(2);
50 : }
3435 rhaas 51 CBC 7 : looked_up_isolation_exec = true;
52 : }
53 :
54 : /*
55 : * Look for files in the output dir first, consistent with a vpath search.
56 : * This is mainly to create more reasonable error messages if the file is
57 : * not found. It also allows local test overrides when running pg_regress
58 : * outside of the source tree.
59 : */
4444 heikki.linnakangas 60 131 : snprintf(infile, sizeof(infile), "%s/specs/%s.spec",
61 : outputdir, testname);
62 131 : if (!file_exists(infile))
63 131 : snprintf(infile, sizeof(infile), "%s/specs/%s.spec",
64 : inputdir, testname);
65 :
66 131 : snprintf(outfile, sizeof(outfile), "%s/results/%s.out",
67 : outputdir, testname);
68 :
69 131 : snprintf(expectfile, sizeof(expectfile), "%s/expected/%s.out",
70 : outputdir, testname);
71 131 : if (!file_exists(expectfile))
72 131 : snprintf(expectfile, sizeof(expectfile), "%s/expected/%s.out",
73 : inputdir, testname);
74 :
75 131 : add_stringlist_item(resultfiles, outfile);
76 131 : add_stringlist_item(expectfiles, expectfile);
77 :
78 131 : if (launcher)
79 : {
4444 heikki.linnakangas 80 UBC 0 : offset += snprintf(psql_cmd + offset, sizeof(psql_cmd) - offset,
81 : "%s ", launcher);
1698 tgl 82 0 : if (offset >= sizeof(psql_cmd))
83 : {
84 0 : fprintf(stderr, _("command too long\n"));
85 0 : exit(2);
86 : }
87 : }
88 :
1698 tgl 89 CBC 262 : offset += snprintf(psql_cmd + offset, sizeof(psql_cmd) - offset,
90 : "\"%s\" \"dbname=%s\" < \"%s\" > \"%s\" 2>&1",
91 : isolation_exec,
92 131 : dblist->str,
93 : infile,
94 : outfile);
95 131 : if (offset >= sizeof(psql_cmd))
96 : {
1698 tgl 97 UBC 0 : fprintf(stderr, _("command too long\n"));
98 0 : exit(2);
99 : }
100 :
830 tgl 101 CBC 131 : appnameenv = psprintf("isolation/%s", testname);
102 131 : setenv("PGAPPNAME", appnameenv, 1);
103 131 : free(appnameenv);
104 :
4444 heikki.linnakangas 105 131 : pid = spawn_process(psql_cmd);
106 :
107 131 : if (pid == INVALID_PID)
108 : {
4444 heikki.linnakangas 109 UBC 0 : fprintf(stderr, _("could not start process for test %s\n"),
110 : testname);
4115 peter_e 111 0 : exit(2);
112 : }
113 :
1321 tgl 114 CBC 131 : unsetenv("PGAPPNAME");
115 :
4444 heikki.linnakangas 116 131 : return pid;
117 : }
118 :
119 : static void
3439 rhaas 120 7 : isolation_init(int argc, char **argv)
121 : {
122 : size_t argv0_len;
123 :
124 : /*
125 : * We unfortunately cannot do the find_other_exec() lookup to find the
126 : * "isolationtester" binary here. regression_main() calls the
127 : * initialization functions before parsing the commandline arguments and
128 : * thus hasn't changed the library search path at this point which in turn
129 : * can cause the "isolationtester -V" invocation that find_other_exec()
130 : * does to fail since it's linked to libpq. So we instead copy argv[0]
131 : * and do the lookup the first time through isolation_start_test().
132 : */
3432 kgrittn 133 7 : argv0_len = strlcpy(saved_argv0, argv[0], MAXPGPATH);
134 7 : if (argv0_len >= MAXPGPATH)
135 : {
2557 peter_e 136 UBC 0 : fprintf(stderr, _("path for isolationtester executable is longer than %d bytes\n"),
137 : (int) (MAXPGPATH - 1));
3432 kgrittn 138 0 : exit(2);
139 : }
140 :
141 : /* set default regression database name */
2457 tgl 142 CBC 7 : add_stringlist_item(&dblist, "isolation_regression");
4444 heikki.linnakangas 143 7 : }
144 :
145 : int
146 7 : main(int argc, char *argv[])
147 : {
818 tgl 148 7 : return regression_main(argc, argv,
149 : isolation_init,
150 : isolation_start_test,
151 : NULL /* no postfunc needed */ );
152 : }
|