"""Tests for the Identity class """ import bip39 from nacl.signing import SigningKey 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 = SigningKey.generate() verify = sign.verify_key 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 = SigningKey.generate() verify2 = SigningKey.generate().verify_key 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) == '' ) 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) == '' ) def test_from_address() -> None: """Test loading an identity from an author address""" skey = SigningKey(TEST_SEED) vkey = skey.verify_key identity = Identity.from_address('@test.bcz76z52y5dlpohtkmpuj3jsdcvfmebzpcgfmtmhu4u7hlexzreya') assert identity.name == 'test' assert identity.sign_key is None assert identity.verify_key == vkey 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) mocker.patch('earthsnake.identity.SigningKey.generate', return_value=skey) 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.encode() == 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 )