mirror of
https://github.com/httpie/cli.git
synced 2025-03-13 14:28:50 +01:00
135 lines
3.8 KiB
Python
135 lines
3.8 KiB
Python
import argparse
|
|
|
|
import pytest
|
|
|
|
from httpie.cli.ports import (
|
|
MAX_PORT,
|
|
MIN_PORT,
|
|
OUTSIDE_VALID_PORT_RANGE_ERROR,
|
|
local_port_arg_type,
|
|
parse_local_port_arg,
|
|
)
|
|
from httpie.compat import has_ipv6_support
|
|
from .utils import HTTP_OK, http
|
|
|
|
|
|
def test_non_existent_interface_arg(httpbin):
|
|
"""We ensure that HTTPie properly wire interface by passing an interface that does not exist. thus, we expect an error."""
|
|
r = http(
|
|
'--interface=1.1.1.1',
|
|
httpbin + '/get',
|
|
tolerate_error_exit_status=True
|
|
)
|
|
assert r.exit_status != 0
|
|
assert (
|
|
'assign requested address' in r.stderr
|
|
or 'The requested address is not valid in its context' in r.stderr
|
|
)
|
|
|
|
|
|
@pytest.mark.parametrize(['local_port_arg', 'expected_output'], [
|
|
# Single ports — valid
|
|
('0', 0),
|
|
('-0', 0),
|
|
(str(MAX_PORT), MAX_PORT),
|
|
('8000', 8000),
|
|
# Single ports — invalid
|
|
(f'{MIN_PORT - 1}', OUTSIDE_VALID_PORT_RANGE_ERROR),
|
|
(f'{MAX_PORT + 1}', OUTSIDE_VALID_PORT_RANGE_ERROR),
|
|
('-', 'not a number'),
|
|
('AAA', 'not a number'),
|
|
(' ', 'not a number'),
|
|
# Port ranges — valid
|
|
(f'{MIN_PORT}-{MAX_PORT}', (MIN_PORT, MAX_PORT)),
|
|
('3000-8000', (3000, 8000)),
|
|
('-0-8000', (0, 8000)),
|
|
('0-0', (0, 0)),
|
|
# Port ranges — invalid
|
|
(f'2-1', 'not a valid port range'),
|
|
(f'2-', 'not a number'),
|
|
(f'2-A', 'not a number'),
|
|
(f'A-A', 'not a number'),
|
|
(f'A-2', 'not a number'),
|
|
(f'-10-1', OUTSIDE_VALID_PORT_RANGE_ERROR),
|
|
(f'1--1', OUTSIDE_VALID_PORT_RANGE_ERROR),
|
|
(f'-10--1', OUTSIDE_VALID_PORT_RANGE_ERROR),
|
|
(f'1-{MAX_PORT + 1}', OUTSIDE_VALID_PORT_RANGE_ERROR),
|
|
])
|
|
def test_parse_local_port_arg(local_port_arg, expected_output):
|
|
expected_error = expected_output if isinstance(expected_output, str) else None
|
|
if not expected_error:
|
|
assert parse_local_port_arg(local_port_arg) == expected_output
|
|
else:
|
|
with pytest.raises(argparse.ArgumentTypeError, match=expected_error):
|
|
parse_local_port_arg(local_port_arg)
|
|
|
|
|
|
def test_local_port_arg_type():
|
|
assert local_port_arg_type('1') == 1
|
|
assert local_port_arg_type('1-1') == 1
|
|
assert local_port_arg_type('1-3') in {1, 2, 3}
|
|
|
|
|
|
def test_invoke_with_out_of_range_local_port_arg(httpbin):
|
|
# An addition to the unittest tests
|
|
r = http(
|
|
'--local-port=70000',
|
|
httpbin + '/get',
|
|
tolerate_error_exit_status=True
|
|
)
|
|
assert r.exit_status != 0
|
|
assert OUTSIDE_VALID_PORT_RANGE_ERROR in r.stderr
|
|
|
|
|
|
@pytest.mark.parametrize('interface_arg', [
|
|
'',
|
|
'-',
|
|
'10.25.a.u',
|
|
'abc',
|
|
'localhost',
|
|
])
|
|
def test_invalid_interface_arg(httpbin, interface_arg):
|
|
r = http(
|
|
'--interface',
|
|
interface_arg,
|
|
httpbin + '/get',
|
|
tolerate_error_exit_status=True,
|
|
)
|
|
assert f"'{interface_arg}' does not appear to be an IPv4 or IPv6" in r.stderr
|
|
|
|
|
|
def test_force_ipv6_on_unsupported_system(remote_httpbin):
|
|
orig = has_ipv6_support()
|
|
has_ipv6_support(False)
|
|
try:
|
|
r = http(
|
|
'-6',
|
|
remote_httpbin + '/get',
|
|
tolerate_error_exit_status=True,
|
|
)
|
|
finally:
|
|
has_ipv6_support(orig)
|
|
assert 'Unable to force IPv6 because your system lack IPv6 support.' in r.stderr
|
|
|
|
|
|
def test_force_both_ipv6_and_ipv4(remote_httpbin):
|
|
r = http(
|
|
'-6', # force IPv6
|
|
'-4', # force IPv4
|
|
remote_httpbin + '/get',
|
|
tolerate_error_exit_status=True,
|
|
)
|
|
|
|
assert 'Unable to force both IPv4 and IPv6, omit the flags to allow both.' in r.stderr
|
|
|
|
|
|
def test_happy_eyeballs(remote_httpbin_secure):
|
|
r = http(
|
|
'--heb', # this will automatically and concurrently try IPv6 and IPv4 endpoints
|
|
'--verify=no',
|
|
remote_httpbin_secure + '/get',
|
|
)
|
|
|
|
assert r.exit_status == 0
|
|
assert HTTP_OK in r
|