Thanks to visit codestin.com
Credit goes to github.com

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 <[email protected]> Discussion: https://postgr.es/m/[email protected]
1 parent 198b371 commit 7bebd0d

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)