Skip to content

Commit

Permalink
add tests
Browse files Browse the repository at this point in the history
Signed-off-by: Jericho Tolentino <[email protected]>
  • Loading branch information
jericht committed May 2, 2024
1 parent 0f651bd commit eb4bea9
Show file tree
Hide file tree
Showing 5 changed files with 284 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,61 @@ def test_heartbeat_acks(
# THEN
assert f"Received ACK for chunk: {response.output.id}" in new_response.output.output

@pytest.mark.skipif(not OSName.is_posix(), reason="Posix-specific test")
def test_init_uses_working_dir(
self,
tmp_path: pathlib.Path,
caplog: pytest.LogCaptureFixture,
) -> None:
backend_proc = None
conn_settings = None
try:
# GIVEN
caplog.set_level(0)
working_dir = tmp_path / "working_dir"
working_dir.mkdir()
frontend = FrontendRunner(working_dir=str(working_dir), timeout_s=5.0)

# WHEN
frontend.init(sys.modules[AdaptorExample.__module__])

# THEN

# Connection file should be in the working dir
connection_file = working_dir / "connection.json"
conn_settings = _load_connection_settings(str(connection_file))

# Backend process started successfully
match = re.search("Started backend process. PID: ([0-9]+)", caplog.text)
assert match is not None
pid = int(match.group(1))
backend_proc = psutil.Process(pid)

# Unix socket matches connection file and is also in the working dir
assert any(
[
conn.laddr == conn_settings.socket
for conn in backend_proc.connections(kind="unix")
]
)
assert conn_settings.socket.startswith(str(working_dir))

finally:
if backend_proc:
try:
backend_proc.kill()
except psutil.NoSuchProcess:
pass # Already stopped

# We don't need to call the `remove` for the NamedPipe server.
# NamedPipe servers are managed by Named Pipe File System it is not a regular file.
# Once all handles are closed, the system automatically cleans up the named pipe.
if OSName.is_posix() and conn_settings:
try:
os.remove(conn_settings.socket)
except FileNotFoundError:
pass # Already deleted

class TestAuthentication:
"""
Tests for background mode authentication.
Expand Down
53 changes: 53 additions & 0 deletions test/openjd/adaptor_runtime/unit/background/test_backend_runner.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
from __future__ import annotations

import json
import os
Expand Down Expand Up @@ -201,3 +202,55 @@ def test_signal_hook(self, mock_submit, signal_mock: MagicMock) -> None:
else:
signal_mock.assert_any_call(signal.SIGBREAK, runner._sigint_handler) # type: ignore[attr-defined]
mock_submit.assert_called_with(server_mock, adaptor_runner._cancel, force_immediate=True)

class ConnectionFileCompat:
@pytest.mark.parametrize(
argnames=["connection_file", "working_dir"],
argvalues=[
["path", "dir"],
[None, None],
],
ids=["both provided", "neither provided"],
)
def test_rejects_not_exactly_one_of_connection_file_and_working_dir(
self,
connection_file: str | None,
working_dir: str | None,
) -> None:
# GIVEN
with pytest.raises(RuntimeError) as raised_err:
# WHEN
BackendRunner(
Mock(),
connection_file_path=connection_file,
working_dir=working_dir,
)

# THEN
assert (
f"Exactly one of 'connection_file_path' or 'working_dir' must be provided, but got: connection_file_path={connection_file} working_dir={working_dir}"
== str(raised_err.value)
)

@pytest.mark.skipif(not OSName.is_posix(), reason="Posix-specific test")
@pytest.mark.parametrize(
argnames=["working_dir"], argvalues=[["dir"], [None]], ids=["provided", "not provided"]
)
def test_run_uses_working_dir_for_socket_path(self, working_dir: str | None) -> None:
# GIVEN
runner = BackendRunner(Mock(), working_dir=working_dir)

with patch.object(
backend_runner.SocketPaths,
"get_process_socket_path",
wraps=backend_runner.SocketPaths.get_process_socket_path,
) as mock_get_process_socket_path:
# WHEN
runner.run()

# THEN
mock_get_process_socket_path.assert_called_once_with(
"runtime",
base_dir=working_dir,
create_dir=True,
)
112 changes: 112 additions & 0 deletions test/openjd/adaptor_runtime/unit/background/test_frontend_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -821,6 +821,118 @@ def test_hook(self, signal_mock: MagicMock, cancel_mock: MagicMock) -> None:
signal_mock.assert_any_call(signal.SIGBREAK, runner._sigint_handler) # type: ignore[attr-defined]
cancel_mock.assert_called_once()

class TestConnectionFileCompat:
@pytest.mark.parametrize(
argnames=["connection_file", "working_dir"],
argvalues=[
["path", "dir"],
[None, None],
],
ids=["both provided", "neither provided"],
)
def test_rejects_not_exactly_one_of_connection_file_and_working_dir(
self,
connection_file: str | None,
working_dir: str | None,
) -> None:
# GIVEN
with pytest.raises(RuntimeError) as raised_err:
# WHEN
FrontendRunner(
connection_file_path=connection_file,
working_dir=working_dir,
)

# THEN
assert (
f"Expected exactly one of 'connection_file_path' or 'working_dir', but got: connection_file_path={connection_file} working_dir={working_dir}"
== str(raised_err.value)
)

@patch.object(frontend_runner, "_wait_for_file")
@patch.object(frontend_runner.os.path, "exists", return_value=False)
@patch.object(frontend_runner.subprocess, "Popen")
def test_init_provides_connection_file_arg(
self,
mock_popen: MagicMock,
mock_exists: MagicMock,
mock_wait_for_file: MagicMock,
) -> None:
# GIVEN
connection_file = os.path.join(os.sep, "path", "to", "connection.json")
runner = FrontendRunner(connection_file_path=connection_file)
adaptor_module = ModuleType("")
adaptor_module.__package__ = "package"

with patch.object(runner, "_heartbeat"):
# WHEN
runner.init(adaptor_module)

# THEN
mock_popen.assert_called_once_with(
[
sys.executable,
"-m",
adaptor_module.__package__,
"daemon",
"_serve",
"--init-data",
json.dumps({}),
"--path-mapping-rules",
json.dumps({}),
"--connection-file",
connection_file,
],
shell=False,
close_fds=True,
start_new_session=True,
stdin=subprocess.DEVNULL,
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
)

@patch.object(frontend_runner, "_wait_for_file")
@patch.object(frontend_runner.os.path, "exists", return_value=False)
@patch.object(frontend_runner.subprocess, "Popen")
def test_init_provides_working_dir_arg(
self,
mock_popen: MagicMock,
mock_exists: MagicMock,
mock_wait_for_file: MagicMock,
) -> None:
# GIVEN
working_dir = os.path.join(os.sep, "path", "to", "working")
runner = FrontendRunner(working_dir=working_dir)
adaptor_module = ModuleType("")
adaptor_module.__package__ = "package"

with patch.object(runner, "_heartbeat"):
# WHEN
runner.init(adaptor_module)

# THEN
mock_popen.assert_called_once_with(
[
sys.executable,
"-m",
adaptor_module.__package__,
"daemon",
"_serve",
"--init-data",
json.dumps({}),
"--path-mapping-rules",
json.dumps({}),
"--working-dir",
working_dir,
],
shell=False,
close_fds=True,
start_new_session=True,
stdin=subprocess.DEVNULL,
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
)


class TestLoadConnectionSettings:
"""
Expand Down
21 changes: 17 additions & 4 deletions test/openjd/adaptor_runtime/unit/http/test_sockets.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,17 @@ def test_create_dir(self, mock_makedirs: MagicMock, create: bool) -> None:
else:
mock_makedirs.assert_not_called()

def test_uses_base_dir(self) -> None:
# GIVEN
subject = SocketPathsStub()
base_dir = os.path.join(os.sep, "base", "dir")

# WHEN
result = subject.get_socket_path("sock", base_dir=base_dir)

# THEN
assert result.startswith(base_dir)

def test_uses_namespace(self) -> None:
# GIVEN
namespace = "my-namespace"
Expand Down Expand Up @@ -240,10 +251,11 @@ class TestLinuxSocketPaths:
argvalues=[
["a"],
["a" * 107],
["/this/part/should/not/matter/" + "a" * 107],
],
ids=["one byte", "107 bytes"],
ids=["one byte", "107 bytes", "path with name of 107 bytes"],
)
def test_accepts_paths_within_107_bytes(self, path: str):
def test_accepts_names_within_107_bytes(self, path: str):
"""
Verifies the function accepts paths up to 100 bytes (108 byte max - 1 byte null terminator)
"""
Expand All @@ -259,7 +271,7 @@ def test_accepts_paths_within_107_bytes(self, path: str):
# THEN
pass # success

def test_rejects_paths_over_107_bytes(self):
def test_rejects_names_over_107_bytes(self):
# GIVEN
length = 108
path = "a" * length
Expand All @@ -283,8 +295,9 @@ class TestMacOSSocketPaths:
argvalues=[
["a"],
["a" * 103],
["/this/part/should/not/matter/" + "a" * 103],
],
ids=["one byte", "103 bytes"],
ids=["one byte", "103 bytes", "path with name of 103 bytes"],
)
def test_accepts_paths_within_103_bytes(self, path: str):
"""
Expand Down
47 changes: 47 additions & 0 deletions test/openjd/adaptor_runtime/unit/test_entrypoint.py
Original file line number Diff line number Diff line change
Expand Up @@ -742,6 +742,53 @@ def test_makes_connection_file_path_absolute(
connection_file_path=mock_abspath.return_value, working_dir=None
)

class TestConnectionFileCompat:
@pytest.mark.parametrize(
argnames=["connection_file", "working_dir"],
argvalues=[
["path", "dir"],
[None, None],
],
ids=["both provided", "neither provided"],
)
def test_rejects_not_exactly_one_of_connection_file_and_working_dir(
self,
connection_file: str | None,
working_dir: str | None,
) -> None:
# GIVEN
entrypoint = EntryPoint(FakeAdaptor)
args = [
"Adaptor",
"daemon",
"run",
]
if connection_file:
args.extend(
[
"--connection-file",
connection_file,
]
)
if working_dir:
args.extend(
[
"--working-dir",
working_dir,
]
)

with patch.object(runtime_entrypoint.sys, "argv", args):
with pytest.raises(RuntimeError) as raised_err:
# WHEN
entrypoint.start()

# THEN
assert (
"Expected exactly one of 'connection_file' or 'working_dir' to be provided, but got args: "
in str(raised_err.value)
)


class TestLoadData:
"""
Expand Down

0 comments on commit eb4bea9

Please sign in to comment.