test_revocation.py 30.74 KiB
# Copyright 2016-2023 Maël Azimi <m.a@moul.re>
#
# Silkaj is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Silkaj is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with Silkaj. If not, see <https://www.gnu.org/licenses/>.
import urllib
from pathlib import Path
from unittest.mock import Mock
import pytest
import rich_click as click
from click.testing import CliRunner
from duniterpy.api import bma
from duniterpy.documents.revocation import Revocation
from silkaj import auth
from silkaj.blockchain import tools as bc_tools
from silkaj.cli import cli
from silkaj.constants import FAILURE_EXIT_STATUS, SUCCESS_EXIT_STATUS
from silkaj.network import client_instance
from silkaj.public_key import gen_pubkey_checksum
from silkaj.wot import idty_tools, revocation
from silkaj.wot import tools as w_tools
from tests.patched.auth import patched_auth_method
from tests.patched.blockchain_tools import patched_get_head_block_gtest
from tests.patched.idty_tools import idty1, idty2, idty_block, lookup_one, lookup_two
# Useful function
def display_dry_options(display, dry_run):
if display:
return ["--display"]
if dry_run:
return ["--dry-run"]
return []
# Values
# idty1
REV_DOC = Revocation(
version=10,
currency="g1-test",
identity=idty1,
)
REV_DOC.signature = "dTv6HHnyBsMXofOZFT21Y3gRzG/frseCaZFfpatpCWj\
YsNA8HPHjTibLUcJ3E9ZUgd0QUV7Bbu868xQE+j/yAg=="
REV_DOC_FALSE = Revocation(
version=10,
currency="g1-test",
identity=idty1,
)
REV_DOC_FALSE.signature = "XXXXXXXXBsMXofOZFT21Y3gRzG/frseCaZFfp\
atpCWjYsNA8HPHjTibLUcJ3E9ZUgd0QUV7Bbu868xQE+j/yAg=="
# idty2
REV_2 = Revocation(
version=10,
currency="g1-test",
identity=idty2,
)
REV_2.signature = "42D2vbIJnv2aGqUMbD+BF+eChzzGo4R3CVPAl5hpIGvoT\
cZQCfKBsRRlZDx6Gwn6lsJ3KLiIwPQeJKGYCW2YBg=="
REV_2_FALSE = Revocation(
version=10,
currency="g1-test",
identity=idty2,
)
REV_2_FALSE.signature = "XXXXXXIJnv2aGqUMbD+BF+eChzzGo4R3CVPAl5hp\
IGvoTcZQCfKBsRRlZDx6Gwn6lsJ3KLiIwPQeJKGYCW2YBg=="
WRONG_FORMAT_REV = "ersion: 10\
Type: Revocation\
Currency: g1-test\
Issuer: 969qRJs8KhsnkyzqarpL4RKZGMdVKNbZgu8fhsigM7Lj\
IdtyUniqueID: aa_aa\
IdtyTimestamp: 703902-00002D6BC5E4FC540A4E188C3880A0ACCA06CD77017D26231A515312162B4070\
IdtySignature: 3RNQcKNI1VMmuCpK7wer8haOA959EQSDIR1v0U\
e/7TpTCOmsU2zYCpC+tqgLQFxDX4A79sB61c11J5C/3Z/TCw==\
42D2vbIJnv2aGqUMbD+BF+eChzzGo4R3CVPAl5hpIGvoTcZQCfKBsRRlZDx6Gwn6lsJ3KLiIwPQeJKGYCW2YBg=="
ERROR_CODE = 1005
ERROR_MESSAGE = "Document has unkown fields or wrong line ending format"
# patched functions
def patch_get_id_block(node, number):
return idty_block
def patched_auth_method_Claude():
return patched_auth_method("a")
def patch_check_many_identities(idty):
return True
def patched_choose_identity(pubkey):
return (
{
"uid": idty1.uid,
"meta": {"timestamp": str(idty1.block_id)},
"self": "kFW2we2K3zx4PZODx0Wf+xdXAJTmYD+yqdyZBsPF7UwqdaCA4N+yHj7+09\
Gjsttl0i9GtWzodyJ6mBE1q7jcAw==",
},
idty1.pubkey,
None,
)
def patched_send_bma_revoke_error(wot_useless, rev_doc_useless):
raise urllib.error.HTTPError(
url="this/is/a/test.url",
code=ERROR_CODE,
msg=ERROR_MESSAGE,
hdrs={},
fp=None,
)
# tests
# test cli dry-run
@pytest.mark.parametrize(
("subcommand", "expected_warn"),
[
(
"create",
False,
),
(
"verify",
False,
),
(
"publish",
True,
),
(
"revoke",
True,
),
],
)
def test_revocation_cli_dry_run(subcommand, expected_warn, monkeypatch):
"""
Tests dry-run option behavior when associated with other options
"""
monkeypatch.setattr(auth, "auth_method", patched_auth_method_Claude)
monkeypatch.setattr(bc_tools, "get_head_block", patched_get_head_block_gtest)
monkeypatch.setattr(w_tools, "choose_identity", patched_choose_identity)
monkeypatch.setattr(bma.blockchain, "block", patch_get_id_block)
monkeypatch.setattr(
idty_tools,
"check_many_identities",
patch_check_many_identities,
)
print("subcommand: ", subcommand) # debug
warning = "WARNING: the document will only be displayed and will not be sent."
command = ["--dry-run", "-gt", "wot", "revocation", subcommand]
print("command: ", " ".join(command)) # debug
file = "revocation.txt"
runner = CliRunner()
with runner.isolated_filesystem():
Path(file).write_text(REV_DOC.signed_raw(), encoding="utf-8")
result = runner.invoke(cli, args=command)
assert "6upqFiJ66WV6N3bPc8x8y7rXT3syqKRmwnVyunCtEj7o" in result.output
assert "Version: 10" in result.output
if expected_warn:
assert warning in result.output
else:
assert warning not in result.output
# test cli create
@pytest.mark.parametrize(
("display", "dry_run", "file", "user_input", "expected"),
[
(
False,
False,
None,
"yes\n",
[
"6upqFiJ66WV6N3bPc8x8y7rXT3syqKRmwnVyunCtEj7o",
"Do you want to save the revocation document for this identity?",
],
),
(
True,
False,
None,
"yes\n",
[
"Version: 10",
"6upqFiJ66WV6N3bPc8x8y7rXT3syqKRmwnVyunCtEj7o",
"Do you want to save the revocation document for this identity?",
],
),
(
False,
True,
None,
None,
[
"Version: 10",
"6upqFiJ66WV6N3bPc8x8y7rXT3syqKRmwnVyunCtEj7o",
],
),
(
False,
False,
Path("test_doc"),
"yes\n",
[
"6upqFiJ66WV6N3bPc8x8y7rXT3syqKRmwnVyunCtEj7o",
"Do you want to save the revocation document for this identity?",
],
),
(
True,
False,
Path("test_doc"),
"yes\n",
[
"Version: 10",
"6upqFiJ66WV6N3bPc8x8y7rXT3syqKRmwnVyunCtEj7o",
"Do you want to save the revocation document for this identity?",
],
),
(
False,
True,
Path("test_doc"),
None,
[
"Version: 10",
"6upqFiJ66WV6N3bPc8x8y7rXT3syqKRmwnVyunCtEj7o",
],
),
(
False,
False,
None,
"no\n",
[
"6upqFiJ66WV6N3bPc8x8y7rXT3syqKRmwnVyunCtEj7o",
"Do you want to save the revocation document for this identity?",
"Ok, goodbye!",
],
),
(
True,
False,
None,
"no\n",
[
"Version: 10",
"6upqFiJ66WV6N3bPc8x8y7rXT3syqKRmwnVyunCtEj7o",
"Do you want to save the revocation document for this identity?",
"Ok, goodbye!",
],
),
],
)
def test_revocation_cli_save(display, dry_run, file, user_input, expected, monkeypatch):
monkeypatch.setattr(auth, "auth_method", patched_auth_method_Claude)
monkeypatch.setattr(bc_tools, "get_head_block", patched_get_head_block_gtest)
monkeypatch.setattr(w_tools, "choose_identity", patched_choose_identity)
monkeypatch.setattr(bma.blockchain, "block", patch_get_id_block)
patched_save_doc = Mock()
monkeypatch.setattr(
revocation,
"save_doc",
patched_save_doc,
)
command = display_dry_options(display, dry_run)
subcommand = ["wot", "revocation", "create"]
command.extend(subcommand)
if file:
command.extend([str(file)])
else:
file = revocation.REVOCATION_LOCAL_PATH
result = CliRunner().invoke(cli, args=command, input=user_input)
if not dry_run and user_input == "yes\n":
patched_save_doc.assert_called_with(file, REV_DOC.signed_raw(), idty1.pubkey)
elif user_input == "no\n" or dry_run:
patched_save_doc.assert_not_called()
for expect in expected:
assert expect in result.output
# test cli verify
@pytest.mark.parametrize(
("display", "dry_run", "doc", "lookup", "file", "expected", "not_expected"),
[
(
False,
False,
REV_DOC,
lookup_one,
"",
[
"| Public key |",
"Revocation document is valid.\n",
],
["Version: 10"],
),
(
False,
False,
REV_DOC,
lookup_two,
"",
[
"One matching identity!\nSimilar identities:",
"uid",
"| Public key |",
"Revocation document is valid.\n",
],
["Version: 10"],
),
(
True,
False,
REV_DOC,
lookup_one,
"",
[
"Version: 10",
"| Public key |",
"Revocation document is valid.\n",
],
[],
),
(
False,
True,
REV_DOC,
lookup_one,
"",
[
"Version: 10",
],
[
"Revocation document is valid.\n",
],
),
(
False,
False,
REV_DOC_FALSE,
lookup_one,
"",
["Error: the signature of the revocation document is invalid."],
[
"Version: 10",
"| Public key |",
"Revocation document is valid.\n",
],
),
(
False,
False,
REV_2,
lookup_two,
"test_doc",
[
"Revocation document does not match any valid identity.\nSimilar identities:",
"uid",
"Claude",
"Claudia",
],
[
"Revocation document is valid.\n",
"| Public key |",
"Version: 10",
],
),
],
)
def test_revocation_cli_verify(
display,
dry_run,
doc,
lookup,
file,
expected,
not_expected,
monkeypatch,
):
def patched_lookup(node, id_pubkey):
return lookup
monkeypatch.setattr(bma.wot, "lookup", patched_lookup)
monkeypatch.setattr(bma.blockchain, "block", patch_get_id_block)
monkeypatch.setattr(bc_tools, "get_head_block", patched_get_head_block_gtest)
# prepare command
command = display_dry_options(display, dry_run)
command.extend(["wot", "revocation", "verify"])
if file:
command.extend([file])
else:
file = revocation.REVOCATION_LOCAL_PATH
# verify file
runner = CliRunner()
with runner.isolated_filesystem():
Path(file).write_text(doc.signed_raw(), encoding="utf-8")
result = runner.invoke(cli, args=command)
for expect in expected:
assert expect in result.output
for not_expect in not_expected:
assert not_expect not in result.output
# test cli publish
@pytest.mark.parametrize(
("display", "dry_run", "doc", "lookup", "file", "user_input", "expected"),
[
(
False,
False,
REV_DOC,
lookup_one,
"",
"yes\n",
[
"| Public key |",
"Do you confirm sending this revocation document immediately?",
],
),
(
False,
False,
REV_DOC,
lookup_two,
"",
"yes\n",
[
"One matching identity!\nSimilar identities:",
"Claudia",
"| Public key |",
"Do you confirm sending this revocation document immediately?",
],
),
(
True,
False,
REV_DOC,
lookup_one,
"",
"yes\n",
[
"| Public key |",
"Do you confirm sending this revocation document immediately?",
"Version: 10",
],
),
(
True,
False,
REV_DOC,
lookup_two,
"",
"yes\n",
[
"One matching identity!\nSimilar identities:",
"| Public key |",
"Do you confirm sending this revocation document immediately?",
"Version: 10",
],
),
(
False,
True,
REV_DOC,
lookup_one,
"",
None,
[
"WARNING: the document will only be displayed and will not be sent.",
"Version: 10",
],
),
(
False,
True,
REV_DOC,
lookup_two,
"",
None,
[
"One matching identity!\nSimilar identities:",
"WARNING: the document will only be displayed and will not be sent.",
"Version: 10",
],
),
(
False,
False,
REV_DOC,
lookup_one,
"",
"no\n",
[
"| Public key |",
"Do you confirm sending this revocation document immediately?",
],
),
(
True,
False,
REV_DOC,
lookup_one,
"",
"no\n",
[
"| Public key |",
"Do you confirm sending this revocation document immediately?",
"Version: 10",
],
),
(
False,
False,
REV_DOC_FALSE,
lookup_one,
"",
None,
["Error: the signature of the revocation document is invalid."],
),
(
True,
False,
REV_DOC_FALSE,
lookup_one,
"",
None,
["Error: the signature of the revocation document is invalid."],
),
(
False,
True,
REV_DOC_FALSE,
lookup_one,
"",
None,
[
"WARNING: the document will only be displayed and will not be sent.",
"Error: the signature of the revocation document is invalid.",
],
),
(
False,
False,
REV_DOC,
lookup_one,
"test_doc",
"yes\n",
[
"| Public key |",
"Do you confirm sending this revocation document immediately?",
],
),
(
True,
False,
REV_DOC,
lookup_one,
"test_doc",
"yes\n",
[
"| Public key |",
"Do you confirm sending this revocation document immediately?",
],
),
(
False,
True,
REV_DOC,
lookup_one,
"test_doc",
"yes\n",
[
"WARNING: the document will only be displayed and will not be sent.",
"Version: 10",
],
),
(
False,
False,
REV_DOC_FALSE,
lookup_one,
"test_doc",
None,
["Error: the signature of the revocation document is invalid."],
),
(
True,
False,
REV_DOC_FALSE,
lookup_one,
"test_doc",
None,
["Error: the signature of the revocation document is invalid."],
),
(
False,
True,
REV_DOC_FALSE,
lookup_one,
"test_doc",
None,
[
"Error: the signature of the revocation document is invalid.",
"WARNING: the document will only be displayed and will not be sent.",
],
),
(
False,
False,
REV_2,
lookup_two,
"",
"",
[
"Revocation document does not match any valid identity.\nSimilar identities:",
],
),
(
False,
False,
REV_DOC,
False,
"",
"",
["Revocation document does not match any valid identity."],
),
],
)
def test_revocation_cli_publish(
display,
dry_run,
doc,
lookup,
file,
user_input,
expected,
monkeypatch,
):
def patched_lookup(node, id_pubkey):
if not lookup:
raise urllib.error.HTTPError(
url="this/is/a/test.url",
code=404,
msg="(Test) Not Found",
hdrs={},
fp=None,
)
return lookup
monkeypatch.setattr(bma.wot, "lookup", patched_lookup)
monkeypatch.setattr(bc_tools, "get_head_block", patched_get_head_block_gtest)
monkeypatch.setattr(bma.blockchain, "block", patch_get_id_block)
patched_send_bma_revoke = Mock()
monkeypatch.setattr(bma.wot, "revoke", patched_send_bma_revoke)
# prepare command
command = display_dry_options(display, dry_run)
command.extend(["wot", "revocation", "publish"])
if file:
command.extend([file])
else:
file = revocation.REVOCATION_LOCAL_PATH
# test publication
runner = CliRunner()
with runner.isolated_filesystem():
Path(file).write_text(doc.signed_raw(), encoding="utf-8")
result = runner.invoke(cli, args=command, input=user_input)
if user_input == "yes\n" and not dry_run:
patched_send_bma_revoke.assert_called_once_with(
client_instance(),
doc.signed_raw(),
)
elif dry_run or user_input == "no\n":
patched_send_bma_revoke.assert_not_called()
for expect in expected:
assert expect in result.output
# test cli publish send errors
@pytest.mark.parametrize(
("display", "file", "user_input", "expected"),
[
(
False,
"",
"yes\n",
[
"| Public key |",
"Do you confirm sending this revocation document immediately?",
"Error while publishing revocation",
],
),
(
True,
"",
"yes\n",
[
"| Public key |",
"Do you confirm sending this revocation document immediately?",
"Version: 10",
"Error while publishing revocation",
],
),
(
False,
"test_doc",
"yes\n",
[
"| Public key |",
"Do you confirm sending this revocation document immediately?",
"Error while publishing revocation",
],
),
(
True,
"test_doc",
"yes\n",
[
"| Public key |",
"Do you confirm sending this revocation document immediately?",
"Version: 10",
"Error while publishing revocation",
],
),
],
)
def test_revocation_cli_publish_send_errors(
display,
file,
user_input,
expected,
monkeypatch,
):
def patched_lookup(node, id_pubkey):
return lookup_one
monkeypatch.setattr(bma.wot, "lookup", patched_lookup)
monkeypatch.setattr(bc_tools, "get_head_block", patched_get_head_block_gtest)
monkeypatch.setattr(bma.blockchain, "block", patch_get_id_block)
monkeypatch.setattr(bma.wot, "revoke", patched_send_bma_revoke_error)
# prepare command
command = display_dry_options(display, False)
command.extend(["wot", "revocation", "publish"])
if file:
command.extend([file])
else:
file = revocation.REVOCATION_LOCAL_PATH
# test publication
runner = CliRunner()
with runner.isolated_filesystem():
Path(file).write_text(REV_DOC.signed_raw(), encoding="utf-8")
result = runner.invoke(cli, args=command, input=user_input)
for expect in expected:
assert expect in result.output
assert result.exit_code == FAILURE_EXIT_STATUS
# test cli revoke
@pytest.mark.parametrize(
("display", "dry_run", "user_input", "doc", "expected"),
[
(
False,
False,
"yes\n",
REV_DOC,
[
"6upqFiJ66WV6N3bPc8x8y7rXT3syqKRmwnVyunCtEj7o",
"Do you confirm sending this revocation document immediately?",
],
),
(
True,
False,
"yes\n",
REV_DOC,
[
"6upqFiJ66WV6N3bPc8x8y7rXT3syqKRmwnVyunCtEj7o",
"Do you confirm sending this revocation document immediately?",
"Version: 10",
],
),
(
False,
True,
None,
REV_DOC,
[
"WARNING: the document will only be displayed and will not be sent.",
"6upqFiJ66WV6N3bPc8x8y7rXT3syqKRmwnVyunCtEj7o",
"Version: 10",
],
),
(
False,
False,
"no\n",
REV_DOC,
[
"6upqFiJ66WV6N3bPc8x8y7rXT3syqKRmwnVyunCtEj7o",
"Do you confirm sending this revocation document immediately?",
],
),
(
True,
False,
"no\n",
REV_DOC,
[
"6upqFiJ66WV6N3bPc8x8y7rXT3syqKRmwnVyunCtEj7o",
"Do you confirm sending this revocation document immediately?",
"Version: 10",
],
),
],
)
def test_revocation_cli_revoke(
display,
dry_run,
user_input,
doc,
expected,
monkeypatch,
):
monkeypatch.setattr(auth, "auth_method", patched_auth_method_Claude)
monkeypatch.setattr(bc_tools, "get_head_block", patched_get_head_block_gtest)
monkeypatch.setattr(w_tools, "choose_identity", patched_choose_identity)
monkeypatch.setattr(bma.blockchain, "block", patch_get_id_block)
patched_send_bma_revoke = Mock()
monkeypatch.setattr(bma.wot, "revoke", patched_send_bma_revoke)
command = display_dry_options(display, dry_run)
command.extend(["wot", "revocation", "revoke"])
client = client_instance()
result = CliRunner().invoke(cli, args=command, input=user_input)
for expect in expected:
assert expect in result.output
if not dry_run and user_input == "yes\n":
patched_send_bma_revoke.assert_called_once_with(client, doc.signed_raw())
if dry_run or user_input == "no\n":
patched_send_bma_revoke.assert_not_called()
# test cli revoke errors
@pytest.mark.parametrize(
("display", "user_input", "doc", "expected"),
[
(
False,
"yes\n",
REV_DOC,
[
"6upqFiJ66WV6N3bPc8x8y7rXT3syqKRmwnVyunCtEj7o",
"Do you confirm sending this revocation document immediately?",
"Error while publishing revocation",
],
),
(
True,
"yes\n",
REV_DOC,
[
"6upqFiJ66WV6N3bPc8x8y7rXT3syqKRmwnVyunCtEj7o",
"Do you confirm sending this revocation document immediately?",
"Version: 10",
"Error while publishing revocation",
],
),
],
)
def test_revocation_cli_revoke_errors(display, user_input, doc, expected, monkeypatch):
monkeypatch.setattr(auth, "auth_method", patched_auth_method_Claude)
monkeypatch.setattr(bc_tools, "get_head_block", patched_get_head_block_gtest)
monkeypatch.setattr(w_tools, "choose_identity", patched_choose_identity)
monkeypatch.setattr(bma.blockchain, "block", patch_get_id_block)
monkeypatch.setattr(bma.wot, "revoke", patched_send_bma_revoke_error)
command = display_dry_options(display, False)
command.extend(["wot", "revocation", "revoke"])
result = CliRunner().invoke(cli, args=command, input=user_input)
for expect in expected:
assert expect in result.output
assert result.exit_code == FAILURE_EXIT_STATUS
# test create_revocation_doc
@pytest.mark.parametrize(("idty", "lookup"), [(idty1, lookup_one)])
def test_create_revocation_doc(idty, lookup):
test = revocation.create_revocation_doc(
lookup["results"][0]["uids"][0],
"6upqFiJ66WV6N3bPc8x8y7rXT3syqKRmwnVyunCtEj7o",
"g1-test",
)
expected = Revocation(
version=10,
currency="g1-test",
identity=idty,
)
assert test == expected
# test save_doc
@pytest.mark.parametrize(
("path", "rev_1", "rev_2", "pubkey"),
[
(
Path("./test_doc.txt"),
REV_DOC,
REV_2,
"6upqFiJ66WV6N3bPc8x8y7rXT3syqKRmwnVyunCtEj7o",
),
(
Path("revocation"),
REV_DOC,
REV_2,
"6upqFiJ66WV6N3bPc8x8y7rXT3syqKRmwnVyunCtEj7o",
),
],
)
def test_save_doc(path, rev_1, rev_2, pubkey, capsys, monkeypatch):
def conf_true(confirm_question):
return True
def conf_false(confirm_question):
return False
runner = CliRunner()
with runner.isolated_filesystem():
# test file is written on en empty location
revocation.save_doc(path, rev_1.signed_raw(), pubkey)
assert path.is_file()
assert path.read_text(encoding="utf-8") == rev_1.signed_raw()
# test file is overwritten if confirm
monkeypatch.setattr(click, "confirm", value=conf_true)
revocation.save_doc(path, rev_2.signed_raw(), pubkey)
expected_confirm = f"Revocation document file stored into `{path}` \
for following public key: {gen_pubkey_checksum(pubkey)}"
assert expected_confirm in capsys.readouterr().out
assert path.read_text(encoding="utf-8") == rev_2.signed_raw()
# test file is not overwritten if not confirm
monkeypatch.setattr(click, "confirm", value=conf_false)
with pytest.raises(SystemExit) as pytest_exit:
revocation.save_doc(path, rev_1.signed_raw(), pubkey)
assert pytest_exit.type == SystemExit
assert pytest_exit.value.code == SUCCESS_EXIT_STATUS
expected_confirm = "Ok, goodbye!"
assert expected_confirm in capsys.readouterr().out
assert path.read_text(encoding="utf-8") == rev_2.signed_raw()
# test verify_document
@pytest.mark.parametrize(
("doc", "lookup"),
[
(REV_DOC, lookup_one),
(REV_DOC, lookup_two),
],
)
def test_verify_document(doc, lookup, capsys, monkeypatch):
def patched_lookup(node, id_pubkey):
return lookup
# prepare test
path = Path("test_file.txt")
monkeypatch.setattr(bma.wot, "lookup", patched_lookup)
# test
runner = CliRunner()
with runner.isolated_filesystem():
path.write_text(doc.signed_raw(), encoding="utf-8")
result = revocation.verify_document(path)
display = capsys.readouterr().out
if len(lookup["results"]) > 1:
assert "One matching identity!\n" in display
assert "Similar identities:" in display
assert result == doc
# test verify_document: no matching identity
@pytest.mark.parametrize(
("doc", "lookup"),
[
(REV_2, lookup_one),
(REV_2, lookup_two),
(REV_2, False),
],
)
def test_verify_document_missing_id(doc, lookup, capsys, monkeypatch):
def patched_lookup(node, id_pubkey):
if not lookup:
http_error = urllib.error.HTTPError(
url="this.is/a/test/url",
code=2001,
msg="No matching identity",
hdrs={},
fp=None,
)
raise http_error
return lookup
# prepare test
path = Path("test_file.txt")
monkeypatch.setattr(bma.wot, "lookup", patched_lookup)
# test
runner = CliRunner()
with runner.isolated_filesystem():
path.write_text(doc.signed_raw(), encoding="utf-8")
with pytest.raises(SystemExit) as pytest_exit:
revocation.verify_document(path)
assert pytest_exit.type == SystemExit
display = capsys.readouterr().out
if not lookup:
assert "Revocation document does not match any valid identity." in str(
pytest_exit.value.code,
)
else:
assert pytest_exit.value.code == FAILURE_EXIT_STATUS
assert (
"Revocation document does not match any valid identity.\nSimilar identities:"
in display
)
# test verify_document : format and sign errors
@pytest.mark.parametrize(
("doc", "currency"),
[
(REV_DOC_FALSE, REV_DOC_FALSE.currency),
(REV_2_FALSE, REV_2_FALSE.currency),
(WRONG_FORMAT_REV, "g1-test"),
],
)
def test_verify_document_sign_errors(doc, currency, monkeypatch):
# prepare test
file = Path("test_file.txt")
patched_lookup = Mock()
monkeypatch.setattr(bma.wot, "lookup", patched_lookup)
# test
runner = CliRunner()
with runner.isolated_filesystem():
if isinstance(doc, str):
file.write_text(doc, encoding="utf-8")
elif isinstance(doc, Revocation):
file.write_text(doc.signed_raw(), encoding="utf-8")
with pytest.raises(SystemExit) as pytest_exit:
revocation.verify_document(file)
assert pytest_exit.type == SystemExit
if isinstance(doc, str):
assert (
"is not a revocation document, or is not correctly formatted."
in pytest_exit.value.code
)
elif isinstance(doc, Revocation):
assert (
pytest_exit.value.code
== "Error: the signature of the revocation document is invalid."
)
patched_lookup.assert_not_called()