Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move GHA e2e integration job to pytest #746

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .flake8
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,8 @@ pytest-parametrize-names-type = tuple
# PT007:
pytest-parametrize-values-type = tuple
pytest-parametrize-values-row-type = tuple
# PT023:
pytest-mark-no-parentheses = true

# flake8-rst-docstrings
rst-roles =
Expand Down
44 changes: 0 additions & 44 deletions .github/workflows/test-library.yml
Original file line number Diff line number Diff line change
Expand Up @@ -210,49 +210,6 @@ jobs:
|| steps.scm-version.outputs.dist-version
}}-py3-none-any.whl')
integration:
runs-on: ${{ matrix.os }}-latest
name: >-
e2e: 🐍${{ matrix.python }} @ ${{ matrix.os }}
needs:
- build
- pre-setup # transitive, for accessing settings
strategy:
matrix:
os: [Ubuntu, macOS]
python: ['3.6', '3.7', '3.8', '3.9', '3.10']
max-parallel: 4
fail-fast: false
steps:
- uses: actions/checkout@v2
with:
ref: ${{ github.event.inputs.release-commitish }}
- name: Make the env clean of non-test files
run: |
shopt -s extglob
mv -v tests/integration/main.sh integration-test.sh
rm -rf !integration-test.sh
shell: bash
- name: Setup Python
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python }}
- name: Download all the dists
uses: actions/download-artifact@v2
with:
name: python-package-distributions
path: dist/
- name: Integration testing
run: |
pip install 'dist/${{ needs.pre-setup.outputs.wheel-artifact-name }}'
proxy \
--hostname 127.0.0.1 \
--enable-web-server \
--pid-file proxy.pid \
--log-file proxy.log \
&
./integration-test.sh
build:
name: build dists ${{ needs.pre-setup.outputs.git-tag }}
needs:
Expand Down Expand Up @@ -577,7 +534,6 @@ jobs:

check: # This job does nothing and is only used for the branch protection
needs:
- integration
- lint
- test

Expand Down
7 changes: 7 additions & 0 deletions proxy/common/_compat.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
"""Compatibility code for using Proxy.py across various versions of Python."""

import platform


SYS_PLATFORM = platform.system()
IS_WINDOWS = SYS_PLATFORM == 'Windows'
5 changes: 2 additions & 3 deletions proxy/common/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,14 @@

from typing import Any, List

from ._compat import IS_WINDOWS # noqa: WPS436
from .version import __version__


def _env_threadless_compliant() -> bool:
"""Returns true for Python 3.8+ across all platforms
except Windows."""
if os.name == 'nt':
return False
return sys.version_info >= (3, 8)
return not IS_WINDOWS and sys.version_info >= (3, 8)


PROXY_PY_START_TIME = time.time()
Expand Down
3 changes: 2 additions & 1 deletion proxy/common/flag.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

from typing import Optional, List, Any, cast

from ._compat import IS_WINDOWS # noqa: WPS436
from .plugins import Plugins
from .types import IpAddress
from .utils import bytes_, is_py2, set_open_file_limit
Expand Down Expand Up @@ -255,7 +256,7 @@ def initialize(
)
# AF_UNIX is not available on Windows
# See https://bugs.python.org/issue33408
if os.name != 'nt':
if not IS_WINDOWS:
args.family = socket.AF_UNIX if args.unix_socket_path else (
socket.AF_INET6 if args.hostname.version == 6 else socket.AF_INET
)
Expand Down
26 changes: 14 additions & 12 deletions proxy/common/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
:copyright: (c) 2013-present by Abhinav Singh and contributors.
:license: BSD, see LICENSE for more details.
"""
import os
import sys
import ssl
import socket
Expand All @@ -20,9 +19,10 @@
from types import TracebackType
from typing import Optional, Dict, Any, List, Tuple, Type, Callable

from ._compat import IS_WINDOWS # noqa: WPS436
from .constants import HTTP_1_1, COLON, WHITESPACE, CRLF, DEFAULT_TIMEOUT, DEFAULT_THREADLESS

if os.name != 'nt':
if not IS_WINDOWS:
import resource

logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -272,14 +272,16 @@ def get_available_port() -> int:

def set_open_file_limit(soft_limit: int) -> None:
"""Configure open file description soft limit on supported OS."""
if os.name != 'nt': # resource module not available on Windows OS
curr_soft_limit, curr_hard_limit = resource.getrlimit(
resource.RLIMIT_NOFILE,
if IS_WINDOWS: # resource module not available on Windows OS
return

curr_soft_limit, curr_hard_limit = resource.getrlimit(
resource.RLIMIT_NOFILE,
)
if curr_soft_limit < soft_limit < curr_hard_limit:
resource.setrlimit(
resource.RLIMIT_NOFILE, (soft_limit, curr_hard_limit),
)
logger.debug(
'Open file soft limit set to %d', soft_limit,
)
if curr_soft_limit < soft_limit < curr_hard_limit:
resource.setrlimit(
resource.RLIMIT_NOFILE, (soft_limit, curr_hard_limit),
)
logger.debug(
'Open file soft limit set to %d', soft_limit,
)
1 change: 1 addition & 0 deletions pytest.ini
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ junit_suite_name = proxy_py_test_suite

# A mapping of markers to their descriptions allowed in strict mode:
markers =
smoke: Quick self-check smoke tests

minversion = 6.2.0

Expand Down
13 changes: 12 additions & 1 deletion tests/core/test_listener.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@

from unittest import mock

import pytest

from proxy.core.acceptor import Listener
from proxy.common._compat import IS_WINDOWS # noqa: WPS436
from proxy.common.flag import FlagParser


Expand Down Expand Up @@ -43,7 +46,15 @@ def test_setup_and_teardown(self, mock_socket: mock.Mock) -> None:
listener.shutdown()
sock.close.assert_called_once()

@unittest.skipIf(os.name == 'nt', 'AF_UNIX not available on windows')
# FIXME: Ignore is necessary for as long as pytest hasn't figured out
# FIXME: typing for their fixtures.
# Refs:
# * https://github.com/pytest-dev/pytest/issues/7469#issuecomment-918345196
# * https://github.com/pytest-dev/pytest/issues/3342
@pytest.mark.skipif(
IS_WINDOWS,
reason='AF_UNIX not available on Windows',
) # type: ignore[misc]
@mock.patch('os.remove')
@mock.patch('socket.socket')
def test_unix_path_listener(self, mock_socket: mock.Mock, mock_remove: mock.Mock) -> None:
Expand Down
52 changes: 52 additions & 0 deletions tests/integration/test_integration.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
"""Test the simplest proxy use scenario for smoke."""
from pathlib import Path
from subprocess import check_output, Popen
from typing import Generator

import pytest

from proxy.common._compat import IS_WINDOWS # noqa: WPS436


# FIXME: Ignore is necessary for as long as pytest hasn't figured out
# FIXME: typing for their fixtures.
# Refs:
# * https://github.com/pytest-dev/pytest/issues/7469#issuecomment-918345196
# * https://github.com/pytest-dev/pytest/issues/3342
@pytest.fixture # type: ignore[misc]
def _proxy_py_instance() -> Generator[None, None, None]:
"""Instantiate proxy.py in a subprocess for testing.
After the testing is over, tear it down.
"""
proxy_cmd = (
'proxy',
'--hostname', '127.0.0.1',
'--enable-web-server',
)
proxy_proc = Popen(proxy_cmd)
try:
yield
finally:
proxy_proc.terminate()
proxy_proc.wait(1)


# FIXME: Ignore is necessary for as long as pytest hasn't figured out
# FIXME: typing for their fixtures.
# Refs:
# * https://github.com/pytest-dev/pytest/issues/7469#issuecomment-918345196
# * https://github.com/pytest-dev/pytest/issues/3342
@pytest.mark.smoke # type: ignore[misc]
@pytest.mark.usefixtures('_proxy_py_instance') # type: ignore[misc]
@pytest.mark.xfail(
IS_WINDOWS,
reason='OSError: [WinError 193] %1 is not a valid Win32 application',
raises=OSError,
) # type: ignore[misc]
def test_curl() -> None:
"""An acceptance test with using ``curl`` through proxy.py."""
this_test_module = Path(__file__)
shell_script_test = this_test_module.with_suffix('.sh')

check_output(str(shell_script_test))
File renamed without changes.
11 changes: 8 additions & 3 deletions tests/test_set_open_file_limit.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,22 @@
:copyright: (c) 2013-present by Abhinav Singh and contributors.
:license: BSD, see LICENSE for more details.
"""
import os
import unittest
from unittest import mock

import pytest

from proxy.common._compat import IS_WINDOWS # noqa: WPS436
from proxy.common.utils import set_open_file_limit

if os.name != 'nt':
if not IS_WINDOWS:
import resource


@unittest.skipIf(os.name == 'nt', 'Open file limit tests disabled for Windows')
@pytest.mark.skipif(
IS_WINDOWS,
reason='Open file limit tests disabled for Windows',
)
class TestSetOpenFileLimit(unittest.TestCase):

@mock.patch('resource.getrlimit', return_value=(128, 1024))
Expand Down
10 changes: 7 additions & 3 deletions tests/testing/test_embed.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,24 @@
:copyright: (c) 2013-present by Abhinav Singh and contributors.
:license: BSD, see LICENSE for more details.
"""
import os
import unittest
import http.client
import urllib.request
import urllib.error

import pytest

from proxy import TestCase
from proxy.common._compat import IS_WINDOWS # noqa: WPS436
from proxy.common.constants import DEFAULT_CLIENT_RECVBUF_SIZE, PROXY_AGENT_HEADER_VALUE
from proxy.common.utils import socket_connection, build_http_request
from proxy.http import httpMethods
from proxy.http.server import HttpWebServerPlugin


@unittest.skipIf(os.name == 'nt', 'Disabled for Windows due to weird permission issues.')
@pytest.mark.skipif(
IS_WINDOWS,
reason='Disabled for Windows due to weird permission issues.',
)
class TestProxyPyEmbedded(TestCase):
"""This test case is a demonstration of proxy.TestCase and also serves as
integration test suite for proxy.py."""
Expand Down