From bbd8424995188238f9f60aaf86d9d33ca52034c5 Mon Sep 17 00:00:00 2001 From: Inso <insomniak.fr@gmail.com> Date: Sun, 6 Sep 2015 17:04:14 +0200 Subject: [PATCH] Certification in empty community --- src/cutecoin/core/net/api/bma/access.py | 2 - src/cutecoin/gui/certification.py | 33 +++- src/cutecoin/gui/community_view.py | 3 +- src/cutecoin/tests/certification/__init__.py | 0 .../tests/certification/test_certification.py | 97 ++++++++++++ .../tests/mocks/bma/init_new_community.py | 146 ++++++++++++++++++ .../tests/mocks/bma/new_blockchain.py | 4 +- 7 files changed, 275 insertions(+), 10 deletions(-) create mode 100644 src/cutecoin/tests/certification/__init__.py create mode 100644 src/cutecoin/tests/certification/test_certification.py create mode 100644 src/cutecoin/tests/mocks/bma/init_new_community.py diff --git a/src/cutecoin/core/net/api/bma/access.py b/src/cutecoin/core/net/api/bma/access.py index a813a2d5..c6e766a0 100644 --- a/src/cutecoin/core/net/api/bma/access.py +++ b/src/cutecoin/core/net/api/bma/access.py @@ -157,8 +157,6 @@ class BmaAccess(QObject): cache_key = BmaAccess._gen_cache_key(request, req_args, get_args) if need_reload: - # Move to network nstead of community - # after removing qthreads if cache_key in self._pending_requests: if caller not in self._pending_requests[cache_key]: logging.debug("New caller".format(caller)) diff --git a/src/cutecoin/gui/certification.py b/src/cutecoin/gui/certification.py index ca55ef33..23201927 100644 --- a/src/cutecoin/gui/certification.py +++ b/src/cutecoin/gui/certification.py @@ -5,10 +5,11 @@ Created on 24 dec. 2014 """ from PyQt5.QtWidgets import QDialog, QMessageBox, QDialogButtonBox, QApplication from PyQt5.QtCore import Qt, pyqtSlot -import quamash from ..gen_resources.certification_uic import Ui_CertificationDialog from . import toast +from ..core.net.api import bma as qtbma import asyncio +import logging class CertificationDialog(QDialog, Ui_CertificationDialog): @@ -63,17 +64,33 @@ class CertificationDialog(QDialog, Ui_CertificationDialog): def handle_error(self, error_code, text): if self.app.preferences['notifications']: toast.display(self.tr("Error"), self.tr("{0} : {1}".format(error_code, text))) - else: - QMessageBox.Critical(self, self.tr("Error", self.tr("{0} : {1}".format(error_code, text)))) + #else: + # QMessageBox.Critical(self, self.tr("Error", self.tr("{0} : {1}".format(error_code, text)))) self.account.certification_broadcasted.disconnect() self.account.broadcast_error.disconnect(self.handle_error) QApplication.restoreOverrideCursor() + def handle_community_data_change(self, request): + if request == qtbma.blockchain.Block: + self.refresh() + def change_current_community(self, index): + try: + self.community.inner_data_changed.disconnect(self.handle_community_data_change) + except TypeError as e: + if 'connect' in str(e): + logging.debug("Error when disconnecting community") + else: + raise self.community = self.account.communities[index] - if self.account.pubkey in self.community.members_pubkeys(): + self.community.inner_data_changed.connect(self.handle_community_data_change) + self.refresh() + + def refresh(self): + if self.account.pubkey in self.community.members_pubkeys() \ + or self.community.get_block(0) == qtbma.blockchain.Block.null_value: self.button_box.button(QDialogButtonBox.Ok).setEnabled(True) - self.button_box.button(QDialogButtonBox.Ok).setText(self.tr("Ok")) + self.button_box.button(QDialogButtonBox.Ok).setText(self.tr("&Ok")) else: self.button_box.button(QDialogButtonBox.Ok).setEnabled(False) self.button_box.button(QDialogButtonBox.Ok).setText(self.tr("Not a member")) @@ -81,3 +98,9 @@ class CertificationDialog(QDialog, Ui_CertificationDialog): def recipient_mode_changed(self, pubkey_toggled): self.edit_pubkey.setEnabled(pubkey_toggled) self.combo_contact.setEnabled(not pubkey_toggled) + + def async_exec(self): + future = asyncio.Future() + self.finished.connect(lambda r: future.set_result(r)) + self.open() + return future \ No newline at end of file diff --git a/src/cutecoin/gui/community_view.py b/src/cutecoin/gui/community_view.py index de3563c1..127c8326 100644 --- a/src/cutecoin/gui/community_view.py +++ b/src/cutecoin/gui/community_view.py @@ -195,7 +195,8 @@ class CommunityWidget(QWidget, Ui_CommunityWidget): logging.debug("Not a member") self.button_membership.setText(self.tr("Send membership demand")) self.button_membership.show() - self.button_certification.hide() + if self.community.get_block(0) != qtbma.blockchain.Block.null_value: + self.button_certification.hide() else: logging.debug("UID not published") self.button_membership.hide() diff --git a/src/cutecoin/tests/certification/__init__.py b/src/cutecoin/tests/certification/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/cutecoin/tests/certification/test_certification.py b/src/cutecoin/tests/certification/test_certification.py new file mode 100644 index 00000000..0dd7d189 --- /dev/null +++ b/src/cutecoin/tests/certification/test_certification.py @@ -0,0 +1,97 @@ +import sys +import unittest +import asyncio +import quamash +import time +import logging +from ucoinpy.documents.peer import BMAEndpoint as PyBMAEndpoint +from PyQt5.QtWidgets import QDialog, QDialogButtonBox +from PyQt5.QtCore import QLocale, Qt +from PyQt5.QtTest import QTest +from cutecoin.tests.mocks.bma import init_new_community +from cutecoin.tests.mocks.access_manager import MockNetworkAccessManager +from cutecoin.core.registry.identities import IdentitiesRegistry +from cutecoin.gui.certification import CertificationDialog +from cutecoin.gui.password_asker import PasswordAskerDialog +from cutecoin.core.app import Application +from cutecoin.core import Account, Community, Wallet +from cutecoin.core.net import Network, Node +from cutecoin.core.net.endpoint import BMAEndpoint +from cutecoin.core.net.api.bma.access import BmaAccess +from cutecoin.tests import get_application +from cutecoin.core.net.api import bma as qtbma + + +class TestCertificationDialog(unittest.TestCase): + def setUp(self): + self.qapplication = get_application() + self.network_manager = MockNetworkAccessManager() + QLocale.setDefault(QLocale("en_GB")) + self.lp = quamash.QEventLoop(self.qapplication) + asyncio.set_event_loop(self.lp) + self.identities_registry = IdentitiesRegistry() + + self.application = Application(self.qapplication, self.lp, self.network_manager, self.identities_registry) + self.application.preferences['notifications'] = False + + self.endpoint = BMAEndpoint(PyBMAEndpoint("", "127.0.0.1", "", 50000)) + self.node = Node(self.network_manager, "test_currency", [self.endpoint], + "", "HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk", + qtbma.blockchain.Block.null_value, Node.ONLINE, + time.time(), {}, "ucoin", "0.14.0", 0) + self.network = Network.create(self.network_manager, self.node) + self.bma_access = BmaAccess.create(self.network) + self.community = Community("test_currency", self.network, self.bma_access) + + self.wallet = Wallet(0, "7Aqw6Efa9EzE7gtsc8SveLLrM7gm6NEGoywSv4FJx6pZ", + "Wallet 1", self.identities_registry) + + # Salt/password : "testcutecoin/testcutecoin" + # Pubkey : 7Aqw6Efa9EzE7gtsc8SveLLrM7gm6NEGoywSv4FJx6pZ + self.account = Account("testcutecoin", "7Aqw6Efa9EzE7gtsc8SveLLrM7gm6NEGoywSv4FJx6pZ", + "john", [self.community], [self.wallet], [], self.identities_registry) + + self.password_asker = PasswordAskerDialog(self.account) + self.password_asker.password = "testcutecoin" + self.password_asker.remember = True + + def tearDown(self): + try: + self.lp.close() + finally: + asyncio.set_event_loop(None) + + def test_certification_init_community(self): + certification_dialog = CertificationDialog(self.application, + self.account, + self.password_asker) + + @asyncio.coroutine + def open_dialog(certification_dialog): + result = yield from certification_dialog.async_exec() + self.assertEqual(result, QDialog.Accepted) + + def close_dialog(): + if certification_dialog.isVisible(): + certification_dialog.close() + + @asyncio.coroutine + def exec_test(): + mock = init_new_community.get_mock() + logging.debug(mock.pretend_url) + yield from asyncio.sleep(1) + self.network_manager.set_mock_path(mock.pretend_url) + self.assertEqual(certification_dialog.button_box.button(QDialogButtonBox.Ok).text(), "&Ok") + QTest.mouseClick(certification_dialog.radio_pubkey, Qt.LeftButton) + QTest.keyClicks(certification_dialog.edit_pubkey, "FADxcH5LmXGmGFgdixSes6nWnC4Vb4pRUBYT81zQRhjn") + QTest.mouseClick(certification_dialog.button_box.button(QDialogButtonBox.Ok), Qt.LeftButton) + + self.lp.call_later(15, close_dialog) + asyncio.async(exec_test()) + self.lp.run_until_complete(open_dialog(certification_dialog)) + + +if __name__ == '__main__': + logging.basicConfig(stream=sys.stderr) + logging.getLogger().setLevel(logging.DEBUG) + unittest.main() diff --git a/src/cutecoin/tests/mocks/bma/init_new_community.py b/src/cutecoin/tests/mocks/bma/init_new_community.py new file mode 100644 index 00000000..cb4700e3 --- /dev/null +++ b/src/cutecoin/tests/mocks/bma/init_new_community.py @@ -0,0 +1,146 @@ +from pretenders.client.http import HTTPMock +from pretenders.common.constants import FOREVER + +bma_peering = b"""{ + "version": 1, + "currency": "test_currency", + "endpoints": [ + "BASIC_MERKLED_API localhost 127.0.0.1 50000" + ], + "status": "UP", + "block": "30152-00003E7F9234E7542FCF669B69B0F84FF79CCCD3", + "signature": "cXuqZuDfyHvxYAEUkPH1TQ1M+8YNDpj8kiHGYi3LIaMqEdVqwVc4yQYGivjxFMYyngRfxXkyvqBKZA6rKOulCA==", + "raw": "Version: 1\\nType: Peer\\nCurrency: meta_brouzouf\\nPublicKey: HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk\\nBlock: 30152-00003E7F9234E7542FCF669B69B0F84FF79CCCD3\\nEndpoints:\\nBASIC_MERKLED_API localhost 127.0.0.1 50000\\n", + "pubkey": "HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk" +}""" + +bma_lookup_test_john = b"""{ + "partial": false, + "results": [ + { + "pubkey": "7Aqw6Efa9EzE7gtsc8SveLLrM7gm6NEGoywSv4FJx6pZ", + "uids": [ + { + "uid": "john", + "meta": { + "timestamp": 1441130831 + }, + "self": "ZrHK0cCqrxWReROK0ciiSb45+dRphJa68qFaSjdve8bBdnGAu7+DIu0d+u/fXrNRXuObihOKMBIawaIVPNHqDw==", + "others": [] + } + ], + "signed": [] + } + ] +}""" + +bma_lookup_test_doe = b"""{ + "partial": false, + "results": [ + { + "pubkey": "FADxcH5LmXGmGFgdixSes6nWnC4Vb4pRUBYT81zQRhjn", + "uids": [ + { + "uid": "doe", + "meta": { + "timestamp": 1441130831 + }, + "self": "cIkHPQQ5+xTb4cKWv85rcYcZT+E3GDtX8B2nCK9Vs12p2Yz4bVaZiMvBBwisAAy2WBOaqHS3ydpXGtADchOICw==", + "others": [] + } + ], + "signed": [] + } + ] +}""" + +bma_lookup_test_patrick = b"""{ + "partial": false, + "results": [ + { + "pubkey": "FADxcH5LmXGmGFgdixSes6nWnC4Vb4pRUBYT81zQRhjn", + "uids": [ + { + "uid": "patrick", + "meta": { + "timestamp": 1441130831 + }, + "self": "QNX2HDAxcHawc47TnMqb5/ou2lwa+zYOyeNk0a52dQDJX/NWmeTzGfTjdCtjpXmSCuPSg0F1mOnLQVd60xAzDA==", + "others": [] + } + ], + "signed": [] + } + ] +}""" + + +def get_mock(): + mock = HTTPMock('127.0.0.1', 50000) + + mock.when('GET /network/peering')\ + .reply(body=bma_peering, + times=FOREVER, + headers={'Content-Type': 'application/json'}) + + mock.when('GET /blockchain/block/0')\ + .reply(body=b"Block not found", + status=404, + times=FOREVER, + headers={'Content-Type': 'application/json'}) + + mock.when('GET /blockchain/current')\ + .reply(body=b"Block not found", + status=404, + times=FOREVER, + headers={'Content-Type': 'application/json'}) + + mock.when('GET /wot/certifiers-of/7Aqw6Efa9EzE7gtsc8SveLLrM7gm6NEGoywSv4FJx6pZ')\ + .reply(body=b"No member matching this pubkey or uid", + status=404, + times=1, + headers={'Content-Type': 'application/json'}) + + mock.when('GET /wot/lookup/john')\ + .reply(body=bma_lookup_test_john, + status=200, + times=1, + headers={'Content-Type': 'application/json'}) + + mock.when('GET /wot/lookup/7Aqw6Efa9EzE7gtsc8SveLLrM7gm6NEGoywSv4FJx6pZ')\ + .reply(body=bma_lookup_test_john, + status=200, + times=1, + headers={'Content-Type': 'application/json'}) + + mock.when('GET /wot/lookup/doe')\ + .reply(body=bma_lookup_test_doe, + status=200, + times=1, + headers={'Content-Type': 'application/json'}) + + mock.when('GET /wot/lookup/FADxcH5LmXGmGFgdixSes6nWnC4Vb4pRUBYT81zQRhjn')\ + .reply(body=bma_lookup_test_doe, + status=200, + times=1, + headers={'Content-Type': 'application/json'}) + + mock.when('GET /wot/lookup/patrick')\ + .reply(body=bma_lookup_test_patrick, + status=200, + times=1, + headers={'Content-Type': 'application/json'}) + + mock.when('GET /wot/lookup/FADxcH5LmXGmGFgdixSes6nWnC4Vb4pRUBYT81zQRhjn')\ + .reply(body=bma_lookup_test_patrick, + status=200, + times=1, + headers={'Content-Type': 'application/json'}) + + mock.when('POST /wot/add.*')\ + .reply(body=b"{}", + status=200, + times=FOREVER, + headers={'Content-Type': 'application/json'}) + + return mock diff --git a/src/cutecoin/tests/mocks/bma/new_blockchain.py b/src/cutecoin/tests/mocks/bma/new_blockchain.py index 71f2932b..fe43d5d2 100644 --- a/src/cutecoin/tests/mocks/bma/new_blockchain.py +++ b/src/cutecoin/tests/mocks/bma/new_blockchain.py @@ -3,7 +3,7 @@ from pretenders.common.constants import FOREVER bma_peering = b"""{ "version": 1, - "currency": "meta_brouzouf", + "currency": "test_currency", "endpoints": [ "BASIC_MERKLED_API localhost 127.0.0.1 50000" ], @@ -37,7 +37,7 @@ def get_mock(): times=FOREVER, headers={'Content-Type': 'application/json'}) - mock.when('GET /blockchain/Block/0')\ + mock.when('GET /blockchain/block/0')\ .reply(body=b"Block not found", status=404, times=FOREVER, -- GitLab