The SSH host key has changed on 8 April, 2022 to this one: SHA256:573uTBSeh74kvOo0HJXi5ijdzRm8me27suzNEDlGyrQ
Python implementation of [Earthstar](https://earthstar-project.org/)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
earthsnake/tests/test_identity.py

261 lines
7.7 KiB

"""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
)