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

Measure and act on pytest-cov #61

Merged
merged 4 commits into from
Jun 11, 2024
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: 1 addition & 1 deletion .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,4 @@ jobs:
- name: check
run: make check
- name: test
run: make test-ci
run: make test-all
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ __pycache__
*.egg-info
build
dist
.coverage
19 changes: 8 additions & 11 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,18 @@

all:: install build

test:: lint test-ci
test:: lint
poetry run pytest -n auto

test-fast:: lint
pytest -n auto
test-all::
poetry run pytest -n auto -m ""

test-ci::
poetry run pytest -sx -n auto
test-dist:: clean build install-dist test-integration

test-dist:: clean build install-dist test-readme
test-integration::
poetry run pytest "tests/test_cli.py::TestIntegration" -m "" -n auto

REDIRECT_OUTPUT ?= > /dev/null
test-readme::
bash scripts/test-readme.sh $(REDIRECT_OUTPUT)

push:: test-fast git-off-main git-no-unsaved
push:: test-all git-off-main git-no-unsaved
@branch=$$(git symbolic-ref --short HEAD); \
git push origin $$branch

Expand Down
87 changes: 86 additions & 1 deletion poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ pycryptodome = "~3.20.0"
pytest = "~8.2.1"
pytest-xdist = "~3.6.1"
toml = "^0.10.2"
pytest-cov = "^5.0.0"

[tool.poetry.scripts]
bipsea = "bipsea.bipsea:cli"
Expand Down
3 changes: 3 additions & 0 deletions pytest.ini
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,6 @@ log_cli = false
log_cli_level = DEBUG
testpaths =
tests
addopts = --cov=bipsea --cov-report=term-missing -m "not slow"
markers =
slow: consumes wall time (deselect with '-m "not slow"')
9 changes: 0 additions & 9 deletions src/bipsea/bip85.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
from typing import Dict, Union

import base58
from ecdsa import SECP256k1

from .bip32 import VERSIONS, ExtendedKey
from .bip32 import derive_key as derive_key_bip32
Expand Down Expand Up @@ -178,14 +177,6 @@ def split_and_validate(path: str):
return segments


def validate_key(entropy: bytes):
"""per BIP-85 we should hard fail under these conditions"""
assert len(entropy) == 32
int_key = int.from_bytes(entropy, "big")
if not int_key or int_key > SECP256k1.order:
raise ValueError("Invalid derived key. Try again with next child index.")


def do_rolls(entropy: bytes, sides: int, rolls: int, index: int) -> str:
"""sides > 1, 1 < rolls > 100"""
max_width = len(str(sides - 1))
Expand Down
File renamed without changes.
77 changes: 75 additions & 2 deletions tests/test_cli.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import logging
import random
import subprocess
import sys
import tempfile
from io import StringIO
from pathlib import Path

import pytest
from click.testing import CliRunner
Expand All @@ -16,7 +21,7 @@

from bipsea.bip32types import validate_prv
from bipsea.bip39 import LANGUAGES, validate_mnemonic_words
from bipsea.bipsea import ISO_TO_LANGUAGE, N_WORDS_ALLOWED, cli
from bipsea.bipsea import ISO_TO_LANGUAGE, N_WORDS_ALLOWED, cli, try_for_pipe_input
from bipsea.util import ASCII_INPUTS, LOGGER_NAME

logger = logging.getLogger(LOGGER_NAME)
Expand Down Expand Up @@ -269,7 +274,7 @@ def test_bad_xprv(self, runner):


class TestIntegration:
def test_chain_all_commands(self, runner):
def test_chain_no_pipe(self, runner):
"""this also tests that the default options are compatible"""
mnemonic_result = runner.invoke(cli, ["mnemonic"])
assert mnemonic_result.exit_code == 0
Expand Down Expand Up @@ -302,3 +307,71 @@ def test_too_short_inputs(self, runner, input):
bad_x_result = runner.invoke(cli, ["derive", "-x", input, "-a", "base85"])
assert bad_x_result.exit_code != 0
assert "Error" in bad_x_result.output

def test_try_for_pipe_input(self, monkeypatch):
test_input = "test input"
monkeypatch.setattr(sys, "stdin", StringIO(test_input))
monkeypatch.setattr(sys.stdin, "isatty", lambda: False)
assert try_for_pipe_input() == test_input.strip()

monkeypatch.setattr(sys.stdin, "isatty", lambda: True)
assert try_for_pipe_input() == ""

@pytest.mark.parametrize(
"cmd, opt", [("validate", "-m"), ("derive", "-m"), ("xprv", "-x")]
)
def test_no_m(self, runner, cmd, opt):
result = runner.invoke(cli, [cmd, opt])
assert result.exit_code != 0
assert "Error" in result.output

commands = [
"bipsea --version",
"bipsea --help",
"bipsea mnemonic --help",
"bipsea validate --help",
"bipsea xprv --help",
"bipsea derive --help",
"bipsea mnemonic | bipsea validate | bipsea xprv | bipsea derive -a mnemonic -n 12",
"bipsea mnemonic -t jpn -n 15",
"bipsea mnemonic -n 12 --pretty",
"bipsea mnemonic -t spa -n 12 | bipsea validate -f spa",
"bipsea mnemonic | bipsea validate",
"bipsea mnemonic | bipsea validate | bipsea xprv",
'bipsea xprv -m "elder major green sting survey canoe inmate funny bright jewel anchor volcano" | bipsea derive -a mnemonic -n 12',
'bipsea validate -f free -m "123456123456123456" | bipsea xprv',
'bipsea validate -f free -m "$(cat input.txt)"',
'bipsea validate -m "elder major green sting survey canoe inmate funny bright jewel anchor volcano" | bipsea xprv | bipsea derive -a base85',
'bipsea validate -m "elder major green sting survey canoe inmate funny bright jewel anchor volcano" | bipsea xprv | bipsea derive -a mnemonic -t jpn -n 12',
'bipsea validate -m "elder major green sting survey canoe inmate funny bright jewel anchor volcano" | bipsea xprv | bipsea derive -a drng -n 1000',
'bipsea validate -m "elder major green sting survey canoe inmate funny bright jewel anchor volcano" | bipsea xprv | bipsea derive -a dice -n 100 -s 6',
]

@pytest.mark.slow
@pytest.mark.parametrize(
"command",
commands,
ids=lambda cmd: (cmd[:32] + "...") if len(cmd) > 32 else cmd,
)
def test_commands(self, command):
with tempfile.NamedTemporaryFile("w", suffix=".sh", delete=False) as script:
script.write("#!/bin/sh\n")
script.write(command + "\n")
script.flush()

Path(script.name).chmod(0o755)

try:
result = subprocess.run(
["poetry", "run", script.name],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True,
)
assert result.returncode == 0, (
f"Command failed: {command}\n"
f"Output: {result.stdout}\n"
f"Error: {result.stderr}"
)
finally:
Path(script.name).unlink()
12 changes: 12 additions & 0 deletions tests/test_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
relative_entropy,
shannon_entropy,
shuffle,
to_hex_string,
)

logger = logging.getLogger(LOGGER_NAME)
Expand Down Expand Up @@ -39,3 +40,14 @@ def test_contains_only_ascii():
def test_shuffle():
shuffled = shuffle(deck_52())
assert shuffled != deck_52()


def test_bad_relatve_entropy():
with pytest.warns(UserWarning, match="outside"):
relative_entropy("λ")


def test_to_hex_string():
data = b"\x00\xff\x10\x20"
expected = "00ff1020"
assert to_hex_string(data) == expected