262 lines
7.7 KiB
Python
262 lines
7.7 KiB
Python
"""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 don’t 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 don’t 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 doesn’t 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
|
||
)
|