Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * isolation_main --- pg_regress test launcher for isolation tests
4 : *
5 : * Portions Copyright (c) 1996-2024, 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 "lib/stringinfo.h"
16 : #include "pg_regress.h"
17 :
18 : static char saved_argv0[MAXPGPATH];
19 : static char isolation_exec[MAXPGPATH];
20 : static bool looked_up_isolation_exec = false;
21 :
22 : #define PG_ISOLATION_VERSIONSTR "isolationtester (PostgreSQL) " PG_VERSION "\n"
23 :
24 : /*
25 : * start an isolation tester process for specified file (including
26 : * redirection), and return process ID
27 : */
28 : static PID_TYPE
29 274 : isolation_start_test(const char *testname,
30 : _stringlist **resultfiles,
31 : _stringlist **expectfiles,
32 : _stringlist **tags)
33 : {
34 : PID_TYPE pid;
35 : char infile[MAXPGPATH];
36 : char outfile[MAXPGPATH];
37 : char expectfile[MAXPGPATH];
38 : StringInfoData psql_cmd;
39 : char *appnameenv;
40 :
41 : /* need to do the path lookup here, check isolation_init() for details */
42 274 : if (!looked_up_isolation_exec)
43 : {
44 : /* look for isolationtester binary */
45 16 : if (find_other_exec(saved_argv0, "isolationtester",
46 : PG_ISOLATION_VERSIONSTR, isolation_exec) != 0)
47 : {
48 0 : fprintf(stderr, _("could not find proper isolationtester binary\n"));
49 0 : exit(2);
50 : }
51 16 : 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 : */
60 274 : snprintf(infile, sizeof(infile), "%s/specs/%s.spec",
61 : outputdir, testname);
62 274 : if (!file_exists(infile))
63 274 : snprintf(infile, sizeof(infile), "%s/specs/%s.spec",
64 : inputdir, testname);
65 :
66 274 : snprintf(outfile, sizeof(outfile), "%s/results/%s.out",
67 : outputdir, testname);
68 :
69 274 : snprintf(expectfile, sizeof(expectfile), "%s/expected/%s.out",
70 : outputdir, testname);
71 274 : if (!file_exists(expectfile))
72 274 : snprintf(expectfile, sizeof(expectfile), "%s/expected/%s.out",
73 : inputdir, testname);
74 :
75 274 : add_stringlist_item(resultfiles, outfile);
76 274 : add_stringlist_item(expectfiles, expectfile);
77 :
78 274 : initStringInfo(&psql_cmd);
79 :
80 274 : if (launcher)
81 0 : appendStringInfo(&psql_cmd, "%s ", launcher);
82 :
83 274 : appendStringInfo(&psql_cmd,
84 : "\"%s\" \"dbname=%s\" < \"%s\" > \"%s\" 2>&1",
85 : isolation_exec,
86 274 : dblist->str,
87 : infile,
88 : outfile);
89 :
90 274 : appnameenv = psprintf("isolation/%s", testname);
91 274 : setenv("PGAPPNAME", appnameenv, 1);
92 274 : free(appnameenv);
93 :
94 274 : pid = spawn_process(psql_cmd.data);
95 :
96 274 : if (pid == INVALID_PID)
97 : {
98 0 : fprintf(stderr, _("could not start process for test %s\n"),
99 : testname);
100 0 : exit(2);
101 : }
102 :
103 274 : unsetenv("PGAPPNAME");
104 :
105 274 : pfree(psql_cmd.data);
106 :
107 274 : return pid;
108 : }
109 :
110 : static void
111 16 : isolation_init(int argc, char **argv)
112 : {
113 : size_t argv0_len;
114 :
115 : /*
116 : * We unfortunately cannot do the find_other_exec() lookup to find the
117 : * "isolationtester" binary here. regression_main() calls the
118 : * initialization functions before parsing the commandline arguments and
119 : * thus hasn't changed the library search path at this point which in turn
120 : * can cause the "isolationtester -V" invocation that find_other_exec()
121 : * does to fail since it's linked to libpq. So we instead copy argv[0]
122 : * and do the lookup the first time through isolation_start_test().
123 : */
124 16 : argv0_len = strlcpy(saved_argv0, argv[0], MAXPGPATH);
125 16 : if (argv0_len >= MAXPGPATH)
126 : {
127 0 : fprintf(stderr, _("path for isolationtester executable is longer than %d bytes\n"),
128 : (int) (MAXPGPATH - 1));
129 0 : exit(2);
130 : }
131 :
132 : /* set default regression database name */
133 16 : add_stringlist_item(&dblist, "isolation_regression");
134 16 : }
135 :
136 : int
137 16 : main(int argc, char *argv[])
138 : {
139 16 : return regression_main(argc, argv,
140 : isolation_init,
141 : isolation_start_test,
142 : NULL /* no postfunc needed */ );
143 : }
|