Skip to content

Commit

Permalink
test: add more tests to improve cover (#5)
Browse files Browse the repository at this point in the history
  • Loading branch information
TheCrab13 authored Nov 9, 2023
1 parent 70908ee commit 64347a3
Show file tree
Hide file tree
Showing 13 changed files with 494 additions and 20 deletions.
7 changes: 0 additions & 7 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -64,13 +64,6 @@ jobs:
run: pip install tox
- name: Run tests
run: tox -e ${{ matrix.toxenv }} -- --override-ini='log_cli=True'
- name: Upload codecov coverage
uses: codecov/codecov-action@v3.1.4
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: ./coverage.xml
flags: ${{ matrix.toxenv }}
fail_ci_if_error: false

coverage:
runs-on: ubuntu-22.04
Expand Down
6 changes: 3 additions & 3 deletions codecov.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
codecov:
notify:
after_n_builds: 3
after_n_builds: 1
require_ci_to_pass: yes

coverage:
Expand All @@ -9,10 +9,10 @@ coverage:
range: "70...100"

comment:
after_n_builds: 3
after_n_builds: 1
layout: "diff,flags,files"
behavior: default
require_changes: yes
require_changes: false

github_checks:
annotations: true
12 changes: 12 additions & 0 deletions pdbstore/io/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,15 @@ def is_compression_supported() -> bool:
from pdbstore.io.cab import compress # pylint: disable=import-outside-toplevel

return compress is not None


def is_decompression_supported() -> bool:
"""Check if CAB decompression is supported
:return: True if supported, else False
"""

# Make local import to avoid unwanted search operation
from pdbstore.io.cab import decompress # pylint: disable=import-outside-toplevel

return decompress is not None
2 changes: 1 addition & 1 deletion pdbstore/report/generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ def generate(self, report_type: str = "products") -> Optional["BaseStatistics"]:

data = self.mapping[report_type]()
if not data.build(self.store):
return None
return None # pragma: no cover
return data

def supported_list(self) -> List[str]:
Expand Down
11 changes: 9 additions & 2 deletions pdbstore/store/entry.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ def __init__(
file_name: str,
file_hash: str,
source_file: PathLike,
compressed: Optional[bool] = False,
compressed: bool = False,
):
# The associated symbol store object
self.store: "Store" = store # type: ignore[name-defined] # noqa: F821
Expand All @@ -29,7 +29,7 @@ def __init__(
# Full path name to the input source file to be stored
self.source_file: Path = util.str_to_path(source_file)
# Flag indicating if the stored file is compressed or not
self.compressed: Optional[bool] = compressed
self.compressed: bool = compressed

def _stored_dir(self) -> Path:
"""Retrieve the full path of the associated directory from associated store.
Expand Down Expand Up @@ -65,6 +65,13 @@ def is_committed(self) -> bool:
file_path = self.stored_path
return file_path.is_file()

def is_compressed(self) -> bool:
"""Determine if compression activated or not
:return: True if compression is enabled, else False
"""
return self.compressed

def commit(self, force: Optional[bool] = False) -> bool:
"""Commit transaction entry by storing the required filse into the symbol store
Expand Down
2 changes: 1 addition & 1 deletion pdbstore/store/store.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ def next_transaction_id(self) -> str:
last_id = int(content)
except exceptions.ReadFileError:
raise
except Exception as exc:
except Exception as exc: # pragma: no cover
raise exceptions.UnexpectedError(
"Failed to extract last id from lastid file"
) from exc
Expand Down
35 changes: 33 additions & 2 deletions tests/cli/test_cli.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import subprocess
import sys
from pathlib import Path
from unittest import mock

Expand All @@ -7,6 +9,7 @@
ERROR_COMMAND_NAME,
ERROR_ENCOUNTERED,
ERROR_INVALID_CONFIGURATION,
ERROR_SUBCOMMAND_NAME,
SUCCESS,
)
from pdbstore.io.output import PDBStoreOutput
Expand All @@ -20,8 +23,7 @@ def test_version(capsys):
assert pdbstore.cli.cli.main() == SUCCESS
assert capsys.readouterr().out == f"{pdbstore.__version__}\n"
assert pdbstore.cli.cli.main(["--version"]) == 0
captured = capsys.readouterr()
assert captured.out == f"{pdbstore.__version__}\n"
assert capsys.readouterr().out == f"{pdbstore.__version__}\n"


def test_config_error(capsys):
Expand Down Expand Up @@ -108,3 +110,32 @@ def test_similar_name(capsys):
"""
)


def test_no_subcommand_name(capsys):
"""test command without subcommand name"""
assert pdbstore.cli.cli.main(["report"]) == ERROR_SUBCOMMAND_NAME
out, err = capsys.readouterr()
assert out.startswith("usage: pdbstore report {file,product,transaction")
assert err == ""


def test_unsupported_subcommand_name(capsys):
"""test command with unsupported subcommand name"""
assert pdbstore.cli.cli.main(["report", "invalid"]) == ERROR_SUBCOMMAND_NAME
out, err = capsys.readouterr()
assert out.startswith("usage: pdbstore report {file,product,transaction")
assert err == ""


def test_commandline_as_module():
"""test command-line invoked as python module"""

command = [sys.executable, "-m", "pdbstore", "--version"]
with subprocess.Popen(
command, stdout=subprocess.PIPE, stderr=subprocess.PIPE
) as proc:
stdout, stderr = proc.communicate()
assert proc.returncode == 0
assert stdout.decode().startswith(pdbstore.__version__)
assert stderr.decode() == ""
124 changes: 124 additions & 0 deletions tests/unit/test_cab.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,3 +177,127 @@ def test_compress_invocation_failure(_which, fake_process, test_args):
with pytest.raises(exceptions.CabCompressionError) as excinfo:
pdbstore.io.cab.compress("/usr/input/file.pdb", "/usr/output/file.pd_")
assert str(excinfo.value) == "compression error for /usr/input/file.pdb"


@mock.patch("pdbstore.util.which")
@pytest.mark.parametrize(
"test_args",
[
(
"linux",
"/usr/bin/gcab",
pdbstore.io.cab._decompress_gcab,
),
(
"windows",
r"C:\Windows\System32\expand.exe",
pdbstore.io.cab._decompress_expand,
),
],
)
def test_decompress_supported_per_platform(_which, test_args):
"""test decompression is supported"""
_which.return_value = test_args[1]
with mock.patch("sys.platform", test_args[0]):
importlib.reload(pdbstore.io.cab)
assert pdbstore.io.cab.decompress is not None
assert pdbstore.io.cab.decompress.__name__ == test_args[2].__name__


@mock.patch("pdbstore.util.which")
@pytest.mark.parametrize("platform", ["linux", "windows"])
def test_decompress_not_supported_per_platform(_which, platform):
"""test compression is not supported"""
_which.return_value = None
with mock.patch("sys.platform", platform):
importlib.reload(pdbstore.io.cab)
assert pdbstore.io.is_decompression_supported() is False


@mock.patch("pdbstore.util.which")
@pytest.mark.parametrize(
"test_args",
[
(
"linux",
"/usr/bin/gcab",
pdbstore.io.cab._decompress_gcab,
[
"gcab",
"-x",
"-C",
"/usr/output",
"/usr/input/file.pd_",
],
),
(
"windows",
r"C:\Windows\System32\expand.exe",
pdbstore.io.cab._decompress_expand,
[
"expand.exe",
"/usr/input/file.pd_",
"/usr/output",
],
),
],
)
def test_decompress_invocation_success(_which, fake_process, test_args):
"""test compression with success"""
_which.return_value = test_args[1]

fake_process.register(
test_args[3],
stdout=b"compression ok",
returncode=0,
)
with mock.patch("sys.platform", test_args[0]):
importlib.reload(pdbstore.io.cab)
assert pdbstore.io.cab.decompress is not None
assert pdbstore.io.cab.decompress.__name__ == test_args[2].__name__
pdbstore.io.cab.decompress("/usr/input/file.pd_", "/usr/output")


@mock.patch("pdbstore.util.which")
@pytest.mark.parametrize(
"test_args",
[
(
"linux",
"/usr/bin/gcab",
pdbstore.io.cab._decompress_gcab,
[
"gcab",
"-x",
"-C",
"/usr/output",
"/usr/input/file.pd_",
],
),
(
"windows",
r"C:\Windows\System32\expand.exe",
pdbstore.io.cab._decompress_expand,
[
"expand.exe",
"/usr/input/file.pd_",
"/usr/output",
],
),
],
)
def test_decompress_invocation_failure(_which, fake_process, test_args):
"""test compression with failure"""
_which.return_value = test_args[1]

fake_process.register(
test_args[3],
stdout="decompression error for /usr/input/file.pd_",
returncode=1,
)
with mock.patch("sys.platform", test_args[0]):
importlib.reload(pdbstore.io.cab)
assert pdbstore.io.cab.decompress.__name__ == test_args[2].__name__
with pytest.raises(exceptions.CabCompressionError) as excinfo:
pdbstore.io.cab.decompress("/usr/input/file.pd_", "/usr/output")
assert str(excinfo.value) == "decompression error for /usr/input/file.pd_"
14 changes: 13 additions & 1 deletion tests/unit/test_hash.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,18 @@ def test_hash_pdb_native(test_data_native_dir, file_info):
assert hash_key == file_info[1]


@pytest.mark.parametrize(
"file_info",
[
("dummylib.pdb", "26AAE66BC7ED4655BD38492E7BB268831"),
],
)
def test_hash_pdb_portable(test_data_portable_dir, file_info):
"""Test PDB file hash"""
hash_key = file.compute_hash_key(test_data_portable_dir / file_info[0])
assert hash_key == file_info[1]


def test_hash_invalid(test_data_invalid_dir):
"""Test invalid exe file"""
with pytest.raises(exceptions.UnknowFileTypeError):
Expand All @@ -51,7 +63,7 @@ def test_hash_not_found(test_data_dir):
],
)
def test_incomplete(dir_name, request):
"""test incomplete portable PDB file content"""
"""test incomplete PDB file content"""
base_dir = request.getfixturevalue(dir_name)
pdb_path = base_dir / "dummylib.pdb"
with open(pdb_path, "rb") as fps:
Expand Down
34 changes: 34 additions & 0 deletions tests/unit/test_report.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import pytest

from pdbstore.report import ReportGenerator


def test_supported_list(tmp_store):
"""test the list of supported report types"""
report = ReportGenerator(tmp_store)
assert sorted(report.supported_list()) == [
ReportGenerator.FILES,
ReportGenerator.PRODUCTS,
ReportGenerator.TRANSACTIONS,
]


@pytest.mark.parametrize(
"report_type",
[
ReportGenerator.FILES,
ReportGenerator.PRODUCTS,
ReportGenerator.TRANSACTIONS,
],
)
def test_valid_report(tmp_store, report_type):
"""test report generation with success"""
report = ReportGenerator(tmp_store)
assert report.generate(report_type) is not None


def test_invalid_report(tmp_store, capsys):
"""test report generation with failure"""
report = ReportGenerator(tmp_store)
assert report.generate("invalid") is None
assert capsys.readouterr().err == "ERROR: invalid : unsupported report type\n"
Loading

0 comments on commit 64347a3

Please sign in to comment.