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

test(decrypt): add integration tests #26

Merged
merged 35 commits into from
Aug 8, 2024
Merged
Show file tree
Hide file tree
Changes from 26 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
1db6f05
test: integration tests outline
athith-g Aug 5, 2024
87999ac
refactor: move INPUT_TEXT to utils
athith-g Aug 5, 2024
eb633d3
refactor: use utils INPUT_TEXT
athith-g Aug 5, 2024
b4c0791
refactor: move INPUT_DIR to utils
athith-g Aug 5, 2024
224de36
test: test decryption of files
athith-g Aug 5, 2024
f416a35
fix: add decrypt.py to cli args
athith-g Aug 5, 2024
d7c572d
fix: use context manager
athith-g Aug 5, 2024
329317d
refactor: move encrypted_files fixture to conftest
athith-g Aug 5, 2024
113c70a
test: complete test_decryption
athith-g Aug 5, 2024
b1ce14f
test: add default dir and no args tests
athith-g Aug 5, 2024
e036aed
test: add no sk provided test
athith-g Aug 5, 2024
e87610b
test: add no valid sk test
athith-g Aug 5, 2024
223fc76
refactor: change error message
athith-g Aug 5, 2024
9ba3758
test: add invalid dir and removal tests
athith-g Aug 6, 2024
3632212
refactor: simply repetitive code
athith-g Aug 6, 2024
fc47c7b
refactor: move function below fixtures:
athith-g Aug 6, 2024
3f44f35
feat: add input file encrypted by bob.sec
athith-g Aug 6, 2024
44ea858
test: add test with file encrypted by bob
athith-g Aug 6, 2024
73e9d19
docs: update docstring for encrypted files
athith-g Aug 6, 2024
e75b18f
docs: update docstrings
athith-g Aug 6, 2024
a76bb4a
docs: more doc updates
athith-g Aug 6, 2024
ca4a79b
refactor: minor changes
athith-g Aug 6, 2024
51b9524
revert: undo import of INPUT_TEST in test_tasks.py
athith-g Aug 6, 2024
4d2b524
revert: undo import of INPUT_TEXT and INPUT_DIR from test_decrypt.py
athith-g Aug 6, 2024
6167df5
revert: undo removal of local encrypted_files fixture
athith-g Aug 6, 2024
dd967e9
refactor: remove whitespace
athith-g Aug 6, 2024
30715d8
refactor: rename test to remove ambiguity
athith-g Aug 6, 2024
3e5fddd
test: make test_no_args more robust
athith-g Aug 6, 2024
34c9ccb
test: add test for directory with bad permissions
athith-g Aug 6, 2024
1a4a235
test: add test for no tmpdir env variable
athith-g Aug 6, 2024
ff76582
revert: remove logging and parentheses
athith-g Aug 6, 2024
8730e7c
refactor: use logging instead of print
athith-g Aug 7, 2024
b6591e7
refactor: test logger output
athith-g Aug 7, 2024
964d8b7
Merge branch 'main' into decrypt_integration
athith-g Aug 7, 2024
c5a4c29
refactor: use critical logging level
athith-g Aug 7, 2024
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: 1 addition & 1 deletion crypt4gh_middleware/decrypt.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ def decrypt_files(file_paths: list[Path], private_keys: list[bytes]):
logger.info(f"Decrypted {file_path} successfully")
except ValueError as e:
if str(e) != "Not a CRYPT4GH formatted file":
print(f"Private key for {file_path} not provided")
print(f"Private key for {file_path.name} not provided")
athith-g marked this conversation as resolved.
Show resolved Hide resolved
continue


Expand Down
Binary file added inputs/hello3.c4gh
Binary file not shown.
19 changes: 19 additions & 0 deletions tests/conftest.py
uniqueg marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
"""Shared fixtures for tests."""

import shutil

import pytest

from tests.utils import INPUT_DIR
athith-g marked this conversation as resolved.
Show resolved Hide resolved


@pytest.fixture(name="encrypted_files")
def fixture_encrypted_files(tmp_path):
"""Returns temporary copies of encrypted files.
First two files are encrypted with alice.pk. Third file is encrypted with bob.pk.
"""
encrypted_files = [INPUT_DIR/"hello.c4gh", INPUT_DIR/"hello2.c4gh", INPUT_DIR/"hello3.c4gh"]
temp_files = [tmp_path/f.name for f in encrypted_files]
for src, dest in zip(encrypted_files, temp_files):
shutil.copy(src, dest)
return temp_files
94 changes: 94 additions & 0 deletions tests/decryption/test_integration.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
"""Integration tests for decrypt.py."""

import os
import shutil
from unittest import mock

import pytest

from crypt4gh_middleware.decrypt import main
from tests.utils import INPUT_DIR, INPUT_TEXT, patch_cli
athith-g marked this conversation as resolved.
Show resolved Hide resolved


@pytest.fixture(name="secret_keys")
def fixture_secret_keys(tmp_path):
"""Returns temporary copies of secret keys."""
encrypted_files = [INPUT_DIR/"alice.sec", INPUT_DIR/"bob.sec"]
temp_files = [tmp_path/"alice.sec", tmp_path/"bob.sec"]
for src, dest in zip(encrypted_files, temp_files):
shutil.copy(src, dest)
return temp_files


@pytest.fixture(name="string_paths")
def fixture_string_paths(encrypted_files, secret_keys):
"""Returns string version of file paths for use in patch_cli."""
return [str(f) for f in (encrypted_files + secret_keys)]


def files_decrypted_successfully(encrypted_files, tmp_path):
"""Check if encrypted files have been decrypted."""
for filename in encrypted_files:
with open(tmp_path/filename, encoding="utf-8") as f:
if f.read() != INPUT_TEXT:
return False
return True


def test_decryption(encrypted_files, string_paths, tmp_path):
"""Test that files are decrypted successfully."""
with patch_cli(["decrypt.py", "--output-dir", str(tmp_path)] + string_paths):
main()
assert files_decrypted_successfully(encrypted_files, tmp_path)


def test_default_dir(encrypted_files, string_paths, tmp_path):
athith-g marked this conversation as resolved.
Show resolved Hide resolved
"""Test that $TMPDIR is used when no output dir is provided."""
with (patch_cli(["decrypt.py"] + string_paths),
mock.patch.dict(os.environ, {"TMPDIR": str(tmp_path)})):
main()
assert files_decrypted_successfully(encrypted_files, tmp_path)


def test_no_args():
athith-g marked this conversation as resolved.
Show resolved Hide resolved
"""Test that an exception is thrown when no arguments are provided."""
with patch_cli(["decrypt.py"]), pytest.raises(SystemExit):
main()


@pytest.mark.parametrize("keys", [[], "secret_keys"])
def test_no_valid_sk_provided(encrypted_files, capsys, keys, request):
athith-g marked this conversation as resolved.
Show resolved Hide resolved
"""Test that error messages are printed when no keys or invalid secret keys are provided."""
# Fixture names passed to pytest.mark.parametrize are strings, so get value
if isinstance(keys, str):
# bob.pk was not used to encrypt hello.c4gh and hello2.c4gh
keys = [request.getfixturevalue(keys)[1]]
athith-g marked this conversation as resolved.
Show resolved Hide resolved

with patch_cli(["decrypt.py"] + [str(f) for f in (encrypted_files[:2] + keys)]):
main()
captured = capsys.readouterr()
assert captured.out == (f"Private key for {encrypted_files[0].name} not provided\n"
f"Private key for {encrypted_files[1].name} not provided\n")


def test_one_sk_provided(encrypted_files, capsys, secret_keys):
"""Test that appropriate error message is printed when only one valid secret key is provided."""
with patch_cli(["decrypt.py"] + [str(f) for f in (encrypted_files + [secret_keys[0]])]):
main()
captured = capsys.readouterr()
assert captured.out == f"Private key for {encrypted_files[2].name} not provided\n"


def test_invalid_output_dir(string_paths):
athith-g marked this conversation as resolved.
Show resolved Hide resolved
"""Test that an exception occurs when an invalid output directory is provided."""
with (patch_cli(["decrypt.py", "--output-dir", "bad_dir"] + string_paths),
pytest.raises(FileNotFoundError)):
main()


def test_files_removed(string_paths, tmp_path):
athith-g marked this conversation as resolved.
Show resolved Hide resolved
"""Test that no files are in the output directory when an exception occurs."""
with (patch_cli(["decrypt.py", "--output-dir", str(tmp_path)] + string_paths + ["bad_file"]),
pytest.raises(FileNotFoundError)):
main()
assert not any(file.exists() for file in tmp_path.iterdir())
4 changes: 4 additions & 0 deletions tests/utils.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
""" Utility functions for tests."""
from functools import wraps
import contextlib
from pathlib import Path
import signal
from unittest import mock

INPUT_DIR = Path(__file__).parents[1]/"inputs"
INPUT_TEXT = "hello world from the input!"


@contextlib.contextmanager
def patch_cli(args):
Expand Down