# Copyright (c) 2021-2025, PostgreSQL Global Development Group
#
# pgbench tests which do not need a server
#
use strict;
use warnings FATAL => 'all' ;
use PostgreSQL::Test::Utils;
use Test::More;
# create a directory for scripts
my $testname = $0 ;
$testname =~ s,.*/,,;
$testname =~ s/\.pl$//;
my $testdir = "$PostgreSQL::Test::Utils::tmp_check/t_${testname}_stuff" ;
mkdir $testdir
or BAIL_OUT("could not create test directory \" ${testdir}\": $!" );
# invoke pgbench
sub pgbench
{
local $Test::Builder::Level = $Test::Builder::Level + 1 ;
my ($opts, $stat, $out, $err, $name) = @_;
command_checks_all([ 'pgbench' , split(/\s+/, $opts) ],
$stat, $out, $err, $name);
return;
}
# invoke pgbench with scripts
sub pgbench_scripts
{
local $Test::Builder::Level = $Test::Builder::Level + 1 ;
my ($opts, $stat, $out, $err, $name, $files) = @_;
my @cmd = ('pgbench' , split /\s+/, $opts);
if (defined $files)
{
for my $fn (sort keys %$files)
{
my $filename = $testdir . '/' . $fn;
# cleanup file weight if any
$filename =~ s/\@\d+$//;
# cleanup from prior runs
unlink $filename;
append_to_file($filename, $$files{$fn});
push @cmd, '--file' => $filename;
}
}
command_checks_all(\@cmd, $stat, $out, $err, $name);
return;
}
#
# Option various errors
#
my @options = (
# name, options, stderr checks
[
'bad option' ,
'-h home -p 5432 -U calvin ---debug --bad-option' ,
[qr{--help.*more information}]
],
[
'no file' ,
'-f no-such-file' ,
[qr{could not open file "no-such-file" :}]
],
[
'no builtin' ,
'-b no-such-builtin' ,
[qr{no builtin script .* "no-such-builtin" }]
],
[
'invalid weight' ,
'--builtin=select-only@one' ,
[qr{invalid weight specification: \@one}]
],
[
'invalid weight' ,
'-b select-only@-1' ,
[qr{weight spec.* out of range .*: -1 }]
],
[ 'too many scripts' , '-S ' x 129 , [qr{at most 128 SQL scripts}] ],
[
'bad #clients', '-c three',
[qr{invalid value "three" for option -c/--clients}]
],
[
'bad #threads', '-j eleven',
[qr{invalid value "eleven" for option -j/--jobs}]
],
[
'bad scale' , '-i -s two' ,
[qr{invalid value "two" for option -s/--scale}]
],
[
'invalid #transactions',
'-t zil' , [qr{invalid value "zil" for option -t/--transactions}]
],
[
'invalid duration' ,
'-T ten' , [qr{invalid value "ten" for option -T/--time}]
],
[
'-t XOR -T' ,
'-N -l --aggregate-interval=5 --log-prefix=notused -t 1000 -T 1' ,
[qr{specify either }]
],
[
'-T XOR -t' ,
'-P 1 --progress-timestamp -l --sampling-rate=0.001 -T 10 -t 1000' ,
[qr{specify either }]
],
[ 'bad variable' , '--define foobla' , [qr{invalid variable definition}] ],
[ 'invalid fillfactor' , '-F 1' , [qr{-F/--fillfactor must be in range}] ],
[ 'invalid query mode' , '-M no-such-mode' , [qr{invalid query mode}] ],
[
'invalid progress' , '--progress=0' ,
[qr{-P/--progress must be in range}]
],
[ 'invalid rate' , '--rate=0.0' , [qr{invalid rate limit}] ],
[ 'invalid latency' , '--latency-limit=0.0' , [qr{invalid latency limit}] ],
[
'invalid sampling rate' , '--sampling-rate=0' ,
[qr{invalid sampling rate}]
],
[
'invalid aggregate interval' ,
'--aggregate-interval=-3' ,
[qr{--aggregate-interval must be in range}]
],
[
'weight zero' ,
'-b se@0 -b si@0 -b tpcb@0' ,
[qr{weight must not be zero}]
],
[ 'init vs run' , '-i -S' , [qr{cannot be used in initialization}] ],
[ 'run vs init' , '-S -F 90' , [qr{cannot be used in benchmarking}] ],
[ 'ambiguous builtin' , '-b s' , [qr{ambiguous}] ],
[
'--progress-timestamp => --progress' , '--progress-timestamp' ,
[qr{allowed only under}]
],
[
'-I without init option' ,
'-I dtg' ,
[qr{cannot be used in benchmarking mode}]
],
[
'invalid init step' ,
'-i -I dta' ,
[
qr{unrecognized initialization step},
qr{Allowed step characters are}
]
],
[
'bad random seed' ,
'--random-seed=one' ,
[
qr{unrecognized random seed option "one" },
qr{Expecting an unsigned integer, "time" or "rand" },
qr{error while setting random seed from --random-seed option}
]
],
[
'bad partition method' ,
'-i --partition-method=BAD' ,
[ qr{"range" }, qr{"hash" }, qr{"BAD" } ]
],
[
'bad partition number' ,
'-i --partitions -1' ,
[qr{--partitions must be in range}]
],
[
'partition method without partitioning' ,
'-i --partition-method=hash' ,
[qr{partition-method requires greater than zero --partitions}]
],
[
'bad maximum number of tries' ,
'--max-tries -10' ,
[qr{invalid number of maximum tries: "-10" }]
],
[
'an infinite number of tries' ,
'--max-tries 0' ,
[
qr{an unlimited number of transaction tries can only be used with --latency-limit or a duration}
]
],
# logging sub-options
[
'sampling => log' , '--sampling-rate=0.01' ,
[qr{log sampling .* only when}]
],
[
'sampling XOR aggregate' ,
'-l --sampling-rate=0.1 --aggregate-interval=3' ,
[qr{sampling .* aggregation .* cannot be used at the same time}]
],
[
'aggregate => log' , '--aggregate-interval=3' ,
[qr{aggregation .* only when}]
],
[ 'log-prefix => log' , '--log-prefix=x' , [qr{prefix .* only when}] ],
[
'duration & aggregation' ,
'-l -T 1 --aggregate-interval=3' ,
[qr{aggr.* not be higher}]
],
[
'duration % aggregation' ,
'-l -T 5 --aggregate-interval=3' ,
[qr{multiple}]
],);
for my $o (@options)
{
my ($name, $opts, $err_checks) = @$o;
pgbench($opts, 1 , [qr{^$}], $err_checks,
'pgbench option error: ' . $name);
}
# Help
pgbench(
'--help' , 0 ,
[
qr{benchmarking tool for PostgreSQL},
qr{Usage},
qr{Initialization options:},
qr{Common options:},
qr{Report bugs to}
],
[qr{^$}],
'pgbench help' );
# Version
pgbench('-V' , 0 , [qr{^pgbench .PostgreSQL. }], [qr{^$}], 'pgbench version' );
# list of builtins
pgbench(
'-b list' ,
0 ,
[qr{^$}],
[
qr{Available builtin scripts:}, qr{tpcb-like},
qr{simple-update}, qr{select-only}
],
'pgbench builtin list' );
# builtin listing
pgbench(
'--show-script se' ,
0 ,
[qr{^$}],
[
qr{select-only: }, qr{SELECT abalance FROM pgbench_accounts WHERE},
qr{(?!UPDATE)}, qr{(?!INSERT)}
],
'pgbench builtin listing' );
my @script_tests = (
# name, err, { file => contents }
[
'missing endif' ,
[qr{\\if without matching \\endif }],
{ 'if-noendif.sql' => '\if 1' }
],
[
'missing if on elif' ,
[qr{\\elif without matching \\if }],
{ 'elif-noif.sql' => '\elif 1' }
],
[
'missing if on else' ,
[qr{\\else without matching \\if }],
{ 'else-noif.sql' => '\else' }
],
[
'missing if on endif' ,
[qr{\\endif without matching \\if }],
{ 'endif-noif.sql' => '\endif' }
],
[
'elif after else' ,
[qr{\\elif after \\else }],
{ 'else-elif.sql' => "\\if 1\n\\else\n\\elif 0\n\\endif" }
],
[
'else after else' ,
[qr{\\else after \\else }],
{ 'else-else.sql' => "\\if 1\n\\else\n\\else\n\\endif" }
],
[
'if syntax error' ,
[qr{syntax error in command "if" }],
{ 'if-bad.sql' => "\\if\n\\endif\n" }
],
[
'elif syntax error' ,
[qr{syntax error in command "elif" }],
{ 'elif-bad.sql' => "\\if 0\n\\elif +\n\\endif\n" }
],
[
'else syntax error' ,
[qr{unexpected argument in command "else" }],
{ 'else-bad.sql' => "\\if 0\n\\else BAD\n\\endif\n" }
],
[
'endif syntax error' ,
[qr{unexpected argument in command "endif" }],
{ 'endif-bad.sql' => "\\if 0\n\\endif BAD\n" }
],
[
'not enough arguments for least' ,
[qr{at least one argument expected \(least\)}],
{ 'bad-least.sql' => "\\set i least()\n" }
],
[
'not enough arguments for greatest' ,
[qr{at least one argument expected \(greatest\)}],
{ 'bad-greatest.sql' => "\\set i greatest()\n" }
],
[
'not enough arguments for hash' ,
[qr{unexpected number of arguments \(hash\)}],
{ 'bad-hash-1.sql' => "\\set i hash()\n" }
],
[
'too many arguments for hash' ,
[qr{unexpected number of arguments \(hash\)}],
{ 'bad-hash-2.sql' => "\\set i hash(1,2,3)\n" }
],
# overflow
[
'bigint overflow 1' ,
[qr{bigint constant overflow}],
{ 'overflow-1.sql' => "\\set i 100000000000000000000\n" }
],
[
'double overflow 2' ,
[qr{double constant overflow}],
{ 'overflow-2.sql' => "\\set d 1.0E309\n" }
],
[
'double overflow 3' ,
[qr{double constant overflow}],
{ 'overflow-3.sql' => "\\set d .1E310\n" }
],
[
'set i' ,
[ qr{set i 1 }, qr{\^ error found here} ],
{ 'set_i_op' => "\\set i 1 +\n" }
],
[
'not enough arguments to permute' ,
[qr{unexpected number of arguments \(permute\)}],
{ 'bad-permute-1.sql' => "\\set i permute(1)\n" }
],
[
'too many arguments to permute' ,
[qr{unexpected number of arguments \(permute\)}],
{ 'bad-permute-2.sql' => "\\set i permute(1, 2, 3, 4)\n" }
],);
for my $t (@script_tests)
{
my ($name, $err, $files) = @$t;
pgbench_scripts('' , 1 , [qr{^$}], $err, 'pgbench option error: ' . $name,
$files);
}
done_testing();
Messung V0.5 in Prozent C=96 H=96 G=95
¤ Dauer der Verarbeitung: 0.24 Sekunden
(vorverarbeitet am 2026-08-10)
¤
*© Formatika GbR, Deutschland