Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 19dbf55

Browse files
authored
Merge pull request #41 from sokolcati/progress_bar
[PGPRO-3690] Tests for progress_bar.
2 parents ad88ee9 + 3cfbffa commit 19dbf55

File tree

6 files changed

+143
-0
lines changed

6 files changed

+143
-0
lines changed

Makefile

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,9 @@ submake-isolation:
4242
$(MAKE) -C $(top_builddir)/src/test/isolation all
4343

4444
temp-install: EXTRA_INSTALL=contrib/pg_query_state
45+
46+
submake-progress_bar:
47+
$(MAKE) -C $(top_builddir)/contrib/pg_query_state
48+
49+
check_progress_bar: submake-progress_bar temp-install
50+
$(prove_check)

pg_query_state.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1360,6 +1360,12 @@ progress_bar(PG_FUNCTION_ARGS)
13601360

13611361
old_progress = 0;
13621362
progress = 0;
1363+
if (SRF_IS_FIRSTCALL())
1364+
{
1365+
pg_atomic_write_u32(&counterpart_userid->n_peers, 1);
1366+
params->reqid = ++reqid;
1367+
}
1368+
13631369
bg_worker_procs = GetRemoteBackendWorkers(proc);
13641370
msgs = GetRemoteBackendQueryStates(proc,
13651371
bg_worker_procs,

t/test_bad_progress_bar.pl

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
# pg_query_state/t/test_bad_progress_bar.pl
2+
#
3+
# Check uncorrect launches of functions progress_bar(pid)
4+
# and progress_bar_visual(pid, delay)
5+
6+
use strict;
7+
use warnings;
8+
use PostgresNode;
9+
use TestLib;
10+
use Test::More tests => 2;
11+
12+
# List of checks for bad cases:
13+
# 1) appealing to a bad pid
14+
# ------- requires DBI and DBD::Pg modules -------
15+
# 2) extracting the state of the process itself
16+
17+
# Test whether we have both DBI and DBD::pg
18+
my $dbdpg_rc = eval
19+
{
20+
require DBI;
21+
require DBD::Pg;
22+
DBD::Pg->import(':async');
23+
1;
24+
};
25+
26+
# start backend for function progress_bar
27+
my $node = PostgresNode->get_new_node('master');
28+
$node->init;
29+
$node->start;
30+
$node->append_conf('postgresql.conf', "shared_preload_libraries = 'pg_query_state'");
31+
$node->restart;
32+
$node->psql('postgres', 'CREATE EXTENSION pg_query_state;');
33+
34+
subtest 'Extracting from bad pid' => sub {
35+
my $stderr;
36+
$node->psql('postgres', 'SELECT * from progress_bar(-1)', stderr => \$stderr);
37+
is ($stderr, 'psql:<stdin>:1: ERROR: backend with pid=-1 not found', "appealing to a bad pid for progress_bar");
38+
$node->psql('postgres', 'SELECT * from progress_bar(-1)_visual', stderr => \$stderr);
39+
is ($stderr, 'psql:<stdin>:1: ERROR: backend with pid=-1 not found', "appealing to a bad pid for progress_bar_visual");
40+
};
41+
42+
if ( not $dbdpg_rc) {
43+
diag('DBI and DBD::Pg are not available, skip 2/3 tests');
44+
}
45+
46+
SKIP: {
47+
skip "DBI and DBD::Pg are not available", 2 if not $dbdpg_rc;
48+
49+
my $dbh_status = DBI->connect('DBI:Pg:' . $node->connstr($_));
50+
if ( !defined $dbh_status )
51+
{
52+
die "Cannot connect to database for dbh with progress_bar\n";
53+
}
54+
55+
my $pid_status = $dbh_status->{pg_pid};
56+
57+
subtest 'Extracting your own status' => sub {
58+
$dbh_status->do('SELECT * from progress_bar(' . $pid_status . ')');
59+
is($dbh_status->errstr, 'ERROR: attempt to extract state of current process', "extracting the state of the process itself for progress_bar");
60+
$dbh_status->do('SELECT * from progress_bar_visual(' . $pid_status . ')');
61+
is($dbh_status->errstr, 'ERROR: attempt to extract state of current process', "extracting the state of the process itself for progress_bar_visual");
62+
};
63+
64+
$dbh_status->disconnect;
65+
}
66+
67+
$node->stop('fast');

tests/common.py

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,54 @@ def onetime_query_state(config, async_conn, query, args={}, num_workers=0):
161161
set_guc(async_conn, 'enable_mergejoin', 'on')
162162
return result, notices
163163

164+
def progress_bar(config, pid):
165+
conn = psycopg2.connect(**config)
166+
curs = conn.cursor()
167+
168+
curs.callproc('progress_bar', (pid,))
169+
result = curs.fetchall()
170+
notices = conn.notices[:]
171+
conn.close()
172+
173+
return result, notices
174+
175+
def onetime_progress_bar(config, async_conn, query, args={}, num_workers=0):
176+
"""
177+
Get intermediate state of 'query' on connection 'async_conn' after number of 'steps'
178+
of node executions from start of query
179+
"""
180+
181+
acurs = async_conn.cursor()
182+
183+
set_guc(async_conn, 'enable_mergejoin', 'off')
184+
set_guc(async_conn, 'max_parallel_workers_per_gather', num_workers)
185+
acurs.execute(query)
186+
187+
# extract progress of current query
188+
MAX_PG_QS_RETRIES = 10
189+
DELAY_BETWEEN_RETRIES = 0.1
190+
pg_qs_args = {
191+
'config': config,
192+
'pid': async_conn.get_backend_pid(),
193+
}
194+
for k, v in args.items():
195+
pg_qs_args[k] = v
196+
n_retries = 0
197+
while True:
198+
result, notices = progress_bar(**pg_qs_args)
199+
n_retries += 1
200+
if len(result) > 0:
201+
break
202+
if n_retries >= MAX_PG_QS_RETRIES:
203+
# pg_query_state callings don't return any result, more likely run
204+
# query has completed
205+
break
206+
time.sleep(DELAY_BETWEEN_RETRIES)
207+
wait(async_conn)
208+
209+
set_guc(async_conn, 'enable_mergejoin', 'on')
210+
return result, notices
211+
164212
def set_guc(async_conn, param, value):
165213
acurs = async_conn.cursor()
166214
acurs.execute('set %s to %s' % (param, value))

tests/pg_qs_test_runner.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ class TeardownException(Exception): pass
6868
test_formats,
6969
test_timing_buffers_conflicts,
7070
test_insert_on_conflict,
71+
test_progress_bar,
7172
]
7273

7374
def setup(con):

tests/test_cases.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -386,3 +386,18 @@ def test_timing_buffers_conflicts(config):
386386
and 'WARNING: buffers statistics disabled\n' in notices
387387

388388
common.n_close((acon,))
389+
390+
def test_progress_bar(config):
391+
"""test progress_bar of simple query"""
392+
393+
acon, = common.n_async_connect(config)
394+
query = 'select * from foo join bar on foo.c1=bar.c1'
395+
396+
qs, notices = common.onetime_progress_bar(config, acon, query)
397+
assert qs[0][0] >= 0 and qs[0][0] < 1
398+
first_qs = qs[0][0]
399+
400+
qs, _ = common.onetime_progress_bar(config, acon, query)
401+
assert qs[0][0] >= first_qs and qs[0][0] < 1
402+
403+
common.n_close((acon,))

0 commit comments

Comments
 (0)