Skip to content

Commit

Permalink
Merge pull request #173 from dcermak/bind_ip_tests
Browse files Browse the repository at this point in the history
Bind to IP tests
  • Loading branch information
dcermak authored Nov 28, 2023
2 parents cbb13a6 + bc78a49 commit 71ad8e2
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 11 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ Breaking changes:
:py:func:`~pytest_container.container.container_and_marks_from_pytest_param`
instead.

- :py:func:`~pytest_container.container.ContainerBaseABC.get_base` no longer
returns the recursive base but the immediate base.


Improvements and new features:

Expand Down
13 changes: 5 additions & 8 deletions pytest_container/container.py
Original file line number Diff line number Diff line change
Expand Up @@ -617,7 +617,7 @@ def prepare_container(
"""Prepares the container so that it can be launched."""

@abstractmethod
def get_base(self) -> "Container":
def get_base(self) -> "Union[Container, DerivedContainer]":
"""Returns the Base of this Container Image. If the container has no
base, then ``self`` is returned.
Expand Down Expand Up @@ -703,15 +703,11 @@ def __str__(self) -> str:
or f"container derived from {self.base.__str__()}"
)

def get_base(self) -> Container:
"""Return the recursive base of this derived container (i.e. if the base
if this container is a derived one, then it takes the base of the
base).
"""
def get_base(self) -> Union[Container, "DerivedContainer"]:
"""Return the base of this derived container."""
if isinstance(self.base, str):
return Container(url=self.base)
return self.base.get_base()
return self.base

def prepare_container(
self, rootdir: Path, extra_build_args: Optional[List[str]] = None
Expand All @@ -732,6 +728,7 @@ def prepare_container(
# tags are added
if not self.containerfile and not self.add_build_tags:
base = self.get_base()
base.prepare_container(rootdir, extra_build_args)
self.container_id, self.url = base.container_id, base.url
return

Expand Down
16 changes: 13 additions & 3 deletions tests/test_container_build.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# pylint: disable=missing-function-docstring,missing-module-docstring
from pathlib import Path
from typing import Union

import pytest
from pytest import Config
Expand Down Expand Up @@ -161,9 +162,18 @@ def test_leap_with_man_and_lua(container: ContainerData):
assert container.connection.exists("lua")


def test_container_objects() -> None:
for cont in CONTAINER_IMAGES:
assert cont.get_base() == LEAP
@pytest.mark.parametrize(
"cont,base",
[
(c, base)
for c, base in zip(CONTAINER_IMAGES, [LEAP, LEAP, LEAP_WITH_MAN])
],
)
def test_container_objects(
cont: Union[Container, DerivedContainer],
base: Union[Container, DerivedContainer],
) -> None:
assert cont.get_base() == base


def test_auto_container_fixture(auto_container: ContainerData):
Expand Down
73 changes: 73 additions & 0 deletions tests/test_port_forwarding.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
"""Module containing tests of the automated port exposure via
:py:attr:`~pytest_container.container.ContainerBase.forwarded_ports`."""
# pylint: disable=missing-function-docstring
import itertools
import socket
from typing import List

import pytest
Expand Down Expand Up @@ -172,3 +174,74 @@ def test_multiple_open_ports(container: ContainerData, number: int, host):
f"curl --insecure https://localhost:{container.forwarded_ports[1].host_port}",
).stdout
)


_INTERFACES = [
name
for name in LOCALHOST.interface.names()
if name[:2] in ("en", "et", "wl")
]
_ADDRESES = [
addr
for addr in itertools.chain.from_iterable(
LOCALHOST.interface(interface).addresses for interface in _INTERFACES
)
if not addr.startswith("169.254.") and not addr.startswith("fe80:")
]


@pytest.mark.parametrize(
"addr,container",
zip(
_ADDRESES,
[
DerivedContainer(
base=WEB_SERVER,
forwarded_ports=[
PortForwarding(container_port=8000, bind_ip=addr)
],
)
for addr in _ADDRESES
],
),
indirect=["container"],
)
def test_bind_to_address(addr: str, container: ContainerData, host) -> None:
"""address"""
for host_addr in _ADDRESES:
cmd = f"{_CURL} http://{host_addr}:{container.forwarded_ports[0].host_port}"
if addr == host_addr:
assert (
host.run_expect([0], cmd).stdout.strip()
== "Hello Green World!"
)
else:
assert host.run_expect([7], cmd)


_sock = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)
_sock.bind(("", 0))
_PORT = _sock.getsockname()[1]
_sock.close()


@pytest.mark.parametrize(
"container",
(
DerivedContainer(
base=WEB_SERVER,
forwarded_ports=[
PortForwarding(container_port=8000, host_port=_PORT)
],
),
),
indirect=True,
)
def test_bind_to_host_port(container: ContainerData, host) -> None:
assert container.forwarded_ports[0].host_port == _PORT
assert (
host.run_expect(
[0], f"{_CURL} http://localhost:{_PORT}"
).stdout.strip()
== "Hello Green World!"
)

0 comments on commit 71ad8e2

Please sign in to comment.