Adding upstream version 4.1.0.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
5f14fad9bf
commit
be6a09053d
14 changed files with 456 additions and 36 deletions
|
@ -9,6 +9,7 @@ from utils import (
|
|||
db_connection,
|
||||
drop_tables,
|
||||
)
|
||||
import pgcli.main
|
||||
import pgcli.pgexecute
|
||||
|
||||
|
||||
|
@ -37,6 +38,7 @@ def executor(connection):
|
|||
password=POSTGRES_PASSWORD,
|
||||
port=POSTGRES_PORT,
|
||||
dsn=None,
|
||||
notify_callback=pgcli.main.notify_callback,
|
||||
)
|
||||
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ Steps for behavioral style tests are defined in this module.
|
|||
Each step is defined by the string decorating it.
|
||||
This string is used to call the step in "*.feature" file.
|
||||
"""
|
||||
|
||||
import pexpect
|
||||
|
||||
from behave import when, then
|
||||
|
|
17
tests/test_application_name.py
Normal file
17
tests/test_application_name.py
Normal file
|
@ -0,0 +1,17 @@
|
|||
from unittest.mock import patch
|
||||
|
||||
from click.testing import CliRunner
|
||||
|
||||
from pgcli.main import cli
|
||||
from pgcli.pgexecute import PGExecute
|
||||
|
||||
|
||||
def test_application_name_in_env():
|
||||
runner = CliRunner()
|
||||
app_name = "wonderful_app"
|
||||
with patch.object(PGExecute, "__init__") as mock_pgxecute:
|
||||
runner.invoke(
|
||||
cli, ["127.0.0.1:5432/hello", "user"], env={"PGAPPNAME": app_name}
|
||||
)
|
||||
kwargs = mock_pgxecute.call_args.kwargs
|
||||
assert kwargs.get("application_name") == app_name
|
|
@ -1,5 +1,8 @@
|
|||
import os
|
||||
import platform
|
||||
import re
|
||||
import tempfile
|
||||
import datetime
|
||||
from unittest import mock
|
||||
|
||||
import pytest
|
||||
|
@ -11,7 +14,9 @@ except ImportError:
|
|||
|
||||
from pgcli.main import (
|
||||
obfuscate_process_password,
|
||||
duration_in_words,
|
||||
format_output,
|
||||
notify_callback,
|
||||
PGCli,
|
||||
OutputSettings,
|
||||
COLOR_CODE_REGEX,
|
||||
|
@ -296,6 +301,24 @@ def test_i_works(tmpdir, executor):
|
|||
run(executor, statement, pgspecial=cli.pgspecial)
|
||||
|
||||
|
||||
@dbtest
|
||||
def test_toggle_verbose_errors(executor):
|
||||
cli = PGCli(pgexecute=executor)
|
||||
|
||||
cli._evaluate_command("\\v on")
|
||||
assert cli.verbose_errors
|
||||
output, _ = cli._evaluate_command("SELECT 1/0")
|
||||
assert "SQLSTATE" in output[0]
|
||||
|
||||
cli._evaluate_command("\\v off")
|
||||
assert not cli.verbose_errors
|
||||
output, _ = cli._evaluate_command("SELECT 1/0")
|
||||
assert "SQLSTATE" not in output[0]
|
||||
|
||||
cli._evaluate_command("\\v")
|
||||
assert cli.verbose_errors
|
||||
|
||||
|
||||
@dbtest
|
||||
def test_echo_works(executor):
|
||||
cli = PGCli(pgexecute=executor)
|
||||
|
@ -312,6 +335,34 @@ def test_qecho_works(executor):
|
|||
assert result == ["asdf"]
|
||||
|
||||
|
||||
@dbtest
|
||||
def test_logfile_works(executor):
|
||||
with tempfile.TemporaryDirectory() as tmpdir:
|
||||
log_file = f"{tmpdir}/tempfile.log"
|
||||
cli = PGCli(pgexecute=executor, log_file=log_file)
|
||||
statement = r"\qecho hello!"
|
||||
cli.execute_command(statement)
|
||||
with open(log_file, "r") as f:
|
||||
log_contents = f.readlines()
|
||||
assert datetime.datetime.fromisoformat(log_contents[0].strip())
|
||||
assert log_contents[1].strip() == r"\qecho hello!"
|
||||
assert log_contents[2].strip() == "hello!"
|
||||
|
||||
|
||||
@dbtest
|
||||
def test_logfile_unwriteable_file(executor):
|
||||
cli = PGCli(pgexecute=executor)
|
||||
statement = r"\log-file forbidden.log"
|
||||
with mock.patch("builtins.open") as mock_open:
|
||||
mock_open.side_effect = PermissionError(
|
||||
"[Errno 13] Permission denied: 'forbidden.log'"
|
||||
)
|
||||
result = run(executor, statement, pgspecial=cli.pgspecial)
|
||||
assert result == [
|
||||
"[Errno 13] Permission denied: 'forbidden.log'\nLogfile capture disabled"
|
||||
]
|
||||
|
||||
|
||||
@dbtest
|
||||
def test_watch_works(executor):
|
||||
cli = PGCli(pgexecute=executor)
|
||||
|
@ -431,6 +482,7 @@ def test_pg_service_file(tmpdir):
|
|||
"b_host",
|
||||
"5435",
|
||||
"",
|
||||
notify_callback,
|
||||
application_name="pgcli",
|
||||
)
|
||||
del os.environ["PGPASSWORD"]
|
||||
|
@ -486,5 +538,50 @@ def test_application_name_db_uri(tmpdir):
|
|||
cli = PGCli(pgclirc_file=str(tmpdir.join("rcfile")))
|
||||
cli.connect_uri("postgres://bar@baz.com/?application_name=cow")
|
||||
mock_pgexecute.assert_called_with(
|
||||
"bar", "bar", "", "baz.com", "", "", application_name="cow"
|
||||
"bar", "bar", "", "baz.com", "", "", notify_callback, application_name="cow"
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"duration_in_seconds,words",
|
||||
[
|
||||
(0, "0 seconds"),
|
||||
(0.0009, "0.001 second"),
|
||||
(0.0005, "0.001 second"),
|
||||
(0.0004, "0.0 second"), # not perfect, but will do
|
||||
(0.2, "0.2 second"),
|
||||
(1, "1 second"),
|
||||
(1.4, "1 second"),
|
||||
(2, "2 seconds"),
|
||||
(3.4, "3 seconds"),
|
||||
(60, "1 minute"),
|
||||
(61, "1 minute 1 second"),
|
||||
(123, "2 minutes 3 seconds"),
|
||||
(3600, "1 hour"),
|
||||
(7235, "2 hours 35 seconds"),
|
||||
(9005, "2 hours 30 minutes 5 seconds"),
|
||||
(86401, "24 hours 1 second"),
|
||||
],
|
||||
)
|
||||
def test_duration_in_words(duration_in_seconds, words):
|
||||
assert duration_in_words(duration_in_seconds) == words
|
||||
|
||||
|
||||
@dbtest
|
||||
def test_notifications(executor):
|
||||
run(executor, "listen chan1")
|
||||
|
||||
with mock.patch("pgcli.main.click.secho") as mock_secho:
|
||||
run(executor, "notify chan1, 'testing1'")
|
||||
mock_secho.assert_called()
|
||||
arg = mock_secho.call_args_list[0].args[0]
|
||||
assert re.match(
|
||||
r'Notification received on channel "chan1" \(PID \d+\):\ntesting1',
|
||||
arg,
|
||||
)
|
||||
|
||||
run(executor, "unlisten chan1")
|
||||
|
||||
with mock.patch("pgcli.main.click.secho") as mock_secho:
|
||||
run(executor, "notify chan1, 'testing2'")
|
||||
mock_secho.assert_not_called()
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import re
|
||||
from textwrap import dedent
|
||||
|
||||
import psycopg
|
||||
|
@ -6,7 +7,7 @@ from unittest.mock import patch, MagicMock
|
|||
from pgspecial.main import PGSpecial, NO_QUERY
|
||||
from utils import run, dbtest, requires_json, requires_jsonb
|
||||
|
||||
from pgcli.main import PGCli
|
||||
from pgcli.main import PGCli, exception_formatter as main_exception_formatter
|
||||
from pgcli.packages.parseutils.meta import FunctionMetadata
|
||||
|
||||
|
||||
|
@ -219,8 +220,33 @@ def test_database_list(executor):
|
|||
|
||||
@dbtest
|
||||
def test_invalid_syntax(executor, exception_formatter):
|
||||
result = run(executor, "invalid syntax!", exception_formatter=exception_formatter)
|
||||
result = run(
|
||||
executor,
|
||||
"invalid syntax!",
|
||||
exception_formatter=lambda x: main_exception_formatter(x, verbose_errors=False),
|
||||
)
|
||||
assert 'syntax error at or near "invalid"' in result[0]
|
||||
assert "SQLSTATE" not in result[0]
|
||||
|
||||
|
||||
@dbtest
|
||||
def test_invalid_syntax_verbose(executor):
|
||||
result = run(
|
||||
executor,
|
||||
"invalid syntax!",
|
||||
exception_formatter=lambda x: main_exception_formatter(x, verbose_errors=True),
|
||||
)
|
||||
fields = r"""
|
||||
Severity: ERROR
|
||||
Severity \(non-localized\): ERROR
|
||||
SQLSTATE code: 42601
|
||||
Message: syntax error at or near "invalid"
|
||||
Position: 1
|
||||
File: scan\.l
|
||||
Line: \d+
|
||||
Routine: scanner_yyerror
|
||||
""".strip()
|
||||
assert re.search(fields, result[0])
|
||||
|
||||
|
||||
@dbtest
|
||||
|
@ -690,6 +716,38 @@ def test_function_definition(executor):
|
|||
result = executor.function_definition("the_number_three")
|
||||
|
||||
|
||||
@dbtest
|
||||
def test_function_notice_order(executor):
|
||||
run(
|
||||
executor,
|
||||
"""
|
||||
CREATE OR REPLACE FUNCTION demo_order() RETURNS VOID AS
|
||||
$$
|
||||
BEGIN
|
||||
RAISE NOTICE 'first';
|
||||
RAISE NOTICE 'second';
|
||||
RAISE NOTICE 'third';
|
||||
RAISE NOTICE 'fourth';
|
||||
RAISE NOTICE 'fifth';
|
||||
RAISE NOTICE 'sixth';
|
||||
END;
|
||||
$$
|
||||
LANGUAGE plpgsql;
|
||||
""",
|
||||
)
|
||||
|
||||
executor.function_definition("demo_order")
|
||||
|
||||
result = run(executor, "select demo_order()")
|
||||
assert "first\nsecond\nthird\nfourth\nfifth\nsixth" in result[0]
|
||||
assert "+------------+" in result[1]
|
||||
assert "| demo_order |" in result[2]
|
||||
assert "|------------|" in result[3]
|
||||
assert "| |" in result[4]
|
||||
assert "+------------+" in result[5]
|
||||
assert "SELECT 1" in result[6]
|
||||
|
||||
|
||||
@dbtest
|
||||
def test_view_definition(executor):
|
||||
run(executor, "create table tbl1 (a text, b numeric)")
|
||||
|
@ -721,6 +779,10 @@ def test_short_host(executor):
|
|||
executor, "host", "localhost1.example.org,localhost2.example.org"
|
||||
):
|
||||
assert executor.short_host == "localhost1"
|
||||
with patch.object(executor, "host", "ec2-11-222-333-444.compute-1.amazonaws.com"):
|
||||
assert executor.short_host == "ec2-11-222-333-444"
|
||||
with patch.object(executor, "host", "1.2.3.4"):
|
||||
assert executor.short_host == "1.2.3.4"
|
||||
|
||||
|
||||
class VirtualCursor:
|
||||
|
|
|
@ -6,7 +6,7 @@ from configobj import ConfigObj
|
|||
from click.testing import CliRunner
|
||||
from sshtunnel import SSHTunnelForwarder
|
||||
|
||||
from pgcli.main import cli, PGCli
|
||||
from pgcli.main import cli, notify_callback, PGCli
|
||||
from pgcli.pgexecute import PGExecute
|
||||
|
||||
|
||||
|
@ -61,6 +61,7 @@ def test_ssh_tunnel(
|
|||
"127.0.0.1",
|
||||
pgcli.ssh_tunnel.local_bind_ports[0],
|
||||
"",
|
||||
notify_callback,
|
||||
)
|
||||
mock_ssh_tunnel_forwarder.reset_mock()
|
||||
mock_pgexecute.reset_mock()
|
||||
|
@ -96,6 +97,7 @@ def test_ssh_tunnel(
|
|||
"127.0.0.1",
|
||||
pgcli.ssh_tunnel.local_bind_ports[0],
|
||||
"",
|
||||
notify_callback,
|
||||
)
|
||||
mock_ssh_tunnel_forwarder.reset_mock()
|
||||
mock_pgexecute.reset_mock()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue