earthsnake/tests/test_identity.py

262 lines
7.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""Tests for the Identity class
"""
import bip39
from ed25519 import SigningKey, create_keypair
import pytest
from pytest_mock.plugin import MockerFixture
from earthsnake.exc import ValidationError
from earthsnake.identity import Identity
from .helpers import DEFAULT_IDENTITY_SEED as TEST_SEED, random_name
TEST_MNEMONIC = bip39.encode_bytes(TEST_SEED)
@pytest.mark.parametrize(
'name',
[
pytest.param('s', id='veryshort'),
pytest.param('sho', id='short'),
pytest.param('longy', id='long'),
pytest.param('verylong', id='verylong'),
pytest.param('0num', id='numberstart'),
],
)
def test_init_bad_name(name: str) -> None:
"""Test if initialisation is not possible with an invalid name"""
sign, verify = create_keypair()
with pytest.raises(ValidationError) as ctx:
Identity(name, verify_key=verify, sign_key=sign)
assert 'Invalid name' in str(ctx.value)
def test_init_key_mismatch() -> None:
"""Test if initialisation fails if the signing and verifying keys dont match"""
sign1, _ = create_keypair()
_, verify2 = create_keypair()
with pytest.raises(ValidationError) as ctx:
Identity('name', verify_key=verify2, sign_key=sign1)
assert 'Signing and verifying keys dont match' in str(ctx.value)
def test_init_no_keys() -> None:
"""Test if initialisation is not possible without keys"""
with pytest.raises(ValidationError) as ctx:
Identity('name')
assert 'At least verify_key must be present' in str(ctx.value)
@pytest.mark.id_key_seed(TEST_SEED)
@pytest.mark.id_name('test')
def test_str(identity: Identity) -> None:
"""Test if the __str__ method returns the author address"""
assert str(identity) == '@test.bcz76z52y5dlpohtkmpuj3jsdcvfmebzpcgfmtmhu4u7hlexzreya'
@pytest.mark.id_key_seed(TEST_SEED)
@pytest.mark.id_name('test')
def test_repr(identity: Identity) -> None:
"""Test if the __repr__ method returns the author address"""
assert (
repr(identity)
== '<Identity (signer) @test.bcz76z52y5dlpohtkmpuj3jsdcvfmebzpcgfmtmhu4u7hlexzreya>'
)
def test_repr_nosign() -> None:
"""Test the __repr__ method marks the identity as a signer in the output"""
identity = Identity.from_address('@test.bcz76z52y5dlpohtkmpuj3jsdcvfmebzpcgfmtmhu4u7hlexzreya')
assert (
repr(identity) == '<Identity @test.bcz76z52y5dlpohtkmpuj3jsdcvfmebzpcgfmtmhu4u7hlexzreya>'
)
def test_from_address() -> None:
"""Test loading an identity from an author address"""
skey = SigningKey(TEST_SEED)
vkey = skey.get_verifying_key()
identity = Identity.from_address('@test.bcz76z52y5dlpohtkmpuj3jsdcvfmebzpcgfmtmhu4u7hlexzreya')
assert identity.name == 'test'
assert identity.sign_key is None
assert identity.verify_key.to_bytes() == vkey.to_bytes()
def test_from_invalid_address() -> None:
"""Test loading an identity from an invalid address"""
with pytest.raises(ValidationError) as ctx:
Identity.from_address('@inva.lid')
assert 'Invalid address @inva.lid' in str(ctx.value)
def test_generate(mocker: MockerFixture) -> None:
"""Test the generate property"""
skey = SigningKey(TEST_SEED)
vkey = skey.get_verifying_key()
mocker.patch('earthsnake.identity.create_keypair', return_value=(skey, vkey))
identity = Identity.generate('test')
assert str(identity) == '@test.bcz76z52y5dlpohtkmpuj3jsdcvfmebzpcgfmtmhu4u7hlexzreya'
assert identity.sign_key
assert identity.verify_key
assert identity.name == 'test'
@pytest.mark.id_key_seed(TEST_SEED)
@pytest.mark.id_name('test')
def test_mnemonic(identity: Identity) -> None:
"""Test the mnemonic property"""
assert identity.mnemonic == f'test {TEST_MNEMONIC}'
def test_mnemonic_no_signing_key() -> None:
"""Test if the mnemonic property returns None if there is no signing key"""
identity = Identity.from_address('@test.bcz76z52y5dlpohtkmpuj3jsdcvfmebzpcgfmtmhu4u7hlexzreya')
assert identity.mnemonic is None
def test_from_mnemonic() -> None:
"""Test if identities can be loaded from mnemonics"""
name = random_name()
identity = Identity.from_mnemonic(f'{name} {TEST_MNEMONIC}')
assert identity.name == name
assert identity.sign_key
assert identity.sign_key.to_seed() == TEST_SEED
assert str(identity) == f'@{name}.bcz76z52y5dlpohtkmpuj3jsdcvfmebzpcgfmtmhu4u7hlexzreya'
@pytest.mark.parametrize(
'address',
[
pytest.param('noat.bcz76z52y5dlpohtkmpuj3jsdcvfmebzpcgfmtmhu4u7hlexzreya', id='no_at'),
pytest.param(
'@toolong.bcz76z52y5dlpohtkmpuj3jsdcvfmebzpcgfmtmhu4u7hlexzreya',
id='too_long',
),
pytest.param('@test.invalidkey', id='invalid_key'),
pytest.param(
'@test.cz76z52y5dlpohtkmpuj3jsdcvfmebzpcgfmtmhu4u7hlexzreya',
id='nonprefixed_key',
),
pytest.param('@test.many.periods', id='many_periods'),
],
)
def test_valid_address_invalid(address: str) -> None:
"""Test if valid_address fails for invalid addresses"""
assert Identity.valid_address(address) is False
def test_valid_address() -> None:
"""Test if valid_address passes on valid addresses"""
assert Identity.valid_address('@test.bcz76z52y5dlpohtkmpuj3jsdcvfmebzpcgfmtmhu4u7hlexzreya')
def test_eq_str() -> None:
"""Test if an Identity is considered equal to its string representation"""
identity_str = '@test.bcz76z52y5dlpohtkmpuj3jsdcvfmebzpcgfmtmhu4u7hlexzreya'
identity = Identity.from_address(identity_str)
assert identity == identity_str
assert identity != '@test.cz76z52y5dlpohtkmpuj3jsdcvfmebzpcgfmtmhu4u7hlexzreyb'
def test_eq_identity() -> None:
"""Test if two different identities are considered equal if their verifying key is equal"""
identity_str = '@test.bcz76z52y5dlpohtkmpuj3jsdcvfmebzpcgfmtmhu4u7hlexzreya'
identity1 = Identity.from_address(identity_str)
identity2 = Identity.from_address(identity_str)
identity3 = Identity.generate('some')
assert identity1 == identity2
assert identity1 != identity3
@pytest.mark.id_key_seed(TEST_SEED)
@pytest.mark.id_name('test')
def test_eq_other(identity: Identity) -> None:
"""Test if Identity cannot be compared to something like an int"""
with pytest.raises(TypeError):
assert identity == 1
def test_sign_nokey() -> None:
"""Test if Identity.sign() fails if the identity doesnt have a signing key available"""
identity_str = '@test.bcz76z52y5dlpohtkmpuj3jsdcvfmebzpcgfmtmhu4u7hlexzreya'
identity = Identity.from_address(identity_str)
with pytest.raises(TypeError):
identity.sign('test data')
@pytest.mark.id_key_seed(TEST_SEED)
@pytest.mark.id_name('test')
def test_sign(identity: Identity) -> None:
"""Test if Identity.sign() works as expected"""
assert (
identity.sign('test data')
== 'b6gyis42cvdfhsp7xx3jb4773ebbqoq4zhdo4pyeitskefrfkkzxwdkwjkjpq2oyglpngx4tpzzezeedp7eb'
'x4i3vkpq7wj6odjinacy'
)
@pytest.mark.id_key_seed(TEST_SEED)
@pytest.mark.id_name('test')
def test_verify(identity: Identity) -> None:
"""Test if Identity.verify works as expected"""
assert (
identity.verify(
'test data',
'b6gyis42cvdfhsp7xx3jb4773ebbqoq4zhdo4pyeitskefrfkkzxwdkwjkjpq2oyglpngx4tpzzezeedp7eb'
'x4i3vkpq7wj6odjinacy',
)
is True
)
assert (
identity.verify(
'test date',
'b6gyis42cvdfhsp7xx3jb4773ebbqoq4zhdo4pyeitskefrfkkzxwdkwjkjpq2oyglpngx4tpzzezeedp7eb'
'x4i3vkpq7wj6odjinacy',
)
is False
)
assert (
identity.verify(
'test data',
'b6gyis42cvdfhsp7xx3jb4773ebbqoq4zhdo4pyeitskefrfkkzxwdkwjkjpq2oyglpngx4tpzzezeedp7eb'
'x4i3vkpq7wj6odjinacq',
)
is False
)