1
0
Fork 0

Merging upstream version 4.0.1.

Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
Daniel Baumann 2025-02-09 20:05:21 +01:00
parent af10454b21
commit 7c65fc707e
Signed by: daniel
GPG key ID: FBB4F0E80A80222F
42 changed files with 955 additions and 184 deletions

View file

@ -23,6 +23,30 @@ Feature: run the cli,
When we send "ctrl + d"
then dbcli exits
Scenario: confirm exit when a transaction is ongoing
When we begin transaction
and we try to send "ctrl + d"
then we see ongoing transaction message
when we send "c"
then dbcli exits
Scenario: cancel exit when a transaction is ongoing
When we begin transaction
and we try to send "ctrl + d"
then we see ongoing transaction message
when we send "a"
then we see dbcli prompt
when we rollback transaction
when we send "ctrl + d"
then dbcli exits
Scenario: interrupt current query via "ctrl + c"
When we send sleep query
and we send "ctrl + c"
then we see cancelled query warning
when we check for any non-idle sleep queries
then we don't see any non-idle sleep queries
Scenario: list databases
When we list databases
then we see list of databases

View file

@ -5,7 +5,7 @@ Feature: manipulate databases:
When we create database
then we see database created
when we drop database
then we confirm the destructive warning
then we respond to the destructive warning: y
then we see database dropped
when we connect to dbserver
then we see database connected

View file

@ -8,15 +8,38 @@ Feature: manipulate tables:
then we see table created
when we insert into table
then we see record inserted
when we select from table
then we see data selected: initial
when we update table
then we see record updated
when we select from table
then we see data selected
then we see data selected: updated
when we delete from table
then we confirm the destructive warning
then we respond to the destructive warning: y
then we see record deleted
when we drop table
then we confirm the destructive warning
then we respond to the destructive warning: y
then we see table dropped
when we connect to dbserver
then we see database connected
Scenario: transaction handling, with cancelling on a destructive warning.
When we connect to test database
then we see database connected
when we create table
then we see table created
when we begin transaction
then we see transaction began
when we insert into table
then we see record inserted
when we delete from table
then we respond to the destructive warning: n
when we select from table
then we see data selected: initial
when we rollback transaction
then we see transaction rolled back
when we select from table
then we see select output without data
when we drop table
then we respond to the destructive warning: y
then we see table dropped

View file

@ -164,10 +164,24 @@ def before_step(context, _):
context.atprompt = False
def is_known_problem(scenario):
"""TODO: why is this not working in 3.12?"""
if sys.version_info >= (3, 12):
return scenario.name in (
'interrupt current query via "ctrl + c"',
"run the cli with --username",
"run the cli with --user",
"run the cli with --port",
)
return False
def before_scenario(context, scenario):
if scenario.name == "list databases":
# not using the cli for that
return
if is_known_problem(scenario):
scenario.skip()
currentdb = None
if "pgbouncer" in scenario.feature.tags:
if context.pgbouncer_available:

View file

@ -7,7 +7,7 @@ Feature: expanded mode:
and we select from table
then we see expanded data selected
when we drop table
then we confirm the destructive warning
then we respond to the destructive warning: y
then we see table dropped
Scenario: expanded off
@ -16,7 +16,7 @@ Feature: expanded mode:
and we select from table
then we see nonexpanded data selected
when we drop table
then we confirm the destructive warning
then we respond to the destructive warning: y
then we see table dropped
Scenario: expanded auto
@ -25,5 +25,5 @@ Feature: expanded mode:
and we select from table
then we see auto data selected
when we drop table
then we confirm the destructive warning
then we respond to the destructive warning: y
then we see table dropped

View file

@ -64,13 +64,83 @@ def step_ctrl_d(context):
"""
Send Ctrl + D to hopefully exit.
"""
step_try_to_ctrl_d(context)
context.cli.expect(pexpect.EOF, timeout=5)
context.exit_sent = True
@when('we try to send "ctrl + d"')
def step_try_to_ctrl_d(context):
"""
Send Ctrl + D, perhaps exiting, perhaps not (if a transaction is
ongoing).
"""
# turn off pager before exiting
context.cli.sendcontrol("c")
context.cli.sendline(r"\pset pager off")
wrappers.wait_prompt(context)
context.cli.sendcontrol("d")
context.cli.expect(pexpect.EOF, timeout=5)
context.exit_sent = True
@when('we send "ctrl + c"')
def step_ctrl_c(context):
"""Send Ctrl + c to hopefully interrupt."""
context.cli.sendcontrol("c")
@then("we see cancelled query warning")
def step_see_cancelled_query_warning(context):
"""
Make sure we receive the warning that the current query was cancelled.
"""
wrappers.expect_exact(context, "cancelled query", timeout=2)
@then("we see ongoing transaction message")
def step_see_ongoing_transaction_error(context):
"""
Make sure we receive the warning that a transaction is ongoing.
"""
context.cli.expect("A transaction is ongoing.", timeout=2)
@when("we send sleep query")
def step_send_sleep_15_seconds(context):
"""
Send query to sleep for 15 seconds.
"""
context.cli.sendline("select pg_sleep(15)")
@when("we check for any non-idle sleep queries")
def step_check_for_active_sleep_queries(context):
"""
Send query to check for any non-idle pg_sleep queries.
"""
context.cli.sendline(
"select state from pg_stat_activity where query not like '%pg_stat_activity%' and query like '%pg_sleep%' and state != 'idle';"
)
@then("we don't see any non-idle sleep queries")
def step_no_active_sleep_queries(context):
"""Confirm that any pg_sleep queries are either idle or not active."""
wrappers.expect_exact(
context,
context.conf["pager_boundary"]
+ "\r"
+ dedent(
"""
+-------+\r
| state |\r
|-------|\r
+-------+\r
SELECT 0\r
"""
)
+ context.conf["pager_boundary"],
timeout=5,
)
@when(r'we send "\?" command')
@ -131,18 +201,31 @@ def step_see_found(context):
)
@then("we confirm the destructive warning")
def step_confirm_destructive_command(context):
"""Confirm destructive command."""
@then("we respond to the destructive warning: {response}")
def step_resppond_to_destructive_command(context, response):
"""Respond to destructive command."""
wrappers.expect_exact(
context,
"You're about to run a destructive command.\r\nDo you want to proceed? (y/n):",
"You're about to run a destructive command.\r\nDo you want to proceed? [y/N]:",
timeout=2,
)
context.cli.sendline("y")
context.cli.sendline(response.strip())
@then("we send password")
def step_send_password(context):
wrappers.expect_exact(context, "Password for", timeout=5)
context.cli.sendline(context.conf["pass"] or "DOES NOT MATTER")
@when('we send "{text}"')
def step_send_text(context, text):
context.cli.sendline(text)
# Try to detect whether we are exiting. If so, set `exit_sent`
# so that `after_scenario` correctly cleans up.
try:
context.cli.expect(pexpect.EOF, timeout=0.2)
except pexpect.TIMEOUT:
pass
else:
context.exit_sent = True

View file

@ -9,6 +9,10 @@ from textwrap import dedent
import wrappers
INITIAL_DATA = "xxx"
UPDATED_DATA = "yyy"
@when("we create table")
def step_create_table(context):
"""
@ -22,7 +26,7 @@ def step_insert_into_table(context):
"""
Send insert into table.
"""
context.cli.sendline("""insert into a(x) values('xxx');""")
context.cli.sendline(f"""insert into a(x) values('{INITIAL_DATA}');""")
@when("we update table")
@ -30,7 +34,9 @@ def step_update_table(context):
"""
Send insert into table.
"""
context.cli.sendline("""update a set x = 'yyy' where x = 'xxx';""")
context.cli.sendline(
f"""update a set x = '{UPDATED_DATA}' where x = '{INITIAL_DATA}';"""
)
@when("we select from table")
@ -46,7 +52,7 @@ def step_delete_from_table(context):
"""
Send deete from table.
"""
context.cli.sendline("""delete from a where x = 'yyy';""")
context.cli.sendline(f"""delete from a where x = '{UPDATED_DATA}';""")
@when("we drop table")
@ -57,6 +63,30 @@ def step_drop_table(context):
context.cli.sendline("drop table a;")
@when("we alter the table")
def step_alter_table(context):
"""
Alter the table by adding a column.
"""
context.cli.sendline("""alter table a add column y varchar;""")
@when("we begin transaction")
def step_begin_transaction(context):
"""
Begin transaction
"""
context.cli.sendline("begin;")
@when("we rollback transaction")
def step_rollback_transaction(context):
"""
Rollback transaction
"""
context.cli.sendline("rollback;")
@then("we see table created")
def step_see_table_created(context):
"""
@ -81,21 +111,42 @@ def step_see_record_updated(context):
wrappers.expect_pager(context, "UPDATE 1\r\n", timeout=2)
@then("we see data selected")
def step_see_data_selected(context):
@then("we see data selected: {data}")
def step_see_data_selected(context, data):
"""
Wait to see select output.
Wait to see select output with initial or updated data.
"""
x = UPDATED_DATA if data == "updated" else INITIAL_DATA
wrappers.expect_pager(
context,
dedent(
f"""\
+-----+\r
| x |\r
|-----|\r
| {x} |\r
+-----+\r
SELECT 1\r
"""
),
timeout=1,
)
@then("we see select output without data")
def step_see_no_data_selected(context):
"""
Wait to see select output without data.
"""
wrappers.expect_pager(
context,
dedent(
"""\
+-----+\r
| x |\r
|-----|\r
| yyy |\r
+-----+\r
SELECT 1\r
+---+\r
| x |\r
|---|\r
+---+\r
SELECT 0\r
"""
),
timeout=1,
@ -116,3 +167,19 @@ def step_see_table_dropped(context):
Wait to see drop output.
"""
wrappers.expect_pager(context, "DROP TABLE\r\n", timeout=2)
@then("we see transaction began")
def step_see_transaction_began(context):
"""
Wait to see transaction began.
"""
wrappers.expect_pager(context, "BEGIN\r\n", timeout=2)
@then("we see transaction rolled back")
def step_see_transaction_rolled_back(context):
"""
Wait to see transaction rollback.
"""
wrappers.expect_pager(context, "ROLLBACK\r\n", timeout=2)

View file

@ -16,7 +16,7 @@ def step_prepare_data(context):
context.cli.sendline("drop table if exists a;")
wrappers.expect_exact(
context,
"You're about to run a destructive command.\r\nDo you want to proceed? (y/n):",
"You're about to run a destructive command.\r\nDo you want to proceed? [y/N]:",
timeout=2,
)
context.cli.sendline("y")

View file

@ -3,10 +3,7 @@ import pexpect
from pgcli.main import COLOR_CODE_REGEX
import textwrap
try:
from StringIO import StringIO
except ImportError:
from io import StringIO
from io import StringIO
def expect_exact(context, expected, timeout):