From 6fdcaf44a7439f157213087bc0fcc1611335ab9a Mon Sep 17 00:00:00 2001 From: codegeschrei Date: Mon, 27 Aug 2018 09:48:20 +0200 Subject: [PATCH 1/3] Problem: we have unused and outdated fixtures (#2476) * Problem: we have unused and outdated fixtures Solution: clean up fixtures and tests accordingly --- tests/backend/localmongodb/test_connection.py | 8 +- tests/backend/localmongodb/test_queries.py | 2 +- tests/commands/conftest.py | 4 +- tests/commands/test_commands.py | 11 +-- tests/conftest.py | 99 +------------------ tests/tendermint/conftest.py | 6 -- tests/tendermint/test_integration.py | 3 +- tests/tendermint/test_lib.py | 45 +++++---- tests/test_config_utils.py | 2 +- tests/test_core.py | 1 - tests/web/test_assets.py | 9 +- tests/web/test_block_tendermint.py | 6 +- tests/web/test_metadata.py | 8 +- tests/web/test_parameters.py | 2 + tests/web/test_server.py | 4 + tests/web/test_validators.py | 2 +- tests/web/test_websocket_server.py | 3 +- 17 files changed, 49 insertions(+), 166 deletions(-) diff --git a/tests/backend/localmongodb/test_connection.py b/tests/backend/localmongodb/test_connection.py index a76f5b85..77692abe 100644 --- a/tests/backend/localmongodb/test_connection.py +++ b/tests/backend/localmongodb/test_connection.py @@ -55,10 +55,8 @@ def test_get_connection_returns_the_correct_instance(db_host, db_port): assert conn.conn._topology_settings.replica_set_name == config['replicaset'] -@mock.patch('bigchaindb.backend.localmongodb.connection.initialize_replica_set') @mock.patch('pymongo.MongoClient.__init__') -@mock.patch('time.sleep') -def test_connection_error(mock_sleep, mock_client, mock_init_repl_set): +def test_connection_error(mock_client): from bigchaindb.backend import connect from bigchaindb.backend.exceptions import ConnectionError @@ -74,9 +72,7 @@ def test_connection_error(mock_sleep, mock_client, mock_init_repl_set): assert mock_client.call_count == 3 -@mock.patch('bigchaindb.backend.localmongodb.connection.initialize_replica_set') -@mock.patch('pymongo.MongoClient') -def test_connection_run_errors(mock_client, mock_init_repl_set): +def test_connection_run_errors(): from bigchaindb.backend import connect from bigchaindb.backend.exceptions import (DuplicateKeyError, OperationError, diff --git a/tests/backend/localmongodb/test_queries.py b/tests/backend/localmongodb/test_queries.py index 4d1d7bdf..363d02a1 100644 --- a/tests/backend/localmongodb/test_queries.py +++ b/tests/backend/localmongodb/test_queries.py @@ -7,7 +7,7 @@ from copy import deepcopy import pytest import pymongo -pytestmark = [pytest.mark.tendermint, pytest.mark.localmongodb, pytest.mark.bdb] +pytestmark = [pytest.mark.tendermint, pytest.mark.bdb] def test_get_txids_filtered(signed_create_tx, signed_transfer_tx): diff --git a/tests/commands/conftest.py b/tests/commands/conftest.py index 025d5708..ce09ff24 100644 --- a/tests/commands/conftest.py +++ b/tests/commands/conftest.py @@ -27,8 +27,8 @@ def mock_db_init_with_existing_db(monkeypatch): @pytest.fixture def mock_processes_start(monkeypatch): - from bigchaindb import processes - monkeypatch.setattr(processes, 'start', lambda *args: None) + from bigchaindb.utils import Process + monkeypatch.setattr(Process, 'run', lambda *args: None) @pytest.fixture diff --git a/tests/commands/test_commands.py b/tests/commands/test_commands.py index 8d7b0725..5e2bd31e 100644 --- a/tests/commands/test_commands.py +++ b/tests/commands/test_commands.py @@ -185,7 +185,7 @@ def test_run_configure_when_config_does_exist(monkeypatch, mock_bigchaindb_backup_config): value = {} - def mock_write_config(newconfig, filename=None): + def mock_write_config(newconfig): value['return'] = newconfig from bigchaindb.commands.bigchaindb import run_configure @@ -250,11 +250,8 @@ def test_run_start_when_db_already_exists(mocker, @pytest.mark.tendermint -@patch('argparse.ArgumentParser.parse_args') -@patch('bigchaindb.commands.utils.base_parser') @patch('bigchaindb.commands.utils.start') -def test_calling_main(start_mock, base_parser_mock, parse_args_mock, - monkeypatch): +def test_calling_main(start_mock, monkeypatch): from bigchaindb.commands.bigchaindb import main argparser_mock = Mock() @@ -283,11 +280,9 @@ def test_calling_main(start_mock, base_parser_mock, parse_args_mock, assert start_mock.called is True -@patch('bigchaindb.config_utils.autoconfigure') @patch('bigchaindb.commands.bigchaindb.run_recover') @patch('bigchaindb.start.start') -def test_recover_db_on_start(mock_autoconfigure, - mock_run_recover, +def test_recover_db_on_start(mock_run_recover, mock_start, mocked_setup_logging): from bigchaindb.commands.bigchaindb import run_start diff --git a/tests/conftest.py b/tests/conftest.py index 8c36f539..0fd4d671 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -37,13 +37,6 @@ USER_PRIVATE_KEY = '8eJ8q9ZQpReWyQT5aFCiwtZ5wDZC4eDnCen88p3tQ6ie' USER_PUBLIC_KEY = 'JEAkEJqLbbgDRAtMm8YAjGp759Aq2qTn9eaEHUj2XePE' -def pytest_runtest_setup(item): - if isinstance(item, item.Function): - backend = item.session.config.getoption('--database-backend') - if (item.get_marker('localmongodb') and backend != 'localmongodb'): - pytest.skip('Skip tendermint specific tests if not using localmongodb') - - def pytest_addoption(parser): from bigchaindb.backend.connection import BACKENDS @@ -56,19 +49,6 @@ def pytest_addoption(parser): ) -def pytest_ignore_collect(path, config): - from bigchaindb.backend.connection import BACKENDS - path = str(path) - - supported_backends = BACKENDS.keys() - - if os.path.isdir(path): - dirname = os.path.split(path)[1] - if dirname in supported_backends and dirname != config.getoption('--database-backend'): - print('Ignoring unrequested backend test dir: ', path) - return True - - def pytest_configure(config): config.addinivalue_line( 'markers', @@ -266,28 +246,12 @@ def merlin(): return generate_key_pair() -@pytest.fixture -def merlin_privkey(merlin): - return merlin.private_key - - -@pytest.fixture -def merlin_pubkey(merlin): - return merlin.public_key - - @pytest.fixture def b(): from bigchaindb import BigchainDB return BigchainDB() -@pytest.fixture -def tb(): - from bigchaindb import BigchainDB - return BigchainDB() - - @pytest.fixture def create_tx(alice, user_pk): from bigchaindb.models import Transaction @@ -349,24 +313,6 @@ def inputs(user_pk, b, alice): b.store_bulk_transactions(transactions) -@pytest.fixture -def inputs_shared(user_pk, user2_pk, alice): - from bigchaindb.models import Transaction - - # create blocks with transactions for `USER` to spend - for block in range(4): - transactions = [ - Transaction.create( - [alice.public_key], - [user_pk, user2_pk], - metadata={'msg': random.random()}, - ).sign([alice.private_key]).to_dict() - for _ in range(10) - ] - block = Block(app_hash='', height=_get_height(b), transaction=transactions) - b.store_block(block._asdict()) - - @pytest.fixture def dummy_db(request): from bigchaindb.backend import connect, schema @@ -389,26 +335,6 @@ def dummy_db(request): pass -@pytest.fixture -def not_yet_created_db(request): - from bigchaindb.backend import connect, schema - from bigchaindb.common.exceptions import DatabaseDoesNotExist - conn = connect() - dbname = request.fixturename - xdist_suffix = getattr(request.config, 'slaveinput', {}).get('slaveid') - if xdist_suffix: - dbname = '{}_{}'.format(dbname, xdist_suffix) - try: - schema.drop_database(conn, dbname) - except DatabaseDoesNotExist: - pass - yield dbname - try: - schema.drop_database(conn, dbname) - except DatabaseDoesNotExist: - pass - - @pytest.fixture def db_config(): from bigchaindb import config @@ -464,29 +390,6 @@ def tendermint_ws_url(tendermint_host, tendermint_port): return 'ws://{}:{}/websocket'.format(tendermint_host, tendermint_port) -@pytest.fixture -def tendermint_context(tendermint_host, tendermint_port, tendermint_ws_url): - TendermintContext = namedtuple( - 'TendermintContext', ('host', 'port', 'ws_url')) - return TendermintContext( - host=tendermint_host, - port=tendermint_port, - ws_url=tendermint_ws_url, - ) - - -@pytest.fixture -def mocked_setup_pub_logger(mocker): - return mocker.patch( - 'bigchaindb.log.setup.setup_pub_logger', autospec=True, spec_set=True) - - -@pytest.fixture -def mocked_setup_sub_logger(mocker): - return mocker.patch( - 'bigchaindb.log.setup.setup_sub_logger', autospec=True, spec_set=True) - - @pytest.fixture(autouse=True) def _abci_http(request): if request.keywords.get('abci', None): @@ -513,7 +416,7 @@ def abci_http(_setup_database, _configure_bigchaindb, abci_server, @pytest.yield_fixture(scope='session') -def event_loop(request): +def event_loop(): import asyncio loop = asyncio.get_event_loop_policy().new_event_loop() diff --git a/tests/tendermint/conftest.py b/tests/tendermint/conftest.py index 22dec41c..8efa8e76 100644 --- a/tests/tendermint/conftest.py +++ b/tests/tendermint/conftest.py @@ -8,12 +8,6 @@ import codecs import abci.types_pb2 as types -@pytest.fixture -def b(): - from bigchaindb import BigchainDB - return BigchainDB() - - @pytest.fixture def validator_pub_key(): return 'B0E42D2589A455EAD339A035D6CE1C8C3E25863F268120AA0162AD7D003A4014' diff --git a/tests/tendermint/test_integration.py b/tests/tendermint/test_integration.py index 1a8250bd..683404bc 100644 --- a/tests/tendermint/test_integration.py +++ b/tests/tendermint/test_integration.py @@ -16,13 +16,12 @@ from io import BytesIO @pytest.mark.tendermint @pytest.mark.bdb -def test_app(tb, init_chain_request): +def test_app(b, init_chain_request): from bigchaindb import App from bigchaindb.tendermint_utils import calculate_hash from bigchaindb.common.crypto import generate_key_pair from bigchaindb.models import Transaction - b = tb app = App(b) p = ProtocolHandler(app) diff --git a/tests/tendermint/test_lib.py b/tests/tendermint/test_lib.py index cc511b3a..d8223a25 100644 --- a/tests/tendermint/test_lib.py +++ b/tests/tendermint/test_lib.py @@ -57,10 +57,9 @@ def test_asset_is_separated_from_transaciton(b): @pytest.mark.bdb -def test_get_latest_block(tb): +def test_get_latest_block(b): from bigchaindb.lib import Block - b = tb for i in range(10): app_hash = os.urandom(16).hex() txn_id = os.urandom(16).hex() @@ -75,8 +74,8 @@ def test_get_latest_block(tb): @pytest.mark.bdb @patch('bigchaindb.backend.query.get_block', return_value=None) @patch('bigchaindb.BigchainDB.get_latest_block', return_value={'height': 10}) -def test_get_empty_block(_0, _1, tb): - assert tb.get_block(5) == {'height': 5, 'transactions': []} +def test_get_empty_block(_0, _1, b): + assert b.get_block(5) == {'height': 5, 'transactions': []} def test_validation_error(b): @@ -172,15 +171,15 @@ def test_validator_updates(b, validator_pub_key): @pytest.mark.bdb -def test_update_utxoset(tb, signed_create_tx, signed_transfer_tx, db_context): +def test_update_utxoset(b, signed_create_tx, signed_transfer_tx, db_context): mongo_client = MongoClient(host=db_context.host, port=db_context.port) - tb.update_utxoset(signed_create_tx) + b.update_utxoset(signed_create_tx) utxoset = mongo_client[db_context.name]['utxos'] assert utxoset.count() == 1 utxo = utxoset.find_one() assert utxo['transaction_id'] == signed_create_tx.id assert utxo['output_index'] == 0 - tb.update_utxoset(signed_transfer_tx) + b.update_utxoset(signed_transfer_tx) assert utxoset.count() == 1 utxo = utxoset.find_one() assert utxo['transaction_id'] == signed_transfer_tx.id @@ -188,14 +187,14 @@ def test_update_utxoset(tb, signed_create_tx, signed_transfer_tx, db_context): @pytest.mark.bdb -def test_store_transaction(mocker, tb, signed_create_tx, +def test_store_transaction(mocker, b, signed_create_tx, signed_transfer_tx, db_context): mocked_store_asset = mocker.patch('bigchaindb.backend.query.store_assets') mocked_store_metadata = mocker.patch( 'bigchaindb.backend.query.store_metadatas') mocked_store_transaction = mocker.patch( 'bigchaindb.backend.query.store_transactions') - tb.store_bulk_transactions([signed_create_tx]) + b.store_bulk_transactions([signed_create_tx]) # mongo_client = MongoClient(host=db_context.host, port=db_context.port) # utxoset = mongo_client[db_context.name]['utxos'] # assert utxoset.count() == 1 @@ -204,40 +203,40 @@ def test_store_transaction(mocker, tb, signed_create_tx, # assert utxo['output_index'] == 0 mocked_store_asset.assert_called_once_with( - tb.connection, + b.connection, [{'id': signed_create_tx.id, 'data': signed_create_tx.asset['data']}], ) mocked_store_metadata.assert_called_once_with( - tb.connection, + b.connection, [{'id': signed_create_tx.id, 'metadata': signed_create_tx.metadata}], ) mocked_store_transaction.assert_called_once_with( - tb.connection, + b.connection, [{k: v for k, v in signed_create_tx.to_dict().items() if k not in ('asset', 'metadata')}], ) mocked_store_asset.reset_mock() mocked_store_metadata.reset_mock() mocked_store_transaction.reset_mock() - tb.store_bulk_transactions([signed_transfer_tx]) + b.store_bulk_transactions([signed_transfer_tx]) # assert utxoset.count() == 1 # utxo = utxoset.find_one() # assert utxo['transaction_id'] == signed_transfer_tx.id # assert utxo['output_index'] == 0 assert not mocked_store_asset.called mocked_store_metadata.asser_called_once_with( - tb.connection, + b.connection, [{'id': signed_transfer_tx.id, 'metadata': signed_transfer_tx.metadata}], ) mocked_store_transaction.assert_called_once_with( - tb.connection, + b.connection, [{k: v for k, v in signed_transfer_tx.to_dict().items() if k != 'metadata'}], ) @pytest.mark.bdb -def test_store_bulk_transaction(mocker, tb, signed_create_tx, +def test_store_bulk_transaction(mocker, b, signed_create_tx, signed_transfer_tx, db_context): mocked_store_assets = mocker.patch( 'bigchaindb.backend.query.store_assets') @@ -245,7 +244,7 @@ def test_store_bulk_transaction(mocker, tb, signed_create_tx, 'bigchaindb.backend.query.store_metadatas') mocked_store_transactions = mocker.patch( 'bigchaindb.backend.query.store_transactions') - tb.store_bulk_transactions((signed_create_tx,)) + b.store_bulk_transactions((signed_create_tx,)) # mongo_client = MongoClient(host=db_context.host, port=db_context.port) # utxoset = mongo_client[db_context.name]['utxos'] # assert utxoset.count() == 1 @@ -253,34 +252,34 @@ def test_store_bulk_transaction(mocker, tb, signed_create_tx, # assert utxo['transaction_id'] == signed_create_tx.id # assert utxo['output_index'] == 0 mocked_store_assets.assert_called_once_with( - tb.connection, + b.connection, [{'id': signed_create_tx.id, 'data': signed_create_tx.asset['data']}], ) mocked_store_metadata.assert_called_once_with( - tb.connection, + b.connection, [{'id': signed_create_tx.id, 'metadata': signed_create_tx.metadata}], ) mocked_store_transactions.assert_called_once_with( - tb.connection, + b.connection, [{k: v for k, v in signed_create_tx.to_dict().items() if k not in ('asset', 'metadata')}], ) mocked_store_assets.reset_mock() mocked_store_metadata.reset_mock() mocked_store_transactions.reset_mock() - tb.store_bulk_transactions((signed_transfer_tx,)) + b.store_bulk_transactions((signed_transfer_tx,)) # assert utxoset.count() == 1 # utxo = utxoset.find_one() # assert utxo['transaction_id'] == signed_transfer_tx.id # assert utxo['output_index'] == 0 assert not mocked_store_assets.called mocked_store_metadata.asser_called_once_with( - tb.connection, + b.connection, [{'id': signed_transfer_tx.id, 'metadata': signed_transfer_tx.metadata}], ) mocked_store_transactions.assert_called_once_with( - tb.connection, + b.connection, [{k: v for k, v in signed_transfer_tx.to_dict().items() if k != 'metadata'}], ) diff --git a/tests/test_config_utils.py b/tests/test_config_utils.py index 05a5ad83..35f0e486 100644 --- a/tests/test_config_utils.py +++ b/tests/test_config_utils.py @@ -24,7 +24,7 @@ def clean_config(monkeypatch, request): monkeypatch.setattr('bigchaindb.config', original_config) -def test_bigchain_instance_is_initialized_when_conf_provided(request): +def test_bigchain_instance_is_initialized_when_conf_provided(): import bigchaindb from bigchaindb import config_utils assert 'CONFIGURED' not in bigchaindb.config diff --git a/tests/test_core.py b/tests/test_core.py index 0e3a2f12..03701267 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -66,7 +66,6 @@ def test_bigchain_class_initialization_with_parameters(): assert bigchain.consensus == BaseConsensusRules -@pytest.mark.genesis def test_get_spent_issue_1271(b, alice, bob, carol): from bigchaindb.models import Transaction diff --git a/tests/web/test_assets.py b/tests/web/test_assets.py index 800537ba..2c658cdc 100644 --- a/tests/web/test_assets.py +++ b/tests/web/test_assets.py @@ -23,8 +23,7 @@ def test_get_assets_with_missing_text_search(client): @pytest.mark.bdb @pytest.mark.tendermint -@pytest.mark.localmongodb -def test_get_assets_tendermint(client, tb, alice): +def test_get_assets_tendermint(client, b, alice): from bigchaindb.models import Transaction # test returns empty list when no assets are found @@ -37,7 +36,7 @@ def test_get_assets_tendermint(client, tb, alice): tx = Transaction.create([alice.public_key], [([alice.public_key], 1)], asset=asset).sign([alice.private_key]) - tb.store_bulk_transactions([tx]) + b.store_bulk_transactions([tx]) # test that asset is returned res = client.get(ASSETS_ENDPOINT + '?search=abc') @@ -51,11 +50,9 @@ def test_get_assets_tendermint(client, tb, alice): @pytest.mark.bdb @pytest.mark.tendermint -@pytest.mark.localmongodb -def test_get_assets_limit_tendermint(client, tb, alice): +def test_get_assets_limit_tendermint(client, b, alice): from bigchaindb.models import Transaction - b = tb # create two assets asset1 = {'msg': 'abc 1'} asset2 = {'msg': 'abc 2'} diff --git a/tests/web/test_block_tendermint.py b/tests/web/test_block_tendermint.py index a726a117..a92822c4 100644 --- a/tests/web/test_block_tendermint.py +++ b/tests/web/test_block_tendermint.py @@ -14,9 +14,8 @@ pytestmark = pytest.mark.tendermint @pytest.mark.bdb @pytest.mark.usefixtures('inputs') -def test_get_block_endpoint(tb, client, alice): +def test_get_block_endpoint(b, client, alice): import copy - b = tb tx = Transaction.create([alice.public_key], [([alice.public_key], 1)], asset={'cycle': 'hero'}) tx = tx.sign([alice.private_key]) @@ -49,8 +48,7 @@ def test_get_block_returns_404_if_not_found(client): @pytest.mark.bdb -def test_get_block_containing_transaction(tb, client, alice): - b = tb +def test_get_block_containing_transaction(b, client, alice): tx = Transaction.create([alice.public_key], [([alice.public_key], 1)], asset={'cycle': 'hero'}) tx = tx.sign([alice.private_key]) b.store_bulk_transactions([tx]) diff --git a/tests/web/test_metadata.py b/tests/web/test_metadata.py index aa0a2382..248ef946 100644 --- a/tests/web/test_metadata.py +++ b/tests/web/test_metadata.py @@ -23,11 +23,9 @@ def test_get_metadata_with_missing_text_search(client): @pytest.mark.bdb @pytest.mark.tendermint -def test_get_metadata_tendermint(client, tb, alice): +def test_get_metadata_tendermint(client, b, alice): from bigchaindb.models import Transaction - b = tb - # test returns empty list when no assets are found res = client.get(METADATA_ENDPOINT + '?search=abc') assert res.json == [] @@ -53,11 +51,9 @@ def test_get_metadata_tendermint(client, tb, alice): @pytest.mark.bdb @pytest.mark.tendermint -def test_get_metadata_limit_tendermint(client, tb, alice): +def test_get_metadata_limit_tendermint(client, b, alice): from bigchaindb.models import Transaction - b = tb - # create two assets asset1 = {'msg': 'abc 1'} meta1 = {'key': 'meta 1'} diff --git a/tests/web/test_parameters.py b/tests/web/test_parameters.py index ccf3119b..3eb8ab2a 100644 --- a/tests/web/test_parameters.py +++ b/tests/web/test_parameters.py @@ -4,6 +4,8 @@ import pytest +pytestmark = pytest.mark.tendermint + def test_valid_txid(): from bigchaindb.web.views.parameters import valid_txid diff --git a/tests/web/test_server.py b/tests/web/test_server.py index 215aa980..5fce3629 100644 --- a/tests/web/test_server.py +++ b/tests/web/test_server.py @@ -2,6 +2,10 @@ # SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0) # Code is Apache-2.0 and docs are CC-BY-4.0 +import pytest + +pytestmark = pytest.mark.tendermint + def test_settings(): import bigchaindb diff --git a/tests/web/test_validators.py b/tests/web/test_validators.py index d26d8cf1..714ceee4 100644 --- a/tests/web/test_validators.py +++ b/tests/web/test_validators.py @@ -9,7 +9,7 @@ pytestmark = pytest.mark.tendermint VALIDATORS_ENDPOINT = '/api/v1/validators/' -def test_get_validators_endpoint(b, client, monkeypatch): +def test_get_validators_endpoint(b, client): validator_set = [{'address': 'F5426F0980E36E03044F74DD414248D29ABCBDB2', 'pub_key': {'data': '4E2685D9016126864733225BE00F005515200727FBAB1312FC78C8B76831255A', 'type': 'ed25519'}, diff --git a/tests/web/test_websocket_server.py b/tests/web/test_websocket_server.py index 64309137..1a2b55af 100644 --- a/tests/web/test_websocket_server.py +++ b/tests/web/test_websocket_server.py @@ -136,7 +136,6 @@ def test_websocket_block_event(b, test_client, loop): @pytest.mark.skip('Processes are not stopping properly, and the whole test suite would hang') -@pytest.mark.genesis def test_integration_from_webapi_to_websocket(monkeypatch, client, loop): # XXX: I think that the `pytest-aiohttp` plugin is sparkling too much # magic in the `asyncio` module: running this test without monkey-patching @@ -152,6 +151,8 @@ def test_integration_from_webapi_to_websocket(monkeypatch, client, loop): import aiohttp from bigchaindb.common import crypto + # TODO processes does not exist anymore, when reactivating this test it + # will fail because of this from bigchaindb import processes from bigchaindb.models import Transaction From 41a2687b9be14165b31dec1e8a0cb067bb202b8e Mon Sep 17 00:00:00 2001 From: vrde Date: Mon, 27 Aug 2018 15:00:02 +0200 Subject: [PATCH 2/3] Problem: websocket fails with ELECTION transaction (#2482) Solution: have a more general approach to process transaction types. If a transaction does *not* contain `asset.id`, then the `id` of the `asset` is the `id` of the transaction. --- bigchaindb/web/websocket_server.py | 24 ++++++++++++++---------- tests/web/test_websocket_server.py | 27 +++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 10 deletions(-) diff --git a/bigchaindb/web/websocket_server.py b/bigchaindb/web/websocket_server.py index 8aea0e20..f0a9f886 100644 --- a/bigchaindb/web/websocket_server.py +++ b/bigchaindb/web/websocket_server.py @@ -48,6 +48,17 @@ def _multiprocessing_to_asyncio(in_queue, out_queue, loop): loop.call_soon_threadsafe(out_queue.put_nowait, value) +def eventify_block(block): + for tx in block['transactions']: + try: + asset_id = tx['asset']['id'] + except KeyError: + asset_id = tx['id'] + yield {'height': block['height'], + 'asset_id': asset_id, + 'transaction_id': tx['id']} + + class Dispatcher: """Dispatch events to websockets. @@ -99,17 +110,10 @@ class Dispatcher: str_buffer.append(event) elif event.type == EventTypes.BLOCK_VALID: - block = event.data + str_buffer = map(json.dumps, eventify_block(event.data)) - for tx in block['transactions']: - asset_id = tx['id'] if tx['operation'] == 'CREATE' else tx['asset']['id'] - data = {'height': block['height'], - 'asset_id': asset_id, - 'transaction_id': tx['id']} - str_buffer.append(json.dumps(data)) - - for _, websocket in self.subscribers.items(): - for str_item in str_buffer: + for str_item in str_buffer: + for _, websocket in self.subscribers.items(): yield from websocket.send_str(str_item) diff --git a/tests/web/test_websocket_server.py b/tests/web/test_websocket_server.py index 1a2b55af..a3de508a 100644 --- a/tests/web/test_websocket_server.py +++ b/tests/web/test_websocket_server.py @@ -21,6 +21,33 @@ class MockWebSocket: self.received.append(s) +def test_eventify_block_works_with_any_transaction(): + from bigchaindb.web.websocket_server import eventify_block + + block = { + 'height': 1, + 'transactions': [{ + 'id': 1 + }, { + 'id': 2, + 'asset': {'id': 1} + }] + } + + expected_events = [{ + 'height': 1, + 'asset_id': 1, + 'transaction_id': 1 + }, { + 'height': 1, + 'asset_id': 1, + 'transaction_id': 2 + }] + + for event, expected in zip(eventify_block(block), expected_events): + assert event == expected + + @asyncio.coroutine def test_bridge_sync_async_queue(loop): from bigchaindb.web.websocket_server import _multiprocessing_to_asyncio From d78ff75225c4ace8f83ae3e92959463ad8320092 Mon Sep 17 00:00:00 2001 From: Troy McConaghy Date: Mon, 27 Aug 2018 15:01:55 +0200 Subject: [PATCH 3/3] Problem: HTTP API docs wrong regarding the mode parameter (#2481) Solution: Edit those docs to be accurate --- docs/server/source/http-client-server-api.rst | 22 +++++++++++++------ 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/docs/server/source/http-client-server-api.rst b/docs/server/source/http-client-server-api.rst index 2026b6db..0f47acb5 100644 --- a/docs/server/source/http-client-server-api.rst +++ b/docs/server/source/http-client-server-api.rst @@ -135,13 +135,21 @@ Transactions :query string mode: (Optional) One of the three supported modes to send a transaction: ``async``, ``sync``, ``commit``. The default is ``async``. - The ``mode`` query parameter inhereted from the mode parameter in Tendermint's - `broadcast API - `_. - ``mode=async`` means the HTTP response will come back immediately, without - even checking to see if the transaction is valid. - ``mode=sync`` means the HTTP response will come back once the node has - checked the validity of the transaction. + Once the posted transaction arrives at a BigchainDB node, + that node will check to see if the transaction is valid. + If it's invalid, the node will return an HTTP 400 (error). + Otherwise, the node will send the transaction to Tendermint (in the same node) using the + `Tendermint broadcast API + `_. + + The meaning of the ``mode`` query parameter is inherited from the mode parameter in + `Tendermint's broadcast API + `_. + ``mode=async`` means the HTTP response will come back immediately, + before Tendermint asks BigchainDB Server to check the validity of the transaction (a second time). + ``mode=sync`` means the HTTP response will come back + after Tendermint gets a response from BigchainDB Server + regarding the validity of the transaction. ``mode=commit`` means the HTTP response will come back once the transaction is in a committed block.