Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit7c01504

Browse files
committed
Add basic TAP tests for psql's tab-completion logic.
Up to now, psql's tab-complete.c has had exactly no regression testcoverage. This patch is an experimental attempt to add some.This needs Perl's IO::Pty module, which isn't installed everywhere,so the test script just skips all tests if that's not present.There may be other portability gotchas too, so I await buildfarmresults with interest.So far this just covers a few very basic keyword-completion andquery-driven-completion scenarios, which should be enough to let usget a feel for whether this is practical at all from a portabilitystandpoint. If it is, there's lots more that can be done.Discussion:https://postgr.es/m/10967.1577562752@sss.pgh.pa.us
1 parent915c04f commit7c01504

File tree

7 files changed

+204
-1
lines changed

7 files changed

+204
-1
lines changed

‎configure

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -706,6 +706,7 @@ with_libxml
706706
XML2_CONFIG
707707
UUID_EXTRA_OBJS
708708
with_uuid
709+
with_readline
709710
with_systemd
710711
with_selinux
711712
with_openssl
@@ -8000,6 +8001,7 @@ $as_echo "$as_me: WARNING: *** Readline does not work on MinGW --- disabling" >&
80008001
fi
80018002

80028003

8004+
80038005
#
80048006
# Prefer libedit
80058007
#

‎configure.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -875,6 +875,7 @@ if test "$PORTNAME" = "win32"; then
875875
with_readline=no
876876
fi
877877
fi
878+
AC_SUBST(with_readline)
878879

879880

880881
#

‎src/Makefile.global.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,7 @@ with_perl= @with_perl@
185185
with_python= @with_python@
186186
with_tcl= @with_tcl@
187187
with_openssl= @with_openssl@
188+
with_readline= @with_readline@
188189
with_selinux= @with_selinux@
189190
with_systemd= @with_systemd@
190191
with_gssapi= @with_gssapi@

‎src/bin/psql/.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/psqlscanslash.c
22
/sql_help.h
33
/sql_help.c
4-
54
/psql
5+
/tmp_check/

‎src/bin/psql/Makefile

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ subdir = src/bin/psql
1616
top_builddir = ../../..
1717
include$(top_builddir)/src/Makefile.global
1818

19+
# make this available to TAP test scripts
20+
exportwith_readline
21+
1922
REFDOCDIR=$(top_srcdir)/doc/src/sgml/ref
2023

2124
overrideCPPFLAGS := -I. -I$(srcdir) -I$(libpq_srcdir)$(CPPFLAGS)
@@ -73,8 +76,15 @@ uninstall:
7376

7477
cleandistclean:
7578
rm -f psql$(X)$(OBJS) lex.backup
79+
rm -rf tmp_check
7680

7781
# files removed here are supposed to be in the distribution tarball,
7882
# so do not clean them in the clean/distclean rules
7983
maintainer-clean: distclean
8084
rm -f sql_help.h sql_help.c psqlscanslash.c
85+
86+
check:
87+
$(prove_check)
88+
89+
installcheck:
90+
$(prove_installcheck)

‎src/bin/psql/t/010_tab_completion.pl

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
use strict;
2+
use warnings;
3+
4+
use PostgresNode;
5+
use TestLib;
6+
use Test::More;
7+
use IPC::Runqw(pump finish timer);
8+
9+
if ($ENV{with_readline}ne'yes')
10+
{
11+
planskip_all=>'readline is not supported by this build';
12+
}
13+
14+
# If we don't have IO::Pty, forget it, because IPC::Run depends on that
15+
# to support pty connections
16+
eval {require IO::Pty; };
17+
if ($@)
18+
{
19+
planskip_all=>'IO::Pty is needed to run this test';
20+
}
21+
22+
# start a new server
23+
my$node = get_new_node('main');
24+
$node->init;
25+
$node->start;
26+
27+
# set up a few database objects
28+
$node->safe_psql('postgres',
29+
"CREATE TABLE tab1 (f1 int, f2 text);\n"
30+
."CREATE TABLE mytab123 (f1 int, f2 text);\n"
31+
."CREATE TABLE mytab246 (f1 int, f2 text);\n");
32+
33+
# Developers would not appreciate this test adding a bunch of junk to
34+
# their ~/.psql_history, so be sure to redirect history into a temp file.
35+
# We might as well put it in the test log directory, so that buildfarm runs
36+
# capture the result for possible debugging purposes.
37+
my$historyfile ="${TestLib::log_path}/010_psql_history.txt";
38+
$ENV{PSQL_HISTORY} =$historyfile;
39+
40+
# fire up an interactive psql session
41+
my$in ='';
42+
my$out ='';
43+
44+
my$timer = timer(5);
45+
46+
my$h =$node->interactive_psql('postgres', \$in, \$out,$timer);
47+
48+
ok($out =~/psql/,"print startup banner");
49+
50+
# Simple test case: type something and see if psql responds as expected
51+
subcheck_completion
52+
{
53+
my ($send,$pattern,$annotation) =@_;
54+
55+
# reset output collector
56+
$out ="";
57+
# restart per-command timer
58+
$timer->start(5);
59+
# send the data to be sent
60+
$in .=$send;
61+
# wait ...
62+
pump$huntil ($out =~m/$pattern/ ||$timer->is_expired);
63+
my$okay = ($out =~m/$pattern/ && !$timer->is_expired);
64+
ok($okay,$annotation);
65+
# for debugging, log actual output if it didn't match
66+
note'Actual output was "' .$out ."\"\n"if !$okay;
67+
}
68+
69+
# Clear query buffer to start over
70+
# (won't work if we are inside a string literal!)
71+
subclear_query
72+
{
73+
check_completion("\\r\n","postgres=#","\\r works");
74+
}
75+
76+
# check basic command completion: SEL<tab> produces SELECT<space>
77+
check_completion("SEL\t","SELECT","complete SEL<tab> to SELECT");
78+
79+
clear_query();
80+
81+
# check case variation is honored
82+
check_completion("sel\t","select","complete sel<tab> to select");
83+
84+
# check basic table name completion
85+
check_completion("* from t\t","\\* from tab1","complete t<tab> to tab1");
86+
87+
clear_query();
88+
89+
# check table name completion with multiple alternatives
90+
# note: readline might print a bell before the completion
91+
check_completion(
92+
"select * from my\t",
93+
"select\\* from my\a?tab",
94+
"complete my<tab> to mytab when there are multiple choices");
95+
96+
# some versions of readline/libedit require two tabs here, some only need one
97+
check_completion("\t\t","mytab123 +mytab246",
98+
"offer multiple table choices");
99+
100+
check_completion("2\t","246",
101+
"finish completion of one of multiple table choices");
102+
103+
clear_query();
104+
105+
# check case-sensitive keyword replacement
106+
# XXX the output here might vary across readline versions
107+
check_completion(
108+
"\\DRD\t",
109+
"\\DRD\b\b\bdrds",
110+
"complete\\DRD<tab> to\\drds");
111+
112+
clear_query();
113+
114+
# send psql an explicit \q to shut it down, else pty won't close properly
115+
$timer->start(5);
116+
$in .="\\q\n";
117+
finish$hordie"psql returned$?";
118+
$timer->reset;
119+
120+
# done
121+
$node->stop;
122+
done_testing();

‎src/test/perl/PostgresNode.pm

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1534,6 +1534,73 @@ sub psql
15341534

15351535
=pod
15361536
1537+
=item$node->interactive_psql($dbname, \$stdin, \$stdout, $timer, %params) => harness
1538+
1539+
InvokeB<psql> onB<$dbname> and return an IPC::Run harness object,
1540+
which the caller may use to send interactive input toB<psql>.
1541+
The process's stdin is sourced from the $stdin scalar reference,
1542+
and its stdout and stderr go to the $stdout scalar reference.
1543+
ptys are used so that psql thinks it's being called interactively.
1544+
1545+
The specified timer object is attached to the harness, as well.
1546+
It's caller's responsibility to select the timeout length, and to
1547+
restart the timer after each command if the timeout is per-command.
1548+
1549+
psql is invoked in tuples-only unaligned mode with reading ofB<.psqlrc>
1550+
disabled. That may be overridden by passing extra psql parameters.
1551+
1552+
Dies on failure to invoke psql, or if psql fails to connect.
1553+
Errors occurring later are the caller's problem.
1554+
1555+
Be sure to "finish" the harness when done with it.
1556+
1557+
The only extra parameter currently accepted is
1558+
1559+
=over
1560+
1561+
=itemextra_params => ['--single-transaction']
1562+
1563+
If given, it must be an array reference containing additional parameters toB<psql>.
1564+
1565+
=back
1566+
1567+
This requires IO::Pty in addition to IPC::Run.
1568+
1569+
=cut
1570+
1571+
subinteractive_psql
1572+
{
1573+
my ($self,$dbname,$stdin,$stdout,$timer,%params) =@_;
1574+
1575+
my@psql_params = ('psql','-XAt','-d',$self->connstr($dbname));
1576+
1577+
push@psql_params, @{$params{extra_params} }
1578+
ifdefined$params{extra_params};
1579+
1580+
# Ensure there is no data waiting to be sent:
1581+
$$stdin =""ifref($stdin);
1582+
# IPC::Run would otherwise append to existing contents:
1583+
$$stdout =""ifref($stdout);
1584+
1585+
my$harness = IPC::Run::start \@psql_params,
1586+
'<pty<',$stdin,'>pty>',$stdout,$timer;
1587+
1588+
# Pump until we see psql's help banner. This ensures that callers
1589+
# won't write anything to the pty before it's ready, avoiding an
1590+
# implementation issue in IPC::Run. Also, it means that psql
1591+
# connection failures are caught here, relieving callers of
1592+
# the need to handle those. (Right now, we have no particularly
1593+
# good handling for errors anyway, but that might be added later.)
1594+
pump$harness
1595+
until$$stdout =~/Type "help" for help/ ||$timer->is_expired;
1596+
1597+
die"psql startup timed out"if$timer->is_expired;
1598+
1599+
return$harness;
1600+
}
1601+
1602+
=pod
1603+
15371604
=item$node->poll_query_until($dbname, $query [, $expected ])
15381605
15391606
RunB<$query> repeatedly, until it returns theB<$expected> result

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp