diff --git a/bigchaindb/__init__.py b/bigchaindb/__init__.py index 74b87129..f6b7b6cf 100644 --- a/bigchaindb/__init__.py +++ b/bigchaindb/__init__.py @@ -17,7 +17,7 @@ config = { 'database': { 'backend': os.environ.get('BIGCHAINDB_DATABASE_BACKEND', 'rethinkdb'), 'host': os.environ.get('BIGCHAINDB_DATABASE_HOST', 'localhost'), - 'port': 28015, + 'port': int(os.environ.get('BIGCHAINDB_DATABASE_PORT', 28015)), 'name': 'bigchain', }, 'keypair': { diff --git a/tests/assets/test_digital_assets.py b/tests/assets/test_digital_assets.py index efb15fc1..66db993e 100644 --- a/tests/assets/test_digital_assets.py +++ b/tests/assets/test_digital_assets.py @@ -3,6 +3,7 @@ import random from unittest.mock import patch +@pytest.mark.bdb @pytest.mark.usefixtures('inputs') def test_asset_transfer(b, user_pk, user_sk): from bigchaindb.common.transaction import AssetLink @@ -31,6 +32,7 @@ def test_validate_bad_asset_creation(b, user_pk): b.validate_transaction(tx_signed) +@pytest.mark.bdb @pytest.mark.usefixtures('inputs') def test_validate_transfer_asset_id_mismatch(b, user_pk, user_sk): from bigchaindb.common.exceptions import AssetIdMismatch @@ -56,6 +58,7 @@ def test_get_asset_id_create_transaction(b, user_pk): assert asset_id == tx_create.id +@pytest.mark.bdb @pytest.mark.usefixtures('inputs') def test_get_asset_id_transfer_transaction(b, user_pk, user_sk): from bigchaindb.common.transaction import AssetLink @@ -91,6 +94,7 @@ def test_asset_id_mismatch(b, user_pk): Asset.get_asset_id([tx1, tx2]) +@pytest.mark.bdb @pytest.mark.usefixtures('inputs') def test_get_transactions_by_asset_id(b, user_pk, user_sk): from bigchaindb.common.transaction import AssetLink @@ -126,6 +130,7 @@ def test_get_transactions_by_asset_id(b, user_pk, user_sk): assert asset_id == txs[1].asset.id +@pytest.mark.bdb @pytest.mark.usefixtures('inputs') def test_get_transactions_by_asset_id_with_invalid_block(b, user_pk, user_sk): from bigchaindb.common.transaction import AssetLink @@ -156,6 +161,7 @@ def test_get_transactions_by_asset_id_with_invalid_block(b, user_pk, user_sk): assert len(txs) == 1 +@pytest.mark.bdb @pytest.mark.usefixtures('inputs') def test_get_asset_by_id(b, user_pk, user_sk): from bigchaindb.common.transaction import AssetLink diff --git a/tests/assets/test_divisible_assets.py b/tests/assets/test_divisible_assets.py index 5c661dd8..79235362 100644 --- a/tests/assets/test_divisible_assets.py +++ b/tests/assets/test_divisible_assets.py @@ -126,6 +126,7 @@ def test_single_in_multiple_own_single_out_single_own_create(b, user_pk, # else there will be no genesis block and b.get_last_voted_block will # fail. # Is there a better way of doing this? +@pytest.mark.bdb @pytest.mark.usefixtures('inputs') def test_single_in_single_own_single_out_single_own_transfer(b, user_pk, user_sk): @@ -160,6 +161,7 @@ def test_single_in_single_own_single_out_single_own_transfer(b, user_pk, # Single owners_before # Multiple output # Single owners_after +@pytest.mark.bdb @pytest.mark.usefixtures('inputs') def test_single_in_single_own_multiple_out_single_own_transfer(b, user_pk, user_sk): @@ -196,6 +198,7 @@ def test_single_in_single_own_multiple_out_single_own_transfer(b, user_pk, # Single owners_before # Single output # Multiple owners_after +@pytest.mark.bdb @pytest.mark.usefixtures('inputs') def test_single_in_single_own_single_out_multiple_own_transfer(b, user_pk, user_sk): @@ -237,6 +240,7 @@ def test_single_in_single_own_single_out_multiple_own_transfer(b, user_pk, # Multiple outputs # Mix: one output with a single owners_after, one output with multiple # owners_after +@pytest.mark.bdb @pytest.mark.usefixtures('inputs') def test_single_in_single_own_multiple_out_mix_own_transfer(b, user_pk, user_sk): @@ -278,6 +282,7 @@ def test_single_in_single_own_multiple_out_mix_own_transfer(b, user_pk, # Multiple owners_before # Single output # Single owners_after +@pytest.mark.bdb @pytest.mark.usefixtures('inputs') def test_single_in_multiple_own_single_out_single_own_transfer(b, user_pk, user_sk): @@ -317,6 +322,7 @@ def test_single_in_multiple_own_single_out_single_own_transfer(b, user_pk, # Single owners_before per input # Single output # Single owners_after +@pytest.mark.bdb @pytest.mark.usefixtures('inputs') def test_multiple_in_single_own_single_out_single_own_transfer(b, user_pk, user_sk): @@ -352,6 +358,7 @@ def test_multiple_in_single_own_single_out_single_own_transfer(b, user_pk, # Multiple owners_before per input # Single output # Single owners_after +@pytest.mark.bdb @pytest.mark.usefixtures('inputs') def test_multiple_in_multiple_own_single_out_single_own_transfer(b, user_pk, user_sk): @@ -397,6 +404,7 @@ def test_multiple_in_multiple_own_single_out_single_own_transfer(b, user_pk, # owners_before # Single output # Single owners_after +@pytest.mark.bdb @pytest.mark.usefixtures('inputs') def test_muiltiple_in_mix_own_multiple_out_single_own_transfer(b, user_pk, user_sk): @@ -442,6 +450,7 @@ def test_muiltiple_in_mix_own_multiple_out_single_own_transfer(b, user_pk, # Multiple outputs # Mix: one output with a single owners_after, one output with multiple # owners_after +@pytest.mark.bdb @pytest.mark.usefixtures('inputs') def test_muiltiple_in_mix_own_multiple_out_mix_own_transfer(b, user_pk, user_sk): @@ -493,6 +502,7 @@ def test_muiltiple_in_mix_own_multiple_out_mix_own_transfer(b, user_pk, # Single owners_before # Single output # Single owners_after +@pytest.mark.bdb @pytest.mark.usefixtures('inputs') def test_multiple_in_different_transactions(b, user_pk, user_sk): from bigchaindb.models import Transaction @@ -554,6 +564,7 @@ def test_multiple_in_different_transactions(b, user_pk, user_sk): # In a TRANSFER transaction of a divisible asset the amount being spent in the # inputs needs to match the amount being sent in the outputs. # In other words `amount_in_inputs - amount_in_outputs == 0` +@pytest.mark.bdb @pytest.mark.usefixtures('inputs') def test_amount_error_transfer(b, user_pk, user_sk): from bigchaindb.models import Transaction @@ -590,6 +601,7 @@ def test_amount_error_transfer(b, user_pk, user_sk): @pytest.mark.skip(reason='Figure out how to handle this case') +@pytest.mark.bdb @pytest.mark.usefixtures('inputs') def test_threshold_same_public_key(b, user_pk, user_sk): # If we try to fulfill a threshold condition where each subcondition has @@ -623,6 +635,7 @@ def test_threshold_same_public_key(b, user_pk, user_sk): assert tx_transfer_signed.validate(b) == tx_transfer_signed +@pytest.mark.bdb @pytest.mark.usefixtures('inputs') def test_sum_amount(b, user_pk, user_sk): from bigchaindb.models import Transaction @@ -655,6 +668,7 @@ def test_sum_amount(b, user_pk, user_sk): assert tx_transfer_signed.conditions[0].amount == 3 +@pytest.mark.bdb @pytest.mark.usefixtures('inputs') def test_divide(b, user_pk, user_sk): from bigchaindb.models import Transaction @@ -687,6 +701,7 @@ def test_divide(b, user_pk, user_sk): # Check that negative inputs are caught when creating a TRANSFER transaction +@pytest.mark.bdb @pytest.mark.usefixtures('inputs') def test_non_positive_amounts_on_transfer(b, user_pk): from bigchaindb.models import Transaction @@ -713,6 +728,7 @@ def test_non_positive_amounts_on_transfer(b, user_pk): # Check that negative inputs are caught when validating a TRANSFER transaction +@pytest.mark.bdb @pytest.mark.usefixtures('inputs') def test_non_positive_amounts_on_transfer_validate(b, user_pk, user_sk): from bigchaindb.models import Transaction @@ -745,6 +761,7 @@ def test_non_positive_amounts_on_transfer_validate(b, user_pk, user_sk): # Check that negative inputs are caught when creating a CREATE transaction +@pytest.mark.bdb @pytest.mark.usefixtures('inputs') def test_non_positive_amounts_on_create(b, user_pk): from bigchaindb.models import Transaction @@ -759,6 +776,7 @@ def test_non_positive_amounts_on_create(b, user_pk): # Check that negative inputs are caught when validating a CREATE transaction +@pytest.mark.bdb @pytest.mark.usefixtures('inputs') def test_non_positive_amounts_on_create_validate(b, user_pk): from bigchaindb.models import Transaction diff --git a/tests/backend/mongodb/test_schema.py b/tests/backend/mongodb/test_schema.py index 257abe6d..b3b726e3 100644 --- a/tests/backend/mongodb/test_schema.py +++ b/tests/backend/mongodb/test_schema.py @@ -1,8 +1,9 @@ import pytest from unittest.mock import patch +pytestmark = pytest.mark.bdb + -@pytest.mark.usefixtures('setup_database') def test_init_creates_db_tables_and_indexes(): import bigchaindb from bigchaindb import backend @@ -30,7 +31,6 @@ def test_init_creates_db_tables_and_indexes(): assert sorted(indexes) == ['_id_', 'block_and_voter'] -@pytest.mark.usefixtures('setup_database') def test_init_database_fails_if_db_exists(): import bigchaindb from bigchaindb import backend @@ -47,7 +47,6 @@ def test_init_database_fails_if_db_exists(): init_database() -@pytest.mark.usefixtures('setup_database') def test_create_tables(): import bigchaindb from bigchaindb import backend @@ -65,7 +64,6 @@ def test_create_tables(): assert sorted(collection_names) == ['backlog', 'bigchain', 'votes'] -@pytest.mark.usefixtures('setup_database') def test_create_secondary_indexes(): import bigchaindb from bigchaindb import backend @@ -94,7 +92,6 @@ def test_create_secondary_indexes(): assert sorted(indexes) == ['_id_', 'block_and_voter'] -@pytest.mark.usefixtures('setup_database') def test_drop(): import bigchaindb from bigchaindb import backend diff --git a/tests/backend/rethinkdb/test_schema.py b/tests/backend/rethinkdb/test_schema.py index 02545a45..1447e80f 100644 --- a/tests/backend/rethinkdb/test_schema.py +++ b/tests/backend/rethinkdb/test_schema.py @@ -6,7 +6,7 @@ from bigchaindb import backend from bigchaindb.backend.rethinkdb import schema -@pytest.mark.usefixtures('setup_database') +@pytest.mark.bdb def test_init_creates_db_tables_and_indexes(): from bigchaindb.backend.schema import init_database conn = backend.connect() @@ -28,7 +28,7 @@ def test_init_creates_db_tables_and_indexes(): 'assignee__transaction_timestamp')) is True -@pytest.mark.usefixtures('setup_database') +@pytest.mark.bdb def test_init_database_fails_if_db_exists(): from bigchaindb.backend.schema import init_database from bigchaindb.common import exceptions @@ -43,14 +43,13 @@ def test_init_database_fails_if_db_exists(): init_database() -def test_create_database(): +def test_create_database(not_yet_created_db): conn = backend.connect() - dbname = bigchaindb.config['database']['name'] - schema.create_database(conn, dbname) - assert conn.run(r.db_list().contains(dbname)) is True + schema.create_database(conn, not_yet_created_db) + assert conn.run(r.db_list().contains(not_yet_created_db)) is True -@pytest.mark.usefixtures('setup_database') +@pytest.mark.bdb def test_create_tables(): conn = backend.connect() dbname = bigchaindb.config['database']['name'] @@ -67,7 +66,7 @@ def test_create_tables(): assert len(conn.run(r.db(dbname).table_list())) == 3 -@pytest.mark.usefixtures('setup_database') +@pytest.mark.bdb def test_create_secondary_indexes(): conn = backend.connect() dbname = bigchaindb.config['database']['name'] @@ -96,29 +95,17 @@ def test_create_secondary_indexes(): 'block_and_voter')) is True -@pytest.mark.usefixtures('setup_database') -def test_drop(): +def test_drop(dummy_db): conn = backend.connect() - dbname = bigchaindb.config['database']['name'] - - # The db is set up by fixtures - assert conn.run(r.db_list().contains(dbname)) is True - - schema.drop_database(conn, dbname) - assert conn.run(r.db_list().contains(dbname)) is False + assert conn.run(r.db_list().contains(dummy_db)) is True + schema.drop_database(conn, dummy_db) + assert conn.run(r.db_list().contains(dummy_db)) is False -@pytest.mark.usefixtures('setup_database') -def test_drop_non_existent_db_raises_an_error(): +def test_drop_non_existent_db_raises_an_error(dummy_db): from bigchaindb.common import exceptions - conn = backend.connect() - dbname = bigchaindb.config['database']['name'] - - # The db is set up by fixtures - assert conn.run(r.db_list().contains(dbname)) is True - - schema.drop_database(conn, dbname) - + assert conn.run(r.db_list().contains(dummy_db)) is True + schema.drop_database(conn, dummy_db) with pytest.raises(exceptions.DatabaseDoesNotExist): - schema.drop_database(conn, dbname) + schema.drop_database(conn, dummy_db) diff --git a/tests/commands/test_commands.py b/tests/commands/test_commands.py index fa238dfd..a3fc3503 100644 --- a/tests/commands/test_commands.py +++ b/tests/commands/test_commands.py @@ -101,7 +101,7 @@ def test_bigchain_run_start_assume_yes_create_default_config(monkeypatch, mock_p # TODO Please beware, that if debugging, the "-s" switch for pytest will # interfere with capsys. # See related issue: https://github.com/pytest-dev/pytest/issues/128 -@pytest.mark.usefixtures('restore_config') +@pytest.mark.usefixtures('ignore_local_config_file') def test_bigchain_show_config(capsys): from bigchaindb import config from bigchaindb.commands.bigchain import run_show_config @@ -229,7 +229,7 @@ def test_run_configure_when_config_does_exist(monkeypatch, @patch('bigchaindb.common.crypto.generate_key_pair', return_value=('private_key', 'public_key')) -@pytest.mark.usefixtures('restore_config') +@pytest.mark.usefixtures('ignore_local_config_file') def test_allow_temp_keypair_generates_one_on_the_fly(mock_gen_keypair, mock_processes_start, mock_db_init_with_existing_db): @@ -247,7 +247,7 @@ def test_allow_temp_keypair_generates_one_on_the_fly(mock_gen_keypair, @patch('bigchaindb.common.crypto.generate_key_pair', return_value=('private_key', 'public_key')) -@pytest.mark.usefixtures('restore_config') +@pytest.mark.usefixtures('ignore_local_config_file') def test_allow_temp_keypair_doesnt_override_if_keypair_found(mock_gen_keypair, mock_processes_start, mock_db_init_with_existing_db): diff --git a/tests/conftest.py b/tests/conftest.py index 57f60cce..31011895 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -14,19 +14,9 @@ import pytest from bigchaindb.common import crypto +TEST_DB_NAME = 'bigchain_test' USER2_SK, USER2_PK = crypto.generate_key_pair() -DB_NAME = 'bigchain_test_{}'.format(os.getpid()) - -CONFIG = { - 'database': { - 'name': DB_NAME, - }, - 'keypair': { - 'private': '31Lb1ZGKTyHnmVK3LUMrAUrPNfd4sE2YyBt3UA4A25aA', - 'public': '4XYfCbabAWVUCbjTmRTFEu2sc3dFEdkse4r6X498B1s8', - } -} # Test user. inputs will be created for this user. Cryptography Keys USER_PRIVATE_KEY = '8eJ8q9ZQpReWyQT5aFCiwtZ5wDZC4eDnCen88p3tQ6ie' @@ -56,6 +46,118 @@ def pytest_ignore_collect(path, config): return True +def pytest_configure(config): + config.addinivalue_line( + 'markers', + 'bdb(): Mark the test as needing BigchainDB, i.e. a database with ' + 'the three tables: "backlog", "bigchain", "votes". BigchainDB will ' + 'be configured such that the database and tables are available for an ' + 'entire test session. For distributed tests, the database name will ' + 'be suffixed with the process identifier, e.g.: "bigchain_test_gw0", ' + 'to ensure that each process session has its own separate database.' + ) + + +@pytest.fixture(autouse=True) +def _bdb_marker(request): + if request.keywords.get('bdb', None): + request.getfixturevalue('_bdb') + + +@pytest.fixture(autouse=True) +def _restore_config(_configure_bigchaindb): + from bigchaindb import config, config_utils + config_before_test = copy.deepcopy(config) + yield + config_utils.set_config(config_before_test) + + +@pytest.fixture +def _restore_dbs(request): + from bigchaindb.backend import connect, schema + from bigchaindb.common.exceptions import DatabaseDoesNotExist + from .utils import list_dbs + conn = connect() + dbs_before_test = list_dbs(conn) + yield + dbs_after_test = list_dbs(conn) + dbs_to_delete = ( + db for db in set(dbs_after_test) - set(dbs_before_test) + if TEST_DB_NAME not in db + ) + print(dbs_to_delete) + for db in dbs_to_delete: + try: + schema.drop_database(conn, db) + except DatabaseDoesNotExist: + pass + + +@pytest.fixture(scope='session') +def _configure_bigchaindb(request): + from bigchaindb import config_utils + test_db_name = TEST_DB_NAME + # Put a suffix like _gw0, _gw1 etc on xdist processes + xdist_suffix = getattr(request.config, 'slaveinput', {}).get('slaveid') + if xdist_suffix: + test_db_name = '{}_{}'.format(TEST_DB_NAME, xdist_suffix) + config = { + 'database': { + 'name': test_db_name, + 'backend': request.config.getoption('--database-backend'), + }, + 'keypair': { + 'private': '31Lb1ZGKTyHnmVK3LUMrAUrPNfd4sE2YyBt3UA4A25aA', + 'public': '4XYfCbabAWVUCbjTmRTFEu2sc3dFEdkse4r6X498B1s8', + } + } + # FIXME + if config['database']['backend'] == 'mongodb': + # not a great way to do this + config['database']['port'] = 27017 + config_utils.set_config(config) + + +@pytest.fixture(scope='session') +def _setup_database(_configure_bigchaindb): + from bigchaindb import config + from bigchaindb.backend import connect, schema + from bigchaindb.common.exceptions import DatabaseDoesNotExist + print('Initializing test db') + dbname = config['database']['name'] + conn = connect() + + try: + schema.drop_database(conn, dbname) + except DatabaseDoesNotExist: + pass + + schema.init_database(conn) + print('Finishing init database') + + yield + + print('Deleting `{}` database'.format(dbname)) + conn = connect() + try: + schema.drop_database(conn, dbname) + except DatabaseDoesNotExist: + pass + + print('Finished deleting `{}`'.format(dbname)) + + +@pytest.fixture +def _bdb(_setup_database, _configure_bigchaindb): + yield + from bigchaindb import config + from bigchaindb.backend import connect + from .utils import flush_db + dbname = config['database']['name'] + conn = connect() + flush_db(conn, dbname) + + # We need this function to avoid loading an existing # conf file located in the home of the user running # the tests. If it's too aggressive we can change it @@ -69,22 +171,6 @@ def ignore_local_config_file(monkeypatch): mock_file_config) -@pytest.fixture -def restore_config(ignore_local_config_file, node_config): - from bigchaindb import config_utils - config_utils.set_config(node_config) - - -@pytest.fixture(scope='module') -def node_config(request): - config = copy.deepcopy(CONFIG) - config['database']['backend'] = request.config.getoption('--database-backend') - if config['database']['backend'] == 'mongodb': - # not a great way to do this - config['database']['port'] = 27017 - return config - - @pytest.fixture def user_sk(): return USER_PRIVATE_KEY @@ -106,7 +192,7 @@ def user2_pk(): @pytest.fixture -def b(restore_config): +def b(): from bigchaindb import Bigchain return Bigchain() @@ -149,35 +235,7 @@ def structurally_valid_vote(): @pytest.fixture -def setup_database(restore_config, node_config): - from bigchaindb.backend import connect, schema - from bigchaindb.common.exceptions import DatabaseDoesNotExist - print('Initializing test db') - db_name = node_config['database']['name'] - conn = connect() - - try: - schema.drop_database(conn, db_name) - except DatabaseDoesNotExist: - pass - - schema.init_database(conn) - print('Finishing init database') - - yield - - print('Deleting `{}` database'.format(db_name)) - conn = connect() - try: - schema.drop_database(conn, db_name) - except DatabaseDoesNotExist: - pass - - print('Finished deleting `{}`'.format(db_name)) - - -@pytest.fixture -def inputs(user_pk, setup_database): +def inputs(user_pk): from bigchaindb import Bigchain from bigchaindb.models import Transaction from bigchaindb.common.exceptions import GenesisBlockAlreadyExistsError @@ -207,7 +265,7 @@ def inputs(user_pk, setup_database): @pytest.fixture -def inputs_shared(user_pk, user2_pk, setup_database): +def inputs_shared(user_pk, user2_pk): from bigchaindb import Bigchain from bigchaindb.models import Transaction from bigchaindb.common.exceptions import GenesisBlockAlreadyExistsError @@ -234,3 +292,45 @@ def inputs_shared(user_pk, user2_pk, setup_database): vote = b.vote(block.id, prev_block_id, True) prev_block_id = block.id b.write_vote(vote) + + +@pytest.fixture +def dummy_db(request): + from bigchaindb.backend import connect, schema + from bigchaindb.common.exceptions import (DatabaseDoesNotExist, + DatabaseAlreadyExists) + conn = connect() + dbname = request.fixturename + xdist_suffix = getattr(request.config, 'slaveinput', {}).get('slaveid') + if xdist_suffix: + dbname = '{}_{}'.format(dbname, xdist_suffix) + try: + schema.create_database(conn, dbname) + except DatabaseAlreadyExists: + schema.drop_database(conn, dbname) + schema.create_database(conn, dbname) + yield dbname + try: + schema.drop_database(conn, dbname) + except DatabaseDoesNotExist: + 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 diff --git a/tests/db/test_bigchain_api.py b/tests/db/test_bigchain_api.py index 58952fbc..67a475d7 100644 --- a/tests/db/test_bigchain_api.py +++ b/tests/db/test_bigchain_api.py @@ -3,6 +3,8 @@ from time import sleep import pytest import random +pytestmark = pytest.mark.bdb + @pytest.mark.skipif(reason='Some tests throw a ResourceWarning that might result in some weird ' 'exceptions while running the tests. The problem seems to *not* ' @@ -29,7 +31,6 @@ def dummy_block(): return block -@pytest.mark.usefixtures('setup_database') class TestBigchainApi(object): def test_get_last_voted_block_cyclic_blockchain(self, b, monkeypatch): from bigchaindb.common.crypto import PrivateKey @@ -591,7 +592,7 @@ class TestTransactionValidation(object): assert excinfo.value.args[0] == 'Only `CREATE` transactions can have null inputs' - @pytest.mark.usefixtures('setup_database') + def test_non_create_input_not_found(self, b, user_pk, signed_transfer_tx): from bigchaindb.common.exceptions import TransactionDoesNotExist from bigchaindb.common.transaction import TransactionLink @@ -745,7 +746,7 @@ class TestBlockValidation(object): assert excinfo.value.args[0] == 'owner_before `a` does not own the input `{}`'.format(valid_input) - @pytest.mark.usefixtures('setup_database') + def test_invalid_signature(self, b): from bigchaindb.common.exceptions import InvalidSignature from bigchaindb.common import crypto @@ -760,7 +761,7 @@ class TestBlockValidation(object): with pytest.raises(InvalidSignature): b.validate_block(block) - @pytest.mark.usefixtures('setup_database') + def test_invalid_node_pubkey(self, b): from bigchaindb.common.exceptions import OperationError from bigchaindb.common import crypto @@ -894,7 +895,6 @@ class TestMultipleInputs(object): assert len(tx.fulfillments) == 1 assert len(tx.conditions) == 1 - @pytest.mark.usefixtures('setup_database') def test_get_owned_ids_single_tx_single_output(self, b, user_sk, user_pk): from bigchaindb.common import crypto from bigchaindb.common.transaction import AssetLink, TransactionLink @@ -923,7 +923,6 @@ class TestMultipleInputs(object): assert owned_inputs_user1 == [] assert owned_inputs_user2 == [TransactionLink(tx.id, 0)] - @pytest.mark.usefixtures('setup_database') def test_get_owned_ids_single_tx_single_output_invalid_block(self, b, user_sk, user_pk): @@ -967,7 +966,6 @@ class TestMultipleInputs(object): assert owned_inputs_user1 == [TransactionLink(tx.id, 0)] assert owned_inputs_user2 == [] - @pytest.mark.usefixtures('setup_database') def test_get_owned_ids_single_tx_multiple_outputs(self, b, user_sk, user_pk): from bigchaindb.common import crypto @@ -1009,7 +1007,6 @@ class TestMultipleInputs(object): assert owned_inputs_user2 == [TransactionLink(tx_transfer.id, 0), TransactionLink(tx_transfer.id, 1)] - @pytest.mark.usefixtures('setup_database') def test_get_owned_ids_multiple_owners(self, b, user_sk, user_pk): from bigchaindb.common import crypto from bigchaindb.common.transaction import AssetLink, TransactionLink @@ -1041,7 +1038,6 @@ class TestMultipleInputs(object): assert owned_inputs_user1 == owned_inputs_user2 assert owned_inputs_user1 == [] - @pytest.mark.usefixtures('setup_database') def test_get_spent_single_tx_single_output(self, b, user_sk, user_pk): from bigchaindb.common import crypto from bigchaindb.common.transaction import AssetLink @@ -1072,7 +1068,6 @@ class TestMultipleInputs(object): spent_inputs_user1 = b.get_spent(input_txid, input_cid) assert spent_inputs_user1 == tx - @pytest.mark.usefixtures('setup_database') def test_get_spent_single_tx_single_output_invalid_block(self, b, user_sk, user_pk): from bigchaindb.common import crypto from bigchaindb.common.transaction import AssetLink @@ -1117,7 +1112,6 @@ class TestMultipleInputs(object): # Now there should be no spents (the block is invalid) assert spent_inputs_user1 is None - @pytest.mark.usefixtures('setup_database') def test_get_spent_single_tx_multiple_outputs(self, b, user_sk, user_pk): from bigchaindb.common import crypto from bigchaindb.common.transaction import Asset, AssetLink @@ -1160,7 +1154,6 @@ class TestMultipleInputs(object): # spendable by BigchainDB assert b.get_spent(tx_create.to_inputs()[2].tx_input.txid, 2) is None - @pytest.mark.usefixtures('setup_database') def test_get_spent_multiple_owners(self, b, user_sk, user_pk): from bigchaindb.common import crypto from bigchaindb.common.transaction import AssetLink diff --git a/tests/integration/conftest.py b/tests/integration/conftest.py index 1faba9a6..b80323c3 100644 --- a/tests/integration/conftest.py +++ b/tests/integration/conftest.py @@ -3,7 +3,7 @@ from bigchaindb.pipelines import block, election, vote, stale @pytest.fixture -def processes(b, setup_database): +def processes(b): b.create_genesis_block() block_maker = block.start() voter = vote.start() diff --git a/tests/integration/test_integration.py b/tests/integration/test_integration.py index 480c20f8..70781096 100644 --- a/tests/integration/test_integration.py +++ b/tests/integration/test_integration.py @@ -2,8 +2,9 @@ import time import pytest +pytestmark = [pytest.mark.bdb, pytest.mark.usefixtures('processes')] + -@pytest.mark.usefixtures('processes') def test_fast_double_create(b, user_pk): from bigchaindb.models import Transaction from bigchaindb.backend.query import count_blocks @@ -25,7 +26,6 @@ def test_fast_double_create(b, user_pk): assert count_blocks(b.connection) == 2 -@pytest.mark.usefixtures('processes') def test_double_create(b, user_pk): from bigchaindb.models import Transaction from bigchaindb.backend.query import count_blocks diff --git a/tests/pipelines/test_block_creation.py b/tests/pipelines/test_block_creation.py index 85fa2d37..18d291ea 100644 --- a/tests/pipelines/test_block_creation.py +++ b/tests/pipelines/test_block_creation.py @@ -27,7 +27,7 @@ def test_filter_by_assignee(b, signed_create_tx): assert block_maker.filter_tx(tx) is None -@pytest.mark.usefixtures('setup_database') +@pytest.mark.bdb def test_validate_transaction(b, create_tx): from bigchaindb.pipelines.block import BlockPipeline @@ -57,7 +57,7 @@ def test_create_block(b, user_pk): assert len(block_doc.transactions) == 100 -@pytest.mark.usefixtures('setup_database') +@pytest.mark.bdb def test_write_block(b, user_pk): from bigchaindb.models import Block, Transaction from bigchaindb.pipelines.block import BlockPipeline @@ -79,7 +79,7 @@ def test_write_block(b, user_pk): assert expected == block_doc -@pytest.mark.usefixtures('setup_database') +@pytest.mark.bdb def test_duplicate_transaction(b, user_pk): from bigchaindb.models import Transaction from bigchaindb.pipelines import block @@ -112,7 +112,7 @@ def test_duplicate_transaction(b, user_pk): assert status != b.TX_IN_BACKLOG -@pytest.mark.usefixtures('setup_database') +@pytest.mark.bdb def test_delete_tx(b, user_pk): from bigchaindb.models import Transaction from bigchaindb.pipelines.block import BlockPipeline @@ -142,7 +142,7 @@ def test_delete_tx(b, user_pk): @patch('bigchaindb.pipelines.block.create_pipeline') -@pytest.mark.usefixtures('setup_database') +@pytest.mark.bdb def test_start(create_pipeline): from bigchaindb.pipelines import block @@ -153,7 +153,7 @@ def test_start(create_pipeline): assert pipeline == create_pipeline.return_value -@pytest.mark.usefixtures('setup_database') +@pytest.mark.bdb def test_full_pipeline(b, user_pk): from bigchaindb.models import Block, Transaction from bigchaindb.pipelines.block import create_pipeline diff --git a/tests/pipelines/test_election.py b/tests/pipelines/test_election.py index a4a7d876..28141dff 100644 --- a/tests/pipelines/test_election.py +++ b/tests/pipelines/test_election.py @@ -10,7 +10,7 @@ from bigchaindb import Bigchain from bigchaindb.pipelines import election -@pytest.mark.usefixtures('setup_database') +@pytest.mark.bdb def test_check_for_quorum_invalid(b, user_pk): from bigchaindb.models import Transaction @@ -44,7 +44,7 @@ def test_check_for_quorum_invalid(b, user_pk): assert e.check_for_quorum(votes[-1]) == test_block -@pytest.mark.usefixtures('setup_database') +@pytest.mark.bdb def test_check_for_quorum_invalid_prev_node(b, user_pk): from bigchaindb.models import Transaction e = election.Election() @@ -79,7 +79,7 @@ def test_check_for_quorum_invalid_prev_node(b, user_pk): assert e.check_for_quorum(votes[-1]) == test_block -@pytest.mark.usefixtures('setup_database') +@pytest.mark.bdb def test_check_for_quorum_valid(b, user_pk): from bigchaindb.models import Transaction @@ -112,7 +112,7 @@ def test_check_for_quorum_valid(b, user_pk): assert e.check_for_quorum(votes[-1]) is None -@pytest.mark.usefixtures('setup_database') +@pytest.mark.bdb def test_check_requeue_transaction(b, user_pk): from bigchaindb.models import Transaction @@ -140,7 +140,7 @@ def test_start(mock_start): mock_start.assert_called_with() -@pytest.mark.usefixtures('setup_database') +@pytest.mark.bdb def test_full_pipeline(b, user_pk): import random from bigchaindb.backend import query diff --git a/tests/pipelines/test_stale_monitor.py b/tests/pipelines/test_stale_monitor.py index 6e35f0ba..e964e28c 100644 --- a/tests/pipelines/test_stale_monitor.py +++ b/tests/pipelines/test_stale_monitor.py @@ -9,7 +9,7 @@ from bigchaindb import config_utils import pytest -@pytest.mark.usefixtures('setup_database') +@pytest.mark.bdb def test_get_stale(b, user_pk): from bigchaindb.models import Transaction tx = Transaction.create([b.me], [([user_pk], 1)]) @@ -26,7 +26,7 @@ def test_get_stale(b, user_pk): assert tx.to_dict() == _tx -@pytest.mark.usefixtures('setup_database') +@pytest.mark.bdb def test_reassign_transactions(b, user_pk): from bigchaindb.backend import query from bigchaindb.models import Transaction @@ -66,22 +66,15 @@ def test_reassign_transactions(b, user_pk): assert tx['assignee'] != 'lol' -@pytest.mark.usefixtures('setup_database') +@pytest.mark.bdb def test_full_pipeline(monkeypatch, user_pk): from bigchaindb.backend import query from bigchaindb.models import Transaction CONFIG = { - 'database': { - 'name': 'bigchain_test_{}'.format(os.getpid()) - }, - 'keypair': { - 'private': '31Lb1ZGKTyHnmVK3LUMrAUrPNfd4sE2YyBt3UA4A25aA', - 'public': '4XYfCbabAWVUCbjTmRTFEu2sc3dFEdkse4r6X498B1s8' - }, 'keyring': ['aaa', 'bbb'], 'backlog_reassign_delay': 0.01 } - config_utils.set_config(CONFIG) + config_utils.update_config(CONFIG) b = Bigchain() original_txs = {} diff --git a/tests/pipelines/test_vote.py b/tests/pipelines/test_vote.py index f7db7d49..bf53dc38 100644 --- a/tests/pipelines/test_vote.py +++ b/tests/pipelines/test_vote.py @@ -62,7 +62,7 @@ def test_vote_creation_invalid(b): vote['signature']) is True -@pytest.mark.usefixtures('setup_database') +@pytest.mark.bdb def test_vote_ungroup_returns_a_set_of_results(b): from bigchaindb.pipelines import vote @@ -74,7 +74,7 @@ def test_vote_ungroup_returns_a_set_of_results(b): assert len(txs) == 10 -@pytest.mark.usefixtures('setup_database') +@pytest.mark.bdb def test_vote_validate_block(b): from bigchaindb.pipelines import vote @@ -99,7 +99,7 @@ def test_vote_validate_block(b): assert tx1 == tx2 -@pytest.mark.usefixtures('setup_database') +@pytest.mark.bdb def test_validate_block_with_invalid_id(b): from bigchaindb.pipelines import vote @@ -114,7 +114,7 @@ def test_validate_block_with_invalid_id(b): assert invalid_dummy_tx == [vote_obj.invalid_dummy_tx] -@pytest.mark.usefixtures('setup_database') +@pytest.mark.bdb def test_validate_block_with_invalid_signature(b): from bigchaindb.pipelines import vote @@ -129,7 +129,7 @@ def test_validate_block_with_invalid_signature(b): assert invalid_dummy_tx == [vote_obj.invalid_dummy_tx] -@pytest.mark.usefixtures('setup_database') +@pytest.mark.bdb def test_vote_validate_transaction(b): from bigchaindb.pipelines import vote from bigchaindb.models import Transaction @@ -146,7 +146,7 @@ def test_vote_validate_transaction(b): assert validation == (False, 456, 10) -@pytest.mark.usefixtures('setup_database') +@pytest.mark.bdb def test_vote_accumulates_transactions(b): from bigchaindb.pipelines import vote @@ -165,7 +165,7 @@ def test_vote_accumulates_transactions(b): assert validation == (False, 456, 10) -@pytest.mark.usefixtures('setup_database') +@pytest.mark.bdb def test_valid_block_voting_sequential(b, monkeypatch): from bigchaindb.backend import query from bigchaindb.common import crypto, util @@ -195,7 +195,7 @@ def test_valid_block_voting_sequential(b, monkeypatch): vote_doc['signature']) is True -@pytest.mark.usefixtures('setup_database') +@pytest.mark.bdb def test_valid_block_voting_multiprocessing(b, monkeypatch): from bigchaindb.backend import query from bigchaindb.common import crypto, util @@ -231,7 +231,7 @@ def test_valid_block_voting_multiprocessing(b, monkeypatch): vote_doc['signature']) is True -@pytest.mark.usefixtures('setup_database') +@pytest.mark.bdb def test_valid_block_voting_with_create_transaction(b, monkeypatch): from bigchaindb.backend import query from bigchaindb.common import crypto, util @@ -274,7 +274,7 @@ def test_valid_block_voting_with_create_transaction(b, monkeypatch): vote_doc['signature']) is True -@pytest.mark.usefixtures('setup_database') +@pytest.mark.bdb def test_valid_block_voting_with_transfer_transactions(monkeypatch, b): from bigchaindb.backend import query from bigchaindb.common import crypto, util @@ -346,7 +346,7 @@ def test_valid_block_voting_with_transfer_transactions(monkeypatch, b): vote2_doc['signature']) is True -@pytest.mark.usefixtures('setup_database') +@pytest.mark.bdb def test_unsigned_tx_in_block_voting(monkeypatch, b, user_pk): from bigchaindb.backend import query from bigchaindb.common import crypto, util @@ -385,7 +385,7 @@ def test_unsigned_tx_in_block_voting(monkeypatch, b, user_pk): vote_doc['signature']) is True -@pytest.mark.usefixtures('setup_database') +@pytest.mark.bdb def test_invalid_id_tx_in_block_voting(monkeypatch, b, user_pk): from bigchaindb.backend import query from bigchaindb.common import crypto, util @@ -426,7 +426,7 @@ def test_invalid_id_tx_in_block_voting(monkeypatch, b, user_pk): vote_doc['signature']) is True -@pytest.mark.usefixtures('setup_database') +@pytest.mark.bdb def test_invalid_content_in_tx_in_block_voting(monkeypatch, b, user_pk): from bigchaindb.backend import query from bigchaindb.common import crypto, util @@ -467,7 +467,7 @@ def test_invalid_content_in_tx_in_block_voting(monkeypatch, b, user_pk): vote_doc['signature']) is True -@pytest.mark.usefixtures('setup_database') +@pytest.mark.bdb def test_invalid_block_voting(monkeypatch, b, user_pk): from bigchaindb.backend import query from bigchaindb.common import crypto, util @@ -504,7 +504,7 @@ def test_invalid_block_voting(monkeypatch, b, user_pk): vote_doc['signature']) is True -@pytest.mark.usefixtures('setup_database') +@pytest.mark.bdb def test_voter_considers_unvoted_blocks_when_single_node(monkeypatch, b): from bigchaindb.backend import query from bigchaindb.pipelines import vote @@ -553,7 +553,7 @@ def test_voter_considers_unvoted_blocks_when_single_node(monkeypatch, b): assert all(vote['node_pubkey'] == b.me for vote in votes) -@pytest.mark.usefixtures('setup_database') +@pytest.mark.bdb def test_voter_chains_blocks_with_the_previous_ones(monkeypatch, b): from bigchaindb.backend import query from bigchaindb.pipelines import vote @@ -595,7 +595,7 @@ def test_voter_chains_blocks_with_the_previous_ones(monkeypatch, b): {block['id'] for block in blocks}) -@pytest.mark.usefixtures('setup_database') +@pytest.mark.bdb def test_voter_checks_for_previous_vote(monkeypatch, b): from bigchaindb.backend import query from bigchaindb.pipelines import vote @@ -637,7 +637,7 @@ def test_voter_checks_for_previous_vote(monkeypatch, b): @patch.object(Pipeline, 'start') -@pytest.mark.usefixtures('setup_database') +@pytest.mark.bdb def test_start(mock_start, b): # TODO: `block.start` is just a wrapper around `vote.create_pipeline`, # that is tested by `test_full_pipeline`. diff --git a/tests/test_config_utils.py b/tests/test_config_utils.py index 548d3160..2a326147 100644 --- a/tests/test_config_utils.py +++ b/tests/test_config_utils.py @@ -9,19 +9,6 @@ import bigchaindb ORIGINAL_CONFIG = copy.deepcopy(bigchaindb._config) -@pytest.fixture -def ignore_local_config_file(monkeypatch): - """ - This fixture's purpose is to override the one under - :module:`tests/conftest.py` so that the original behaviour of - :func:`bigchaindb.config_utils.file_config` is restored, so that it can be - tested. - - """ - from bigchaindb.config_utils import file_config - monkeypatch.setattr('bigchaindb.config_utils.file_config', file_config) - - @pytest.fixture(scope='function', autouse=True) def clean_config(monkeypatch): monkeypatch.setattr('bigchaindb.config', copy.deepcopy(ORIGINAL_CONFIG)) diff --git a/tests/test_core.py b/tests/test_core.py index 16974098..5dfbc028 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -91,9 +91,10 @@ def test_has_previous_vote(monkeypatch): bigchain.has_previous_vote(block) -@pytest.mark.parametrize('count,exists', ((1, True), (0, False))) -def test_transaction_exists(monkeypatch, count, exists): +@pytest.mark.parametrize('exists', (True, False)) +def test_transaction_exists(monkeypatch, exists): from bigchaindb.core import Bigchain - monkeypatch.setattr(RqlQuery, 'run', lambda x, y: count) + monkeypatch.setattr( + 'bigchaindb.backend.query.has_transaction', lambda x, y: exists) bigchain = Bigchain(public_key='pubkey', private_key='privkey') assert bigchain.transaction_exists('txid') is exists diff --git a/tests/utils.py b/tests/utils.py new file mode 100644 index 00000000..ca51fb6e --- /dev/null +++ b/tests/utils.py @@ -0,0 +1,43 @@ +from functools import singledispatch + +import rethinkdb as r + +from bigchaindb.backend.mongodb.connection import MongoDBConnection +from bigchaindb.backend.rethinkdb.connection import RethinkDBConnection + + +@singledispatch +def list_dbs(connection): + raise NotImplementedError + + +@list_dbs.register(RethinkDBConnection) +def list_rethink_dbs(connection): + return connection.run(r.db_list()) + + +@list_dbs.register(MongoDBConnection) +def list_mongo_dbs(connection): + raise NotImplementedError + + +@singledispatch +def flush_db(connection, dbname): + raise NotImplementedError + + +@flush_db.register(RethinkDBConnection) +def flush_rethink_db(connection, dbname): + try: + connection.run(r.db(dbname).table('bigchain').delete()) + connection.run(r.db(dbname).table('backlog').delete()) + connection.run(r.db(dbname).table('votes').delete()) + except r.ReqlOpFailedError: + pass + + +@flush_db.register(MongoDBConnection) +def flush_mongo_db(connection, dbname): + connection.conn[dbname].bigchain.delete_many({}) + connection.conn[dbname].backlog.delete_many({}) + connection.conn[dbname].votes.delete_many({}) diff --git a/tests/web/conftest.py b/tests/web/conftest.py index 61e51ba9..272483e0 100644 --- a/tests/web/conftest.py +++ b/tests/web/conftest.py @@ -2,7 +2,7 @@ import pytest @pytest.fixture -def app(request, restore_config): +def app(request): from bigchaindb.web import server app = server.create_app(debug=True) return app diff --git a/tests/web/test_transactions.py b/tests/web/test_transactions.py index 743843dd..45c94181 100644 --- a/tests/web/test_transactions.py +++ b/tests/web/test_transactions.py @@ -8,6 +8,7 @@ from bigchaindb.common import crypto TX_ENDPOINT = '/api/v1/transactions/' +@pytest.mark.bdb @pytest.mark.usefixtures('inputs') def test_get_transaction_endpoint(b, client, user_pk): input_tx = b.get_owned_ids(user_pk).pop() @@ -17,6 +18,7 @@ def test_get_transaction_endpoint(b, client, user_pk): assert res.status_code == 200 +@pytest.mark.bdb @pytest.mark.usefixtures('inputs') def test_get_transaction_returns_404_if_not_found(client): res = client.get(TX_ENDPOINT + '123') @@ -26,7 +28,7 @@ def test_get_transaction_returns_404_if_not_found(client): assert res.status_code == 404 -@pytest.mark.usefixtures('setup_database') +@pytest.mark.bdb def test_post_create_transaction_endpoint(b, client): from bigchaindb.models import Transaction user_priv, user_pub = crypto.generate_key_pair() @@ -120,6 +122,7 @@ def test_post_invalid_transaction(client, exc, msg, monkeypatch): 'Invalid transaction ({}): {}'.format(exc, msg)) +@pytest.mark.bdb @pytest.mark.usefixtures('inputs') def test_post_transfer_transaction_endpoint(b, client, user_pk, user_sk): sk, pk = crypto.generate_key_pair() @@ -141,6 +144,7 @@ def test_post_transfer_transaction_endpoint(b, client, user_pk, user_sk): assert res.json['conditions'][0]['owners_after'][0] == user_pub +@pytest.mark.bdb @pytest.mark.usefixtures('inputs') def test_post_invalid_transfer_transaction_returns_400(b, client, user_pk, user_sk): from bigchaindb.models import Transaction @@ -158,6 +162,7 @@ def test_post_invalid_transfer_transaction_returns_400(b, client, user_pk, user_ assert res.status_code == 400 +@pytest.mark.bdb @pytest.mark.usefixtures('inputs') def test_get_transaction_status_endpoint(b, client, user_pk): input_tx = b.get_owned_ids(user_pk).pop() @@ -171,6 +176,7 @@ def test_get_transaction_status_endpoint(b, client, user_pk): assert res.status_code == 200 +@pytest.mark.bdb @pytest.mark.usefixtures('inputs') def test_get_transaction_status_returns_404_if_not_found(client): res = client.get(TX_ENDPOINT + '123' + "/status") diff --git a/tests/web/test_unspents.py b/tests/web/test_unspents.py index e5cb3ab1..9539c664 100644 --- a/tests/web/test_unspents.py +++ b/tests/web/test_unspents.py @@ -1,10 +1,10 @@ import pytest +pytestmark = [pytest.mark.bdb, pytest.mark.usefixtures('inputs')] UNSPENTS_ENDPOINT = '/api/v1/unspents/' -@pytest.mark.usefixtures('inputs') def test_get_unspents_endpoint(b, client, user_pk): expected = [u.to_uri('..') for u in b.get_owned_ids(user_pk)] res = client.get(UNSPENTS_ENDPOINT + '?public_key={}'.format(user_pk)) @@ -12,13 +12,11 @@ def test_get_unspents_endpoint(b, client, user_pk): assert res.status_code == 200 -@pytest.mark.usefixtures('inputs') def test_get_unspents_endpoint_without_public_key(client): res = client.get(UNSPENTS_ENDPOINT) assert res.status_code == 400 -@pytest.mark.usefixtures('inputs') def test_get_unspents_endpoint_with_unused_public_key(client): expected = [] res = client.get(UNSPENTS_ENDPOINT + '?public_key=abc')