argon2-cffi/tests/test_utils.py
Hynek Schlawack 4da64d2ed4
Lint stricter
2023-07-04 09:08:17 +02:00

146 lines
3.6 KiB
Python

# SPDX-License-Identifier: MIT
from base64 import b64encode
from dataclasses import replace
import pytest
from hypothesis import given
from hypothesis import strategies as st
from argon2 import Parameters, Type, extract_parameters
from argon2._utils import NoneType, _check_types, _decoded_str_len
from argon2.exceptions import InvalidHashError
class TestCheckTypes:
def test_success(self):
"""
Returns None if all types are okay.
"""
assert None is _check_types(
bytes=(b"bytes", bytes),
tuple=((1, 2), tuple),
str_or_None=(None, (str, NoneType)),
)
def test_fail(self):
"""
Returns summary of failures.
"""
rv = _check_types(
bytes=("not bytes", bytes), str_or_None=(42, (str, NoneType))
)
assert "." == rv[-1] # proper grammar FTW
assert "'str_or_None' must be a str, or NoneType (got int)" in rv
assert "'bytes' must be a bytes (got str)" in rv
@given(st.binary())
def test_decoded_str_len(bs):
"""
_decoded_str_len computes the resulting length.
"""
assert len(bs) == _decoded_str_len(len(b64encode(bs).rstrip(b"=")))
VALID_HASH = (
"$argon2id$v=19$m=65536,t=2,p=4$"
"c29tZXNhbHQ$GpZ3sK/oH9p7VIiV56G/64Zo/8GaUw434IimaPqxwCo"
)
VALID_PARAMETERS = Parameters(
type=Type.ID,
salt_len=8,
hash_len=32,
version=19,
memory_cost=65536,
time_cost=2,
parallelism=4,
)
VALID_HASH_V18 = (
"$argon2i$m=8,t=1,p=1$c29tZXNhbHQ$gwQOXSNhxiOxPOA0+PY10P9QFO"
"4NAYysnqRt1GSQLE55m+2GYDt9FEjPMHhP2Cuf0nOEXXMocVrsJAtNSsKyfg"
)
VALID_PARAMETERS_V18 = Parameters(
type=Type.I,
salt_len=8,
hash_len=64,
version=18,
memory_cost=8,
time_cost=1,
parallelism=1,
)
class TestExtractParameters:
def test_valid_hash(self):
"""
A valid hash is parsed.
"""
parsed = extract_parameters(VALID_HASH)
assert VALID_PARAMETERS == parsed
def test_valid_hash_v18(self):
"""
A valid Argon v1.2 hash is parsed.
"""
parsed = extract_parameters(VALID_HASH_V18)
assert VALID_PARAMETERS_V18 == parsed
@pytest.mark.parametrize(
"hash",
[
"",
"abc" + VALID_HASH,
VALID_HASH.replace("p=4", "p=four"),
VALID_HASH.replace(",p=4", ""),
],
)
def test_invalid_hash(self, hash):
"""
Invalid hashes of various types raise an InvalidHash error.
"""
with pytest.raises(InvalidHashError):
extract_parameters(hash)
class TestParameters:
def test_eq(self):
"""
Parameters are equal iff every attribute is equal.
"""
assert VALID_PARAMETERS == VALID_PARAMETERS # noqa: PLR0124
assert VALID_PARAMETERS != replace(VALID_PARAMETERS, salt_len=9)
def test_eq_wrong_type(self):
"""
Parameters are only compared if they have the same type.
"""
assert VALID_PARAMETERS != "foo"
assert VALID_PARAMETERS != object()
def test_repr(self):
"""
__repr__ returns s ensible string.
"""
assert repr(
Parameters(
type=Type.ID,
salt_len=8,
hash_len=32,
version=19,
memory_cost=65536,
time_cost=2,
parallelism=4,
)
) == (
"Parameters(type=<Type.ID: 2>, version=19, salt_len=8, "
"hash_len=32, time_cost=2, memory_cost=65536, parallelism=4)"
)