Skip to content

Commit 7bebd0d

Browse files
committed
libpq_pipeline: add PQtrace() support and tests
The libpq_pipeline program recently introduced by commit acb7e4e is well equipped to test the PQtrace() functionality, so let's make it do that. Author: Álvaro Herrera <alvherre@alvh.no-ip.org> Discussion: https://postgr.es/m/20210327192812.GA25115@alvherre.pgsql
1 parent 198b371 commit 7bebd0d

File tree

9 files changed

+352
-28
lines changed

9 files changed

+352
-28
lines changed

src/test/modules/libpq_pipeline/libpq_pipeline.c

Lines changed: 60 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,17 @@
2323
#include "catalog/pg_type_d.h"
2424
#include "common/fe_memutils.h"
2525
#include "libpq-fe.h"
26+
#include "pg_getopt.h"
2627
#include "portability/instr_time.h"
2728

2829

2930
static void exit_nicely(PGconn *conn);
3031

3132
const char *const progname = "libpq_pipeline";
3233

34+
/* Options and defaults */
35+
char *tracefile = NULL; /* path to PQtrace() file */
36+
3337

3438
#define DEBUG
3539
#ifdef DEBUG
@@ -1209,8 +1213,10 @@ usage(const char *progname)
12091213
{
12101214
fprintf(stderr, "%s tests libpq's pipeline mode.\n\n", progname);
12111215
fprintf(stderr, "Usage:\n");
1212-
fprintf(stderr, " %s tests", progname);
1213-
fprintf(stderr, " %s testname [conninfo [number_of_rows]]\n", progname);
1216+
fprintf(stderr, " %s [OPTION] tests\n", progname);
1217+
fprintf(stderr, " %s [OPTION] TESTNAME [CONNINFO [NUMBER_OF_ROWS]\n", progname);
1218+
fprintf(stderr, "\nOptions:\n");
1219+
fprintf(stderr, " -t TRACEFILE generate a libpq trace to TRACEFILE\n");
12141220
}
12151221

12161222
static void
@@ -1231,37 +1237,54 @@ main(int argc, char **argv)
12311237
{
12321238
const char *conninfo = "";
12331239
PGconn *conn;
1240+
FILE *trace;
1241+
char *testname;
12341242
int numrows = 10000;
12351243
PGresult *res;
1244+
int c;
12361245

1237-
if (strcmp(argv[1], "tests") == 0)
1246+
while ((c = getopt(argc, argv, "t:")) != -1)
12381247
{
1239-
print_test_list();
1240-
exit(0);
1248+
switch (c)
1249+
{
1250+
case 't': /* trace file */
1251+
tracefile = pg_strdup(optarg);
1252+
break;
1253+
}
12411254
}
12421255

1243-
/*
1244-
* The testname parameter is mandatory; it can be followed by a conninfo
1245-
* string and number of rows.
1246-
*/
1247-
if (argc < 2 || argc > 4)
1256+
if (optind < argc)
1257+
{
1258+
testname = argv[optind];
1259+
optind++;
1260+
}
1261+
else
12481262
{
12491263
usage(argv[0]);
12501264
exit(1);
12511265
}
12521266

1253-
if (argc >= 3)
1254-
conninfo = pg_strdup(argv[2]);
1267+
if (strcmp(testname, "tests") == 0)
1268+
{
1269+
print_test_list();
1270+
exit(0);
1271+
}
12551272

1256-
if (argc >= 4)
1273+
if (optind < argc)
1274+
{
1275+
conninfo = argv[optind];
1276+
optind++;
1277+
}
1278+
if (optind < argc)
12571279
{
12581280
errno = 0;
1259-
numrows = strtol(argv[3], NULL, 10);
1281+
numrows = strtol(argv[optind], NULL, 10);
12601282
if (errno != 0 || numrows <= 0)
12611283
{
1262-
fprintf(stderr, "couldn't parse \"%s\" as a positive integer\n", argv[3]);
1284+
fprintf(stderr, "couldn't parse \"%s\" as a positive integer\n", argv[optind]);
12631285
exit(1);
12641286
}
1287+
optind++;
12651288
}
12661289

12671290
/* Make a connection to the database */
@@ -1272,30 +1295,42 @@ main(int argc, char **argv)
12721295
PQerrorMessage(conn));
12731296
exit_nicely(conn);
12741297
}
1298+
1299+
/* Set the trace file, if requested */
1300+
if (tracefile != NULL)
1301+
{
1302+
trace = fopen(tracefile, "w+");
1303+
1304+
if (trace == NULL)
1305+
pg_fatal("could not open file \"%s\": %m", tracefile);
1306+
PQtrace(conn, trace);
1307+
PQtraceSetFlags(conn,
1308+
PQTRACE_SUPPRESS_TIMESTAMPS | PQTRACE_REGRESS_MODE);
1309+
}
1310+
12751311
res = PQexec(conn, "SET lc_messages TO \"C\"");
12761312
if (PQresultStatus(res) != PGRES_COMMAND_OK)
12771313
pg_fatal("failed to set lc_messages: %s", PQerrorMessage(conn));
12781314

1279-
if (strcmp(argv[1], "disallowed_in_pipeline") == 0)
1315+
if (strcmp(testname, "disallowed_in_pipeline") == 0)
12801316
test_disallowed_in_pipeline(conn);
1281-
else if (strcmp(argv[1], "multi_pipelines") == 0)
1317+
else if (strcmp(testname, "multi_pipelines") == 0)
12821318
test_multi_pipelines(conn);
1283-
else if (strcmp(argv[1], "pipeline_abort") == 0)
1319+
else if (strcmp(testname, "pipeline_abort") == 0)
12841320
test_pipeline_abort(conn);
1285-
else if (strcmp(argv[1], "pipelined_insert") == 0)
1321+
else if (strcmp(testname, "pipelined_insert") == 0)
12861322
test_pipelined_insert(conn, numrows);
1287-
else if (strcmp(argv[1], "prepared") == 0)
1323+
else if (strcmp(testname, "prepared") == 0)
12881324
test_prepared(conn);
1289-
else if (strcmp(argv[1], "simple_pipeline") == 0)
1325+
else if (strcmp(testname, "simple_pipeline") == 0)
12901326
test_simple_pipeline(conn);
1291-
else if (strcmp(argv[1], "singlerow") == 0)
1327+
else if (strcmp(testname, "singlerow") == 0)
12921328
test_singlerowmode(conn);
1293-
else if (strcmp(argv[1], "transaction") == 0)
1329+
else if (strcmp(testname, "transaction") == 0)
12941330
test_transaction(conn);
12951331
else
12961332
{
1297-
fprintf(stderr, "\"%s\" is not a recognized test name\n", argv[1]);
1298-
usage(argv[0]);
1333+
fprintf(stderr, "\"%s\" is not a recognized test name\n", testname);
12991334
exit(1);
13001335
}
13011336

src/test/modules/libpq_pipeline/t/001_libpq_pipeline.pl

Lines changed: 50 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
use Config;
55
use PostgresNode;
66
use TestLib;
7-
use Test::More tests => 8;
7+
use Test::More;
88
use Cwd;
99

1010
my $node = get_new_node('main');
@@ -14,15 +14,62 @@
1414
my $numrows = 10000;
1515
$ENV{PATH} = "$ENV{PATH}:" . getcwd();
1616

17-
my ($out, $err) = run_command(['libpq_pipeline', 'tests']);
17+
my ($out, $err) = run_command([ 'libpq_pipeline', 'tests' ]);
1818
die "oops: $err" unless $err eq '';
1919
my @tests = split(/\s+/, $out);
2020

2121
for my $testname (@tests)
2222
{
23+
my @extraargs = ();
24+
my $cmptrace = grep(/^$testname$/,
25+
qw(simple_pipeline multi_pipelines prepared singlerow
26+
pipeline_abort transaction disallowed_in_pipeline)) > 0;
27+
28+
# For a bunch of tests, generate a libpq trace file too.
29+
my $traceout = "$TestLib::log_path/$testname.trace";
30+
if ($cmptrace)
31+
{
32+
push @extraargs, "-t", $traceout;
33+
}
34+
35+
# Execute the test
2336
$node->command_ok(
24-
[ 'libpq_pipeline', $testname, $node->connstr('postgres'), $numrows ],
37+
[
38+
'libpq_pipeline', @extraargs,
39+
$testname, $node->connstr('postgres'),
40+
$numrows
41+
],
2542
"libpq_pipeline $testname");
43+
44+
# Compare the trace, if requested
45+
if ($cmptrace)
46+
{
47+
my $expected;
48+
my $result;
49+
50+
$expected = slurp_file_eval("traces/$testname.trace");
51+
next unless $expected ne "";
52+
$result = slurp_file_eval($traceout);
53+
next unless $result ne "";
54+
55+
is($expected, $result, "$testname trace match");
56+
}
2657
}
2758

2859
$node->stop('fast');
60+
61+
done_testing();
62+
63+
sub slurp_file_eval
64+
{
65+
my $filepath = shift;
66+
my $contents;
67+
68+
eval { $contents = slurp_file($filepath); };
69+
if ($@)
70+
{
71+
fail "reading $filepath: $@";
72+
return "";
73+
}
74+
return $contents;
75+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
F 27 Query "SET lc_messages TO "C""
2+
B 8 CommandComplete "SET"
3+
B 5 ReadyForQuery I
4+
F 13 Query "SELECT 1"
5+
B 33 RowDescription 1 "?column?" NNNN 0 NNNN 4 -1 0
6+
B 11 DataRow 1 1 '1'
7+
B 13 CommandComplete "SELECT 1"
8+
B 5 ReadyForQuery I
9+
F 4 Terminate
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
F 27 Query "SET lc_messages TO "C""
2+
B 8 CommandComplete "SET"
3+
B 5 ReadyForQuery I
4+
F 21 Parse "" "SELECT $1" 1 NNNN
5+
F 19 Bind "" "" 0 1 1 '1' 1 0
6+
F 6 Describe P ""
7+
F 9 Execute "" 0
8+
F 4 Sync
9+
F 21 Parse "" "SELECT $1" 1 NNNN
10+
F 19 Bind "" "" 0 1 1 '1' 1 0
11+
F 6 Describe P ""
12+
F 9 Execute "" 0
13+
F 4 Sync
14+
B 4 ParseComplete
15+
B 4 BindComplete
16+
B 33 RowDescription 1 "?column?" NNNN 0 NNNN 4 -1 0
17+
B 11 DataRow 1 1 '1'
18+
B 13 CommandComplete "SELECT 1"
19+
B 5 ReadyForQuery I
20+
B 4 ParseComplete
21+
B 4 BindComplete
22+
B 33 RowDescription 1 "?column?" NNNN 0 NNNN 4 -1 0
23+
B 11 DataRow 1 1 '1'
24+
B 13 CommandComplete "SELECT 1"
25+
B 5 ReadyForQuery I
26+
F 4 Terminate
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
F 27 Query "SET lc_messages TO "C""
2+
B 8 CommandComplete "SET"
3+
B 5 ReadyForQuery I
4+
F 42 Query "DROP TABLE IF EXISTS pq_pipeline_demo"
5+
B 123 NoticeResponse S "NOTICE" V "NOTICE" C "00000" M "table "pq_pipeline_demo" does not exist, skipping" F "SSSS" L "SSSS" R "SSSS" \x00
6+
B 15 CommandComplete "DROP TABLE"
7+
B 5 ReadyForQuery I
8+
F 83 Query "CREATE UNLOGGED TABLE pq_pipeline_demo(id serial primary key, itemno integer);"
9+
B 17 CommandComplete "CREATE TABLE"
10+
B 5 ReadyForQuery I
11+
F 61 Parse "" "INSERT INTO pq_pipeline_demo(itemno) VALUES ($1);" 1 NNNN
12+
F 19 Bind "" "" 0 1 1 '1' 1 0
13+
F 6 Describe P ""
14+
F 9 Execute "" 0
15+
F 39 Parse "" "SELECT no_such_function($1)" 1 NNNN
16+
F 19 Bind "" "" 0 1 1 '1' 1 0
17+
F 6 Describe P ""
18+
F 9 Execute "" 0
19+
F 61 Parse "" "INSERT INTO pq_pipeline_demo(itemno) VALUES ($1);" 1 NNNN
20+
F 19 Bind "" "" 0 1 1 '2' 1 0
21+
F 6 Describe P ""
22+
F 9 Execute "" 0
23+
F 4 Sync
24+
F 61 Parse "" "INSERT INTO pq_pipeline_demo(itemno) VALUES ($1);" 1 NNNN
25+
F 19 Bind "" "" 0 1 1 '3' 1 0
26+
F 6 Describe P ""
27+
F 9 Execute "" 0
28+
F 4 Sync
29+
B 4 ParseComplete
30+
B 4 BindComplete
31+
B 4 NoData
32+
B 15 CommandComplete "INSERT 0 1"
33+
B 217 ErrorResponse S "ERROR" V "ERROR" C "42883" M "function no_such_function(integer) does not exist" H "No function matches the given name and argument types. You might need to add explicit type casts." P "8" F "SSSS" L "SSSS" R "SSSS" \x00
34+
B 5 ReadyForQuery I
35+
B 4 ParseComplete
36+
B 4 BindComplete
37+
B 4 NoData
38+
B 15 CommandComplete "INSERT 0 1"
39+
B 5 ReadyForQuery I
40+
F 26 Parse "" "SELECT 1; SELECT 2" 0
41+
F 12 Bind "" "" 0 0 0
42+
F 6 Describe P ""
43+
F 9 Execute "" 0
44+
F 4 Sync
45+
B 123 ErrorResponse S "ERROR" V "ERROR" C "42601" M "cannot insert multiple commands into a prepared statement" F "SSSS" L "SSSS" R "SSSS" \x00
46+
B 5 ReadyForQuery I
47+
F 54 Parse "" "SELECT 1.0/g FROM generate_series(3, -1, -1) g" 0
48+
F 12 Bind "" "" 0 0 0
49+
F 6 Describe P ""
50+
F 9 Execute "" 0
51+
F 4 Sync
52+
B 4 ParseComplete
53+
B 4 BindComplete
54+
B 33 RowDescription 1 "?column?" NNNN 0 NNNN 65535 -1 0
55+
B 32 DataRow 1 22 '0.33333333333333333333'
56+
B 32 DataRow 1 22 '0.50000000000000000000'
57+
B 32 DataRow 1 22 '1.00000000000000000000'
58+
B 70 ErrorResponse S "ERROR" V "ERROR" C "22012" M "division by zero" F "SSSS" L "SSSS" R "SSSS" \x00
59+
B 5 ReadyForQuery I
60+
F 40 Query "SELECT itemno FROM pq_pipeline_demo"
61+
B 31 RowDescription 1 "itemno" NNNN 2 NNNN 4 -1 0
62+
B 11 DataRow 1 1 '3'
63+
B 13 CommandComplete "SELECT 1"
64+
B 5 ReadyForQuery I
65+
F 4 Terminate
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
F 27 Query "SET lc_messages TO "C""
2+
B 8 CommandComplete "SET"
3+
B 5 ReadyForQuery I
4+
F 68 Parse "select_one" "SELECT $1, '42', $1::numeric, interval '1 sec'" 1 NNNN
5+
F 16 Describe S "select_one"
6+
F 4 Sync
7+
B 4 ParseComplete
8+
B 10 ParameterDescription 1 NNNN
9+
B 113 RowDescription 4 "?column?" NNNN 0 NNNN 4 -1 0 "?column?" NNNN 0 NNNN 65535 -1 0 "numeric" NNNN 0 NNNN 65535 -1 0 "interval" NNNN 0 NNNN 16 -1 0
10+
B 5 ReadyForQuery I
11+
F 10 Query "BEGIN"
12+
B 10 CommandComplete "BEGIN"
13+
B 5 ReadyForQuery T
14+
F 43 Query "DECLARE cursor_one CURSOR FOR SELECT 1"
15+
B 19 CommandComplete "DECLARE CURSOR"
16+
B 5 ReadyForQuery T
17+
F 16 Describe P "cursor_one"
18+
F 4 Sync
19+
B 33 RowDescription 1 "?column?" NNNN 0 NNNN 4 -1 0
20+
B 5 ReadyForQuery T
21+
F 4 Terminate
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
F 27 Query "SET lc_messages TO "C""
2+
B 8 CommandComplete "SET"
3+
B 5 ReadyForQuery I
4+
F 21 Parse "" "SELECT $1" 1 NNNN
5+
F 19 Bind "" "" 0 1 1 '1' 1 0
6+
F 6 Describe P ""
7+
F 9 Execute "" 0
8+
F 4 Sync
9+
B 4 ParseComplete
10+
B 4 BindComplete
11+
B 33 RowDescription 1 "?column?" NNNN 0 NNNN 4 -1 0
12+
B 11 DataRow 1 1 '1'
13+
B 13 CommandComplete "SELECT 1"
14+
B 5 ReadyForQuery I
15+
F 4 Terminate

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy